commit
ea64e9d5ad
22
.tinkerwell/snippets/DeleteUser.php
Normal file
22
.tinkerwell/snippets/DeleteUser.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
$email = 'test@example.com';
|
||||
$user = User::whereEmail($email)->first();
|
||||
$teams = $user->teams;
|
||||
foreach ($teams as $team) {
|
||||
$servers = $team->servers;
|
||||
if ($servers->count() > 0) {
|
||||
foreach ($servers as $server) {
|
||||
dump($server);
|
||||
$server->delete();
|
||||
}
|
||||
}
|
||||
dump($team);
|
||||
$team->delete();
|
||||
}
|
||||
if ($user) {
|
||||
dump($user);
|
||||
$user->delete();
|
||||
}
|
@ -7,17 +7,34 @@
|
||||
class StackForm extends Component
|
||||
{
|
||||
public $service;
|
||||
public $isConfigurationRequired = false;
|
||||
public $fields = [];
|
||||
protected $listeners = ["saveCompose"];
|
||||
protected $rules = [
|
||||
public $rules = [
|
||||
'service.docker_compose_raw' => 'required',
|
||||
'service.docker_compose' => 'required',
|
||||
'service.name' => 'required',
|
||||
'service.description' => 'nullable',
|
||||
];
|
||||
public function mount () {
|
||||
if ($this->service->applications->filter(fn($app) => str($app->image)->contains('minio/minio'))->count() > 0) {
|
||||
$this->isConfigurationRequired = true;
|
||||
public $validationAttributes = [];
|
||||
public function mount()
|
||||
{
|
||||
$extraFields = $this->service->extraFields();
|
||||
foreach ($extraFields as $serviceName => $fields) {
|
||||
foreach ($fields as $fieldKey => $field) {
|
||||
$key = data_get($field, 'key');
|
||||
$value = data_get($field, 'value');
|
||||
$rules = data_get($field, 'rules');
|
||||
$isPassword = data_get($field, 'isPassword');
|
||||
$this->fields[$key] = [
|
||||
"serviceName" => $serviceName,
|
||||
"key" => $key,
|
||||
"name" => $fieldKey,
|
||||
"value" => $value,
|
||||
"isPassword" => $isPassword,
|
||||
];
|
||||
$this->rules["fields.$key.value"] = $rules;
|
||||
$this->validationAttributes["fields.$key.value"] = $fieldKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
public function saveCompose($raw)
|
||||
@ -32,6 +49,7 @@ public function submit()
|
||||
try {
|
||||
$this->validate();
|
||||
$this->service->save();
|
||||
$this->service->saveExtraFields($this->fields);
|
||||
$this->service->parse();
|
||||
$this->service->refresh();
|
||||
$this->service->saveComposeConfigs();
|
||||
|
@ -934,7 +934,16 @@ private function generate_healthcheck_commands()
|
||||
}
|
||||
return implode(' ', $generated_healthchecks_commands);
|
||||
}
|
||||
private function pull_latest_image($image)
|
||||
{
|
||||
$this->execute_remote_command(
|
||||
["echo -n 'Pulling latest image ($image) from the registry.'"],
|
||||
|
||||
[
|
||||
executeInDocker($this->deployment_uuid, "docker pull {$image}"), "hidden" => true
|
||||
]
|
||||
);
|
||||
}
|
||||
private function build_image()
|
||||
{
|
||||
if ($this->application->build_pack === 'static') {
|
||||
@ -948,6 +957,9 @@ private function build_image()
|
||||
}
|
||||
|
||||
if ($this->application->settings->is_static || $this->application->build_pack === 'static') {
|
||||
if ($this->application->static_image) {
|
||||
$this->pull_latest_image($this->application->static_image);
|
||||
}
|
||||
if ($this->application->build_pack === 'static') {
|
||||
$dockerfile = base64_encode("FROM {$this->application->static_image}
|
||||
WORKDIR /usr/share/nginx/html/
|
||||
@ -1012,8 +1024,9 @@ private function build_image()
|
||||
]
|
||||
);
|
||||
} else {
|
||||
// Pure Dockerfile based deployment
|
||||
$this->execute_remote_command([
|
||||
executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
|
||||
executeInDocker($this->deployment_uuid, "docker build --pull $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -1049,6 +1062,17 @@ private function stop_running_container(bool $force = false)
|
||||
|
||||
private function start_by_compose_file()
|
||||
{
|
||||
if (
|
||||
!$this->application->dockerfile &&
|
||||
(
|
||||
$this->application->build_pack === 'dockerimage' ||
|
||||
$this->application->build_pack === 'dockerfile')
|
||||
) {
|
||||
$this->execute_remote_command(
|
||||
["echo -n 'Pulling latest images from the registry.'"],
|
||||
[executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} pull"), "hidden" => true],
|
||||
);
|
||||
}
|
||||
$this->execute_remote_command(
|
||||
["echo -n 'Starting application (could take a while).'"],
|
||||
[executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} up --build -d"), "hidden" => true],
|
||||
|
@ -45,7 +45,168 @@ public function type()
|
||||
{
|
||||
return 'service';
|
||||
}
|
||||
public function extraFields()
|
||||
{
|
||||
$fields = collect([]);
|
||||
$applications = $this->applications()->get();
|
||||
foreach ($applications as $application) {
|
||||
$image = str($application->image)->before(':')->value();
|
||||
switch ($image) {
|
||||
case str($image)->contains('minio'):
|
||||
$console_url = $this->environment_variables()->where('key', 'MINIO_BROWSER_REDIRECT_URL')->first();
|
||||
$s3_api_url = $this->environment_variables()->where('key', 'MINIO_SERVER_URL')->first();
|
||||
$admin_user = $this->environment_variables()->where('key', 'SERVICE_USER_MINIO')->first();
|
||||
$admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_MINIO')->first();
|
||||
$fields->put('MinIO', [
|
||||
'Console URL' => [
|
||||
'key' => data_get($console_url, 'key'),
|
||||
'value' => data_get($console_url, 'value'),
|
||||
'rules' => 'required|url',
|
||||
],
|
||||
'S3 API URL' => [
|
||||
'key' => data_get($s3_api_url, 'key'),
|
||||
'value' => data_get($s3_api_url, 'value'),
|
||||
'rules' => 'required|url',
|
||||
],
|
||||
'Admin User' => [
|
||||
'key' => data_get($admin_user, 'key'),
|
||||
'value' => data_get($admin_user, 'value'),
|
||||
'rules' => 'required',
|
||||
],
|
||||
'Admin Password' => [
|
||||
'key' => data_get($admin_password, 'key'),
|
||||
'value' => data_get($admin_password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$databases = $this->databases()->get();
|
||||
|
||||
foreach ($databases as $database) {
|
||||
$image = str($database->image)->before(':')->value();
|
||||
switch ($image) {
|
||||
case str($image)->contains('postgres'):
|
||||
$userVariables = ['SERVICE_USER_POSTGRES', 'SERVICE_USER_POSTGRESQL'];
|
||||
$passwordVariables = ['SERVICE_PASSWORD_POSTGRES', 'SERVICE_PASSWORD_POSTGRESQL'];
|
||||
$dbNameVariables = ['POSTGRESQL_DATABASE', 'POSTGRES_DB'];
|
||||
$postgres_user = $this->environment_variables()->whereIn('key', $userVariables)->first();
|
||||
$postgres_password = $this->environment_variables()->whereIn('key', $passwordVariables)->first();
|
||||
$postgres_db_name = $this->environment_variables()->whereIn('key', $dbNameVariables)->first();
|
||||
$fields->put('PostgreSQL', [
|
||||
'User' => [
|
||||
'key' => data_get($postgres_user, 'key'),
|
||||
'value' => data_get($postgres_user, 'value'),
|
||||
'rules' => 'required',
|
||||
],
|
||||
'Password' => [
|
||||
'key' => data_get($postgres_password, 'key'),
|
||||
'value' => data_get($postgres_password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
'Database Name' => [
|
||||
'key' => data_get($postgres_db_name, 'key'),
|
||||
'value' => data_get($postgres_db_name, 'value'),
|
||||
'rules' => 'required',
|
||||
],
|
||||
]);
|
||||
break;
|
||||
case str($image)->contains('mysql'):
|
||||
$userVariables = ['SERVICE_USER_MYSQL', 'SERVICE_USER_WORDPRESS'];
|
||||
$passwordVariables = ['SERVICE_PASSWORD_MYSQL', 'SERVICE_PASSWORD_WORDPRESS'];
|
||||
$rootPasswordVariables = ['SERVICE_PASSWORD_MYSQLROOT', 'SERVICE_PASSWORD_ROOT'];
|
||||
$dbNameVariables = ['MYSQL_DATABASE'];
|
||||
$mysql_user = $this->environment_variables()->whereIn('key', $userVariables)->first();
|
||||
$mysql_password = $this->environment_variables()->whereIn('key', $passwordVariables)->first();
|
||||
$mysql_root_password = $this->environment_variables()->whereIn('key', $rootPasswordVariables)->first();
|
||||
$mysql_db_name = $this->environment_variables()->whereIn('key', $dbNameVariables)->first();
|
||||
$fields->put('MySQL', [
|
||||
'User' => [
|
||||
'key' => data_get($mysql_user, 'key'),
|
||||
'value' => data_get($mysql_user, 'value'),
|
||||
'rules' => 'required',
|
||||
],
|
||||
'Password' => [
|
||||
'key' => data_get($mysql_password, 'key'),
|
||||
'value' => data_get($mysql_password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
'Root Password' => [
|
||||
'key' => data_get($mysql_root_password, 'key'),
|
||||
'value' => data_get($mysql_root_password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
'Database Name' => [
|
||||
'key' => data_get($mysql_db_name, 'key'),
|
||||
'value' => data_get($mysql_db_name, 'value'),
|
||||
'rules' => 'required',
|
||||
],
|
||||
]);
|
||||
break;
|
||||
case str($image)->contains('mariadb'):
|
||||
$userVariables = ['SERVICE_USER_MARIADB', 'SERVICE_USER_WORDPRESS', '_APP_DB_USER'];
|
||||
$passwordVariables = ['SERVICE_PASSWORD_MARIADB', 'SERVICE_PASSWORD_WORDPRESS', '_APP_DB_PASS'];
|
||||
$rootPasswordVariables = ['SERVICE_PASSWORD_MARIADBROOT', 'SERVICE_PASSWORD_ROOT', '_APP_DB_ROOT_PASS'];
|
||||
$dbNameVariables = ['SERVICE_DATABASE_MARIADB', 'SERVICE_DATABASE_WORDPRESS', '_APP_DB_SCHEMA'];
|
||||
$mariadb_user = $this->environment_variables()->whereIn('key', $userVariables)->first();
|
||||
$mariadb_password = $this->environment_variables()->whereIn('key', $passwordVariables)->first();
|
||||
$mariadb_root_password = $this->environment_variables()->whereIn('key', $rootPasswordVariables)->first();
|
||||
$mariadb_db_name = $this->environment_variables()->whereIn('key', $dbNameVariables)->first();
|
||||
$fields->put('MariaDB', [
|
||||
'User' => [
|
||||
'key' => data_get($mariadb_user, 'key'),
|
||||
'value' => data_get($mariadb_user, 'value'),
|
||||
'rules' => 'required',
|
||||
],
|
||||
'Password' => [
|
||||
'key' => data_get($mariadb_password, 'key'),
|
||||
'value' => data_get($mariadb_password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
'Root Password' => [
|
||||
'key' => data_get($mariadb_root_password, 'key'),
|
||||
'value' => data_get($mariadb_root_password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
'Database Name' => [
|
||||
'key' => data_get($mariadb_db_name, 'key'),
|
||||
'value' => data_get($mariadb_db_name, 'value'),
|
||||
'rules' => data_get($mariadb_db_name, 'value') && 'required',
|
||||
],
|
||||
]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
public function saveExtraFields($fields)
|
||||
{
|
||||
foreach ($fields as $field) {
|
||||
$key = data_get($field, 'key');
|
||||
$value = data_get($field, 'value');
|
||||
$found = $this->environment_variables()->where('key', $key)->first();
|
||||
if ($found) {
|
||||
$found->value = $value;
|
||||
$found->save();
|
||||
} else {
|
||||
$this->environment_variables()->create([
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
'is_build_time' => false,
|
||||
'service_id' => $this->id,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
public function documentation()
|
||||
{
|
||||
$services = getServiceTemplates();
|
||||
@ -257,7 +418,7 @@ public function parse(bool $isNew = false): Collection
|
||||
}
|
||||
}
|
||||
$networks = collect();
|
||||
foreach ($serviceNetworks as $key =>$serviceNetwork) {
|
||||
foreach ($serviceNetworks as $key => $serviceNetwork) {
|
||||
if (gettype($serviceNetwork) === 'string') {
|
||||
// networks:
|
||||
// - appwrite
|
||||
@ -268,7 +429,7 @@ public function parse(bool $isNew = false): Collection
|
||||
// ipv4_address: 192.168.203.254
|
||||
// $networks->put($serviceNetwork, null);
|
||||
ray($key);
|
||||
$networks->put($key,$serviceNetwork);
|
||||
$networks->put($key, $serviceNetwork);
|
||||
}
|
||||
}
|
||||
foreach ($definedNetwork as $key => $network) {
|
||||
@ -564,12 +725,18 @@ public function parse(bool $isNew = false): Collection
|
||||
}
|
||||
|
||||
// Add labels to the service
|
||||
$fqdns = collect(data_get($savedService, 'fqdns'));
|
||||
$defaultLabels = defaultLabels($this->id, $containerName, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id);
|
||||
$serviceLabels = $serviceLabels->merge($defaultLabels);
|
||||
if (!$isDatabase && $fqdns->count() > 0) {
|
||||
if ($fqdns) {
|
||||
$serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($this->uuid, $fqdns, true));
|
||||
if (!$isDatabase) {
|
||||
if ($savedService->serviceType()) {
|
||||
$fqdns = generateServiceSpecificFqdns($savedService, forTraefik: true);
|
||||
} else {
|
||||
$fqdns = collect(data_get($savedService, 'fqdns'));
|
||||
}
|
||||
$defaultLabels = defaultLabels($this->id, $containerName, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id);
|
||||
$serviceLabels = $serviceLabels->merge($defaultLabels);
|
||||
if ($fqdns->count() > 0) {
|
||||
if ($fqdns) {
|
||||
$serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($this->uuid, $fqdns, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
data_set($service, 'labels', $serviceLabels->toArray());
|
||||
|
@ -22,6 +22,16 @@ public function type()
|
||||
{
|
||||
return 'service';
|
||||
}
|
||||
public function serviceType()
|
||||
{
|
||||
$found = str(collect(SPECIFIC_SERVICES)->filter(function ($service) {
|
||||
return str($this->image)->before(':')->value() === $service;
|
||||
})->first());
|
||||
if ($found->isNotEmpty()) {
|
||||
return $found;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public function service()
|
||||
{
|
||||
return $this->belongsTo(Service::class);
|
||||
|
@ -29,7 +29,6 @@ public function databaseType()
|
||||
return "standalone-$image";
|
||||
}
|
||||
public function getServiceDatabaseUrl() {
|
||||
// $type = $this->databaseType();
|
||||
$port = $this->public_port;
|
||||
$realIp = $this->service->server->ip;
|
||||
if ($realIp === 'host.docker.internal' || isDev()) {
|
||||
|
@ -16,22 +16,28 @@ public function __construct(public Service $service)
|
||||
{
|
||||
$this->links = collect([]);
|
||||
$service->applications()->get()->map(function ($application) {
|
||||
if ($application->fqdn) {
|
||||
$fqdns = collect(Str::of($application->fqdn)->explode(','));
|
||||
$fqdns->map(function ($fqdn) {
|
||||
$this->links->push(getFqdnWithoutPort($fqdn));
|
||||
});
|
||||
}
|
||||
if ($application->ports) {
|
||||
$portsCollection = collect(Str::of($application->ports)->explode(','));
|
||||
$portsCollection->map(function ($port) {
|
||||
if (Str::of($port)->contains(':')) {
|
||||
$hostPort = Str::of($port)->before(':');
|
||||
} else {
|
||||
$hostPort = $port;
|
||||
}
|
||||
$this->links->push(base_url(withPort:false) . ":{$hostPort}");
|
||||
});
|
||||
$type = $application->serviceType();
|
||||
if ($type) {
|
||||
$links = generateServiceSpecificFqdns($application, false);
|
||||
$this->links = $this->links->merge($links);
|
||||
} else {
|
||||
if ($application->fqdn) {
|
||||
$fqdns = collect(Str::of($application->fqdn)->explode(','));
|
||||
$fqdns->map(function ($fqdn) {
|
||||
$this->links->push(getFqdnWithoutPort($fqdn));
|
||||
});
|
||||
}
|
||||
if ($application->ports) {
|
||||
$portsCollection = collect(Str::of($application->ports)->explode(','));
|
||||
$portsCollection->map(function ($port) {
|
||||
if (Str::of($port)->contains(':')) {
|
||||
$hostPort = Str::of($port)->before(':');
|
||||
} else {
|
||||
$hostPort = $port;
|
||||
}
|
||||
$this->links->push(base_url(withPort: false) . ":{$hostPort}");
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -23,3 +23,6 @@
|
||||
'influxdb',
|
||||
'clickhouse/clickhouse-server'
|
||||
];
|
||||
const SPECIFIC_SERVICES = [
|
||||
'quay.io/minio/minio',
|
||||
];
|
||||
|
@ -144,6 +144,39 @@ function defaultLabels($id, $name, $pull_request_id = 0, string $type = 'applica
|
||||
}
|
||||
return $labels;
|
||||
}
|
||||
function generateServiceSpecificFqdns($service, $forTraefik = false)
|
||||
{
|
||||
$variables = collect($service->service->environment_variables);
|
||||
$type = $service->serviceType();
|
||||
$payload = collect([]);
|
||||
switch ($type) {
|
||||
case $type->contains('minio'):
|
||||
$MINIO_BROWSER_REDIRECT_URL = $variables->where('key', 'MINIO_BROWSER_REDIRECT_URL')->first();
|
||||
if (is_null($MINIO_BROWSER_REDIRECT_URL?->value)) {
|
||||
$MINIO_BROWSER_REDIRECT_URL->update([
|
||||
"value" => generateFqdn($service->service->server, 'console-' . $service->uuid)
|
||||
]);
|
||||
}
|
||||
$MINIO_SERVER_URL = $variables->where('key', 'MINIO_SERVER_URL')->first();
|
||||
if (is_null($MINIO_SERVER_URL?->value)) {
|
||||
$MINIO_SERVER_URL->update([
|
||||
"value" => generateFqdn($service->service->server, 'minio-' . $service->uuid)
|
||||
]);
|
||||
}
|
||||
if ($forTraefik) {
|
||||
$payload = collect([
|
||||
$MINIO_BROWSER_REDIRECT_URL->value . ':9001',
|
||||
$MINIO_SERVER_URL->value . ':9000',
|
||||
]);
|
||||
} else {
|
||||
$payload = collect([
|
||||
$MINIO_BROWSER_REDIRECT_URL->value,
|
||||
$MINIO_SERVER_URL->value,
|
||||
]);
|
||||
}
|
||||
}
|
||||
return $payload;
|
||||
}
|
||||
function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled, $onlyPort = null)
|
||||
{
|
||||
$labels = collect([]);
|
||||
|
@ -126,7 +126,6 @@ function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase $oneS
|
||||
function updateCompose($resource)
|
||||
{
|
||||
try {
|
||||
ray($resource);
|
||||
$name = data_get($resource, 'name');
|
||||
$dockerComposeRaw = data_get($resource, 'service.docker_compose_raw');
|
||||
$dockerCompose = Yaml::parse($dockerComposeRaw);
|
||||
|
@ -27,7 +27,6 @@
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Stringable;
|
||||
use Nubs\RandomNameGenerator\All;
|
||||
use Poliander\Cron\CronExpression;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
use phpseclib3\Crypt\RSA;
|
||||
@ -173,7 +172,11 @@ function get_latest_version_of_coolify(): string
|
||||
|
||||
function generate_random_name(?string $cuid = null): string
|
||||
{
|
||||
$generator = All::create();
|
||||
$generator = new \Nubs\RandomNameGenerator\All(
|
||||
[
|
||||
new \Nubs\RandomNameGenerator\Alliteration(),
|
||||
]
|
||||
);
|
||||
if (is_null($cuid)) {
|
||||
$cuid = new Cuid2(7);
|
||||
}
|
||||
@ -444,20 +447,25 @@ function getServiceTemplates()
|
||||
if (isDev()) {
|
||||
$services = File::get(base_path('templates/service-templates.json'));
|
||||
$services = collect(json_decode($services))->sortKeys();
|
||||
$version = config('version');
|
||||
$services = $services->map(function ($service) use ($version) {
|
||||
if (version_compare($version, data_get($service, 'minVersion', '0.0.0'), '<')) {
|
||||
$service->disabled = true;
|
||||
}
|
||||
return $service;
|
||||
});
|
||||
} else {
|
||||
$services = Http::get(config('constants.services.official'));
|
||||
if ($services->failed()) {
|
||||
throw new \Exception($services->body());
|
||||
try {
|
||||
$response = Http::retry(3, 50)->get(config('constants.services.official'));
|
||||
if ($response->failed()) {
|
||||
return collect([]);
|
||||
}
|
||||
$services = $response->json();
|
||||
$services = collect($services)->sortKeys();
|
||||
} catch (\Throwable $e) {
|
||||
$services = collect([]);
|
||||
}
|
||||
$services = collect($services->json())->sortKeys();
|
||||
}
|
||||
// $version = config('version');
|
||||
// $services = $services->map(function ($service) use ($version) {
|
||||
// if (version_compare($version, data_get($service, 'minVersion', '0.0.0'), '<')) {
|
||||
// $service->disabled = true;
|
||||
// }
|
||||
// return $service;
|
||||
// });
|
||||
return $services;
|
||||
}
|
||||
|
||||
@ -493,7 +501,8 @@ function queryResourcesByUuid(string $uuid)
|
||||
return $resource;
|
||||
}
|
||||
|
||||
function generateDeployWebhook($resource) {
|
||||
function generateDeployWebhook($resource)
|
||||
{
|
||||
$baseUrl = base_url();
|
||||
$api = Url::fromString($baseUrl) . '/api/v1';
|
||||
$endpoint = '/deploy';
|
||||
@ -501,6 +510,7 @@ function generateDeployWebhook($resource) {
|
||||
$url = $api . $endpoint . "?uuid=$uuid&force=false";
|
||||
return $url;
|
||||
}
|
||||
function removeAnsiColors($text) {
|
||||
function removeAnsiColors($text)
|
||||
{
|
||||
return preg_replace('/\e[[][A-Za-z0-9];?[0-9]*m?/', '', $text);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
// The release version of your application
|
||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||
'release' => '4.0.0-beta.123',
|
||||
'release' => '4.0.0-beta.124',
|
||||
// When left empty or `null` the Laravel environment will be used
|
||||
'environment' => config('app.env'),
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
<?php
|
||||
|
||||
return '4.0.0-beta.123';
|
||||
return '4.0.0-beta.124';
|
||||
|
@ -44,6 +44,7 @@ services:
|
||||
- STRIPE_PRICE_ID_PRO_YEARLY
|
||||
- STRIPE_PRICE_ID_ULTIMATE_MONTHLY
|
||||
- STRIPE_PRICE_ID_ULTIMATE_YEARLY
|
||||
- STRIPE_EXCLUDED_PLANS
|
||||
- PADDLE_VENDOR_ID
|
||||
- PADDLE_WEBHOOK_SECRET
|
||||
- PADDLE_VENDOR_AUTH_CODE
|
||||
|
@ -3,7 +3,7 @@
|
||||
href="{{ route('project.service', $parameters) }}">
|
||||
<button>Configuration</button>
|
||||
</a>
|
||||
<x-services.links :service="$service" />
|
||||
<x-services.links />
|
||||
<div class="flex-1"></div>
|
||||
@if (serviceStatus($service) === 'degraded')
|
||||
<button wire:click='deploy' onclick="startService.showModal()"
|
||||
|
@ -5,7 +5,7 @@
|
||||
<div class="fixed z-50 top-[4.5rem] left-4" id="vue">
|
||||
<magic-bar></magic-bar>
|
||||
</div>
|
||||
<main class="main max-w-screen-2xl">
|
||||
<main class="pb-10 main max-w-screen-2xl">
|
||||
{{ $slot }}
|
||||
</main>
|
||||
@endsection
|
||||
|
@ -67,7 +67,7 @@
|
||||
services, called resources. Any CPU intensive process will use the server's CPU where you
|
||||
are deploying your resources.</p>
|
||||
<p>Localhost is the server where Coolify is running on. It is not recommended to use one server
|
||||
for everyting.</p>
|
||||
for everything.</p>
|
||||
<p>Remote Server is a server reachable through SSH. It can be hosted at home, or from any cloud
|
||||
provider.</p>
|
||||
</x-slot:explanation>
|
||||
|
@ -182,7 +182,7 @@ class="w-full text-white rounded input input-sm bg-coolgray-200 disabled:bg-cool
|
||||
</button>
|
||||
@endif
|
||||
@empty
|
||||
<div>No service found.</div>
|
||||
<div>No service found. Please try to reload the list!</div>
|
||||
@endforelse
|
||||
@endif
|
||||
</div>
|
||||
|
@ -16,19 +16,21 @@
|
||||
<x-forms.input label="Description" id="application.description"></x-forms.input>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
@if ($application->required_fqdn)
|
||||
<x-forms.input required placeholder="https://app.coolify.io" label="Domains"
|
||||
id="application.fqdn" helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io, https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "></x-forms.input>
|
||||
@else
|
||||
<x-forms.input placeholder="https://app.coolify.io" label="Domains"
|
||||
id="application.fqdn" helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io, https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "></x-forms.input>
|
||||
@if (!$application->serviceType()?->contains(str($application->image)->before(':')))
|
||||
@if ($application->required_fqdn)
|
||||
<x-forms.input required placeholder="https://app.coolify.io" label="Domains"
|
||||
id="application.fqdn"
|
||||
helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io, https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "></x-forms.input>
|
||||
@else
|
||||
<x-forms.input placeholder="https://app.coolify.io" label="Domains" id="application.fqdn"
|
||||
helper="You can specify one domain with path or more with comma. You can specify a port to bind the domain to.<br><br><span class='text-helper'>Example</span><br>- http://app.coolify.io, https://cloud.coolify.io/dashboard<br>- http://app.coolify.io/api/v3<br>- http://app.coolify.io:3000 -> app.coolify.io will point to port 3000 inside the container. "></x-forms.input>
|
||||
@endif
|
||||
@endif
|
||||
<x-forms.input required
|
||||
helper="You can change the image you would like to deploy.<br><br><span class='text-warning'>WARNING. You could corrupt your data. Only do it if you know what you are doing.</span>"
|
||||
label="Image" id="application.image"></x-forms.input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="pt-2">Advanced</h3>
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox instantSave label="Exclude from service status"
|
||||
|
@ -28,7 +28,7 @@
|
||||
<div class="w-full pl-8">
|
||||
<div x-cloak x-show="activeTab === 'service-stack'">
|
||||
<livewire:project.service.stack-form :service="$service" />
|
||||
<div class="grid grid-cols-1 gap-2 pt-4 xl:grid-cols-3">
|
||||
<div class="grid grid-cols-1 gap-2 pt-4 xl:grid-cols-1">
|
||||
@foreach ($applications as $application)
|
||||
<div @class([
|
||||
'border-l border-dashed border-red-500' => Str::of(
|
||||
@ -58,7 +58,7 @@
|
||||
@endif
|
||||
<div class="text-xs">{{ $application->status }}</div>
|
||||
</a>
|
||||
<a class="flex gap-2 p-1 mx-4 font-bold rounded group-hover:text-white hover:no-underline"
|
||||
<a class="flex items-center gap-2 p-1 mx-4 font-bold rounded group-hover:text-white hover:no-underline"
|
||||
href="{{ route('project.service.logs', [...$parameters, 'service_name' => $application->name]) }}"><span
|
||||
class="hover:text-warning">Logs</span></a>
|
||||
</div>
|
||||
@ -88,7 +88,7 @@ class="hover:text-warning">Logs</span></a>
|
||||
@endif
|
||||
<div class="text-xs">{{ $database->status }}</div>
|
||||
</a>
|
||||
<a class="flex gap-2 p-1 mx-4 font-bold rounded hover:no-underline group-hover:text-white"
|
||||
<a class="flex items-center gap-2 p-1 mx-4 font-bold rounded hover:no-underline group-hover:text-white"
|
||||
href="{{ route('project.service.logs', [...$parameters, 'service_name' => $database->name]) }}"><span
|
||||
class="hover:text-warning">Logs</span></a>
|
||||
</div>
|
||||
|
@ -12,9 +12,17 @@
|
||||
<x-forms.input id="service.name" required label="Service Name" placeholder="My super wordpress site" />
|
||||
<x-forms.input id="service.description" label="Description" />
|
||||
</div>
|
||||
{{-- @if ($isConfigurationRequired)
|
||||
<div class="text-warning">This service requires additional confiugration. Please check our <a
|
||||
href="https://coolify.io/docs" class="text-white underline">documentation</a> for further information.
|
||||
@if ($fields)
|
||||
<div>
|
||||
<h3>Service Specific Configuration</h3>
|
||||
</div>
|
||||
@endif --}}
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
@foreach ($fields as $serviceName => $fields)
|
||||
<x-forms.input type="{{ data_get($fields, 'isPassword') ? 'password' : 'text' }}" required
|
||||
helper="Variable name: {{ $serviceName }}"
|
||||
label="{{ data_get($fields, 'serviceName') }} {{ data_get($fields, 'name') }}"
|
||||
id="fields.{{ $serviceName }}.value"></x-forms.input>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
|
@ -1,4 +1,4 @@
|
||||
# documentation: https://fider.io/doc
|
||||
# documentation: https://fider.io/docs
|
||||
# slogan: Fider is an open-source feedback platform for collecting and managing user feedback, helping you prioritize improvements to your products and services.
|
||||
# tags: feedback, user-feedback
|
||||
|
||||
|
@ -13,29 +13,3 @@ services:
|
||||
- MINIO_ROOT_PASSWORD=$SERVICE_PASSWORD_MINIO
|
||||
volumes:
|
||||
- minio-data:/data
|
||||
|
||||
# services:
|
||||
# minio:
|
||||
# image: minio/minio
|
||||
# command: server /data --address ":9000" --console-address ":9001"
|
||||
# networks:
|
||||
# - coolify
|
||||
# environment:
|
||||
# - MINIO_SERVER_URL=http://minio.65.21.189.27.sslip.io
|
||||
# - MINIO_BROWSER_REDIRECT_URL=http://console.65.21.189.27.sslip.io
|
||||
# - MINIO_BROWSER=on
|
||||
# - MINIO_ROOT_USER=asd
|
||||
# - MINIO_ROOT_PASSWORD=asdasdasd
|
||||
# labels:
|
||||
# - "traefik.enable=true"
|
||||
# - "traefik.http.routers.minio-console.rule=Host(`console.65.21.189.27.sslip.io`)"
|
||||
# - "traefik.http.routers.minio-console.entrypoints=http"
|
||||
# - "traefik.http.routers.minio-console.service=minio-console"
|
||||
# - "traefik.http.services.minio-console.loadbalancer.server.port=9001"
|
||||
# - "traefik.http.routers.minio.rule=Host(`minio.65.21.189.27.sslip.io`)"
|
||||
# - "traefik.http.routers.minio.entrypoints=http"
|
||||
# - "traefik.http.routers.minio.service=minio"
|
||||
# - "traefik.http.services.minio.loadbalancer.server.port=9000"
|
||||
# networks:
|
||||
# coolify:
|
||||
# external: true
|
||||
|
@ -132,7 +132,7 @@
|
||||
]
|
||||
},
|
||||
"fider": {
|
||||
"documentation": "https:\/\/fider.io\/doc",
|
||||
"documentation": "https:\/\/fider.io\/docs",
|
||||
"slogan": "Fider is an open-source feedback platform for collecting and managing user feedback, helping you prioritize improvements to your products and services.",
|
||||
"compose": "c2VydmljZXM6CiAgZmlkZXI6CiAgICBpbWFnZTogJ2dldGZpZGVyL2ZpZGVyOnN0YWJsZScKICAgIGVudmlyb25tZW50OgogICAgICBCQVNFX1VSTDogJFNFUlZJQ0VfRlFETl9GSURFUgogICAgICBEQVRBQkFTRV9VUkw6ICdwb3N0Z3JlczovLyRTRVJWSUNFX1VTRVJfTVlTUUw6JFNFUlZJQ0VfUEFTU1dPUkRfTVlTUUxAZGF0YWJhc2U6NTQzMi9maWRlcj9zc2xtb2RlPWRpc2FibGUnCiAgICAgIEpXVF9TRUNSRVQ6ICRTRVJWSUNFX1BBU1NXT1JEXzY0X0ZJREVSCiAgICAgIEVNQUlMX05PUkVQTFk6ICcke0VNQUlMX05PUkVQTFk6LW5vcmVwbHlAZXhhbXBsZS5jb219JwogICAgICBFTUFJTF9NQUlMR1VOX0FQSTogJEVNQUlMX01BSUxHVU5fQVBJCiAgICAgIEVNQUlMX01BSUxHVU5fRE9NQUlOOiAkRU1BSUxfTUFJTEdVTl9ET01BSU4KICAgICAgRU1BSUxfTUFJTEdVTl9SRUdJT046ICRFTUFJTF9NQUlMR1VOX1JFR0lPTgogICAgICBFTUFJTF9TTVRQX0hPU1Q6ICcke0VNQUlMX1NNVFBfSE9TVDotc210cC5tYWlsZ3VuLmNvbX0nCiAgICAgIEVNQUlMX1NNVFBfUE9SVDogJyR7RU1BSUxfU01UUF9QT1JUOi01ODd9JwogICAgICBFTUFJTF9TTVRQX1VTRVJOQU1FOiAnJHtFTUFJTF9TTVRQX1VTRVJOQU1FOi1wb3N0bWFzdGVyQG1haWxndW4uY29tfScKICAgICAgRU1BSUxfU01UUF9QQVNTV09SRDogJEVNQUlMX1NNVFBfUEFTU1dPUkQKICAgICAgRU1BSUxfU01UUF9FTkFCTEVfU1RBUlRUTFM6ICRFTUFJTF9TTVRQX0VOQUJMRV9TVEFSVFRMUwogICAgICBFTUFJTF9BV1NTRVNfUkVHSU9OOiAkRU1BSUxfQVdTU0VTX1JFR0lPTgogICAgICBFTUFJTF9BV1NTRVNfQUNDRVNTX0tFWV9JRDogJEVNQUlMX0FXU1NFU19BQ0NFU1NfS0VZX0lECiAgICAgIEVNQUlMX0FXU1NFU19TRUNSRVRfQUNDRVNTX0tFWTogJEVNQUlMX0FXU1NFU19TRUNSRVRfQUNDRVNTX0tFWQogIGRhdGFiYXNlOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxMicKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3BnX2RhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIFBPU1RHUkVTX1VTRVI6ICRTRVJWSUNFX1VTRVJfTVlTUUwKICAgICAgUE9TVEdSRVNfUEFTU1dPUkQ6ICRTRVJWSUNFX1BBU1NXT1JEX01ZU1FMCiAgICAgIFBPU1RHUkVTX0RCOiAnJHtQT1NUR1JFU19EQjotZmlkZXJ9Jwo=",
|
||||
"tags": [
|
||||
|
@ -4,7 +4,7 @@
|
||||
"version": "3.12.36"
|
||||
},
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.123"
|
||||
"version": "4.0.0-beta.124"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user