Hetzner Service, DTOs, provision script

This commit is contained in:
2025-03-28 13:56:07 +00:00
parent 891079fd99
commit d21250ce66
9 changed files with 296 additions and 5 deletions

View File

@@ -0,0 +1,13 @@
<?php
namespace App\Data\ServerProviders;
class Image
{
public function __construct(
public string $id,
public string $name,
public string $osFlavor,
public string $osVersion,
) {}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace App\Data\ServerProviders;
class Location
{
public function __construct(
public string $id,
public string $name,
public string $country,
public string $city,
) {}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Data\ServerProviders;
class ServerType
{
/**
* @param string $name The name of the server type
* @param int $cores The number of cores
* @param int $memory The amount of memory in MB
* @param int $disk The amount of disk space in GB
*/
public function __construct(
public string $id,
public string $name,
public int $cores,
public int $memory,
public int $disk,
public float $priceMonthly,
public float $priceHourly,
) {}
}

View File

@@ -4,6 +4,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Service extends Model
{
@@ -13,4 +14,9 @@ class Service extends Model
{
return $this->belongsTo(Server::class);
}
public function slices(): HasMany
{
return $this->hasMany(Slice::class);
}
}

View File

@@ -3,8 +3,12 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Slice extends Model
{
//
public function service(): BelongsTo
{
return $this->belongsTo(Service::class);
}
}

View File

@@ -0,0 +1,89 @@
<?php
namespace App\Services\ServerProviders;
use App\Data\ServerProviders\Image;
use App\Data\ServerProviders\Location;
use App\Data\ServerProviders\ServerType;
use App\Http\Integrations\Connectors\HetznerConnector;
use App\Http\Integrations\Requests\Hetzner\Images\ListImagesRequest;
use App\Http\Integrations\Requests\Hetzner\Locations\ListLocationsRequest;
use App\Http\Integrations\Requests\Hetzner\ServerTypes\ListServerTypesRequest;
use Exception;
use Illuminate\Support\Collection;
class HetznerService implements ServerProviderService
{
public function __construct()
{
$this->connector = new HetznerConnector;
}
public function createServer(
string $name,
string $serverType,
string $location,
string $image,
): bool {
return false;
}
public function listServerTypes(): Collection
{
$response = $this->connector->send(new ListServerTypesRequest);
if ($response->status() !== 200) {
throw new Exception('Failed to fetch server types from Hetzner');
}
return collect($response->json('server_types'))->where('deprecated', false)->where('architecture', 'x86')->map(function ($serverType) {
return new ServerType(
id: $serverType['id'],
name: $serverType['name'],
cores: $serverType['cores'],
memory: $serverType['memory'] * 1024,
disk: $serverType['disk'],
priceMonthly: $serverType['prices'][0]['monthly']['gross'] ?? 0,
priceHourly: $serverType['prices'][0]['hourly']['gross'] ?? 0,
);
});
}
public function listLocations(): Collection
{
$response = $this->connector->send(new ListLocationsRequest);
if ($response->status() !== 200) {
throw new Exception('Failed to fetch locations from Hetzner');
}
return collect($response->json('locations'))->map(function ($location) {
return new Location(
id: $location['id'],
name: $location['name'],
country: $location['country'],
city: $location['city'],
);
});
}
public function listImages(): Collection
{
$response = $this->connector->send(new ListImagesRequest(
architecture: 'x86',
));
if ($response->status() !== 200) {
throw new Exception('Failed to fetch images from Hetzner');
}
return collect($response->json('images'))->where('os_flavor', 'ubuntu')->map(function ($image) {
return new Image(
id: $image['id'],
name: $image['description'],
osFlavor: $image['os_flavor'],
osVersion: $image['os_version'],
);
});
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Services\ServerProviders;
use Illuminate\Support\Collection;
use Saloon\Http\Connector;
interface ServerProviderService
{
protected Connector $connector;
public function createServer(
string $name,
string $serverType,
string $location,
string $image,
): bool;
public function listServerTypes(): Collection;
public function listLocations(): Collection;
public function listImages(): Collection;
}