1515use App \Services \VultrService ;
1616use Illuminate \Http \JsonResponse ;
1717use Illuminate \Http \Request ;
18+ use Illuminate \Support \Facades \DB ;
1819use OpenApi \Attributes as OA ;
1920
2021class VultrController extends Controller
@@ -286,6 +287,10 @@ public function createServer(Request $request): JsonResponse
286287 return response ()->json (['message ' => 'Private key not found. ' ], 404 );
287288 }
288289
290+ $ vultrService = null ;
291+ $ vultrInstanceId = null ;
292+ $ server = null ;
293+
289294 try {
290295 $ vultrService = new VultrService ($ token ->token );
291296 $ publicKey = $ privateKey ->getPublicKey ();
@@ -317,33 +322,41 @@ public function createServer(Request $request): JsonResponse
317322 }
318323
319324 $ vultrInstance = $ vultrService ->createInstance ($ params );
325+ $ vultrInstanceId = (string ) $ vultrInstance ['id ' ];
320326 $ ipAddress = $ vultrService ->getPublicIp ($ vultrInstance , $ request ->disable_public_ipv4 , $ request ->enable_ipv6 ) ?? Server::PLACEHOLDER_IP ;
321327
322- $ server = Server::create ([
323- 'name ' => $ normalizedServerName ,
324- 'ip ' => $ ipAddress ,
325- 'user ' => 'root ' ,
326- 'port ' => 22 ,
327- 'team_id ' => $ teamId ,
328- 'private_key_id ' => $ privateKey ->id ,
329- 'cloud_provider_token_id ' => $ token ->id ,
330- 'vultr_instance_id ' => $ vultrInstance ['id ' ],
331- 'vultr_instance_status ' => $ vultrInstance ['status ' ] ?? null ,
332- ]);
333-
334- $ vultrInstance = $ vultrService ->waitForPublicIp ($ vultrInstance , $ request ->disable_public_ipv4 , $ request ->enable_ipv6 );
335- $ assignedIpAddress = $ vultrService ->getPublicIp ($ vultrInstance , $ request ->disable_public_ipv4 , $ request ->enable_ipv6 );
336- if ($ assignedIpAddress && $ assignedIpAddress !== $ server ->ip ) {
337- $ ipAddress = $ assignedIpAddress ;
338- $ server ->update ([
339- 'ip ' => $ assignedIpAddress ,
340- 'vultr_instance_status ' => $ vultrInstance ['status ' ] ?? $ server ->vultr_instance_status ,
328+ $ server = DB ::transaction (function () use ($ normalizedServerName , $ ipAddress , $ teamId , $ privateKey , $ token , $ vultrInstanceId , $ vultrInstance ): Server {
329+ $ server = Server::create ([
330+ 'name ' => $ normalizedServerName ,
331+ 'ip ' => $ ipAddress ,
332+ 'user ' => 'root ' ,
333+ 'port ' => 22 ,
334+ 'team_id ' => $ teamId ,
335+ 'private_key_id ' => $ privateKey ->id ,
336+ 'cloud_provider_token_id ' => $ token ->id ,
337+ 'vultr_instance_id ' => $ vultrInstanceId ,
338+ 'vultr_instance_status ' => $ vultrInstance ['status ' ] ?? null ,
341339 ]);
342- }
343340
344- $ server ->proxy ->set ('status ' , 'exited ' );
345- $ server ->proxy ->set ('type ' , ProxyTypes::TRAEFIK ->value );
346- $ server ->save ();
341+ $ server ->proxy ->set ('status ' , 'exited ' );
342+ $ server ->proxy ->set ('type ' , ProxyTypes::TRAEFIK ->value );
343+ $ server ->save ();
344+
345+ return $ server ;
346+ });
347+
348+ try {
349+ $ vultrInstance = $ vultrService ->waitForPublicIp ($ vultrInstance , $ request ->disable_public_ipv4 , $ request ->enable_ipv6 );
350+ $ assignedIpAddress = $ vultrService ->getPublicIp ($ vultrInstance , $ request ->disable_public_ipv4 , $ request ->enable_ipv6 );
351+ if ($ assignedIpAddress && $ assignedIpAddress !== $ server ->ip ) {
352+ $ server ->update ([
353+ 'ip ' => $ assignedIpAddress ,
354+ 'vultr_instance_status ' => $ vultrInstance ['status ' ] ?? $ server ->vultr_instance_status ,
355+ ]);
356+ }
357+ } catch (\Throwable $ e ) {
358+ report ($ e );
359+ }
347360
348361 if ($ request ->instant_validate ) {
349362 ValidateServer::dispatch ($ server );
@@ -353,27 +366,48 @@ public function createServer(Request $request): JsonResponse
353366 'team_id ' => $ teamId ,
354367 'server_uuid ' => $ server ->uuid ,
355368 'server_name ' => $ server ->name ,
356- 'vultr_instance_id ' => $ vultrInstance [ ' id ' ] ,
357- 'ip ' => $ ipAddress ,
369+ 'vultr_instance_id ' => $ vultrInstanceId ,
370+ 'ip ' => $ server -> ip ,
358371 ]);
359372
360373 return response ()->json ([
361374 'uuid ' => $ server ->uuid ,
362- 'vultr_instance_id ' => $ vultrInstance [ ' id ' ] ,
363- 'ip ' => $ ipAddress ,
375+ 'vultr_instance_id ' => $ vultrInstanceId ,
376+ 'ip ' => $ server -> ip ,
364377 ])->setStatusCode (201 );
365378 } catch (RateLimitException $ e ) {
379+ $ this ->deleteUntrackedInstance ($ vultrService , $ vultrInstanceId , $ server );
380+
366381 $ response = response ()->json (['message ' => $ e ->getMessage ()], 429 );
367382 if ($ e ->retryAfter !== null ) {
368383 $ response ->header ('Retry-After ' , $ e ->retryAfter );
369384 }
370385
371386 return $ response ;
372- } catch (\Throwable ) {
387+ } catch (\Throwable $ e ) {
388+ $ this ->deleteUntrackedInstance ($ vultrService , $ vultrInstanceId , $ server );
389+
390+ logger ()->error ('Failed to create Vultr server ' , [
391+ 'error ' => $ e ->getMessage (),
392+ ]);
393+
373394 return response ()->json (['message ' => 'Failed to create Vultr server. ' ], 500 );
374395 }
375396 }
376397
398+ private function deleteUntrackedInstance (?VultrService $ vultrService , ?string $ vultrInstanceId , ?Server $ server ): void
399+ {
400+ if (! $ vultrService || ! $ vultrInstanceId || $ server ) {
401+ return ;
402+ }
403+
404+ try {
405+ $ vultrService ->deleteInstance ($ vultrInstanceId );
406+ } catch (\Throwable $ e ) {
407+ report ($ e );
408+ }
409+ }
410+
377411 private function findMatchingSshKey (array $ sshKeys , string $ publicKey ): ?array
378412 {
379413 $ normalizedPublicKey = $ this ->normalizePublicKey ($ publicKey );
0 commit comments