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 ( 3eb280...40da3f )
by Jamie
7s
created

Server::addSecurityGroup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 8
c 0
b 0
f 0
rs 9.4285
ccs 0
cts 0
cp 0
cc 1
eloc 4
nc 1
nop 1
crap 2
1
<?php declare (strict_types=1);
2
3
namespace OpenStack\Compute\v2\Models;
4
5
use OpenCloud\Common\Resource\HasWaiterTrait;
6
use OpenCloud\Common\Resource\Creatable;
7
use OpenCloud\Common\Resource\Deletable;
8
use OpenCloud\Common\Resource\Listable;
9
use OpenCloud\Common\Resource\Retrievable;
10
use OpenCloud\Common\Resource\Updateable;
11
use OpenCloud\Common\Resource\OperatorResource;
12
use OpenCloud\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
     * Rebuilds the server.
167
     *
168
     * @param array $options {@see \OpenStack\Compute\v2\Api::rebuildServer}
169
     */
170 1
    public function rebuild(array $options)
171
    {
172 1
        $options['id'] = $this->id;
173 1
        $response = $this->execute($this->api->rebuildServer(), $options);
174
175 1
        $this->populateFromResponse($response);
176 1
    }
177
178
    /**
179
     * Resizes the server to a new flavor. Once this operation is complete and server has transitioned
180
     * to an active state, you will either need to call {@see confirmResize()} or {@see revertResize()}.
181
     *
182
     * @param string $flavorId The UUID of the new flavor your server will be based on.
183
     */
184 1
    public function resize(string $flavorId)
185
    {
186 1
        $response = $this->execute($this->api->resizeServer(), [
187 1
            'id'       => $this->id,
188 1
            'flavorId' => $flavorId,
189 1
        ]);
190
191 1
        $this->populateFromResponse($response);
192 1
    }
193
194
    /**
195
     * Confirms a previous resize operation.
196
     */
197 1
    public function confirmResize()
198
    {
199 1
        $this->execute($this->api->confirmServerResize(), ['confirmResize' => null, 'id' => $this->id]);
200 1
    }
201
202
    /**
203
     * Reverts a previous resize operation.
204
     */
205 1
    public function revertResize()
206
    {
207 1
        $this->execute($this->api->revertServerResize(), ['revertResize' => null, 'id' => $this->id]);
208 1
    }
209
210
    /**
211
     * Creates an image for the current server.
212
     *
213
     * @param array $options {@see \OpenStack\Compute\v2\Api::createServerImage}
214
     */
215 1
    public function createImage(array $options)
216
    {
217 1
        $options['id'] = $this->id;
218 1
        $this->execute($this->api->createServerImage(), $options);
219 1
    }
220
221
    /**
222
     * Iterates over all the IP addresses for this server.
223
     *
224
     * @param array $options {@see \OpenStack\Compute\v2\Api::getAddressesByNetwork}
225
     *
226
     * @return array An array containing to two keys: "public" and "private"
227
     */
228 2
    public function listAddresses(array $options = []): array
229
    {
230 2
        $options['id'] = $this->id;
231
232 2
        $data = (isset($options['networkLabel'])) ? $this->api->getAddressesByNetwork() : $this->api->getAddresses();
233 2
        $response = $this->execute($data, $options);
234 2
        return Utils::jsonDecode($response)['addresses'];
235
    }
236
237
    /**
238
     * Retrieves metadata from the API.
239
     *
240
     * @return array
241
     */
242 1
    public function getMetadata(): array
243
    {
244 1
        $response = $this->execute($this->api->getServerMetadata(), ['id' => $this->id]);
245 1
        return $this->parseMetadata($response);
246
    }
247
248
    /**
249
     * Resets all the metadata for this server with the values provided. All existing metadata keys
250
     * will either be replaced or removed.
251
     *
252
     * @param array $metadata {@see \OpenStack\Compute\v2\Api::putServerMetadata}
253
     */
254
    public function resetMetadata(array $metadata)
255
    {
256 1
        $response = $this->execute($this->api->putServerMetadata(), ['id' => $this->id, 'metadata' => $metadata]);
257
        $this->metadata = $this->parseMetadata($response);
258 1
    }
259 1
260
    /**
261
     * Merges the existing metadata for the server with the values provided. Any existing keys
262
     * referenced in the user options will be replaced with the user's new values. All other
263
     * existing keys will remain unaffected.
264
     *
265
     * @param array $metadata {@see \OpenStack\Compute\v2\Api::postServerMetadata}
266
     *
267
     * @return array
268
     */
269
    public function mergeMetadata(array $metadata)
270
    {
271 1
        $response = $this->execute($this->api->postServerMetadata(), ['id' => $this->id, 'metadata' => $metadata]);
272
        $this->metadata = $this->parseMetadata($response);
273 1
    }
