From 00a8c847e9f753f50faecb6a6be76ed55d623712 Mon Sep 17 00:00:00 2001 From: Joao Patricio Date: Wed, 3 May 2023 06:23:45 +0100 Subject: [PATCH] wip --- .gitignore | 3 + app/Data/ServerMetadata.php | 13 + app/Enums/ProxyTypes.php | 10 + app/Http/Controllers/ProjectController.php | 1 + app/Http/Controllers/ServerController.php | 16 + app/Http/Livewire/ActivityMonitor.php | 44 ++ app/Http/Livewire/Server/Proxy.php | 30 ++ app/Models/Server.php | 14 + composer.json | 2 + composer.lock | 423 +++++++++++++++++- ...2023_03_24_140711_create_servers_table.php | 1 + database/seeders/ServerSeeder.php | 9 + resources/views/home.blade.php | 2 +- .../views/livewire/activity-monitor.blade.php | 17 + .../views/livewire/server/proxy.blade.php | 30 ++ resources/views/server/show.blade.php | 5 + routes/web.php | 3 + 17 files changed, 621 insertions(+), 2 deletions(-) create mode 100644 app/Data/ServerMetadata.php create mode 100644 app/Enums/ProxyTypes.php create mode 100644 app/Http/Controllers/ServerController.php create mode 100644 app/Http/Livewire/ActivityMonitor.php create mode 100644 app/Http/Livewire/Server/Proxy.php create mode 100644 resources/views/livewire/activity-monitor.blade.php create mode 100644 resources/views/livewire/server/proxy.blade.php create mode 100644 resources/views/server/show.blade.php diff --git a/.gitignore b/.gitignore index 084a8d2f2..f24ddff6a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,9 @@ yarn-error.log /.bash_history /_volumes +# Temp while developing Proxy deployment +resources/recipes + .lesshst psysh_history .psql_history diff --git a/app/Data/ServerMetadata.php b/app/Data/ServerMetadata.php new file mode 100644 index 000000000..af4340b38 --- /dev/null +++ b/app/Data/ServerMetadata.php @@ -0,0 +1,13 @@ +route('home'); } + $activity = Activity::query() ->where('properties->type', '=', 'deployment') ->where('properties->uuid', '=', $deployment_uuid) diff --git a/app/Http/Controllers/ServerController.php b/app/Http/Controllers/ServerController.php new file mode 100644 index 000000000..b76acefa0 --- /dev/null +++ b/app/Http/Controllers/ServerController.php @@ -0,0 +1,16 @@ + $server, + ]); + } +} diff --git a/app/Http/Livewire/ActivityMonitor.php b/app/Http/Livewire/ActivityMonitor.php new file mode 100644 index 000000000..56d04d851 --- /dev/null +++ b/app/Http/Livewire/ActivityMonitor.php @@ -0,0 +1,44 @@ +activity = Activity::query() + ->find($this->activityId); + } + + public function newMonitorActivity($activityId) + { + $this->activityId = $activityId; + + $this->hydrateActivity(); + + $this->isPollingActive = true; + } + + public function polling() + { + $this->hydrateActivity(); + + if (data_get($this->activity, 'properties.exitCode') !== null) { + $this->isPollingActive = false; + } + } + + public function render() + { + return view('livewire.activity-monitor'); + } +} diff --git a/app/Http/Livewire/Server/Proxy.php b/app/Http/Livewire/Server/Proxy.php new file mode 100644 index 000000000..b01db728c --- /dev/null +++ b/app/Http/Livewire/Server/Proxy.php @@ -0,0 +1,30 @@ +server = $server; + } + + public function runInstallProxy() + { + $activity = remoteProcess(['ls -alh'], $this->server); + + $this->emit('newMonitorActivity', $activity->id); + } + + public function render() + { + return view('livewire.server.proxy'); + } +} diff --git a/app/Models/Server.php b/app/Models/Server.php index da302d056..1ea28ee86 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -2,6 +2,9 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Builder; +use Spatie\SchemalessAttributes\Casts\SchemalessAttributes; + class Server extends BaseModel { protected static function booted() @@ -12,10 +15,21 @@ protected static function booted() ]); }); } + + public $casts = [ + 'extra_attributes' => SchemalessAttributes::class, + ]; + + public function scopeWithExtraAttributes(): Builder + { + return $this->extra_attributes->modelScope(); + } + public function privateKey() { return $this->belongsTo(PrivateKey::class); } + public function settings() { return $this->hasOne(ServerSetting::class); diff --git a/composer.json b/composer.json index 3f4d36caf..a4bb8d943 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "license": "MIT", "require": { "php": "^8.2", + "doctrine/dbal": "^3.6", "guzzlehttp/guzzle": "^7.5.0", "laravel/fortify": "^v1.16.0", "laravel/framework": "^v10.7.1", @@ -16,6 +17,7 @@ "spatie/laravel-activitylog": "^4.7.3", "spatie/laravel-data": "^3.4.3", "spatie/laravel-ray": "^1.32.4", + "spatie/laravel-schemaless-attributes": "^2.4", "symfony/yaml": "^6.2", "visus/cuid2": "^2.0.0" }, diff --git a/composer.lock b/composer.lock index 449f2337e..0b3f0e779 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d7ed21949975efcb1891e098e4d2abfa", + "content-hash": "4d4a58970bcb8990e0fa643bef8c8243", "packages": [ { "name": "bacon/bacon-qr-code", @@ -241,6 +241,211 @@ }, "time": "2022-10-27T11:44:00+00:00" }, + { + "name": "doctrine/cache", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", + "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", + "shasum": "" + }, + "require": { + "php": "~7.1 || ^8.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "cache/integration-tests": "dev-master", + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "symfony/var-exporter": "^4.4 || ^5.4 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", + "homepage": "https://www.doctrine-project.org/projects/cache.html", + "keywords": [ + "abstraction", + "apcu", + "cache", + "caching", + "couchdb", + "memcached", + "php", + "redis", + "xcache" + ], + "support": { + "issues": "https://github.com/doctrine/cache/issues", + "source": "https://github.com/doctrine/cache/tree/2.2.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", + "type": "tidelift" + } + ], + "time": "2022-05-20T20:07:39+00:00" + }, + { + "name": "doctrine/dbal", + "version": "3.6.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "b4bd1cfbd2b916951696d82e57d054394d84864c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/b4bd1cfbd2b916951696d82e57d054394d84864c", + "reference": "b4bd1cfbd2b916951696d82e57d054394d84864c", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2", + "doctrine/cache": "^1.11|^2.0", + "doctrine/deprecations": "^0.5.3|^1", + "doctrine/event-manager": "^1|^2", + "php": "^7.4 || ^8.0", + "psr/cache": "^1|^2|^3", + "psr/log": "^1|^2|^3" + }, + "require-dev": { + "doctrine/coding-standard": "11.1.0", + "fig/log-test": "^1", + "jetbrains/phpstorm-stubs": "2022.3", + "phpstan/phpstan": "1.10.9", + "phpstan/phpstan-strict-rules": "^1.5", + "phpunit/phpunit": "9.6.6", + "psalm/plugin-phpunit": "0.18.4", + "squizlabs/php_codesniffer": "3.7.2", + "symfony/cache": "^5.4|^6.0", + "symfony/console": "^4.4|^5.4|^6.0", + "vimeo/psalm": "4.30.0" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "keywords": [ + "abstraction", + "database", + "db2", + "dbal", + "mariadb", + "mssql", + "mysql", + "oci8", + "oracle", + "pdo", + "pgsql", + "postgresql", + "queryobject", + "sasql", + "sql", + "sqlite", + "sqlserver", + "sqlsrv" + ], + "support": { + "issues": "https://github.com/doctrine/dbal/issues", + "source": "https://github.com/doctrine/dbal/tree/3.6.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal", + "type": "tidelift" + } + ], + "time": "2023-04-14T07:25:38+00:00" + }, { "name": "doctrine/deprecations", "version": "v1.0.0", @@ -284,6 +489,97 @@ }, "time": "2022-05-02T15:47:09+00:00" }, + { + "name": "doctrine/event-manager", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "conflict": { + "doctrine/common": "<2.9" + }, + "require-dev": { + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.8.8", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.28" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "event dispatcher", + "event manager", + "event system", + "events" + ], + "support": { + "issues": "https://github.com/doctrine/event-manager/issues", + "source": "https://github.com/doctrine/event-manager/tree/2.0.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", + "type": "tidelift" + } + ], + "time": "2022-10-12T20:59:15+00:00" + }, { "name": "doctrine/inflector", "version": "2.0.6", @@ -2960,6 +3256,55 @@ }, "time": "2022-06-13T21:57:56+00:00" }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" + }, { "name": "psr/clock", "version": "1.0.0", @@ -4054,6 +4399,82 @@ ], "time": "2023-03-23T08:04:54+00:00" }, + { + "name": "spatie/laravel-schemaless-attributes", + "version": "2.4.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-schemaless-attributes.git", + "reference": "ae19842763fe8d5a5059f8a7c0802bee6662b00c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-schemaless-attributes/zipball/ae19842763fe8d5a5059f8a7c0802bee6662b00c", + "reference": "ae19842763fe8d5a5059f8a7c0802bee6662b00c", + "shasum": "" + }, + "require": { + "illuminate/contracts": "^7.0|^8.0|^9.0|^10.0", + "illuminate/database": "^7.0|^8.0|^9.0|^10.0", + "illuminate/support": "^7.0|^8.0|^9.0|^10.0", + "php": "^8.0", + "spatie/laravel-package-tools": "^1.4.3" + }, + "require-dev": { + "brianium/paratest": "^6.2", + "mockery/mockery": "^1.4", + "nunomaduro/collision": "^5.3|^6.0", + "orchestra/testbench": "^6.15|^7.0|^8.0", + "pestphp/pest-plugin-laravel": "^1.3", + "phpunit/phpunit": "^9.5.4" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\SchemalessAttributes\\SchemalessAttributesServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\SchemalessAttributes\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Add schemaless attributes to Eloquent models", + "homepage": "https://github.com/spatie/laravel-schemaless-attributes", + "keywords": [ + "laravel-schemaless-attributes", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-schemaless-attributes/issues", + "source": "https://github.com/spatie/laravel-schemaless-attributes/tree/2.4.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2023-01-14T20:58:52+00:00" + }, { "name": "spatie/macroable", "version": "2.0.0", diff --git a/database/migrations/2023_03_24_140711_create_servers_table.php b/database/migrations/2023_03_24_140711_create_servers_table.php index ba62f7977..84e2ab6ba 100644 --- a/database/migrations/2023_03_24_140711_create_servers_table.php +++ b/database/migrations/2023_03_24_140711_create_servers_table.php @@ -21,6 +21,7 @@ public function up(): void $table->string('user')->default('root'); $table->foreignId('team_id'); $table->foreignId('private_key_id'); + $table->schemalessAttributes('extra_attributes'); $table->timestamps(); }); } diff --git a/database/seeders/ServerSeeder.php b/database/seeders/ServerSeeder.php index 32fc46613..ca551d1e2 100644 --- a/database/seeders/ServerSeeder.php +++ b/database/seeders/ServerSeeder.php @@ -2,6 +2,8 @@ namespace Database\Seeders; +use App\Data\ServerMetadata; +use App\Enums\ProxyTypes; use App\Models\PrivateKey; use App\Models\Server; use App\Models\Team; @@ -16,6 +18,7 @@ public function run(): void { $root_team = Team::find(0); $private_key_1 = PrivateKey::find(1); + Server::create([ 'id' => 1, 'name' => "testing-local-docker-container", @@ -23,6 +26,9 @@ public function run(): void 'ip' => "coolify-testing-host", 'team_id' => $root_team->id, 'private_key_id' => $private_key_1->id, + 'extra_attributes' => ServerMetadata::from([ + 'proxy' => ProxyTypes::TRAEFIK_V2->value + ]), ]); Server::create([ 'id' => 2, @@ -31,6 +37,9 @@ public function run(): void 'ip' => "coolify-testing-host-2", 'team_id' => $root_team->id, 'private_key_id' => $private_key_1->id, + 'extra_attributes' => ServerMetadata::from([ + // + ]), ]); } diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index cf6d4aaf7..09091fdea 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -1,7 +1,7 @@

