diff --git a/samples/networking/v2/floatingIPs/create.php b/samples/networking/v2/floatingIPs/create.php new file mode 100644 index 00000000..96c1cb27 --- /dev/null +++ b/samples/networking/v2/floatingIPs/create.php @@ -0,0 +1,21 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$networking = $openstack->networkingV2ExtLayer3(); + +/** @var \OpenStack\Networking\v2\Extensions\Layer3\Models\FloatingIp $ip */ +$ip = $networking->createFloatingIp([ + "floatingNetworkId" => "{networkId}", + "portId" => "{portId}", +]); diff --git a/samples/networking/v2/floatingIPs/delete.php b/samples/networking/v2/floatingIPs/delete.php new file mode 100644 index 00000000..6accb015 --- /dev/null +++ b/samples/networking/v2/floatingIPs/delete.php @@ -0,0 +1,17 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$openstack->networkingV2ExtLayer3() + ->getFloatingIp('{id}') + ->delete(); diff --git a/samples/networking/v2/floatingIPs/get.php b/samples/networking/v2/floatingIPs/get.php new file mode 100644 index 00000000..54ff62ca --- /dev/null +++ b/samples/networking/v2/floatingIPs/get.php @@ -0,0 +1,17 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +/** @var \OpenStack\Networking\v2\Extensions\Layer3\Models\FloatingIp $ip */ +$ip = $openstack->networkingV2ExtLayer3() + ->getFloatingIp('{id}'); diff --git a/samples/networking/v2/floatingIPs/list.php b/samples/networking/v2/floatingIPs/list.php new file mode 100644 index 00000000..da87c819 --- /dev/null +++ b/samples/networking/v2/floatingIPs/list.php @@ -0,0 +1,20 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$floatingIps = $openstack->networkingV2ExtLayer3() + ->listFloatingIps(); + +foreach ($floatingIps as $floatingIp) { + /** @var \OpenStack\Networking\v2\Extensions\Layer3\Models\FloatingIp $floatingIp */ +} diff --git a/samples/networking/v2/floatingIPs/update.php b/samples/networking/v2/floatingIPs/update.php new file mode 100644 index 00000000..9698d30d --- /dev/null +++ b/samples/networking/v2/floatingIPs/update.php @@ -0,0 +1,19 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$floatingIp = $openstack->networkingV2ExtLayer3() + ->getFloatingIp('{id}'); + +$floatingIp->portId = '{newPortId}'; +$floatingIp->update(); diff --git a/samples/networking/v2/securityGroupRules/create.php b/samples/networking/v2/securityGroupRules/create.php new file mode 100644 index 00000000..70ac6094 --- /dev/null +++ b/samples/networking/v2/securityGroupRules/create.php @@ -0,0 +1,26 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$networking = $openstack->networkingV2ExtSecGroups(); + +/** @var \OpenStack\Networking\v2\Extensions\SecurityGroups\Models\SecurityGroupRule $rule */ +$rule = $networking->createSecurityGroupRule([ + "direction" => "ingress", + "ethertype" => "IPv4", + "portRangeMin" => "80", + "portRangeMax" => "80", + "protocol" => "tcp", + "remoteGroupId" => "{groupId}", + "securityGroupId" => "{secGroupId}", +]); diff --git a/samples/networking/v2/securityGroupRules/delete.php b/samples/networking/v2/securityGroupRules/delete.php new file mode 100644 index 00000000..52b56e5f --- /dev/null +++ b/samples/networking/v2/securityGroupRules/delete.php @@ -0,0 +1,19 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +/** @var \OpenStack\Networking\v2\Extensions\SecurityGroups\Models\SecurityGroupRule $rule */ +$rule = $openstack->networkingV2ExtSecGroups() + ->getSecurityGroupRule('{id}'); + +$rule->delete(); diff --git a/samples/networking/v2/securityGroupRules/get.php b/samples/networking/v2/securityGroupRules/get.php new file mode 100644 index 00000000..085e5acf --- /dev/null +++ b/samples/networking/v2/securityGroupRules/get.php @@ -0,0 +1,17 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +/** @var \OpenStack\Networking\v2\Extensions\SecurityGroups\Models\SecurityGroupRule $rule */ +$rule = $openstack->networkingV2ExtSecGroups() + ->getSecurityGroupRule('{id}'); diff --git a/samples/networking/v2/securityGroupRules/list.php b/samples/networking/v2/securityGroupRules/list.php new file mode 100644 index 00000000..de1e9701 --- /dev/null +++ b/samples/networking/v2/securityGroupRules/list.php @@ -0,0 +1,20 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$rules = $openstack->networkingV2ExtSecGroups() + ->listSecurityGroupRules(); + +foreach ($rules as $rule) { + /** @var \OpenStack\Networking\v2\Extensions\SecurityGroups\Models\SecurityGroupRule $rule */ +} diff --git a/samples/networking/v2/securityGroups/create.php b/samples/networking/v2/securityGroups/create.php new file mode 100644 index 00000000..32ddb0f7 --- /dev/null +++ b/samples/networking/v2/securityGroups/create.php @@ -0,0 +1,21 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$networking = $openstack->networkingV2ExtSecGroups(); + +/** @var \OpenStack\Networking\v2\Extensions\SecurityGroups\Models\SecurityGroup $secGroup */ +$secGroup = $networking->createSecurityGroup([ + 'name' => 'new-webservers', + 'description' => 'security group for webservers', +]); diff --git a/samples/networking/v2/securityGroups/delete.php b/samples/networking/v2/securityGroups/delete.php new file mode 100644 index 00000000..69bb2ba7 --- /dev/null +++ b/samples/networking/v2/securityGroups/delete.php @@ -0,0 +1,19 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$networking = $openstack->networkingV2ExtSecGroups(); + +/** @var \OpenStack\Networking\v2\Extensions\SecurityGroups\Models\SecurityGroup $secGroup */ +$secGroup = $networking->getSecurityGroup('{id}'); +$secGroup->delete(); diff --git a/samples/networking/v2/securityGroups/get.php b/samples/networking/v2/securityGroups/get.php new file mode 100644 index 00000000..26f46278 --- /dev/null +++ b/samples/networking/v2/securityGroups/get.php @@ -0,0 +1,19 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$networking = $openstack->networkingV2ExtSecGroups(); + +/** @var \OpenStack\Networking\v2\Extensions\SecurityGroups\Models\SecurityGroup $secGroup */ +$secGroup = $networking->getSecurityGroup('{id}'); +$secGroup->retrieve(); diff --git a/samples/networking/v2/securityGroups/list.php b/samples/networking/v2/securityGroups/list.php new file mode 100644 index 00000000..2a423f36 --- /dev/null +++ b/samples/networking/v2/securityGroups/list.php @@ -0,0 +1,21 @@ + '{authUrl}', + 'region' => '{region}', + 'user' => [ + 'id' => '{userId}', + 'password' => '{password}' + ], + 'scope' => ['project' => ['id' => '{projectId}']] +]); + +$networking = $openstack->networkingV2ExtSecGroups(); + +$secGroups = $networking->listSecurityGroups(); + +foreach ($secGroups as $secGroup) { + /** @var \OpenStack\Networking\v2\Extensions\SecurityGroups\Models\SecurityGroup $secGroup */ +} diff --git a/samples/networking/v2/subnets/create.php b/samples/networking/v2/subnets/create.php index 4f741e4d..07287476 100644 --- a/samples/networking/v2/subnets/create.php +++ b/samples/networking/v2/subnets/create.php @@ -9,11 +9,7 @@ 'id' => '{userId}', 'password' => '{password}' ], - 'scope' => [ - 'project' => [ - 'id' => '{projectId}' - ] - ] + 'scope' => ['project' => ['id' => '{projectId}']] ]); $networking = $openstack->networkingV2(); diff --git a/src/BlockStorage/v2/Models/Snapshot.php b/src/BlockStorage/v2/Models/Snapshot.php index 072d8415..aead6c9c 100644 --- a/src/BlockStorage/v2/Models/Snapshot.php +++ b/src/BlockStorage/v2/Models/Snapshot.php @@ -2,7 +2,7 @@ namespace OpenStack\BlockStorage\v2\Models; -use OpenCloud\Common\Resource\AbstractResource; +use OpenCloud\Common\Resource\OperatorResource; use OpenCloud\Common\Resource\Creatable; use OpenCloud\Common\Resource\Deletable; use OpenCloud\Common\Resource\HasMetadata; @@ -16,7 +16,7 @@ /** * @property \OpenStack\BlockStorage\v2\Api $api */ -class Snapshot extends AbstractResource implements Listable, Creatable, Updateable, Deletable, Retrievable, HasMetadata +class Snapshot extends OperatorResource implements Listable, Creatable, Updateable, Deletable, Retrievable, HasMetadata { use HasWaiterTrait; diff --git a/src/BlockStorage/v2/Models/Volume.php b/src/BlockStorage/v2/Models/Volume.php index 50be8759..4cdd60f2 100644 --- a/src/BlockStorage/v2/Models/Volume.php +++ b/src/BlockStorage/v2/Models/Volume.php @@ -1,7 +1,7 @@ 'POST', 'jsonKey' => 'network', 'params' => [ - 'name' => $this->params->name('network'), - 'shared' => $this->params->shared(), - 'adminStateUp' => $this->params->adminStateUp(), + 'name' => $this->params->name('network'), + 'shared' => $this->params->shared(), + 'adminStateUp' => $this->params->adminStateUp(), + 'routerAccessible' => $this->params->routerAccessibleJson(), + 'tenantId' => $this->params->tenantId(), ], ]; } diff --git a/src/Networking/v2/Extensions/Layer3/Api.php b/src/Networking/v2/Extensions/Layer3/Api.php new file mode 100644 index 00000000..002d2a43 --- /dev/null +++ b/src/Networking/v2/Extensions/Layer3/Api.php @@ -0,0 +1,168 @@ +params = new Params(); + } + + public function postFloatingIps(): array + { + return [ + 'method' => 'POST', + 'path' => $this->pathPrefix . '/floatingips', + 'jsonKey' => 'floatingip', + 'params' => [ + 'tenantId' => $this->params->tenantIdJson(), + 'floatingNetworkId' => $this->params->floatingNetworkIdJson(), + 'fixedIpAddress' => $this->params->fixedIpAddressJson(), + 'floatingIpAddress' => $this->params->floatingIpAddressJson(), + 'portId' => $this->params->portIdJson(), + ], + ]; + } + + public function getFloatingIps(): array + { + return [ + 'method' => 'GET', + 'path' => $this->pathPrefix . '/floatingips', + 'params' => [], + ]; + } + + public function putFloatingIp(): array + { + return [ + 'method' => 'PUT', + 'path' => $this->pathPrefix . '/floatingips/{id}', + 'jsonKey' => 'floatingip', + 'params' => [ + 'id' => $this->params->idPath(), + 'floatingNetworkId' => $this->params->floatingNetworkIdJson(), + 'fixedIpAddress' => $this->params->fixedIpAddressJson(), + 'floatingIpAddress' => $this->params->floatingIpAddressJson(), + 'portId' => $this->params->portIdJson(), + ], + ]; + } + + public function getFloatingIp(): array + { + return [ + 'method' => 'GET', + 'path' => $this->pathPrefix . '/floatingips/{id}', + 'params' => [ + 'id' => $this->params->idPath(), + 'portId' => $this->params->portIdJson(), + ], + ]; + } + + public function deleteFloatingIp(): array + { + return [ + 'method' => 'DELETE', + 'path' => $this->pathPrefix . '/floatingips/{id}', + 'params' => [ + 'id' => $this->params->idPath(), + ], + ]; + } + + public function postRouters(): array + { + return [ + 'method' => 'POST', + 'path' => $this->pathPrefix . '/routers', + 'jsonKey' => 'router', + 'params' => [ + 'name' => $this->params->nameJson(), + 'externalGatewayInfo' => $this->params->externalGatewayInfo(), + 'adminStateUp' => $this->params->adminStateUp(), + 'tenantId' => $this->params->tenantId(), + 'distributed' => $this->params->distributedJson(), + 'ha' => $this->params->haJson(), + ], + ]; + } + + public function getRouters(): array + { + return [ + 'method' => 'GET', + 'path' => $this->pathPrefix . '/routers', + 'params' => [], + ]; + } + + public function putRouter(): array + { + return [ + 'method' => 'PUT', + 'path' => $this->pathPrefix . '/routers/{id}', + 'jsonKey' => 'router', + 'params' => [ + 'id' => $this->params->idPath(), + 'name' => $this->params->nameJson(), + 'externalGatewayInfo' => $this->params->externalGatewayInfo(), + 'adminStateUp' => $this->params->adminStateUp(), + ], + ]; + } + + public function getRouter(): array + { + return [ + 'method' => 'GET', + 'path' => $this->pathPrefix . '/routers/{id}', + 'params' => [ + 'id' => $this->params->idPath(), + ], + ]; + } + + public function deleteRouter(): array + { + return [ + 'method' => 'DELETE', + 'path' => $this->pathPrefix . '/routers/{id}', + 'params' => [ + 'id' => $this->params->idPath(), + ], + ]; + } + + public function putAddInterface() + { + return [ + 'method' => 'PUT', + 'path' => $this->pathPrefix . '/routers/{id}/add_router_interface', + 'params' => [ + 'id' => $this->params->idPath(), + 'subnetId' => $this->params->subnetId(), + 'portId' => $this->params->portIdJson(), + ], + ]; + } + + public function putRemoveInterface() + { + return [ + 'method' => 'PUT', + 'path' => $this->pathPrefix . '/routers/{id}/remove_router_interface', + 'params' => [ + 'id' => $this->params->idPath(), + 'subnetId' => $this->params->subnetId(), + 'portId' => $this->params->portIdJson(), + ], + ]; + } +} diff --git a/src/Networking/v2/Extensions/Layer3/Models/FixedIp.php b/src/Networking/v2/Extensions/Layer3/Models/FixedIp.php new file mode 100644 index 00000000..f328dbef --- /dev/null +++ b/src/Networking/v2/Extensions/Layer3/Models/FixedIp.php @@ -0,0 +1,18 @@ + 'subnetId' + ]; +} diff --git a/src/Networking/v2/Extensions/Layer3/Models/FloatingIp.php b/src/Networking/v2/Extensions/Layer3/Models/FloatingIp.php new file mode 100644 index 00000000..2798648c --- /dev/null +++ b/src/Networking/v2/Extensions/Layer3/Models/FloatingIp.php @@ -0,0 +1,75 @@ + 'floatingNetworkId', + "router_id" => 'routerId', + "fixed_ip_address" => 'fixedIpAddress', + "floating_ip_address" => 'floatingIpAddress', + "tenant_id" => 'tenantId', + "port_id" => 'portId', + ]; + + protected $resourceKey = 'floatingip'; + protected $resourcesKey = 'floatingips'; + + public function create(array $userOptions): Creatable + { + $response = $this->execute($this->api->postFloatingIps(), $userOptions); + return $this->populateFromResponse($response); + } + + public function update() + { + $response = $this->executeWithState($this->api->putFloatingIp()); + $this->populateFromResponse($response); + } + + public function delete() + { + $this->executeWithState($this->api->deleteFloatingIp()); + } + + public function retrieve() + { + $this->executeWithState($this->api->getFloatingIp()); + } +} diff --git a/src/Networking/v2/Extensions/Layer3/Models/GatewayInfo.php b/src/Networking/v2/Extensions/Layer3/Models/GatewayInfo.php new file mode 100644 index 00000000..58364995 --- /dev/null +++ b/src/Networking/v2/Extensions/Layer3/Models/GatewayInfo.php @@ -0,0 +1,23 @@ + 'networkId', + 'enable_snat' => 'enableSnat', + 'fixed_ips' => 'fixedIps', + ]; +} diff --git a/src/Networking/v2/Extensions/Layer3/Models/Router.php b/src/Networking/v2/Extensions/Layer3/Models/Router.php new file mode 100644 index 00000000..f33c3db6 --- /dev/null +++ b/src/Networking/v2/Extensions/Layer3/Models/Router.php @@ -0,0 +1,83 @@ + 'externalGatewayInfo', + 'admin_state_up' => 'adminStateUp', + 'tenant_id' => 'tenantId', + ]; + + public function create(array $userOptions): Creatable + { + $response = $this->execute($this->api->postRouters(), $userOptions); + return $this->populateFromResponse($response); + } + + public function update() + { + $this->executeWithState($this->api->putRouter()); + } + + public function retrieve() + { + $this->executeWithState($this->api->getRouter()); + } + + public function delete() + { + $this->executeWithState($this->api->deleteRouter()); + } + + /** + * @param array $userOptions {@see \OpenStack\Networking\v2\Extensions\Layer3\Api::putAddInterface} + */ + public function addInterface(array $userOptions) + { + $userOptions['id'] = $this->id; + $this->execute($this->api->putAddInterface(), $userOptions); + } + + /** + * @param array $userOptions {@see \OpenStack\Networking\v2\Extensions\Layer3\Api::putRemoveInterface} + */ + public function removeInterface(array $userOptions) + { + $userOptions['id'] = $this->id; + $this->execute($this->api->putRemoveInterface(), $userOptions); + } +} diff --git a/src/Networking/v2/Extensions/Layer3/Params.php b/src/Networking/v2/Extensions/Layer3/Params.php new file mode 100644 index 00000000..57856cb5 --- /dev/null +++ b/src/Networking/v2/Extensions/Layer3/Params.php @@ -0,0 +1,116 @@ + self::STRING_TYPE, + 'description' => 'The UUID of the tenant. Only administrative users can specify a tenant UUID other than their own.', + 'sentAs' => 'tenant_id', + ]; + } + + public function floatingNetworkIdJson() + { + return [ + 'type' => self::STRING_TYPE, + 'description' => 'The UUID of the network associated with the floating IP.', + 'sentAs' => 'floating_network_id', + 'required' => true, + ]; + } + + public function fixedIpAddressJson() + { + return [ + 'type' => self::STRING_TYPE, + 'description' => 'The fixed IP address that is associated with the floating IP. To associate the floating IP with a fixed IP at creation time, you must specify the identifier of the internal port. If an internal port has multiple associated IP addresses, the service chooses the first IP address unless you explicitly define a fixed IP address in the fixed_ip_address parameter.', + 'sentAs' => 'fixed_ip_address', + ]; + } + + public function floatingIpAddressJson() + { + return [ + 'type' => self::STRING_TYPE, + 'description' => 'The floating IP address.', + 'sentAs' => 'fixed_ip_address', + ]; + } + + public function portIdJson() + { + return [ + 'type' => self::STRING_TYPE, + 'description' => 'The UUID of the port.', + 'sentAs' => 'port_id', + ]; + } + + public function enableSnatJson(): array + { + return [ + 'type' => self::BOOL_TYPE, + 'description' => 'Enable Source NAT (SNAT) attribute, a part of ext-gw-mode extension. When a gateway is attached to a router using an L3 extension, Network Address Translation (NAT) is enabled for traffic generated by subnets attached to the router.', + 'location' => self::JSON, + 'sentAs' => 'enable_snat', + ]; + } + + public function ipJson(): array + { + return [ + 'type' => self::STRING_TYPE, + ]; + } + + public function externalFixedIpsJson(): array + { + return [ + 'type' => self::ARRAY_TYPE, + 'location' => self::JSON, + 'sentAs' => 'external_fixed_ips', + 'items' => [ + 'type' => self::OBJECT_TYPE, + 'properties' => [ + 'subnetId' => $this->subnetId(), + 'ip' => $this->ipJson(), + ], + ], + ]; + } + + public function externalGatewayInfo(): array + { + return [ + 'type' => self::OBJECT_TYPE, + 'sentAs' => 'external_gateway_info', + 'properties' => [ + 'networkId' => $this->networkId(), + 'enableSnat' => $this->enableSnatJson(), + 'fixedIps' => $this->externalFixedIpsJson(), + ], + ]; + } + + public function distributedJson(): array + { + return [ + 'type' => self::BOOL_TYPE, + 'location' => self::JSON, + 'description' => 'If true, indicates a distributed router.', + ]; + } + + public function haJson(): array + { + return [ + 'type' => self::BOOL_TYPE, + 'location' => self::JSON, + 'description' => 'If true, indicates a highly-available router.', + ]; + } +} diff --git a/src/Networking/v2/Extensions/Layer3/Service.php b/src/Networking/v2/Extensions/Layer3/Service.php new file mode 100644 index 00000000..a510c258 --- /dev/null +++ b/src/Networking/v2/Extensions/Layer3/Service.php @@ -0,0 +1,75 @@ +model(FloatingIp::class, $info); + } + + private function router(array $info = []): Router + { + return $this->model(Router::class, $info); + } + + /** + * @param array $options + * + * @return FloatingIp + */ + public function createFloatingIp(array $options): FloatingIp + { + return $this->floatingIp()->create($options); + } + + /** + * @return FloatingIp + */ + public function getFloatingIp($id): FloatingIp + { + return $this->floatingIp(['id' => $id]); + } + + /** + * @return \Generator + */ + public function listFloatingIps(): \Generator + { + return $this->floatingIp()->enumerate($this->api->getFloatingIps()); + } + + /** + * @param array $options + * + * @return Router + */ + public function createRouter(array $options): Router + { + return $this->router()->create($options); + } + + /** + * @return Router + */ + public function getRouter($id): Router + { + return $this->router(['id' => $id]); + } + + /** + * @return \Generator + */ + public function listRouters(): \Generator + { + return $this->router()->enumerate($this->api->getRouters()); + } +} diff --git a/src/Networking/v2/Extensions/SecurityGroups/Api.php b/src/Networking/v2/Extensions/SecurityGroups/Api.php new file mode 100644 index 00000000..0f2c1680 --- /dev/null +++ b/src/Networking/v2/Extensions/SecurityGroups/Api.php @@ -0,0 +1,152 @@ +params = new Params(); + } + + /** + * Returns information about GET security-groups/{security_group_id} HTTP + * operation + * + * @return array + */ + public function getSecurityGroups() + { + return [ + 'method' => 'GET', + 'path' => 'security-groups', + 'params' => [], + ]; + } + + /** + * Returns information about POST security-groups HTTP operation + * + * @return array + */ + public function postSecurityGroups() + { + return [ + 'method' => 'POST', + 'path' => 'security-groups', + 'jsonKey' => 'security_group', + 'params' => [ + 'description' => $this->params->descriptionJson(), + 'name' => $this->params->nameJson(), + ], + ]; + } + + /** + * Returns information about GET security-groups/{security_group_id} HTTP + * operation + * + * @return array + */ + public function getSecurityGroup() + { + return [ + 'method' => 'GET', + 'path' => 'security-groups/{id}', + 'params' => [ + 'id' => $this->params->idPath(), + ], + ]; + } + + /** + * Returns information about DELETE security-groups/{security_group_id} HTTP + * operation + * + * @return array + */ + public function deleteSecurityGroup() + { + return [ + 'method' => 'DELETE', + 'path' => 'security-groups/{id}', + 'params' => [ + 'id' => $this->params->idPath(), + ], + ]; + } + + /** + * Returns information about GET security-group-rules HTTP operation + * + * @return array + */ + public function getSecurityRules() + { + return [ + 'method' => 'GET', + 'path' => 'security-group-rules', + 'params' => [], + ]; + } + + /** + * Returns information about POST security-group-rules HTTP operation + * + * @return array + */ + public function postSecurityRules() + { + return [ + 'method' => 'POST', + 'path' => 'security-group-rules', + 'jsonKey' => 'security_group_rule', + 'params' => [ + 'direction' => $this->params->directionJson(), + 'ethertype' => $this->params->ethertypeJson(), + 'securityGroupId' => $this->params->securityGroupIdJson(), + 'portRangeMin' => $this->params->portRangeMinJson(), + 'portRangeMax' => $this->params->portRangeMaxJson(), + 'protocol' => $this->params->protocolJson(), + 'remoteGroupId' => $this->params->remoteGroupIdJson(), + 'remoteIpPrefix' => $this->params->remoteIpPrefixJson(), + ], + ]; + } + + /** + * Returns information about DELETE + * security-group-rules/{rules-security-groups-id} HTTP operation + * + * @return array + */ + public function deleteSecurityRule() + { + return [ + 'method' => 'DELETE', + 'path' => 'security-group-rules/{id}', + 'params' => [ + 'id' => $this->params->idPath(), + ], + ]; + } + + /** + * Returns information about GET + * security-group-rules/{rules-security-groups-id} HTTP operation + * + * @return array + */ + public function getSecurityRule() + { + return [ + 'method' => 'GET', + 'path' => 'security-group-rules/{id}', + 'params' => [ + 'id' => $this->params->idPath(), + ], + ]; + } +} diff --git a/src/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroup.php b/src/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroup.php new file mode 100644 index 00000000..1ac12d54 --- /dev/null +++ b/src/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroup.php @@ -0,0 +1,76 @@ + 'securityGroupRules', + 'tenant_id' => 'tenantId', + ]; + + protected $resourceKey = 'security_group'; + protected $resourcesKey = 'security_groups'; + + /** + * {@inheritDoc} + */ + public function create(array $userOptions): Creatable + { + $response = $this->execute($this->api->postSecurityGroups(), $userOptions); + return $this->populateFromResponse($response); + } + + /** + * {@inheritDoc} + */ + public function delete() + { + $this->executeWithState($this->api->deleteSecurityGroup()); + } + + /** + * {@inheritDoc} + */ + public function retrieve() + { + $response = $this->executeWithState($this->api->getSecurityGroup()); + $this->populateFromResponse($response); + } +} diff --git a/src/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroupRule.php b/src/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroupRule.php new file mode 100644 index 00000000..cb1148a0 --- /dev/null +++ b/src/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroupRule.php @@ -0,0 +1,106 @@ + 'portRangeMax', + 'port_range_min' => 'portRangeMin', + 'remote_group_id' => 'remoteGroupId', + 'remote_ip_prefix' => 'remoteIpPrefix', + 'security_group_id' => 'securityGroupId', + 'tenant_id' => 'tenantId', + ]; + + protected $resourceKey = 'security_group_rule'; + + protected $resourcesKey = 'security_group_rules'; + + /** + * {@inheritDoc} + */ + public function create(array $userOptions): Creatable + { + $response = $this->execute($this->api->postSecurityRules(), $userOptions); + return $this->populateFromResponse($response); + } + + /** + * {@inheritDoc} + */ + public function delete() + { + $this->executeWithState($this->api->deleteSecurityRule()); + } + + /** + * {@inheritDoc} + */ + public function retrieve() + { + $response = $this->executeWithState($this->api->getSecurityRule()); + $this->populateFromResponse($response); + } +} diff --git a/src/Networking/v2/Extensions/SecurityGroups/Params.php b/src/Networking/v2/Extensions/SecurityGroups/Params.php new file mode 100644 index 00000000..38f10beb --- /dev/null +++ b/src/Networking/v2/Extensions/SecurityGroups/Params.php @@ -0,0 +1,92 @@ + self::STRING_TYPE, + 'description' => "Ingress or egress: the direction in which the security group rule is applied. For a compute instance, an ingress security group rule is applied to incoming (ingress) traffic for that instance. An egress rule is applied to traffic leaving the instance.", + ]; + } + + public function ethertypeJson() + { + return [ + 'type' => self::STRING_TYPE, + 'description' => "Must be IPv4 or IPv6, and addresses represented in CIDR must match the ingress or egress rules.", + ]; + } + + public function idJson() + { + return [ + 'type' => self::STRING_TYPE, + 'description' => "The UUID of the security group rule.", + ]; + } + + public function portRangeMaxJson() + { + return [ + 'type' => self::STRING_TYPE, + 'sentAs' => 'port_range_max', + 'description' => "The maximum port number in the range that is matched by the security group rule. The port_range_min attribute constrains the port_range_max attribute. If the protocol is ICMP, this value must be an ICMP type.", + ]; + } + + public function portRangeMinJson() + { + return [ + 'sentAs' => 'port_range_min', + 'type' => self::STRING_TYPE, + 'description' => "The minimum port number in the range that is matched by the security group rule. If the protocol is TCP or UDP, this value must be less than or equal to the port_range_max attribute value. If the protocol is ICMP, this value must be an ICMP type.", + ]; + } + + public function protocolJson() + { + return [ + 'type' => self::STRING_TYPE, + 'description' => "The protocol that is matched by the security group rule. Value is null, icmp, icmpv6, tcp, or udp.", + ]; + } + + public function remoteGroupIdJson() + { + return [ + 'sentAs' => 'remote_group_id', + 'type' => self::STRING_TYPE, + 'description' => "The remote group UUID to associate with this security group rule. You can specify either the remote_group_id or remote_ip_prefix attribute in the request body.", + ]; + } + + public function remoteIpPrefixJson() + { + return [ + 'sentAs' => 'remote_ip_prefix', + 'type' => self::STRING_TYPE, + 'description' => "The remote IP prefix to associate with this security group rule. You can specify either the remote_group_id or remote_ip_prefix attribute in the request body. This attribute value matches the IP prefix as the source IP address of the IP packet.", + ]; + } + + public function securityGroupIdJson() + { + return [ + 'sentAs' => 'security_group_id', + 'type' => self::STRING_TYPE, + 'description' => "The UUID of the security group.", + ]; + } + + public function tenantIdJson() + { + return [ + 'sentAs' => 'tenant_id', + 'type' => self::STRING_TYPE, + 'description' => "The UUID of the tenant who owns the security group rule. Only administrative users can specify a tenant UUID other than their own.", + ]; + } +} diff --git a/src/Networking/v2/Extensions/SecurityGroups/Service.php b/src/Networking/v2/Extensions/SecurityGroups/Service.php new file mode 100644 index 00000000..17972d73 --- /dev/null +++ b/src/Networking/v2/Extensions/SecurityGroups/Service.php @@ -0,0 +1,79 @@ +model(SecurityGroup::class, $info); + } + + private function securityGroupRule(array $info = []): SecurityGroupRule + { + return $this->model(SecurityGroupRule::class, $info); + } + + /** + * @return \Generator + */ + public function listSecurityGroups(): \Generator + { + return $this->securityGroup()->enumerate($this->api->getSecurityGroups()); + } + + /** + * @param array $options + * + * @return SecurityGroup + */ + public function createSecurityGroup(array $options): SecurityGroup + { + return $this->securityGroup()->create($options); + } + + /** + * @param string $id + * + * @return SecurityGroup + */ + public function getSecurityGroup(string $id): SecurityGroup + { + return $this->securityGroup(['id' => $id]); + } + + /** + * @return \Generator + */ + public function listSecurityGroupRules(): \Generator + { + return $this->securityGroupRule()->enumerate($this->api->getSecurityRules()); + } + + /** + * @param array $options + * + * @return SecurityGroupRule + */ + public function createSecurityGroupRule(array $options): SecurityGroupRule + { + return $this->securityGroupRule()->create($options); + } + + /** + * @param string $id + * + * @return SecurityGroupRule + */ + public function getSecurityGroupRule(string $id): SecurityGroupRule + { + return $this->securityGroupRule(['id' => $id]); + } +} diff --git a/src/Networking/v2/Models/Network.php b/src/Networking/v2/Models/Network.php index 78b22efa..89c0b9a4 100644 --- a/src/Networking/v2/Models/Network.php +++ b/src/Networking/v2/Models/Network.php @@ -1,8 +1,9 @@ - 'adminStateUp', + 'tenant_id' => 'tenantId', ]; protected $resourceKey = 'network'; diff --git a/src/Networking/v2/Models/Port.php b/src/Networking/v2/Models/Port.php index 8e9fc4f5..303fed81 100644 --- a/src/Networking/v2/Models/Port.php +++ b/src/Networking/v2/Models/Port.php @@ -1,18 +1,22 @@ - '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', + ]; + protected $resourceKey = 'port'; /** @@ -129,6 +146,11 @@ public function bulkCreate(array $userOptions): array return $this->extractMultipleInstances($response); } + public function retrieve() + { + $this->executeWithState($this->api->getPort()); + } + public function update() { $this->executeWithState($this->api->putPort()); diff --git a/src/Networking/v2/Models/Subnet.php b/src/Networking/v2/Models/Subnet.php index 2bfe5654..6380ee08 100644 --- a/src/Networking/v2/Models/Subnet.php +++ b/src/Networking/v2/Models/Subnet.php @@ -2,7 +2,7 @@ namespace OpenStack\Networking\v2\Models; -use OpenCloud\Common\Resource\AbstractResource; +use OpenCloud\Common\Resource\OperatorResource; use OpenCloud\Common\Resource\Listable; use OpenCloud\Common\Resource\Creatable; use OpenCloud\Common\Resource\Deletable; @@ -13,7 +13,7 @@ * * @property \OpenStack\Networking\v2\Api $api */ -class Subnet extends AbstractResource implements Listable, Retrievable, Creatable, Deletable +class Subnet extends OperatorResource implements Listable, Retrievable, Creatable, Deletable { /** @var string */ public $id; diff --git a/src/Networking/v2/Params.php b/src/Networking/v2/Params.php index c3972c0f..31eec5be 100644 --- a/src/Networking/v2/Params.php +++ b/src/Networking/v2/Params.php @@ -1,4 +1,4 @@ - self::STRING_TYPE, + 'location' => self::JSON, + ]; + } + + /** + * Returns information about name parameter + * + * @return array + */ + public function nameJson(): array + { + return [ + 'type' => self::STRING_TYPE, + 'location' => self::JSON, + ]; + } + public function urlId($type): array { return array_merge(parent::id($type), [ @@ -366,4 +392,14 @@ private function queryFilter($field): array Filters are applicable to all list requests.', ]; } + + public function routerAccessibleJson(): array + { + return [ + 'type' => self::BOOL_TYPE, + 'location' => self::JSON, + 'sentAs' => 'router:external', + 'description' => 'Indicates whether this network is externally accessible.', + ]; + } } diff --git a/src/ObjectStore/v1/Models/Account.php b/src/ObjectStore/v1/Models/Account.php index 7051862b..b5895301 100644 --- a/src/ObjectStore/v1/Models/Account.php +++ b/src/ObjectStore/v1/Models/Account.php @@ -2,7 +2,7 @@ namespace OpenStack\ObjectStore\v1\Models; -use OpenCloud\Common\Resource\AbstractResource; +use OpenCloud\Common\Resource\OperatorResource; use OpenCloud\Common\Resource\HasMetadata; use OpenCloud\Common\Resource\Retrievable; use Psr\Http\Message\ResponseInterface; @@ -10,7 +10,7 @@ /** * @property \OpenStack\ObjectStore\v1\Api $api */ -class Account extends AbstractResource implements Retrievable, HasMetadata +class Account extends OperatorResource implements Retrievable, HasMetadata { use MetadataTrait; diff --git a/src/ObjectStore/v1/Models/Container.php b/src/ObjectStore/v1/Models/Container.php index d13a4d94..95f5a5f0 100644 --- a/src/ObjectStore/v1/Models/Container.php +++ b/src/ObjectStore/v1/Models/Container.php @@ -6,7 +6,7 @@ use GuzzleHttp\Psr7\LimitStream; use Psr\Http\Message\ResponseInterface; use OpenCloud\Common\Error\BadResponseError; -use OpenCloud\Common\Resource\AbstractResource; +use OpenCloud\Common\Resource\OperatorResource; use OpenCloud\Common\Resource\Creatable; use OpenCloud\Common\Resource\Deletable; use OpenCloud\Common\Resource\HasMetadata; @@ -16,7 +16,7 @@ /** * @property \OpenStack\ObjectStore\v1\Api $api */ -class Container extends AbstractResource implements Creatable, Deletable, Retrievable, Listable, HasMetadata +class Container extends OperatorResource implements Creatable, Deletable, Retrievable, Listable, HasMetadata { use MetadataTrait; diff --git a/src/ObjectStore/v1/Models/Object.php b/src/ObjectStore/v1/Models/Object.php index 908747cf..3e0d3979 100644 --- a/src/ObjectStore/v1/Models/Object.php +++ b/src/ObjectStore/v1/Models/Object.php @@ -6,7 +6,7 @@ use OpenCloud\Common\Transport\Utils; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; -use OpenCloud\Common\Resource\AbstractResource; +use OpenCloud\Common\Resource\OperatorResource; use OpenCloud\Common\Resource\Creatable; use OpenCloud\Common\Resource\Deletable; use OpenCloud\Common\Resource\HasMetadata; @@ -14,7 +14,7 @@ /** * @property \OpenStack\ObjectStore\v1\Api $api */ -class Object extends AbstractResource implements Creatable, Deletable, HasMetadata +class Object extends OperatorResource implements Creatable, Deletable, HasMetadata { use MetadataTrait; diff --git a/src/OpenStack.php b/src/OpenStack.php index 923916ff..a2eac2dc 100644 --- a/src/OpenStack.php +++ b/src/OpenStack.php @@ -67,7 +67,7 @@ private function getDefaultIdentityService(array $options): Service public function computeV2(array $options = []): \OpenStack\Compute\v2\Service { $defaults = ['catalogName' => 'nova', 'catalogType' => 'compute']; - return $this->builder->createService('Compute', 2, array_merge($defaults, $options)); + return $this->builder->createService('Compute\\v2', array_merge($defaults, $options)); } /** @@ -80,7 +80,33 @@ public function computeV2(array $options = []): \OpenStack\Compute\v2\Service public function networkingV2(array $options = []): \OpenStack\Networking\v2\Service { $defaults = ['catalogName' => 'neutron', 'catalogType' => 'network']; - return $this->builder->createService('Networking', 2, array_merge($defaults, $options)); + return $this->builder->createService('Networking\\v2', array_merge($defaults, $options)); + } + + /** + * Creates a new Networking v2 Layer 3 service. + * + * @param array $options Options that will be used in configuring the service. + * + * @return \OpenStack\Networking\v2\Extensions\Layer3\Service + */ + public function networkingV2ExtLayer3(array $options = []): \OpenStack\Networking\v2\Extensions\Layer3\Service + { + $defaults = ['catalogName' => 'neutron', 'catalogType' => 'network']; + return $this->builder->createService('Networking\\v2\\Extensions\\Layer3', array_merge($defaults, $options)); + } + + /** + * Creates a new Networking v2 Layer 3 service. + * + * @param array $options Options that will be used in configuring the service. + * + * @return \OpenStack\Networking\v2\Extensions\SecurityGroups\Service + */ + public function networkingV2ExtSecGroups(array $options = []): \OpenStack\Networking\v2\Extensions\SecurityGroups\Service + { + $defaults = ['catalogName' => 'neutron', 'catalogType' => 'network']; + return $this->builder->createService('Networking\\v2\\Extensions\\SecurityGroups', array_merge($defaults, $options)); } /** @@ -93,7 +119,7 @@ public function networkingV2(array $options = []): \OpenStack\Networking\v2\Serv public function identityV2(array $options = []): \OpenStack\Identity\v2\Service { $defaults = ['catalogName' => false, 'catalogType' => false]; - return $this->builder->createService('Identity', 2, array_merge($defaults, $options)); + return $this->builder->createService('Identity\\v2', array_merge($defaults, $options)); } /** @@ -106,7 +132,7 @@ public function identityV2(array $options = []): \OpenStack\Identity\v2\Service public function identityV3(array $options = []): \OpenStack\Identity\v3\Service { $defaults = ['catalogName' => false, 'catalogType' => false]; - return $this->builder->createService('Identity', 3, array_merge($defaults, $options)); + return $this->builder->createService('Identity\\v3', array_merge($defaults, $options)); } /** @@ -119,7 +145,7 @@ public function identityV3(array $options = []): \OpenStack\Identity\v3\Service public function objectStoreV1(array $options = []): \OpenStack\ObjectStore\v1\Service { $defaults = ['catalogName' => 'swift', 'catalogType' => 'object-store']; - return $this->builder->createService('ObjectStore', 1, array_merge($defaults, $options)); + return $this->builder->createService('ObjectStore\\v1', array_merge($defaults, $options)); } /** @@ -132,7 +158,7 @@ public function objectStoreV1(array $options = []): \OpenStack\ObjectStore\v1\Se public function blockStorageV2(array $options = []): \OpenStack\BlockStorage\v2\Service { $defaults = ['catalogName' => 'cinderv2', 'catalogType' => 'volumev2']; - return $this->builder->createService('BlockStorage', 2, array_merge($defaults, $options)); + return $this->builder->createService('BlockStorage\\v2', array_merge($defaults, $options)); } /** @@ -145,6 +171,6 @@ public function blockStorageV2(array $options = []): \OpenStack\BlockStorage\v2\ public function imagesV2(array $options = []): \OpenStack\Images\v2\Service { $defaults = ['catalogName' => 'glance', 'catalogType' => 'image']; - return $this->builder->createService('Images', 2, array_merge($defaults, $options)); + return $this->builder->createService('Images\\v2', array_merge($defaults, $options)); } } diff --git a/tests/integration/BlockStorage/V2Test.php b/tests/integration/BlockStorage/v2/CoreTest.php similarity index 97% rename from tests/integration/BlockStorage/V2Test.php rename to tests/integration/BlockStorage/v2/CoreTest.php index 77a7d641..fdf761eb 100644 --- a/tests/integration/BlockStorage/V2Test.php +++ b/tests/integration/BlockStorage/v2/CoreTest.php @@ -1,6 +1,6 @@ service; } - protected function getBasePath() - { - return __DIR__ . '/../../../samples/block_storage/v2/'; - } - public function runTests() { $this->startTimer(); diff --git a/tests/integration/Compute/V2Test.php b/tests/integration/Compute/v2/CoreTest.php similarity index 98% rename from tests/integration/Compute/V2Test.php rename to tests/integration/Compute/v2/CoreTest.php index b92314c2..3583bf02 100644 --- a/tests/integration/Compute/V2Test.php +++ b/tests/integration/Compute/v2/CoreTest.php @@ -1,6 +1,6 @@ service; } - protected function getBasePath() - { - return __DIR__ . '/../../../samples/compute/v2/'; - } - private function searchImages($name) { foreach ($this->getService()->listImages() as $image) { diff --git a/tests/integration/Identity/V2Test.php b/tests/integration/Identity/V2Test.php deleted file mode 100644 index 7d7624fc..00000000 --- a/tests/integration/Identity/V2Test.php +++ /dev/null @@ -1,16 +0,0 @@ -service; } - protected function getBasePath() - { - return __DIR__ . '/../../../samples/identity/v3/'; - } - public function runTests() { $this->defaultLogging = true; diff --git a/tests/integration/Images/V2Test.php b/tests/integration/Images/v2/CoreTest.php similarity index 86% rename from tests/integration/Images/V2Test.php rename to tests/integration/Images/v2/CoreTest.php index bd3eb4de..4cd10fe0 100644 --- a/tests/integration/Images/V2Test.php +++ b/tests/integration/Images/v2/CoreTest.php @@ -1,33 +1,13 @@ service) { - $this->service = Utils::getOpenStack()->imagesV2(); - } - - return $this->service; - } - - protected function getBasePath() - { - return __DIR__ . '/../../../samples/images/v2/'; - } - public function runTests() { $this->startTimer(); diff --git a/tests/integration/Networking/V2Test.php b/tests/integration/Networking/v2/CoreTest.php similarity index 95% rename from tests/integration/Networking/V2Test.php rename to tests/integration/Networking/v2/CoreTest.php index 7d5f500d..f3eb3244 100644 --- a/tests/integration/Networking/V2Test.php +++ b/tests/integration/Networking/v2/CoreTest.php @@ -1,31 +1,14 @@ service) { - $this->service = Utils::getOpenStack()->networkingV2(); - } - - return $this->service; - } - - protected function getBasePath() - { - return __DIR__ . '/../../../samples/networking/v2/'; - } - public function runTests() { $this->startTimer(); @@ -40,7 +23,6 @@ public function runTests() public function subnets() { $this->createSubnetsAndDelete(); - //$this->createSubnetWithGatewayIp(); $this->createSubnetWithHostRoutes(); list($subnetId, $networkId) = $this->createSubnet(); diff --git a/tests/integration/Networking/v2/Layer3Test.php b/tests/integration/Networking/v2/Layer3Test.php new file mode 100644 index 00000000..556530d4 --- /dev/null +++ b/tests/integration/Networking/v2/Layer3Test.php @@ -0,0 +1,109 @@ +getBaseClient()->networkingV2ExtLayer3(); + } + + private function getV2Service(): \OpenStack\Networking\v2\Service + { + return $this->getBaseClient()->networkingV2(); + } + + public function runTests() + { + $this->startTimer(); + $this->floatingIps(); + $this->outputTimeTaken(); + } + + public function teardown() + { + parent::teardown(); + + $this->deleteItems($this->getV2Service()->listPorts()); + $this->deleteItems($this->getV2Service()->listNetworks()); + $this->deleteItems($this->getService()->listFloatingIps()); + } + + private function createNetwork(): Network + { + $network = $this->getV2Service()->createNetwork(['name' => $this->randomStr(), 'routerAccessible' => true]); + $network->waitUntilActive(); + return $network; + } + + private function createSubnet(Network $network): Subnet + { + return $this->getV2Service()->createSubnet([ + 'networkId' => $network->id, + 'name' => $this->randomStr(), + 'ipVersion' => 4, + 'cidr' => '192.168.199.0/24', + ]); + } + + private function createPort(Network $network): Port + { + return $this->getV2Service()->createPort(['networkId' => $network->id, 'name' => $this->randomStr()]); + } + + public function floatingIps() + { + $this->logStep('Creating network'); + $network = $this->createNetwork(); + + $this->logStep('Creating subnet for network %id%', ['%id%' => $network->id]); + $this->createSubnet($network); + + $this->logStep('Creating port for network %id%', ['%id%' => $network->id]); + $port1 = $this->createPort($network); + + $replacements = [ + '{networkId}' => $network->id, + '{portId}' => $port1->id, + ]; + + $this->logStep('Create floating IP'); + /** @var FloatingIp $ip */ + $path = $this->sampleFile($replacements, 'floatingIPs/create.php'); + require_once $path; + $this->assertInstanceOf(FloatingIp::class, $ip); + $this->assertEquals($network->id, $ip->floatingNetworkId); + $this->assertEquals($port1->id, $ip->portId); + + $this->logStep('List floating IPs'); + $path = $this->sampleFile($replacements, 'floatingIPs/list.php'); + require_once $path; + + $this->logStep('Get floating IP'); + $replacements['{id}'] = $ip->id; + $path = $this->sampleFile($replacements, 'floatingIPs/get.php'); + require_once $path; + $this->assertInstanceOf(FloatingIp::class, $ip); + + $this->logStep('Update floating IP'); + $port2 = $this->createPort($network); + $replacements['{newPortId}'] = $port2->id; + $path = $this->sampleFile($replacements, 'floatingIPs/update.php'); + require_once $path; + + $this->logStep('Delete floating IP'); + $path = $this->sampleFile($replacements, 'floatingIPs/update.php'); + require_once $path; + + $port1->delete(); + $port2->delete(); + $network->delete(); + } +} diff --git a/tests/integration/Networking/v2/SecGroupTest.php b/tests/integration/Networking/v2/SecGroupTest.php new file mode 100644 index 00000000..e4e510a9 --- /dev/null +++ b/tests/integration/Networking/v2/SecGroupTest.php @@ -0,0 +1,12 @@ +service; } - protected function getBasePath() - { - return __DIR__ . '/../../../samples/object_store/v1/'; - } - public function runTests() { $this->startTimer(); diff --git a/tests/integration/SampleManager.php b/tests/integration/SampleManager.php index 0d84bca1..7a020551 100644 --- a/tests/integration/SampleManager.php +++ b/tests/integration/SampleManager.php @@ -40,6 +40,11 @@ protected function getGlobalReplacements() ]; } + public function getConnectionStr() + { + return str_replace('$openstack =', 'return', $this->getConnectionTemplate()); + } + protected function getConnectionTemplate() { if ($this->verbosity === 1) { diff --git a/tests/integration/run.php b/tests/integration/run.php index 94dbee2d..0ff606cb 100644 --- a/tests/integration/run.php +++ b/tests/integration/run.php @@ -4,7 +4,7 @@ require_once $rootDir . '/vendor/autoload.php'; -$basePath = $rootDir . '/samples'; +$sampleDir = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'samples'; -$runner = new \OpenCloud\Integration\Runner($basePath, 'OpenStack\\Integration'); +$runner = new \OpenCloud\Integration\Runner($sampleDir, __DIR__, 'OpenStack\\Integration'); $runner->runServices(); diff --git a/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIp.resp b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIp.resp new file mode 100644 index 00000000..d4f9fbd5 --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIp.resp @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "floatingip": { + "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57", + "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f", + "fixed_ip_address": "10.0.0.3", + "floating_ip_address": "172.24.4.228", + "tenant_id": "4969c491a3c74ee4af974e6d800c62de", + "status": "ACTIVE", + "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab", + "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7" + } +} \ No newline at end of file diff --git a/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIps.resp b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIps.resp new file mode 100644 index 00000000..66046e79 --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIps.resp @@ -0,0 +1,27 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "floatingips": [ + { + "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f", + "tenant_id": "4969c491a3c74ee4af974e6d800c62de", + "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57", + "fixed_ip_address": "10.0.0.3", + "floating_ip_address": "172.24.4.228", + "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab", + "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7", + "status": "ACTIVE" + }, + { + "router_id": null, + "tenant_id": "4969c491a3c74ee4af974e6d800c62de", + "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57", + "fixed_ip_address": null, + "floating_ip_address": "172.24.4.227", + "port_id": null, + "id": "61cea855-49cb-4846-997d-801b70c71bdd", + "status": "DOWN" + } + ] +} \ No newline at end of file diff --git a/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/Router.resp b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/Router.resp new file mode 100644 index 00000000..79fed195 --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/Router.resp @@ -0,0 +1,23 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "router": { + "status": "ACTIVE", + "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" + } + ] + }, + "name": "router1", + "admin_state_up": true, + "tenant_id": "d6554fe62e2f41efbb6e026fad5c1542", + "routes": [], + "id": "a07eea83-7710-4860-931b-5fe220fae533" + } +} \ No newline at end of file diff --git a/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/Routers.resp b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/Routers.resp new file mode 100644 index 00000000..76cf5cbf --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/Routers.resp @@ -0,0 +1,34 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "routers": [ + { + "status": "ACTIVE", + "external_gateway_info": null, + "name": "second_routers", + "admin_state_up": true, + "tenant_id": "6b96ff0cb17a4b859e1e575d221683d3", + "routes": [], + "id": "7177abc4-5ae9-4bb7-b0d4-89e94a4abf3b" + }, + { + "status": "ACTIVE", + "external_gateway_info": { + "network_id": "3c5bcddd-6af9-4e6b-9c3e-c153e521cab8", + "enable_snat": true, + "external_fixed_ips": [ + { + "subnet_id": "255.255.255.0", + "ip": "192.168.10.2" + } + ] + }, + "name": "router1", + "admin_state_up": true, + "tenant_id": "33a40233088643acb66ff6eb0ebea679", + "routes": [], + "id": "a9254bdb-2613-4a13-ac4c-adc581fba50d" + } + ] +} \ 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 new file mode 100644 index 00000000..62915f42 --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/Layer3/Models/FloatingIpTest.php @@ -0,0 +1,52 @@ +rootFixturesDir = dirname(__DIR__); + + $this->floatingIp = new FloatingIp($this->client->reveal(), new Api()); + $this->floatingIp->id = 'id'; + } + + public function test_it_updates() + { + $expectedJson = ['floatingip' => [ + "floating_network_id" => "376da547-b977-4cfe-9cba-275c80debf57", + "port_id" => "ce705c24-c1ef-408a-bda3-7bbd946164ab", + ]]; + + $this->setupMock('PUT', 'v2.0/floatingips/id', $expectedJson, [], new Response(202)); + + $this->floatingIp->floatingNetworkId = "376da547-b977-4cfe-9cba-275c80debf57"; + $this->floatingIp->portId = "ce705c24-c1ef-408a-bda3-7bbd946164ab"; + $this->floatingIp->update(); + } + + public function test_it_deletes() + { + $this->setupMock('DELETE', 'v2.0/floatingips/id', null, [], new Response(202)); + + $this->floatingIp->delete(); + } + + public function test_it_retrieves() + { + $this->setupMock('GET', 'v2.0/floatingips/id', null, [], 'FloatingIp'); + + $this->floatingIp->retrieve(); + } +} diff --git a/tests/unit/Networking/v2/Extensions/Layer3/Models/RouterTest.php b/tests/unit/Networking/v2/Extensions/Layer3/Models/RouterTest.php new file mode 100644 index 00000000..1f1b013a --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/Layer3/Models/RouterTest.php @@ -0,0 +1,91 @@ +rootFixturesDir = dirname(__DIR__); + + $this->router = new Router($this->client->reveal(), new Api()); + $this->router->id = 'id'; + } + + public function test_it_deletes() + { + $this->setupMock('DELETE', 'v2.0/routers/id', null, [], new Response(202)); + + $this->router->delete(); + } + + public function test_it_updates() + { + $expectedJson = ['router' => [ + 'name' => 'new', + 'external_gateway_info' => [ + "network_id" => "8ca37218-28ff-41cb-9b10-039601ea7e6b", + "enable_snat" => true, + "external_fixed_ips" => [ + [ + "subnet_id" => "255.255.255.0", + "ip" => "192.168.10.1", + ], + ], + ], + ]]; + + $this->setupMock('PUT', 'v2.0/routers/id', $expectedJson, [], new Response(201)); + + $gatewayInfo = new GatewayInfo(); + $gatewayInfo->networkId = '8ca37218-28ff-41cb-9b10-039601ea7e6b'; + $gatewayInfo->enableSnat = true; + + $fixedIp = new FixedIp(); + $fixedIp->subnetId = '255.255.255.0'; + $fixedIp->ip = '192.168.10.1'; + $gatewayInfo->fixedIps = [$fixedIp]; + + $this->router->externalGatewayInfo = $gatewayInfo; + $this->router->name = 'new'; + + $this->router->update(); + } + + public function test_it_retrieves() + { + $this->setupMock('GET', 'v2.0/routers/id', null, [], 'Router'); + + $this->router->retrieve(); + } + + public function test_it_adds_interface() + { + $expectedJson = ['subnet_id' => 'a2f1f29d-571b-4533-907f-5803ab96ead1']; + + $this->setupMock('PUT', 'v2.0/routers/id/add_router_interface', $expectedJson, [], new Response(201)); + + $this->router->addInterface(['subnetId' => 'a2f1f29d-571b-4533-907f-5803ab96ead1']); + } + + public function test_it_remove_interface() + { + $expectedJson = ['subnet_id' => 'a2f1f29d-571b-4533-907f-5803ab96ead1']; + + $this->setupMock('PUT', 'v2.0/routers/id/remove_router_interface', $expectedJson, [], new Response(201)); + + $this->router->removeInterface(['subnetId' => 'a2f1f29d-571b-4533-907f-5803ab96ead1']); + } +} diff --git a/tests/unit/Networking/v2/Extensions/Layer3/ServiceTest.php b/tests/unit/Networking/v2/Extensions/Layer3/ServiceTest.php new file mode 100644 index 00000000..afe2eff0 --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/Layer3/ServiceTest.php @@ -0,0 +1,127 @@ +rootFixturesDir = __DIR__; + + $this->service = new Service($this->client->reveal(), new Api()); + } + + public function test_it_lists_floating_ips() + { + $this->client + ->request('GET', 'v2.0/floatingips', ['headers' => []]) + ->shouldBeCalled() + ->willReturn($this->getFixture('FloatingIps')); + + foreach ($this->service->listFloatingIps() as $ip) { + /** @var $ip FloatingIp */ + $this->assertInstanceOf(FloatingIp::class, $ip); + + $this->assertNotNull($ip->tenantId); + $this->assertNotNull($ip->floatingNetworkId); + $this->assertNotNull($ip->floatingIpAddress); + $this->assertNotNull($ip->id); + $this->assertNotNull($ip->status); + } + } + + public function test_it_gets_floating_ip() + { + $this->assertInstanceOf(FloatingIp::class, $this->service->getFloatingIp('id')); + } + + public function test_it_creates_floatingIp() + { + $expectedJson = ["floatingip" => [ + "floating_network_id" => "376da547-b977-4cfe-9cba-275c80debf57", + "port_id" => "ce705c24-c1ef-408a-bda3-7bbd946164ab", + ]]; + + $this->setupMock('POST', 'v2.0/floatingips', $expectedJson, [], new Response(201)); + + $ip = $this->service->createFloatingIp([ + "floatingNetworkId" => "376da547-b977-4cfe-9cba-275c80debf57", + "portId" => "ce705c24-c1ef-408a-bda3-7bbd946164ab", + ]); + + $this->assertInstanceOf(FloatingIp::class, $ip); + } + + public function test_it_lists_routers() + { + $this->client + ->request('GET', 'v2.0/routers', ['headers' => []]) + ->shouldBeCalled() + ->willReturn($this->getFixture('Routers')); + + foreach ($this->service->listRouters() as $r) { + /** @var $r Router */ + $this->assertInstanceOf(Router::class, $r); + + $this->assertNotNull($r->status); + $this->assertNotNull($r->name); + $this->assertNotNull($r->adminStateUp); + $this->assertNotNull($r->tenantId); + $this->assertNotNull($r->id); + } + } + + public function test_it_gets_router() + { + $this->assertInstanceOf(Router::class, $this->service->getRouter('id')); + } + + public function test_it_creates_router() + { + $expectedJson = ["router" => [ + "name" => "test_router", + "external_gateway_info" => [ + "network_id" => "8ca37218-28ff-41cb-9b10-039601ea7e6b", + "enable_snat" => true, + "external_fixed_ips" => [ + [ + "subnet_id" => "255.255.255.0", + "ip" => "192.168.10.1", + ], + ], + ], + "admin_state_up" => true, + ]]; + + $this->setupMock('POST', 'v2.0/routers', $expectedJson, [], new Response(201)); + + $r = $this->service->createRouter([ + 'name' => 'test_router', + 'adminStateUp' => true, + 'externalGatewayInfo' => [ + 'networkId' => '8ca37218-28ff-41cb-9b10-039601ea7e6b', + 'enableSnat' => true, + 'fixedIps' => [ + [ + 'subnetId' => '255.255.255.0', + 'ip' => '192.168.10.1', + ], + ], + ], + ]); + + $this->assertInstanceOf(Router::class, $r); + } +} diff --git a/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroup.resp b/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroup.resp new file mode 100644 index 00000000..d7000122 --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroup.resp @@ -0,0 +1,37 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "security_group":{ + "description":"default", + "id":"85cc3048-abc3-43cc-89b3-377341426ac5", + "name":"default", + "security_group_rules":[ + { + "direction":"ingress", + "ethertype":"IPv6", + "id":"c0b09f00-1d49-4e64-a0a7-8a186d928138", + "port_range_max":22, + "port_range_min":22, + "protocol":"TCP", + "remote_group_id":null, + "remote_ip_prefix":null, + "security_group_id":"85cc3048-abc3-43cc-89b3-377341426ac5", + "tenant_id":"5831008" + }, + { + "direction":"ingress", + "ethertype":"IPv4", + "id":"f7d45c89-008e-4bab-88ad-d6811724c51c", + "port_range_max":22, + "port_range_min":22, + "protocol":"TCP", + "remote_group_id":null, + "remote_ip_prefix":null, + "security_group_id":"85cc3048-abc3-43cc-89b3-377341426ac5", + "tenant_id":"5831008" + } + ], + "tenant_id":"5831008" + } +} \ No newline at end of file diff --git a/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroupRule.resp b/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroupRule.resp new file mode 100644 index 00000000..36ab1466 --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroupRule.resp @@ -0,0 +1,17 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "security_group_rule":{ + "direction":"ingress", + "ethertype":"IPv6", + "id":"c0b09f00-1d49-4e64-a0a7-8a186d928138", + "port_range_max":22, + "port_range_min":22, + "protocol":"TCP", + "remote_group_id":null, + "remote_ip_prefix":null, + "security_group_id":"85cc3048-abc3-43cc-89b3-377341426ac5", + "tenant_id":"5831008" + } +} \ No newline at end of file diff --git a/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroupRules.resp b/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroupRules.resp new file mode 100644 index 00000000..e5ce88fa --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroupRules.resp @@ -0,0 +1,31 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "security_group_rules":[ + { + "direction":"ingress", + "ethertype":"IPv6", + "id":"c0b09f00-1d49-4e64-a0a7-8a186d928138", + "port_range_max":22, + "port_range_min":22, + "protocol":"TCP", + "remote_group_id":null, + "remote_ip_prefix":null, + "security_group_id":"85cc3048-abc3-43cc-89b3-377341426ac5", + "tenant_id":"5831008" + }, + { + "direction":"ingress", + "ethertype":"IPv4", + "id":"f7d45c89-008e-4bab-88ad-d6811724c51c", + "port_range_max":22, + "port_range_min":22, + "protocol":"TCP", + "remote_group_id":null, + "remote_ip_prefix":null, + "security_group_id":"85cc3048-abc3-43cc-89b3-377341426ac5", + "tenant_id":"5831008" + } + ] +} \ No newline at end of file diff --git a/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroups.resp b/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroups.resp new file mode 100644 index 00000000..34d040a8 --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/SecurityGroups/Fixtures/SecurityGroups.resp @@ -0,0 +1,39 @@ +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "security_groups": [ + { + "description": "default", + "id": "85cc3048-abc3-43cc-89b3-377341426ac5", + "name": "default", + "security_group_rules": [ + { + "direction": "ingress", + "ethertype": "IPv6", + "id": "c0b09f00-1d49-4e64-a0a7-8a186d928138", + "port_range_max": 22, + "port_range_min": 22, + "protocol": "TCP", + "remote_group_id": null, + "remote_ip_prefix": null, + "security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5", + "tenant_id": "5831008" + }, + { + "direction": "ingress", + "ethertype": "IPv4", + "id": "f7d45c89-008e-4bab-88ad-d6811724c51c", + "port_range_max": 22, + "port_range_min": 22, + "protocol": "TCP", + "remote_group_id": null, + "remote_ip_prefix": null, + "security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5", + "tenant_id": "5831008" + } + ], + "tenant_id": "5831008" + } + ] +} \ No newline at end of file diff --git a/tests/unit/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroupRuleTest.php b/tests/unit/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroupRuleTest.php new file mode 100644 index 00000000..ba69b0c8 --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroupRuleTest.php @@ -0,0 +1,38 @@ +rootFixturesDir = dirname(__DIR__); + + $this->securityGroupRule = new SecurityGroupRule($this->client->reveal(), new Api()); + $this->securityGroupRule->id = 'id'; + } + + public function test_it_deletes() + { + $this->setupMock('DELETE', 'security-group-rules/id', null, [], new Response(202)); + + $this->securityGroupRule->delete(); + } + + public function test_it_retrieves() + { + $this->setupMock('GET', 'security-group-rules/id', null, [], 'SecurityGroupRule'); + + $this->securityGroupRule->retrieve(); + } +} diff --git a/tests/unit/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroupTest.php b/tests/unit/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroupTest.php new file mode 100644 index 00000000..76eb42c3 --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/SecurityGroups/Models/SecurityGroupTest.php @@ -0,0 +1,38 @@ +rootFixturesDir = dirname(__DIR__); + + $this->securityGroup = new SecurityGroup($this->client->reveal(), new Api()); + $this->securityGroup->id = 'id'; + } + + public function test_it_deletes() + { + $this->setupMock('DELETE', 'security-groups/id', null, [], new Response(202)); + + $this->securityGroup->delete(); + } + + public function test_it_retrieves() + { + $this->setupMock('GET', 'security-groups/id', null, [], 'SecurityGroup'); + + $this->securityGroup->retrieve(); + } +} diff --git a/tests/unit/Networking/v2/Extensions/SecurityGroups/ServiceTest.php b/tests/unit/Networking/v2/Extensions/SecurityGroups/ServiceTest.php new file mode 100644 index 00000000..039e7737 --- /dev/null +++ b/tests/unit/Networking/v2/Extensions/SecurityGroups/ServiceTest.php @@ -0,0 +1,115 @@ +rootFixturesDir = __DIR__; + + $this->service = new Service($this->client->reveal(), new Api()); + } + + public function test_it_lists_secgroups() + { + $this->client + ->request('GET', 'security-groups', ['headers' => []]) + ->shouldBeCalled() + ->willReturn($this->getFixture('SecurityGroups')); + + foreach ($this->service->listSecurityGroups() as $sg) { + /** @var $sg SecurityGroup */ + $this->assertInstanceOf(SecurityGroup::class, $sg); + + $this->assertEquals('default', $sg->name); + $this->assertEquals('default', $sg->description); + $this->assertEquals('85cc3048-abc3-43cc-89b3-377341426ac5', $sg->id); + $this->assertCount(2, $sg->securityGroupRules); + } + } + + public function test_it_creates_secgroup() + { + $options = [ + 'name' => 'new-webservers', + 'description' => 'security group for webservers', + ]; + + $expectedJson = ['security_group' => $options]; + + $this->setupMock('POST', 'security-groups', $expectedJson, [], new Response(201)); + + $n = $this->service->createSecurityGroup($options); + $this->assertInstanceOf(SecurityGroup::class, $n); + } + + public function test_it_gets_secgroup() + { + $this->assertInstanceOf(SecurityGroup::class, $this->service->getSecurityGroup('id')); + } + + public function test_it_lists_secgrouprules() + { + $this->client + ->request('GET', 'security-group-rules', ['headers' => []]) + ->shouldBeCalled() + ->willReturn($this->getFixture('SecurityGroupRules')); + + foreach ($this->service->listSecurityGroupRules() as $sgr) { + /** @var $sgr SecurityGroupRule */ + $this->assertInstanceOf(SecurityGroupRule::class, $sgr); + + $this->assertNotNull($sgr->direction); + $this->assertNotNull($sgr->ethertype); + $this->assertNotNull($sgr->id); + $this->assertNotNull($sgr->securityGroupId); + $this->assertNotNull($sgr->tenantId); + } + } + + public function test_it_creates_secgrouprule() + { + $options = [ + "direction" => "ingress", + "portRangeMin" => "80", + "ethertype" => "IPv4", + "portRangeMax" => "80", + "protocol" => "tcp", + "remoteGroupId" => "85cc3048-abc3-43cc-89b3-377341426ac5", + "securityGroupId" => "a7734e61-b545-452d-a3cd-0189cbd9747a", + ]; + + $expectedJson = ['security_group_rule' => [ + "direction" => "ingress", + "port_range_min" => "80", + "ethertype" => "IPv4", + "port_range_max" => "80", + "protocol" => "tcp", + "remote_group_id" => "85cc3048-abc3-43cc-89b3-377341426ac5", + "security_group_id" => "a7734e61-b545-452d-a3cd-0189cbd9747a", + ]]; + + $this->setupMock('POST', 'security-group-rules', $expectedJson, [], new Response(201)); + + $n = $this->service->createSecurityGroupRule($options); + $this->assertInstanceOf(SecurityGroupRule::class, $n); + } + + public function test_it_gets_secgrouprule() + { + $this->assertInstanceOf(SecurityGroupRule::class, $this->service->getSecurityGroupRule('id')); + } +} diff --git a/tests/unit/Networking/v2/Models/PortTest.php b/tests/unit/Networking/v2/Models/PortTest.php index 4082c830..65939991 100644 --- a/tests/unit/Networking/v2/Models/PortTest.php +++ b/tests/unit/Networking/v2/Models/PortTest.php @@ -47,6 +47,13 @@ public function test_it_updates() $this->port->update(); } + public function test_it_retrieves() + { + $this->setupMock('GET', 'v2.0/ports/' . self::PORT_ID, null, [], new Response(204)); + + $this->port->retrieve(); + } + public function test_it_deletes() { $this->setupMock('DELETE', 'v2.0/ports/' . self::PORT_ID, null, [], new Response(204)); diff --git a/tests/unit/OpenStackTest.php b/tests/unit/OpenStackTest.php index 2ecf5a97..a145def0 100644 --- a/tests/unit/OpenStackTest.php +++ b/tests/unit/OpenStackTest.php @@ -22,7 +22,7 @@ public function setUp() public function test_it_supports_compute_v2() { $this->builder - ->createService('Compute', 2, ['catalogName' => 'nova', 'catalogType' => 'compute']) + ->createService('Compute\\v2', ['catalogName' => 'nova', 'catalogType' => 'compute']) ->shouldBeCalled() ->willReturn($this->service('Compute', 2)); @@ -32,7 +32,7 @@ public function test_it_supports_compute_v2() public function test_it_supports_identity_v2() { $this->builder - ->createService('Identity', 2, ['catalogName' => false, 'catalogType' => false]) + ->createService('Identity\\v2', ['catalogName' => false, 'catalogType' => false]) ->shouldBeCalled() ->willReturn($this->service('Identity', 2)); @@ -42,7 +42,7 @@ public function test_it_supports_identity_v2() public function test_it_supports_identity_v3() { $this->builder - ->createService('Identity', 3, ['catalogName' => false, 'catalogType' => false]) + ->createService('Identity\\v3', ['catalogName' => false, 'catalogType' => false]) ->shouldBeCalled() ->willReturn($this->service('Identity', 3)); @@ -52,7 +52,7 @@ public function test_it_supports_identity_v3() public function test_it_supports_networking_v2() { $this->builder - ->createService('Networking', 2, ['catalogName' => 'neutron', 'catalogType' => 'network']) + ->createService('Networking\\v2', ['catalogName' => 'neutron', 'catalogType' => 'network']) ->shouldBeCalled() ->willReturn($this->service('Networking', 2)); @@ -62,7 +62,7 @@ public function test_it_supports_networking_v2() public function test_it_supports_object_store_v1() { $this->builder - ->createService('ObjectStore', 1, ['catalogName' => 'swift', 'catalogType' => 'object-store']) + ->createService('ObjectStore\\v1', ['catalogName' => 'swift', 'catalogType' => 'object-store']) ->shouldBeCalled() ->willReturn($this->service('ObjectStore', 1)); @@ -72,7 +72,7 @@ public function test_it_supports_object_store_v1() public function test_it_supports_block_storage_v2() { $this->builder - ->createService('BlockStorage', 2, ['catalogName' => 'cinderv2', 'catalogType' => 'volumev2']) + ->createService('BlockStorage\\v2', ['catalogName' => 'cinderv2', 'catalogType' => 'volumev2']) ->shouldBeCalled() ->willReturn($this->service('BlockStorage', 2)); @@ -82,7 +82,7 @@ public function test_it_supports_block_storage_v2() public function test_it_supports_images_v2() { $this->builder - ->createService('Images', 2, ['catalogName' => 'glance', 'catalogType' => 'image']) + ->createService('Images\\v2', ['catalogName' => 'glance', 'catalogType' => 'image']) ->shouldBeCalled() ->willReturn($this->service('Images', 2));