From e8a0bd37f428cc6b48982b4db8f4d6e250327f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Tremblay=20Lefran=C3=A7ois?= Date: Tue, 26 Nov 2024 13:47:50 -0500 Subject: [PATCH 01/12] added plex logo --- public/svgs/plex.svg | 1 + 1 file changed, 1 insertion(+) create mode 100644 public/svgs/plex.svg diff --git a/public/svgs/plex.svg b/public/svgs/plex.svg new file mode 100644 index 000000000..872b135cf --- /dev/null +++ b/public/svgs/plex.svg @@ -0,0 +1 @@ + \ No newline at end of file From c10de805fa9ae9e6f5a56eda4f0baaf4642744bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Tremblay=20Lefran=C3=A7ois?= Date: Tue, 26 Nov 2024 13:47:58 -0500 Subject: [PATCH 02/12] first try adding ple --- templates/compose/plex.yaml | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 templates/compose/plex.yaml diff --git a/templates/compose/plex.yaml b/templates/compose/plex.yaml new file mode 100644 index 000000000..740b10c66 --- /dev/null +++ b/templates/compose/plex.yaml @@ -0,0 +1,39 @@ +# documentation: https://github.com/plexinc/pms-docker +# slogan: Plex combines free movies & TV with the best free streaming services, so there’s always more to discover. +# tags: media, server, movies, tv, music +# logo: svgs/plex.svg +# port: 32400 + +services: + plex: + image: lscr.io/linuxserver/plex:latest + ports: + - 32400:32400 + - 1900:1900/udp + - 5353:5353/udp + - 8324:8324 + - 32410:32410/udp + - 32412:32412/udp + - 32413:32413/udp + - 32414:32414/udp + - 32469:32469 + environment: + - SERVICE_FQDN_PLEX + - _APP_URL=$SERVICE_FQDN_PLEX + - SERVICE_FQDN_PLEX_32400 + - PUID=1000 + - PGID=1000 + - TZ=Europe/Madrid + - VERSION=latest + - PLEX_CLAIM=${PLEX_CLAIM} + devices: + - "/dev/dri:/dev/dri" + volumes: + - plex-config:/config + - plex-tvshows:/data/tvshows + - plex-movies:/data/movies + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:32400"] + interval: 2s + timeout: 10s + retries: 15 From 63b8dacd064d12fdd9879eb5182c7c555358902a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Tremblay=20Lefran=C3=A7ois?= Date: Tue, 26 Nov 2024 14:37:21 -0500 Subject: [PATCH 03/12] working config with claim token --- templates/compose/plex.yaml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/templates/compose/plex.yaml b/templates/compose/plex.yaml index 740b10c66..23df694bc 100644 --- a/templates/compose/plex.yaml +++ b/templates/compose/plex.yaml @@ -6,7 +6,7 @@ services: plex: - image: lscr.io/linuxserver/plex:latest + image: plexinc/pms-docker:latest ports: - 32400:32400 - 1900:1900/udp @@ -18,13 +18,11 @@ services: - 32414:32414/udp - 32469:32469 environment: - - SERVICE_FQDN_PLEX - - _APP_URL=$SERVICE_FQDN_PLEX - SERVICE_FQDN_PLEX_32400 + - _APP_URL=$SERVICE_FQDN_PLEX - PUID=1000 - PGID=1000 - - TZ=Europe/Madrid - - VERSION=latest + - TZ=${TZ:-America/Toronto} - PLEX_CLAIM=${PLEX_CLAIM} devices: - "/dev/dri:/dev/dri" @@ -33,7 +31,7 @@ services: - plex-tvshows:/data/tvshows - plex-movies:/data/movies healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:32400"] + test: ["CMD", "curl", "-f", "http://localhost:32400/identity"] interval: 2s timeout: 10s retries: 15 From b08a1ef3f188d797efcb28db55b50a344068a615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Tremblay=20Lefran=C3=A7ois?= Date: Wed, 27 Nov 2024 08:42:02 -0500 Subject: [PATCH 04/12] removed optional ports --- templates/compose/plex.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/templates/compose/plex.yaml b/templates/compose/plex.yaml index 23df694bc..8d55ed5bc 100644 --- a/templates/compose/plex.yaml +++ b/templates/compose/plex.yaml @@ -7,16 +7,6 @@ services: plex: image: plexinc/pms-docker:latest - ports: - - 32400:32400 - - 1900:1900/udp - - 5353:5353/udp - - 8324:8324 - - 32410:32410/udp - - 32412:32412/udp - - 32413:32413/udp - - 32414:32414/udp - - 32469:32469 environment: - SERVICE_FQDN_PLEX_32400 - _APP_URL=$SERVICE_FQDN_PLEX From 2a9d9830a3f0c33ac0c51ecdb0edefc34fe76e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Tremblay=20Lefran=C3=A7ois?= Date: Mon, 2 Dec 2024 07:37:07 -0500 Subject: [PATCH 05/12] commented out devices section --- templates/compose/plex.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/compose/plex.yaml b/templates/compose/plex.yaml index 8d55ed5bc..0bc6e0334 100644 --- a/templates/compose/plex.yaml +++ b/templates/compose/plex.yaml @@ -14,8 +14,8 @@ services: - PGID=1000 - TZ=${TZ:-America/Toronto} - PLEX_CLAIM=${PLEX_CLAIM} - devices: - - "/dev/dri:/dev/dri" + #devices: + # - "/dev/dri:/dev/dri" volumes: - plex-config:/config - plex-tvshows:/data/tvshows From 60a723beb65c355150d6278b9593b7a7c19b558a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Tremblay=20Lefran=C3=A7ois?= Date: Mon, 2 Dec 2024 08:22:01 -0500 Subject: [PATCH 06/12] changed to linuxserver base image and updated doc stirng --- templates/compose/plex.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/compose/plex.yaml b/templates/compose/plex.yaml index 0bc6e0334..9ffa15224 100644 --- a/templates/compose/plex.yaml +++ b/templates/compose/plex.yaml @@ -1,12 +1,12 @@ -# documentation: https://github.com/plexinc/pms-docker -# slogan: Plex combines free movies & TV with the best free streaming services, so there’s always more to discover. +# documentation: https://docs.linuxserver.io/images/docker-plex/ +# slogan: Plex organizes video, music and photos from personal media libraries and streams them to smart TVs, streaming boxes and mobile devices. # tags: media, server, movies, tv, music # logo: svgs/plex.svg # port: 32400 services: plex: - image: plexinc/pms-docker:latest + image: lscr.io/linuxserver/plex:latest environment: - SERVICE_FQDN_PLEX_32400 - _APP_URL=$SERVICE_FQDN_PLEX @@ -18,8 +18,8 @@ services: # - "/dev/dri:/dev/dri" volumes: - plex-config:/config - - plex-tvshows:/data/tvshows - - plex-movies:/data/movies + - plex-tv:/tv + - plex-movies:/movies healthcheck: test: ["CMD", "curl", "-f", "http://localhost:32400/identity"] interval: 2s From 74311f4feb482b370c945923e049e2aa4fe68ee9 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 3 Dec 2024 15:39:24 +0100 Subject: [PATCH 07/12] Refactor string concatenation and update function signatures for improved readability and null handling in shared helper functions --- bootstrap/helpers/shared.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index d64b5ab6e..a3ef93dfc 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -90,8 +90,11 @@ function metrics_dir(): string return base_configuration_dir().'/metrics'; } -function sanitize_string(string $input): string +function sanitize_string(?string $input = null): ?string { + if (is_null($input)) { + return null; + } // Remove any HTML/PHP tags $sanitized = strip_tags($input); From 21f8d8b492d996d985e8b15adf552600cc2ee743 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:54:29 +0100 Subject: [PATCH 08/12] Update service-templates.json --- templates/service-templates.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/templates/service-templates.json b/templates/service-templates.json index 222ca1601..1532c1609 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -2170,6 +2170,21 @@ "logo": "svgs/plane.svg", "minversion": "0.0.0" }, + "plex": { + "documentation": "https://docs.linuxserver.io/images/docker-plex/?utm_source=coolify.io", + "slogan": "Plex organizes video, music and photos from personal media libraries and streams them to smart TVs, streaming boxes and mobile devices.", + "compose": "c2VydmljZXM6CiAgcGxleDoKICAgIGltYWdlOiAnbHNjci5pby9saW51eHNlcnZlci9wbGV4OmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9QTEVYXzMyNDAwCiAgICAgIC0gX0FQUF9VUkw9JFNFUlZJQ0VfRlFETl9QTEVYCiAgICAgIC0gUFVJRD0xMDAwCiAgICAgIC0gUEdJRD0xMDAwCiAgICAgIC0gJ1RaPSR7VFo6LUFtZXJpY2EvVG9yb250b30nCiAgICAgIC0gJ1BMRVhfQ0xBSU09JHtQTEVYX0NMQUlNfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3BsZXgtY29uZmlnOi9jb25maWcnCiAgICAgIC0gJ3BsZXgtdHY6L3R2JwogICAgICAtICdwbGV4LW1vdmllczovbW92aWVzJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vbG9jYWxob3N0OjMyNDAwL2lkZW50aXR5JwogICAgICBpbnRlcnZhbDogMnMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDE1Cg==", + "tags": [ + "media", + "server", + "movies", + "tv", + "music" + ], + "logo": "svgs/plex.svg", + "minversion": "0.0.0", + "port": "32400" + }, "plunk": { "documentation": "https://docs.useplunk.com/getting-started/introduction?utm_source=coolify.io", "slogan": "Plunk, The Open-Source Email Platform for AWS", From 26ba433fd3f4371fd971f57cfb41b001a364fa45 Mon Sep 17 00:00:00 2001 From: Jeremy Angele Date: Tue, 3 Dec 2024 22:24:36 +0100 Subject: [PATCH 09/12] Use computed property for timezones --- app/Livewire/Server/Show.php | 15 ++++++++++----- resources/views/livewire/server/show.blade.php | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/Livewire/Server/Show.php b/app/Livewire/Server/Show.php index a5544489d..ac5211c1b 100644 --- a/app/Livewire/Server/Show.php +++ b/app/Livewire/Server/Show.php @@ -5,7 +5,7 @@ namespace App\Livewire\Server; use App\Actions\Server\StartSentinel; use App\Actions\Server\StopSentinel; use App\Models\Server; -use Livewire\Attributes\Locked; +use Livewire\Attributes\Computed; use Livewire\Attributes\Validate; use Livewire\Component; @@ -79,9 +79,6 @@ class Show extends Component #[Validate(['required'])] public string $serverTimezone; - #[Locked] - public array $timezones; - public function getListeners() { $teamId = auth()->user()->currentTeam()->id; @@ -96,13 +93,21 @@ class Show extends Component { try { $this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); - $this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray(); $this->syncData(); } catch (\Throwable $e) { return handleError($e, $this); } } + #[Computed] + public function timezones(): array + { + return collect(timezone_identifiers_list()) + ->sort() + ->values() + ->toArray(); + } + public function syncData(bool $toModel = false) { if ($toModel) { diff --git a/resources/views/livewire/server/show.blade.php b/resources/views/livewire/server/show.blade.php index 5aed0b4e2..0d1d5e681 100644 --- a/resources/views/livewire/server/show.blade.php +++ b/resources/views/livewire/server/show.blade.php @@ -88,7 +88,7 @@
Date: Wed, 4 Dec 2024 12:43:52 +0100 Subject: [PATCH 12/12] test: setup database for upcoming tests --- app/Models/Application.php | 3 +- app/Models/Server.php | 3 +- config/database.php | 16 ++++ database/factories/ApplicationFactory.php | 22 ++++++ database/factories/ServerFactory.php | 17 ++++ phpunit.xml | 4 +- tests/Feature/ExecuteContainerCommandTest.php | 57 ++++++++++++++ tests/Traits/HandlesTestDatabase.php | 78 +++++++++++++++++++ 8 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 database/factories/ApplicationFactory.php create mode 100644 database/factories/ServerFactory.php create mode 100644 tests/Feature/ExecuteContainerCommandTest.php create mode 100644 tests/Traits/HandlesTestDatabase.php diff --git a/app/Models/Application.php b/app/Models/Application.php index c284528f1..a68c1d54a 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -4,6 +4,7 @@ namespace App\Models; use App\Enums\ApplicationDeploymentStatus; use Illuminate\Database\Eloquent\Casts\Attribute; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Process\InvokedProcess; @@ -104,7 +105,7 @@ use Visus\Cuid2\Cuid2; class Application extends BaseModel { - use SoftDeletes; + use HasFactory, SoftDeletes; private static $parserVersion = '4'; diff --git a/app/Models/Server.php b/app/Models/Server.php index 83b91b254..e0a66c58b 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -11,6 +11,7 @@ use App\Notifications\Server\Reachable; use App\Notifications\Server\Unreachable; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\Attribute; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; @@ -48,7 +49,7 @@ use Symfony\Component\Yaml\Yaml; class Server extends BaseModel { - use SchemalessAttributesTrait, SoftDeletes; + use HasFactory, SchemalessAttributesTrait, SoftDeletes; public static $batch_counter = 0; diff --git a/config/database.php b/config/database.php index f48a68082..6f4acbfd2 100644 --- a/config/database.php +++ b/config/database.php @@ -49,6 +49,22 @@ return [ 'search_path' => 'public', 'sslmode' => 'prefer', ], + + 'testing' => [ + 'driver' => 'pgsql', + 'url' => env('DATABASE_TEST_URL'), + 'host' => env('DB_TEST_HOST', 'postgres'), + 'port' => env('DB_TEST_PORT', '5432'), + 'database' => env('DB_TEST_DATABASE', 'coolify_test'), + 'username' => env('DB_TEST_USERNAME', 'coolify'), + 'password' => env('DB_TEST_PASSWORD', 'password'), + 'charset' => 'utf8', + 'prefix' => '', + 'prefix_indexes' => true, + 'search_path' => 'public', + 'sslmode' => 'prefer', + ], + ], /* diff --git a/database/factories/ApplicationFactory.php b/database/factories/ApplicationFactory.php new file mode 100644 index 000000000..ded507c56 --- /dev/null +++ b/database/factories/ApplicationFactory.php @@ -0,0 +1,22 @@ + fake()->unique()->name(), + 'destination_id' => 1, + 'git_repository' => fake()->url(), + 'git_branch' => fake()->word(), + 'build_pack' => 'nixpacks', + 'ports_exposes' => '3000', + 'environment_id' => 1, + 'destination_id' => 1, + ]; + } +} diff --git a/database/factories/ServerFactory.php b/database/factories/ServerFactory.php new file mode 100644 index 000000000..29546bf56 --- /dev/null +++ b/database/factories/ServerFactory.php @@ -0,0 +1,17 @@ + fake()->unique()->name(), + 'ip' => fake()->unique()->ipv4(), + 'private_key_id' => 1, + ]; + } +} diff --git a/phpunit.xml b/phpunit.xml index 45cb69439..f1c2be92d 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -13,8 +13,8 @@ - - + + diff --git a/tests/Feature/ExecuteContainerCommandTest.php b/tests/Feature/ExecuteContainerCommandTest.php new file mode 100644 index 000000000..6d485fe65 --- /dev/null +++ b/tests/Feature/ExecuteContainerCommandTest.php @@ -0,0 +1,57 @@ +shouldSetUpDatabase()) { + $this->setUpTestDatabase(); + } + // Create test data + $this->user = User::factory()->create(); + $this->team = $this->user->teams()->first(); + $this->server = Server::factory()->create(['team_id' => $this->team->id]); + $this->application = Application::factory()->create(); + + // Login the user + $this->actingAs($this->user); + } + + protected function tearDown(): void + { + if ($this->shouldSetUpDatabase()) { + $this->tearDownTestDatabase(); + } + parent::tearDown(); + } + + private function shouldSetUpDatabase(): bool + { + return in_array($this->name(), [ + 'it_allows_valid_container_access', + 'it_prevents_cross_server_container_access', + ]); + } +} diff --git a/tests/Traits/HandlesTestDatabase.php b/tests/Traits/HandlesTestDatabase.php new file mode 100644 index 000000000..adb577e7c --- /dev/null +++ b/tests/Traits/HandlesTestDatabase.php @@ -0,0 +1,78 @@ +createTestDatabase($database); + + // Run migrations + Artisan::call('migrate:fresh', [ + '--database' => 'testing', + '--seed' => false, + ]); + } catch (\Exception $e) { + $this->tearDownTestDatabase(); + throw $e; + } + } + + protected function tearDownTestDatabase(): void + { + try { + // Drop test database + $database = config('database.connections.testing.database'); + $this->dropTestDatabase($database); + } catch (\Exception $e) { + // Log error but don't throw + error_log('Failed to tear down test database: '.$e->getMessage()); + } + } + + protected function createTestDatabase($database) + { + try { + // Connect to postgres database to create/drop test database + config(['database.connections.pgsql.database' => 'postgres']); + DB::purge('pgsql'); + DB::reconnect('pgsql'); + + // Drop if exists and create new database + DB::connection('pgsql')->statement("DROP DATABASE IF EXISTS $database WITH (FORCE);"); + DB::connection('pgsql')->statement("CREATE DATABASE $database;"); + + // Switch back to testing connection + DB::disconnect('pgsql'); + DB::reconnect('testing'); + } catch (\Exception $e) { + $this->tearDownTestDatabase(); + throw new \Exception('Could not create test database: '.$e->getMessage()); + } + } + + protected function dropTestDatabase($database) + { + try { + // Connect to postgres database to drop test database + config(['database.connections.pgsql.database' => 'postgres']); + DB::purge('pgsql'); + DB::reconnect('pgsql'); + + // Drop the test database + DB::connection('pgsql')->statement("DROP DATABASE IF EXISTS $database WITH (FORCE);"); + + DB::disconnect('pgsql'); + } catch (\Exception $e) { + // Log error but don't throw + error_log('Failed to drop test database: '.$e->getMessage()); + } + } +}