Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
127 / 127
100.00% covered (success)
100.00%
36 / 36
CRAP
100.00% covered (success)
100.00%
1 / 1
InstanceService
100.00% covered (success)
100.00%
127 / 127
100.00% covered (success)
100.00%
36 / 36
70
100.00% covered (success)
100.00%
1 / 1
 getInstances
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getInstance
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createInstance
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 updateInstance
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 deleteInstance
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 haltInstances
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 haltInstance
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 rebootInstances
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 rebootInstance
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 startInstances
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 startInstance
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 reinstallInstance
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getBandwidth
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
 getNeighbors
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getVPCs
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 attachVPC
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 detachVPC
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getIsoStatus
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 attachIsoToInstance
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 detachIsoFromInstance
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 setBackupSchedule
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getBackupSchedule
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 restoreInstance
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
8
 getIPv4Addresses
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
 createIPv4Address
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deleteIPv4Address
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createReverseIPv4Address
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setDefaultIPv4ReverseDNSEntry
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getIPv6Addresses
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createReverseIPv6Address
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getReverseIPv6Addresses
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
3
 deleteReverseIPv6Address
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserData
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getAvailableUpgrades
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
6
 singleInstanceAction
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 multipleInstancesAction
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace Vultr\VultrPhp\Services\Instances;
6
7use Vultr\VultrPhp\Services\Applications\Application;
8use Vultr\VultrPhp\Services\OperatingSystems\OperatingSystem;
9use Vultr\VultrPhp\Services\VultrService;
10use Vultr\VultrPhp\Util\ListOptions;
11use Vultr\VultrPhp\Util\VultrUtil;
12use Vultr\VultrPhp\VultrClientException;
13
14/**
15 * Instance service handler, for all instances endpoints.
16 *
17 * @see https://www.vultr.com/api/#tag/instances
18 */
19class InstanceService extends VultrService
20{
21    public const FILTER_LABEL = 'label';
22    public const FILTER_MAIN_IP = 'main_ip';
23    public const FILTER_REGION = 'region';
24
25    /**
26     * Get vps instances on the account.
27     *
28     * @see https://www.vultr.com/api/#operation/list-instances
29     * @param $filters - array|null - ENUM(FILTER_LABEL, FILTER_MAIN_IP, FILTER_REGION)
30     * @param $options - ListOptions|null - Interact via reference.
31     * @throws InstanceException
32     * @return Instance[]
33     */
34    public function getInstances(?array $filters = null, ?ListOptions &$options = null) : array
35    {
36        return $this->getListObjects('instances', new Instance(), $options, $filters);
37    }
38
39    /**
40     * Retrieve a specific instance on the account.
41     *
42     * @see https://www.vultr.com/api/#operation/get-instance
43     * @param $id - string
44     * @throws InstanceException
45     * @return Instance
46     */
47    public function getInstance(string $id) : Instance
48    {
49        return $this->getObject('instances/'.$id, new Instance());
50    }
51
52    /**
53     * Create a new vps instance in a region with the desired plan and image.
54     *
55     * @see https://www.vultr.com/api/#operation/create-instance
56     * @param $create - InstanceCreate
57     * @throws InstanceException
58     * @return Instance
59     */
60    public function createInstance(InstanceCreate $create) : Instance
61    {
62        return $this->createObject('instances', new Instance(), $create->getPayloadParams());
63    }
64
65    /**
66     * Update all information for an instance. All attributes are optional. If not set, the attributes will not be sent to the api.
67     *
68     * @see https://www.vultr.com/api/#operation/update-instance
69     * @param $id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
70     * @param $update - InstanceUpdate
71     * @throws InstanceException
72     * @return Instance
73     */
74    public function updateInstance(string $id, InstanceUpdate $update) : Instance
75    {
76        $client = $this->getClientHandler();
77
78        try
79        {
80            $response = $client->patch('instances/'.$id, $update->getPayloadParams());
81        }
82        catch (VultrClientException $e)
83        {
84            throw new InstanceException('Failed to update instance: '.$e->getMessage(), $e->getHTTPCode(), $e);
85        }
86
87        $model = new Instance();
88
89        return VultrUtil::convertJSONToObject((string)$response->getBody(), $model, $model->getResponseName());
90    }
91
92    /**
93     * Delete an instance on the account.
94     *
95     * @see https://www.vultr.com/api/#operation/delete-instance
96     * @param $id - string
97     * @throws InstanceException
98     * @return void
99     */
100    public function deleteInstance(string $id) : void
101    {
102        $this->deleteObject('instances/'.$id, new Instance());
103    }
104
105    /**
106     * Halt an array of instances on the account.
107     *
108     * @see https://www.vultr.com/api/#operation/halt-instances
109     * @param $ids - array
110     * @throws InstanceException
111     * @return void
112     */
113    public function haltInstances(array $ids) : void
114    {
115        $this->multipleInstancesAction('halt', $ids);
116    }
117
118    /**
119     * Halt a specific instance on the account.
120     *
121     * @see https://www.vultr.com/api/#operation/halt-instance
122     * @param $id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
123     * @throws InstanceException
124     * @return void
125     */
126    public function haltInstance(string $id) : void
127    {
128        $this->singleInstanceAction('halt', $id);
129    }
130
131    /**
132     * Reboot an array of instances on the account.
133     *
134     * @see https://www.vultr.com/api/#operation/reboot-instances
135     * @param $ids - array - Example: ['cb676a46-66fd-4dfb-b839-443f2e6c0b60', 'cb676a46-22fd-4dfb-b839-443f2e6c0b60']
136     * @throws InstanceException
137     * @return void
138     */
139    public function rebootInstances(array $ids) : void
140    {
141        $this->multipleInstancesAction('reboot', $ids);
142    }
143
144    /**
145     * Reboot a specific instance on the account.
146     *
147     * @see https://www.vultr.com/api/#operation/reboot-instance
148     * @param $id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
149     * @throws InstanceException
150     * @return void
151     */
152    public function rebootInstance(string $id) : void
153    {
154        $this->singleInstanceAction('reboot', $id);
155    }
156
157    /**
158     * Start a group of instances on the account.
159     *
160     * @see https://www.vultr.com/api/#operation/start-instances
161     * @param $ids - array - Example: ['cb676a46-66fd-4dfb-b839-443f2e6c0b60', 'cb676a46-22fd-4dfb-b839-443f2e6c0b60']
162     * @throws InstanceException
163     * @return void
164     */
165    public function startInstances(array $ids) : void
166    {
167        $this->multipleInstancesAction('start', $ids);
168    }
169
170    /**
171     * Start a specific instance on the account.
172     *
173     * @see https://www.vultr.com/api/#operation/start-instance
174     * @param $id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
175     * @throws InstanceException
176     * @return void
177     */
178    public function startInstance(string $id) : void
179    {
180        $this->singleInstanceAction('start', $id);
181    }
182
183    /**
184     * Reinstall an instance. This may take a few extra seconds to complete.
185     *
186     * @see https://www.vultr.com/api/#operation/reinstall-instance
187     * @param $id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
188     * @throws InstanceException
189     * @return Instance
190     */
191    public function reinstallInstance(string $id, ?string $hostname = null) : Instance
192    {
193        try
194        {
195            $response = $this->getClientHandler()->post('instances/'.$id.'/reinstall', $hostname !== null ? ['hostname' => $hostname] : []);
196        }
197        catch (VultrClientException $e)
198        {
199            throw new InstanceException('Failed to get bandwidth for instance: '.$e->getMessage(), $e->getHTTPCode(), $e);
200        }
201
202        $model = new Instance();
203        return VultrUtil::convertJSONToObject((string)$response->getBody(), $model, $model->getResponseName());
204    }
205
206    /**
207     * Get bandwidth information about an instance.
208     *
209     * The structure of the array will follow this format.
210     * ['2022-11-05' => ['incoming_bytes' => 234523452352, 'outgoing_bytes' => 132432423]]
211     *
212     * @see https://www.vultr.com/api/#operation/get-instance-bandwidth
213     * @param $id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
214     * @throws InstanceException
215     * @throws VultrException
216     * @return array
217     */
218    public function getBandwidth(string $id) : array
219    {
220        try
221        {
222            $response = $this->getClientHandler()->get('instances/'.$id.'/bandwidth');
223        }
224        catch (VultrClientException $e)
225        {
226            throw new InstanceException('Failed to get bandwidth for instance: '.$e->getMessage(), $e->getHTTPCode(), $e);
227        }
228
229        $decode = VultrUtil::decodeJSON((string)$response->getBody(), true);
230
231        $output = [];
232        // Just a standardization, in the event the api ever changes its attributes. We can just change it here maintain backwards compat.
233        foreach ($decode['bandwidth'] as $date => $attr)
234        {
235            $output[$date] = [];
236            foreach (['incoming_bytes', 'outgoing_bytes'] as $attribute)
237            {
238                $output[$date][$attribute] = $attr[$attribute];
239            }
240        }
241
242        return $output;
243    }
244
245    /**
246     * Get neighboring instances that live on the same host machine as this instance.
247     *
248     * @see https://www.vultr.com/api/#operation/get-instance-neighbors
249     * @param $id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
250     * @throws InstanceException
251     * @throws VultrException
252     * @return array
253     */
254    public function getNeighbors(string $id) : array
255    {
256        try
257        {
258            $response = $this->getClientHandler()->get('instances/'.$id.'/neighbors');
259        }
260        catch (VultrClientException $e)
261        {
262            throw new InstanceException('Failed to get neighbors for instance: '.$e->getMessage(), $e->getHTTPCode(), $e);
263        }
264
265        return VultrUtil::decodeJSON((string)$response->getBody(), true)['neighbors'] ?? [];
266    }
267
268    /**
269     * Get a list of attach vpc's attached to this instance.
270     *
271     * @see https://www.vultr.com/api/#operation/list-instance-vpcs
272     * @param $id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
273     * @param $options - ListOptions|null - Interact via reference.
274     * @throws InstanceException
275     * @return array
276     */
277    public function getVPCs(string $id, ?ListOptions &$options = null) : array
278    {
279        return $this->getListObjects('instances/'.$id.'/vpcs', new VPCAttachment(), $options);
280    }
281
282    /**
283     * Attach a vpc network to an instance.
284     *
285     * @see https://www.vultr.com/api/#operation/attach-instance-vpc
286     * @param $id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
287     * @param $vpc_id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
288     * @throws InstanceException
289     * @return void
290     */
291    public function attachVPC(string $id, string $vpc_id) : void
292    {
293        try
294        {
295            $this->getClientHandler()->post('instances/'.$id.'/vpcs/attach', ['vpc_id' => $vpc_id]);
296        }
297        catch (VultrClientException $e)
298        {
299            throw new InstanceException('Failed to attach vpc: '.$e->getMessage(), $e->getHTTPCode(), $e);
300        }
301    }
302
303    /**
304     * Detach a vpc network from an instance.
305     *
306     * @see https://www.vultr.com/api/#operation/detach-instance-vpc
307     * @param $id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
308     * @param $vpc_id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
309     * @throws InstanceException
310     * @return void
311     */
312    public function detachVPC(string $id, string $vpc_id) : void
313    {
314        try
315        {
316            $this->getClientHandler()->post('instances/'.$id.'/vpcs/detach', ['vpc_id' => $vpc_id]);
317        }
318        catch (VultrClientException $e)
319        {
320            throw new InstanceException('Failed to detach vpc: '.$e->getMessage(), $e->getHTTPCode(), $e);
321        }
322    }
323
324    /**
325     * Get the iso mount status on an instance.
326     *
327     * @see https://www.vultr.com/api/#operation/get-instance-iso-status
328     * @param $id - string - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
329     * @throws InstanceException
330     * @return IsoStatus
331     */
332    public function getIsoStatus(string $id) : IsoStatus
333    {
334        try
335        {
336            $response = $this->getClientHandler()->get('instances/'.$id.'/iso');
337        }
338        catch (VultrClientException $e)
339        {
340            throw new InstanceException('Failed to get iso status: '.$e->getMessage(), $e->getHTTPCode(), $e);
341        }
342
343        $model = new IsoStatus();
344        return VultrUtil::convertJSONToObject((string)$response->getBody(), $model, $model->getResponseName());
345    }
346
347    /**
348     * Attach an iso to an instance. This will cause a reboot.
349     *
350     * @see https://www.vultr.com/api/#operation/attach-instance-iso
351     * @param $id - string - Instance ID - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
352     * @param $iso_id - string
353     * @throws InstanceException
354     * @return IsoStatus
355     */
356    public function attachIsoToInstance(string $id, string $iso_id) : IsoStatus
357    {
358        return $this->createObject('instances/'.$id.'/iso/attach', new IsoStatus(), ['iso_id' => $iso_id]);
359    }
360
361    /**
362     * Detach an iso from an instance. This will cause a reboot.
363     *
364     * @see https://www.vultr.com/api/#operation/detach-instance-iso
365     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
366     * @throws InstanceException
367     * @return IsoStatus
368     */
369    public function detachIsoFromInstance(string $id) : IsoStatus
370    {
371        try
372        {
373            $response = $this->getClientHandler()->post('instances/'.$id.'/iso/detach');
374        }
375        catch (VultrClientException $e)
376        {
377            throw new InstanceException('Failed to detach iso: '.$e->getMessage(), $e->getHTTPCode(), $e);
378        }
379
380        $model = new IsoStatus();
381        return VultrUtil::convertJSONToObject((string)$response->getBody(), $model, $model->getResponseName());
382    }
383
384    /**
385     * Set the backup schedule for an instance in UTC.
386     *
387     * @see https://www.vultr.com/api/#operation/create-instance-backup-schedule
388     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
389     * @param $backup - BackupSchedule
390     * @throws InstanceException
391     * @return void
392     */
393    public function setBackupSchedule(string $id, BackupSchedule $backup) : void
394    {
395        try
396        {
397            $this->getClientHandler()->post('instances/'.$id.'/backup-schedule', $backup->getInitializedProps());
398        }
399        catch (VultrClientException $e)
400        {
401            throw new InstanceException('Failed to setup backup schedule: '.$e->getMessage(), $e->getHTTPCode(), $e);
402        }
403    }
404
405    /**
406     * Get the backup schedule for an instance on the account.
407     *
408     * @see https://www.vultr.com/api/#operation/get-instance-backup-schedule
409     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
410     * @throws InstanceException
411     * @return BackupSchedule
412     */
413    public function getBackupSchedule(string $id) : BackupSchedule
414    {
415        return $this->getObject('instances/'.$id.'/backup-schedule', new BackupSchedule());
416    }
417
418    /**
419     * Restore an instance.
420     *
421     * $snapshot_id or $backup_id must be specified. But they both cannot be specified.
422     * The actual response from the api returns an object. But its pointless as you have already fed in the parameters and it feeds it them back to you.
423     * The status doesn't mean anything to act off from the response. While your instance is restoring use getInstance to view its status.
424     *
425     * @see https://www.vultr.com/api/#operation/restore-instance
426     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
427     * @param $snapshot_id - string|null
428     * @param $backup_id - string|null
429     * @throws InstanceException
430     * @return void
431     */
432    public function restoreInstance(string $id, ?string $snapshot_id = null, ?string $backup_id = null) : void
433    {
434        if ($snapshot_id === null && $backup_id === null)
435        {
436            throw new InstanceException('1 of the following parameters must be specified. snapshot_id or backup_id');
437        }
438        else if ($snapshot_id !== null && $backup_id !== null)
439        {
440            throw new InstanceException('Only 1 parameter is allowed to be specified. Choose 1 snapshot_id or backup_id');
441        }
442
443        $params = [];
444        if ($snapshot_id !== null)
445        {
446            $params['snapshot_id'] = $snapshot_id;
447        }
448        else if ($backup_id !== null)
449        {
450            $params['backup_id'] = $backup_id;
451        }
452
453        try
454        {
455            $this->getClientHandler()->post('instances/'.$id.'/restore', $params);
456        }
457        catch (VultrClientException $e)
458        {
459            throw new InstanceException('Failed to restore instance: '.$e->getMessage(), $e->getHTTPCode(), $e);
460        }
461    }
462
463    /**
464     * Get IPV4 Address information on the instance.
465     *
466     * @see https://www.vultr.com/api/#operation/get-instance-ipv4
467     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
468     * @param $options - ListOptions|null - Interact via reference.
469     * @throws InstanceException
470     * @return InstanceIPv4Info[]
471     */
472    public function getIPv4Addresses(string $id, ?ListOptions &$options = null) : array
473    {
474        try
475        {
476            $response = $this->getClientHandler()->get('instances/'.$id.'/ipv4', ['public_network' => 'true']);
477        }
478        catch (VultrClientException $e)
479        {
480            throw new InstanceException('Failed to get ipv4 addresses: '.$e->getMessage(), $e->getHTTPCode(), $e);
481        }
482
483        $objects = [];
484        $decode = VultrUtil::decodeJSON((string)$response->getBody());
485        $model = new InstanceIPv4Info();
486        $response_name = $model->getResponseListName();
487        foreach ($decode->$response_name as $info)
488        {
489            $object = VultrUtil::mapObject($info, $model);
490            $objects[] = $object;
491        }
492        return $objects;
493    }
494
495    /**
496     * Create an ipv4 address and attach to the instance.
497     *
498     * @see https://www.vultr.com/api/#operation/create-instance-ipv4
499     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
500     * @param $reboot - bool
501     * @throws InstanceException
502     * @return InstanceIPv4Info
503     */
504    public function createIPv4Address(string $id, bool $reboot = true) : InstanceIPv4Info
505    {
506        return $this->createObject('instances/'.$id.'/ipv4', new InstanceIPv4Info(), ['reboot' => $reboot]);
507    }
508
509    /**
510     * Delete and detach an ipv4 address from the instance.
511     *
512     * @see https://www.vultr.com/api/#operation/delete-instance-ipv4
513     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
514     * @param $ip - string - Example: 127.0.0.1
515     * @throws InstanceException
516     * @return void
517     */
518    public function deleteIPv4Address(string $id, string $ip) : void
519    {
520        $this->deleteObject('instances/'.$id.'/ipv4/'.$ip, new InstanceIPv4Info());
521    }
522
523    /**
524     * @see https://www.vultr.com/api/#operation/create-instance-reverse-ipv4
525     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
526     * @param $ip - string - Example: 127.0.0.1
527     * @param $reverse - string - Example: foo.example.com
528     * @throws InstanceException
529     * @return void
530     */
531    public function createReverseIPv4Address(string $id, string $ip, string $reverse) : void
532    {
533        try
534        {
535            $this->getClientHandler()->post('instances/'.$id.'/ipv4/reverse', ['ip' => $ip, 'reverse' => $reverse]);
536        }
537        catch (VultrClientException $e)
538        {
539            throw new InstanceException('Failed to create reverse ipv4 address: '.$e->getMessage(), $e->getHTTPCode(), $e);
540        }
541    }
542
543    /**
544     * @see https://www.vultr.com/api/#operation/post-instances-instance-id-ipv4-reverse-default
545     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
546     * @param $ip - string - Example: 127.0.0.1
547     * @throws InstanceException
548     * @return void
549     */
550    public function setDefaultIPv4ReverseDNSEntry(string $id, string $ip) : void
551    {
552        try
553        {
554            $this->getClientHandler()->post('instances/'.$id.'/ipv4/reverse/default', ['ip' => $ip]);
555        }
556        catch (VultrClientException $e)
557        {
558            throw new InstanceException('Failed to set default reverse ipv4 address: '.$e->getMessage(), $e->getHTTPCode(), $e);
559        }
560    }
561
562    /**
563     * Get IPV6 address information on the instance.
564     *
565     * @see https://www.vultr.com/api/#operation/get-instance-ipv6
566     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
567     * @throws InstanceException
568     * @return InstanceIPv6Info[]
569     */
570    public function getIPv6Addresses(string $id) : array
571    {
572        return $this->getListObjects('instances/'.$id.'/ipv6', new InstanceIPv6Info());
573    }
574
575    /**
576     * @see https://www.vultr.com/api/#operation/create-instance-reverse-ipv6
577     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
578     * @param $ipv6 - string - Example: 2001:0db8:0005:6bb0:5400:2ff0:fee5:0002
579     * @param $reverse - string - Example: foo.example.com
580     * @throws InstanceException
581     * @return void
582     */
583    public function createReverseIPv6Address(string $id, string $ipv6, string $reverse) : void
584    {
585        try
586        {
587            $this->getClientHandler()->post('instances/'.$id.'/ipv6/reverse', ['ip' => $ipv6, 'reverse' => $reverse]);
588        }
589        catch (VultrClientException $e)
590        {
591            throw new InstanceException('Failed to create reverse ipv6 address: '.$e->getMessage(), $e->getHTTPCode(), $e);
592        }
593    }
594
595    /**
596     * @see https://www.vultr.com/api/#operation/list-instance-ipv6-reverse
597     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
598     * @throws InstanceException
599     * @throws VultrException
600     * @return InstanceReverseIPv6[]
601     */
602    public function getReverseIPv6Addresses(string $id) : array
603    {
604        try
605        {
606            $response = $this->getClientHandler()->get('instances/'.$id.'/ipv6/reverse');
607        }
608        catch (VultrClientException $e)
609        {
610            throw new InstanceException('Failed to get reverse ipv6 addresses: '.$e->getMessage(), $e->getHTTPCode(), $e);
611        }
612
613        $objects = [];
614        $model = new InstanceReverseIPv6();
615        $stdclass = VultrUtil::decodeJSON((string)$response->getBody());
616        $list_name = $model->getResponseListName();
617        foreach ($stdclass->$list_name as $object)
618        {
619            $objects[] = VultrUtil::mapObject($object, $model);
620        }
621        return $objects;
622    }
623
624    /**
625     * @see https://www.vultr.com/api/#operation/delete-instance-reverse-ipv6
626     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
627     * @param $ipv6 - string - Example: 2001:0db8:0005:6bb0:5400:2ff0:fee5:0002
628     * @throws InstanceException
629     * @return void
630     */
631    public function deleteReverseIPv6Address(string $id, string $ipv6)
632    {
633        $this->deleteObject('instances/'.$id.'/ipv6/reverse/'.$ipv6, new InstanceReverseIPv6());
634    }
635
636    /**
637     * Get the user data for an instance decoded from base64.
638     *
639     * @see https://www.vultr.com/api/#operation/get-instance-userdata
640     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
641     * @throws InstanceException
642     * @return string
643     */
644    public function getUserData(string $id) : string
645    {
646        try
647        {
648            $response = $this->getClientHandler()->get('instances/'.$id.'/user-data');
649        }
650        catch (VultrClientException $e)
651        {
652            throw new InstanceException('Failed to get user data: '.$e->getMessage(), $e->getHTTPCode(), $e);
653        }
654
655        return base64_decode(VultrUtil::decodeJSON((string)$response->getBody(), true)['user_data']['data']);
656    }
657
658    /**
659     * Get available plan upgrades for an instance in the region.
660     *
661     * @see https://www.vultr.com/api/#operation/get-instance-upgrades
662     * @param $id - string - Instance Id - Example: cb676a46-66fd-4dfb-b839-443f2e6c0b60
663     * @param $type - string - filter based on upgrade types.
664     * @throws InstanceException
665     * @return (OperatingSystem|Application|VPSPlan)[]
666     */
667    public function getAvailableUpgrades(string $id, string $type = 'all') : array
668    {
669        try
670        {
671            $response = $this->getClientHandler()->get('instances/'.$id.'/upgrades', ['type' => $type]);
672        }
673        catch (VultrClientException $e)
674        {
675            throw new InstanceException('Failed to get available upgrades: '.$e->getMessage(), $e->getHTTPCode(), $e);
676        }
677
678        $output = [];
679        $upgrades = VultrUtil::decodeJSON((string)$response->getBody())->upgrades;
680
681        foreach ($upgrades->os as $system)
682        {
683            $output[] = VultrUtil::mapObject($system, new OperatingSystem());
684        }
685
686        foreach ($upgrades->applications as $application)
687        {
688            $output[] = VultrUtil::mapObject($application, new Application());
689        }
690
691        foreach ($upgrades->plans as $vps_plan)
692        {
693            $plan = $this->getVultrClient()->plans->getPlan($vps_plan);
694            if ($plan === null) continue; // Plan is no longer being offered.
695            $output[] = $plan;
696        }
697
698        return $output;
699    }
700
701    // Private routines
702
703    private function singleInstanceAction(string $action, string $id) : void
704    {
705        try
706        {
707            $this->getClientHandler()->post('instances/'.$id.'/'.$action);
708        }
709        catch (VultrClientException $e)
710        {
711            throw new InstanceException('Failed to '.$action.' instance: '.$e->getMessage(), $e->getHTTPCode(), $e);
712        }
713    }
714
715    private function multipleInstancesAction(string $action, array $ids) : void
716    {
717        try
718        {
719            $this->getClientHandler()->post('instances/'.$action, ['instance_ids' => $ids]);
720        }
721        catch (VultrClientException $e)
722        {
723            throw new InstanceException('Failed to '.$action.' instances: '.$e->getMessage(), $e->getHTTPCode(), $e);
724        }
725    }
726}