commit
de7380fb0c
25
.github/workflows/fix-php-code-style-issues.yml
vendored
Normal file
25
.github/workflows/fix-php-code-style-issues.yml
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
name: Fix PHP code style issues
|
||||
|
||||
on: [push]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
php-code-styling:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Fix PHP code style issues
|
||||
uses: aglipanci/laravel-pint-action@2.4
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: Fix styling
|
10
README.md
10
README.md
@ -31,15 +31,19 @@ # Donations
|
||||
|
||||
Thank you so much!
|
||||
|
||||
Special thanks to our biggest sponsor, [CCCareers](https://cccareers.org/)!
|
||||
Special thanks to our biggest sponsors!
|
||||
|
||||
<a href="https://cccareers.org/" target="_blank"><img src="./other/logos/ccc-logo.webp" alt="cccareers logo" width="200"/></a>
|
||||
<a href="http://htznr.li/CoolifyXHetzner" target="_blank"><img src="./other/logos/hetzner.jpg" alt="hetzner logo" width="200"/></a>
|
||||
<a href="https://logto.io/?ref=coolify" target="_blank"><img src="./other/logos/logto.webp" alt="logto logo" width="200"/></a>
|
||||
<a href="https://bc.direct/?utm_source=coolify.io" target="_blank"><img src="./other/logos/bc.png" alt="bc direct logo" width="200"/></a>
|
||||
<a href="https://www.quantcdn.io/?utm_source=coolify.io" target="_blank"><img src="./other/logos/quant.svg" alt="quantcdn logo" width="200"/></a>
|
||||
<a href="https://arcjet.com/?utm_source=coolify.io" target="_blank"><img src="./other/logos/arcjet.svg" alt="arcjet logo" width="200"/></a>
|
||||
|
||||
|
||||
## Github Sponsors ($40+)
|
||||
<a href="https://bc.direct"><img width="60px" alt="BC Direct" src="https://github.com/coollabsio/coolify/assets/5845193/a4063c41-95ed-4a32-8814-cd1475572e37"/></a>
|
||||
<a href="https://serpapi.com/?utm_source=coolify.io"><img width="60px" alt="SerpAPI" src="https://github.com/serpapi.png"/></a>
|
||||
<a href="https://typebot.io/?utm_source=coolify.io"><img src="https://pbs.twimg.com/profile_images/1509194008366657543/9I-C7uWT_400x400.jpg" width="60px" alt="typebot"/></a>
|
||||
<a href="https://www.quantcdn.io/?utm_source=coolify.io"><img src="https://github.com/quantcdn.png" width="60px" alt="QuantCDN"/></a>
|
||||
<a href="https://www.runpod.io/?utm_source=coolify.io">
|
||||
<svg style="width:60px;height:60px;background:#fff;" xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 200 200"><g><path d="M74.5 51.1c-25.4 14.9-27 16-29.6 20.2-1.8 3-1.9 5.3-1.9 32.3 0 21.7.3 29.4 1.3 30.6 1.9 2.5 46.7 27.9 48.5 27.6 1.5-.3 1.7-3.1 2-27.7.2-21.9 0-27.8-1.1-29.5-.8-1.2-9.9-6.8-20.2-12.6-10.3-5.8-19.4-11.5-20.2-12.7-1.8-2.6-.9-5.9 1.8-7.4 1.6-.8 6.3 0 21.8 4C87.8 78.7 98 81 99.6 81c4.4 0 49.9-25.9 49.9-28.4 0-1.6-3.4-2.8-24-8.2-13.2-3.5-25.1-6.3-26.5-6.3-1.4.1-12.4 5.9-24.5 13z"></path><path d="m137.2 68.1-3.3 2.1 6.3 3.7c3.5 2 6.3 4.3 6.3 5.1 0 .9-8 6.1-19.4 12.6-10.6 6-20 11.9-20.7 12.9-1.2 1.6-1.4 7.2-1.2 29.4.3 24.8.5 27.6 2 27.9 1.8.3 46.6-25.1 48.6-27.6.9-1.2 1.2-8.8 1.2-30.2s-.3-29-1.2-30.2c-1.6-1.9-12.1-7.8-13.9-7.8-.8 0-2.9 1-4.7 2.1z"></path></g></svg></a>
|
||||
<a href="https://lightspeed.run/?utm_source=coolify.io"><img src="https://github.com/lightspeedrun.png" width="60px" alt="Lightspeed.run"/></a>
|
||||
|
@ -3,17 +3,17 @@
|
||||
namespace App\Actions\Application;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\StandaloneDocker;
|
||||
use App\Notifications\Application\StatusChanged;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class StopApplication
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Application $application)
|
||||
{
|
||||
if ($application->destination->server->isSwarm()) {
|
||||
instant_remote_process(["docker stack rm {$application->uuid}"], $application->destination->server);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
class StopApplicationOneServer
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Application $application, Server $server)
|
||||
{
|
||||
if ($application->destination->server->isSwarm()) {
|
||||
@ -32,6 +33,7 @@ public function handle(Application $application, Server $server)
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
ray($e->getMessage());
|
||||
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
class PrepareCoolifyTask
|
||||
{
|
||||
protected Activity $activity;
|
||||
|
||||
protected CoolifyTaskArgs $remoteProcessArgs;
|
||||
|
||||
public function __construct(CoolifyTaskArgs $remoteProcessArgs)
|
||||
@ -28,12 +29,12 @@ public function __construct(CoolifyTaskArgs $remoteProcessArgs)
|
||||
->withProperties($properties)
|
||||
->performedOn($remoteProcessArgs->model)
|
||||
->event($remoteProcessArgs->type)
|
||||
->log("[]");
|
||||
->log('[]');
|
||||
} else {
|
||||
$this->activity = activity()
|
||||
->withProperties($remoteProcessArgs->toArray())
|
||||
->event($remoteProcessArgs->type)
|
||||
->log("[]");
|
||||
->log('[]');
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,6 +43,7 @@ public function __invoke(): Activity
|
||||
$job = new CoolifyTask($this->activity, ignore_errors: $this->remoteProcessArgs->ignore_errors, call_event_on_finish: $this->remoteProcessArgs->call_event_on_finish, call_event_data: $this->remoteProcessArgs->call_event_data);
|
||||
dispatch($job);
|
||||
$this->activity->refresh();
|
||||
|
||||
return $this->activity;
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public static function decodeOutput(?Activity $activity = null): string
|
||||
return collect($decoded)
|
||||
->sortBy(fn ($i) => $i['order'])
|
||||
->map(fn ($i) => $i['output'])
|
||||
->implode("");
|
||||
->implode('');
|
||||
}
|
||||
|
||||
public function __invoke(): ProcessResult
|
||||
@ -116,7 +116,7 @@ public function __invoke(): ProcessResult
|
||||
try {
|
||||
if ($this->call_event_data) {
|
||||
event(resolve("App\\Events\\$this->call_event_on_finish", [
|
||||
"data" => $this->call_event_data,
|
||||
'data' => $this->call_event_data,
|
||||
]));
|
||||
} else {
|
||||
event(resolve("App\\Events\\$this->call_event_on_finish", [
|
||||
@ -127,6 +127,7 @@ public function __invoke(): ProcessResult
|
||||
ray($e);
|
||||
}
|
||||
}
|
||||
|
||||
return $processResult;
|
||||
}
|
||||
|
||||
@ -182,6 +183,7 @@ protected function getLatestCounter(): int
|
||||
if ($description === null || count($description) === 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return end($description)['order'] + 1;
|
||||
}
|
||||
|
||||
|
@ -4,22 +4,23 @@
|
||||
|
||||
use App\Models\StandaloneClickhouse;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class StartClickhouse
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public StandaloneClickhouse $database;
|
||||
|
||||
public array $commands = [];
|
||||
|
||||
public string $configuration_dir;
|
||||
|
||||
public function handle(StandaloneClickhouse $database)
|
||||
{
|
||||
$this->database = $database;
|
||||
|
||||
|
||||
$container_name = $this->database->uuid;
|
||||
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||
|
||||
@ -57,7 +58,7 @@ public function handle(StandaloneClickhouse $database)
|
||||
'interval' => '5s',
|
||||
'timeout' => '5s',
|
||||
'retries' => 10,
|
||||
'start_period' => '5s'
|
||||
'start_period' => '5s',
|
||||
],
|
||||
'mem_limit' => $this->database->limits_memory,
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
@ -65,15 +66,15 @@ public function handle(StandaloneClickhouse $database)
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
],
|
||||
],
|
||||
'networks' => [
|
||||
$this->database->destination->network => [
|
||||
'external' => true,
|
||||
'name' => $this->database->destination->network,
|
||||
'attachable' => true,
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
if (! is_null($this->database->limits_cpuset)) {
|
||||
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
|
||||
@ -82,10 +83,10 @@ public function handle(StandaloneClickhouse $database)
|
||||
$docker_compose['services'][$container_name]['logging'] = [
|
||||
'driver' => 'fluentd',
|
||||
'options' => [
|
||||
'fluentd-address' => "tcp://127.0.0.1:24224",
|
||||
'fluentd-async' => "true",
|
||||
'fluentd-sub-second-precision' => "true",
|
||||
]
|
||||
'fluentd-address' => 'tcp://127.0.0.1:24224',
|
||||
'fluentd-async' => 'true',
|
||||
'fluentd-sub-second-precision' => 'true',
|
||||
],
|
||||
];
|
||||
}
|
||||
if (count($this->database->ports_mappings_array) > 0) {
|
||||
@ -111,6 +112,7 @@ public function handle(StandaloneClickhouse $database)
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
|
||||
$this->commands[] = "echo 'Database started.'";
|
||||
|
||||
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
|
||||
}
|
||||
|
||||
@ -125,6 +127,7 @@ private function generate_local_persistent_volumes()
|
||||
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
|
||||
}
|
||||
}
|
||||
|
||||
return $local_persistent_volumes;
|
||||
}
|
||||
|
||||
@ -141,6 +144,7 @@ private function generate_local_persistent_volumes_only_volume_names()
|
||||
'external' => false,
|
||||
];
|
||||
}
|
||||
|
||||
return $local_persistent_volumes_names;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St
|
||||
}
|
||||
}
|
||||
EOF;
|
||||
$dockerfile = <<< EOF
|
||||
$dockerfile = <<< 'EOF'
|
||||
FROM nginx:stable-alpine
|
||||
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
@ -113,7 +113,7 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St
|
||||
'context' => $configuration_dir,
|
||||
'dockerfile' => 'Dockerfile',
|
||||
],
|
||||
'image' => "nginx:stable-alpine",
|
||||
'image' => 'nginx:stable-alpine',
|
||||
'container_name' => $proxyContainerName,
|
||||
'restart' => RESTART_MODE,
|
||||
'ports' => [
|
||||
@ -130,17 +130,17 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St
|
||||
'interval' => '5s',
|
||||
'timeout' => '5s',
|
||||
'retries' => 3,
|
||||
'start_period' => '1s'
|
||||
'start_period' => '1s',
|
||||
],
|
||||
],
|
||||
]
|
||||
],
|
||||
'networks' => [
|
||||
$network => [
|
||||
'external' => true,
|
||||
'name' => $network,
|
||||
'attachable' => true,
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
$dockercompose_base64 = base64_encode(Yaml::dump($docker_compose, 4, 2));
|
||||
$nginxconf_base64 = base64_encode($nginxconf);
|
||||
|
@ -3,19 +3,19 @@
|
||||
namespace App\Actions\Database;
|
||||
|
||||
use App\Models\StandaloneDragonfly;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class StartDragonfly
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public StandaloneDragonfly $database;
|
||||
public array $commands = [];
|
||||
public string $configuration_dir;
|
||||
|
||||
public array $commands = [];
|
||||
|
||||
public string $configuration_dir;
|
||||
|
||||
public function handle(StandaloneDragonfly $database)
|
||||
{
|
||||
@ -48,7 +48,7 @@ public function handle(StandaloneDragonfly $database)
|
||||
$this->database->destination->network,
|
||||
],
|
||||
'ulimits' => [
|
||||
'memlock'=> '-1'
|
||||
'memlock' => '-1',
|
||||
],
|
||||
'labels' => [
|
||||
'coolify.managed' => 'true',
|
||||
@ -58,7 +58,7 @@ public function handle(StandaloneDragonfly $database)
|
||||
'interval' => '5s',
|
||||
'timeout' => '5s',
|
||||
'retries' => 10,
|
||||
'start_period' => '5s'
|
||||
'start_period' => '5s',
|
||||
],
|
||||
'mem_limit' => $this->database->limits_memory,
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
@ -66,15 +66,15 @@ public function handle(StandaloneDragonfly $database)
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
],
|
||||
],
|
||||
'networks' => [
|
||||
$this->database->destination->network => [
|
||||
'external' => true,
|
||||
'name' => $this->database->destination->network,
|
||||
'attachable' => true,
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
if (! is_null($this->database->limits_cpuset)) {
|
||||
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
|
||||
@ -83,10 +83,10 @@ public function handle(StandaloneDragonfly $database)
|
||||
$docker_compose['services'][$container_name]['logging'] = [
|
||||
'driver' => 'fluentd',
|
||||
'options' => [
|
||||
'fluentd-address' => "tcp://127.0.0.1:24224",
|
||||
'fluentd-async' => "true",
|
||||
'fluentd-sub-second-precision' => "true",
|
||||
]
|
||||
'fluentd-address' => 'tcp://127.0.0.1:24224',
|
||||
'fluentd-async' => 'true',
|
||||
'fluentd-sub-second-precision' => 'true',
|
||||
],
|
||||
];
|
||||
}
|
||||
if (count($this->database->ports_mappings_array) > 0) {
|
||||
@ -112,6 +112,7 @@ public function handle(StandaloneDragonfly $database)
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
|
||||
$this->commands[] = "echo 'Database started.'";
|
||||
|
||||
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
|
||||
}
|
||||
|
||||
@ -126,6 +127,7 @@ private function generate_local_persistent_volumes()
|
||||
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
|
||||
}
|
||||
}
|
||||
|
||||
return $local_persistent_volumes;
|
||||
}
|
||||
|
||||
@ -142,6 +144,7 @@ private function generate_local_persistent_volumes_only_volume_names()
|
||||
'external' => false,
|
||||
];
|
||||
}
|
||||
|
||||
return $local_persistent_volumes_names;
|
||||
}
|
||||
|
||||
|
@ -5,17 +5,18 @@
|
||||
use App\Models\StandaloneKeydb;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class StartKeydb
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public StandaloneKeydb $database;
|
||||
public array $commands = [];
|
||||
public string $configuration_dir;
|
||||
|
||||
public array $commands = [];
|
||||
|
||||
public string $configuration_dir;
|
||||
|
||||
public function handle(StandaloneKeydb $database)
|
||||
{
|
||||
@ -56,7 +57,7 @@ public function handle(StandaloneKeydb $database)
|
||||
'interval' => '5s',
|
||||
'timeout' => '5s',
|
||||
'retries' => 10,
|
||||
'start_period' => '5s'
|
||||
'start_period' => '5s',
|
||||
],
|
||||
'mem_limit' => $this->database->limits_memory,
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
@ -64,15 +65,15 @@ public function handle(StandaloneKeydb $database)
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
],
|
||||
],
|
||||
'networks' => [
|
||||
$this->database->destination->network => [
|
||||
'external' => true,
|
||||
'name' => $this->database->destination->network,
|
||||
'attachable' => true,
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
if (! is_null($this->database->limits_cpuset)) {
|
||||
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
|
||||
@ -81,10 +82,10 @@ public function handle(StandaloneKeydb $database)
|
||||
$docker_compose['services'][$container_name]['logging'] = [
|
||||
'driver' => 'fluentd',
|
||||
'options' => [
|
||||
'fluentd-address' => "tcp://127.0.0.1:24224",
|
||||
'fluentd-async' => "true",
|
||||
'fluentd-sub-second-precision' => "true",
|
||||
]
|
||||
'fluentd-address' => 'tcp://127.0.0.1:24224',
|
||||
'fluentd-async' => 'true',
|
||||
'fluentd-sub-second-precision' => 'true',
|
||||
],
|
||||
];
|
||||
}
|
||||
if (count($this->database->ports_mappings_array) > 0) {
|
||||
@ -119,6 +120,7 @@ public function handle(StandaloneKeydb $database)
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
|
||||
$this->commands[] = "echo 'Database started.'";
|
||||
|
||||
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
|
||||
}
|
||||
|
||||
@ -133,6 +135,7 @@ private function generate_local_persistent_volumes()
|
||||
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
|
||||
}
|
||||
}
|
||||
|
||||
return $local_persistent_volumes;
|
||||
}
|
||||
|
||||
@ -149,6 +152,7 @@ private function generate_local_persistent_volumes_only_volume_names()
|
||||
'external' => false,
|
||||
];
|
||||
}
|
||||
|
||||
return $local_persistent_volumes_names;
|
||||
}
|
||||
|
||||
@ -165,6 +169,7 @@ private function generate_environment_variables()
|
||||
|
||||
return $environment_variables->all();
|
||||
}
|
||||
|
||||
private function add_custom_keydb()
|
||||
{
|
||||
if (is_null($this->database->keydb_conf) || empty($this->database->keydb_conf)) {
|
||||
|
@ -4,15 +4,17 @@
|
||||
|
||||
use App\Models\StandaloneMariadb;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class StartMariadb
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public StandaloneMariadb $database;
|
||||
|
||||
public array $commands = [];
|
||||
|
||||
public string $configuration_dir;
|
||||
|
||||
public function handle(StandaloneMariadb $database)
|
||||
@ -46,11 +48,11 @@ public function handle(StandaloneMariadb $database)
|
||||
'coolify.managed' => 'true',
|
||||
],
|
||||
'healthcheck' => [
|
||||
'test' => ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"],
|
||||
'test' => ['CMD', 'healthcheck.sh', '--connect', '--innodb_initialized'],
|
||||
'interval' => '5s',
|
||||
'timeout' => '5s',
|
||||
'retries' => 10,
|
||||
'start_period' => '5s'
|
||||
'start_period' => '5s',
|
||||
],
|
||||
'mem_limit' => $this->database->limits_memory,
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
@ -58,15 +60,15 @@ public function handle(StandaloneMariadb $database)
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
],
|
||||
],
|
||||
'networks' => [
|
||||
$this->database->destination->network => [
|
||||
'external' => true,
|
||||
'name' => $this->database->destination->network,
|
||||
'attachable' => true,
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
if (! is_null($this->database->limits_cpuset)) {
|
||||
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
|
||||
@ -75,10 +77,10 @@ public function handle(StandaloneMariadb $database)
|
||||
$docker_compose['services'][$container_name]['logging'] = [
|
||||
'driver' => 'fluentd',
|
||||
'options' => [
|
||||
'fluentd-address' => "tcp://127.0.0.1:24224",
|
||||
'fluentd-async' => "true",
|
||||
'fluentd-sub-second-precision' => "true",
|
||||
]
|
||||
'fluentd-address' => 'tcp://127.0.0.1:24224',
|
||||
'fluentd-async' => 'true',
|
||||
'fluentd-sub-second-precision' => 'true',
|
||||
],
|
||||
];
|
||||
}
|
||||
if (count($this->database->ports_mappings_array) > 0) {
|
||||
@ -112,6 +114,7 @@ public function handle(StandaloneMariadb $database)
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
|
||||
$this->commands[] = "echo 'Database started.'";
|
||||
|
||||
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
|
||||
}
|
||||
|
||||
@ -126,6 +129,7 @@ private function generate_local_persistent_volumes()
|
||||
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
|
||||
}
|
||||
}
|
||||
|
||||
return $local_persistent_volumes;
|
||||
}
|
||||
|
||||
@ -142,6 +146,7 @@ private function generate_local_persistent_volumes_only_volume_names()
|
||||
'external' => false,
|
||||
];
|
||||
}
|
||||
|
||||
return $local_persistent_volumes_names;
|
||||
}
|
||||
|
||||
@ -166,8 +171,10 @@ private function generate_environment_variables()
|
||||
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MARIADB_PASSWORD'))->isEmpty()) {
|
||||
$environment_variables->push("MARIADB_PASSWORD={$this->database->mariadb_password}");
|
||||
}
|
||||
|
||||
return $environment_variables->all();
|
||||
}
|
||||
|
||||
private function add_custom_mysql()
|
||||
{
|
||||
if (is_null($this->database->mariadb_conf) || empty($this->database->mariadb_conf)) {
|
||||
|
@ -4,22 +4,24 @@
|
||||
|
||||
use App\Models\StandaloneMongodb;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class StartMongodb
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public StandaloneMongodb $database;
|
||||
|
||||
public array $commands = [];
|
||||
|
||||
public string $configuration_dir;
|
||||
|
||||
public function handle(StandaloneMongodb $database)
|
||||
{
|
||||
$this->database = $database;
|
||||
|
||||
$startCommand = "mongod";
|
||||
$startCommand = 'mongod';
|
||||
|
||||
$container_name = $this->database->uuid;
|
||||
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||
@ -51,14 +53,14 @@ public function handle(StandaloneMongodb $database)
|
||||
],
|
||||
'healthcheck' => [
|
||||
'test' => [
|
||||
"CMD",
|
||||
"echo",
|
||||
"ok"
|
||||
'CMD',
|
||||
'echo',
|
||||
'ok',
|
||||
],
|
||||
'interval' => '5s',
|
||||
'timeout' => '5s',
|
||||
'retries' => 10,
|
||||
'start_period' => '5s'
|
||||
'start_period' => '5s',
|
||||
],
|
||||
'mem_limit' => $this->database->limits_memory,
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
@ -66,15 +68,15 @@ public function handle(StandaloneMongodb $database)
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
],
|
||||
],
|
||||
'networks' => [
|
||||
$this->database->destination->network => [
|
||||
'external' => true,
|
||||
'name' => $this->database->destination->network,
|
||||
'attachable' => true,
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
if (! is_null($this->database->limits_cpuset)) {
|
||||
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
|
||||
@ -83,10 +85,10 @@ public function handle(StandaloneMongodb $database)
|
||||
$docker_compose['services'][$container_name]['logging'] = [
|
||||
'driver' => 'fluentd',
|
||||
'options' => [
|
||||
'fluentd-address' => "tcp://127.0.0.1:24224",
|
||||
'fluentd-async' => "true",
|
||||
'fluentd-sub-second-precision' => "true",
|
||||
]
|
||||
'fluentd-address' => 'tcp://127.0.0.1:24224',
|
||||
'fluentd-async' => 'true',
|
||||
'fluentd-sub-second-precision' => 'true',
|
||||
],
|
||||
];
|
||||
}
|
||||
if (count($this->database->ports_mappings_array) > 0) {
|
||||
@ -129,6 +131,7 @@ public function handle(StandaloneMongodb $database)
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
|
||||
$this->commands[] = "echo 'Database started.'";
|
||||
|
||||
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
|
||||
}
|
||||
|
||||
@ -143,6 +146,7 @@ private function generate_local_persistent_volumes()
|
||||
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
|
||||
}
|
||||
}
|
||||
|
||||
return $local_persistent_volumes;
|
||||
}
|
||||
|
||||
@ -159,6 +163,7 @@ private function generate_local_persistent_volumes_only_volume_names()
|
||||
'external' => false,
|
||||
];
|
||||
}
|
||||
|
||||
return $local_persistent_volumes_names;
|
||||
}
|
||||
|
||||
@ -180,8 +185,10 @@ private function generate_environment_variables()
|
||||
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MONGO_INITDB_DATABASE'))->isEmpty()) {
|
||||
$environment_variables->push("MONGO_INITDB_DATABASE={$this->database->mongo_initdb_database}");
|
||||
}
|
||||
|
||||
return $environment_variables->all();
|
||||
}
|
||||
|
||||
private function add_custom_mongo_conf()
|
||||
{
|
||||
if (is_null($this->database->mongo_conf) || empty($this->database->mongo_conf)) {
|
||||
@ -192,6 +199,7 @@ private function add_custom_mongo_conf()
|
||||
$content_base64 = base64_encode($content);
|
||||
$this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null";
|
||||
}
|
||||
|
||||
private function add_default_database()
|
||||
{
|
||||
$content = "db = db.getSiblingDB(\"{$this->database->mongo_initdb_database}\");db.createCollection('init_collection');db.createUser({user: \"{$this->database->mongo_initdb_root_username}\", pwd: \"{$this->database->mongo_initdb_root_password}\",roles: [{role:\"readWrite\",db:\"{$this->database->mongo_initdb_database}\"}]});";
|
||||
|
@ -4,15 +4,17 @@
|
||||
|
||||
use App\Models\StandaloneMysql;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class StartMysql
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public StandaloneMysql $database;
|
||||
|
||||
public array $commands = [];
|
||||
|
||||
public string $configuration_dir;
|
||||
|
||||
public function handle(StandaloneMysql $database)
|
||||
@ -46,11 +48,11 @@ public function handle(StandaloneMysql $database)
|
||||
'coolify.managed' => 'true',
|
||||
],
|
||||
'healthcheck' => [
|
||||
'test' => ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p{$this->database->mysql_root_password}"],
|
||||
'test' => ['CMD', 'mysqladmin', 'ping', '-h', 'localhost', '-u', 'root', "-p{$this->database->mysql_root_password}"],
|
||||
'interval' => '5s',
|
||||
'timeout' => '5s',
|
||||
'retries' => 10,
|
||||
'start_period' => '5s'
|
||||
'start_period' => '5s',
|
||||
],
|
||||
'mem_limit' => $this->database->limits_memory,
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
@ -58,15 +60,15 @@ public function handle(StandaloneMysql $database)
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
],
|
||||
],
|
||||
'networks' => [
|
||||
$this->database->destination->network => [
|
||||
'external' => true,
|
||||
'name' => $this->database->destination->network,
|
||||
'attachable' => true,
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
if (! is_null($this->database->limits_cpuset)) {
|
||||
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
|
||||
@ -75,10 +77,10 @@ public function handle(StandaloneMysql $database)
|
||||
$docker_compose['services'][$container_name]['logging'] = [
|
||||
'driver' => 'fluentd',
|
||||
'options' => [
|
||||
'fluentd-address' => "tcp://127.0.0.1:24224",
|
||||
'fluentd-async' => "true",
|
||||
'fluentd-sub-second-precision' => "true",
|
||||
]
|
||||
'fluentd-address' => 'tcp://127.0.0.1:24224',
|
||||
'fluentd-async' => 'true',
|
||||
'fluentd-sub-second-precision' => 'true',
|
||||
],
|
||||
];
|
||||
}
|
||||
if (count($this->database->ports_mappings_array) > 0) {
|
||||
@ -112,6 +114,7 @@ public function handle(StandaloneMysql $database)
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
|
||||
$this->commands[] = "echo 'Database started.'";
|
||||
|
||||
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
|
||||
}
|
||||
|
||||
@ -126,6 +129,7 @@ private function generate_local_persistent_volumes()
|
||||
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
|
||||
}
|
||||
}
|
||||
|
||||
return $local_persistent_volumes;
|
||||
}
|
||||
|
||||
@ -142,6 +146,7 @@ private function generate_local_persistent_volumes_only_volume_names()
|
||||
'external' => false,
|
||||
];
|
||||
}
|
||||
|
||||
return $local_persistent_volumes_names;
|
||||
}
|
||||
|
||||
@ -166,8 +171,10 @@ private function generate_environment_variables()
|
||||
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MYSQL_PASSWORD'))->isEmpty()) {
|
||||
$environment_variables->push("MYSQL_PASSWORD={$this->database->mysql_password}");
|
||||
}
|
||||
|
||||
return $environment_variables->all();
|
||||
}
|
||||
|
||||
private function add_custom_mysql()
|
||||
{
|
||||
if (is_null($this->database->mysql_conf) || empty($this->database->mysql_conf)) {
|
||||
|
@ -4,16 +4,19 @@
|
||||
|
||||
use App\Models\StandalonePostgresql;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class StartPostgresql
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public StandalonePostgresql $database;
|
||||
|
||||
public array $commands = [];
|
||||
|
||||
public array $init_scripts = [];
|
||||
|
||||
public string $configuration_dir;
|
||||
|
||||
public function handle(StandalonePostgresql $database)
|
||||
@ -25,7 +28,7 @@ public function handle(StandalonePostgresql $database)
|
||||
$this->commands = [
|
||||
"echo 'Starting {$database->name}.'",
|
||||
"mkdir -p $this->configuration_dir",
|
||||
"mkdir -p $this->configuration_dir/docker-entrypoint-initdb.d/"
|
||||
"mkdir -p $this->configuration_dir/docker-entrypoint-initdb.d/",
|
||||
];
|
||||
|
||||
$persistent_storages = $this->generate_local_persistent_volumes();
|
||||
@ -50,13 +53,13 @@ public function handle(StandalonePostgresql $database)
|
||||
],
|
||||
'healthcheck' => [
|
||||
'test' => [
|
||||
"CMD-SHELL",
|
||||
"psql -U {$this->database->postgres_user} -d {$this->database->postgres_db} -c 'SELECT 1' || exit 1"
|
||||
'CMD-SHELL',
|
||||
"psql -U {$this->database->postgres_user} -d {$this->database->postgres_db} -c 'SELECT 1' || exit 1",
|
||||
],
|
||||
'interval' => '5s',
|
||||
'timeout' => '5s',
|
||||
'retries' => 10,
|
||||
'start_period' => '5s'
|
||||
'start_period' => '5s',
|
||||
],
|
||||
'mem_limit' => $this->database->limits_memory,
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
@ -64,15 +67,15 @@ public function handle(StandalonePostgresql $database)
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
],
|
||||
],
|
||||
'networks' => [
|
||||
$this->database->destination->network => [
|
||||
'external' => true,
|
||||
'name' => $this->database->destination->network,
|
||||
'attachable' => true,
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
if (! is_null($this->database->limits_cpuset)) {
|
||||
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
|
||||
@ -81,10 +84,10 @@ public function handle(StandalonePostgresql $database)
|
||||
$docker_compose['services'][$container_name]['logging'] = [
|
||||
'driver' => 'fluentd',
|
||||
'options' => [
|
||||
'fluentd-address' => "tcp://127.0.0.1:24224",
|
||||
'fluentd-async' => "true",
|
||||
'fluentd-sub-second-precision' => "true",
|
||||
]
|
||||
'fluentd-address' => 'tcp://127.0.0.1:24224',
|
||||
'fluentd-async' => 'true',
|
||||
'fluentd-sub-second-precision' => 'true',
|
||||
],
|
||||
];
|
||||
}
|
||||
if (count($this->database->ports_mappings_array) > 0) {
|
||||
@ -133,6 +136,7 @@ public function handle(StandalonePostgresql $database)
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
|
||||
$this->commands[] = "echo 'Database started.'";
|
||||
|
||||
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
|
||||
}
|
||||
|
||||
@ -147,6 +151,7 @@ private function generate_local_persistent_volumes()
|
||||
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
|
||||
}
|
||||
}
|
||||
|
||||
return $local_persistent_volumes;
|
||||
}
|
||||
|
||||
@ -163,6 +168,7 @@ private function generate_local_persistent_volumes_only_volume_names()
|
||||
'external' => false,
|
||||
];
|
||||
}
|
||||
|
||||
return $local_persistent_volumes_names;
|
||||
}
|
||||
|
||||
@ -187,6 +193,7 @@ private function generate_environment_variables()
|
||||
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('POSTGRES_DB'))->isEmpty()) {
|
||||
$environment_variables->push("POSTGRES_DB={$this->database->postgres_db}");
|
||||
}
|
||||
|
||||
return $environment_variables->all();
|
||||
}
|
||||
|
||||
@ -203,6 +210,7 @@ private function generate_init_scripts()
|
||||
$this->init_scripts[] = "$this->configuration_dir/docker-entrypoint-initdb.d/{$filename}";
|
||||
}
|
||||
}
|
||||
|
||||
private function add_custom_conf()
|
||||
{
|
||||
if (is_null($this->database->postgres_conf) || empty($this->database->postgres_conf)) {
|
||||
|
@ -5,17 +5,18 @@
|
||||
use App\Models\StandaloneRedis;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class StartRedis
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public StandaloneRedis $database;
|
||||
public array $commands = [];
|
||||
public string $configuration_dir;
|
||||
|
||||
public array $commands = [];
|
||||
|
||||
public string $configuration_dir;
|
||||
|
||||
public function handle(StandaloneRedis $database)
|
||||
{
|
||||
@ -55,12 +56,12 @@ public function handle(StandaloneRedis $database)
|
||||
'test' => [
|
||||
'CMD-SHELL',
|
||||
'redis-cli',
|
||||
'ping'
|
||||
'ping',
|
||||
],
|
||||
'interval' => '5s',
|
||||
'timeout' => '5s',
|
||||
'retries' => 10,
|
||||
'start_period' => '5s'
|
||||
'start_period' => '5s',
|
||||
],
|
||||
'mem_limit' => $this->database->limits_memory,
|
||||
'memswap_limit' => $this->database->limits_memory_swap,
|
||||
@ -68,15 +69,15 @@ public function handle(StandaloneRedis $database)
|
||||
'mem_reservation' => $this->database->limits_memory_reservation,
|
||||
'cpus' => (float) $this->database->limits_cpus,
|
||||
'cpu_shares' => $this->database->limits_cpu_shares,
|
||||
]
|
||||
],
|
||||
],
|
||||
'networks' => [
|
||||
$this->database->destination->network => [
|
||||
'external' => true,
|
||||
'name' => $this->database->destination->network,
|
||||
'attachable' => true,
|
||||
]
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
||||
if (! is_null($this->database->limits_cpuset)) {
|
||||
data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset);
|
||||
@ -85,10 +86,10 @@ public function handle(StandaloneRedis $database)
|
||||
$docker_compose['services'][$container_name]['logging'] = [
|
||||
'driver' => 'fluentd',
|
||||
'options' => [
|
||||
'fluentd-address' => "tcp://127.0.0.1:24224",
|
||||
'fluentd-async' => "true",
|
||||
'fluentd-sub-second-precision' => "true",
|
||||
]
|
||||
'fluentd-address' => 'tcp://127.0.0.1:24224',
|
||||
'fluentd-async' => 'true',
|
||||
'fluentd-sub-second-precision' => 'true',
|
||||
],
|
||||
];
|
||||
}
|
||||
if (count($this->database->ports_mappings_array) > 0) {
|
||||
@ -123,6 +124,7 @@ public function handle(StandaloneRedis $database)
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml pull";
|
||||
$this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d";
|
||||
$this->commands[] = "echo 'Database started.'";
|
||||
|
||||
return remote_process($this->commands, $database->destination->server, callEventOnFinish: 'DatabaseStatusChanged');
|
||||
}
|
||||
|
||||
@ -137,6 +139,7 @@ private function generate_local_persistent_volumes()
|
||||
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
|
||||
}
|
||||
}
|
||||
|
||||
return $local_persistent_volumes;
|
||||
}
|
||||
|
||||
@ -153,6 +156,7 @@ private function generate_local_persistent_volumes_only_volume_names()
|
||||
'external' => false,
|
||||
];
|
||||
}
|
||||
|
||||
return $local_persistent_volumes_names;
|
||||
}
|
||||
|
||||
@ -169,6 +173,7 @@ private function generate_environment_variables()
|
||||
|
||||
return $environment_variables->all();
|
||||
}
|
||||
|
||||
private function add_custom_redis()
|
||||
{
|
||||
if (is_null($this->database->redis_conf) || empty($this->database->redis_conf)) {
|
||||
|
@ -17,7 +17,9 @@
|
||||
class GetContainersStatus
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public $applications;
|
||||
|
||||
public $server;
|
||||
|
||||
public function handle(Server $server)
|
||||
@ -28,7 +30,7 @@ public function handle(Server $server)
|
||||
$this->server = $server;
|
||||
if (! $this->server->isFunctional()) {
|
||||
return 'Server is not ready.';
|
||||
};
|
||||
}
|
||||
$this->applications = $this->server->applications();
|
||||
$skip_these_applications = collect([]);
|
||||
foreach ($this->applications as $application) {
|
||||
@ -239,7 +241,7 @@ private function sentinel()
|
||||
$environmentName = data_get($service, 'environment.name');
|
||||
|
||||
if ($projectUuid && $serviceUuid && $environmentName) {
|
||||
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/service/" . $serviceUuid;
|
||||
$url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/service/'.$serviceUuid;
|
||||
} else {
|
||||
$url = null;
|
||||
}
|
||||
@ -265,7 +267,7 @@ private function sentinel()
|
||||
$environment = data_get($application, 'environment.name');
|
||||
|
||||
if ($projectUuid && $applicationUuid && $environment) {
|
||||
$url = base_url() . '/project/' . $projectUuid . "/" . $environment . "/application/" . $applicationUuid;
|
||||
$url = base_url().'/project/'.$projectUuid.'/'.$environment.'/application/'.$applicationUuid;
|
||||
} else {
|
||||
$url = null;
|
||||
}
|
||||
@ -290,7 +292,7 @@ private function sentinel()
|
||||
$applicationUuid = data_get($preview, 'application.uuid');
|
||||
|
||||
if ($projectUuid && $applicationUuid && $environmentName) {
|
||||
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/application/" . $applicationUuid;
|
||||
$url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/application/'.$applicationUuid;
|
||||
} else {
|
||||
$url = null;
|
||||
}
|
||||
@ -315,7 +317,7 @@ private function sentinel()
|
||||
$databaseUuid = data_get($database, 'uuid');
|
||||
|
||||
if ($projectUuid && $databaseUuid && $environmentName) {
|
||||
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/database/" . $databaseUuid;
|
||||
$url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/database/'.$databaseUuid;
|
||||
} else {
|
||||
$url = null;
|
||||
}
|
||||
@ -351,9 +353,11 @@ private function sentinel()
|
||||
} catch (\Exception $e) {
|
||||
// send_internal_notification("ContainerStatusJob failed on ({$this->server->id}) with: " . $e->getMessage());
|
||||
ray($e->getMessage());
|
||||
|
||||
return handleError($e);
|
||||
}
|
||||
}
|
||||
|
||||
private function old_way()
|
||||
{
|
||||
if ($this->server->isSwarm()) {
|
||||
@ -361,7 +365,7 @@ private function old_way()
|
||||
$containerReplicates = instant_remote_process(["docker service ls --format '{{json .}}'"], $this->server, false);
|
||||
} else {
|
||||
// Precheck for containers
|
||||
$containers = instant_remote_process(["docker container ls -q"], $this->server, false);
|
||||
$containers = instant_remote_process(['docker container ls -q'], $this->server, false);
|
||||
if (! $containers) {
|
||||
return;
|
||||
}
|
||||
@ -390,6 +394,7 @@ private function old_way()
|
||||
data_set($container, 'State.Health.Status', 'unhealthy');
|
||||
}
|
||||
}
|
||||
|
||||
return $container;
|
||||
});
|
||||
}
|
||||
@ -569,7 +574,7 @@ private function old_way()
|
||||
$environmentName = data_get($service, 'environment.name');
|
||||
|
||||
if ($projectUuid && $serviceUuid && $environmentName) {
|
||||
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/service/" . $serviceUuid;
|
||||
$url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/service/'.$serviceUuid;
|
||||
} else {
|
||||
$url = null;
|
||||
}
|
||||
@ -595,7 +600,7 @@ private function old_way()
|
||||
$environment = data_get($application, 'environment.name');
|
||||
|
||||
if ($projectUuid && $applicationUuid && $environment) {
|
||||
$url = base_url() . '/project/' . $projectUuid . "/" . $environment . "/application/" . $applicationUuid;
|
||||
$url = base_url().'/project/'.$projectUuid.'/'.$environment.'/application/'.$applicationUuid;
|
||||
} else {
|
||||
$url = null;
|
||||
}
|
||||
@ -620,7 +625,7 @@ private function old_way()
|
||||
$applicationUuid = data_get($preview, 'application.uuid');
|
||||
|
||||
if ($projectUuid && $applicationUuid && $environmentName) {
|
||||
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/application/" . $applicationUuid;
|
||||
$url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/application/'.$applicationUuid;
|
||||
} else {
|
||||
$url = null;
|
||||
}
|
||||
@ -645,7 +650,7 @@ private function old_way()
|
||||
$databaseUuid = data_get($database, 'uuid');
|
||||
|
||||
if ($projectUuid && $databaseUuid && $environmentName) {
|
||||
$url = base_url() . '/project/' . $projectUuid . "/" . $environmentName . "/database/" . $databaseUuid;
|
||||
$url = base_url().'/project/'.$projectUuid.'/'.$environmentName.'/database/'.$databaseUuid;
|
||||
} else {
|
||||
$url = null;
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ public function create(array $input): User
|
||||
}
|
||||
// Set session variable
|
||||
session(['currentTeam' => $user->currentTeam = $team]);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,10 @@
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
|
||||
class CheckResaleLicense
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle()
|
||||
{
|
||||
try {
|
||||
@ -18,6 +18,7 @@ public function handle()
|
||||
$settings->update([
|
||||
'is_resale_license_active' => true,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
// if (!$settings->resale_license) {
|
||||
@ -38,6 +39,7 @@ public function handle()
|
||||
$settings->update([
|
||||
'is_resale_license_active' => true,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
$data = Http::withHeaders([
|
||||
@ -51,6 +53,7 @@ public function handle()
|
||||
$settings->update([
|
||||
'is_resale_license_active' => true,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
if (data_get($data, 'license_key.status') === 'active') {
|
||||
|
@ -2,13 +2,14 @@
|
||||
|
||||
namespace App\Actions\Proxy;
|
||||
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Support\Str;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class CheckConfiguration
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Server $server, bool $reset = false)
|
||||
{
|
||||
$proxyType = $server->proxyType();
|
||||
@ -26,8 +27,9 @@ public function handle(Server $server, bool $reset = false)
|
||||
$proxy_configuration = Str::of(generate_default_proxy_configuration($server))->trim()->value;
|
||||
}
|
||||
if (! $proxy_configuration || is_null($proxy_configuration)) {
|
||||
throw new \Exception("Could not generate proxy configuration");
|
||||
throw new \Exception('Could not generate proxy configuration');
|
||||
}
|
||||
|
||||
return $proxy_configuration;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
class CheckProxy
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Server $server, $fromUI = false)
|
||||
{
|
||||
if (! $server->isFunctional()) {
|
||||
@ -18,6 +19,7 @@ public function handle(Server $server, $fromUI = false)
|
||||
$server->proxy = null;
|
||||
$server->save();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
$proxyType = $server->proxyType();
|
||||
@ -30,7 +32,7 @@ public function handle(Server $server, $fromUI = false)
|
||||
}
|
||||
if (! $server->isProxyShouldRun()) {
|
||||
if ($fromUI) {
|
||||
throw new \Exception("Proxy should not run. You selected the Custom Proxy.");
|
||||
throw new \Exception('Proxy should not run. You selected the Custom Proxy.');
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -42,12 +44,14 @@ public function handle(Server $server, $fromUI = false)
|
||||
if ($status === 'running') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
$status = getContainerStatus($server, 'coolify-proxy');
|
||||
if ($status === 'running') {
|
||||
$server->proxy->set('status', 'running');
|
||||
$server->save();
|
||||
|
||||
return false;
|
||||
}
|
||||
if ($server->settings->is_cloudflare_tunnel) {
|
||||
@ -76,6 +80,7 @@ public function handle(Server $server, $fromUI = false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
class StartProxy
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Server $server, bool $async = true): string|Activity
|
||||
{
|
||||
try {
|
||||
@ -22,7 +23,7 @@ public function handle(Server $server, bool $async = true): string|Activity
|
||||
$proxy_path = $server->proxyPath();
|
||||
$configuration = CheckConfiguration::run($server);
|
||||
if (! $configuration) {
|
||||
throw new \Exception("Configuration is not synced");
|
||||
throw new \Exception('Configuration is not synced');
|
||||
}
|
||||
SaveConfiguration::run($server, $configuration);
|
||||
$docker_compose_yml_base64 = base64_encode($configuration);
|
||||
@ -34,11 +35,11 @@ public function handle(Server $server, bool $async = true): string|Activity
|
||||
"cd $proxy_path",
|
||||
"echo 'Creating required Docker Compose file.'",
|
||||
"echo 'Starting coolify-proxy.'",
|
||||
"docker stack deploy -c docker-compose.yml coolify-proxy",
|
||||
"echo 'Proxy started successfully.'"
|
||||
'docker stack deploy -c docker-compose.yml coolify-proxy',
|
||||
"echo 'Proxy started successfully.'",
|
||||
]);
|
||||
} else {
|
||||
$caddfile = "import /dynamic/*.caddy";
|
||||
$caddfile = 'import /dynamic/*.caddy';
|
||||
$commands = $commands->merge([
|
||||
"mkdir -p $proxy_path/dynamic",
|
||||
"cd $proxy_path",
|
||||
@ -47,16 +48,17 @@ public function handle(Server $server, bool $async = true): string|Activity
|
||||
"echo 'Pulling docker image.'",
|
||||
'docker compose pull',
|
||||
"echo 'Stopping existing coolify-proxy.'",
|
||||
"docker compose down -v --remove-orphans > /dev/null 2>&1",
|
||||
'docker compose down -v --remove-orphans > /dev/null 2>&1',
|
||||
"echo 'Starting coolify-proxy.'",
|
||||
'docker compose up -d --remove-orphans',
|
||||
"echo 'Proxy started successfully.'"
|
||||
"echo 'Proxy started successfully.'",
|
||||
]);
|
||||
$commands = $commands->merge(connectProxyToNetworks($server));
|
||||
}
|
||||
|
||||
if ($async) {
|
||||
$activity = remote_process($commands, $server, callEventOnFinish: 'ProxyStarted', callEventData: $server);
|
||||
|
||||
return $activity;
|
||||
} else {
|
||||
instant_remote_process($commands, $server);
|
||||
@ -64,6 +66,7 @@ public function handle(Server $server, bool $async = true): string|Activity
|
||||
$server->proxy->set('type', $proxyType);
|
||||
$server->save();
|
||||
ProxyStarted::dispatch($server);
|
||||
|
||||
return 'OK';
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
|
@ -2,12 +2,13 @@
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use App\Models\Server;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class CleanupDocker
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Server $server, bool $force = true)
|
||||
{
|
||||
if ($force) {
|
||||
|
@ -9,18 +9,19 @@
|
||||
class ConfigureCloudflared
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Server $server, string $cloudflare_token)
|
||||
{
|
||||
try {
|
||||
$config = [
|
||||
"services" => [
|
||||
"coolify-cloudflared" => [
|
||||
"container_name" => "coolify-cloudflared",
|
||||
"image" => "cloudflare/cloudflared:latest",
|
||||
"restart" => RESTART_MODE,
|
||||
"network_mode" => "host",
|
||||
"command" => "tunnel run",
|
||||
"environment" => [
|
||||
'services' => [
|
||||
'coolify-cloudflared' => [
|
||||
'container_name' => 'coolify-cloudflared',
|
||||
'image' => 'cloudflare/cloudflared:latest',
|
||||
'restart' => RESTART_MODE,
|
||||
'network_mode' => 'host',
|
||||
'command' => 'tunnel run',
|
||||
'environment' => [
|
||||
"TUNNEL_TOKEN={$cloudflare_token}",
|
||||
],
|
||||
],
|
||||
@ -29,12 +30,12 @@ public function handle(Server $server, string $cloudflare_token)
|
||||
$config = Yaml::dump($config, 12, 2);
|
||||
$docker_compose_yml_base64 = base64_encode($config);
|
||||
$commands = collect([
|
||||
"mkdir -p /tmp/cloudflared",
|
||||
"cd /tmp/cloudflared",
|
||||
'mkdir -p /tmp/cloudflared',
|
||||
'cd /tmp/cloudflared',
|
||||
"echo '$docker_compose_yml_base64' | base64 -d | tee docker-compose.yml > /dev/null",
|
||||
"docker compose pull",
|
||||
"docker compose down -v --remove-orphans > /dev/null 2>&1",
|
||||
"docker compose up -d --remove-orphans",
|
||||
'docker compose pull',
|
||||
'docker compose down -v --remove-orphans > /dev/null 2>&1',
|
||||
'docker compose up -d --remove-orphans',
|
||||
]);
|
||||
instant_remote_process($commands, $server);
|
||||
} catch (\Throwable $e) {
|
||||
@ -42,7 +43,7 @@ public function handle(Server $server, string $cloudflare_token)
|
||||
throw $e;
|
||||
} finally {
|
||||
$commands = collect([
|
||||
"rm -fr /tmp/cloudflared",
|
||||
'rm -fr /tmp/cloudflared',
|
||||
]);
|
||||
instant_remote_process($commands, $server);
|
||||
}
|
||||
|
@ -2,13 +2,14 @@
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class InstallDocker
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Server $server)
|
||||
{
|
||||
$supported_os_type = $server->validateOS();
|
||||
@ -36,40 +37,41 @@ public function handle(Server $server)
|
||||
if (isDev() && $server->id === 0) {
|
||||
$command = $command->merge([
|
||||
"echo 'Installing Prerequisites...'",
|
||||
"sleep 1",
|
||||
'sleep 1',
|
||||
"echo 'Installing Docker Engine...'",
|
||||
"echo 'Configuring Docker Engine (merging existing configuration with the required)...'",
|
||||
"sleep 4",
|
||||
'sleep 4',
|
||||
"echo 'Restarting Docker Engine...'",
|
||||
"ls -l /tmp"
|
||||
'ls -l /tmp',
|
||||
]);
|
||||
|
||||
return remote_process($command, $server);
|
||||
} else {
|
||||
if ($supported_os_type->contains('debian')) {
|
||||
$command = $command->merge([
|
||||
"echo 'Installing Prerequisites...'",
|
||||
"apt-get update -y",
|
||||
"command -v curl >/dev/null || apt install -y curl",
|
||||
"command -v wget >/dev/null || apt install -y wget",
|
||||
"command -v git >/dev/null || apt install -y git",
|
||||
"command -v jq >/dev/null || apt install -y jq",
|
||||
'apt-get update -y',
|
||||
'command -v curl >/dev/null || apt install -y curl',
|
||||
'command -v wget >/dev/null || apt install -y wget',
|
||||
'command -v git >/dev/null || apt install -y git',
|
||||
'command -v jq >/dev/null || apt install -y jq',
|
||||
]);
|
||||
} elseif ($supported_os_type->contains('rhel')) {
|
||||
$command = $command->merge([
|
||||
"echo 'Installing Prerequisites...'",
|
||||
"command -v curl >/dev/null || dnf install -y curl",
|
||||
"command -v wget >/dev/null || dnf install -y wget",
|
||||
"command -v git >/dev/null || dnf install -y git",
|
||||
"command -v jq >/dev/null || dnf install -y jq",
|
||||
'command -v curl >/dev/null || dnf install -y curl',
|
||||
'command -v wget >/dev/null || dnf install -y wget',
|
||||
'command -v git >/dev/null || dnf install -y git',
|
||||
'command -v jq >/dev/null || dnf install -y jq',
|
||||
]);
|
||||
} elseif ($supported_os_type->contains('sles')) {
|
||||
$command = $command->merge([
|
||||
"echo 'Installing Prerequisites...'",
|
||||
"zypper update -y",
|
||||
"command -v curl >/dev/null || zypper install -y curl",
|
||||
"command -v wget >/dev/null || zypper install -y wget",
|
||||
"command -v git >/dev/null || zypper install -y git",
|
||||
"command -v jq >/dev/null || zypper install -y jq",
|
||||
'zypper update -y',
|
||||
'command -v curl >/dev/null || zypper install -y curl',
|
||||
'command -v wget >/dev/null || zypper install -y wget',
|
||||
'command -v git >/dev/null || zypper install -y git',
|
||||
'command -v jq >/dev/null || zypper install -y jq',
|
||||
]);
|
||||
} else {
|
||||
throw new \Exception('Unsupported OS');
|
||||
@ -78,29 +80,30 @@ public function handle(Server $server)
|
||||
"echo 'Installing Docker Engine...'",
|
||||
"curl https://releases.rancher.com/install-docker/{$dockerVersion}.sh | sh || curl https://get.docker.com | sh -s -- --version {$dockerVersion}",
|
||||
"echo 'Configuring Docker Engine (merging existing configuration with the required)...'",
|
||||
"test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json \"/etc/docker/daemon.json.original-$(date +\"%Y%m%d-%H%M%S\")\"",
|
||||
'test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json "/etc/docker/daemon.json.original-$(date +"%Y%m%d-%H%M%S")"',
|
||||
"test ! -s /etc/docker/daemon.json && echo '{$config}' | base64 -d | tee /etc/docker/daemon.json > /dev/null",
|
||||
"echo '{$config}' | base64 -d | tee /etc/docker/daemon.json.coolify > /dev/null",
|
||||
"jq . /etc/docker/daemon.json.coolify | tee /etc/docker/daemon.json.coolify.pretty > /dev/null",
|
||||
"mv /etc/docker/daemon.json.coolify.pretty /etc/docker/daemon.json.coolify",
|
||||
'jq . /etc/docker/daemon.json.coolify | tee /etc/docker/daemon.json.coolify.pretty > /dev/null',
|
||||
'mv /etc/docker/daemon.json.coolify.pretty /etc/docker/daemon.json.coolify',
|
||||
"jq -s '.[0] * .[1]' /etc/docker/daemon.json.coolify /etc/docker/daemon.json | tee /etc/docker/daemon.json.appended > /dev/null",
|
||||
"mv /etc/docker/daemon.json.appended /etc/docker/daemon.json",
|
||||
'mv /etc/docker/daemon.json.appended /etc/docker/daemon.json',
|
||||
"echo 'Restarting Docker Engine...'",
|
||||
"systemctl enable docker >/dev/null 2>&1 || true",
|
||||
"systemctl restart docker",
|
||||
'systemctl enable docker >/dev/null 2>&1 || true',
|
||||
'systemctl restart docker',
|
||||
]);
|
||||
if ($server->isSwarm()) {
|
||||
$command = $command->merge([
|
||||
"docker network create --attachable --driver overlay coolify-overlay >/dev/null 2>&1 || true",
|
||||
'docker network create --attachable --driver overlay coolify-overlay >/dev/null 2>&1 || true',
|
||||
]);
|
||||
} else {
|
||||
$command = $command->merge([
|
||||
"docker network create --attachable coolify >/dev/null 2>&1 || true",
|
||||
'docker network create --attachable coolify >/dev/null 2>&1 || true',
|
||||
]);
|
||||
$command = $command->merge([
|
||||
"echo 'Done!'",
|
||||
]);
|
||||
}
|
||||
|
||||
return remote_process($command, $server);
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,13 @@
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use App\Models\Server;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class InstallLogDrain
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Server $server)
|
||||
{
|
||||
if ($server->settings->is_logdrain_newrelic_enabled) {
|
||||
@ -25,8 +26,9 @@ public function handle(Server $server)
|
||||
if ($type === 'none') {
|
||||
$command = [
|
||||
"echo 'Stopping old Fluent Bit'",
|
||||
"docker rm -f coolify-log-drain || true",
|
||||
'docker rm -f coolify-log-drain || true',
|
||||
];
|
||||
|
||||
return instant_remote_process($command, $server);
|
||||
} elseif ($type === 'newrelic') {
|
||||
if (! $server->settings->is_logdrain_newrelic_enabled) {
|
||||
@ -63,7 +65,7 @@ public function handle(Server $server)
|
||||
if (! $server->settings->is_logdrain_highlight_enabled) {
|
||||
throw new \Exception('Highlight log drain is not enabled.');
|
||||
}
|
||||
$config = base64_encode("
|
||||
$config = base64_encode('
|
||||
[SERVICE]
|
||||
Flush 5
|
||||
Daemon off
|
||||
@ -71,7 +73,7 @@ public function handle(Server $server)
|
||||
Parsers_File parsers.conf
|
||||
[INPUT]
|
||||
Name forward
|
||||
tag \${HIGHLIGHT_PROJECT_ID}
|
||||
tag ${HIGHLIGHT_PROJECT_ID}
|
||||
Buffer_Chunk_Size 1M
|
||||
Buffer_Max_Size 6M
|
||||
[OUTPUT]
|
||||
@ -79,7 +81,7 @@ public function handle(Server $server)
|
||||
Match *
|
||||
Host otel.highlight.io
|
||||
Port 24224
|
||||
");
|
||||
');
|
||||
} elseif ($type === 'axiom') {
|
||||
if (! $server->settings->is_logdrain_axiom_enabled) {
|
||||
throw new \Exception('Axiom log drain is not enabled.');
|
||||
@ -133,7 +135,7 @@ public function handle(Server $server)
|
||||
Regex /^(?!\s*$).+/
|
||||
");
|
||||
}
|
||||
$compose = base64_encode("
|
||||
$compose = base64_encode('
|
||||
services:
|
||||
coolify-log-drain:
|
||||
image: cr.fluentbit.io/fluent/fluent-bit:2.0
|
||||
@ -147,7 +149,7 @@ public function handle(Server $server)
|
||||
ports:
|
||||
- 127.0.0.1:24224:24224
|
||||
restart: unless-stopped
|
||||
");
|
||||
');
|
||||
$readme = base64_encode('# New Relic Log Drain
|
||||
This log drain is based on [Fluent Bit](https://fluentbit.io/) and New Relic Log Forwarder.
|
||||
|
||||
@ -191,7 +193,7 @@ public function handle(Server $server)
|
||||
];
|
||||
} elseif ($type === 'custom') {
|
||||
$add_envs_command = [
|
||||
"touch $config_path/.env"
|
||||
"touch $config_path/.env",
|
||||
];
|
||||
} else {
|
||||
throw new \Exception('Unknown log drain type.');
|
||||
@ -203,6 +205,7 @@ public function handle(Server $server)
|
||||
"cd $config_path && docker compose up -d --remove-orphans",
|
||||
];
|
||||
$command = array_merge($command, $add_envs_command, $restart_command);
|
||||
|
||||
return instant_remote_process($command, $server);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e);
|
||||
|
@ -2,12 +2,13 @@
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use App\Models\Server;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class StartSentinel
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Server $server, $version = 'latest', bool $restart = false)
|
||||
{
|
||||
if ($restart) {
|
||||
@ -15,8 +16,8 @@ public function handle(Server $server, $version = 'latest', bool $restart = fals
|
||||
}
|
||||
instant_remote_process([
|
||||
"docker run --rm --pull always -d -e \"SCHEDULER=true\" --name coolify-sentinel -v /var/run/docker.sock:/var/run/docker.sock -v /data/coolify/metrics:/app/metrics -v /data/coolify/logs:/app/logs --pid host --health-cmd \"curl --fail http://127.0.0.1:8888/api/health || exit 1\" --health-interval 10s --health-retries 3 ghcr.io/coollabsio/sentinel:$version",
|
||||
"chown -R 9999:root /data/coolify/metrics /data/coolify/logs",
|
||||
"chmod -R 700 /data/coolify/metrics /data/coolify/logs"
|
||||
'chown -R 9999:root /data/coolify/metrics /data/coolify/logs',
|
||||
'chmod -R 700 /data/coolify/metrics /data/coolify/logs',
|
||||
], $server, false);
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,18 @@
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class UpdateCoolify
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public ?Server $server = null;
|
||||
|
||||
public ?string $latestVersion = null;
|
||||
|
||||
public ?string $currentVersion = null;
|
||||
|
||||
public function handle($manual_update = false)
|
||||
@ -46,14 +49,15 @@ private function update()
|
||||
{
|
||||
if (isDev()) {
|
||||
remote_process([
|
||||
"sleep 10"
|
||||
'sleep 10',
|
||||
], $this->server);
|
||||
|
||||
return;
|
||||
}
|
||||
remote_process([
|
||||
"curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh -o /data/coolify/source/upgrade.sh",
|
||||
"bash /data/coolify/source/upgrade.sh $this->latestVersion"
|
||||
'curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh -o /data/coolify/source/upgrade.sh',
|
||||
"bash /data/coolify/source/upgrade.sh $this->latestVersion",
|
||||
], $this->server);
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,13 @@
|
||||
|
||||
namespace App\Actions\Service;
|
||||
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use App\Models\Service;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class DeleteService
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Service $service)
|
||||
{
|
||||
try {
|
||||
|
@ -2,26 +2,27 @@
|
||||
|
||||
namespace App\Actions\Service;
|
||||
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use App\Models\Service;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class StartService
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Service $service)
|
||||
{
|
||||
ray('Starting service: '.$service->name);
|
||||
$service->saveComposeConfigs();
|
||||
$commands[] = "cd " . $service->workdir();
|
||||
$commands[] = 'cd '.$service->workdir();
|
||||
$commands[] = "echo 'Saved configuration files to {$service->workdir()}.'";
|
||||
$commands[] = "echo 'Creating Docker network.'";
|
||||
$commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid";
|
||||
$commands[] = "echo Starting service.";
|
||||
$commands[] = 'echo Starting service.';
|
||||
$commands[] = "echo 'Pulling images.'";
|
||||
$commands[] = "docker compose pull";
|
||||
$commands[] = 'docker compose pull';
|
||||
$commands[] = "echo 'Starting containers.'";
|
||||
$commands[] = "docker compose up -d --remove-orphans --force-recreate --build";
|
||||
$commands[] = 'docker compose up -d --remove-orphans --force-recreate --build';
|
||||
$commands[] = "docker network connect $service->uuid coolify-proxy >/dev/null 2>&1 || true";
|
||||
if (data_get($service, 'connect_to_docker_network')) {
|
||||
$compose = data_get($service, 'docker_compose', []);
|
||||
@ -32,6 +33,7 @@ public function handle(Service $service)
|
||||
}
|
||||
}
|
||||
$activity = remote_process($commands, $service->server, type_uuid: $service->uuid, callEventOnFinish: 'ServiceStatusChanged');
|
||||
|
||||
return $activity;
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,13 @@
|
||||
|
||||
namespace App\Actions\Service;
|
||||
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use App\Models\Service;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class StopService
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Service $service)
|
||||
{
|
||||
try {
|
||||
@ -33,6 +34,7 @@ public function handle(Service $service)
|
||||
} catch (\Exception $e) {
|
||||
echo $e->getMessage();
|
||||
ray($e->getMessage());
|
||||
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
class ComplexStatusCheck
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Application $application)
|
||||
{
|
||||
$servers = $application->additional_servers;
|
||||
@ -17,9 +18,11 @@ public function handle(Application $application)
|
||||
if (! $server->isFunctional()) {
|
||||
if ($is_main_server) {
|
||||
$application->update(['status' => 'exited:unhealthy']);
|
||||
|
||||
continue;
|
||||
} else {
|
||||
$application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited:unhealthy']);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -44,9 +47,11 @@ public function handle(Application $application)
|
||||
} else {
|
||||
if ($is_main_server) {
|
||||
$application->update(['status' => 'exited:unhealthy']);
|
||||
|
||||
continue;
|
||||
} else {
|
||||
$application->additional_servers()->updateExistingPivot($server->id, ['status' => 'exited:unhealthy']);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -8,17 +8,20 @@
|
||||
class PullImage
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Service $resource)
|
||||
{
|
||||
$resource->saveComposeConfigs();
|
||||
|
||||
$commands[] = "cd " . $resource->workdir();
|
||||
$commands[] = 'cd '.$resource->workdir();
|
||||
$commands[] = "echo 'Saved configuration files to {$resource->workdir()}.'";
|
||||
$commands[] = "docker compose pull";
|
||||
$commands[] = 'docker compose pull';
|
||||
|
||||
$server = data_get($resource, 'server');
|
||||
|
||||
if (!$server) return;
|
||||
if (! $server) {
|
||||
return;
|
||||
}
|
||||
|
||||
instant_remote_process($commands, $resource->server);
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
@ -32,6 +31,7 @@ public function handle()
|
||||
$confirm = $this->confirm('Are you sure you want to remove user with email: '.$email.'?');
|
||||
if (! $confirm) {
|
||||
$this->info('User removal cancelled.');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->info("Removing user with email: $email");
|
||||
@ -40,6 +40,7 @@ public function handle()
|
||||
foreach ($teams as $team) {
|
||||
if ($team->members->count() > 1) {
|
||||
$this->error('User is a member of a team with more than one member. Please remove user from team first.');
|
||||
|
||||
return;
|
||||
}
|
||||
$team->delete();
|
||||
@ -48,6 +49,7 @@ public function handle()
|
||||
} catch (\Exception $e) {
|
||||
$this->error('Failed to remove user.');
|
||||
$this->error($e->getMessage());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
class CleanupApplicationDeploymentQueue extends Command
|
||||
{
|
||||
protected $signature = 'cleanup:application-deployment-queue {--team-id=}';
|
||||
|
||||
protected $description = 'CleanupApplicationDeploymentQueue';
|
||||
|
||||
public function handle()
|
||||
@ -15,7 +16,7 @@ public function handle()
|
||||
$team_id = $this->option('team-id');
|
||||
$servers = \App\Models\Server::where('team_id', $team_id)->get();
|
||||
foreach ($servers as $server) {
|
||||
$deployments = ApplicationDeploymentQueue::whereIn("status", ["in_progress", "queued"])->where("server_id", $server->id)->get();
|
||||
$deployments = ApplicationDeploymentQueue::whereIn('status', ['in_progress', 'queued'])->where('server_id', $server->id)->get();
|
||||
foreach ($deployments as $deployment) {
|
||||
$deployment->update(['status' => 'failed']);
|
||||
instant_remote_process(['docker rm -f '.$deployment->deployment_uuid], $server, false);
|
||||
|
@ -8,6 +8,7 @@
|
||||
class CleanupDatabase extends Command
|
||||
{
|
||||
protected $signature = 'cleanup:database {--yes}';
|
||||
|
||||
protected $description = 'Cleanup database';
|
||||
|
||||
public function handle()
|
||||
|
@ -8,6 +8,7 @@
|
||||
class CleanupQueue extends Command
|
||||
{
|
||||
protected $signature = 'cleanup:queue';
|
||||
|
||||
protected $description = 'Cleanup Queue';
|
||||
|
||||
public function handle()
|
||||
|
@ -20,6 +20,7 @@
|
||||
class CleanupStuckedResources extends Command
|
||||
{
|
||||
protected $signature = 'cleanup:stucked-resources';
|
||||
|
||||
protected $description = 'Cleanup Stucked Resources';
|
||||
|
||||
public function handle()
|
||||
@ -28,6 +29,7 @@ public function handle()
|
||||
echo "Running cleanup stucked resources.\n";
|
||||
$this->cleanup_stucked_resources();
|
||||
}
|
||||
|
||||
private function cleanup_stucked_resources()
|
||||
{
|
||||
|
||||
@ -158,16 +160,19 @@ private function cleanup_stucked_resources()
|
||||
if (! data_get($application, 'environment')) {
|
||||
echo 'Application without environment: '.$application->name.'\n';
|
||||
$application->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! $application->destination()) {
|
||||
echo 'Application without destination: '.$application->name.'\n';
|
||||
$application->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! data_get($application, 'destination.server')) {
|
||||
echo 'Application without server: '.$application->name.'\n';
|
||||
$application->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -180,16 +185,19 @@ private function cleanup_stucked_resources()
|
||||
if (! data_get($postgresql, 'environment')) {
|
||||
echo 'Postgresql without environment: '.$postgresql->name.'\n';
|
||||
$postgresql->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! $postgresql->destination()) {
|
||||
echo 'Postgresql without destination: '.$postgresql->name.'\n';
|
||||
$postgresql->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! data_get($postgresql, 'destination.server')) {
|
||||
echo 'Postgresql without server: '.$postgresql->name.'\n';
|
||||
$postgresql->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -202,16 +210,19 @@ private function cleanup_stucked_resources()
|
||||
if (! data_get($redis, 'environment')) {
|
||||
echo 'Redis without environment: '.$redis->name.'\n';
|
||||
$redis->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! $redis->destination()) {
|
||||
echo 'Redis without destination: '.$redis->name.'\n';
|
||||
$redis->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! data_get($redis, 'destination.server')) {
|
||||
echo 'Redis without server: '.$redis->name.'\n';
|
||||
$redis->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -225,16 +236,19 @@ private function cleanup_stucked_resources()
|
||||
if (! data_get($mongodb, 'environment')) {
|
||||
echo 'Mongodb without environment: '.$mongodb->name.'\n';
|
||||
$mongodb->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! $mongodb->destination()) {
|
||||
echo 'Mongodb without destination: '.$mongodb->name.'\n';
|
||||
$mongodb->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! data_get($mongodb, 'destination.server')) {
|
||||
echo 'Mongodb without server: '.$mongodb->name.'\n';
|
||||
$mongodb->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -248,16 +262,19 @@ private function cleanup_stucked_resources()
|
||||
if (! data_get($mysql, 'environment')) {
|
||||
echo 'Mysql without environment: '.$mysql->name.'\n';
|
||||
$mysql->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! $mysql->destination()) {
|
||||
echo 'Mysql without destination: '.$mysql->name.'\n';
|
||||
$mysql->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! data_get($mysql, 'destination.server')) {
|
||||
echo 'Mysql without server: '.$mysql->name.'\n';
|
||||
$mysql->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -271,16 +288,19 @@ private function cleanup_stucked_resources()
|
||||
if (! data_get($mariadb, 'environment')) {
|
||||
echo 'Mariadb without environment: '.$mariadb->name.'\n';
|
||||
$mariadb->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! $mariadb->destination()) {
|
||||
echo 'Mariadb without destination: '.$mariadb->name.'\n';
|
||||
$mariadb->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! data_get($mariadb, 'destination.server')) {
|
||||
echo 'Mariadb without server: '.$mariadb->name.'\n';
|
||||
$mariadb->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -294,16 +314,19 @@ private function cleanup_stucked_resources()
|
||||
if (! data_get($service, 'environment')) {
|
||||
echo 'Service without environment: '.$service->name.'\n';
|
||||
$service->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! $service->destination()) {
|
||||
echo 'Service without destination: '.$service->name.'\n';
|
||||
$service->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! data_get($service, 'server')) {
|
||||
echo 'Service without server: '.$service->name.'\n';
|
||||
$service->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -316,6 +339,7 @@ private function cleanup_stucked_resources()
|
||||
if (! data_get($service, 'service')) {
|
||||
echo 'ServiceApplication without service: '.$service->name.'\n';
|
||||
$service->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -328,6 +352,7 @@ private function cleanup_stucked_resources()
|
||||
if (! data_get($service, 'service')) {
|
||||
echo 'ServiceDatabase without service: '.$service->name.'\n';
|
||||
$service->forceDelete();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
class CleanupUnreachableServers extends Command
|
||||
{
|
||||
protected $signature = 'cleanup:unreachable-servers';
|
||||
|
||||
protected $description = 'Cleanup Unreachable Servers (7 days)';
|
||||
|
||||
public function handle()
|
||||
@ -19,7 +20,7 @@ public function handle()
|
||||
echo "Cleanup unreachable server ($server->id) with name $server->name";
|
||||
send_internal_notification("Server $server->name is unreachable for 7 days. Cleaning up...");
|
||||
$server->update([
|
||||
'ip' => '1.2.3.4'
|
||||
'ip' => '1.2.3.4',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
class Dev extends Command
|
||||
{
|
||||
protected $signature = 'dev:init';
|
||||
|
||||
protected $description = 'Init the app in dev mode';
|
||||
|
||||
public function handle()
|
||||
|
@ -2,12 +2,10 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Jobs\DatabaseBackupStatusJob;
|
||||
use App\Jobs\SendConfirmationForWaitlistJob;
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationPreview;
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use App\Models\ScheduledDatabaseBackupExecution;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandalonePostgresql;
|
||||
use App\Models\Team;
|
||||
@ -49,7 +47,9 @@ class Emails extends Command
|
||||
* Execute the console command.
|
||||
*/
|
||||
private ?MailMessage $mail = null;
|
||||
|
||||
private ?string $email = null;
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$type = select(
|
||||
@ -73,7 +73,7 @@ public function handle()
|
||||
);
|
||||
$emailsGathered = ['realusers-before-trial', 'realusers-server-lost-connection'];
|
||||
if (isDev()) {
|
||||
$this->email = "test@example.com";
|
||||
$this->email = 'test@example.com';
|
||||
} else {
|
||||
if (! in_array($type, $emailsGathered)) {
|
||||
$this->email = text('Email Address to send to:');
|
||||
@ -82,12 +82,13 @@ public function handle()
|
||||
set_transanctional_email_settings();
|
||||
|
||||
$this->mail = new MailMessage();
|
||||
$this->mail->subject("Test Email");
|
||||
$this->mail->subject('Test Email');
|
||||
switch ($type) {
|
||||
case 'updates':
|
||||
$teams = Team::all();
|
||||
if (! $teams || $teams->isEmpty()) {
|
||||
echo 'No teams found.'.PHP_EOL;
|
||||
|
||||
return;
|
||||
}
|
||||
$emails = [];
|
||||
@ -99,7 +100,7 @@ public function handle()
|
||||
}
|
||||
}
|
||||
$emails = array_unique($emails);
|
||||
$this->info("Sending to " . count($emails) . " emails.");
|
||||
$this->info('Sending to '.count($emails).' emails.');
|
||||
foreach ($emails as $email) {
|
||||
$this->info($email);
|
||||
}
|
||||
@ -111,7 +112,7 @@ public function handle()
|
||||
$unsubscribeUrl = route('unsubscribe.marketing.emails', [
|
||||
'token' => encrypt($email),
|
||||
]);
|
||||
$this->mail->view('emails.updates', ["unsubscribeUrl" => $unsubscribeUrl]);
|
||||
$this->mail->view('emails.updates', ['unsubscribeUrl' => $unsubscribeUrl]);
|
||||
$this->sendEmail($email);
|
||||
}
|
||||
}
|
||||
@ -246,6 +247,7 @@ public function handle()
|
||||
$teams = Team::doesntHave('subscription')->where('id', '!=', 0)->get();
|
||||
if (! $teams || $teams->isEmpty()) {
|
||||
echo 'No teams found.'.PHP_EOL;
|
||||
|
||||
return;
|
||||
}
|
||||
$emails = [];
|
||||
@ -257,7 +259,7 @@ public function handle()
|
||||
}
|
||||
}
|
||||
$emails = array_unique($emails);
|
||||
$this->info("Sending to " . count($emails) . " emails.");
|
||||
$this->info('Sending to '.count($emails).' emails.');
|
||||
foreach ($emails as $email) {
|
||||
$this->info($email);
|
||||
}
|
||||
@ -296,7 +298,8 @@ public function handle()
|
||||
break;
|
||||
}
|
||||
}
|
||||
private function sendEmail(string $email = null)
|
||||
|
||||
private function sendEmail(?string $email = null)
|
||||
{
|
||||
if ($email) {
|
||||
$this->email = $email;
|
||||
|
@ -7,7 +7,9 @@
|
||||
class Horizon extends Command
|
||||
{
|
||||
protected $signature = 'start:horizon';
|
||||
|
||||
protected $description = 'Start Horizon';
|
||||
|
||||
public function handle()
|
||||
{
|
||||
if (config('coolify.is_horizon_enabled')) {
|
||||
|
@ -15,6 +15,7 @@
|
||||
class Init extends Command
|
||||
{
|
||||
protected $signature = 'app:init {--full-cleanup} {--cleanup-deployments}';
|
||||
|
||||
protected $description = 'Cleanup instance related stuffs';
|
||||
|
||||
public function handle()
|
||||
@ -26,6 +27,7 @@ public function handle()
|
||||
if ($cleanup_deployments) {
|
||||
echo "Running cleanup deployments.\n";
|
||||
$this->cleanup_in_progress_application_deployments();
|
||||
|
||||
return;
|
||||
}
|
||||
if ($full_cleanup) {
|
||||
@ -52,6 +54,7 @@ public function handle()
|
||||
$settings->update(['is_auto_update_enabled' => false]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
$this->cleanup_stucked_helper_containers();
|
||||
@ -82,6 +85,7 @@ private function restore_coolify_db_backup()
|
||||
echo "Error in restoring coolify db backup: {$e->getMessage()}\n";
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanup_stucked_helper_containers()
|
||||
{
|
||||
$servers = Server::all();
|
||||
@ -91,6 +95,7 @@ private function cleanup_stucked_helper_containers()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function alive()
|
||||
{
|
||||
$id = config('app.id');
|
||||
@ -99,6 +104,7 @@ private function alive()
|
||||
$do_not_track = data_get($settings, 'do_not_track');
|
||||
if ($do_not_track == true) {
|
||||
echo "Skipping alive as do_not_track is enabled\n";
|
||||
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use function Termwind\ask;
|
||||
use function Termwind\render;
|
||||
use function Termwind\style;
|
||||
@ -32,6 +33,7 @@ public function handle()
|
||||
|
||||
if (blank($channel)) {
|
||||
$this->showHelp();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ public function handle()
|
||||
$this->info('Root user\'s email updated successfully.');
|
||||
} catch (\Exception $e) {
|
||||
$this->error('Failed to update root user\'s email.');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ public function handle()
|
||||
$passwordAgain = password('Again');
|
||||
if ($password != $passwordAgain) {
|
||||
$this->error('Passwords do not match.');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->info('Updating root password...');
|
||||
@ -42,6 +43,7 @@ public function handle()
|
||||
$this->info('Root password updated successfully.');
|
||||
} catch (\Exception $e) {
|
||||
$this->error('Failed to update root password.');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,9 @@
|
||||
class Scheduler extends Command
|
||||
{
|
||||
protected $signature = 'start:scheduler';
|
||||
|
||||
protected $description = 'Start Scheduler';
|
||||
|
||||
public function handle()
|
||||
{
|
||||
if (config('coolify.is_scheduler_enabled')) {
|
||||
|
@ -48,11 +48,13 @@ public function handle()
|
||||
$this->deleteServer();
|
||||
}
|
||||
}
|
||||
|
||||
private function deleteServer()
|
||||
{
|
||||
$servers = Server::all();
|
||||
if ($servers->count() === 0) {
|
||||
$this->error('There are no applications to delete.');
|
||||
|
||||
return;
|
||||
}
|
||||
$serversToDelete = multiselect(
|
||||
@ -64,7 +66,7 @@ private function deleteServer()
|
||||
$toDelete = $servers->where('id', $server)->first();
|
||||
if ($toDelete) {
|
||||
$this->info($toDelete);
|
||||
$confirmed = confirm("Are you sure you want to delete all selected resources?");
|
||||
$confirmed = confirm('Are you sure you want to delete all selected resources?');
|
||||
if (! $confirmed) {
|
||||
break;
|
||||
}
|
||||
@ -72,11 +74,13 @@ private function deleteServer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function deleteApplication()
|
||||
{
|
||||
$applications = Application::all();
|
||||
if ($applications->count() === 0) {
|
||||
$this->error('There are no applications to delete.');
|
||||
|
||||
return;
|
||||
}
|
||||
$applicationsToDelete = multiselect(
|
||||
@ -88,7 +92,7 @@ private function deleteApplication()
|
||||
$toDelete = $applications->where('id', $application)->first();
|
||||
if ($toDelete) {
|
||||
$this->info($toDelete);
|
||||
$confirmed = confirm("Are you sure you want to delete all selected resources? ");
|
||||
$confirmed = confirm('Are you sure you want to delete all selected resources? ');
|
||||
if (! $confirmed) {
|
||||
break;
|
||||
}
|
||||
@ -96,11 +100,13 @@ private function deleteApplication()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function deleteDatabase()
|
||||
{
|
||||
$databases = StandalonePostgresql::all();
|
||||
if ($databases->count() === 0) {
|
||||
$this->error('There are no databases to delete.');
|
||||
|
||||
return;
|
||||
}
|
||||
$databasesToDelete = multiselect(
|
||||
@ -112,7 +118,7 @@ private function deleteDatabase()
|
||||
$toDelete = $databases->where('id', $database)->first();
|
||||
if ($toDelete) {
|
||||
$this->info($toDelete);
|
||||
$confirmed = confirm("Are you sure you want to delete all selected resources?");
|
||||
$confirmed = confirm('Are you sure you want to delete all selected resources?');
|
||||
if (! $confirmed) {
|
||||
return;
|
||||
}
|
||||
@ -120,11 +126,13 @@ private function deleteDatabase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function deleteService()
|
||||
{
|
||||
$services = Service::all();
|
||||
if ($services->count() === 0) {
|
||||
$this->error('There are no services to delete.');
|
||||
|
||||
return;
|
||||
}
|
||||
$servicesToDelete = multiselect(
|
||||
@ -136,7 +144,7 @@ private function deleteService()
|
||||
$toDelete = $services->where('id', $service)->first();
|
||||
if ($toDelete) {
|
||||
$this->info($toDelete);
|
||||
$confirmed = confirm("Are you sure you want to delete all selected resources?");
|
||||
$confirmed = confirm('Are you sure you want to delete all selected resources?');
|
||||
if (! $confirmed) {
|
||||
return;
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ private function process_file($file)
|
||||
}
|
||||
if ($ignore) {
|
||||
$this->info("Ignoring $file");
|
||||
|
||||
return;
|
||||
}
|
||||
$this->info("Processing $file");
|
||||
@ -125,6 +126,7 @@ private function process_file($file)
|
||||
$env_file_base64 = base64_encode($env_file_content);
|
||||
$payload['envs'] = $env_file_base64;
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
}
|
||||
|
@ -33,30 +33,31 @@ public function handle()
|
||||
$that = $this;
|
||||
$only_template = $this->option('templates');
|
||||
$only_version = $this->option('release');
|
||||
$bunny_cdn = "https://cdn.coollabs.io";
|
||||
$bunny_cdn_path = "coolify";
|
||||
$bunny_cdn_storage_name = "coolcdn";
|
||||
$bunny_cdn = 'https://cdn.coollabs.io';
|
||||
$bunny_cdn_path = 'coolify';
|
||||
$bunny_cdn_storage_name = 'coolcdn';
|
||||
|
||||
$parent_dir = realpath(dirname(__FILE__).'/../../..');
|
||||
|
||||
$compose_file = "docker-compose.yml";
|
||||
$compose_file_prod = "docker-compose.prod.yml";
|
||||
$install_script = "install.sh";
|
||||
$upgrade_script = "upgrade.sh";
|
||||
$production_env = ".env.production";
|
||||
$service_template = "service-templates.json";
|
||||
$compose_file = 'docker-compose.yml';
|
||||
$compose_file_prod = 'docker-compose.prod.yml';
|
||||
$install_script = 'install.sh';
|
||||
$upgrade_script = 'upgrade.sh';
|
||||
$production_env = '.env.production';
|
||||
$service_template = 'service-templates.json';
|
||||
|
||||
$versions = "versions.json";
|
||||
$versions = 'versions.json';
|
||||
|
||||
PendingRequest::macro('storage', function ($fileName) use ($that) {
|
||||
$headers = [
|
||||
'AccessKey' => env('BUNNY_STORAGE_API_KEY'),
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/octet-stream'
|
||||
'Content-Type' => 'application/octet-stream',
|
||||
];
|
||||
$fileStream = fopen($fileName, "r");
|
||||
$fileStream = fopen($fileName, 'r');
|
||||
$file = fread($fileStream, filesize($fileName));
|
||||
$that->info('Uploading: '.$fileName);
|
||||
|
||||
return PendingRequest::baseUrl('https://storage.bunnycdn.com')->withHeaders($headers)->withBody($file)->throw();
|
||||
});
|
||||
PendingRequest::macro('purge', function ($url) use ($that) {
|
||||
@ -65,9 +66,10 @@ public function handle()
|
||||
'Accept' => 'application/json',
|
||||
];
|
||||
$that->info('Purging: '.$url);
|
||||
|
||||
return PendingRequest::withHeaders($headers)->get('https://api.bunny.net/purge', [
|
||||
"url" => $url,
|
||||
"async" => false
|
||||
'url' => $url,
|
||||
'async' => false,
|
||||
]);
|
||||
});
|
||||
try {
|
||||
@ -76,7 +78,7 @@ public function handle()
|
||||
}
|
||||
if ($only_template) {
|
||||
$this->info('About to sync service-templates.json to BunnyCDN.');
|
||||
$confirmed = confirm("Are you sure you want to sync?");
|
||||
$confirmed = confirm('Are you sure you want to sync?');
|
||||
if (! $confirmed) {
|
||||
return;
|
||||
}
|
||||
@ -85,6 +87,7 @@ public function handle()
|
||||
$pool->purge("$bunny_cdn/$bunny_cdn_path/$service_template"),
|
||||
]);
|
||||
$this->info('Service template uploaded & purged...');
|
||||
|
||||
return;
|
||||
} elseif ($only_version) {
|
||||
$this->info('About to sync versions.json to BunnyCDN.');
|
||||
@ -101,10 +104,10 @@ public function handle()
|
||||
$pool->purge("$bunny_cdn/$bunny_cdn_path/$versions"),
|
||||
]);
|
||||
$this->info('versions.json uploaded & purged...');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Http::pool(fn (Pool $pool) => [
|
||||
$pool->storage(fileName: "$parent_dir/$compose_file")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file"),
|
||||
$pool->storage(fileName: "$parent_dir/$compose_file_prod")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file_prod"),
|
||||
@ -119,9 +122,9 @@ public function handle()
|
||||
$pool->purge("$bunny_cdn/$bunny_cdn_path/$upgrade_script"),
|
||||
$pool->purge("$bunny_cdn/$bunny_cdn_path/$install_script"),
|
||||
]);
|
||||
$this->info("All files uploaded & purged...");
|
||||
$this->info('All files uploaded & purged...');
|
||||
} catch (\Throwable $e) {
|
||||
$this->error("Error: " . $e->getMessage());
|
||||
$this->error('Error: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,9 @@
|
||||
class WaitlistInvite extends Command
|
||||
{
|
||||
public Waitlist|User|null $next_patient = null;
|
||||
public string|null $password = null;
|
||||
|
||||
public ?string $password = null;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
@ -38,7 +40,9 @@ public function handle()
|
||||
$this->main();
|
||||
}
|
||||
}
|
||||
private function main() {
|
||||
|
||||
private function main()
|
||||
{
|
||||
if ($this->argument('email')) {
|
||||
if ($this->option('only-email')) {
|
||||
$this->next_patient = User::whereEmail($this->argument('email'))->first();
|
||||
@ -52,6 +56,7 @@ private function main() {
|
||||
}
|
||||
if (! $this->next_patient) {
|
||||
$this->error("{$this->argument('email')} not found in the waitlist.");
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -60,6 +65,7 @@ private function main() {
|
||||
if ($this->next_patient) {
|
||||
if ($this->option('only-email')) {
|
||||
$this->send_email();
|
||||
|
||||
return;
|
||||
}
|
||||
$this->register_user();
|
||||
@ -69,6 +75,7 @@ private function main() {
|
||||
$this->info('No verified user found in the waitlist. 👀');
|
||||
}
|
||||
}
|
||||
|
||||
private function register_user()
|
||||
{
|
||||
$already_registered = User::whereEmail($this->next_patient->email)->first();
|
||||
@ -85,11 +92,13 @@ private function register_user()
|
||||
throw new \Exception('User already registered');
|
||||
}
|
||||
}
|
||||
|
||||
private function remove_from_waitlist()
|
||||
{
|
||||
$this->next_patient->delete();
|
||||
$this->info("User removed from waitlist successfully.");
|
||||
$this->info('User removed from waitlist successfully.');
|
||||
}
|
||||
|
||||
private function send_email()
|
||||
{
|
||||
$token = Crypt::encryptString("{$this->next_patient->email}@@@$this->password");
|
||||
@ -100,6 +109,6 @@ private function send_email()
|
||||
]);
|
||||
$mail->subject('Congratulations! You are invited to join Coolify Cloud.');
|
||||
send_user_an_email($mail, $this->next_patient->email);
|
||||
$this->info("Email sent successfully. 📧");
|
||||
$this->info('Email sent successfully. 📧');
|
||||
}
|
||||
}
|
||||
|
@ -4,13 +4,13 @@
|
||||
|
||||
use App\Jobs\CheckLogDrainContainerJob;
|
||||
use App\Jobs\CleanupInstanceStuffsJob;
|
||||
use App\Jobs\DatabaseBackupJob;
|
||||
use App\Jobs\ScheduledTaskJob;
|
||||
use App\Jobs\ContainerStatusJob;
|
||||
use App\Jobs\DatabaseBackupJob;
|
||||
use App\Jobs\PullCoolifyImageJob;
|
||||
use App\Jobs\PullHelperImageJob;
|
||||
use App\Jobs\PullSentinelImageJob;
|
||||
use App\Jobs\PullTemplatesFromCDN;
|
||||
use App\Jobs\ScheduledTaskJob;
|
||||
use App\Jobs\ServerStatusJob;
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use App\Models\ScheduledTask;
|
||||
@ -22,6 +22,7 @@
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
private $all_servers;
|
||||
|
||||
protected function schedule(Schedule $schedule): void
|
||||
{
|
||||
$this->all_servers = Server::all();
|
||||
@ -55,6 +56,7 @@ protected function schedule(Schedule $schedule): void
|
||||
$schedule->command('uploads:clear')->everyTwoMinutes();
|
||||
}
|
||||
}
|
||||
|
||||
private function pull_images($schedule)
|
||||
{
|
||||
$servers = $this->all_servers->where('settings.is_usable', true)->where('settings.is_reachable', true)->where('ip', '!=', '1.2.3.4');
|
||||
@ -65,6 +67,7 @@ private function pull_images($schedule)
|
||||
$schedule->job(new PullHelperImageJob($server))->everyFiveMinutes()->onOneServer();
|
||||
}
|
||||
}
|
||||
|
||||
private function check_resources($schedule)
|
||||
{
|
||||
if (isCloud()) {
|
||||
@ -86,6 +89,7 @@ private function check_resources($schedule)
|
||||
$schedule->job(new ServerStatusJob($server))->everyMinute()->onOneServer();
|
||||
}
|
||||
}
|
||||
|
||||
private function check_scheduled_backups($schedule)
|
||||
{
|
||||
$scheduled_backups = ScheduledDatabaseBackup::all();
|
||||
@ -99,6 +103,7 @@ private function check_scheduled_backups($schedule)
|
||||
if (is_null(data_get($scheduled_backup, 'database'))) {
|
||||
ray('database not found');
|
||||
$scheduled_backup->delete();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -127,6 +132,7 @@ private function check_scheduled_tasks($schedule)
|
||||
if (! $application && ! $service) {
|
||||
ray('application/service attached to scheduled task does not exist');
|
||||
$scheduled_task->delete();
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($application) {
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
@ -13,14 +11,16 @@
|
||||
class ApplicationStatusChanged implements ShouldBroadcast
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $teamId;
|
||||
|
||||
public function __construct($teamId = null)
|
||||
{
|
||||
if (is_null($teamId)) {
|
||||
$teamId = auth()->user()->currentTeam()->id ?? null;
|
||||
}
|
||||
if (is_null($teamId)) {
|
||||
throw new \Exception("Team id is null");
|
||||
throw new \Exception('Team id is null');
|
||||
}
|
||||
$this->teamId = $teamId;
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
@ -13,14 +11,16 @@
|
||||
class BackupCreated implements ShouldBroadcast
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $teamId;
|
||||
|
||||
public function __construct($teamId = null)
|
||||
{
|
||||
if (is_null($teamId)) {
|
||||
$teamId = auth()->user()->currentTeam()->id ?? null;
|
||||
}
|
||||
if (is_null($teamId)) {
|
||||
throw new \Exception("Team id is null");
|
||||
throw new \Exception('Team id is null');
|
||||
}
|
||||
$this->teamId = $teamId;
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
@ -13,14 +11,16 @@
|
||||
class DatabaseStatusChanged implements ShouldBroadcast
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $userId;
|
||||
|
||||
public function __construct($userId = null)
|
||||
{
|
||||
if (is_null($userId)) {
|
||||
$userId = auth()->user()->id ?? null;
|
||||
}
|
||||
if (is_null($userId)) {
|
||||
throw new \Exception("User id is null");
|
||||
throw new \Exception('User id is null');
|
||||
}
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
class ProxyStarted
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public function __construct(public $data)
|
||||
{
|
||||
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
@ -13,14 +11,16 @@
|
||||
class ProxyStatusChanged implements ShouldBroadcast
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $teamId;
|
||||
|
||||
public function __construct($teamId = null)
|
||||
{
|
||||
if (is_null($teamId)) {
|
||||
$teamId = auth()->user()->currentTeam()->id ?? null;
|
||||
}
|
||||
if (is_null($teamId)) {
|
||||
throw new \Exception("Team id is null");
|
||||
throw new \Exception('Team id is null');
|
||||
}
|
||||
$this->teamId = $teamId;
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
@ -13,14 +11,16 @@
|
||||
class ServiceStatusChanged implements ShouldBroadcast
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $userId;
|
||||
|
||||
public function __construct($userId = null)
|
||||
{
|
||||
if (is_null($userId)) {
|
||||
$userId = auth()->user()->id ?? null;
|
||||
}
|
||||
if (is_null($userId)) {
|
||||
throw new \Exception("User id is null");
|
||||
throw new \Exception('User id is null');
|
||||
}
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
@ -13,7 +11,9 @@
|
||||
class TestEvent implements ShouldBroadcast
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public $teamId;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->teamId = auth()->user()->currentTeam()->id;
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* A list of exception types with their corresponding custom log levels.
|
||||
*
|
||||
@ -22,14 +21,16 @@ class Handler extends ExceptionHandler
|
||||
protected $levels = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the exception types that are not reported.
|
||||
*
|
||||
* @var array<int, class-string<\Throwable>>
|
||||
*/
|
||||
protected $dontReport = [
|
||||
ProcessException::class
|
||||
ProcessException::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the inputs that are never flashed to the session on validation exceptions.
|
||||
*
|
||||
@ -40,6 +41,7 @@ class Handler extends ExceptionHandler
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
|
||||
private InstanceSettings $settings;
|
||||
|
||||
protected function unauthenticated($request, AuthenticationException $exception)
|
||||
@ -47,8 +49,10 @@ protected function unauthenticated($request, AuthenticationException $exception)
|
||||
if ($request->is('api/*') || $request->expectsJson() || $this->shouldReturnJson($request, $exception)) {
|
||||
return response()->json(['message' => $exception->getMessage()], 401);
|
||||
}
|
||||
|
||||
return redirect()->guest($exception->redirectTo() ?? route('login'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the exception handling callbacks for the application.
|
||||
*/
|
||||
@ -72,7 +76,7 @@ function (Scope $scope) {
|
||||
$scope->setUser(
|
||||
[
|
||||
'email' => $email,
|
||||
'instanceAdmin' => $instanceAdmin
|
||||
'instanceAdmin' => $instanceAdmin,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -6,5 +6,4 @@
|
||||
|
||||
class ProcessException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -27,18 +27,20 @@ public function deployments(Request $request)
|
||||
return invalid_token();
|
||||
}
|
||||
$servers = Server::whereTeamId($teamId)->get();
|
||||
$deployments_per_server = ApplicationDeploymentQueue::whereIn("status", ["in_progress", "queued"])->whereIn("server_id", $servers->pluck("id"))->get([
|
||||
"id",
|
||||
"application_id",
|
||||
"application_name",
|
||||
"deployment_url",
|
||||
"pull_request_id",
|
||||
"server_name",
|
||||
"server_id",
|
||||
"status"
|
||||
$deployments_per_server = ApplicationDeploymentQueue::whereIn('status', ['in_progress', 'queued'])->whereIn('server_id', $servers->pluck('id'))->get([
|
||||
'id',
|
||||
'application_id',
|
||||
'application_name',
|
||||
'deployment_url',
|
||||
'pull_request_id',
|
||||
'server_name',
|
||||
'server_id',
|
||||
'status',
|
||||
])->sortBy('id')->toArray();
|
||||
|
||||
return response()->json($deployments_per_server, 200);
|
||||
}
|
||||
|
||||
public function deploy(Request $request)
|
||||
{
|
||||
$teamId = get_team_id_from_token();
|
||||
@ -57,8 +59,10 @@ public function deploy(Request $request)
|
||||
} elseif ($uuids) {
|
||||
return $this->by_uuids($uuids, $teamId, $force);
|
||||
}
|
||||
|
||||
return response()->json(['error' => 'You must provide uuid or tag.', 'docs' => 'https://coolify.io/docs/api-reference/deploy-webhook'], 400);
|
||||
}
|
||||
|
||||
private function by_uuids(string $uuid, int $teamId, bool $force = false)
|
||||
{
|
||||
$uuids = explode(',', $uuid);
|
||||
@ -82,10 +86,13 @@ private function by_uuids(string $uuid, int $teamId, bool $force = false)
|
||||
}
|
||||
if ($deployments->count() > 0) {
|
||||
$payload->put('deployments', $deployments->toArray());
|
||||
|
||||
return response()->json($payload->toArray(), 200);
|
||||
}
|
||||
return response()->json(['error' => "No resources found.", 'docs' => 'https://coolify.io/docs/api-reference/deploy-webhook'], 404);
|
||||
|
||||
return response()->json(['error' => 'No resources found.', 'docs' => 'https://coolify.io/docs/api-reference/deploy-webhook'], 404);
|
||||
}
|
||||
|
||||
public function by_tags(string $tags, int $team_id, bool $force = false)
|
||||
{
|
||||
$tags = explode(',', $tags);
|
||||
@ -107,6 +114,7 @@ public function by_tags(string $tags, int $team_id, bool $force = false)
|
||||
$services = $found_tag->services()->get();
|
||||
if ($applications->count() === 0 && $services->count() === 0) {
|
||||
$message->push("No resources found for tag {$tag}.");
|
||||
|
||||
continue;
|
||||
}
|
||||
foreach ($applications as $resource) {
|
||||
@ -127,11 +135,13 @@ public function by_tags(string $tags, int $team_id, bool $force = false)
|
||||
if ($deployments->count() > 0) {
|
||||
$payload->put('details', $deployments->toArray());
|
||||
}
|
||||
|
||||
return response()->json($payload->toArray(), 200);
|
||||
}
|
||||
|
||||
return response()->json(['error' => "No resources found with this tag.", 'docs' => 'https://coolify.io/docs/api-reference/deploy-webhook'], 404);
|
||||
return response()->json(['error' => 'No resources found with this tag.', 'docs' => 'https://coolify.io/docs/api-reference/deploy-webhook'], 404);
|
||||
}
|
||||
|
||||
public function deploy_resource($resource, bool $force = false): array
|
||||
{
|
||||
$message = null;
|
||||
@ -200,6 +210,7 @@ public function deploy_resource($resource, bool $force = false): array
|
||||
StartService::run($resource);
|
||||
$message = "Service {$resource->name} started. It could take a while, be patient.";
|
||||
}
|
||||
|
||||
return ['message' => $message, 'deployment_uuid' => $deployment_uuid];
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,10 @@ public function projects(Request $request)
|
||||
return invalid_token();
|
||||
}
|
||||
$projects = ModelsProject::whereTeamId($teamId)->select('id', 'name', 'uuid')->get();
|
||||
|
||||
return response()->json($projects);
|
||||
}
|
||||
|
||||
public function project_by_uuid(Request $request)
|
||||
{
|
||||
$teamId = get_team_id_from_token();
|
||||
@ -24,8 +26,10 @@ public function project_by_uuid(Request $request)
|
||||
return invalid_token();
|
||||
}
|
||||
$project = ModelsProject::whereTeamId($teamId)->whereUuid(request()->uuid)->first()->load(['environments']);
|
||||
|
||||
return response()->json($project);
|
||||
}
|
||||
|
||||
public function environment_details(Request $request)
|
||||
{
|
||||
$teamId = get_team_id_from_token();
|
||||
@ -34,6 +38,7 @@ public function environment_details(Request $request)
|
||||
}
|
||||
$project = ModelsProject::whereTeamId($teamId)->whereUuid(request()->uuid)->first();
|
||||
$environment = $project->environments()->whereName(request()->environment_name)->first()->load(['applications', 'postgresqls', 'redis', 'mongodbs', 'mysqls', 'mariadbs', 'services']);
|
||||
|
||||
return response()->json($environment);
|
||||
}
|
||||
}
|
||||
|
@ -30,9 +30,10 @@ public function resources(Request $request)
|
||||
$payload['status'] = $resource->status;
|
||||
}
|
||||
$payload['type'] = $resource->type();
|
||||
|
||||
return $payload;
|
||||
});
|
||||
|
||||
return response()->json($resources);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,10 +17,13 @@ public function servers(Request $request)
|
||||
$servers = ModelsServer::whereTeamId($teamId)->select('id', 'name', 'uuid', 'ip', 'user', 'port')->get()->load(['settings'])->map(function ($server) {
|
||||
$server['is_reachable'] = $server->settings->is_reachable;
|
||||
$server['is_usable'] = $server->settings->is_usable;
|
||||
|
||||
return $server;
|
||||
});
|
||||
|
||||
return response()->json($servers);
|
||||
}
|
||||
|
||||
public function server_by_uuid(Request $request)
|
||||
{
|
||||
$with_resources = $request->query('resources');
|
||||
@ -47,11 +50,13 @@ public function server_by_uuid(Request $request)
|
||||
} else {
|
||||
$payload['status'] = $resource->status;
|
||||
}
|
||||
|
||||
return $payload;
|
||||
});
|
||||
} else {
|
||||
$server->load(['settings']);
|
||||
}
|
||||
|
||||
return response()->json($server);
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,10 @@ public function teams(Request $request)
|
||||
return invalid_token();
|
||||
}
|
||||
$teams = auth()->user()->teams;
|
||||
|
||||
return response()->json($teams);
|
||||
}
|
||||
|
||||
public function team_by_id(Request $request)
|
||||
{
|
||||
$id = $request->id;
|
||||
@ -26,10 +28,12 @@ public function team_by_id(Request $request)
|
||||
$teams = auth()->user()->teams;
|
||||
$team = $teams->where('id', $id)->first();
|
||||
if (is_null($team)) {
|
||||
return response()->json(['error' => 'Team not found.', "docs" => "https://coolify.io/docs/api-reference/get-team-by-teamid"], 404);
|
||||
return response()->json(['error' => 'Team not found.', 'docs' => 'https://coolify.io/docs/api-reference/get-team-by-teamid'], 404);
|
||||
}
|
||||
|
||||
return response()->json($team);
|
||||
}
|
||||
|
||||
public function members_by_id(Request $request)
|
||||
{
|
||||
$id = $request->id;
|
||||
@ -40,10 +44,12 @@ public function members_by_id(Request $request)
|
||||
$teams = auth()->user()->teams;
|
||||
$team = $teams->where('id', $id)->first();
|
||||
if (is_null($team)) {
|
||||
return response()->json(['error' => 'Team not found.', "docs" => "https://coolify.io/docs/api-reference/get-team-by-teamid-members"], 404);
|
||||
return response()->json(['error' => 'Team not found.', 'docs' => 'https://coolify.io/docs/api-reference/get-team-by-teamid-members'], 404);
|
||||
}
|
||||
|
||||
return response()->json($team->members);
|
||||
}
|
||||
|
||||
public function current_team(Request $request)
|
||||
{
|
||||
$teamId = get_team_id_from_token();
|
||||
@ -51,8 +57,10 @@ public function current_team(Request $request)
|
||||
return invalid_token();
|
||||
}
|
||||
$team = auth()->user()->currentTeam();
|
||||
|
||||
return response()->json($team);
|
||||
}
|
||||
|
||||
public function current_team_members(Request $request)
|
||||
{
|
||||
$teamId = get_team_id_from_token();
|
||||
@ -60,6 +68,7 @@ public function current_team_members(Request $request)
|
||||
return invalid_token();
|
||||
}
|
||||
$team = auth()->user()->currentTeam();
|
||||
|
||||
return response()->json($team->members);
|
||||
}
|
||||
}
|
||||
|
@ -14,33 +14,42 @@
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Fortify\Fortify;
|
||||
use Laravel\Fortify\Contracts\FailedPasswordResetLinkRequestResponse;
|
||||
use Laravel\Fortify\Contracts\SuccessfulPasswordResetLinkRequestResponse;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Laravel\Fortify\Fortify;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, ValidatesRequests;
|
||||
|
||||
public function realtime_test() {
|
||||
public function realtime_test()
|
||||
{
|
||||
if (auth()->user()?->currentTeam()->id !== 0) {
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
TestEvent::dispatch();
|
||||
|
||||
return 'Look at your other tab.';
|
||||
}
|
||||
public function verify() {
|
||||
|
||||
public function verify()
|
||||
{
|
||||
return view('auth.verify-email');
|
||||
}
|
||||
public function email_verify(EmailVerificationRequest $request) {
|
||||
|
||||
public function email_verify(EmailVerificationRequest $request)
|
||||
{
|
||||
$request->fulfill();
|
||||
$name = request()->user()?->name;
|
||||
|
||||
// send_internal_notification("User {$name} verified their email address.");
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
public function forgot_password(Request $request) {
|
||||
|
||||
public function forgot_password(Request $request)
|
||||
{
|
||||
if (is_transactional_emails_active()) {
|
||||
$arrayOfRequest = $request->only(Fortify::email());
|
||||
$request->merge([
|
||||
@ -60,10 +69,13 @@ public function forgot_password(Request $request) {
|
||||
if ($status == Password::RESET_THROTTLED) {
|
||||
return response('Already requested a password reset in the past minutes.', 400);
|
||||
}
|
||||
|
||||
return app(FailedPasswordResetLinkRequestResponse::class, ['status' => $status]);
|
||||
}
|
||||
|
||||
return response()->json(['message' => 'Transactional emails are not active'], 400);
|
||||
}
|
||||
|
||||
public function link()
|
||||
{
|
||||
$token = request()->get('token');
|
||||
@ -90,9 +102,11 @@ public function link()
|
||||
}
|
||||
Auth::login($user);
|
||||
session(['currentTeam' => $team]);
|
||||
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('login')->with('error', 'Invalid credentials.');
|
||||
}
|
||||
|
||||
@ -108,11 +122,12 @@ public function accept_invitation()
|
||||
if ($resetPassword) {
|
||||
$user->update([
|
||||
'password' => Hash::make($invitationUuid),
|
||||
'force_password_reset' => true
|
||||
'force_password_reset' => true,
|
||||
]);
|
||||
}
|
||||
if ($user->teams()->where('team_id', $invitation->team->id)->exists()) {
|
||||
$invitation->delete();
|
||||
|
||||
return redirect()->route('team.index');
|
||||
}
|
||||
$user->teams()->attach($invitation->team->id, ['role' => $invitation->role]);
|
||||
@ -121,6 +136,7 @@ public function accept_invitation()
|
||||
return redirect()->route('login');
|
||||
}
|
||||
refreshSession($invitation->team);
|
||||
|
||||
return redirect()->route('team.index');
|
||||
} else {
|
||||
abort(401);
|
||||
@ -143,6 +159,7 @@ public function revoke_invitation()
|
||||
abort(401);
|
||||
}
|
||||
$invitation->delete();
|
||||
|
||||
return redirect()->route('team.index');
|
||||
} catch (\Throwable $e) {
|
||||
throw $e;
|
||||
|
@ -12,21 +12,21 @@ class MagicController extends Controller
|
||||
public function servers()
|
||||
{
|
||||
return response()->json([
|
||||
'servers' => Server::isUsable()->get()
|
||||
'servers' => Server::isUsable()->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function destinations()
|
||||
{
|
||||
return response()->json([
|
||||
'destinations' => Server::destinationsByServer(request()->query('server_id'))->sortBy('name')
|
||||
'destinations' => Server::destinationsByServer(request()->query('server_id'))->sortBy('name'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function projects()
|
||||
{
|
||||
return response()->json([
|
||||
'projects' => Project::ownedByCurrentTeam()->get()
|
||||
'projects' => Project::ownedByCurrentTeam()->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -35,11 +35,12 @@ public function environments()
|
||||
$project = Project::ownedByCurrentTeam()->whereUuid(request()->query('project_uuid'))->first();
|
||||
if (! $project) {
|
||||
return response()->json([
|
||||
'environments' => []
|
||||
'environments' => [],
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'environments' => $project->environments
|
||||
'environments' => $project->environments,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -49,8 +50,9 @@ public function newProject()
|
||||
['name' => request()->query('name') ?? generate_random_name()],
|
||||
['team_id' => currentTeam()->id]
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'project_uuid' => $project->uuid
|
||||
'project_uuid' => $project->uuid,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -60,6 +62,7 @@ public function newEnvironment()
|
||||
['name' => request()->query('name') ?? generate_random_name()],
|
||||
['project_id' => Project::ownedByCurrentTeam()->whereUuid(request()->query('project_uuid'))->firstOrFail()->id]
|
||||
);
|
||||
|
||||
return response()->json([
|
||||
'environment_name' => $environment->name,
|
||||
]);
|
||||
@ -75,6 +78,7 @@ public function newTeam()
|
||||
);
|
||||
auth()->user()->teams()->attach($team, ['role' => 'admin']);
|
||||
refreshSession();
|
||||
|
||||
return redirect(request()->header('Referer'));
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,15 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class OauthController extends Controller {
|
||||
class OauthController extends Controller
|
||||
{
|
||||
public function redirect(string $provider)
|
||||
{
|
||||
$socialite_provider = get_socialite_provider($provider);
|
||||
|
||||
return $socialite_provider->redirect();
|
||||
}
|
||||
|
||||
@ -26,9 +26,11 @@ public function callback(string $provider)
|
||||
]);
|
||||
}
|
||||
Auth::login($user);
|
||||
|
||||
return redirect('/');
|
||||
} catch (\Exception $e) {
|
||||
ray($e->getMessage());
|
||||
|
||||
return redirect()->route('login')->withErrors([__('auth.failed.callback')]);
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,11 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pion\Laravel\ChunkUpload\Exceptions\UploadFailedException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException;
|
||||
use Pion\Laravel\ChunkUpload\Handler\AbstractHandler;
|
||||
use Pion\Laravel\ChunkUpload\Handler\HandlerFactory;
|
||||
use Pion\Laravel\ChunkUpload\Receiver\FileReceiver;
|
||||
|
||||
@ -21,7 +18,7 @@ public function upload(Request $request)
|
||||
if (is_null($resource)) {
|
||||
return response()->json(['error' => 'You do not have permission for this database'], 500);
|
||||
}
|
||||
$receiver = new FileReceiver("file", $request, HandlerFactory::classFromRequest($request));
|
||||
$receiver = new FileReceiver('file', $request, HandlerFactory::classFromRequest($request));
|
||||
|
||||
if ($receiver->isUploaded() === false) {
|
||||
throw new UploadMissingFileException();
|
||||
@ -34,9 +31,10 @@ public function upload(Request $request)
|
||||
}
|
||||
|
||||
$handler = $save->handler();
|
||||
|
||||
return response()->json([
|
||||
"done" => $handler->getPercentageDone(),
|
||||
'status' => true
|
||||
'done' => $handler->getPercentageDone(),
|
||||
'status' => true,
|
||||
]);
|
||||
}
|
||||
// protected function saveFileToS3($file)
|
||||
@ -64,19 +62,20 @@ protected function saveFile(UploadedFile $file, $resource)
|
||||
{
|
||||
$mime = str_replace('/', '-', $file->getMimeType());
|
||||
$filePath = "upload/{$resource->uuid}";
|
||||
$finalPath = storage_path("app/" . $filePath);
|
||||
$finalPath = storage_path('app/'.$filePath);
|
||||
$file->move($finalPath, 'restore');
|
||||
|
||||
return response()->json([
|
||||
'mime_type' => $mime
|
||||
'mime_type' => $mime,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function createFilename(UploadedFile $file)
|
||||
{
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$filename = str_replace("." . $extension, "", $file->getClientOriginalName()); // Filename without extension
|
||||
$filename = str_replace('.'.$extension, '', $file->getClientOriginalName()); // Filename without extension
|
||||
|
||||
$filename .= "_" . md5(time()) . "." . $extension;
|
||||
$filename .= '_'.md5(time()).'.'.$extension;
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
@ -30,13 +30,14 @@ public function manual(Request $request)
|
||||
];
|
||||
$json = json_encode($data);
|
||||
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Bitbicket::manual_bitbucket", $json);
|
||||
|
||||
return;
|
||||
}
|
||||
$return_payloads = collect([]);
|
||||
$payload = $request->collect();
|
||||
$headers = $request->headers->all();
|
||||
$x_bitbucket_token = data_get($headers, 'x-hub-signature.0', "");
|
||||
$x_bitbucket_event = data_get($headers, 'x-event-key.0', "");
|
||||
$x_bitbucket_token = data_get($headers, 'x-hub-signature.0', '');
|
||||
$x_bitbucket_event = data_get($headers, 'x-event-key.0', '');
|
||||
$handled_events = collect(['repo:push', 'pullrequest:created', 'pullrequest:rejected', 'pullrequest:fulfilled']);
|
||||
if (! $handled_events->contains($x_bitbucket_event)) {
|
||||
return response([
|
||||
@ -76,7 +77,7 @@ public function manual(Request $request)
|
||||
$webhook_secret = data_get($application, 'manual_webhook_secret_bitbucket');
|
||||
$payload = $request->getContent();
|
||||
|
||||
list($algo, $hash) = explode('=', $x_bitbucket_token, 2);
|
||||
[$algo, $hash] = explode('=', $x_bitbucket_token, 2);
|
||||
$payloadHash = hash_hmac($algo, $payload, $webhook_secret);
|
||||
if (! hash_equals($hash, $payloadHash) && ! isDev()) {
|
||||
$return_payloads->push([
|
||||
@ -85,6 +86,7 @@ public function manual(Request $request)
|
||||
'message' => 'Invalid signature.',
|
||||
]);
|
||||
ray('Invalid signature');
|
||||
|
||||
continue;
|
||||
}
|
||||
$isFunctional = $application->destination->server->isFunctional();
|
||||
@ -95,6 +97,7 @@ public function manual(Request $request)
|
||||
'message' => 'Server is not functional.',
|
||||
]);
|
||||
ray('Server is not functional: '.$application->destination->server->name);
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($x_bitbucket_event === 'repo:push') {
|
||||
@ -178,9 +181,11 @@ public function manual(Request $request)
|
||||
}
|
||||
}
|
||||
ray($return_payloads);
|
||||
|
||||
return response($return_payloads);
|
||||
} catch (Exception $e) {
|
||||
ray($e);
|
||||
|
||||
return handleError($e);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ public function manual(Request $request)
|
||||
})->first();
|
||||
if ($gitea_delivery_found) {
|
||||
ray('Webhook already found');
|
||||
|
||||
return;
|
||||
}
|
||||
$data = [
|
||||
@ -41,6 +42,7 @@ public function manual(Request $request)
|
||||
];
|
||||
$json = json_encode($data);
|
||||
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Gitea::manual_{$x_gitea_delivery}", $json);
|
||||
|
||||
return;
|
||||
}
|
||||
$x_gitea_event = Str::lower($request->header('X-Gitea-Event'));
|
||||
@ -103,6 +105,7 @@ public function manual(Request $request)
|
||||
'status' => 'failed',
|
||||
'message' => 'Invalid signature.',
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
$isFunctional = $application->destination->server->isFunctional();
|
||||
@ -112,6 +115,7 @@ public function manual(Request $request)
|
||||
'status' => 'failed',
|
||||
'message' => 'Server is not functional.',
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($x_gitea_event === 'push') {
|
||||
@ -213,9 +217,11 @@ public function manual(Request $request)
|
||||
}
|
||||
}
|
||||
ray($return_payloads);
|
||||
|
||||
return response($return_payloads);
|
||||
} catch (Exception $e) {
|
||||
ray($e->getMessage());
|
||||
|
||||
return handleError($e);
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ public function manual(Request $request)
|
||||
})->first();
|
||||
if ($github_delivery_found) {
|
||||
ray('Webhook already found');
|
||||
|
||||
return;
|
||||
}
|
||||
$data = [
|
||||
@ -47,6 +48,7 @@ public function manual(Request $request)
|
||||
];
|
||||
$json = json_encode($data);
|
||||
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::manual_{$x_github_delivery}", $json);
|
||||
|
||||
return;
|
||||
}
|
||||
$x_github_event = Str::lower($request->header('X-GitHub-Event'));
|
||||
@ -108,6 +110,7 @@ public function manual(Request $request)
|
||||
'status' => 'failed',
|
||||
'message' => 'Invalid signature.',
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
$isFunctional = $application->destination->server->isFunctional();
|
||||
@ -117,6 +120,7 @@ public function manual(Request $request)
|
||||
'status' => 'failed',
|
||||
'message' => 'Server is not functional.',
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($x_github_event === 'push') {
|
||||
@ -218,12 +222,15 @@ public function manual(Request $request)
|
||||
}
|
||||
}
|
||||
ray($return_payloads);
|
||||
|
||||
return response($return_payloads);
|
||||
} catch (Exception $e) {
|
||||
ray($e->getMessage());
|
||||
|
||||
return handleError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function normal(Request $request)
|
||||
{
|
||||
try {
|
||||
@ -239,6 +246,7 @@ public function normal(Request $request)
|
||||
})->first();
|
||||
if ($github_delivery_found) {
|
||||
ray('Webhook already found');
|
||||
|
||||
return;
|
||||
}
|
||||
$data = [
|
||||
@ -253,6 +261,7 @@ public function normal(Request $request)
|
||||
];
|
||||
$json = json_encode($data);
|
||||
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::normal_{$x_github_delivery}", $json);
|
||||
|
||||
return;
|
||||
}
|
||||
$x_github_event = Str::lower($request->header('X-GitHub-Event'));
|
||||
@ -280,6 +289,7 @@ public function normal(Request $request)
|
||||
if ($action === 'new_permissions_accepted') {
|
||||
GithubAppPermissionJob::dispatch($github_app);
|
||||
}
|
||||
|
||||
return response('cool');
|
||||
}
|
||||
if ($x_github_event === 'push') {
|
||||
@ -329,6 +339,7 @@ public function normal(Request $request)
|
||||
'application_uuid' => $application->uuid,
|
||||
'application_name' => $application->name,
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($x_github_event === 'push') {
|
||||
@ -431,12 +442,15 @@ public function normal(Request $request)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response($return_payloads);
|
||||
} catch (Exception $e) {
|
||||
ray($e->getMessage());
|
||||
|
||||
return handleError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function redirect(Request $request)
|
||||
{
|
||||
try {
|
||||
@ -464,11 +478,13 @@ public function redirect(Request $request)
|
||||
$github_app->webhook_secret = $webhook_secret;
|
||||
$github_app->private_key_id = $private_key->id;
|
||||
$github_app->save();
|
||||
|
||||
return redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]);
|
||||
} catch (Exception $e) {
|
||||
return handleError($e);
|
||||
}
|
||||
}
|
||||
|
||||
public function install(Request $request)
|
||||
{
|
||||
try {
|
||||
@ -488,6 +504,7 @@ public function install(Request $request)
|
||||
];
|
||||
$json = json_encode($data);
|
||||
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Github::install_{$installation_id}", $json);
|
||||
|
||||
return;
|
||||
}
|
||||
$source = $request->get('source');
|
||||
@ -497,6 +514,7 @@ public function install(Request $request)
|
||||
$github_app->installation_id = $installation_id;
|
||||
$github_app->save();
|
||||
}
|
||||
|
||||
return redirect()->route('source.github.show', ['github_app_uuid' => $github_app->uuid]);
|
||||
} catch (Exception $e) {
|
||||
return handleError($e);
|
||||
|
@ -31,6 +31,7 @@ public function manual(Request $request)
|
||||
];
|
||||
$json = json_encode($data);
|
||||
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Gitlab::manual_gitlab", $json);
|
||||
|
||||
return;
|
||||
}
|
||||
$return_payloads = collect([]);
|
||||
@ -44,6 +45,7 @@ public function manual(Request $request)
|
||||
'status' => 'failed',
|
||||
'message' => 'Event not allowed. Only push and merge_request events are allowed.',
|
||||
]);
|
||||
|
||||
return response($return_payloads);
|
||||
}
|
||||
|
||||
@ -58,6 +60,7 @@ public function manual(Request $request)
|
||||
'status' => 'failed',
|
||||
'message' => 'Nothing to do. No branch found in the request.',
|
||||
]);
|
||||
|
||||
return response($return_payloads);
|
||||
}
|
||||
$added_files = data_get($payload, 'commits.*.added');
|
||||
@ -78,6 +81,7 @@ public function manual(Request $request)
|
||||
'status' => 'failed',
|
||||
'message' => 'Nothing to do. No branch found in the request.',
|
||||
]);
|
||||
|
||||
return response($return_payloads);
|
||||
}
|
||||
ray('Webhook GitHub Pull Request Event with branch: '.$branch.' and base branch: '.$base_branch.' and pull request id: '.$pull_request_id);
|
||||
@ -90,6 +94,7 @@ public function manual(Request $request)
|
||||
'status' => 'failed',
|
||||
'message' => "Nothing to do. No applications found with deploy key set, branch is '$branch' and Git Repository name has $full_name.",
|
||||
]);
|
||||
|
||||
return response($return_payloads);
|
||||
}
|
||||
}
|
||||
@ -100,6 +105,7 @@ public function manual(Request $request)
|
||||
'status' => 'failed',
|
||||
'message' => "Nothing to do. No applications found with branch '$base_branch'.",
|
||||
]);
|
||||
|
||||
return response($return_payloads);
|
||||
}
|
||||
}
|
||||
@ -112,6 +118,7 @@ public function manual(Request $request)
|
||||
'message' => 'Invalid signature.',
|
||||
]);
|
||||
ray('Invalid signature');
|
||||
|
||||
continue;
|
||||
}
|
||||
$isFunctional = $application->destination->server->isFunctional();
|
||||
@ -122,6 +129,7 @@ public function manual(Request $request)
|
||||
'message' => 'Server is not functional',
|
||||
]);
|
||||
ray('Server is not functional: '.$application->destination->server->name);
|
||||
|
||||
continue;
|
||||
}
|
||||
if ($x_gitlab_event === 'push') {
|
||||
@ -214,6 +222,7 @@ public function manual(Request $request)
|
||||
'status' => 'success',
|
||||
'message' => 'Preview Deployment closed',
|
||||
]);
|
||||
|
||||
return response($return_payloads);
|
||||
}
|
||||
$return_payloads->push([
|
||||
@ -230,9 +239,11 @@ public function manual(Request $request)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response($return_payloads);
|
||||
} catch (Exception $e) {
|
||||
ray($e->getMessage());
|
||||
|
||||
return handleError($e);
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ public function events(Request $request)
|
||||
];
|
||||
$json = json_encode($data);
|
||||
Storage::disk('webhooks-during-maintenance')->put("{$epoch}_Stripe::events_stripe", $json);
|
||||
|
||||
return;
|
||||
}
|
||||
$webhookSecret = config('subscription.stripe_webhook_secret');
|
||||
@ -48,7 +49,7 @@ public function events(Request $request)
|
||||
);
|
||||
$webhook = Webhook::create([
|
||||
'type' => 'stripe',
|
||||
'payload' => $request->getContent()
|
||||
'payload' => $request->getContent(),
|
||||
]);
|
||||
$type = data_get($event, 'type');
|
||||
$data = data_get($event, 'data.object');
|
||||
@ -108,11 +109,13 @@ public function events(Request $request)
|
||||
$subscription = Subscription::where('stripe_customer_id', $customerId)->first();
|
||||
if (! $subscription) {
|
||||
send_internal_notification('invoice.payment_failed failed but no subscription found in Coolify for customer: '.$customerId);
|
||||
|
||||
return response('No subscription found in Coolify.');
|
||||
}
|
||||
$team = data_get($subscription, 'team');
|
||||
if (! $team) {
|
||||
send_internal_notification('invoice.payment_failed failed but no team found in Coolify for customer: '.$customerId);
|
||||
|
||||
return response('No team found in Coolify.');
|
||||
}
|
||||
if (! $subscription->stripe_invoice_paid) {
|
||||
@ -127,10 +130,12 @@ public function events(Request $request)
|
||||
$subscription = Subscription::where('stripe_customer_id', $customerId)->first();
|
||||
if (! $subscription) {
|
||||
send_internal_notification('payment_intent.payment_failed, no subscription found in Coolify for customer: '.$customerId);
|
||||
|
||||
return response('No subscription found in Coolify.');
|
||||
}
|
||||
if ($subscription->stripe_invoice_paid) {
|
||||
send_internal_notification('payment_intent.payment_failed but invoice is active for customer: '.$customerId);
|
||||
|
||||
return;
|
||||
}
|
||||
send_internal_notification('Subscription payment failed for customer: '.$customerId);
|
||||
@ -152,10 +157,12 @@ public function events(Request $request)
|
||||
if (! $subscription) {
|
||||
if ($status === 'incomplete_expired') {
|
||||
send_internal_notification('Subscription incomplete expired for customer: '.$customerId);
|
||||
return response("Subscription incomplete expired", 200);
|
||||
|
||||
return response('Subscription incomplete expired', 200);
|
||||
}
|
||||
send_internal_notification('No subscription found for: '.$customerId);
|
||||
return response("No subscription found", 400);
|
||||
|
||||
return response('No subscription found', 400);
|
||||
}
|
||||
$trialEndedAlready = data_get($subscription, 'stripe_trial_already_ended');
|
||||
$cancelAtPeriodEnd = data_get($data, 'cancel_at_period_end');
|
||||
@ -264,6 +271,7 @@ public function events(Request $request)
|
||||
'status' => 'failed',
|
||||
'failure_reason' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return response($e->getMessage(), 400);
|
||||
}
|
||||
}
|
||||
|
@ -22,21 +22,26 @@ public function confirm(Request $request)
|
||||
$found->verified = true;
|
||||
$found->save();
|
||||
send_internal_notification('Waitlist confirmed: '.$email);
|
||||
|
||||
return 'Thank you for confirming your email address. We will notify you when you are next in line.';
|
||||
} else {
|
||||
$found->delete();
|
||||
send_internal_notification('Waitlist expired: '.$email);
|
||||
|
||||
return 'Your confirmation code has expired. Please sign up again.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('dashboard');
|
||||
} catch (Exception $e) {
|
||||
send_internal_notification('Waitlist confirmation failed: '.$e->getMessage());
|
||||
ray($e->getMessage());
|
||||
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
}
|
||||
|
||||
public function cancel(Request $request)
|
||||
{
|
||||
$email = request()->get('email');
|
||||
@ -46,12 +51,15 @@ public function cancel(Request $request)
|
||||
if ($found && ! $found->verified) {
|
||||
$found->delete();
|
||||
send_internal_notification('Waitlist cancelled: '.$email);
|
||||
|
||||
return 'Your email address has been removed from the waitlist.';
|
||||
}
|
||||
|
||||
return redirect()->route('dashboard');
|
||||
} catch (Exception $e) {
|
||||
send_internal_notification('Waitlist cancellation failed: '.$e->getMessage());
|
||||
ray($e->getMessage());
|
||||
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ public function handle(Request $request, Closure $next): Response
|
||||
auth()->logout();
|
||||
request()->session()->invalidate();
|
||||
request()->session()->regenerateToken();
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
$force_password_reset = auth()->user()->force_password_reset;
|
||||
@ -27,9 +28,11 @@ public function handle(Request $request, Closure $next): Response
|
||||
if ($request->routeIs('auth.force-password-reset') || $request->path() === 'force-password-reset' || $request->path() === 'livewire/update' || $request->path() === 'logout') {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return redirect()->route('auth.force-password-reset');
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class DecideWhatToDoWithUser
|
||||
{
|
||||
@ -23,12 +23,14 @@ public function handle(Request $request, Closure $next): Response
|
||||
if (! isCloud() && showBoarding() && ! in_array($request->path(), allowedPathsForBoardingAccounts())) {
|
||||
return redirect()->route('onboarding');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
if (! auth()->user()->hasVerifiedEmail()) {
|
||||
if ($request->path() === 'verify' || in_array($request->path(), allowedPathsForInvalidAccounts()) || $request->routeIs('verify.verify')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return redirect()->route('verify.email');
|
||||
}
|
||||
if (! isSubscriptionActive() && ! isSubscriptionOnGracePeriod()) {
|
||||
@ -36,6 +38,7 @@ public function handle(Request $request, Closure $next): Response
|
||||
if (Str::startsWith($request->path(), 'invitations')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return redirect()->route('subscription.index');
|
||||
}
|
||||
}
|
||||
@ -43,6 +46,7 @@ public function handle(Request $request, Closure $next): Response
|
||||
if (Str::startsWith($request->path(), 'invitations')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return redirect()->route('onboarding');
|
||||
}
|
||||
if (auth()->user()->hasVerifiedEmail() && $request->path() === 'verify') {
|
||||
@ -51,6 +55,7 @@ public function handle(Request $request, Closure $next): Response
|
||||
if (isSubscriptionActive() && $request->routeIs('subscription.index')) {
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,6 @@ class PreventRequestsDuringMaintenance extends Middleware
|
||||
*/
|
||||
protected $except = [
|
||||
'webhooks/*',
|
||||
'/api/health'
|
||||
'/api/health',
|
||||
];
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ public function handle(Request $request, Closure $next, string ...$guards): Resp
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,11 +12,12 @@
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ApplicationPullRequestUpdateJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class ApplicationPullRequestUpdateJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public string $build_logs_url;
|
||||
|
||||
public string $body;
|
||||
|
||||
public function __construct(
|
||||
@ -32,10 +33,12 @@ public function handle()
|
||||
try {
|
||||
if ($this->application->is_public_repository()) {
|
||||
ray('Public repository. Skipping comment update.');
|
||||
|
||||
return;
|
||||
}
|
||||
if ($this->status === ProcessStatus::CLOSED) {
|
||||
$this->delete_comment();
|
||||
|
||||
return;
|
||||
} elseif ($this->status === ProcessStatus::IN_PROGRESS) {
|
||||
$this->body = "The preview deployment is in progress. 🟡\n\n";
|
||||
@ -49,8 +52,8 @@ public function handle()
|
||||
}
|
||||
$this->build_logs_url = base_url()."/project/{$this->application->environment->project->uuid}/{$this->application->environment->name}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
|
||||
|
||||
$this->body .= "[Open Build Logs](" . $this->build_logs_url . ")\n\n\n";
|
||||
$this->body .= "Last updated at: " . now()->toDateTimeString() . " CET";
|
||||
$this->body .= '[Open Build Logs]('.$this->build_logs_url.")\n\n\n";
|
||||
$this->body .= 'Last updated at: '.now()->toDateTimeString().' CET';
|
||||
|
||||
ray('Updating comment', $this->body);
|
||||
if ($this->preview->pull_request_issue_comment_id) {
|
||||
@ -60,6 +63,7 @@ public function handle()
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
ray($e);
|
||||
|
||||
return $e;
|
||||
}
|
||||
}
|
||||
@ -83,6 +87,7 @@ private function create_comment()
|
||||
$this->preview->pull_request_issue_comment_id = $data['id'];
|
||||
$this->preview->save();
|
||||
}
|
||||
|
||||
private function delete_comment()
|
||||
{
|
||||
githubApi(source: $this->application->source, endpoint: "/repos/{$this->application->git_repository}/issues/comments/{$this->preview->pull_request_issue_comment_id}", method: 'delete');
|
||||
|
@ -10,19 +10,23 @@
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
|
||||
class ApplicationRestartJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class ApplicationRestartJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, ExecuteRemoteCommand;
|
||||
use Dispatchable, ExecuteRemoteCommand, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $timeout = 3600;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public string $applicationDeploymentQueueId;
|
||||
|
||||
public function __construct(string $applicationDeploymentQueueId)
|
||||
{
|
||||
$this->applicationDeploymentQueueId = $applicationDeploymentQueueId;
|
||||
}
|
||||
public function handle() {
|
||||
|
||||
public function handle()
|
||||
{
|
||||
ray('Restarting application');
|
||||
}
|
||||
}
|
||||
|
@ -15,13 +15,14 @@
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Sleep;
|
||||
|
||||
class CheckLogDrainContainerJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class CheckLogDrainContainerJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public function __construct(public Server $server)
|
||||
{
|
||||
}
|
||||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping($this->server->id))->dontRelease()];
|
||||
@ -31,6 +32,7 @@ public function uniqueId(): int
|
||||
{
|
||||
return $this->server->id;
|
||||
}
|
||||
|
||||
public function healthcheck()
|
||||
{
|
||||
$status = instant_remote_process(["docker inspect --format='{{json .State.Status}}' coolify-log-drain"], $this->server, false);
|
||||
@ -40,14 +42,15 @@ public function healthcheck()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
// ray("checking log drain statuses for {$this->server->id}");
|
||||
try {
|
||||
if (! $this->server->isFunctional()) {
|
||||
return;
|
||||
};
|
||||
$containers = instant_remote_process(["docker container ls -q"], $this->server, false);
|
||||
}
|
||||
$containers = instant_remote_process(['docker container ls -q'], $this->server, false);
|
||||
if (! $containers) {
|
||||
return;
|
||||
}
|
||||
@ -66,6 +69,7 @@ public function handle()
|
||||
$this->server->team?->notify(new ContainerRestarted('Coolify Log Drainer', $this->server));
|
||||
$this->server->update(['log_drain_notification_sent' => false]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (! $this->server->log_drain_notification_sent) {
|
||||
@ -80,8 +84,11 @@ public function handle()
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
if (!isCloud()) send_internal_notification("CheckLogDrainContainerJob failed on ({$this->server->id}) with: " . $e->getMessage());
|
||||
if (! isCloud()) {
|
||||
send_internal_notification("CheckLogDrainContainerJob failed on ({$this->server->id}) with: ".$e->getMessage());
|
||||
}
|
||||
ray($e->getMessage());
|
||||
|
||||
return handleError($e);
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CheckResaleLicenseJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class CheckResaleLicenseJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CleanupHelperContainersJob implements ShouldQueue, ShouldBeUnique, ShouldBeEncrypted
|
||||
class CleanupHelperContainersJob implements ShouldBeEncrypted, ShouldBeUnique, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CleanupInstanceStuffsJob implements ShouldQueue, ShouldBeUnique, ShouldBeEncrypted
|
||||
class CleanupInstanceStuffsJob implements ShouldBeEncrypted, ShouldBeUnique, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
@ -49,6 +49,7 @@ private function cleanup_waitlist()
|
||||
$item->delete();
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanup_invitation_link()
|
||||
{
|
||||
$invitation = TeamInvitation::all();
|
||||
|
@ -12,18 +12,21 @@
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class ContainerStatusJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $tries = 4;
|
||||
|
||||
public function backoff(): int
|
||||
{
|
||||
return isDev() ? 1 : 3;
|
||||
}
|
||||
|
||||
public function __construct(public Server $server)
|
||||
{
|
||||
}
|
||||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping($this->server->uuid))];
|
||||
|
@ -11,7 +11,7 @@
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
|
||||
class CoolifyTask implements ShouldQueue, ShouldBeEncrypted
|
||||
class CoolifyTask implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
@ -35,7 +35,7 @@ public function handle(): void
|
||||
'activity' => $this->activity,
|
||||
'ignore_errors' => $this->ignore_errors,
|
||||
'call_event_on_finish' => $this->call_event_on_finish,
|
||||
'call_event_data' => $this->call_event_data
|
||||
'call_event_data' => $this->call_event_data,
|
||||
]);
|
||||
|
||||
$remote_process();
|
||||
|
@ -25,26 +25,37 @@
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Str;
|
||||
use Throwable;
|
||||
|
||||
class DatabaseBackupJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public ?Team $team = null;
|
||||
|
||||
public Server $server;
|
||||
|
||||
public ScheduledDatabaseBackup $backup;
|
||||
|
||||
public StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|ServiceDatabase $database;
|
||||
|
||||
public ?string $container_name = null;
|
||||
|
||||
public ?string $directory_name = null;
|
||||
|
||||
public ?ScheduledDatabaseBackupExecution $backup_log = null;
|
||||
|
||||
public string $backup_status = 'failed';
|
||||
|
||||
public ?string $backup_location = null;
|
||||
|
||||
public string $backup_dir;
|
||||
|
||||
public string $backup_file;
|
||||
|
||||
public int $size = 0;
|
||||
|
||||
public ?string $backup_output = null;
|
||||
|
||||
public ?S3Storage $s3 = null;
|
||||
|
||||
public function __construct($backup)
|
||||
@ -84,11 +95,13 @@ public function handle(): void
|
||||
$this->backup->update(['status' => 'failed']);
|
||||
StopDatabase::run($this->database);
|
||||
$this->database->delete();
|
||||
|
||||
return;
|
||||
}
|
||||
$status = Str::of(data_get($this->database, 'status'));
|
||||
if (! $status->startsWith('running') && $this->database->id !== 0) {
|
||||
ray('database not running');
|
||||
|
||||
return;
|
||||
}
|
||||
if (data_get($this->backup, 'database_type') === 'App\Models\ServiceDatabase') {
|
||||
@ -223,20 +236,20 @@ public function handle(): void
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->backup_dir = backup_dir() . "/databases/" . Str::of($this->team->name)->slug() . '-' . $this->team->id . '/' . $this->directory_name;
|
||||
$this->backup_dir = backup_dir().'/databases/'.Str::of($this->team->name)->slug().'-'.$this->team->id.'/'.$this->directory_name;
|
||||
|
||||
if ($this->database->name === 'coolify-db') {
|
||||
$databasesToBackup = ['coolify'];
|
||||
$this->directory_name = $this->container_name = "coolify-db";
|
||||
$this->directory_name = $this->container_name = 'coolify-db';
|
||||
$ip = Str::slug($this->server->ip);
|
||||
$this->backup_dir = backup_dir() . "/coolify" . "/coolify-db-$ip";
|
||||
$this->backup_dir = backup_dir().'/coolify'."/coolify-db-$ip";
|
||||
}
|
||||
foreach ($databasesToBackup as $database) {
|
||||
$size = 0;
|
||||
ray('Backing up '.$database);
|
||||
try {
|
||||
if (str($databaseType)->contains('postgres')) {
|
||||
$this->backup_file = "/pg-dump-$database-" . Carbon::now()->timestamp . ".dmp";
|
||||
$this->backup_file = "/pg-dump-$database-".Carbon::now()->timestamp.'.dmp';
|
||||
$this->backup_location = $this->backup_dir.$this->backup_file;
|
||||
$this->backup_log = ScheduledDatabaseBackupExecution::create([
|
||||
'database_name' => $database,
|
||||
@ -255,7 +268,7 @@ public function handle(): void
|
||||
$databaseName = $database;
|
||||
}
|
||||
}
|
||||
$this->backup_file = "/mongo-dump-$databaseName-" . Carbon::now()->timestamp . ".tar.gz";
|
||||
$this->backup_file = "/mongo-dump-$databaseName-".Carbon::now()->timestamp.'.tar.gz';
|
||||
$this->backup_location = $this->backup_dir.$this->backup_file;
|
||||
$this->backup_log = ScheduledDatabaseBackupExecution::create([
|
||||
'database_name' => $databaseName,
|
||||
@ -264,7 +277,7 @@ public function handle(): void
|
||||
]);
|
||||
$this->backup_standalone_mongodb($database);
|
||||
} elseif (str($databaseType)->contains('mysql')) {
|
||||
$this->backup_file = "/mysql-dump-$database-" . Carbon::now()->timestamp . ".dmp";
|
||||
$this->backup_file = "/mysql-dump-$database-".Carbon::now()->timestamp.'.dmp';
|
||||
$this->backup_location = $this->backup_dir.$this->backup_file;
|
||||
$this->backup_log = ScheduledDatabaseBackupExecution::create([
|
||||
'database_name' => $database,
|
||||
@ -273,7 +286,7 @@ public function handle(): void
|
||||
]);
|
||||
$this->backup_standalone_mysql($database);
|
||||
} elseif (str($databaseType)->contains('mariadb')) {
|
||||
$this->backup_file = "/mariadb-dump-$database-" . Carbon::now()->timestamp . ".dmp";
|
||||
$this->backup_file = "/mariadb-dump-$database-".Carbon::now()->timestamp.'.dmp';
|
||||
$this->backup_location = $this->backup_dir.$this->backup_file;
|
||||
$this->backup_log = ScheduledDatabaseBackupExecution::create([
|
||||
'database_name' => $database,
|
||||
@ -301,7 +314,7 @@ public function handle(): void
|
||||
'status' => 'failed',
|
||||
'message' => $this->backup_output,
|
||||
'size' => $size,
|
||||
'filename' => null
|
||||
'filename' => null,
|
||||
]);
|
||||
}
|
||||
send_internal_notification('DatabaseBackupJob failed with: '.$e->getMessage());
|
||||
@ -315,13 +328,14 @@ public function handle(): void
|
||||
BackupCreated::dispatch($this->team->id);
|
||||
}
|
||||
}
|
||||
|
||||
private function backup_standalone_mongodb(string $databaseWithCollections): void
|
||||
{
|
||||
try {
|
||||
ray($this->database->toArray());
|
||||
$url = $this->database->get_db_url(useInternal: true);
|
||||
if ($databaseWithCollections === 'all') {
|
||||
$commands[] = "mkdir -p " . $this->backup_dir;
|
||||
$commands[] = 'mkdir -p '.$this->backup_dir;
|
||||
if (str($this->database->image)->startsWith('mongo:4.0')) {
|
||||
$commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --archive > $this->backup_location";
|
||||
} else {
|
||||
@ -335,7 +349,7 @@ private function backup_standalone_mongodb(string $databaseWithCollections): voi
|
||||
$databaseName = $databaseWithCollections;
|
||||
$collectionsToExclude = collect();
|
||||
}
|
||||
$commands[] = "mkdir -p " . $this->backup_dir;
|
||||
$commands[] = 'mkdir -p '.$this->backup_dir;
|
||||
if ($collectionsToExclude->count() === 0) {
|
||||
if (str($this->database->image)->startsWith('mongo:4.0')) {
|
||||
$commands[] = "docker exec $this->container_name mongodump --uri=$url --gzip --archive > $this->backup_location";
|
||||
@ -362,10 +376,11 @@ private function backup_standalone_mongodb(string $databaseWithCollections): voi
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function backup_standalone_postgresql(string $database): void
|
||||
{
|
||||
try {
|
||||
$commands[] = "mkdir -p " . $this->backup_dir;
|
||||
$commands[] = 'mkdir -p '.$this->backup_dir;
|
||||
$commands[] = "docker exec $this->container_name pg_dump --format=custom --no-acl --no-owner --username {$this->database->postgres_user} $database > $this->backup_location";
|
||||
$this->backup_output = instant_remote_process($commands, $this->server);
|
||||
$this->backup_output = trim($this->backup_output);
|
||||
@ -379,10 +394,11 @@ private function backup_standalone_postgresql(string $database): void
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function backup_standalone_mysql(string $database): void
|
||||
{
|
||||
try {
|
||||
$commands[] = "mkdir -p " . $this->backup_dir;
|
||||
$commands[] = 'mkdir -p '.$this->backup_dir;
|
||||
$commands[] = "docker exec $this->container_name mysqldump -u root -p{$this->database->mysql_root_password} $database > $this->backup_location";
|
||||
ray($commands);
|
||||
$this->backup_output = instant_remote_process($commands, $this->server);
|
||||
@ -397,10 +413,11 @@ private function backup_standalone_mysql(string $database): void
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function backup_standalone_mariadb(string $database): void
|
||||
{
|
||||
try {
|
||||
$commands[] = "mkdir -p " . $this->backup_dir;
|
||||
$commands[] = 'mkdir -p '.$this->backup_dir;
|
||||
$commands[] = "docker exec $this->container_name mariadb-dump -u root -p{$this->database->mariadb_root_password} $database > $this->backup_location";
|
||||
ray($commands);
|
||||
$this->backup_output = instant_remote_process($commands, $this->server);
|
||||
@ -415,6 +432,7 @@ private function backup_standalone_mariadb(string $database): void
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function add_to_backup_output($output): void
|
||||
{
|
||||
if ($this->backup_output) {
|
||||
|
@ -3,19 +3,16 @@
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use App\Models\Server;
|
||||
use App\Models\Team;
|
||||
use App\Notifications\Database\DailyBackup;
|
||||
use App\Notifications\Server\HighDiskUsage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class DatabaseBackupStatusJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class DatabaseBackupStatusJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
@ -42,13 +39,6 @@ public function handle()
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// $scheduled_backups = ScheduledDatabaseBackup::all();
|
||||
// $databases = collect();
|
||||
// $teams = collect();
|
||||
|
@ -24,7 +24,7 @@
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
class DeleteResourceJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
|
@ -10,21 +10,22 @@
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use RuntimeException;
|
||||
|
||||
class DockerCleanupJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $timeout = 300;
|
||||
|
||||
public ?int $usageBefore = null;
|
||||
|
||||
public function __construct(public Server $server)
|
||||
{
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
@ -32,6 +33,7 @@ public function handle(): void
|
||||
$this->server->applications()->each(function ($application) use (&$isInprogress) {
|
||||
if ($application->isDeploymentInprogress()) {
|
||||
$isInprogress = true;
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
@ -12,18 +12,21 @@
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class GithubAppPermissionJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class GithubAppPermissionJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $tries = 4;
|
||||
|
||||
public function backoff(): int
|
||||
{
|
||||
return isDev() ? 1 : 3;
|
||||
}
|
||||
|
||||
public function __construct(public GithubApp $github_app)
|
||||
{
|
||||
}
|
||||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping($this->github_app->uuid))];
|
||||
@ -40,7 +43,7 @@ public function handle()
|
||||
$github_access_token = generate_github_jwt_token($this->github_app);
|
||||
$response = Http::withHeaders([
|
||||
'Authorization' => "Bearer $github_access_token",
|
||||
'Accept' => 'application/vnd.github+json'
|
||||
'Accept' => 'application/vnd.github+json',
|
||||
])->get("{$this->github_app->api_url}/app");
|
||||
$response = $response->json();
|
||||
$permissions = data_get($response, 'permissions');
|
||||
|
@ -11,11 +11,12 @@
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class InstanceAutoUpdateJob implements ShouldQueue, ShouldBeUnique, ShouldBeEncrypted
|
||||
class InstanceAutoUpdateJob implements ShouldBeEncrypted, ShouldBeUnique, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $timeout = 600;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public function __construct()
|
||||
|
@ -13,7 +13,7 @@
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class PullCoolifyImageJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class PullCoolifyImageJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
@ -22,6 +22,7 @@ class PullCoolifyImageJob implements ShouldQueue, ShouldBeEncrypted
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
@ -49,8 +50,8 @@ public function handle(): void
|
||||
return;
|
||||
}
|
||||
instant_remote_process([
|
||||
"curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh -o /data/coolify/source/upgrade.sh",
|
||||
"bash /data/coolify/source/upgrade.sh $latest_version"
|
||||
'curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh -o /data/coolify/source/upgrade.sh',
|
||||
"bash /data/coolify/source/upgrade.sh $latest_version",
|
||||
], $server);
|
||||
} catch (\Throwable $e) {
|
||||
throw $e;
|
||||
|
@ -11,7 +11,7 @@
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class PullHelperImageJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class PullHelperImageJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
@ -26,9 +26,11 @@ public function uniqueId(): string
|
||||
{
|
||||
return $this->server->uuid;
|
||||
}
|
||||
|
||||
public function __construct(public Server $server)
|
||||
{
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
|
@ -12,7 +12,7 @@
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class PullSentinelImageJob implements ShouldQueue, ShouldBeEncrypted
|
||||
class PullSentinelImageJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
@ -27,15 +27,18 @@ public function uniqueId(): string
|
||||
{
|
||||
return $this->server->uuid;
|
||||
}
|
||||
|
||||
public function __construct(public Server $server)
|
||||
{
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
$version = get_latest_sentinel_version();
|
||||
if (! $version) {
|
||||
ray('Failed to get latest Sentinel version');
|
||||
|
||||
return;
|
||||
}
|
||||
$local_version = instant_remote_process(['docker exec coolify-sentinel sh -c "curl http://127.0.0.1:8888/api/version"'], $this->server, false);
|
||||
@ -44,6 +47,7 @@ public function handle(): void
|
||||
}
|
||||
if (version_compare($local_version, $version, '<')) {
|
||||
StartSentinel::run($this->server, $version, true);
|
||||
|
||||
return;
|
||||
}
|
||||
ray('Sentinel image is up to date');
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
@ -12,7 +11,7 @@
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class PullTemplatesFromCDN implements ShouldQueue, ShouldBeEncrypted
|
||||
class PullTemplatesFromCDN implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
@ -21,6 +20,7 @@ class PullTemplatesFromCDN implements ShouldQueue, ShouldBeEncrypted
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
|
@ -11,7 +11,7 @@
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class PullVersionsFromCDN implements ShouldQueue, ShouldBeEncrypted
|
||||
class PullVersionsFromCDN implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
@ -20,6 +20,7 @@ class PullVersionsFromCDN implements ShouldQueue, ShouldBeEncrypted
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
|
@ -2,10 +2,10 @@
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\ScheduledTask;
|
||||
use App\Models\ScheduledTaskExecution;
|
||||
use App\Models\Server;
|
||||
use App\Models\Application;
|
||||
use App\Models\Service;
|
||||
use App\Models\Team;
|
||||
use App\Notifications\ScheduledTask\TaskFailed;
|
||||
@ -21,13 +21,19 @@ class ScheduledTaskJob implements ShouldQueue
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public ?Team $team = null;
|
||||
|
||||
public Server $server;
|
||||
|
||||
public ScheduledTask $task;
|
||||
|
||||
public Application|Service $resource;
|
||||
|
||||
public ?ScheduledTaskExecution $task_log = null;
|
||||
|
||||
public string $task_status = 'failed';
|
||||
|
||||
public ?string $task_output = null;
|
||||
|
||||
public array $containers = [];
|
||||
|
||||
public function __construct($task)
|
||||
@ -69,8 +75,7 @@ public function handle(): void
|
||||
$this->containers[] = str_replace('/', '', $container['Names']);
|
||||
});
|
||||
}
|
||||
}
|
||||
elseif ($this->resource->type() == 'service') {
|
||||
} elseif ($this->resource->type() == 'service') {
|
||||
$this->resource->applications()->get()->each(function ($application) {
|
||||
if (str(data_get($application, 'status'))->contains('running')) {
|
||||
$this->containers[] = data_get($application, 'name').'-'.data_get($this->resource, 'uuid');
|
||||
@ -99,13 +104,13 @@ public function handle(): void
|
||||
'status' => 'success',
|
||||
'message' => $this->task_output,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No valid container was found.
|
||||
throw new \Exception('ScheduledTaskJob failed: No valid container was found. Is the container name correct?');
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
if ($this->task_log) {
|
||||
$this->task_log->update([
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user