Servers

@forelse ($servers as $server) - {{ data_get($server, 'name') }} + {{ data_get($server, 'name') }} @empty

No servers found.

@endforelse diff --git a/resources/views/livewire/activity-monitor.blade.php b/resources/views/livewire/activity-monitor.blade.php new file mode 100644 index 000000000..812095706 --- /dev/null +++ b/resources/views/livewire/activity-monitor.blade.php @@ -0,0 +1,17 @@ +
+ @isset($this->activity) + Activity: {{ $this->activity?->id }} + Status: {{ $this->activity?->properties->get('status') }} +
{{
+            \App\Actions\CoolifyTask\RunRemoteProcess::decodeOutput($this->activity)
+        }}
+ @else + Not monitoring any activity. + @endisset + +
diff --git a/resources/views/livewire/server/proxy.blade.php b/resources/views/livewire/server/proxy.blade.php new file mode 100644 index 000000000..91832611c --- /dev/null +++ b/resources/views/livewire/server/proxy.blade.php @@ -0,0 +1,30 @@ +
+

Proxy

+ + @if($this->server->extra_attributes->proxy) +
+
+ Proxy type: {{ $this->server->extra_attributes->proxy }} +
+
Features in W11.
+
    +
  • Edit config file
  • +
  • Enable dashboard (blocking port by firewall)
  • +
  • Dashboard access - login/password
  • +
  • Setup host for Traefik Dashboard
  • +
  • Visit (nav to traefik dashboard)
  • +
+
+ @else + No proxy installed. + + + @endif + + + +
diff --git a/resources/views/server/show.blade.php b/resources/views/server/show.blade.php new file mode 100644 index 000000000..9491ce149 --- /dev/null +++ b/resources/views/server/show.blade.php @@ -0,0 +1,5 @@ + +

{{ $server->name }}

+ + +
diff --git a/routes/web.php b/routes/web.php index 6aa837d2d..198a0bab5 100644 --- a/routes/web.php +++ b/routes/web.php @@ -2,6 +2,7 @@ use App\Http\Controllers\HomeController; use App\Http\Controllers\ProjectController; +use App\Http\Controllers\ServerController; use Illuminate\Support\Facades\Route; /* @@ -26,6 +27,8 @@ Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}', [ProjectController::class, 'application'])->name('project.application'); Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}/deployment/{deployment_uuid}', [ProjectController::class, 'deployment'])->name('project.deployment'); + Route::get('/server/{server:uuid}', [ServerController::class, 'show'])->name('server.show'); + // Route::get('/database/{database_uuid}', [ProjectController::class, 'database'])->name('project.database'); // Route::get('//service/{service_uuid}', [ProjectController::class, 'service'])->name('project.service');