      1: <?php
      2: /**
      3:  * Copyright 2012-2014 Rackspace US, Inc.
      4:  *
      5:  * Licensed under the Apache License, Version 2.0 (the "License");
      6:  * you may not use this file except in compliance with the License.
      7:  * You may obtain a copy of the License at
      8:  *
      9:  * http://www.apache.org/licenses/LICENSE-2.0
     10:  *
     11:  * Unless required by applicable law or agreed to in writing, software
     12:  * distributed under the License is distributed on an "AS IS" BASIS,
     13:  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14:  * See the License for the specific language governing permissions and
     15:  * limitations under the License.
     16:  */
     17:
     18: namespace OpenCloud\Image\Resource;
     19:
     20: use OpenCloud\Image\Enum\OperationType;
     21: use OpenCloud\Image\Resource\JsonPatch\Document as JsonDocument;
     22: use OpenCloud\Image\Resource\JsonPatch\Operation as JsonOperation;
     23: use OpenCloud\Image\Resource\Schema\Schema;
     24:
     25: /**
     26:  * Class that represents a Glance Image. In more general terms, a virtual machine image is a single file which contains
     27:  * a virtual disk that has an installed bootable operating system. In the Cloud Images API, an image is represented by
     28:  * a JSON-encoded data structure (the image schema) and its raw binary data (the image file).
     29:  *
     30:  * @package OpenCloud\Images\Resource
     31:  */
     32: class Image extends AbstractSchemaResource implements ImageInterface
     33: {
     34:     protected static $url_resource = 'images';
     35:     protected static $json_name = '';
     36:     protected static $json_collection_name = 'images';
     37:
     38:     /**
     39:      * Update this resource
     40:      *
     41:      * @param array  $params
     42:      * @param Schema $schema
     43:      * @return \Guzzle\Http\Message\Response
     44:      * @throws \RuntimeException
     45:      */
     46:     public function update(array $params, Schema $schema = null)
     47:     {
     48:         $schema = $schema ?: $this->getService()->getImageSchema();
     49:
     50:         $document = new JsonDocument();
     51:
     52:         foreach ($params as $propertyName => $value) {
     53:
     54:             // find property object
     55:             if (!($property = $schema->getProperty($propertyName))) {
     56:                 // check whether additional properties are found
     57:                 if (false === ($property = $schema->validateAdditionalProperty($value))) {
     58:                     throw new \RuntimeException(
     59:                         'If a property does not exist in the schema, the `additionalProperties` property must be set'
     60:                     );
     61:                 }
     62:             }
     63:
     64:             // do validation checks
     65:             $property->setName($propertyName);
     66:             $property->setValue($value);
     67:             $property->validate();
     68:
     69:             // decide operation type
     70:             if (!$value) {
     71:                 $operationType = OperationType::REMOVE;
     72:             } elseif ($this->offsetExists($propertyName)) {
     73:                 $operationType = OperationType::REPLACE;
     74:             } else {
     75:                 $operationType = $schema->decideOperationType($property);
     76:             }
     77:
     78:             // create JSON-patch operation
     79:             $operation = JsonOperation::factory($schema, $property, $operationType);
     80:
     81:             // add to JSON document
     82:             $document->addOperation($operation);
     83:         }
     84:
     85:         // create request
     86:         $body = $document->toString();
     87:
     88:         return $this->getClient()
     89:             ->patch($this->getUrl(), $this->getService()->getPatchHeaders(), $body)
     90:             ->send();
     91:     }
     92:
     93:     /**
     94:      * Refresh this resource
     95:      *
     96:      * @return \Guzzle\Http\Message\Response
     97:      */
     98:     public function refresh()
     99:     {
    100:         $response = $this->getClient()->get($this->getUrl())->send();
    101:
    102:         $this->setData($response->json());
    103:
    104:         return $response;
    105:     }
    106:
    107:     /**
    108:      * Delete this resource
    109:      *
    110:      * @return \Guzzle\Http\Message\Response
    111:      */
    112:     public function delete()
    113:     {
    114:         return $this->getClient()->delete($this->getUrl())->send();
    115:     }
    116:
    117:     /**
    118:      * List the members of this image
    119:      *
    120:      * @param array $params
    121:      * @return mixed
    122:      */
    123:     public function listMembers(array $params = array())
    124:     {
    125:         $url = clone $this->getUrl();
    126:         $url->addPath(Member::resourceName())->setQuery($params);
    127:
    128:         return $this->getService()->resourceList('Member', $url, $this);
    129:     }
    130:
    131:     /**
    132:      * Iterator use only
    133:      *
    134:      * @param $data
    135:      * @return mixed
    136:      */
    137:     public function member($data)
    138:     {
    139:         $data = (array) $data;
    140:
    141:         $member = $this->getService()->resource('Member', null, $this);
    142:         $member->setData($data);
    143:
    144:         if (isset($data['member_id'])) {
    145:             $member->setId($data['member_id']);
    146:         }
    147:
    148:         return $member;
    149:     }
    150:
    151:     /**
    152:      * Get a member belonging to this image
    153:      *
    154:      * @param $memberId
    155:      * @return mixed
    156:      */
    157:     public function getMember($memberId)
    158:     {
    159:         $url = clone $this->getUrl();
    160:         $url->addPath('members');
    161:         $url->addPath((string) $memberId);
    162:
    163:         $data = $this->getClient()->get($url)->send()->json();
    164:
    165:         return $this->member($data);
    166:     }
    167:
    168:     /**
    169:      * Add a member to this image
    170:      *
    171:      * @param $tenantId
    172:      * @return \Guzzle\Http\Message\Response
    173:      */
    174:     public function createMember($tenantId)
    175:     {
    176:         $url = $this->getUrl();
    177:         $url->addPath('members');
    178:
    179:         $json = json_encode(array('member' => $tenantId));
    180:         return $this->getClient()->post($url, self::getJsonHeader(), $json)->send();
    181:     }
    182:
    183:     /**
    184:      * Delete a member from this image
    185:      *
    186:      * @param $tenantId
    187:      * @return \Guzzle\Http\Message\Response
    188:      */
    189:     public function deleteMember($tenantId)
    190:     {
    191:         $url = $this->getUrl();
    192:         $url->addPath('members');
    193:         $url->addPath((string)$tenantId);
    194:
    195:         return $this->getClient()->delete($url)->send();
    196:     }
    197:
    198:     /**
    199:      * Add a tag to this image
    200:      *
    201:      * @param string $tag
    202:      * @return \Guzzle\Http\Message\Response
    203:      */
    204:     public function addTag($tag)
    205:     {
    206:         $url = clone $this->getUrl();
    207:         $url->addPath('tags')->addPath((string) $tag);
    208:
    209:         return $this->getClient()->put($url)->send();
    210:     }
    211:
    212:     /**
    213:      * Delete a tag from this image
    214:      *
    215:      * @param $tag
    216:      * @return \Guzzle\Http\Message\Response
    217:      */
    218:     public function deleteTag($tag)
    219:     {
    220:         $url = clone $this->getUrl();
    221:         $url->addPath('tags')->addPath((string) $tag);
    222:
    223:         return $this->getClient()->delete($url)->send();
    224:     }
    225: }
    226: