Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v4.0.0-beta.285 #2261

Merged
merged 7 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Special thanks to our biggest sponsor, [CCCareers](https://cccareers.org/)!

## 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">
Expand Down
38 changes: 19 additions & 19 deletions app/Actions/Docker/GetContainersStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@
use App\Actions\Proxy\CheckProxy;
use App\Actions\Proxy\StartProxy;
use App\Actions\Shared\ComplexStatusCheck;
use App\Models\Application;
use App\Models\ApplicationPreview;
use App\Models\Server;
use App\Models\ServiceDatabase;
use App\Notifications\Container\ContainerRestarted;
use App\Notifications\Container\ContainerStopped;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Lorisleiva\Actions\Concerns\AsAction;

class GetContainersStatus
Expand All @@ -24,9 +22,9 @@ class GetContainersStatus

public function handle(Server $server)
{
if (isDev()) {
$server = Server::find(0);
}
// if (isDev()) {
// $server = Server::find(0);
// }
$this->server = $server;
if (!$this->server->isFunctional()) {
return 'Server is not ready.';
Expand Down Expand Up @@ -154,7 +152,7 @@ private function sentinel()
if ($isPublic) {
$foundTcpProxy = $containers->filter(function ($value, $key) use ($uuid) {
if ($this->server->isSwarm()) {
// TODO: fix this with sentinel
// TODO: fix this with sentinel
return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
} else {
return data_get($value, 'name') === "$uuid-proxy";
Expand Down Expand Up @@ -316,7 +314,7 @@ private function sentinel()
$this->server->proxyType();
$foundProxyContainer = $containers->filter(function ($value, $key) {
if ($this->server->isSwarm()) {
// TODO: fix this with sentinel
// TODO: fix this with sentinel
return data_get($value, 'Spec.Name') === 'coolify-proxy_traefik';
} else {
return data_get($value, 'name') === 'coolify-proxy';
Expand Down Expand Up @@ -442,19 +440,21 @@ private function old_way()
if ($database_id) {
$service_db = ServiceDatabase::where('id', $database_id)->first();
if ($service_db) {
$uuid = $service_db->service->uuid;
$isPublic = data_get($service_db, 'is_public');
if ($isPublic) {
$foundTcpProxy = $containers->filter(function ($value, $key) use ($uuid) {
if ($this->server->isSwarm()) {
return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
} else {
return data_get($value, 'Name') === "/$uuid-proxy";
$uuid = data_get($service_db, 'service.uuid');
if ($uuid) {
$isPublic = data_get($service_db, 'is_public');
if ($isPublic) {
$foundTcpProxy = $containers->filter(function ($value, $key) use ($uuid) {
if ($this->server->isSwarm()) {
return data_get($value, 'Spec.Name') === "coolify-proxy_$uuid";
} else {
return data_get($value, 'Name') === "/$uuid-proxy";
}
})->first();
if (!$foundTcpProxy) {
StartDatabaseProxy::run($service_db);
// $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$service_db->service->name}", $this->server));
}
})->first();
if (!$foundTcpProxy) {
StartDatabaseProxy::run($service_db);
// $this->server->team?->notify(new ContainerRestarted("TCP Proxy for {$service_db->service->name}", $this->server));
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions app/Jobs/ScheduledTaskJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@
use App\Models\Application;
use App\Models\Service;
use App\Models\Team;
use App\Notifications\ScheduledTask\TaskFailed;
use Illuminate\Bus\Queueable;
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\Collection;
use Throwable;

class ScheduledTaskJob implements ShouldQueue
{
Expand Down Expand Up @@ -114,6 +113,7 @@ public function handle(): void
'message' => $this->task_output ?? $e->getMessage(),
]);
}
$this->team?->notify(new TaskFailed($this->task, $e->getMessage()));
// send_internal_notification('ScheduledTaskJob failed with: ' . $e->getMessage());
throw $e;
}
Expand Down
1 change: 0 additions & 1 deletion app/Jobs/SendMessageToDiscordJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public function handle(): void
$payload = [
'content' => $this->text,
];
ray($payload);
Http::post($this->webhookUrl, $payload);
}
}
3 changes: 3 additions & 0 deletions app/Livewire/Boarding/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ class Index extends Component

public function mount()
{
if (auth()->user()?->isMember() && auth()->user()->currentTeam()->show_boarding === true) {
return redirect()->route('dashboard');
}
$this->privateKeyName = generate_random_name();
$this->remoteServerName = generate_random_name();
if (isDev()) {
Expand Down
1 change: 1 addition & 0 deletions app/Livewire/Notifications/Discord.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Discord extends Component
'team.discord_notifications_deployments' => 'nullable|boolean',
'team.discord_notifications_status_changes' => 'nullable|boolean',
'team.discord_notifications_database_backups' => 'nullable|boolean',
'team.discord_notifications_scheduled_tasks' => 'nullable|boolean',
];
protected $validationAttributes = [
'team.discord_webhook_url' => 'Discord Webhook',
Expand Down
1 change: 1 addition & 0 deletions app/Livewire/Notifications/Email.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Email extends Component
'team.smtp_notifications_deployments' => 'nullable|boolean',
'team.smtp_notifications_status_changes' => 'nullable|boolean',
'team.smtp_notifications_database_backups' => 'nullable|boolean',
'team.smtp_notifications_scheduled_tasks' => 'nullable|boolean',
'team.use_instance_email_settings' => 'boolean',
'team.resend_enabled' => 'nullable|boolean',
'team.resend_api_key' => 'nullable',
Expand Down
2 changes: 2 additions & 0 deletions app/Livewire/Notifications/Telegram.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ class Telegram extends Component
'team.telegram_notifications_deployments' => 'nullable|boolean',
'team.telegram_notifications_status_changes' => 'nullable|boolean',
'team.telegram_notifications_database_backups' => 'nullable|boolean',
'team.telegram_notifications_scheduled_tasks' => 'nullable|boolean',
'team.telegram_notifications_test_message_thread_id' => 'nullable|string',
'team.telegram_notifications_deployments_message_thread_id' => 'nullable|string',
'team.telegram_notifications_status_changes_message_thread_id' => 'nullable|string',
'team.telegram_notifications_database_backups_message_thread_id' => 'nullable|string',
'team.telegram_notifications_scheduled_tasks_thread_id' => 'nullable|string',
];
protected $validationAttributes = [
'team.telegram_token' => 'Token',
Expand Down
10 changes: 9 additions & 1 deletion app/Livewire/Project/Application/General.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class General extends Component
public ?string $initialDockerComposeLocation = null;
public ?string $initialDockerComposePrLocation = null;

public $parsedServices = [];
public null|Collection $parsedServices;
public $parsedServiceDomains = [];

protected $listeners = [
Expand Down Expand Up @@ -118,6 +118,10 @@ public function mount()
{
try {
$this->parsedServices = $this->application->parseCompose();
if (is_null($this->parsedServices) || empty($this->parsedServices)) {
$this->dispatch('error', "Failed to parse your docker-compose file. Please check the syntax and try again.");
return;
}
} catch (\Throwable $e) {
$this->dispatch('error', $e->getMessage());
}
Expand Down Expand Up @@ -160,6 +164,10 @@ public function loadComposeFile($isInit = false)
return;
}
['parsedServices' => $this->parsedServices, 'initialDockerComposeLocation' => $this->initialDockerComposeLocation, 'initialDockerComposePrLocation' => $this->initialDockerComposePrLocation] = $this->application->loadComposeFile($isInit);
if (is_null($this->parsedServices)) {
$this->dispatch('error', "Failed to parse your docker-compose file. Please check the syntax and try again.");
return;
}
$compose = $this->application->parseCompose();
$services = data_get($compose, 'services');
if ($services) {
Expand Down
149 changes: 76 additions & 73 deletions app/Livewire/Project/Resource/Create.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class Create extends Component
public $type;
public function mount()
{
$services = getServiceTemplates();
$type = str(request()->query('type'));
$destination_uuid = request()->query('destination');
$server_id = request()->query('server_id');
Expand All @@ -25,83 +24,87 @@ public function mount()
if (!$environment) {
return redirect()->route('dashboard');
}
if (in_array($type, DATABASE_TYPES)) {
if ($type->value() === "postgresql") {
$database = create_standalone_postgresql($environment->id, $destination_uuid);
} else if ($type->value() === 'redis') {
$database = create_standalone_redis($environment->id, $destination_uuid);
} else if ($type->value() === 'mongodb') {
$database = create_standalone_mongodb($environment->id, $destination_uuid);
} else if ($type->value() === 'mysql') {
$database = create_standalone_mysql($environment->id, $destination_uuid);
} else if ($type->value() === 'mariadb') {
$database = create_standalone_mariadb($environment->id, $destination_uuid);
} else if ($type->value() === 'keydb') {
$database = create_standalone_keydb($environment->id, $destination_uuid);
} else if ($type->value() === 'dragonfly') {
$database = create_standalone_dragonfly($environment->id, $destination_uuid);
} else if ($type->value() === 'clickhouse') {
$database = create_standalone_clickhouse($environment->id, $destination_uuid);
}
return redirect()->route('project.database.configuration', [
'project_uuid' => $project->uuid,
'environment_name' => $environment->name,
'database_uuid' => $database->uuid,
]);
}
if ($type->startsWith('one-click-service-') && !is_null((int)$server_id)) {
$oneClickServiceName = $type->after('one-click-service-')->value();
$oneClickService = data_get($services, "$oneClickServiceName.compose");
$oneClickDotEnvs = data_get($services, "$oneClickServiceName.envs", null);
if ($oneClickDotEnvs) {
$oneClickDotEnvs = str(base64_decode($oneClickDotEnvs))->split('/\r\n|\r|\n/')->filter(function ($value) {
return !empty($value);
});
}
if ($oneClickService) {
$destination = StandaloneDocker::whereUuid($destination_uuid)->first();
$service_payload = [
'name' => "$oneClickServiceName-" . str()->random(10),
'docker_compose_raw' => base64_decode($oneClickService),
'environment_id' => $environment->id,
'service_type' => $oneClickServiceName,
'server_id' => (int) $server_id,
'destination_id' => $destination->id,
'destination_type' => $destination->getMorphClass(),
];
if ($oneClickServiceName === 'cloudflared') {
data_set($service_payload, 'connect_to_docker_network', true);
}
$service = Service::create($service_payload);
$service->name = "$oneClickServiceName-" . $service->uuid;
$service->save();
if ($oneClickDotEnvs?->count() > 0) {
$oneClickDotEnvs->each(function ($value) use ($service) {
$key = str()->before($value, '=');
$value = str(str()->after($value, '='));
$generatedValue = $value;
if ($value->contains('SERVICE_')) {
$command = $value->after('SERVICE_')->beforeLast('_');
$generatedValue = generateEnvValue($command->value(), $service);
}
EnvironmentVariable::create([
'key' => $key,
'value' => $generatedValue,
'service_id' => $service->id,
'is_build_time' => false,
'is_preview' => false,
]);
});
if (isset($type) && isset($destination_uuid) && isset($server_id)) {
$services = getServiceTemplates();

if (in_array($type, DATABASE_TYPES)) {
if ($type->value() === "postgresql") {
$database = create_standalone_postgresql($environment->id, $destination_uuid);
} else if ($type->value() === 'redis') {
$database = create_standalone_redis($environment->id, $destination_uuid);
} else if ($type->value() === 'mongodb') {
$database = create_standalone_mongodb($environment->id, $destination_uuid);
} else if ($type->value() === 'mysql') {
$database = create_standalone_mysql($environment->id, $destination_uuid);
} else if ($type->value() === 'mariadb') {
$database = create_standalone_mariadb($environment->id, $destination_uuid);
} else if ($type->value() === 'keydb') {
$database = create_standalone_keydb($environment->id, $destination_uuid);
} else if ($type->value() === 'dragonfly') {
$database = create_standalone_dragonfly($environment->id, $destination_uuid);
} else if ($type->value() === 'clickhouse') {
$database = create_standalone_clickhouse($environment->id, $destination_uuid);
}
$service->parse(isNew: true);
return redirect()->route('project.service.configuration', [
'service_uuid' => $service->uuid,
'environment_name' => $environment->name,
return redirect()->route('project.database.configuration', [
'project_uuid' => $project->uuid,
'environment_name' => $environment->name,
'database_uuid' => $database->uuid,
]);
}
if ($type->startsWith('one-click-service-') && !is_null((int)$server_id)) {
$oneClickServiceName = $type->after('one-click-service-')->value();
$oneClickService = data_get($services, "$oneClickServiceName.compose");
$oneClickDotEnvs = data_get($services, "$oneClickServiceName.envs", null);
if ($oneClickDotEnvs) {
$oneClickDotEnvs = str(base64_decode($oneClickDotEnvs))->split('/\r\n|\r|\n/')->filter(function ($value) {
return !empty($value);
});
}
if ($oneClickService) {
$destination = StandaloneDocker::whereUuid($destination_uuid)->first();
$service_payload = [
'name' => "$oneClickServiceName-" . str()->random(10),
'docker_compose_raw' => base64_decode($oneClickService),
'environment_id' => $environment->id,
'service_type' => $oneClickServiceName,
'server_id' => (int) $server_id,
'destination_id' => $destination->id,
'destination_type' => $destination->getMorphClass(),
];
if ($oneClickServiceName === 'cloudflared') {
data_set($service_payload, 'connect_to_docker_network', true);
}
$service = Service::create($service_payload);
$service->name = "$oneClickServiceName-" . $service->uuid;
$service->save();
if ($oneClickDotEnvs?->count() > 0) {
$oneClickDotEnvs->each(function ($value) use ($service) {
$key = str()->before($value, '=');
$value = str(str()->after($value, '='));
$generatedValue = $value;
if ($value->contains('SERVICE_')) {
$command = $value->after('SERVICE_')->beforeLast('_');
$generatedValue = generateEnvValue($command->value(), $service);
}
EnvironmentVariable::create([
'key' => $key,
'value' => $generatedValue,
'service_id' => $service->id,
'is_build_time' => false,
'is_preview' => false,
]);
});
}
$service->parse(isNew: true);
return redirect()->route('project.service.configuration', [
'service_uuid' => $service->uuid,
'environment_name' => $environment->name,
'project_uuid' => $project->uuid,
]);
}
}
$this->type = $type->value();
}
$this->type = $type->value();
}
public function render()
{
Expand Down