diff --git a/README.md b/README.md index 21731f5..981ea0a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -#php-rackspace-clouddb - *work-in-progress* +#php-rackspace-clouddb PHP Class for connecting applications to [Rackspace's Cloud Databases Service](http://www.rackspace.com/cloud/cloud_hosting_products/databases/) @@ -95,4 +95,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/example.php b/example.php new file mode 100644 index 0000000..424f125 --- /dev/null +++ b/example.php @@ -0,0 +1,47 @@ +#!/usr/bin/php -q +listInstances(); + +// List all database users in an instance +//$responseObject = $rcdb->listDatabaseInstanceUsers(RACKSPACE_INSTANCE_ID); + +// List all flavors (hardware profiles) +//$responseObject = $rcdb->listFlavors(); + +// Create a new database (with the name defined in $database) +//$responseObject = $rcdb->createDatabase(RACKSPACE_INSTANCE_ID, $database); + +// Create a new user ('john.smith' with the password 'p4ssw0rd') +//$responseObject = $rcdb->createUser(RACKSPACE_INSTANCE_ID,$database,'john.smith','p4assw0rd'); + +// Grant a user ('john.smith') access to a database +//$responseObject = $rcdb->grantUserAccess(RACKSPACE_INSTANCE_ID, $database, 'john.smith'); + +// Revoke a users access to a database +//$responseObject = $rcdb->revokeUserAccess(RACKSPACE_INSTANCE_ID, $database, 'john.smith'); + +// NB: Some operations (such as creating a database or a user) don't return a +// JSON response object unless there an error occurs. +echo '
'.print_r($responseObject,true).'
'; + +?> diff --git a/rackspace-clouddb.class.php b/rackspace-clouddb.class.php index fae9a1f..8867b57 100644 --- a/rackspace-clouddb.class.php +++ b/rackspace-clouddb.class.php @@ -1,327 +1,358 @@ - * @link https://github.com/variableaction/php-rackspace-clouddb -*/ -########################################################################################################### - - class RackspaceCloudDB { - - private $account; - private $authToken; - - # ----------------------------------------------------------------------------------- - # __construct() - # stores account details, generates endpoints, and generates token - # ----------------------------------------------------------------------------------- - - public function __construct($username,$apiKey,$accountID,$datacenter='ORD',$authGeo='US',$automaticallyCreateToken=true) { - - // Set Account Details - $this->account->username = $username; - $this->account->apiKey = $apiKey; - $this->account->id = $accountID; - - // Set/generate API endpoints - $this->setEndpoints($authGeo,$datacenter); - - // Automatically create token (if $automaticallyCreateToken is true) - if ($automaticallyCreateToken) { $this->createAuthToken(); } - - } - - # --------------------------------------------------------------------------------- - # setEndpoints() - # defaults to US and Chicago Datacenter (ORD) - # --------------------------------------------------------------------------------- - - private function setEndpoints($authGeo,$datacenter) { - - // ---------------------------------------------------------------------- - // Set auth endpoint - // ---------------------------------------------------------------------- - - switch ($authGeo) { - - case 'UK': - $this->api->endpoints->auth = 'https://lon.identity.api.rackspacecloud.com/v1.1/auth'; - //$this->api->endpoints->auth = 'https://lon.identity.api.rackspacecloud.com/v2.0/'; - break; - - case 'US': - default: - $this->api->endpoints->auth = 'https://identity.api.rackspacecloud.com/v1.1/auth'; - //$this->api->endpoints->auth = 'https://identity.api.rackspacecloud.com/v2.0/'; - break; - - } - - // ---------------------------------------------------------------------- - // Set datacenter endpoint - // ---------------------------------------------------------------------- - - switch ($datacenter) { - - // London - case 'LON': - $this->api->endpoints->clouddb = 'https://lon.databases.api.rackspacecloud.com/v1.0/'; - break; - - // Dallas/Ft. Worth - case 'DFW': - $this->api->endpoints->clouddb = 'https://dfw.databases.api.rackspacecloud.com/v1.0/'; - break; - - // Chicago - case 'ORD': - default: - $this->api->endpoints->clouddb = 'https://ord.databases.api.rackspacecloud.com/v1.0/'; - break; - - } - - - // Append account number for endpoint - $this->api->endpoints->clouddb = "{$this->api->endpoints->clouddb}{$this->account->id}/"; - - } - - # ----------------------------------------------------------------------------------- - # basicCURL() - # ----------------------------------------------------------------------------------- - - private function basicCURL($url,$headers=array(),$data=null,$additionalOptions=null) { - - // setup handler - $ch = curl_init($url); - - // Set options - curl_setopt_array($ch,array( - CURLOPT_HTTPHEADER => $headers, - CURLOPT_RETURNTRANSFER => 1 - )); - - // if there is data, attach it to the request - if ($data) { - curl_setopt_array($ch,array( - CURLOPT_POST => 1, - CURLOPT_POSTFIELDS => $data, - )); - } - - // add additional options if sent - if ($additionalOptions) { - curl_setopt_array($ch,$additionalOptions); - } - - // execute request - $response = curl_exec($ch); - - // close connection - curl_close($ch); - - // return reponse - return $response; - - } - - # ----------------------------------------------------------------------------------- - # createAuthToken() - # ----------------------------------------------------------------------------------- - - public function createAuthToken() { - - $this->api->endpoints->auth; - - $requestObject->credentials->username = $this->account->username; - $requestObject->credentials->key = $this->account->apiKey; - - $jsonString = json_encode($requestObject); - - $response = $this->basicCURL( - $this->api->endpoints->auth, - array('Content-Type: application/json'), - $jsonString - ); - - $objectFromResponse = json_decode($response); - - // Set auth token - $this->authToken = $objectFromResponse->auth->token->id; - - } - - # ----------------------------------------------------------------------------------- - # listFlavors() - # ----------------------------------------------------------------------------------- - - public function listFlavors() { - $response = $this->basicCURL( - $this->api->endpoints->clouddb.'/flavors/detail', - array('X-Auth-Token: '.$this->authToken,'Accept: application/json','Accept: application/json') - ); - return json_decode($response); - } - - - # ----------------------------------------------------------------------------------- - # listInstances() - # ----------------------------------------------------------------------------------- - - public function listInstances() { - - $response = $this->basicCURL( - $this->api->endpoints->clouddb.'/instances', - array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json') - - ); - - //$objectFromResponse = json_decode($response); - - return json_decode($response); - - } - - # ----------------------------------------------------------------------------------- - # createInstance() - # ----------------------------------------------------------------------------------- - - public function createInstance($instanceName,$flavor='1',$volumeSize='2') { - - $requestObject->instance->flavorRef = $this->api->endpoints->clouddb.'/flavors/'.$flavor; - $requestObject->instance->name = $instanceName; - $requestObject->instance->volume = (object) array('size' => $volumeSize); - - $jsonString = json_encode($requestObject); - - $response = $this->basicCURL( - $this->api->endpoints->clouddb.'/instances', - array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), - $jsonString - ); - - return json_decode($response); - - } - - - # ----------------------------------------------------------------------------------- - # deleteInstance() -- tested; works - # ----------------------------------------------------------------------------------- - - public function deleteInstance($instanceID) { - $response = $this->basicCURL( - $this->api->endpoints->clouddb.'/instances/'.$instanceID, - array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), - null, - array(CURLOPT_CUSTOMREQUEST => "DELETE") - ); - return json_decode($response); - } - - # ----------------------------------------------------------------------------------- - # createDatabase() - # ----------------------------------------------------------------------------------- - - public function createDatabase($instanceID,$dbName) { - - $requestObject->databases[] = (object) array("name" => $dbName); - - $jsonString = json_encode($requestObject); - - $response = $this->basicCURL( - $this->api->endpoints->clouddb.'/instances/'.$instanceID.'/databases', - array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), - $jsonString - ); - - return json_decode($response); - - } - - - # ----------------------------------------------------------------------------------- - # listDatabaseInstanceDatabases() - # ----------------------------------------------------------------------------------- - - public function listDatabaseInstanceDatabases($instanceID) { - - $response = $this->basicCURL( - $this->api->endpoints->clouddb.'/instances/'.$instanceID.'/databases', - array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json') - - ); - - return json_decode($response); - - - } - - # ----------------------------------------------------------------------------------- - # listDatabaseInstanceUsers() - # ----------------------------------------------------------------------------------- - - public function listDatabaseInstanceUsers($instanceID) { - - $response = $this->basicCURL( - $this->api->endpoints->clouddb.'/instances/'.$instanceID.'/users', - array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json') - - ); - - return json_decode($response); - - - } - - # ----------------------------------------------------------------------------------- - # createUser() -- creates with access to a specific database - # looks like the API response to this is just a 202 header - # ----------------------------------------------------------------------------------- - - public function createUser($instanceID,$dbName,$username,$password) { - - $requestObject->users[] = (object) array( - "databases" => array((object) array("name" => $dbName)), - "name" => $username, - "password" => $password - ); - - - $jsonString = json_encode($requestObject); - - $response = $this->basicCURL( - $this->api->endpoints->clouddb.'/instances/'.$instanceID.'/users', - array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), - $jsonString - ); - - return json_decode($response); - } - - # ----------------------------------------------------------------------------------- - # restartInstance() -- tested; works - # ----------------------------------------------------------------------------------- - - public function restartInstance($instanceID) { - - $response = $this->basicCURL( - $this->api->endpoints->clouddb.'/instances/'.$instanceID.'/action', - array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), - '{"restart": {}}' - ); - - return json_decode($response); - } - - - - - } - -?> + * @author Andy Fleming + * @author Iain Collins + * @version 1.1 + * @link https://github.com/variableaction/php-rackspace-clouddb + */ + +class RackspaceCloudDB { + + private $account; + private $authToken; + + /** + * @param string $username Your Rackspace username + * @param string $apiKey Your Rackspace API Key + * @param string $accountId Your Rackspace Account ID + * @param string $datacenter Your datacenter e.g.'ORD' (Chicago - Default), 'DFW' (Dallas/Ft. Worth), 'LON' (London) + * @param string $authGeo Your authentication region e.g. 'US' (Default), 'UK' + * @param bool $automaticallyCreateToken Default true + */ + public function __construct($username,$apiKey,$accountId,$datacenter='ORD',$authGeo='US',$automaticallyCreateToken=true) { + + // Set Account Details + $this->account->username = $username; + $this->account->apiKey = $apiKey; + $this->account->id = $accountId; + + // Set/generate API endpoints + $this->setEndpoints($datacenter, $authGeo); + + // Automatically create token (if $automaticallyCreateToken is true) + if ($automaticallyCreateToken) + $this->createAuthToken(); + } + + /** + * Set endpoints for requests (where they need to go) based on region and datacenter. + * + * @param string $datacenter Your datacenter e.g.'ORD' (Chicago - Default), 'LON' (London) + * @param string $authGeo Your authentication region e.g. 'US' (Default), 'UK' + */ + private function setEndpoints($datacenter,$authGeo) { + + // Set auth endpoint based on region + switch ($authGeo) { + case 'UK': + $this->api->endpoints->auth = 'https://lon.identity.api.rackspacecloud.com/v1.1/auth'; + //$this->api->endpoints->auth = 'https://lon.identity.api.rackspacecloud.com/v2.0/'; + break; + case 'US': + default: + $this->api->endpoints->auth = 'https://identity.api.rackspacecloud.com/v1.1/auth'; + //$this->api->endpoints->auth = 'https://identity.api.rackspacecloud.com/v2.0/'; + break; + } + + // Set clouddb endpoint based on specific datacenter + switch ($datacenter) { + + case 'LON': // London + $this->api->endpoints->clouddb = 'https://lon.databases.api.rackspacecloud.com/v1.0/'; + break; + case 'DFW': // Dallas/Ft. Worth + $this->api->endpoints->clouddb = 'https://dfw.databases.api.rackspacecloud.com/v1.0/'; + break; + case 'ORD': // Chicago + default: + $this->api->endpoints->clouddb = 'https://ord.databases.api.rackspacecloud.com/v1.0/'; + break; + } + + // Append account number for endpoint + $this->api->endpoints->clouddb = "{$this->api->endpoints->clouddb}{$this->account->id}/"; + + } + + /** + * Make requests using libcurl + */ + private function basicCURL($url,$headers=array(),$data=null,$additionalOptions=null) { + + // setup handler + $ch = curl_init($url); + + // Set options + curl_setopt_array($ch,array( + CURLOPT_HTTPHEADER => $headers, + CURLOPT_RETURNTRANSFER => 1 + )); + + // if there is data, attach it to the request + if ($data) { + curl_setopt_array($ch,array( + CURLOPT_POST => 1, + CURLOPT_POSTFIELDS => $data, + )); + } + + // add additional options if sent + if ($additionalOptions) { + curl_setopt_array($ch,$additionalOptions); + } + + // execute request + $response = curl_exec($ch); + + // close connection + curl_close($ch); + + // return reponse + return $response; + + } + + /** + * Create a new authtoken used for all subsequent requests + */ + public function createAuthToken() { + + $this->api->endpoints->auth; + + $requestObject->credentials->username = $this->account->username; + $requestObject->credentials->key = $this->account->apiKey; + + $jsonString = json_encode($requestObject); + + $response = $this->basicCURL( + $this->api->endpoints->auth, + array('Content-Type: application/json'), + $jsonString + ); + + $objectFromResponse = json_decode($response); + + // Set auth token + $this->authToken = $objectFromResponse->auth->token->id; + + } + + /** + * List all available flavours. + * + * From the Rackspace documentation: + * "A flavor is an available hardware configuration for a database instance. + * Each flavor has a unique combination of memory capacity and priority for CPU time." + */ + public function listFlavors() { + $response = $this->basicCURL( + $this->api->endpoints->clouddb.'/flavors', + array('X-Auth-Token: '.$this->authToken,'Accept: application/json','Accept: application/json') + ); + return json_decode($response); + } + + /** + * List all avalible clouddb instances on an account + */ + public function listInstances() { + $response = $this->basicCURL( + $this->api->endpoints->clouddb.'/instances', + array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json') + ); + return json_decode($response); + } + + /** + * Create a new clouddb instance. + * + * The $sizeInGigabytes must be between 1 and 150. It can be increased later, but not decreased. + * + * @param string $instanceName A user firendly name for the new instance + * @param int $flavour An ID of the flavour (i.e. hardware config) for this instance (default '1') + * @param int $sizeInGigabytes The size of the volume in Gigabytes (Default 1 GB, can be increased later) + */ + public function createInstance($instanceName,$flavor='1',$sizeInGigabytes='1') { + + $requestObject->instance->flavorRef = $this->api->endpoints->clouddb.'/flavors/'.$flavor; + $requestObject->instance->name = $instanceName; + $requestObject->instance->volume = (object) array('size' => $sizeInGigabytes); + + $jsonString = json_encode($requestObject); + + $response = $this->basicCURL( + $this->api->endpoints->clouddb.'/instances', + array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), + $jsonString + ); + + return json_decode($response); + } + + /** + * Delete a database instance + * + * @param string $instanceId The ID of the instance to delete + */ + public function deleteInstance($instanceId) { + $response = $this->basicCURL( + $this->api->endpoints->clouddb.'/instances/'.$instanceId, + array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), + null, + array(CURLOPT_CUSTOMREQUEST => "DELETE") + ); + return json_decode($response); + } + + /** + * Delete a database instance + * + * NB: Database names cannot contain periods (MySQL allows this but Rackspace do not). + * + * @param string $instanceId An instance ID + * @param string $database The name of the new database (can contain A-z, 0-9 - and _) + */ + public function createDatabase($instanceId,$database) { + + $requestObject->databases[] = (object) array("name" => $database); + + $jsonString = json_encode($requestObject); + + $response = $this->basicCURL( + $this->api->endpoints->clouddb.'/instances/'.$instanceId.'/databases', + array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), + $jsonString + ); + + return json_decode($response); + + } + + /** + * List all databases in a given instance. + * + * @param string $instanceId An instance ID + */ + public function listDatabaseInstanceDatabases($instanceId) { + $response = $this->basicCURL( + $this->api->endpoints->clouddb.'/instances/'.$instanceId.'/databases', + array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json') + + ); + return json_decode($response); + } + + /** + * List all users in a given instance. + * + * @param string $instanceId An instance ID + */ + public function listDatabaseInstanceUsers($instanceId) { + $response = $this->basicCURL( + $this->api->endpoints->clouddb.'/instances/'.$instanceId.'/users', + array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json') + + ); + return json_decode($response); + } + + /** + * Create a user in an instance, and grant them access to a specific database. + * + * Simply returns a status code of 200 on success. + * + * @param string $instanceId An instance ID + * @param string $database A database to grant them access to + * @param string $username A username for the new user + * @param string $password A password for the new user + */ + public function createUser($instanceId,$database,$username,$password) { + $requestObject->users[] = (object) array( + "databases" => array((object) array("name" => $database)), + "name" => $username, + "password" => $password + ); + + $jsonString = json_encode($requestObject); + + $response = $this->basicCURL( + $this->api->endpoints->clouddb.'/instances/'.$instanceId.'/users', + array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), + $jsonString + ); + + return json_decode($response); + } + + /** + * Grant a user access to a specific database + * + * Simply returns a status code of 200 on success. + * + * @param string $instanceId The ID of the instance the database is in + * @param string $database The database to grant access to + * @param string $username The user to be granted access + */ + public function grantUserAccess($instanceId,$database,$username) { + + $requestObject->databases[] = (object) array("name" => $database); + + $jsonString = json_encode($requestObject); + + $response = $this->basicCURL( + $this->api->endpoints->clouddb.'/instances/'.$instanceId.'/users/'.$username.'/databases', + array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), + $jsonString, + array(CURLOPT_CUSTOMREQUEST => "PUT") + ); + + return json_decode($response); + + } + + /** + * Revoke a users access to a specific database + * + * Simply returns a status code of 200 on success. + * + * @param string $instanceId The ID of the instance the database is in + * @param string $database The database to revoke access from + * @param string $username The user to revoke access from + */ + public function revokeUserAccess($instanceId,$database,$username) { + $response = $this->basicCURL( + $this->api->endpoints->clouddb.'/instances/'.$instanceId.'/users/'.$username.'/databases/'.$database, + array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), + null, + array(CURLOPT_CUSTOMREQUEST => "DELETE") + ); + return json_decode($response); + } + + /** + * Restart an instance. + * + * @param string $instanceId The ID of the instance to restart + */ + public function restartInstance($instanceId) { + $response = $this->basicCURL( + $this->api->endpoints->clouddb.'/instances/'.$instanceId.'/action', + array('X-Auth-Token: '.$this->authToken,'Content-Type: application/json','Accept: application/json'), + '{"restart": {}}' + ); + return json_decode($response); + } + +} +?> \ No newline at end of file