Add endpoints

This commit is contained in:
Lance Pioch 2024-06-15 05:14:54 -04:00
parent 30051ab0d7
commit 4cba1540ac
6 changed files with 102 additions and 21 deletions

View File

@ -0,0 +1,41 @@
<?php
namespace App\Casts;
use App\Models\Objects\Endpoint;
use Illuminate\Contracts\Database\Eloquent\Castable;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Support\Collection;
use Stringable;
use TypeError;
class EndpointCollection implements Castable
{
public static function castUsing(array $arguments)
{
return new class() implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
if (! isset($attributes[$key])) {
return new Collection();
}
$data = json_decode($attributes[$key], true);
return (new Collection($data))->map(function ($value) {
return new Endpoint($value);
});
}
public function set($model, $key, $value, $attributes)
{
if (!$value instanceof Collection) {
return new Collection();
}
return $value->map(fn ($endpoint) => (string) $endpoint);
}
};
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Livewire;
use App\Models\Objects\Endpoint;
use Livewire\Mechanisms\HandleComponents\Synthesizers\Synth;
class EndpointSynth extends Synth
{
public static $key = 'endpoint';
public static function match($target)
{
return $target instanceof Endpoint;
}
public function dehydrate($target)
{
return (string) $target;
}
public function hydrate($value)
{
return new Endpoint($value);
}
}

View File

@ -12,28 +12,30 @@ class Endpoint
public const PORT_CEIL = 65535;
public const PORT_RANGE_LIMIT = 1000;
public const PORT_RANGE_REGEX = '/^(\d{4,5})-(\d{4,5})$/';
public const INADDR_ANY = '0.0.0.0';
public int $port;
public string $ip;
public function __construct(string $address = null, int $port = null) {
if ($address === null) {
$address = '0.0.0.0';
public function __construct(string|int $port, string $ip = null) {
$this->ip = $ip ?? self::INADDR_ANY;
$this->port = (int) $port;
if (str_contains($port, ':')) {
[$this->ip, $this->port] = explode(':', $port);
}
$ip = $address;
if (str_contains($address, ':')) {
[$ip, $port] = explode(':', $address);
throw_unless(filter_var($this->ip, FILTER_VALIDATE_IP) !== false, new InvalidArgumentException("$this->ip is an invalid IP address"));
throw_unless($this->port > self::PORT_FLOOR, "Port $this->port must be greater than " . self::PORT_FLOOR);
throw_unless($this->port < self::PORT_CEIL, "Port $this->port must be less than " . self::PORT_CEIL);
}
throw_unless(is_numeric($port), new InvalidArgumentException("Port ($port) must be a number"));
$port = (int) $port;
public function __toString()
{
if ($this->ip === self::INADDR_ANY) {
return (string) $this->port;
}
throw_unless(is_int($port), new InvalidArgumentException("Port ($port) must be an integer"));
throw_unless(filter_var($ip, FILTER_VALIDATE_IP) !== false, new InvalidArgumentException("$ip is an invalid IP address"));
$this->ip = $ip;
$this->port = $port;
return "$this->ip:$this->port";
}
}

View File

@ -2,8 +2,10 @@
namespace App\Models;
use App\Casts\EndpointCollection;
use App\Enums\ServerState;
use App\Exceptions\Http\Connection\DaemonConnectionException;
use App\Models\Objects\Endpoint;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Notifications\Notifiable;
@ -67,7 +69,6 @@ class Server extends Model
'database_limit' => 'present|nullable|integer|min:0',
'allocation_limit' => 'sometimes|nullable|integer|min:0',
'backup_limit' => 'present|nullable|integer|min:0',
'ports' => 'array',
];
protected function casts(): array
@ -90,7 +91,7 @@ class Server extends Model
'deleted_at' => 'datetime',
'installed_at' => 'datetime',
'docker_labels' => 'array',
'ports' => 'array',
'ports' => EndpointCollection::class,
];
}
@ -309,9 +310,16 @@ class Server extends Model
return cache()->get("servers.$this->uuid.container.status") ?? 'missing';
}
public function getPrimaryEndpoint()
public function getPrimaryEndpoint(): ?Endpoint
{
dd($this->ports);
dd($this->variables);
$endpoint = $this->ports->first();
$portEggVariable = $this->variables->firstWhere('env_variable', 'SERVER_PORT');
if ($portEggVariable) {
$portServerVariable = $this->serverVariables->firstWhere('variable_id', $portEggVariable->id);
$endpoint = new Endpoint($portServerVariable->variable_value);
}
return $endpoint;
}
}

View File

@ -3,6 +3,7 @@
namespace App\Providers;
use App\Extensions\Themes\Theme;
use App\Livewire\EndpointSynth;
use App\Models;
use App\Models\ApiKey;
use App\Models\Node;
@ -21,6 +22,7 @@ use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
use Laravel\Sanctum\Sanctum;
use Livewire\Livewire;
class AppServiceProvider extends ServiceProvider
{
@ -72,6 +74,8 @@ class AppServiceProvider extends ServiceProvider
$this->bootAuth();
$this->bootBroadcast();
Livewire::propertySynthesizer(EndpointSynth::class);
$bearerTokens = fn (OpenApi $openApi) => $openApi->secure(SecurityScheme::http('bearer'));
Gate::define('viewApiDocs', fn () => true);
Scramble::registerApi('application', ['api_path' => 'api/application', 'info' => ['version' => '1.0']]);

View File

@ -2,6 +2,7 @@
namespace App\Services\Servers;
use App\Models\Objects\Endpoint;
use App\Models\Server;
class StartupCommandService
@ -13,9 +14,8 @@ class StartupCommandService
{
$endpoint = $server->getPrimaryEndpoint();
$find = ['{{SERVER_MEMORY}}', '{{SERVER_IP}}', '{{SERVER_PORT}}'];
$replace = [$server->memory, $server->allocation->ip, $server->allocation->port];
$replace = [$server->memory, $endpoint->ip ?? Endpoint::INADDR_ANY, $endpoint->port ?? ''];
foreach ($server->variables as $variable) {
$find[] = '{{' . $variable->env_variable . '}}';