diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml index 80edde1f8..c460cf21f 100644 --- a/.github/workflows/integration_tests.yml +++ b/.github/workflows/integration_tests.yml @@ -22,22 +22,28 @@ jobs: openstack_version: [ "stable/2023.2" ] php_version: [ 8.1 ] include: + - name: "dalmatian" + openstack_version: "stable/2024.2" + ubuntu_version: "22.04" + - name: "caracal" + openstack_version: "stable/2024.1" + ubuntu_version: "22.04" - name: "bobcat" openstack_version: "stable/2023.2" ubuntu_version: "22.04" - name: "antelope" - openstack_version: "stable/2023.1" + openstack_version: "unmaintained/2023.1" ubuntu_version: "22.04" - name: "zed" - openstack_version: "stable/zed" + openstack_version: "unmaintained/zed" + ubuntu_version: "20.04" + - name: "yoga" + openstack_version: "unmaintained/yoga" + ubuntu_version: "20.04" + - name: "wallaby" + openstack_version: "unmaintained/wallaby" ubuntu_version: "20.04" - #- name: "yoga" - # openstack_version: "unmaintained/yoga" - # ubuntu_version: "20.04" - #- name: "wallaby" - # openstack_version: "unmaintained/wallaby" - # ubuntu_version: "20.04" - # block_storage_v2: true + block_storage_v2: true runs-on: ubuntu-${{ matrix.ubuntu_version }} name: Deploy OpenStack ${{ matrix.name }} and run integration tests with php ${{matrix.php_version}} steps: @@ -76,13 +82,14 @@ jobs: key: ${{ runner.os }}-openstack-${{ matrix.openstack_version }}-${{ github.workflow }} - name: Deploy devstack - uses: EmilienM/devstack-action@v0.11 + uses: EmilienM/devstack-action@v0.15 with: branch: ${{ matrix.openstack_version }} conf_overrides: | CINDER_ISCSI_HELPER=lioadm SWIFT_ENABLE_TEMPURLS=True SWIFT_TEMPURL_KEY=secretkey + TARGET_BRANCH=${{ matrix.openstack_version }} [[post-config|\$SWIFT_CONFIG_PROXY_SERVER]] [filter:versioned_writes] allow_object_versioning = true diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 22972dd7a..b379bdfdb 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3 ] + php: [ 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 ] composer: - name: lowest arg: "--prefer-lowest --prefer-stable" @@ -34,7 +34,7 @@ jobs: run: | echo "::set-output name=dir::$(composer config cache-files-dir)" - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: | ~/.php_cs.cache diff --git a/COVERAGE.md b/COVERAGE.md index c743bfcb2..3fee51a64 100644 --- a/COVERAGE.md +++ b/COVERAGE.md @@ -1,6 +1,8 @@ # OpenStack versions coverage While we strive to support all versions of OpenStack, we can only test limited number of versions. The current set: +* 2024.2 Dalmatian +* 2024.1 Caracal * 2023.2 Bobcat * 2023.1 Antelope * Zed diff --git a/samples/Networking/v2/floatingIPs/create.php b/samples/Networking/v2/floatingIPs/create.php index 0e7aea991..410640e61 100644 --- a/samples/Networking/v2/floatingIPs/create.php +++ b/samples/Networking/v2/floatingIPs/create.php @@ -17,5 +17,6 @@ $floatingIp = $networking->createFloatingIp([ "floatingNetworkId" => "{networkId}", "portId" => "{portId}", - 'fixedIpAddress' => '{fixedIpAddress}', + "fixedIpAddress" => "{fixedIpAddress}", + "description" => "{description}", ]); diff --git a/src/Common/Auth/AuthHandler.php b/src/Common/Auth/AuthHandler.php index 71a58721c..4abf2b83e 100644 --- a/src/Common/Auth/AuthHandler.php +++ b/src/Common/Auth/AuthHandler.php @@ -25,7 +25,7 @@ class AuthHandler /** @var Token */ private $token; - public function __construct(callable $nextHandler, callable $tokenGenerator, Token $token = null) + public function __construct(callable $nextHandler, callable $tokenGenerator, ?Token $token = null) { $this->nextHandler = $nextHandler; $this->tokenGenerator = $tokenGenerator; diff --git a/src/Common/Error/Builder.php b/src/Common/Error/Builder.php index f2717aa1a..a9830309f 100644 --- a/src/Common/Error/Builder.php +++ b/src/Common/Error/Builder.php @@ -35,7 +35,7 @@ class Builder */ private $client; - public function __construct(ClientInterface $client = null) + public function __construct(?ClientInterface $client = null) { $this->client = $client ?: new Client(); } @@ -164,7 +164,7 @@ private function getStatusCodeMessage(int $statusCode): string * @param mixed $userValue The incorrect value the user actually provided * @param string|null $furtherLink a link to further information if necessary (optional) */ - public function userInputError(string $expectedType, $userValue, string $furtherLink = null): UserInputError + public function userInputError(string $expectedType, $userValue, ?string $furtherLink = null): UserInputError { $message = $this->header('User Input Error'); diff --git a/src/Common/HydratorStrategyTrait.php b/src/Common/HydratorStrategyTrait.php index 83d5719bc..43ddd946d 100644 --- a/src/Common/HydratorStrategyTrait.php +++ b/src/Common/HydratorStrategyTrait.php @@ -25,7 +25,7 @@ public function hydrate(array $data, array $aliases = []) } } - public function set(string $key, $property, array $data, callable $fn = null) + public function set(string $key, $property, array $data, ?callable $fn = null) { if (isset($data[$key]) && property_exists($this, $property)) { $value = $fn ? call_user_func($fn, $data[$key]) : $data[$key]; diff --git a/src/Common/JsonSchema/Schema.php b/src/Common/JsonSchema/Schema.php index 36396d5ee..d2ac5cdd7 100644 --- a/src/Common/JsonSchema/Schema.php +++ b/src/Common/JsonSchema/Schema.php @@ -14,7 +14,7 @@ class Schema /** @var Validator */ private $validator; - public function __construct($body, Validator $validator = null) + public function __construct($body, ?Validator $validator = null) { $this->body = (object) $body; $this->validator = $validator ?: new Validator(); diff --git a/src/Common/Resource/Alias.php b/src/Common/Resource/Alias.php index ebd7a6bfd..53944bab1 100644 --- a/src/Common/Resource/Alias.php +++ b/src/Common/Resource/Alias.php @@ -26,7 +26,7 @@ class Alias * @param string|null $className A class name for the property value * @param bool $list Whether value of the property should be treated as a list or not */ - public function __construct(string $propertyName, string $className = null, bool $list = false) + public function __construct(string $propertyName, ?string $className = null, bool $list = false) { $this->isList = $list; $this->propertyName = $propertyName; diff --git a/src/Common/Resource/Listable.php b/src/Common/Resource/Listable.php index a19499e3d..899e80fc2 100644 --- a/src/Common/Resource/Listable.php +++ b/src/Common/Resource/Listable.php @@ -18,11 +18,11 @@ interface Listable * of the marker will depend on the last element returned in the previous response. If a limit is * provided, the loop will continue up until that point. * - * @param array $def The operation definition - * @param array $userVals The user values - * @param callable $mapFn an optional callback that will be executed on every resource iteration + * @param array $def The operation definition + * @param array $userVals The user values + * @param callable|null $mapFn an optional callback that will be executed on every resource iteration * * @returns \Generator */ - public function enumerate(array $def, array $userVals = [], callable $mapFn = null); + public function enumerate(array $def, array $userVals = [], ?callable $mapFn = null); } diff --git a/src/Common/Resource/OperatorResource.php b/src/Common/Resource/OperatorResource.php index 894925986..ac940c762 100644 --- a/src/Common/Resource/OperatorResource.php +++ b/src/Common/Resource/OperatorResource.php @@ -69,7 +69,7 @@ private function getResourcesKey(): string * * @returns \Generator */ - public function enumerate(array $def, array $userVals = [], callable $mapFn = null): \Generator + public function enumerate(array $def, array $userVals = [], ?callable $mapFn = null): \Generator { $operation = $this->getOperation($def); @@ -105,7 +105,7 @@ public function enumerate(array $def, array $userVals = [], callable $mapFn = nu * * @return array */ - public function extractMultipleInstances(ResponseInterface $response, string $key = null): array + public function extractMultipleInstances(ResponseInterface $response, ?string $key = null): array { $key = $key ?: $this->getResourcesKey(); $resourcesData = Utils::jsonDecode($response)[$key]; diff --git a/src/Common/Service/Builder.php b/src/Common/Service/Builder.php index f63eefc18..a5dca9974 100644 --- a/src/Common/Service/Builder.php +++ b/src/Common/Service/Builder.php @@ -109,7 +109,7 @@ private function stockAuthHandler(array &$options): void } } - private function httpClient(string $baseUrl, HandlerStack $stack, string $serviceType = null, string $microVersion = null): ClientInterface + private function httpClient(string $baseUrl, HandlerStack $stack, ?string $serviceType = null, ?string $microVersion = null): ClientInterface { $clientOptions = [ 'base_uri' => Utils::normalizeUrl($baseUrl), diff --git a/src/Common/Transport/HandlerStack.php b/src/Common/Transport/HandlerStack.php index fd500be50..158b57b3c 100644 --- a/src/Common/Transport/HandlerStack.php +++ b/src/Common/Transport/HandlerStack.php @@ -10,7 +10,7 @@ class HandlerStack /** * @deprecated use \OpenStack\Common\Transport\HandlerStackFactory::createWithOptions instead */ - public static function create(callable $handler = null): \GuzzleHttp\HandlerStack + public static function create(?callable $handler = null): \GuzzleHttp\HandlerStack { return HandlerStackFactory::create($handler); } diff --git a/src/Common/Transport/HandlerStackFactory.php b/src/Common/Transport/HandlerStackFactory.php index a2324d581..7afa03735 100644 --- a/src/Common/Transport/HandlerStackFactory.php +++ b/src/Common/Transport/HandlerStackFactory.php @@ -13,7 +13,7 @@ class HandlerStackFactory /** * @deprecated use \OpenStack\Common\Transport\HandlerStackFactory::createWithOptions instead */ - public static function create(callable $handler = null): HandlerStack + public static function create(?callable $handler = null): HandlerStack { $stack = new HandlerStack($handler ?: Utils::chooseHandler()); $stack->push(Middleware::httpErrors(), 'http_errors'); diff --git a/src/Common/Transport/Middleware.php b/src/Common/Transport/Middleware.php index d11667ef4..c7eaed348 100644 --- a/src/Common/Transport/Middleware.php +++ b/src/Common/Transport/Middleware.php @@ -31,7 +31,7 @@ function (ResponseInterface $response) use ($request, $verbosity) { }; } - public static function authHandler(callable $tokenGenerator, Token $token = null): callable + public static function authHandler(callable $tokenGenerator, ?Token $token = null): callable { return function (callable $handler) use ($tokenGenerator, $token) { return new AuthHandler($handler, $tokenGenerator, $token); @@ -49,7 +49,7 @@ public static function history(array &$container): callable /** * @codeCoverageIgnore */ - public static function retry(callable $decider, callable $delay = null): callable + public static function retry(callable $decider, ?callable $delay = null): callable { return GuzzleMiddleware::retry($decider, $delay); } diff --git a/src/Common/Transport/RequestSerializer.php b/src/Common/Transport/RequestSerializer.php index 533a11c5c..20d29e668 100644 --- a/src/Common/Transport/RequestSerializer.php +++ b/src/Common/Transport/RequestSerializer.php @@ -11,7 +11,7 @@ class RequestSerializer { private $jsonSerializer; - public function __construct(JsonSerializer $jsonSerializer = null) + public function __construct(?JsonSerializer $jsonSerializer = null) { $this->jsonSerializer = $jsonSerializer ?: new JsonSerializer(); } diff --git a/src/Common/Transport/Utils.php b/src/Common/Transport/Utils.php index 6a52a81a2..52a4f3c91 100644 --- a/src/Common/Transport/Utils.php +++ b/src/Common/Transport/Utils.php @@ -45,7 +45,7 @@ public static function jsonDecode(ResponseInterface $response, bool $assoc = tru * * @return array */ - public static function flattenJson($data, string $key = null) + public static function flattenJson($data, ?string $key = null) { return (!empty($data) && $key && isset($data[$key])) ? $data[$key] : $data; } diff --git a/src/Compute/v2/Service.php b/src/Compute/v2/Service.php index 3dc1fd4c8..968b22ebc 100644 --- a/src/Compute/v2/Service.php +++ b/src/Compute/v2/Service.php @@ -44,7 +44,7 @@ public function createServer(array $options): Server * * @return \Generator */ - public function listServers(bool $detailed = false, array $options = [], callable $mapFn = null): \Generator + public function listServers(bool $detailed = false, array $options = [], ?callable $mapFn = null): \Generator { $def = (true === $detailed) ? $this->api->getServersDetail() : $this->api->getServers(); @@ -72,13 +72,13 @@ public function getServer(array $options = []): Server /** * List flavors. * - * @param array $options {@see \OpenStack\Compute\v2\Api::getFlavors} - * @param callable $mapFn a callable function that will be invoked on every iteration of the list - * @param bool $detailed set to true to fetch flavors' details + * @param array $options {@see \OpenStack\Compute\v2\Api::getFlavors} + * @param callable|null $mapFn a callable function that will be invoked on every iteration of the list + * @param bool $detailed set to true to fetch flavors' details * * @return \Generator */ - public function listFlavors(array $options = [], callable $mapFn = null, bool $detailed = false): \Generator + public function listFlavors(array $options = [], ?callable $mapFn = null, bool $detailed = false): \Generator { $def = true === $detailed ? $this->api->getFlavorsDetail() : $this->api->getFlavors(); @@ -119,7 +119,7 @@ public function createFlavor(array $options = []): Flavor * * @return \Generator */ - public function listImages(array $options = [], callable $mapFn = null): \Generator + public function listImages(array $options = [], ?callable $mapFn = null): \Generator { return $this->model(Image::class)->enumerate($this->api->getImages(), $options, $mapFn); } @@ -143,12 +143,12 @@ public function getImage(array $options = []): Image /** * List key pairs. * - * @param array $options {@see \OpenStack\Compute\v2\Api::getKeyPairs} - * @param callable $mapFn a callable function that will be invoked on every iteration of the list + * @param array $options {@see \OpenStack\Compute\v2\Api::getKeyPairs} + * @param callable|null $mapFn a callable function that will be invoked on every iteration of the list * * @return \Generator */ - public function listKeypairs(array $options = [], callable $mapFn = null): \Generator + public function listKeypairs(array $options = [], ?callable $mapFn = null): \Generator { return $this->model(Keypair::class)->enumerate($this->api->getKeypairs(), $options, $mapFn); } @@ -197,14 +197,14 @@ public function getHypervisorStatistics(): HypervisorStatistic /** * List hypervisors. * - * @param bool $detailed Determines whether detailed information will be returned. If FALSE is specified, only - * the ID, name and links attributes are returned, saving bandwidth. - * @param array $options {@see \OpenStack\Compute\v2\Api::getHypervisors} - * @param callable $mapFn a callable function that will be invoked on every iteration of the list + * @param bool $detailed Determines whether detailed information will be returned. If FALSE is specified, only + * the ID, name and links attributes are returned, saving bandwidth. + * @param array $options {@see \OpenStack\Compute\v2\Api::getHypervisors} + * @param callable|null $mapFn a callable function that will be invoked on every iteration of the list * * @return \Generator */ - public function listHypervisors(bool $detailed = false, array $options = [], callable $mapFn = null): \Generator + public function listHypervisors(bool $detailed = false, array $options = [], ?callable $mapFn = null): \Generator { $def = (true === $detailed) ? $this->api->getHypervisorsDetail() : $this->api->getHypervisors(); @@ -224,12 +224,12 @@ public function getHypervisor(array $options = []): Hypervisor /** * List hosts. * - * @param array $options {@see \OpenStack\Compute\v2\Api::getHosts} - * @param callable $mapFn a callable function that will be invoked on every iteration of the list + * @param array $options {@see \OpenStack\Compute\v2\Api::getHosts} + * @param callable|null $mapFn a callable function that will be invoked on every iteration of the list * * @return \Generator */ - public function listHosts(array $options = [], callable $mapFn = null): \Generator + public function listHosts(array $options = [], ?callable $mapFn = null): \Generator { return $this->model(Host::class)->enumerate($this->api->getHosts(), $options, $mapFn); } @@ -255,12 +255,12 @@ public function getHost(array $options = []): Host /** * List AZs. * - * @param array $options {@see \OpenStack\Compute\v2\Api::getAvailabilityZones} - * @param callable $mapFn a callable function that will be invoked on every iteration of the list + * @param array $options {@see \OpenStack\Compute\v2\Api::getAvailabilityZones} + * @param callable|null $mapFn a callable function that will be invoked on every iteration of the list * * @return \Generator */ - public function listAvailabilityZones(array $options = [], callable $mapFn = null): \Generator + public function listAvailabilityZones(array $options = [], ?callable $mapFn = null): \Generator { return $this->model(AvailabilityZone::class)->enumerate($this->api->getAvailabilityZones(), $options, $mapFn); } diff --git a/src/Images/v2/Models/Schema.php b/src/Images/v2/Models/Schema.php index 44532fab2..10373e6fa 100644 --- a/src/Images/v2/Models/Schema.php +++ b/src/Images/v2/Models/Schema.php @@ -8,7 +8,7 @@ class Schema extends \OpenStack\Common\JsonSchema\Schema { - public function __construct($data, Validator $validator = null) + public function __construct($data, ?Validator $validator = null) { if (!isset($data->type)) { $data->type = 'object'; diff --git a/src/Networking/v2/Extensions/Layer3/Api.php b/src/Networking/v2/Extensions/Layer3/Api.php index faab09ac6..c7b3ec8ec 100644 --- a/src/Networking/v2/Extensions/Layer3/Api.php +++ b/src/Networking/v2/Extensions/Layer3/Api.php @@ -26,6 +26,7 @@ public function postFloatingIps(): array 'jsonKey' => 'floatingip', 'params' => [ 'tenantId' => $this->params->tenantIdJson(), + 'description' => $this->notRequired($this->params->descriptionJson()), 'floatingNetworkId' => $this->params->floatingNetworkIdJson(), 'fixedIpAddress' => $this->params->fixedIpAddressJson(), 'floatingIpAddress' => $this->params->floatingIpAddressJson(), @@ -53,6 +54,7 @@ public function putFloatingIp(): array 'jsonKey' => 'floatingip', 'params' => [ 'id' => $this->params->idPath(), + 'description' => $this->notRequired($this->params->descriptionJson()), 'floatingNetworkId' => $this->notRequired($this->params->floatingNetworkIdJson()), 'fixedIpAddress' => $this->params->fixedIpAddressJson(), 'floatingIpAddress' => $this->params->floatingIpAddressJson(), diff --git a/src/Networking/v2/Extensions/Layer3/ApiTrait.php b/src/Networking/v2/Extensions/Layer3/ApiTrait.php index 5d7c757ac..362f9bd7b 100644 --- a/src/Networking/v2/Extensions/Layer3/ApiTrait.php +++ b/src/Networking/v2/Extensions/Layer3/ApiTrait.php @@ -20,7 +20,9 @@ public function postFloatingIps(): array 'jsonKey' => 'floatingip', 'params' => [ 'tenantId' => $this->params->tenantIdJson(), + 'description' => $this->notRequired($this->params->descriptionJson()), 'floatingNetworkId' => $this->params->floatingNetworkIdJson(), + 'subnetId' => $this->notRequired($this->params->subnetIdJson()), 'fixedIpAddress' => $this->params->fixedIpAddressJson(), 'floatingIpAddress' => $this->params->floatingIpAddressJson(), 'portId' => $this->params->portIdJson(), @@ -47,6 +49,7 @@ public function putFloatingIp(): array 'jsonKey' => 'floatingip', 'params' => [ 'id' => $this->params->idPath(), + 'description' => $this->notRequired($this->params->descriptionJson()), 'floatingNetworkId' => $this->notRequired($this->params->floatingNetworkIdJson()), 'fixedIpAddress' => $this->params->fixedIpAddressJson(), 'floatingIpAddress' => $this->params->floatingIpAddressJson(), diff --git a/src/Networking/v2/Extensions/Layer3/Models/FloatingIp.php b/src/Networking/v2/Extensions/Layer3/Models/FloatingIp.php index 048b942b2..2a0ecb927 100644 --- a/src/Networking/v2/Extensions/Layer3/Models/FloatingIp.php +++ b/src/Networking/v2/Extensions/Layer3/Models/FloatingIp.php @@ -21,6 +21,9 @@ class FloatingIp extends OperatorResource implements Listable, Creatable, Retrie /** @var string */ public $status; + /** @var string */ + public $description; + /** @var string */ public $floatingNetworkId; diff --git a/src/Networking/v2/Extensions/Layer3/Params.php b/src/Networking/v2/Extensions/Layer3/Params.php index d502f61cd..ef6d2787e 100644 --- a/src/Networking/v2/Extensions/Layer3/Params.php +++ b/src/Networking/v2/Extensions/Layer3/Params.php @@ -9,6 +9,15 @@ */ class Params extends \OpenStack\Networking\v2\Params { + public function descriptionJson(): array + { + return [ + 'type' => self::STRING_TYPE, + 'description' => 'The description of the floating IP.', + 'sentAs' => 'description', + ]; + } + public function tenantIdJson(): array { return [ diff --git a/src/Networking/v2/Extensions/Layer3/ParamsTrait.php b/src/Networking/v2/Extensions/Layer3/ParamsTrait.php index c201a82e7..274656554 100644 --- a/src/Networking/v2/Extensions/Layer3/ParamsTrait.php +++ b/src/Networking/v2/Extensions/Layer3/ParamsTrait.php @@ -9,6 +9,15 @@ */ trait ParamsTrait { + public function descriptionJson(): array + { + return [ + 'type' => self::STRING_TYPE, + 'description' => 'The description of the floating IP.', + 'sentAs' => 'description', + ]; + } + public function floatingNetworkIdJson(): array { return [ @@ -37,6 +46,15 @@ public function floatingIpAddressJson(): array ]; } + public function subnetIdJson(): array + { + return [ + 'type' => self::STRING_TYPE, + 'description' => 'The UUID of the subnet of the floating Network associated with the floating IP.', + 'sentAs' => 'subnet', + ]; + } + public function portIdJson(): array { return [ diff --git a/src/ObjectStore/v1/Models/Container.php b/src/ObjectStore/v1/Models/Container.php index fa9350268..74f2e4662 100644 --- a/src/ObjectStore/v1/Models/Container.php +++ b/src/ObjectStore/v1/Models/Container.php @@ -57,7 +57,7 @@ public function populateFromResponse(ResponseInterface $response): self * * @return \Generator */ - public function listObjects(array $options = [], callable $mapFn = null): \Generator + public function listObjects(array $options = [], ?callable $mapFn = null): \Generator { $options = array_merge($options, ['name' => $this->name, 'format' => 'json']); diff --git a/src/ObjectStore/v1/Service.php b/src/ObjectStore/v1/Service.php index d4bdbae78..e4686c3b6 100644 --- a/src/ObjectStore/v1/Service.php +++ b/src/ObjectStore/v1/Service.php @@ -30,7 +30,7 @@ public function getAccount(): Account * * @return \Generator */ - public function listContainers(array $options = [], callable $mapFn = null): \Generator + public function listContainers(array $options = [], ?callable $mapFn = null): \Generator { $options = array_merge($options, ['format' => 'json']); @@ -41,9 +41,9 @@ public function listContainers(array $options = [], callable $mapFn = null): \Ge * Retrieves a Container object and populates its name according to the value provided. Please note that the * remote API is not contacted. * - * @param string $name The unique name of the container + * @param string|null $name The unique name of the container */ - public function getContainer(string $name = null): Container + public function getContainer(?string $name = null): Container { return $this->model(Container::class, ['name' => $name]); } diff --git a/src/OpenStack.php b/src/OpenStack.php index 4eecd642a..254e66df3 100644 --- a/src/OpenStack.php +++ b/src/OpenStack.php @@ -33,7 +33,7 @@ class OpenStack * ['requestOptions'] = (array) Guzzle Http request options [OPTIONAL] * ['cachedToken'] = (array) Cached token credential [OPTIONAL] */ - public function __construct(array $options = [], Builder $builder = null) + public function __construct(array $options = [], ?Builder $builder = null) { $defaults = ['errorVerbosity' => 2]; $options = array_merge($defaults, $options); diff --git a/tests/sample/Compute/v2/VolumeAttachmentTest.php b/tests/sample/Compute/v2/VolumeAttachmentTest.php index 17361b3c6..62512c949 100644 --- a/tests/sample/Compute/v2/VolumeAttachmentTest.php +++ b/tests/sample/Compute/v2/VolumeAttachmentTest.php @@ -84,9 +84,20 @@ public function testDetach(VolumeAttachment $createdVolumeAttachment) $volume->waitUntil('available', 240); $this->assertEquals('available', $volume->status); + sleep(5); + $server = $this->getService()->getServer(['id' => $createdVolumeAttachment->serverId]); + $server->retrieve(); foreach ($server->listVolumeAttachments() as $volumeAttachment) { - $this->assertNotEquals($createdVolumeAttachment->id, $volumeAttachment->id); + if ($volumeAttachment->volumeId === $createdVolumeAttachment->volumeId) { + print_r($volume); + print_r($volumeAttachment); + print_r($server); + + $this->fail('Volume attachment was not detached'); + } else { + $this->assertNotEquals($createdVolumeAttachment->id, $volumeAttachment->id); + } } $volume->delete(); diff --git a/tests/sample/Networking/v2/FloatingIpTest.php b/tests/sample/Networking/v2/FloatingIpTest.php index 196f0edc5..5c447dbf5 100644 --- a/tests/sample/Networking/v2/FloatingIpTest.php +++ b/tests/sample/Networking/v2/FloatingIpTest.php @@ -63,16 +63,19 @@ public function testCreate(): FloatingIpData 'name' => $this->randomStr(), ]); $fixedIp = $this->findSubnetIp($data->port, $data->internalSubnet); + $description = $this->randomStr(); /** @var FloatingIp $floatingIp */ require_once $this->sampleFile('floatingIPs/create.php', [ '{networkId}' => $data->externalNetwork->id, '{portId}' => $data->port->id, '{fixedIpAddress}' => $fixedIp, + '{description}' => $description, ]); $this->assertInstanceOf(FloatingIp::class, $floatingIp); $this->assertEquals($data->externalNetwork->id, $floatingIp->floatingNetworkId); $this->assertEquals($data->port->id, $floatingIp->portId); + $this->assertEquals($description, $floatingIp->description); $data->floatingIp = $floatingIp; @@ -123,6 +126,7 @@ public function testGet(FloatingIpData $data) $this->assertInstanceOf(FloatingIp::class, $floatingIp); $this->assertEquals($data->floatingIp->id, $floatingIp->id); $this->assertEmpty($floatingIp->portId); + $this->assertEmpty($floatingIp->description); $floatingIp->retrieve(); $this->assertEquals($data->floatingIp->portId, $floatingIp->portId); diff --git a/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIp.resp b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIp.resp index d4f9fbd5d..35a5d434f 100644 --- a/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIp.resp +++ b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIp.resp @@ -8,6 +8,7 @@ Content-Type: application/json "fixed_ip_address": "10.0.0.3", "floating_ip_address": "172.24.4.228", "tenant_id": "4969c491a3c74ee4af974e6d800c62de", + "description": "some-floating-ip", "status": "ACTIVE", "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab", "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7" diff --git a/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIps.resp b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIps.resp index 66046e790..50d7d1033 100644 --- a/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIps.resp +++ b/tests/unit/Networking/v2/Extensions/Layer3/Fixtures/FloatingIps.resp @@ -11,6 +11,7 @@ Content-Type: application/json "floating_ip_address": "172.24.4.228", "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab", "id": "2f245a7b-796b-4f26-9cf9-9e82d248fda7", + "description": "some-floating-ip", "status": "ACTIVE" }, { @@ -21,6 +22,7 @@ Content-Type: application/json "floating_ip_address": "172.24.4.227", "port_id": null, "id": "61cea855-49cb-4846-997d-801b70c71bdd", + "description": "some-floating-ip", "status": "DOWN" } ] diff --git a/tests/unit/Networking/v2/Extensions/Layer3/Models/FloatingIpTest.php b/tests/unit/Networking/v2/Extensions/Layer3/Models/FloatingIpTest.php index a0446f862..7567b0552 100644 --- a/tests/unit/Networking/v2/Extensions/Layer3/Models/FloatingIpTest.php +++ b/tests/unit/Networking/v2/Extensions/Layer3/Models/FloatingIpTest.php @@ -27,12 +27,14 @@ public function test_it_updates() $expectedJson = ['floatingip' => [ "floating_network_id" => "376da547-b977-4cfe-9cba-275c80debf57", "port_id" => "ce705c24-c1ef-408a-bda3-7bbd946164ab", + "description" => "some-floating-ip", ]]; $this->mockRequest('PUT', 'v2.0/floatingips/id', new Response(202), $expectedJson, []); $this->floatingIp->floatingNetworkId = "376da547-b977-4cfe-9cba-275c80debf57"; $this->floatingIp->portId = "ce705c24-c1ef-408a-bda3-7bbd946164ab"; + $this->floatingIp->description = "some-floating-ip"; $this->floatingIp->update(); } @@ -49,6 +51,10 @@ public function test_it_retrieves() $this->floatingIp->retrieve(); + self::assertEquals( + 'some-floating-ip', + $this->floatingIp->description + ); self::assertEquals( '376da547-b977-4cfe-9cba-275c80debf57', $this->floatingIp->floatingNetworkId