2023-04-19 10:42:15 +00:00
< ? php
2023-12-07 18:06:32 +00:00
namespace App\Livewire\Project\Application ;
2023-04-19 10:42:15 +00:00
use App\Models\Application ;
2023-09-20 13:42:41 +00:00
use Illuminate\Support\Collection ;
2023-05-16 13:41:23 +00:00
use Illuminate\Support\Str ;
2023-11-13 08:04:19 +00:00
use Livewire\Component ;
2023-11-24 14:48:23 +00:00
use Visus\Cuid2\Cuid2 ;
2023-04-19 10:42:15 +00:00
class General extends Component
{
public string $applicationId ;
public Application $application ;
2023-09-20 13:42:41 +00:00
public Collection $services ;
2023-04-19 10:42:15 +00:00
public string $name ;
2023-10-09 09:10:04 +00:00
public ? string $fqdn = null ;
2023-04-19 10:42:15 +00:00
public string $git_repository ;
public string $git_branch ;
2023-10-09 09:10:04 +00:00
public ? string $git_commit_sha = null ;
2023-04-19 10:42:15 +00:00
public string $build_pack ;
2023-10-20 10:34:25 +00:00
public ? string $ports_exposes = null ;
2023-04-19 10:42:15 +00:00
2023-10-18 08:32:08 +00:00
public $customLabels ;
public bool $labelsChanged = false ;
2023-10-18 09:20:40 +00:00
public bool $isConfigurationChanged = false ;
2023-10-18 08:32:08 +00:00
2023-11-27 10:54:55 +00:00
public ? string $initialDockerComposeLocation = null ;
2023-11-27 14:50:22 +00:00
public ? string $initialDockerComposePrLocation = null ;
2023-11-27 10:54:55 +00:00
2023-11-24 14:48:23 +00:00
public $parsedServices = [];
public $parsedServiceDomains = [];
2023-11-20 10:35:31 +00:00
protected $listeners = [
'resetDefaultLabels'
];
2023-04-19 10:42:15 +00:00
protected $rules = [
2023-07-06 12:37:14 +00:00
'application.name' => 'required' ,
2023-08-07 16:46:40 +00:00
'application.description' => 'nullable' ,
2023-04-19 10:42:15 +00:00
'application.fqdn' => 'nullable' ,
'application.git_repository' => 'required' ,
'application.git_branch' => 'required' ,
'application.git_commit_sha' => 'nullable' ,
2023-05-05 07:02:50 +00:00
'application.install_command' => 'nullable' ,
'application.build_command' => 'nullable' ,
'application.start_command' => 'nullable' ,
2023-04-19 10:42:15 +00:00
'application.build_pack' => 'required' ,
2023-04-25 13:48:45 +00:00
'application.static_image' => 'required' ,
2023-04-19 10:42:15 +00:00
'application.base_directory' => 'required' ,
'application.publish_directory' => 'nullable' ,
2023-04-25 12:43:35 +00:00
'application.ports_exposes' => 'required' ,
'application.ports_mappings' => 'nullable' ,
2023-08-11 20:41:47 +00:00
'application.dockerfile' => 'nullable' ,
2023-10-10 09:16:38 +00:00
'application.docker_registry_image_name' => 'nullable' ,
'application.docker_registry_image_tag' => 'nullable' ,
2023-10-10 12:02:43 +00:00
'application.dockerfile_location' => 'nullable' ,
2023-11-24 14:48:23 +00:00
'application.docker_compose_location' => 'nullable' ,
2023-11-27 14:50:22 +00:00
'application.docker_compose_pr_location' => 'nullable' ,
2023-11-24 14:48:23 +00:00
'application.docker_compose' => 'nullable' ,
2023-11-28 09:11:53 +00:00
'application.docker_compose_pr' => 'nullable' ,
2023-11-24 14:48:23 +00:00
'application.docker_compose_raw' => 'nullable' ,
2023-11-28 09:11:53 +00:00
'application.docker_compose_pr_raw' => 'nullable' ,
2023-11-07 12:49:15 +00:00
'application.dockerfile_target_build' => 'nullable' ,
2023-12-17 19:56:12 +00:00
'application.docker_compose_custom_start_command' => 'nullable' ,
'application.docker_compose_custom_build_command' => 'nullable' ,
2024-01-29 15:07:00 +00:00
'application.custom_labels' => 'nullable' ,
'application.custom_docker_run_options' => 'nullable' ,
'application.settings.is_static' => 'boolean|required' ,
2024-01-02 12:55:35 +00:00
'application.settings.is_raw_compose_deployment_enabled' => 'boolean|required' ,
2024-01-18 10:40:13 +00:00
'application.settings.is_build_server_enabled' => 'boolean|required' ,
2023-04-19 10:42:15 +00:00
];
2023-06-16 10:35:40 +00:00
protected $validationAttributes = [
'application.name' => 'name' ,
2023-08-07 16:46:40 +00:00
'application.description' => 'description' ,
2023-06-16 10:35:40 +00:00
'application.fqdn' => 'FQDN' ,
'application.git_repository' => 'Git repository' ,
'application.git_branch' => 'Git branch' ,
'application.git_commit_sha' => 'Git commit SHA' ,
'application.install_command' => 'Install command' ,
'application.build_command' => 'Build command' ,
'application.start_command' => 'Start command' ,
'application.build_pack' => 'Build pack' ,
'application.static_image' => 'Static image' ,
'application.base_directory' => 'Base directory' ,
'application.publish_directory' => 'Publish directory' ,
'application.ports_exposes' => 'Ports exposes' ,
'application.ports_mappings' => 'Ports mappings' ,
2023-08-11 20:41:47 +00:00
'application.dockerfile' => 'Dockerfile' ,
2023-10-10 09:16:38 +00:00
'application.docker_registry_image_name' => 'Docker registry image name' ,
'application.docker_registry_image_tag' => 'Docker registry image tag' ,
2023-10-10 12:02:43 +00:00
'application.dockerfile_location' => 'Dockerfile location' ,
2023-11-24 14:48:23 +00:00
'application.docker_compose_location' => 'Docker compose location' ,
2023-11-27 14:50:22 +00:00
'application.docker_compose_pr_location' => 'Docker compose location' ,
2023-11-24 14:48:23 +00:00
'application.docker_compose' => 'Docker compose' ,
2023-11-28 09:11:53 +00:00
'application.docker_compose_pr' => 'Docker compose' ,
2023-11-24 14:48:23 +00:00
'application.docker_compose_raw' => 'Docker compose raw' ,
2023-11-28 09:11:53 +00:00
'application.docker_compose_pr_raw' => 'Docker compose raw' ,
2023-10-18 08:32:08 +00:00
'application.custom_labels' => 'Custom labels' ,
2023-11-07 12:49:15 +00:00
'application.dockerfile_target_build' => 'Dockerfile target build' ,
2024-01-29 15:07:00 +00:00
'application.custom_docker_run_options' => 'Custom docker run commands' ,
2023-12-17 19:56:12 +00:00
'application.docker_compose_custom_start_command' => 'Docker compose custom start command' ,
'application.docker_compose_custom_build_command' => 'Docker compose custom build command' ,
2024-01-29 15:07:00 +00:00
'application.settings.is_static' => 'Is static' ,
2024-01-02 12:55:35 +00:00
'application.settings.is_raw_compose_deployment_enabled' => 'Is raw compose deployment enabled' ,
2024-01-18 10:40:13 +00:00
'application.settings.is_build_server_enabled' => 'Is build server enabled' ,
2023-06-16 10:35:40 +00:00
];
2023-10-18 08:32:08 +00:00
public function mount ()
{
2023-11-24 14:48:23 +00:00
try {
$this -> parsedServices = $this -> application -> parseCompose ();
} catch ( \Throwable $e ) {
2023-12-07 18:06:32 +00:00
$this -> dispatch ( 'error' , $e -> getMessage ());
2023-11-24 14:48:23 +00:00
}
$this -> parsedServiceDomains = $this -> application -> docker_compose_domains ? json_decode ( $this -> application -> docker_compose_domains , true ) : [];
2023-10-20 10:34:25 +00:00
$this -> ports_exposes = $this -> application -> ports_exposes ;
2023-10-18 09:26:01 +00:00
if ( str ( $this -> application -> status ) -> startsWith ( 'running' ) && is_null ( $this -> application -> config_hash )) {
$this -> application -> isConfigurationChanged ( true );
}
2023-10-18 09:20:40 +00:00
$this -> isConfigurationChanged = $this -> application -> isConfigurationChanged ();
2023-12-18 13:01:25 +00:00
$this -> customLabels = $this -> application -> parseContainerLabels ();
2024-01-02 16:22:44 +00:00
if ( ! $this -> customLabels && $this -> application -> destination -> server -> proxyType () === 'TRAEFIK_V2' ) {
2024-01-15 11:30:49 +00:00
$this -> customLabels = str ( implode ( " | " , generateLabelsApplication ( $this -> application ))) -> replace ( " | " , " \n " );
2024-01-02 16:14:52 +00:00
$this -> application -> custom_labels = base64_encode ( $this -> customLabels );
$this -> application -> save ();
2024-01-02 15:44:41 +00:00
}
2023-11-27 10:54:55 +00:00
$this -> initialDockerComposeLocation = $this -> application -> docker_compose_location ;
2023-10-18 08:32:08 +00:00
}
2023-11-20 10:35:31 +00:00
public function instantSave ()
{
$this -> application -> settings -> save ();
2023-12-07 18:06:32 +00:00
$this -> dispatch ( 'success' , 'Settings saved.' );
2023-12-06 20:32:23 +00:00
$this -> application -> refresh ();
if ( $this -> ports_exposes !== $this -> application -> ports_exposes ) {
$this -> resetDefaultLabels ( false );
}
2023-11-20 10:35:31 +00:00
}
2023-11-24 14:48:23 +00:00
public function loadComposeFile ( $isInit = false )
{
2023-11-27 10:54:55 +00:00
try {
if ( $isInit && $this -> application -> docker_compose_raw ) {
return ;
}
2023-11-27 14:50:22 +00:00
[ 'parsedServices' => $this -> parsedServices , 'initialDockerComposeLocation' => $this -> initialDockerComposeLocation , 'initialDockerComposePrLocation' => $this -> initialDockerComposePrLocation ] = $this -> application -> loadComposeFile ( $isInit );
2023-12-07 18:06:32 +00:00
$this -> dispatch ( 'success' , 'Docker compose file loaded.' );
2023-11-27 10:54:55 +00:00
} catch ( \Throwable $e ) {
$this -> application -> docker_compose_location = $this -> initialDockerComposeLocation ;
2023-11-27 14:50:22 +00:00
$this -> application -> docker_compose_pr_location = $this -> initialDockerComposePrLocation ;
2023-11-27 10:54:55 +00:00
$this -> application -> save ();
return handleError ( $e , $this );
2023-11-24 14:48:23 +00:00
}
2023-11-27 10:54:55 +00:00
}
public function generateDomain ( string $serviceName )
{
$domain = $this -> parsedServiceDomains [ $serviceName ][ 'domain' ] ? ? null ;
if ( ! $domain ) {
$uuid = new Cuid2 ( 7 );
$domain = generateFqdn ( $this -> application -> destination -> server , $uuid );
$this -> parsedServiceDomains [ $serviceName ][ 'domain' ] = $domain ;
$this -> application -> docker_compose_domains = json_encode ( $this -> parsedServiceDomains );
2023-11-24 14:48:23 +00:00
$this -> application -> save ();
}
2023-11-27 10:54:55 +00:00
return $domain ;
2023-11-24 14:48:23 +00:00
}
2023-10-18 08:32:08 +00:00
public function updatedApplicationBuildPack ()
{
2023-10-13 19:08:59 +00:00
if ( $this -> application -> build_pack !== 'nixpacks' ) {
2023-12-06 20:32:23 +00:00
$this -> application -> settings -> is_static = false ;
2023-10-13 19:08:59 +00:00
$this -> application -> settings -> save ();
2024-01-10 10:00:06 +00:00
} else {
$this -> application -> ports_exposes = $this -> ports_exposes = 3000 ;
$this -> resetDefaultLabels ( false );
2023-10-13 19:08:59 +00:00
}
2023-11-27 14:25:15 +00:00
if ( $this -> application -> build_pack === 'dockercompose' ) {
$this -> application -> fqdn = null ;
$this -> application -> settings -> save ();
}
2024-01-10 09:58:31 +00:00
if ( $this -> application -> build_pack === 'static' ) {
$this -> application -> ports_exposes = $this -> ports_exposes = 80 ;
$this -> resetDefaultLabels ( false );
}
2023-10-11 10:12:25 +00:00
$this -> submit ();
2024-01-10 10:07:53 +00:00
$this -> dispatch ( 'build_pack_updated' );
2023-10-11 10:12:25 +00:00
}
2023-10-18 08:32:08 +00:00
public function getWildcardDomain ()
{
2023-09-30 13:39:40 +00:00
$server = data_get ( $this -> application , 'destination.server' );
if ( $server ) {
$fqdn = generateFqdn ( $server , $this -> application -> uuid );
$this -> application -> fqdn = $fqdn ;
$this -> application -> save ();
2023-11-06 08:27:00 +00:00
$this -> updatedApplicationFqdn ();
2023-09-30 13:39:40 +00:00
}
}
2023-10-18 08:32:08 +00:00
public function resetDefaultLabels ( $showToaster = true )
2023-04-19 10:42:15 +00:00
{
2024-01-15 11:30:49 +00:00
$this -> customLabels = str ( implode ( " | " , generateLabelsApplication ( $this -> application ))) -> replace ( " | " , " \n " );
2023-10-20 10:34:25 +00:00
$this -> ports_exposes = $this -> application -> ports_exposes ;
2023-10-18 08:32:08 +00:00
$this -> submit ( $showToaster );
2023-04-19 10:42:15 +00:00
}
2023-08-08 09:51:36 +00:00
2023-10-18 08:32:08 +00:00
public function updatedApplicationFqdn ()
{
$this -> resetDefaultLabels ( false );
2024-01-15 09:03:15 +00:00
// $this->dispatch('success', 'Labels reset to default!');
2023-10-18 08:32:08 +00:00
}
public function submit ( $showToaster = true )
2023-04-19 10:42:15 +00:00
{
2023-05-16 13:27:47 +00:00
try {
2024-01-02 16:22:44 +00:00
if ( ! $this -> customLabels && $this -> application -> destination -> server -> proxyType () === 'TRAEFIK_V2' ) {
2024-01-15 11:30:49 +00:00
$this -> customLabels = str ( implode ( " | " , generateLabelsApplication ( $this -> application ))) -> replace ( " | " , " \n " );
2024-01-02 16:14:52 +00:00
$this -> application -> custom_labels = base64_encode ( $this -> customLabels );
$this -> application -> save ();
}
2023-12-17 19:56:12 +00:00
if ( $this -> application -> build_pack === 'dockercompose' && $this -> initialDockerComposeLocation !== $this -> application -> docker_compose_location ) {
2023-11-27 10:54:55 +00:00
$this -> loadComposeFile ();
}
2023-09-20 13:42:41 +00:00
$this -> validate ();
2023-10-20 10:34:25 +00:00
if ( $this -> ports_exposes !== $this -> application -> ports_exposes ) {
$this -> resetDefaultLabels ( false );
}
2023-10-18 08:32:08 +00:00
if ( data_get ( $this -> application , 'build_pack' ) === 'dockerimage' ) {
2023-10-11 10:10:40 +00:00
$this -> validate ([
'application.docker_registry_image_name' => 'required' ,
'application.docker_registry_image_tag' => 'required' ,
]);
}
2023-09-19 13:51:13 +00:00
if ( data_get ( $this -> application , 'fqdn' )) {
2024-01-15 09:03:15 +00:00
$this -> application -> fqdn = str ( $this -> application -> fqdn ) -> replaceEnd ( ',' , '' ) -> trim ();
$domains = str ( $this -> application -> fqdn ) -> trim () -> explode ( ',' ) -> map ( function ( $domain ) {
return str ( $domain ) -> trim () -> lower ();
2023-08-27 12:55:57 +00:00
});
2024-01-15 09:03:15 +00:00
$domains = $domains -> unique ();
2024-02-07 13:59:33 +00:00
if ( $this -> application -> additional_servers -> count () === 0 ) {
foreach ( $domains as $domain ) {
if ( ! validate_dns_entry ( $domain , $this -> application -> destination -> server )) {
2024-02-15 10:55:43 +00:00
$showToaster && $this -> dispatch ( 'error' , " Validating DNS ( $domain ) failed. " , " Make sure you have added the DNS records correctly.<br><br>Check this <a target='_blank' class='text-white underline' href='https://coolify.io/docs/dns-settings'>documentation</a> for further help. " );
2024-02-07 13:59:33 +00:00
}
2024-01-15 09:03:15 +00:00
}
}
2024-01-30 08:22:34 +00:00
check_fqdn_usage ( $this -> application );
2023-08-27 12:55:57 +00:00
$this -> application -> fqdn = $domains -> implode ( ',' );
}
2023-12-07 18:06:32 +00:00
2024-01-29 15:07:00 +00:00
if ( data_get ( $this -> application , 'custom_docker_run_options' )) {
$this -> application -> custom_docker_run_options = str ( $this -> application -> custom_docker_run_options ) -> trim ();
}
2023-09-19 13:51:13 +00:00
if ( data_get ( $this -> application , 'dockerfile' )) {
2023-08-21 16:00:12 +00:00
$port = get_port_from_dockerfile ( $this -> application -> dockerfile );
2023-10-02 07:08:33 +00:00
if ( $port && ! $this -> application -> ports_exposes ) {
2023-08-21 16:00:12 +00:00
$this -> application -> ports_exposes = $port ;
}
2023-08-11 20:41:47 +00:00
}
2023-07-07 12:56:20 +00:00
if ( $this -> application -> base_directory && $this -> application -> base_directory !== '/' ) {
$this -> application -> base_directory = rtrim ( $this -> application -> base_directory , '/' );
}
if ( $this -> application -> publish_directory && $this -> application -> publish_directory !== '/' ) {
$this -> application -> publish_directory = rtrim ( $this -> application -> publish_directory , '/' );
}
2023-11-28 10:10:48 +00:00
if ( $this -> application -> build_pack === 'dockercompose' ) {
$this -> application -> docker_compose_domains = json_encode ( $this -> parsedServiceDomains );
$this -> parsedServices = $this -> application -> parseCompose ();
}
2023-12-12 15:34:05 +00:00
$this -> application -> custom_labels = base64_encode ( $this -> customLabels );
2023-05-16 13:27:47 +00:00
$this -> application -> save ();
2023-12-07 18:06:32 +00:00
$showToaster && $this -> dispatch ( 'success' , 'Application settings updated!' );
2023-09-11 15:36:30 +00:00
} catch ( \Throwable $e ) {
2023-09-15 13:34:25 +00:00
return handleError ( $e , $this );
2023-10-18 08:32:08 +00:00
} finally {
2023-10-18 09:20:40 +00:00
$this -> isConfigurationChanged = $this -> application -> isConfigurationChanged ();
2023-05-16 13:27:47 +00:00
}
2023-04-19 10:42:15 +00:00
}
}