From 34c57509509d469cf1d76a783ca1cdea4dd68ea1 Mon Sep 17 00:00:00 2001 From: Saeed Vaziry <61919774+saeedvaziry@users.noreply.github.com> Date: Sun, 17 Nov 2024 10:58:09 +0100 Subject: [PATCH] load linode regions and plans dynamically (#367) --- app/ServerProviders/AWS.php | 7 +- app/ServerProviders/Hetzner.php | 1 - app/ServerProviders/Linode.php | 115 +++++++++++++++++++++----------- lang/en.json | 2 +- 4 files changed, 82 insertions(+), 43 deletions(-) diff --git a/app/ServerProviders/AWS.php b/app/ServerProviders/AWS.php index 27f2168..48c2f4f 100755 --- a/app/ServerProviders/AWS.php +++ b/app/ServerProviders/AWS.php @@ -107,7 +107,12 @@ public function plans(?string $region): array return collect($plans) ->mapWithKeys(fn ($value) => [ - $value['InstanceType'] => $value['InstanceType'].' - '.$value['VCpuInfo']['DefaultVCpus'].' vCPUs, '.$value['MemoryInfo']['SizeInMiB'].' MB RAM', + $value['InstanceType'] => __('server_providers.plan', [ + 'name' => $value['InstanceType'], + 'cpu' => $value['VCpuInfo']['DefaultVCpus'] ?? 'N/A', + 'memory' => $value['MemoryInfo']['SizeInMiB'] ?? 'N/A', + 'disk' => $value['InstanceStorageInfo']['TotalSizeInGB'] ?? 'N/A', + ]), ]) ->toArray(); } diff --git a/app/ServerProviders/Hetzner.php b/app/ServerProviders/Hetzner.php index c7851c3..4c08a98 100644 --- a/app/ServerProviders/Hetzner.php +++ b/app/ServerProviders/Hetzner.php @@ -76,7 +76,6 @@ public function plans(?string $region): array $value['name'] => __('server_providers.plan', [ 'name' => $value['name'], 'cpu' => $value['cores'], - 'architecture' => $value['architecture'], 'memory' => $value['memory'], 'disk' => $value['disk'], ]), diff --git a/app/ServerProviders/Linode.php b/app/ServerProviders/Linode.php index 79e0ca0..2c0fde0 100644 --- a/app/ServerProviders/Linode.php +++ b/app/ServerProviders/Linode.php @@ -6,6 +6,7 @@ use App\Exceptions\ServerProviderError; use App\Facades\Notifier; use App\Notifications\FailedToDeleteServerFromProvider; +use Exception; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; @@ -13,23 +14,12 @@ class Linode extends AbstractProvider { protected string $apiUrl = 'https://api.linode.com/v4'; - public function createRules($input): array + public function createRules(array $input): array { - $rules = []; - // plans - $plans = []; - foreach (config('serverproviders.linode.plans') as $plan) { - $plans[] = $plan['value']; - } - $rules['plan'] = 'required|in:'.implode(',', $plans); - // regions - $regions = []; - foreach (config('serverproviders.linode.regions') as $region) { - $regions[] = $region['value']; - } - $rules['region'] = 'required|in:'.implode(',', $regions); - - return $rules; + return [ + 'plan' => 'required', + 'region' => 'required', + ]; } public function credentialValidationRules($input): array @@ -59,7 +49,12 @@ public function data(array $input): array */ public function connect(?array $credentials = null): bool { - $connect = Http::withToken($credentials['token'])->get($this->apiUrl.'/account'); + try { + $connect = Http::withToken($credentials['token'])->get($this->apiUrl.'/account'); + } catch (Exception) { + throw new CouldNotConnectToProvider('Linode'); + } + if (! $connect->ok()) { throw new CouldNotConnectToProvider('Linode'); } @@ -69,16 +64,41 @@ public function connect(?array $credentials = null): bool public function plans(?string $region): array { - return collect(config('serverproviders.linode.plans')) - ->mapWithKeys(fn ($value) => [$value['value'] => $value['title']]) - ->toArray(); + try { + $plans = Http::withToken($this->serverProvider->credentials['token']) + ->get($this->apiUrl.'/linode/types') + ->json(); + + return collect($plans['data']) + ->mapWithKeys(function ($value) { + return [ + $value['id'] => __('server_providers.plan', [ + 'name' => $value['label'], + 'cpu' => $value['vcpus'], + 'memory' => $value['memory'], + 'disk' => $value['disk'], + ]), + ]; + }) + ->toArray(); + } catch (Exception) { + return []; + } } public function regions(): array { - return collect(config('serverproviders.linode.regions')) - ->mapWithKeys(fn ($value) => [$value['value'] => $value['title']]) - ->toArray(); + try { + $regions = Http::withToken($this->serverProvider->credentials['token']) + ->get($this->apiUrl.'/regions') + ->json(); + + return collect($regions['data']) + ->mapWithKeys(fn ($value) => [$value['id'] => $value['label']]) + ->toArray(); + } catch (Exception) { + return []; + } } /** @@ -88,19 +108,24 @@ public function create(): void { $this->generateKeyPair(); - $create = Http::withToken($this->server->serverProvider->credentials['token']) - ->post($this->apiUrl.'/linode/instances', [ - 'backups_enabled' => false, - 'image' => config('serverproviders.linode.images')[$this->server->os], - 'root_pass' => $this->server->authentication['root_pass'], - 'authorized_keys' => [ - $this->server->sshKey()['public_key'], - ], - 'booted' => true, - 'label' => str($this->server->name)->slug(), - 'type' => $this->server->provider_data['plan'], - 'region' => $this->server->provider_data['region'], - ]); + try { + $create = Http::withToken($this->server->serverProvider->credentials['token']) + ->post($this->apiUrl.'/linode/instances', [ + 'backups_enabled' => false, + 'image' => config('serverproviders.linode.images')[$this->server->os], + 'root_pass' => $this->server->authentication['root_pass'], + 'authorized_keys' => [ + $this->server->sshKey()['public_key'], + ], + 'booted' => true, + 'label' => str($this->server->name)->slug(), + 'type' => $this->server->provider_data['plan'], + 'region' => $this->server->provider_data['region'], + ]); + } catch (Exception) { + throw new ServerProviderError('Failed to create server on Linode'); + } + if (! $create->ok()) { $msg = __('Failed to create server on Linode'); $errors = $create->json('errors'); @@ -119,8 +144,12 @@ public function create(): void public function isRunning(): bool { - $status = Http::withToken($this->server->serverProvider->credentials['token']) - ->get($this->apiUrl.'/linode/instances/'.$this->server->provider_data['linode_id']); + try { + $status = Http::withToken($this->server->serverProvider->credentials['token']) + ->get($this->apiUrl.'/linode/instances/'.$this->server->provider_data['linode_id']); + } catch (Exception) { + return false; + } if (! $status->ok()) { return false; @@ -132,8 +161,14 @@ public function isRunning(): bool public function delete(): void { if (isset($this->server->provider_data['linode_id'])) { - $delete = Http::withToken($this->server->serverProvider->credentials['token']) - ->delete($this->apiUrl.'/linode/instances/'.$this->server->provider_data['linode_id']); + try { + $delete = Http::withToken($this->server->serverProvider->credentials['token']) + ->delete($this->apiUrl.'/linode/instances/'.$this->server->provider_data['linode_id']); + } catch (Exception) { + Notifier::send($this->server, new FailedToDeleteServerFromProvider($this->server)); + + return; + } if (! $delete->ok()) { Notifier::send($this->server, new FailedToDeleteServerFromProvider($this->server)); diff --git a/lang/en.json b/lang/en.json index 1c51746..8c8e9f1 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1,5 +1,5 @@ { "servers.create.public_key_text": "mkdir -p /root/.ssh && touch /root/.ssh/authorized_keys && echo ':public_key' >> /root/.ssh/authorized_keys", "servers.create.public_key_warning": "Your server needs to have a new unused installation of supported operating systems and must have a root user. To get started, add our public key to /root/.ssh/authorized_keys file by running the bellow command on your server as root.", - "server_providers.plan": ":name - :cpu Cores(:architecture) - :memory - :disk Disk" + "server_providers.plan": ":name - :cpu Cores - :memory Memory - :disk Disk" }