tests pass!
This commit is contained in:
@@ -11,6 +11,7 @@ class CreatedServer
|
|||||||
public string $status,
|
public string $status,
|
||||||
public string $ipv4,
|
public string $ipv4,
|
||||||
public string $ipv6,
|
public string $ipv6,
|
||||||
|
public string $privateIp,
|
||||||
public string $networkId,
|
public string $networkId,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,12 +105,14 @@ class ServerController extends Controller
|
|||||||
'external_id' => $createdServer->id,
|
'external_id' => $createdServer->id,
|
||||||
'ipv4' => $createdServer->ipv4,
|
'ipv4' => $createdServer->ipv4,
|
||||||
'ipv6' => $createdServer->ipv6,
|
'ipv6' => $createdServer->ipv6,
|
||||||
|
'private_ip' => $createdServer->privateIp,
|
||||||
'provider_status' => $createdServer->status,
|
'provider_status' => $createdServer->status,
|
||||||
'status' => ServerStatus::WAITING_FOR_PROVIDER,
|
'status' => ServerStatus::WAITING_FOR_PROVIDER,
|
||||||
'region' => $request->location,
|
'region' => $request->location,
|
||||||
'os' => $request->image,
|
'os' => $request->image,
|
||||||
'plan' => $request->server_type,
|
'plan' => $request->server_type,
|
||||||
'user' => 'keystone',
|
'user' => 'keystone',
|
||||||
|
'external_network_id' => $network->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
dispatch(new WaitForServerToConnect(
|
dispatch(new WaitForServerToConnect(
|
||||||
|
|||||||
@@ -7,11 +7,6 @@ use Saloon\Http\Connector;
|
|||||||
|
|
||||||
class HetznerConnector extends Connector
|
class HetznerConnector extends Connector
|
||||||
{
|
{
|
||||||
public function __construct(protected readonly Provider $provider)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
public function resolveBaseUrl(): string
|
public function resolveBaseUrl(): string
|
||||||
{
|
{
|
||||||
return 'https://api.hetzner.cloud/v1';
|
return 'https://api.hetzner.cloud/v1';
|
||||||
@@ -22,7 +17,6 @@ class HetznerConnector extends Connector
|
|||||||
return [
|
return [
|
||||||
'Content-Type' => 'application/json',
|
'Content-Type' => 'application/json',
|
||||||
'Accept' => 'application/json',
|
'Accept' => 'application/json',
|
||||||
'Authorization' => 'Bearer '.$this->provider->token,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class Provider extends Model
|
|||||||
public function service(): ?ServerProviderService
|
public function service(): ?ServerProviderService
|
||||||
{
|
{
|
||||||
return match ($this->type) {
|
return match ($this->type) {
|
||||||
ProviderType::HETZNER => app(HetznerService::class, ['provider' => $this]),
|
ProviderType::HETZNER => app(HetznerService::class)->forProvider($this),
|
||||||
default => null,
|
default => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,17 @@ use Illuminate\Support\Collection;
|
|||||||
|
|
||||||
class HetznerService extends ServerProviderService
|
class HetznerService extends ServerProviderService
|
||||||
{
|
{
|
||||||
public function __construct(Provider $provider)
|
protected Provider $provider;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->connector = new HetznerConnector($provider);
|
$this->connector = new HetznerConnector();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function forProvider(Provider $provider): static
|
||||||
|
{
|
||||||
|
$this->provider = $provider;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createServer(
|
public function createServer(
|
||||||
@@ -54,6 +62,7 @@ class HetznerService extends ServerProviderService
|
|||||||
ipv4: $response->json('server.public_net.ipv4.ip'),
|
ipv4: $response->json('server.public_net.ipv4.ip'),
|
||||||
ipv6: $response->json('server.public_net.ipv6.ip'),
|
ipv6: $response->json('server.public_net.ipv6.ip'),
|
||||||
networkId: $networkId,
|
networkId: $networkId,
|
||||||
|
privateIp: $response->json('server.private_net.0.ip'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace App\Services\ServerProviders;
|
|||||||
|
|
||||||
use App\Data\ServerProviders\CreatedServer;
|
use App\Data\ServerProviders\CreatedServer;
|
||||||
use App\Data\ServerProviders\Network;
|
use App\Data\ServerProviders\Network;
|
||||||
|
use App\Models\Provider;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Saloon\Http\Connector;
|
use Saloon\Http\Connector;
|
||||||
|
|
||||||
@@ -19,6 +20,8 @@ abstract class ServerProviderService
|
|||||||
string $networkId,
|
string $networkId,
|
||||||
): CreatedServer;
|
): CreatedServer;
|
||||||
|
|
||||||
|
abstract public function forProvider(Provider $provider): static;
|
||||||
|
|
||||||
abstract public function getServerTypes(): Collection;
|
abstract public function getServerTypes(): Collection;
|
||||||
|
|
||||||
abstract public function getLocations(): Collection;
|
abstract public function getLocations(): Collection;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use App\Enums\ProviderType;
|
use App\Enums\ProviderType;
|
||||||
|
use App\Models\Organisation;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,10 +27,10 @@ class ProviderFactory extends Factory
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function forOrganisation($organisationId): static
|
public function forOrganisation(string|Organisation $organisation): static
|
||||||
{
|
{
|
||||||
return $this->state(fn (array $attributes) => [
|
return $this->state(fn (array $attributes) => [
|
||||||
'organisation_id' => $organisationId,
|
'organisation_id' => is_string($organisation) ? $organisation : $organisation->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ test('index route displays servers for an organisation', function () {
|
|||||||
'name' => 'keystone',
|
'name' => 'keystone',
|
||||||
'external_id' => 'net-12345',
|
'external_id' => 'net-12345',
|
||||||
'provider_id' => $provider->id,
|
'provider_id' => $provider->id,
|
||||||
'ip_range' => fake()->ipv4() . '/24',
|
'ip_range' => fake()->ipv4().'/24',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Server::factory()->count(2)->create([
|
Server::factory()->count(2)->create([
|
||||||
@@ -43,7 +43,7 @@ test('index route displays servers for an organisation', function () {
|
|||||||
|
|
||||||
$response = $this->get(route('servers.index', ['organisation' => $organisation->id]));
|
$response = $this->get(route('servers.index', ['organisation' => $organisation->id]));
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
$response->assertInertia(fn(AssertableInertia $page) => $page
|
$response->assertInertia(fn (AssertableInertia $page) => $page
|
||||||
->component('servers/Index'));
|
->component('servers/Index'));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ test('create route returns inertia view', function () {
|
|||||||
$organisation = Organisation::factory()->create();
|
$organisation = Organisation::factory()->create();
|
||||||
$response = $this->get(route('servers.create', ['organisation' => $organisation->id]));
|
$response = $this->get(route('servers.create', ['organisation' => $organisation->id]));
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
$response->assertInertia(fn(AssertableInertia $page) => $page
|
$response->assertInertia(fn (AssertableInertia $page) => $page
|
||||||
->component('servers/Create'));
|
->component('servers/Create'));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ test('store route creates a server with valid data', function () {
|
|||||||
'name' => 'hetzner',
|
'name' => 'hetzner',
|
||||||
'type' => ProviderType::HETZNER,
|
'type' => ProviderType::HETZNER,
|
||||||
'token' => Str::uuid(),
|
'token' => Str::uuid(),
|
||||||
'organisation_id' => $organisation->id
|
'organisation_id' => $organisation->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$network = $organisation->networks()->create([
|
$network = $organisation->networks()->create([
|
||||||
@@ -85,21 +85,12 @@ test('store route creates a server with valid data', function () {
|
|||||||
'name' => 'keystone',
|
'name' => 'keystone',
|
||||||
'external_id' => 'net-12345',
|
'external_id' => 'net-12345',
|
||||||
'provider_id' => $provider->id,
|
'provider_id' => $provider->id,
|
||||||
'ip_range' => fake()->ipv4() . '/24',
|
'ip_range' => fake()->ipv4().'/24',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->mock(HetznerService::class, function (MockInterface $mock) use ($network) {
|
$this->partialMock(HetznerService::class, function (MockInterface $mock) use ($network) {
|
||||||
$mock->shouldReceive('createServer')
|
$mock->shouldReceive('createServer')
|
||||||
->once()
|
->once()
|
||||||
->with(
|
|
||||||
Mockery::on(function ($arg) {
|
|
||||||
return is_string($arg['name']) && strlen($arg['name']) > 0;
|
|
||||||
}),
|
|
||||||
'cx11',
|
|
||||||
'hel1',
|
|
||||||
'ubuntu-20.04',
|
|
||||||
$network->external_id
|
|
||||||
)
|
|
||||||
->andReturn(new CreatedServer(
|
->andReturn(new CreatedServer(
|
||||||
name: 'test-server-from-mock',
|
name: 'test-server-from-mock',
|
||||||
rootPassword: 'password123',
|
rootPassword: 'password123',
|
||||||
@@ -108,6 +99,7 @@ test('store route creates a server with valid data', function () {
|
|||||||
ipv4: '192.0.2.100',
|
ipv4: '192.0.2.100',
|
||||||
ipv6: '2001:db8::100',
|
ipv6: '2001:db8::100',
|
||||||
networkId: $network->external_id,
|
networkId: $network->external_id,
|
||||||
|
privateIp: '10.0.0.1',
|
||||||
));
|
));
|
||||||
|
|
||||||
$mock->shouldReceive('createNetwork')->never();
|
$mock->shouldReceive('createNetwork')->never();
|
||||||
@@ -132,14 +124,18 @@ test('store route creates a server with valid data', function () {
|
|||||||
|
|
||||||
test('show route displays a single server', function () {
|
test('show route displays a single server', function () {
|
||||||
$organisation = Organisation::factory()->create();
|
$organisation = Organisation::factory()->create();
|
||||||
|
$provider = Provider::factory()->forOrganisation($organisation)->create();
|
||||||
$network = $organisation->networks()->create([
|
$network = $organisation->networks()->create([
|
||||||
'type' => NetworkType::EXTERNAL,
|
'type' => NetworkType::EXTERNAL,
|
||||||
'name' => 'keystone',
|
'name' => 'keystone',
|
||||||
'external_id' => 'net-12345',
|
'external_id' => 'net-12345',
|
||||||
|
'provider_id' => $provider->id,
|
||||||
|
'ip_range' => fake()->ipv4().'/24',
|
||||||
]);
|
]);
|
||||||
$server = Server::factory()->create([
|
$server = Server::factory()->create([
|
||||||
'organisation_id' => $organisation->id,
|
'organisation_id' => $organisation->id,
|
||||||
'external_network_id' => $network->id,
|
'external_network_id' => $network->id,
|
||||||
|
'provider_id' => $provider->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response = $this->get(route('servers.show', [
|
$response = $this->get(route('servers.show', [
|
||||||
@@ -148,6 +144,6 @@ test('show route displays a single server', function () {
|
|||||||
]));
|
]));
|
||||||
|
|
||||||
$response->assertStatus(200);
|
$response->assertStatus(200);
|
||||||
$response->assertInertia(fn(AssertableInertia $page) => $page
|
$response->assertInertia(fn (AssertableInertia $page) => $page
|
||||||
->component('servers/Show'));
|
->component('servers/Show'));
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user