mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-14 16:17:10 +00:00
Add Vultr cloud provider integration
This commit is contained in:
1 parent
2833c68af9
commit
94abbe1590
33 files changed
+2978
-44
No files matched your search
@@ -9,6 +9,7 @@ use App\Models\CloudProviderToken;
|
||||
use App\Models\Server;
|
||||
use App\Rules\ValidServerIp;
|
||||
use App\Services\HetznerService;
|
||||
use App\Services\VultrService;
|
||||
use App\Support\ValidationPatterns;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -75,8 +76,12 @@ class Show extends Component
|
||||
|
||||
public ?string $hetznerServerStatus = null;
|
||||
|
||||
public ?string $vultrInstanceStatus = null;
|
||||
|
||||
public bool $hetznerServerManuallyStarted = false;
|
||||
|
||||
public bool $vultrInstanceManuallyStarted = false;
|
||||
|
||||
public bool $isValidating = false;
|
||||
|
||||
// Hetzner linking properties
|
||||
@@ -92,6 +97,18 @@ class Show extends Component
|
||||
|
||||
public bool $hetznerNoMatchFound = false;
|
||||
|
||||
public Collection $availableVultrTokens;
|
||||
|
||||
public ?int $selectedVultrTokenId = null;
|
||||
|
||||
public ?string $manualVultrInstanceId = null;
|
||||
|
||||
public ?array $matchedVultrInstance = null;
|
||||
|
||||
public ?string $vultrSearchError = null;
|
||||
|
||||
public bool $vultrNoMatchFound = false;
|
||||
|
||||
public function getListeners()
|
||||
{
|
||||
$teamId = $this->server->team_id ?? auth()->user()->currentTeam()->id;
|
||||
@@ -173,10 +190,12 @@ class Show extends Component
|
||||
}
|
||||
// Load saved Hetzner status and validation state
|
||||
$this->hetznerServerStatus = $this->server->hetzner_server_status;
|
||||
$this->vultrInstanceStatus = $this->server->vultr_instance_status;
|
||||
$this->isValidating = $this->server->is_validating ?? false;
|
||||
|
||||
// Load Hetzner tokens for linking
|
||||
// Load cloud provider tokens for linking
|
||||
$this->loadHetznerTokens();
|
||||
$this->loadVultrTokens();
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
@@ -289,6 +308,22 @@ class Show extends Component
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
if ($this->server->vultr_instance_id) {
|
||||
$status = $this->server->refreshVultrState();
|
||||
$this->server->refresh();
|
||||
$this->vultrInstanceStatus = $this->server->vultr_instance_status;
|
||||
$this->ip = $this->server->ip;
|
||||
|
||||
if (in_array($status, ['stopped', 'suspended', 'deleted'], true)) {
|
||||
$message = $status === 'deleted'
|
||||
? 'Vultr instance is deleted or no longer accessible. Relink this server before validating.'
|
||||
: 'Vultr instance is '.($status ?? 'not running').'. Power it on before validating.';
|
||||
$this->dispatch('error', $message);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$this->validationLogs = $this->server->validation_logs = null;
|
||||
$this->server->save();
|
||||
$this->dispatch('init', $install);
|
||||
@@ -453,6 +488,27 @@ class Show extends Component
|
||||
}
|
||||
}
|
||||
|
||||
public function checkVultrInstanceStatus(bool $manual = false)
|
||||
{
|
||||
try {
|
||||
if (! $this->server->vultr_instance_id || ! $this->server->cloudProviderToken) {
|
||||
$this->dispatch('error', 'This server is not associated with a Vultr instance or token.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->vultrInstanceStatus = $this->server->refreshVultrState();
|
||||
$this->server->refresh();
|
||||
$this->ip = $this->server->ip;
|
||||
|
||||
if ($manual) {
|
||||
$this->dispatch('success', 'Instance status refreshed: '.ucfirst($this->vultrInstanceStatus ?? 'unknown'));
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function handleServerValidated($event = null)
|
||||
{
|
||||
// Check if event is for this server
|
||||
@@ -472,6 +528,7 @@ class Show extends Component
|
||||
|
||||
// Reload Hetzner tokens in case the linking section should now be shown
|
||||
$this->loadHetznerTokens();
|
||||
$this->loadVultrTokens();
|
||||
|
||||
$this->dispatch('refreshServerShow');
|
||||
$this->dispatch('refreshServer');
|
||||
@@ -498,6 +555,27 @@ class Show extends Component
|
||||
}
|
||||
}
|
||||
|
||||
public function startVultrInstance()
|
||||
{
|
||||
try {
|
||||
if (! $this->server->vultr_instance_id || ! $this->server->cloudProviderToken) {
|
||||
$this->dispatch('error', 'This server is not associated with a Vultr instance or token.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$vultrService = new VultrService($this->server->cloudProviderToken->token);
|
||||
$vultrService->startInstance($this->server->vultr_instance_id);
|
||||
|
||||
$this->vultrInstanceStatus = 'starting';
|
||||
$this->server->update(['vultr_instance_status' => 'starting']);
|
||||
$this->vultrInstanceManuallyStarted = true;
|
||||
$this->dispatch('success', 'Vultr instance is starting...');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function refreshServerMetadata(): void
|
||||
{
|
||||
try {
|
||||
@@ -531,6 +609,13 @@ class Show extends Component
|
||||
->get();
|
||||
}
|
||||
|
||||
public function loadVultrTokens(): void
|
||||
{
|
||||
$this->availableVultrTokens = CloudProviderToken::ownedByCurrentTeam()
|
||||
->where('provider', 'vultr')
|
||||
->get();
|
||||
}
|
||||
|
||||
public function searchHetznerServer(): void
|
||||
{
|
||||
$this->hetznerSearchError = null;
|
||||
@@ -658,6 +743,130 @@ class Show extends Component
|
||||
}
|
||||
}
|
||||
|
||||
public function searchVultrInstance(): void
|
||||
{
|
||||
$this->vultrSearchError = null;
|
||||
$this->vultrNoMatchFound = false;
|
||||
$this->matchedVultrInstance = null;
|
||||
|
||||
if (! $this->selectedVultrTokenId) {
|
||||
$this->vultrSearchError = 'Please select a Vultr token.';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
|
||||
$token = $this->availableVultrTokens->firstWhere('id', $this->selectedVultrTokenId);
|
||||
if (! $token) {
|
||||
$this->vultrSearchError = 'Invalid token selected.';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$vultrService = new VultrService($token->token);
|
||||
$matched = $vultrService->findInstanceByIp($this->server->ip);
|
||||
|
||||
if ($matched) {
|
||||
$this->matchedVultrInstance = $matched;
|
||||
} else {
|
||||
$this->vultrNoMatchFound = true;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$this->vultrSearchError = 'Failed to search Vultr instances: '.$e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public function searchVultrInstanceById(): void
|
||||
{
|
||||
$this->vultrSearchError = null;
|
||||
$this->vultrNoMatchFound = false;
|
||||
$this->matchedVultrInstance = null;
|
||||
|
||||
if (! $this->selectedVultrTokenId) {
|
||||
$this->vultrSearchError = 'Please select a Vultr token first.';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $this->manualVultrInstanceId) {
|
||||
$this->vultrSearchError = 'Please enter a Vultr Instance ID.';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
|
||||
$token = $this->availableVultrTokens->firstWhere('id', $this->selectedVultrTokenId);
|
||||
if (! $token) {
|
||||
$this->vultrSearchError = 'Invalid token selected.';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$vultrService = new VultrService($token->token);
|
||||
$instanceData = $vultrService->getInstance($this->manualVultrInstanceId);
|
||||
|
||||
if (! empty($instanceData)) {
|
||||
$this->matchedVultrInstance = $instanceData;
|
||||
} else {
|
||||
$this->vultrNoMatchFound = true;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$this->vultrSearchError = 'Failed to fetch Vultr instance: '.$e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public function linkToVultr()
|
||||
{
|
||||
if (! $this->matchedVultrInstance) {
|
||||
$this->dispatch('error', 'No Vultr instance selected.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
|
||||
$token = $this->availableVultrTokens->firstWhere('id', $this->selectedVultrTokenId);
|
||||
if (! $token) {
|
||||
$this->dispatch('error', 'Invalid token selected.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$vultrService = new VultrService($token->token);
|
||||
$instanceData = $vultrService->getInstance($this->matchedVultrInstance['id']);
|
||||
|
||||
if (empty($instanceData)) {
|
||||
$this->dispatch('error', 'Could not find Vultr instance with ID: '.$this->matchedVultrInstance['id']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->server->update([
|
||||
'cloud_provider_token_id' => $this->selectedVultrTokenId,
|
||||
'vultr_instance_id' => $this->matchedVultrInstance['id'],
|
||||
'vultr_instance_status' => $instanceData['status'] ?? null,
|
||||
]);
|
||||
|
||||
$this->vultrInstanceStatus = $instanceData['status'] ?? null;
|
||||
|
||||
$this->matchedVultrInstance = null;
|
||||
$this->selectedVultrTokenId = null;
|
||||
$this->manualVultrInstanceId = null;
|
||||
$this->vultrNoMatchFound = false;
|
||||
$this->vultrSearchError = null;
|
||||
|
||||
$this->dispatch('success', 'Server successfully linked to Vultr!');
|
||||
$this->dispatch('refreshServerShow');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.server.show');
|
||||
|
||||
Reference in new issue
Block a user