Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flavors extra-specs #165

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Common/Api/Parameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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];
Expand Down
56 changes: 56 additions & 0 deletions src/Common/Resource/HasExtraSpecs.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php declare(strict_types=1);

namespace OpenStack\Common\Resource;

use Psr\Http\Message\ResponseInterface;

interface HasExtraSpecs
{
/**
* Retrieves extra specs for the resource in the form of an associative array or hash. Each key represents the
* extra specs item's name, and each value represents extra specs item's remote value.
*
* @return array
*/
public function getExtraSpecs(): array;

/**
* Merges a set of new values with those which already exist (on the remote API) for a resource. For example, if
* the resource has this extra specs already set:
*
* Foo: val1
* Bar: val2
*
* and mergeExtraSpecs(['Foo' => '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;
}
33 changes: 33 additions & 0 deletions src/Compute/v2/Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 [
Expand Down
42 changes: 39 additions & 3 deletions src/Compute/v2/Models/Flavor.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}

Expand All @@ -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'] : [];
}
}
17 changes: 17 additions & 0 deletions src/Compute/v2/Params.php
Original file line number Diff line number Diff line change
Expand Up @@ -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' => <<<TYPEOTHER
The value being set for your key. Bear in mind that "key" is just an example, you can name it anything.
TYPEOTHER
]
];
}

public function personality(): array
{
return [
Expand Down