From 12d7bafed3548e6c4cb098e6866406f1e31a229e Mon Sep 17 00:00:00 2001 From: i0 Date: Sat, 21 Oct 2017 15:46:05 +0330 Subject: [PATCH] Add flavors extra-specs Add flavors extra-specs support. https://developer.openstack.org/api-ref/compute/#flavors-extra-specs-flavors-os-flavor-extra-specs --- src/Common/Api/Parameter.php | 4 +- src/Common/Resource/HasExtraSpecs.php | 56 +++++++++++++++++++++++++++ src/Compute/v2/Api.php | 33 ++++++++++++++++ src/Compute/v2/Models/Flavor.php | 42 ++++++++++++++++++-- src/Compute/v2/Params.php | 17 ++++++++ 5 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 src/Common/Resource/HasExtraSpecs.php diff --git a/src/Common/Api/Parameter.php b/src/Common/Api/Parameter.php index 15ab8369..ff91f1db 100644 --- a/src/Common/Api/Parameter.php +++ b/src/Common/Api/Parameter.php @@ -151,7 +151,7 @@ private function stockItemSchema(array $data) private function stockProperties(array $data) { if (isset($data['properties'])) { - if ($this->name && stripos($this->name, 'metadata') !== false) { + if ($this->name && (stripos($this->name, 'metadata') !== false || stripos($this->name, 'extraSpecs') !== false)) { $this->properties = new Parameter($data['properties']); } else { foreach ($data['properties'] as $name => $property) { @@ -247,7 +247,7 @@ private function validateObject($userValues) */ private function getNestedProperty($key): Parameter { - if ($this->name && stripos($this->name, 'metadata') !== false && $this->properties instanceof Parameter) { + if ($this->name && (stripos($this->name, 'metadata') !== false || stripos($this->name, 'extraSpecs') !== false) && $this->properties instanceof Parameter) { return $this->properties; } elseif (isset($this->properties[$key])) { return $this->properties[$key]; diff --git a/src/Common/Resource/HasExtraSpecs.php b/src/Common/Resource/HasExtraSpecs.php new file mode 100644 index 00000000..7ec136bb --- /dev/null +++ b/src/Common/Resource/HasExtraSpecs.php @@ -0,0 +1,56 @@ + 'val3', 'Baz' => 'val4']); is called, then the resource will have the following + * extra specs: + * + * Foo: val3 + * Bar: val2 + * Baz: val4 + * + * You will notice that any extra specs items which are not specified in the call are preserved. + * + * @param array $extra specs The new extra specs items + * + * @return void + */ + public function mergeExtraSpecs(array $extraSpecs); + + /** + * Deletes an extra spec, by key, for a flavor, by ID. + * + * @param string $extra specs key + * + * @return void + */ + public function deleteExtraSpec($extraSpecs); + + /** + * Extracts extra specs from a response object and returns it in the form of an associative array. + * + * @param ResponseInterface $response + * + * @return array + */ + public function parseExtraSpecs(ResponseInterface $response): array; +} diff --git a/src/Compute/v2/Api.php b/src/Compute/v2/Api.php index 6ef4d24f..9ff37059 100644 --- a/src/Compute/v2/Api.php +++ b/src/Compute/v2/Api.php @@ -84,6 +84,39 @@ public function deleteFlavor(): array ]; } + public function getFlavorExtraSpecs(): array + { + return [ + 'method' => 'GET', + 'path' => 'flavors/{id}/os-extra_specs', + 'params' => ['id' => $this->params->urlId('flavor')] + ]; + } + + public function postFlavorExtraSpecs(): array + { + return [ + 'method' => 'POST', + 'path' => 'flavors/{id}/os-extra_specs', + 'params' => [ + 'id' => $this->params->urlId('flavor'), + 'extraSpecs' => $this->params->extraSpecs() + ] + ]; + } + + public function deleteFlavorExtraSpecKey(): array + { + return [ + 'method' => 'DELETE', + 'path' => 'flavors/{id}/os-extra_specs/{key}', + 'params' => [ + 'id' => $this->params->urlId('flavor'), + 'key' => $this->params->key(), + ] + ]; + } + public function getImages(): array { return [ diff --git a/src/Compute/v2/Models/Flavor.php b/src/Compute/v2/Models/Flavor.php index 0455492c..d015de1d 100644 --- a/src/Compute/v2/Models/Flavor.php +++ b/src/Compute/v2/Models/Flavor.php @@ -4,16 +4,19 @@ use OpenStack\Common\Resource\Creatable; use OpenStack\Common\Resource\Deletable; +use OpenStack\Common\Resource\HasExtraSpecs; use OpenStack\Common\Resource\OperatorResource; use OpenStack\Common\Resource\Listable; use OpenStack\Common\Resource\Retrievable; +use OpenStack\Common\Transport\Utils; +use Psr\Http\Message\ResponseInterface; /** * Represents a Compute v2 Flavor. * * @property \OpenStack\Compute\v2\Api $api */ -class Flavor extends OperatorResource implements Listable, Retrievable, Creatable, Deletable +class Flavor extends OperatorResource implements Listable, Retrievable, Creatable, Deletable, HasExtraSpecs { /** @var int */ public $disk; @@ -36,15 +39,25 @@ class Flavor extends OperatorResource implements Listable, Retrievable, Creatabl /** @var array */ public $links; + /** @var array */ + public $extraSpecs = []; + protected $resourceKey = 'flavor'; protected $resourcesKey = 'flavors'; + public function populateFromResponse(ResponseInterface $response): self + { + parent::populateFromResponse($response); + $this->extraSpecs = $this->parseExtraSpecs($response); + return $this; + } + /** * {@inheritDoc} */ public function retrieve() { - $response = $this->execute($this->api->getFlavor(), ['id' => (string) $this->id]); + $response = $this->execute($this->api->getFlavor(), ['id' => (string)$this->id]); $this->populateFromResponse($response); } @@ -62,6 +75,29 @@ public function create(array $userOptions): Creatable */ public function delete() { - $this->execute($this->api->deleteFlavor(), ['id' => (string) $this->id]); + $this->execute($this->api->deleteFlavor(), ['id' => (string)$this->id]); + } + + public function getExtraSpecs(): array + { + $response = $this->executeWithState($this->api->getFlavorExtraSpecs()); + $this->extraSpecs = $this->parseExtraSpecs($response); + return $this->extraSpecs; + } + + public function mergeExtraSpecs(array $extraSpecs) + { + $this->execute($this->api->postFlavorExtraSpecs(), ['id' => $this->id, 'extraSpecs' => $extraSpecs]); + } + + public function deleteExtraSpec($key) + { + $this->execute($this->api->deleteFlavorExtraSpecKey(), ['id' => $this->id, 'key' => $key]); + } + + public function parseExtraSpecs(ResponseInterface $response): array + { + $json = Utils::jsonDecode($response); + return isset($json['extra_specs']) ? $json['extra_specs'] : []; } } diff --git a/src/Compute/v2/Params.php b/src/Compute/v2/Params.php index b65df14f..5cff2607 100644 --- a/src/Compute/v2/Params.php +++ b/src/Compute/v2/Params.php @@ -146,6 +146,23 @@ public function metadata(): array ]; } + public function extraSpecs(): array + { + return [ + 'type' => self::OBJECT_TYPE, + 'sentAs' => 'extra_specs', + 'location' => self::JSON, + 'required' => true, + 'description' => 'An arbitrary key/value pairing that will be used for extra specs.', + 'properties' => [ + 'type' => self::STRING_TYPE, + 'description' => <<