mirror of
https://github.com/vitodeploy/vito.git
synced 2025-04-20 10:21:37 +00:00
load AWS regions and plans dynamically via SDK (#366)
This commit is contained in:
parent
deb0b328e3
commit
cc79aa9fbf
@ -15,7 +15,6 @@
|
|||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Database\Query\Builder;
|
use Illuminate\Database\Query\Builder;
|
||||||
use Illuminate\Support\Facades\Bus;
|
use Illuminate\Support\Facades\Bus;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
@ -45,7 +44,6 @@ public function create(User $creator, Project $project, array $input): Server
|
|||||||
'progress_step' => 'Initializing',
|
'progress_step' => 'Initializing',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
DB::beginTransaction();
|
|
||||||
try {
|
try {
|
||||||
if ($server->provider != 'custom') {
|
if ($server->provider != 'custom') {
|
||||||
$server->provider_id = $input['server_provider'];
|
$server->provider_id = $input['server_provider'];
|
||||||
@ -70,12 +68,10 @@ public function create(User $creator, Project $project, array $input): Server
|
|||||||
// install server
|
// install server
|
||||||
$this->install($server);
|
$this->install($server);
|
||||||
|
|
||||||
DB::commit();
|
|
||||||
|
|
||||||
return $server;
|
return $server;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$server->provider()->delete();
|
$server->delete();
|
||||||
DB::rollBack();
|
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'provider' => $e->getMessage(),
|
'provider' => $e->getMessage(),
|
||||||
]);
|
]);
|
||||||
|
@ -79,6 +79,7 @@ public static function regions(?int $id): array
|
|||||||
if (! $id) {
|
if (! $id) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
/** @var ?ServerProvider $profile */
|
||||||
$profile = self::find($id);
|
$profile = self::find($id);
|
||||||
if (! $profile) {
|
if (! $profile) {
|
||||||
return [];
|
return [];
|
||||||
@ -109,7 +110,7 @@ public static function plans(?int $id, ?string $region): array
|
|||||||
}
|
}
|
||||||
|
|
||||||
$plans = $profile->provider()->plans($region);
|
$plans = $profile->provider()->plans($region);
|
||||||
Cache::put('plans-'.$id.'-'.$region, $plans, 600);
|
Cache::put('plans-'.$id.'-'.$region, $plans, 60);
|
||||||
|
|
||||||
return $plans;
|
return $plans;
|
||||||
}
|
}
|
||||||
|
@ -20,21 +20,10 @@ class AWS extends AbstractProvider
|
|||||||
|
|
||||||
public function createRules(array $input): array
|
public function createRules(array $input): array
|
||||||
{
|
{
|
||||||
$rules = [];
|
return [
|
||||||
// plans
|
'plan' => ['required'],
|
||||||
$plans = [];
|
'region' => ['required'],
|
||||||
foreach (config('serverproviders.aws.plans') as $plan) {
|
];
|
||||||
$plans[] = $plan['value'];
|
|
||||||
}
|
|
||||||
$rules['plan'] = 'required|in:'.implode(',', $plans);
|
|
||||||
// regions
|
|
||||||
$regions = [];
|
|
||||||
foreach (config('serverproviders.aws.regions') as $region) {
|
|
||||||
$regions[] = $region['value'];
|
|
||||||
}
|
|
||||||
$rules['region'] = 'required|in:'.implode(',', $regions);
|
|
||||||
|
|
||||||
return $rules;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function credentialValidationRules(array $input): array
|
public function credentialValidationRules(array $input): array
|
||||||
@ -78,18 +67,65 @@ public function connect(?array $credentials = null): bool
|
|||||||
|
|
||||||
public function plans(?string $region): array
|
public function plans(?string $region): array
|
||||||
{
|
{
|
||||||
return collect(config('serverproviders.aws.plans'))
|
$this->connectToEc2Client($region);
|
||||||
->mapWithKeys(fn ($value) => [$value['value'] => $value['title']])
|
|
||||||
|
$nextToken = null;
|
||||||
|
$plans = [];
|
||||||
|
|
||||||
|
do {
|
||||||
|
$params = [
|
||||||
|
'Filters' => [
|
||||||
|
[
|
||||||
|
'Name' => 'processor-info.supported-architecture',
|
||||||
|
'Values' => ['x86_64', 'arm64'], // Include both x86_64 and ARM64
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Name' => 'current-generation',
|
||||||
|
'Values' => ['true'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Name' => 'supported-virtualization-type',
|
||||||
|
'Values' => ['hvm'], // Ubuntu AMIs require HVM
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Name' => 'bare-metal',
|
||||||
|
'Values' => ['false'], // Skip bare-metal unless explicitly needed
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($nextToken) {
|
||||||
|
$params['NextToken'] = $nextToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $this->ec2Client->describeInstanceTypes($params);
|
||||||
|
|
||||||
|
$plans = array_merge($plans, $result->get('InstanceTypes'));
|
||||||
|
|
||||||
|
$nextToken = $result->get('NextToken');
|
||||||
|
} while ($nextToken);
|
||||||
|
|
||||||
|
return collect($plans)
|
||||||
|
->mapWithKeys(fn ($value) => [
|
||||||
|
$value['InstanceType'] => $value['InstanceType'].' - '.$value['VCpuInfo']['DefaultVCpus'].' vCPUs, '.$value['MemoryInfo']['SizeInMiB'].' MB RAM',
|
||||||
|
])
|
||||||
->toArray();
|
->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function regions(): array
|
public function regions(): array
|
||||||
{
|
{
|
||||||
return collect(config('serverproviders.aws.regions'))
|
$this->connectToEc2Client();
|
||||||
->mapWithKeys(fn ($value) => [$value['value'] => $value['title']])
|
|
||||||
|
$regions = $this->ec2Client->describeRegions();
|
||||||
|
|
||||||
|
return collect($regions->toArray()['Regions'] ?? [])
|
||||||
|
->mapWithKeys(fn ($value) => [$value['RegionName'] => $value['RegionName']])
|
||||||
->toArray();
|
->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
public function create(): void
|
public function create(): void
|
||||||
{
|
{
|
||||||
$this->connectToEc2Client();
|
$this->connectToEc2Client();
|
||||||
@ -136,12 +172,16 @@ public function delete(): void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function connectToEc2Client(): void
|
private function connectToEc2Client(?string $region = null): void
|
||||||
{
|
{
|
||||||
$credentials = $this->server->serverProvider->getCredentials();
|
$credentials = $this->serverProvider->getCredentials();
|
||||||
|
|
||||||
|
if (! $region) {
|
||||||
|
$region = $this->server?->provider_data['region'];
|
||||||
|
}
|
||||||
|
|
||||||
$this->ec2Client = new Ec2Client([
|
$this->ec2Client = new Ec2Client([
|
||||||
'region' => $this->server->provider_data['region'],
|
'region' => $region ?? config('serverproviders.aws.regions')[0]['value'],
|
||||||
'version' => '2016-11-15',
|
'version' => '2016-11-15',
|
||||||
'credentials' => [
|
'credentials' => [
|
||||||
'key' => $credentials['key'],
|
'key' => $credentials['key'],
|
||||||
@ -202,11 +242,14 @@ private function createSecurityGroup(): void
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
private function runInstance(): void
|
private function runInstance(): void
|
||||||
{
|
{
|
||||||
$keyName = $groupName = $this->server->name.'-'.$this->server->id;
|
$keyName = $groupName = $this->server->name.'-'.$this->server->id;
|
||||||
$result = $this->ec2Client->runInstances([
|
$result = $this->ec2Client->runInstances([
|
||||||
'ImageId' => config('serverproviders.aws.images.'.$this->server->provider_data['region'].'.'.$this->server->os),
|
'ImageId' => $this->getImageId($this->server->os),
|
||||||
'MinCount' => 1,
|
'MinCount' => 1,
|
||||||
'MaxCount' => 1,
|
'MaxCount' => 1,
|
||||||
'InstanceType' => $this->server->provider_data['plan'],
|
'InstanceType' => $this->server->provider_data['plan'],
|
||||||
@ -220,4 +263,50 @@ private function runInstance(): void
|
|||||||
$this->server->provider_data = $providerData;
|
$this->server->provider_data = $providerData;
|
||||||
$this->server->save();
|
$this->server->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function getImageId(string $os): string
|
||||||
|
{
|
||||||
|
$this->connectToEc2Client();
|
||||||
|
|
||||||
|
$version = config('core.operating_system_versions.'.$os);
|
||||||
|
|
||||||
|
ds($version);
|
||||||
|
|
||||||
|
$result = $this->ec2Client->describeImages([
|
||||||
|
'Filters' => [
|
||||||
|
[
|
||||||
|
'Name' => 'name',
|
||||||
|
'Values' => ['ubuntu/images/*-'.$version.'-amd64-server-*'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Name' => 'state',
|
||||||
|
'Values' => ['available'],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Name' => 'virtualization-type',
|
||||||
|
'Values' => ['hvm'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'Owners' => ['099720109477'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Extract and display image information
|
||||||
|
$images = $result->get('Images');
|
||||||
|
|
||||||
|
ds($images);
|
||||||
|
|
||||||
|
if (! empty($images)) {
|
||||||
|
// Sort images by creation date to get the latest one
|
||||||
|
usort($images, function ($a, $b) {
|
||||||
|
return strtotime($b['CreationDate']) - strtotime($a['CreationDate']);
|
||||||
|
});
|
||||||
|
|
||||||
|
return $images[0]['ImageId'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception('Could not find image ID');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,11 @@
|
|||||||
\App\Enums\OperatingSystem::UBUNTU22,
|
\App\Enums\OperatingSystem::UBUNTU22,
|
||||||
\App\Enums\OperatingSystem::UBUNTU24,
|
\App\Enums\OperatingSystem::UBUNTU24,
|
||||||
],
|
],
|
||||||
|
'operating_system_versions' => [
|
||||||
|
\App\Enums\OperatingSystem::UBUNTU20 => '20.04',
|
||||||
|
\App\Enums\OperatingSystem::UBUNTU22 => '22.04',
|
||||||
|
\App\Enums\OperatingSystem::UBUNTU24 => '24.04',
|
||||||
|
],
|
||||||
'webservers' => [
|
'webservers' => [
|
||||||
\App\Enums\Webserver::NONE,
|
\App\Enums\Webserver::NONE,
|
||||||
\App\Enums\Webserver::NGINX,
|
\App\Enums\Webserver::NGINX,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user