GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( b5ace7...4e0661 )
by Jamie
16s
created

Server::stop()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 1
cts 1
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 0
crap 1
1
<?php declare(strict_types=1);
2
3
namespace OpenStack\Compute\v2\Models;
4
5
use OpenStack\Common\Resource\HasWaiterTrait;
6
use OpenStack\Common\Resource\Creatable;
7
use OpenStack\Common\Resource\Deletable;
8
use OpenStack\Common\Resource\Listable;
9
use OpenStack\Common\Resource\Retrievable;
10
use OpenStack\Common\Resource\Updateable;
11
use OpenStack\Common\Resource\OperatorResource;
12
use OpenStack\Common\Transport\Utils;
13
use OpenStack\BlockStorage\v2\Models\VolumeAttachment;
14
use OpenStack\Compute\v2\Enum;
15
use OpenStack\Networking\v2\Extensions\SecurityGroups\Models\SecurityGroup;
16
use Psr\Http\Message\ResponseInterface;
17
18
/**
19
 * @property \OpenStack\Compute\v2\Api $api
20
 */
21
class Server extends OperatorResource implements
22
    Creatable,
23
    Updateable,
24
    Deletable,
25
    Retrievable,
26
    Listable
27
{
28
    use HasWaiterTrait;
29
30
    /** @var string */
31
    public $id;
32
33
    /** @var string */
34
    public $ipv4;
35
36
    /** @var string */
37
    public $ipv6;
38
39
    /** @var array */
40
    public $addresses;
41
42
    /** @var \DateTimeImmutable */
43
    public $created;
44
45
    /** @var \DateTimeImmutable */
46
    public $updated;
47
48
    /** @var Flavor */
49
    public $flavor;
50
51
    /** @var string */
52
    public $hostId;
53
54
    /** @var Image */
55
    public $image;
56
57
    /** @var array */
58
    public $links;
59
60
    /** @var array */
61
    public $metadata;
62
63
    /** @var string */
64
    public $name;
65
66
    /** @var string */
67
    public $progress;
68
69
    /** @var string */
70
    public $status;
71
72
    /** @var string */
73
    public $tenantId;
74
75
    /** @var string */
76
    public $userId;
77
78
    /** @var string */
79
    public $adminPass;
80
81
    /** @var string */
82
    public $taskState;
83
84
    protected $resourceKey = 'server';
85
    protected $resourcesKey = 'servers';
86
    protected $markerKey = 'id';
87
88
    protected $aliases = [
89
        'block_device_mapping_v2' => 'blockDeviceMapping',
90
        'accessIPv4'              => 'ipv4',
91
        'accessIPv6'              => 'ipv6',
92
        'tenant_id'               => 'tenantId',
93
        'user_id'                 => 'userId',
94
        'security_groups'         => 'securityGroups',
95
        'OS-EXT-STS:task_state'   => 'taskState',
96
    ];
97
98
    /**
99
     * {@inheritDoc}
100
     *
101 2
     * @param array $userOptions {@see \OpenStack\Compute\v2\Api::postServer}
102
     */
103 2
    public function create(array $userOptions): Creatable
104 2
    {
105
        $response = $this->execute($this->api->postServer(), $userOptions);
106
        return $this->populateFromResponse($response);
107
    }
108
109
    /**
110 1
     * {@inheritDoc}
111
     */
112 1
    public function update()
113
    {
114 1
        $response = $this->execute($this->api->putServer(), $this->getAttrs(['id', 'name', 'ipv4', 'ipv6']));
115
        $this->populateFromResponse($response);
116
    }
117
118
    /**
119
     * {@inheritDoc}
120 1
     */
121
    public function delete()
122 1
    {
123 1
        $this->execute($this->api->deleteServer(), $this->getAttrs(['id']));
124
    }
125
126
    /**
127
     * {@inheritDoc}
128 1
     */
129
    public function retrieve()
130 1
    {
131
        $response = $this->execute($this->api->getServer(), $this->getAttrs(['id']));
132 1
        $this->populateFromResponse($response);
133
    }
134
135
    /**
136
     * Changes the root password for a server.
137
     *
138
     * @param string $newPassword The new root password
139
     */
140 1
    public function changePassword(string $newPassword)
141
    {
142 1
        $this->execute($this->api->changeServerPassword(), [
143 1
            'id'       => $this->id,
144
            'password' => $newPassword,
145 1
        ]);
146 1
    }
147
148
    /**
149
     * Reboots the server.
150
     *
151
     * @param string $type The type of reboot that will be performed. Either SOFT or HARD is supported.
152
     */
153 2
    public function reboot(string $type = Enum::REBOOT_SOFT)
154
    {
155 2
        if (!in_array($type, ['SOFT', 'HARD'])) {
156 1
            throw new \RuntimeException('Reboot type must either be SOFT or HARD');
157
        }
158
159 1
        $this->execute($this->api->rebootServer(), [
160 1
            'id'   => $this->id,
161 1
            'type' => $type,
162 1
        ]);
163 1
    }
164
165
    /**
166
     * Starts server
167
     */
168
    public function start()
169
    {
170 1
        $this->execute($this->api->startServer(), [
171
            'id' => $this->id,
172 1
            'os-start' => null
173 1
        ]);
174
    }
175 1
176 1
    /**
177
     * Stops server
178
     */
179
    public function stop()
180
    {
181
        $this->execute($this->api->stopServer(), [
182
            'id' => $this->id,
183
            'os-stop' => null
184 1
        ]);
185
    }
186 1
187 1
    /**
188 1
     * Rebuilds the server.
189 1
     *
190
     * @param array $options {@see \OpenStack\Compute\v2\Api::rebuildServer}
191 1
     */
192 1
    public function rebuild(array $options)
193
    {
194
        $options['id'] = $this->id;
195
        $response = $this->execute($this->api->rebuildServer(), $options);
196
197 1
        $this->populateFromResponse($response);
198
    }
199 1
200 1
    /**
201
     * Resizes the server to a new flavor. Once this operation is complete and server has transitioned
202
     * to an active state, you will either need to call {@see confirmResize()} or {@see revertResize()}.
203
     *
204
     * @param string $flavorId The UUID of the new flavor your server will be based on.
205 1
     */
206
    public function resize(string $flavorId)
207 1
    {
208 1
        $response = $this->execute($this->api->resizeServer(), [
209
            'id'       => $this->id,
210
            'flavorId' => $flavorId,
211
        ]);
212
213
        $this->populateFromResponse($response);
214
    }
215 1
216
    /**
217 1
     * Confirms a previous resize operation.
218 1
     */
219 1
    public function confirmResize()
220
    {
221
        $this->execute($this->api->confirmServerResize(), ['confirmResize' => null, 'id' => $this->id]);
222
    }
223
224
    /**
225
     * Reverts a previous resize operation.
226
     */
227
    public function revertResize()
228 2
    {
229
        $this->execute($this->api->revertServerResize(), ['revertResize' => null, 'id' => $this->id]);
230 2
    }
231
232 2
    /**
233 2
     * Creates an image for the current server.
234 2
     *
235
     * @param array $options {@see \OpenStack\Compute\v2\Api::createServerImage}
236
     */
237
    public function createImage(array $options)
238
    {
239
        $options['id'] = $this->id;
240
        $this->execute($this->api->createServerImage(), $options);
241
    }
242 1
243
    /**
244 1
     * Iterates over all the IP addresses for this server.
245 1
     *
246
     * @param array $options {@see \OpenStack\Compute\v2\Api::getAddressesByNetwork}
247
     *
248
     * @return array An array containing to two keys: "public" and "private"
249
     */
250
    public function listAddresses(array $options = []): array
251
    {
252
        $options['id'] = $this->id;
253
254
        $data = (isset($options['networkLabel'])) ? $this->api->getAddressesByNetwork() : $this->api->getAddresses();
255
        $response = $this->execute($data, $options);
256 1
        return Utils::jsonDecode($response)['addresses'];
257
    }
258 1
259 1
    /**
260
     * Retrieves metadata from the API.
261
     *
262
     * @return array
263
     */
264
    public function getMetadata(): array
265
    {
266
        $response = $this->execute($this->api->getServerMetadata(), ['id' => $this->id]);
267
        return $this->parseMetadata($response);
268
    }
269
270
    /**
271 1
     * Resets all the metadata for this server with the values provided. All existing metadata keys
272
     * will either be replaced or removed.
273 1
     *
274 1
     * @param array $metadata {@see \OpenStack\Compute\v2\Api::putServerMetadata}
275
     */
276
    public function resetMetadata(array $metadata)
277
    {
278
        $response = $this->execute($this->api->putServerMetadata(), ['id' => $this->id, 'metadata' => $metadata]);
279
        $this->metadata = $this->parseMetadata($response);
280
    }
281
282
    /**
283
     * Merges the existing metadata for the server with the values provided. Any existing keys
284 1
     * referenced in the user options will be replaced with the user's new values. All other
285
     * existing keys will remain unaffected.
286 1
     *
287 1
     * @param array $metadata {@see \OpenStack\Compute\v2\Api::postServerMetadata}
288
     *
289
     * @return array
290
     */
291
    public function mergeMetadata(array $metadata)
292
    {
293
        $response = $this->execute($this->api->postServerMetadata(), ['id' => $this->id, 'metadata' => $metadata]);
294
        $this->metadata = $this->parseMetadata($response);
295 1
    }
296
297 1
    /**
298 1
     * Retrieve the value for a specific metadata key.
299
     *
300
     * @param string $key {@see \OpenStack\Compute\v2\Api::getServerMetadataKey}
301
     *
302
     * @return mixed
303
     */
304 View Code Duplication
    public function getMetadataItem(string $key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
305
    {
306
        $response = $this->execute($this->api->getServerMetadataKey(), ['id' => $this->id, 'key' => $key]);
307
        $value = $this->parseMetadata($response)[$key];
308
        $this->metadata[$key] = $value;
309
        return $value;
310
    }
311
312
    /**
313
     * Remove a specific metadata key.
314
     *
315
     * @param string $key {@see \OpenStack\Compute\v2\Api::deleteServerMetadataKey}
316
     */
317 View Code Duplication
    public function deleteMetadataItem(string $key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
318
    {
319
        if (isset($this->metadata[$key])) {
320
            unset($this->metadata[$key]);
321
        }
322
323
        $this->execute($this->api->deleteServerMetadataKey(), ['id' => $this->id, 'key' => $key]);
324
    }
325
326
327
    /**
328
     * Add security group to a server (addSecurityGroup action)
329
     *
330
     * @param array $options {@see \OpenStack\Compute\v2\Api::postSecurityGroup}
331
     *
332
     * @return SecurityGroup
333
     */
334
    public function addSecurityGroup(array $options) : SecurityGroup
335
    {
336
        $options['id'] = $this->id;
337
338
        $response = $this->execute($this->api->postSecurityGroup(), $options);
339
340
        return $this->model(SecurityGroup::class)->populateFromResponse($response);
341
    }
342
343
    /**
344
     * Add security group to a server (addSecurityGroup action)
345
     *
346
     * @param array $options {@see \OpenStack\Compute\v2\Api::deleteSecurityGroup}
347
     */
348
    public function removeSecurityGroup(array $options)
349
    {
350
        $options['id'] = $this->id;
351
        $this->execute($this->api->deleteSecurityGroup(), $options);
352
    }
353
354
    public function parseMetadata(ResponseInterface $response): array
355
    {
356
        return Utils::jsonDecode($response)['metadata'];
357
    }
358
359
    /**
360
     * Returns Generator for SecurityGroups
361
     *
362
     * @return \Generator
363
     */
364
    public function listSecurityGroups(): \Generator
365
    {
366
        return $this->model(SecurityGroup::class)->enumerate($this->api->getSecurityGroups(), ['id' => $this->id]);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface OpenStack\Common\Resource\ResourceInterface as the method enumerate() does only exist in the following implementations of said interface: OpenStack\BlockStorage\v2\Models\Snapshot, OpenStack\BlockStorage\v2\Models\Volume, OpenStack\BlockStorage\v2\Models\VolumeAttachment, OpenStack\BlockStorage\v2\Models\VolumeType, OpenStack\Common\Resource\OperatorResource, OpenStack\Compute\v2\Models\Flavor, OpenStack\Compute\v2\Models\HypervisorStatistic, OpenStack\Compute\v2\Models\Image, OpenStack\Compute\v2\Models\Keypair, OpenStack\Compute\v2\Models\Server, OpenStack\Identity\v2\Models\Catalog, OpenStack\Identity\v2\Models\Endpoint, OpenStack\Identity\v2\Models\Entry, OpenStack\Identity\v2\Models\Tenant, OpenStack\Identity\v2\Models\Token, OpenStack\Identity\v3\Models\Assignment, OpenStack\Identity\v3\Models\Catalog, OpenStack\Identity\v3\Models\Credential, OpenStack\Identity\v3\Models\Domain, OpenStack\Identity\v3\Models\Endpoint, OpenStack\Identity\v3\Models\Group, OpenStack\Identity\v3\Models\Policy, OpenStack\Identity\v3\Models\Project, OpenStack\Identity\v3\Models\Role, OpenStack\Identity\v3\Models\Service, OpenStack\Identity\v3\Models\Token, OpenStack\Identity\v3\Models\User, OpenStack\Images\v2\Models\Image, OpenStack\Images\v2\Models\Member, OpenStack\Networking\v2\...ayer3\Models\FloatingIp, OpenStack\Networking\v2\...ns\Layer3\Models\Router, OpenStack\Networking\v2\...ps\Models\SecurityGroup, OpenStack\Networking\v2\...odels\SecurityGroupRule, OpenStack\Networking\v2\Models\Network, OpenStack\Networking\v2\Models\Port, OpenStack\Networking\v2\Models\Subnet, OpenStack\ObjectStore\v1\Models\Account, OpenStack\ObjectStore\v1\Models\Container, OpenStack\ObjectStore\v1\Models\Object.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
367
    }
368
369
370
    /**
371
     * Returns Generator for VolumeAttachment
372
     *
373
     * @return \Generator
374
     */
375
    public function listVolumeAttachments(): \Generator
376
    {
377
        return $this->model(VolumeAttachment::class)->enumerate($this->api->getVolumeAttachments(), ['id' => $this->id]);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface OpenStack\Common\Resource\ResourceInterface as the method enumerate() does only exist in the following implementations of said interface: OpenStack\BlockStorage\v2\Models\Snapshot, OpenStack\BlockStorage\v2\Models\Volume, OpenStack\BlockStorage\v2\Models\VolumeAttachment, OpenStack\BlockStorage\v2\Models\VolumeType, OpenStack\Common\Resource\OperatorResource, OpenStack\Compute\v2\Models\Flavor, OpenStack\Compute\v2\Models\HypervisorStatistic, OpenStack\Compute\v2\Models\Image, OpenStack\Compute\v2\Models\Keypair, OpenStack\Compute\v2\Models\Server, OpenStack\Identity\v2\Models\Catalog, OpenStack\Identity\v2\Models\Endpoint, OpenStack\Identity\v2\Models\Entry, OpenStack\Identity\v2\Models\Tenant, OpenStack\Identity\v2\Models\Token, OpenStack\Identity\v3\Models\Assignment, OpenStack\Identity\v3\Models\Catalog, OpenStack\Identity\v3\Models\Credential, OpenStack\Identity\v3\Models\Domain, OpenStack\Identity\v3\Models\Endpoint, OpenStack\Identity\v3\Models\Group, OpenStack\Identity\v3\Models\Policy, OpenStack\Identity\v3\Models\Project, OpenStack\Identity\v3\Models\Role, OpenStack\Identity\v3\Models\Service, OpenStack\Identity\v3\Models\Token, OpenStack\Identity\v3\Models\User, OpenStack\Images\v2\Models\Image, OpenStack\Images\v2\Models\Member, OpenStack\Networking\v2\...ayer3\Models\FloatingIp, OpenStack\Networking\v2\...ns\Layer3\Models\Router, OpenStack\Networking\v2\...ps\Models\SecurityGroup, OpenStack\Networking\v2\...odels\SecurityGroupRule, OpenStack\Networking\v2\Models\Network, OpenStack\Networking\v2\Models\Port, OpenStack\Networking\v2\Models\Subnet, OpenStack\ObjectStore\v1\Models\Account, OpenStack\ObjectStore\v1\Models\Container, OpenStack\ObjectStore\v1\Models\Object.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
378
    }
379
380
    /**
381
     * Attach a volume and returns volume that was attached
382
     *
383
     * @param $volumeId
384
     *
385
     * @return VolumeAttachment
386
     */
387
    public function attachVolume(string $volumeId): VolumeAttachment
388
    {
389
        $response =  $this->execute($this->api->postVolumeAttachments(), ['id' => $this->id, 'volumeId' => $volumeId]);
390
391
        return $this->model(VolumeAttachment::class)->populateFromResponse($response);
392
    }
393
394
    /**
395
     * Detach a volume
396
     *
397
     * @param $attachmentId
398
     *
399
     * @return void
400
     */
401
    public function detachVolume(string $attachmentId)
402
    {
403
        $this->execute($this->api->deleteVolumeAttachments(), ['id' => $this->id, 'attachmentId' => $attachmentId]);
404
    }
405
}
406