diff --git a/composer.json b/composer.json index 76d360e4..b38a5f79 100644 --- a/composer.json +++ b/composer.json @@ -34,15 +34,15 @@ }, "require": { "php": "~7.0", - "guzzlehttp/guzzle": "~6.1", - "justinrainbow/json-schema": "~5.2" + "guzzlehttp/guzzle": "^6.1", + "justinrainbow/json-schema": "^5.2" }, "require-dev": { "phpunit/phpunit": "^6.5", "psr/log": "^1.0", - "satooshi/php-coveralls": "^2.0", + "php-coveralls/php-coveralls": "^2.0", "jakub-onderka/php-parallel-lint": "^1.0", - "friendsofphp/php-cs-fixer": "^2.9" + "friendsofphp/php-cs-fixer": "^2.13" }, "extra": { "branch-alias": { diff --git a/src/BlockStorage/v2/Api.php b/src/BlockStorage/v2/Api.php index 6b591bab..55d0ae0c 100644 --- a/src/BlockStorage/v2/Api.php +++ b/src/BlockStorage/v2/Api.php @@ -29,6 +29,7 @@ public function postVolumes(): array 'imageId' => $this->params->imageRef(), 'volumeType' => $this->params->volumeType(), 'metadata' => $this->params->metadata(), + 'projectId' => $this->params->projectId(), ], ]; } @@ -191,21 +192,21 @@ public function getSnapshots(): array 'method' => 'GET', 'path' => 'snapshots', 'params' => [ - 'marker' => $this->params->marker(), - 'limit' => $this->params->limit(), - 'sortDir' => $this->params->sortDir(), - 'sortKey' => $this->params->sortKey(), + 'marker' => $this->params->marker(), + 'limit' => $this->params->limit(), + 'sortDir' => $this->params->sortDir(), + 'sortKey' => $this->params->sortKey(), + 'allTenants' => $this->params->allTenants(), ], ]; } public function getSnapshotsDetail(): array { - return [ - 'method' => 'GET', - 'path' => 'snapshots/detail', - 'params' => [], - ]; + $api = $this->getSnapshots(); + $api['path'] .= '/detail'; + + return $api; } public function getSnapshot(): array @@ -304,4 +305,45 @@ public function putQuotaSet(): array ], ]; } + + public function postVolumeBootable(): array + { + return [ + 'method' => 'POST', + 'path' => 'volumes/{id}/action', + 'jsonKey' => 'os-set_bootable', + 'params' => [ + 'id' => $this->params->idPath(), + 'bootable' => $this->params->bootable(), + ], + ]; + } + + public function postImageMetadata(): array + { + return [ + 'method' => 'POST', + 'path' => 'volumes/{id}/action', + 'jsonKey' => 'os-set_image_metadata', + 'params' => [ + 'id' => $this->params->idPath(), + 'metadata' => $this->params->metadata(), + ], + ]; + } + + public function postResetStatus(): array + { + return [ + 'method' => 'POST', + 'path' => 'volumes/{id}/action', + 'jsonKey' => 'os-reset_status', + 'params' => [ + 'id' => $this->params->idPath(), + 'status' => $this->params->volumeStatus(), + 'migrationStatus' => $this->params->volumeMigrationStatus(), + 'attachStatus' => $this->params->volumeAttachStatus(), + ], + ]; + } } diff --git a/src/BlockStorage/v2/Models/Snapshot.php b/src/BlockStorage/v2/Models/Snapshot.php index fde510f9..f87c93d4 100644 --- a/src/BlockStorage/v2/Models/Snapshot.php +++ b/src/BlockStorage/v2/Models/Snapshot.php @@ -47,12 +47,16 @@ class Snapshot extends OperatorResource implements Listable, Creatable, Updateab /** @var int */ public $size; + /** @var string */ + public $projectId; + protected $resourceKey = 'snapshot'; protected $resourcesKey = 'snapshots'; protected $markerKey = 'id'; protected $aliases = [ - 'volume_id' => 'volumeId', + 'volume_id' => 'volumeId', + 'os-extended-snapshot-attributes:project_id' => 'projectId', ]; /** diff --git a/src/BlockStorage/v2/Models/Volume.php b/src/BlockStorage/v2/Models/Volume.php index 88fbb79d..01e8a1df 100644 --- a/src/BlockStorage/v2/Models/Volume.php +++ b/src/BlockStorage/v2/Models/Volume.php @@ -62,6 +62,9 @@ class Volume extends OperatorResource implements Creatable, Listable, Updateable /** @var string */ public $host; + /** @var string */ + public $bootable; + /** @var array */ public $metadata = []; @@ -156,4 +159,41 @@ public function parseMetadata(ResponseInterface $response): array return isset($json['metadata']) ? $json['metadata'] : []; } + + /** + * Update the bootable status for a volume, mark it as a bootable volume. + * + * @param bool $bootable + */ + public function setBootable(bool $bootable = true) + { + $this->execute($this->api->postVolumeBootable(), ['id' => $this->id, 'bootable' => $bootable]); + } + + /** + * Sets the image metadata for a volume. + * + * @param array $metadata + */ + public function setImageMetadata(array $metadata) + { + $this->execute($this->api->postImageMetadata(), ['id' => $this->id, 'metadata' => $metadata]); + } + + /** + * Administrator only. Resets the status, attach status, and migration status for a volume. Specify the os-reset_status action in the request body. + * + * @param array $options + * + * $options['status'] = (string) The volume status. + * $options['migrationStatus'] = (string) The volume migration status. + * $options['attachStatus'] = (string) The volume attach status. [OPTIONAL] + * + * @see https://developer.openstack.org/api-ref/block-storage/v2/index.html#volume-actions-volumes-action + */ + public function resetStatus(array $options) + { + $options = array_merge($options, ['id' => $this->id]); + $this->execute($this->api->postResetStatus(), $options); + } } diff --git a/src/BlockStorage/v2/Params.php b/src/BlockStorage/v2/Params.php index 86dd4051..694864fe 100644 --- a/src/BlockStorage/v2/Params.php +++ b/src/BlockStorage/v2/Params.php @@ -80,6 +80,47 @@ public function volumeType(): array ]; } + public function bootable(): array + { + return [ + 'type' => self::BOOL_TYPE, + 'location' => self::JSON, + 'description' => 'Enables or disables the bootable attribute. You can boot an instance from a bootable volume.', + ]; + } + + public function volumeStatus(): array + { + return [ + 'type' => self::STRING_TYPE, + 'location' => self::JSON, + 'required' => true, + 'description' => 'The volume status.', + ]; + } + + public function volumeMigrationStatus(): array + { + return [ + 'type' => self::STRING_TYPE, + 'location' => self::JSON, + 'required' => false, + 'description' => 'The volume migration status.', + 'sentAs' => 'migration_status', + ]; + } + + public function volumeAttachStatus(): array + { + return [ + 'type' => self::STRING_TYPE, + 'location' => self::JSON, + 'required' => false, + 'description' => 'The volume attach status.', + 'sentAs' => 'attach_status', + ]; + } + public function metadata(): array { return [ @@ -226,4 +267,14 @@ public function quotaSetVolumesIscsi(): array { return $this->quotaSetLimit('volumes_iscsi', 'The number of allowed volumes iscsi'); } + + public function projectId(): array + { + return [ + 'type' => self::STRING_TYPE, + 'location' => self::URL, + 'sentAs' => 'project_id', + 'description' => 'The UUID of the project in a multi-tenancy cloud.', + ]; + } } diff --git a/src/Compute/v2/Api.php b/src/Compute/v2/Api.php index d6b235d7..2a8dde1a 100644 --- a/src/Compute/v2/Api.php +++ b/src/Compute/v2/Api.php @@ -667,6 +667,8 @@ public function postKeypair(): array 'params' => [ 'name' => $this->isRequired($this->params->name('keypair')), 'publicKey' => $this->params->keypairPublicKey(), + 'type' => $this->params->keypairType(), + 'userId' => $this->params->keypairUserId(), ], ]; } diff --git a/src/Compute/v2/Models/Keypair.php b/src/Compute/v2/Models/Keypair.php index 4bd2625e..7efd6b21 100644 --- a/src/Compute/v2/Models/Keypair.php +++ b/src/Compute/v2/Models/Keypair.php @@ -37,6 +37,9 @@ class Keypair extends OperatorResource implements Listable, Retrievable, Deletab /** @var string */ public $userId; + /** @var string */ + public $type; + /** @var string */ public $id; @@ -47,6 +50,7 @@ class Keypair extends OperatorResource implements Listable, Retrievable, Deletab 'public_key' => 'publicKey', 'private_key' => 'privateKey', 'user_id' => 'userId', + 'type' => 'type', ]; protected $resourceKey = 'keypair'; diff --git a/src/Compute/v2/Params.php b/src/Compute/v2/Params.php index c071c934..e61ae3ad 100644 --- a/src/Compute/v2/Params.php +++ b/src/Compute/v2/Params.php @@ -475,6 +475,25 @@ public function userId(): array ]; } + public function keypairUserId(): array + { + return [ + 'type' => self::STRING_TYPE, + 'sentAs' => 'user_id', + 'location' => self::JSON, + 'description' => 'This allows administrative users to upload keys for other users than themselves. Requires micro version 2.10.', + ]; + } + + public function keypairType(): array + { + return [ + 'type' => self::STRING_TYPE, + 'location' => self::JSON, + 'description' => 'The type of the keypair. Allowed values are ssh or x509. Require micro version 2.2.', + ]; + } + public function flavorRam(): array { return [ diff --git a/src/Networking/v2/Api.php b/src/Networking/v2/Api.php index 11733b7a..d4cc0e39 100644 --- a/src/Networking/v2/Api.php +++ b/src/Networking/v2/Api.php @@ -35,9 +35,10 @@ public function getNetworks(): array 'method' => 'GET', 'path' => $this->pathPrefix.'/networks', 'params' => [ - 'name' => $this->params->queryName(), - 'tenantId' => $this->params->queryTenantId(), - 'status' => $this->params->queryStatus(), + 'name' => $this->params->queryName(), + 'tenantId' => $this->params->queryTenantId(), + 'status' => $this->params->queryStatus(), + 'routerExternal' => $this->params->queryRouterExternal(), ], ]; } @@ -201,7 +202,7 @@ public function getPorts(): array 'displayName' => $this->params->displayNameQuery(), 'adminState' => $this->params->adminStateQuery(), 'networkId' => $this->notRequired($this->params->networkId()), - 'tenantId' => $this->params->tenantId(), + 'tenantId' => $this->params->tenantIdQuery(), 'deviceOwner' => $this->params->deviceOwnerQuery(), 'macAddress' => $this->params->macAddrQuery(), 'portId' => $this->params->portIdQuery(), @@ -230,6 +231,7 @@ public function postSinglePort(): array 'allowedAddressPairs' => $this->params->allowedAddrPairs(), 'deviceOwner' => $this->params->deviceOwner(), 'deviceId' => $this->params->deviceId(), + 'portSecurityEnabled' => $this->params->portSecurityEnabled(), ], ]; } diff --git a/src/Networking/v2/Extensions/Layer3/Models/FixedIp.php b/src/Networking/v2/Extensions/Layer3/Models/FixedIp.php index 55145135..b22d163c 100644 --- a/src/Networking/v2/Extensions/Layer3/Models/FixedIp.php +++ b/src/Networking/v2/Extensions/Layer3/Models/FixedIp.php @@ -13,6 +13,7 @@ class FixedIp extends AbstractResource public $ip; protected $aliases = [ - 'subnet_id' => 'subnetId', + 'subnet_id' => 'subnetId', + 'ip_address' => 'ip', ]; } diff --git a/src/Networking/v2/Extensions/Layer3/Models/FloatingIp.php b/src/Networking/v2/Extensions/Layer3/Models/FloatingIp.php index 44973ddc..b2959e4e 100644 --- a/src/Networking/v2/Extensions/Layer3/Models/FloatingIp.php +++ b/src/Networking/v2/Extensions/Layer3/Models/FloatingIp.php @@ -74,4 +74,9 @@ public function retrieve() $response = $this->executeWithState($this->api->getFloatingIp()); $this->populateFromResponse($response); } + + public function associatePort(string $portId) + { + $this->execute($this->api->putFloatingIp(), ['id' => $this->id, 'portId' => $portId]); + } } diff --git a/src/Networking/v2/Extensions/Layer3/Models/GatewayInfo.php b/src/Networking/v2/Extensions/Layer3/Models/GatewayInfo.php index ce735b1b..0614fe05 100644 --- a/src/Networking/v2/Extensions/Layer3/Models/GatewayInfo.php +++ b/src/Networking/v2/Extensions/Layer3/Models/GatewayInfo.php @@ -13,7 +13,7 @@ class GatewayInfo extends AbstractResource /** @var string */ public $enableSnat; - /** @var []FixedIp */ + /** @var FixedIp[] */ public $fixedIps; protected $aliases = [ @@ -27,7 +27,7 @@ class GatewayInfo extends AbstractResource protected function getAliases(): array { return parent::getAliases() + [ - 'fixed_ips' => new Alias('fixedIps', FixedIp::class, true), + 'external_fixed_ips' => new Alias('fixedIps', FixedIp::class, true), ]; } } diff --git a/src/Networking/v2/Extensions/SecurityGroups/Api.php b/src/Networking/v2/Extensions/SecurityGroups/Api.php index 1e715faa..e30ddc24 100644 --- a/src/Networking/v2/Extensions/SecurityGroups/Api.php +++ b/src/Networking/v2/Extensions/SecurityGroups/Api.php @@ -24,7 +24,10 @@ public function getSecurityGroups() return [ 'method' => 'GET', 'path' => $this->pathPrefix.'/security-groups', - 'params' => [], + 'params' => [ + 'tenantId' => $this->params->queryTenantId(), + 'name' => $this->params->filterName(), + ], ]; } diff --git a/src/Networking/v2/Extensions/SecurityGroups/Params.php b/src/Networking/v2/Extensions/SecurityGroups/Params.php index 09f4c24f..88325a73 100644 --- a/src/Networking/v2/Extensions/SecurityGroups/Params.php +++ b/src/Networking/v2/Extensions/SecurityGroups/Params.php @@ -89,4 +89,13 @@ public function tenantIdJson() 'description' => 'The UUID of the tenant who owns the security group rule. Only administrative users can specify a tenant UUID other than their own.', ]; } + + public function filterName(): array + { + return [ + 'description' => sprintf('Filter the list result by the human-readable name of the resource'), + 'type' => self::STRING_TYPE, + 'location' => self::QUERY, + ]; + } } diff --git a/src/Networking/v2/Extensions/SecurityGroups/Service.php b/src/Networking/v2/Extensions/SecurityGroups/Service.php index ad78bc5c..aeda22ab 100644 --- a/src/Networking/v2/Extensions/SecurityGroups/Service.php +++ b/src/Networking/v2/Extensions/SecurityGroups/Service.php @@ -22,11 +22,13 @@ private function securityGroupRule(array $info = []): SecurityGroupRule } /** + * @param array $options + * * @return \Generator */ - public function listSecurityGroups(): \Generator + public function listSecurityGroups(array $options = []): \Generator { - return $this->securityGroup()->enumerate($this->api->getSecurityGroups()); + return $this->securityGroup()->enumerate($this->api->getSecurityGroups(), $options); } /** diff --git a/src/Networking/v2/Models/Network.php b/src/Networking/v2/Models/Network.php index ab92bfa6..7af74b2a 100644 --- a/src/Networking/v2/Models/Network.php +++ b/src/Networking/v2/Models/Network.php @@ -41,9 +41,13 @@ class Network extends OperatorResource implements Listable, Retrievable, Creatab /** @var string */ public $tenantId; + /** @var bool */ + public $routerExternal; + protected $aliases = [ - 'admin_state_up' => 'adminStateUp', - 'tenant_id' => 'tenantId', + 'admin_state_up' => 'adminStateUp', + 'tenant_id' => 'tenantId', + 'router:external' => 'routerExternal', ]; protected $resourceKey = 'network'; diff --git a/src/Networking/v2/Models/Port.php b/src/Networking/v2/Models/Port.php index e67b123b..d3144870 100644 --- a/src/Networking/v2/Models/Port.php +++ b/src/Networking/v2/Models/Port.php @@ -36,7 +36,7 @@ class Port extends OperatorResource implements Creatable, Updateable, Deletable, /** * A set of zero or more allowed address pairs. An address pair consists of an IP address and MAC address. * - * @var []string + * @var array */ public $allowedAddressPairs; @@ -119,19 +119,22 @@ class Port extends OperatorResource implements Creatable, Updateable, Deletable, public $portSecurityEnabled; protected $aliases = [ - 'admin_state_up' => 'adminStateUp', - 'display_name' => 'displayName', - 'network_id' => 'networkId', - 'tenant_id' => 'tenantId', - 'device_owner' => 'deviceOwner', - 'mac_address' => 'macAddress', - 'port_id' => 'portId', - 'security_groups' => 'securityGroups', - 'device_id' => 'deviceId', - 'fixed_ips' => 'fixedIps', + 'port_security_enabled' => 'portSecurityEnabled', + 'admin_state_up' => 'adminStateUp', + 'display_name' => 'displayName', + 'network_id' => 'networkId', + 'tenant_id' => 'tenantId', + 'device_owner' => 'deviceOwner', + 'mac_address' => 'macAddress', + 'port_id' => 'portId', + 'security_groups' => 'securityGroups', + 'device_id' => 'deviceId', + 'fixed_ips' => 'fixedIps', + 'allowed_address_pairs' => 'allowedAddressPairs', ]; - protected $resourceKey = 'port'; + protected $resourceKey = 'port'; + protected $resourcesKey = 'ports'; /** * {@inheritdoc} diff --git a/src/Networking/v2/Params.php b/src/Networking/v2/Params.php index abbe9dc4..50bc8828 100644 --- a/src/Networking/v2/Params.php +++ b/src/Networking/v2/Params.php @@ -61,6 +61,17 @@ public function adminStateUp(): array ]; } + public function portSecurityEnabled(): array + { + return [ + 'type' => self::BOOL_TYPE, + 'location' => self::JSON, + 'sentAs' => 'port_security_enabled', + 'description' => 'The port security status. A valid value is enabled (true) or disabled (false). If port security is enabled for the port, security + group rules and anti-spoofing rules are applied to the traffic on the port. If disabled, no such rules are applied.', + ]; + } + public function networkId(): array { return [ @@ -100,6 +111,16 @@ public function tenantId(): array ]; } + public function projectId(): array + { + return [ + 'type' => self::STRING_TYPE, + 'sentAs' => 'project_id', + 'location' => self::QUERY, + 'description' => 'The ID of the tenant who owns the network. Only administrative users can specify a tenant ID other than their own. You cannot change this value through authorization policies', + ]; + } + public function gatewayIp(): array { return [ @@ -337,6 +358,7 @@ public function secGroupIds(): array return [ 'type' => self::ARRAY_TYPE, 'location' => self::JSON, + 'sentAs' => 'security_groups', 'items' => [ 'type' => self::STRING_TYPE, 'description' => 'The UUID of the security group', @@ -426,6 +448,15 @@ public function routerAccessibleJson(): array ]; } + public function queryRouterExternal(): array + { + return [ + 'type' => self::BOOL_TYPE, + 'location' => self::QUERY, + 'sentAs' => 'router:external', + ]; + } + protected function quotaLimit(string $sentAs, string $description): array { return [ diff --git a/src/ObjectStore/v1/Models/StorageObject.php b/src/ObjectStore/v1/Models/StorageObject.php index cd406189..a4016d2d 100644 --- a/src/ObjectStore/v1/Models/StorageObject.php +++ b/src/ObjectStore/v1/Models/StorageObject.php @@ -35,7 +35,7 @@ class StorageObject extends OperatorResource implements Creatable, Deletable, Ha /** @var string */ public $contentType; - /** @var int */ + /** @var string */ public $contentLength; /** @var \DateTimeImmutable */ diff --git a/tests/unit/BlockStorage/v2/Models/VolumeTest.php b/tests/unit/BlockStorage/v2/Models/VolumeTest.php index 2914df7d..17c0bdbb 100644 --- a/tests/unit/BlockStorage/v2/Models/VolumeTest.php +++ b/tests/unit/BlockStorage/v2/Models/VolumeTest.php @@ -88,4 +88,44 @@ public function test_it_resets_metadata() $this->volume->resetMetadata(['key1' => 'val1']); } + + public function test_it_sets_volume_bootable() + { + $this->setupMock('POST', 'volumes/1/action', ['os-set_bootable' => ['bootable' => 'True']], [], new Response(200)); + + $this->volume->setBootable(true); + } + + public function test_it_sets_image_meta_data() + { + $expectedJson = [ + 'os-set_image_metadata' => [ + 'metadata' => [ + 'attr_foo' => 'foofoo', + 'attr_bar' => 'barbar', + ], + ], + ]; + + $this->setupMock('POST', 'volumes/1/action', $expectedJson, [], new Response(200)); + $this->volume->setImageMetadata([ + 'attr_foo' => 'foofoo', + 'attr_bar' => 'barbar', + ]); + } + + public function test_it_resets_status() + { + $expectedJson = ['os-reset_status' => ['status' => 'available', 'attach_status' => 'detached', 'migration_status' => 'migrating']]; + + $this->setupMock('POST', 'volumes/1/action', $expectedJson, [], new Response(202)); + + $this->volume->resetStatus( + [ + 'status' => 'available', + 'attachStatus' => 'detached', + 'migrationStatus' => 'migrating', + ] + ); + } } diff --git a/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/Router.resp b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/Router.resp index 79fed195..96123b41 100644 --- a/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/Router.resp +++ b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/Router.resp @@ -3,21 +3,44 @@ Content-Type: application/json { "router": { - "status": "ACTIVE", + "admin_state_up": true, + "availability_zone_hints": [], + "availability_zones": [ + "nova" + ], + "created_at": "2018-03-19T19:17:04Z", + "description": "", + "distributed": false, "external_gateway_info": { - "network_id": "85d76829-6415-48ff-9c63-5c5ca8c61ac6", "enable_snat": true, "external_fixed_ips": [ { - "subnet_id": "255.255.255.0", - "ip": "192.168.10.2" + "ip_address": "172.24.4.6", + "subnet_id": "b930d7f6-ceb7-40a0-8b81-a425dd994ccf" + }, + { + "ip_address": "2001:db8::9", + "subnet_id": "0c56df5d-ace5-46c8-8f4c-45fa4e334d18" } - ] + ], + "network_id": "ae34051f-aa6c-4c75-abf5-50dc9ac99ef3" }, + "flavor_id": "f7b14d9a-b0dc-4fbe-bb14-a0f4970a69e0", + "ha": false, + "id": "f8a44de0-fc8e-45df-93c7-f79bf3b01c95", "name": "router1", - "admin_state_up": true, - "tenant_id": "d6554fe62e2f41efbb6e026fad5c1542", - "routes": [], - "id": "a07eea83-7710-4860-931b-5fe220fae533" + "revision_number": 1, + "routes": [ + { + "destination": "179.24.1.0/24", + "nexthop": "172.24.3.99" + } + ], + "status": "ACTIVE", + "updated_at": "2018-03-19T19:17:22Z", + "project_id": "0bd18306d801447bb457a46252d82d13", + "tenant_id": "0bd18306d801447bb457a46252d82d13", + "service_type_id": null, + "tags": ["tag1,tag2"] } -} \ No newline at end of file +} diff --git a/tests/unit/Networking/v2/Extensions/Layer3/Models/FloatingIpTest.php b/tests/unit/Networking/v2/Extensions/Layer3/Models/FloatingIpTest.php index f7e5e51f..01d778d2 100644 --- a/tests/unit/Networking/v2/Extensions/Layer3/Models/FloatingIpTest.php +++ b/tests/unit/Networking/v2/Extensions/Layer3/Models/FloatingIpTest.php @@ -79,4 +79,11 @@ public function test_it_retrieves() $this->floatingIp->id ); } + + public function test_it_associates_port() + { + $this->setupMock('PUT', 'v2.0/floatingips/id', ['floatingip' => ['port_id' => 'some-port-id']], [], 'FloatingIp'); + + $this->floatingIp->associatePort('some-port-id'); + } } diff --git a/tests/unit/Networking/v2/Extensions/Layer3/Models/RouterTest.php b/tests/unit/Networking/v2/Extensions/Layer3/Models/RouterTest.php index 0962c0a1..6b2d3ce2 100644 --- a/tests/unit/Networking/v2/Extensions/Layer3/Models/RouterTest.php +++ b/tests/unit/Networking/v2/Extensions/Layer3/Models/RouterTest.php @@ -69,6 +69,9 @@ public function test_it_retrieves() $this->setupMock('GET', 'v2.0/routers/id', null, [], 'Router'); $this->router->retrieve(); + + $this->assertEquals('f8a44de0-fc8e-45df-93c7-f79bf3b01c95', $this->router->id); + $this->assertCount(2, $this->router->externalGatewayInfo->fixedIps); } public function test_it_adds_interface() diff --git a/tests/unit/Networking/v2/Fixtures/port_get.resp b/tests/unit/Networking/v2/Fixtures/port_get.resp index 14a7f70c..4bc2a1b3 100644 --- a/tests/unit/Networking/v2/Fixtures/port_get.resp +++ b/tests/unit/Networking/v2/Fixtures/port_get.resp @@ -4,14 +4,14 @@ Content-Type: application/json { "port": { "status": "ACTIVE", - "name": "", + "name": "port-name", "allowed_address_pairs": [], "admin_state_up": true, "network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7", "tenant_id": "7e02058126cc4950b75f9970368ba177", "extra_dhcp_opts": [], "device_owner": "network:router_interface", - "mac_address": "fa:16:3e:23:fd:d7", + "mac_address": "00:11:22:33:44:55", "fixed_ips": [ { "subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2", @@ -20,6 +20,7 @@ Content-Type: application/json ], "id": "46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2", "security_groups": [], - "device_id": "5e3898d7-11be-483e-9732-b2f5eccd2b2e" + "device_id": "fake-device-id", + "port_security_enabled": true } } \ No newline at end of file diff --git a/tests/unit/Networking/v2/Models/PortTest.php b/tests/unit/Networking/v2/Models/PortTest.php index a66b72a2..8450de3c 100644 --- a/tests/unit/Networking/v2/Models/PortTest.php +++ b/tests/unit/Networking/v2/Models/PortTest.php @@ -49,9 +49,18 @@ public function test_it_updates() public function test_it_retrieves() { - $this->setupMock('GET', 'v2.0/ports/' . self::PORT_ID, null, [], new Response(204)); + $this->setupMock('GET', 'v2.0/ports/' . self::PORT_ID, null, [], 'port_get'); $this->port->retrieve(); + $this->assertEquals('46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2', $this->port->id); + $this->assertEquals('ACTIVE', $this->port->status); + $this->assertEquals('port-name', $this->port->name); + $this->assertEquals(true, $this->port->adminStateUp); + $this->assertEquals(true,$this->port->portSecurityEnabled); + $this->assertEquals('network:router_interface', $this->port->deviceOwner); + $this->assertEquals('fake-device-id', $this->port->deviceId); + $this->assertEquals('00:11:22:33:44:55', $this->port->macAddress); + $this->assertCount(1, $this->port->fixedIps); } public function test_it_deletes()