274 1
275
    /**
276
     * Retrieve the value for a specific metadata key.
277
     *
278
     * @param string $key {@see \OpenStack\Compute\v2\Api::getServerMetadataKey}
279
     *
280
     * @return mixed
281
     */
282 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...
283
    {
284 1
        $response = $this->execute($this->api->getServerMetadataKey(), ['id' => $this->id, 'key' => $key]);
285
        $value = $this->parseMetadata($response)[$key];
286 1
        $this->metadata[$key] = $value;
287 1
        return $value;
288
    }
289
290
    /**
291
     * Remove a specific metadata key.
292
     *
293
     * @param string $key {@see \OpenStack\Compute\v2\Api::deleteServerMetadataKey}
294
     */
295 1 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...
296
    {
297 1
        if (isset($this->metadata[$key])) {
298 1
            unset($this->metadata[$key]);
299
        }
300
301
        $this->execute($this->api->deleteServerMetadataKey(), ['id' => $this->id, 'key' => $key]);
302
    }
303
304
305
    /**
306
     * Add security group to a server (addSecurityGroup action)
307
     *
308
     * @param array $options {@see \OpenStack\Compute\v2\Api::postSecurityGroup}
309
     *
310
     * @return SecurityGroup
311
     */
312
    public function addSecurityGroup(array $options) : SecurityGroup
313
    {
314
        $options['id'] = $this->id;
315
316
        $response = $this->execute($this->api->postSecurityGroup(), $options);
317
318
        return $this->model(SecurityGroup::class)->populateFromResponse($response);
319
    }
320
321
    /**
322
     * Add security group to a server (addSecurityGroup action)
323
     *
324
     * @param array $options {@see \OpenStack\Compute\v2\Api::deleteSecurityGroup}
325
     */
326
    public function removeSecurityGroup(array $options)
327
    {
328
        $options['id'] = $this->id;
329
        $this->execute($this->api->deleteSecurityGroup(), $options);
330
    }
331
332
    public function parseMetadata(ResponseInterface $response): array
333
    {
334
        return Utils::jsonDecode($response)['metadata'];
335
    }
336
337
    /**
338
     * Returns Generator for SecurityGroups
339
     *
340
     * @return \Generator
341
     */
342
    public function listSecurityGroups(): \Generator
343
    {
344
        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 OpenCloud\Common\Resource\ResourceInterface as the method enumerate() does only exist in the following implementations of said interface: OpenCloud\Common\Resource\OperatorResource, OpenCloud\Test\Common\Resource\Server, OpenCloud\Test\Common\Re...ce\TestOperatorResource, OpenCloud\Test\Common\Service\Fixtures\Models\Foo, OpenStack\BlockStorage\v2\Models\Snapshot, OpenStack\BlockStorage\v2\Models\Volume, OpenStack\BlockStorage\v2\Models\VolumeAttachment, OpenStack\BlockStorage\v2\Models\VolumeType, 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...
345
    }
346
347
348
    /**
349
     * Returns Generator for VolumeAttachment
350
     *
351
     * @return \Generator
352
     */
353
    public function listVolumeAttachments(): \Generator
354
    {
355
        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 OpenCloud\Common\Resource\ResourceInterface as the method enumerate() does only exist in the following implementations of said interface: OpenCloud\Common\Resource\OperatorResource, OpenCloud\Test\Common\Resource\Server, OpenCloud\Test\Common\Re...ce\TestOperatorResource, OpenCloud\Test\Common\Service\Fixtures\Models\Foo, OpenStack\BlockStorage\v2\Models\Snapshot, OpenStack\BlockStorage\v2\Models\Volume, OpenStack\BlockStorage\v2\Models\VolumeAttachment, OpenStack\BlockStorage\v2\Models\VolumeType, 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...
356
    }
357
358
    /**
359
     * Attach a volume and returns volume that was attached
360
     *
361
     * @param $volumeId
362
     *
363
     * @return VolumeAttachment
364
     */
365
    public function attachVolume(string $volumeId): VolumeAttachment
366
    {
367
        $response =  $this->execute($this->api->postVolumeAttachments(), ['id' => $this->id, 'volumeId' => $volumeId]);
368
369
        return $this->model(VolumeAttachment::class)->populateFromResponse($response);
370
    }
371
372
    /**
373
     * Detach a volume
374
     *
375
     * @param $attachmentId
376
     *
377
     * @return void
378
     */
379
    public function detachVolume(string $attachmentId)
380
    {
381
        $this->execute($this->api->deleteVolumeAttachments(), ['id' => $this->id, 'attachmentId' => $attachmentId]);
382
    }
383
}
384