You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2015/06/14 12:52:12 UTC

[01/21] libcloud git commit: DigitalOceanDNSDriver implementation.

Repository: libcloud
Updated Branches:
  refs/heads/trunk 78b95fd9d -> ac75a302d


DigitalOceanDNSDriver implementation.

Pulled connection/response from libcloud.compute.driver.digitalocean into libcloud.common.digitalocean
Implemented majority functions in libcloud.dns.driver.digitalocean

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/f50b8d42
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/f50b8d42
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/f50b8d42

Branch: refs/heads/trunk
Commit: f50b8d421f4b9b930abddda7b400111070c1f2f8
Parents: 78b95fd
Author: Javier Castillo II <jc...@libcloud.castlecorporation.com>
Authored: Sat Apr 11 01:26:18 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:57 2015 +0800

----------------------------------------------------------------------
 libcloud/common/digitalocean.py      | 120 ++++++++++++++
 libcloud/dns/drivers/digitalocean.py | 267 ++++++++++++++++++++++++++++++
 libcloud/dns/providers.py            |   2 +
 libcloud/dns/types.py                |   1 +
 4 files changed, 390 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/f50b8d42/libcloud/common/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/common/digitalocean.py b/libcloud/common/digitalocean.py
new file mode 100644
index 0000000..097b207
--- /dev/null
+++ b/libcloud/common/digitalocean.py
@@ -0,0 +1,120 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Common settings and connection objects for DigitalOcean Cloud
+"""
+
+from libcloud.utils.py3 import httplib
+
+from libcloud.common.base import ConnectionUserAndKey, ConnectionKey
+from libcloud.common.base import JsonResponse
+from libcloud.common.types import InvalidCredsError
+
+__all__ = [
+    'DigitalOcean_v1_Response',
+    'DigitalOcean_v1_Connection',
+    'DigitalOcean_v2_Response'
+    'DigitalOcean_v2_Connection',
+]
+
+AUTH_URL = 'https://api.digitalocean.com'
+
+
+class DigitalOcean_v1_Response(JsonResponse):
+    def parse_error(self):
+        if self.status == httplib.FOUND and '/api/error' in self.body:
+            # Hacky, but DigitalOcean error responses are awful
+            raise InvalidCredsError(self.body)
+        elif self.status == httplib.UNAUTHORIZED:
+            body = self.parse_body()
+            raise InvalidCredsError(body['message'])
+        else:
+            body = self.parse_body()
+
+            if 'error_message' in body:
+                error = '%s (code: %s)' % (body['error_message'], self.status)
+            else:
+                error = body
+            return error
+
+
+class DigitalOcean_v1_Connection(ConnectionUserAndKey):
+    """
+    Connection class for the DigitalOcean (v1) driver.
+    """
+
+    host = 'api.digitalocean.com'
+    responseCls = DigitalOcean_v1_Response
+
+    def add_default_params(self, params):
+        """
+        Add parameters that are necessary for every request
+
+        This method adds ``client_id`` and ``api_key`` to
+        the request.
+        """
+        params['client_id'] = self.user_id
+        params['api_key'] = self.key
+        return params
+
+
+class DigitalOcean_v2_Response(JsonResponse):
+    valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
+                            httplib.NO_CONTENT]
+
+    def parse_error(self):
+        if self.status == httplib.UNAUTHORIZED:
+            body = self.parse_body()
+            raise InvalidCredsError(body['message'])
+        else:
+            body = self.parse_body()
+            if 'message' in body:
+                error = '%s (code: %s)' % (body['message'], self.status)
+            else:
+                error = body
+            return error
+
+    def success(self):
+        return self.status in self.valid_response_codes
+
+
+class DigitalOcean_v2_Connection(ConnectionKey):
+    """
+    Connection class for the DigitalOcean (v2) driver.
+    """
+
+    host = 'api.digitalocean.com'
+    responseCls = DigitalOcean_v2_Response
+
+    def add_default_headers(self, headers):
+        """
+        Add headers that are necessary for every request
+
+        This method adds ``token`` to the request.
+        """
+        headers['Authorization'] = 'Bearer %s' % (self.key)
+        headers['Content-Type'] = 'application/json'
+        return headers
+
+class DigitalOceanConnection(DigitalOcean_v2_Connection):
+    """
+    Connection class for the DigitalOcean driver.
+    """
+    pass
+
+
+class DigitalOceanResponse(DigitalOcean_v2_Response):
+    pass

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f50b8d42/libcloud/dns/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/dns/drivers/digitalocean.py b/libcloud/dns/drivers/digitalocean.py
new file mode 100644
index 0000000..40357b9
--- /dev/null
+++ b/libcloud/dns/drivers/digitalocean.py
@@ -0,0 +1,267 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+Digital Ocean DNS Driver
+"""
+
+__all__ = [
+    'DigitalOceanDNSDriver'
+]
+
+from libcloud.utils.py3 import httplib
+
+from libcloud.common.digitalocean import DigitalOceanConnection, DigitalOceanResponse
+from libcloud.dns.types import Provider, RecordType
+from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError
+from libcloud.dns.base import DNSDriver, Zone, Record
+
+
+class DigitalOceanDNSDriver(DNSDriver):
+    connectionCls = DigitalOceanConnection
+    type = Provider.DIGITAL_OCEAN
+    name = "DigitalOcean"
+    website = 'https://www.digitalocean.com'
+
+    RECORD_TYPE_MAP = {
+        RecordType.NS : 'NS',
+        RecordType.A : 'A',
+        RecordType.AAAA : 'AAAA',
+        RecordType.CNAME : 'CNAME',
+        RecordType.MX : 'MX',
+        RecordType.TXT : 'TXT',
+        RecordType.SRV : 'SRV',
+    }
+
+    def list_zones(self):
+        """
+        Return a list of zones.
+
+        :return: ``list`` of :class:`Zone`
+        """
+        data = self._paginated_request('/v2/domains', 'domains')
+        return list(map(self._to_zone, data))
+
+    def list_records(self, zone):
+        """
+        Return a list of records for the provided zone.
+
+        :param zone: Zone to list records for.
+        :type zone: :class:`Zone`
+
+        :return: ``list`` of :class:`Record`
+        """
+        data = self._paginated_request('/v2/domains/%s/records' % (zone.id),
+                                       'domain_records')
+# TODO: Not use list comprehension to add zone to record for proper data map
+#       functionality?
+        return list(map(self._to_record, data, [zone for z in data]))
+
+    def get_zone(self, zone_id):
+        """
+        Return a Zone instance.
+
+        :param zone_id: ID of the required zone
+        :type  zone_id: ``str``
+
+        :rtype: :class:`Zone`
+        """
+        data = self.connection.request('/v2/domains/%s' %
+               (zone_id)).object['domain']
+
+        return self._to_zone(data)
+
+    def get_record(self, zone_id, record_id):
+        """
+        Return a Record instance.
+
+        :param zone_id: ID of the required zone
+        :type  zone_id: ``str``
+
+        :param record_id: ID of the required record
+        :type  record_id: ``str``
+
+        :rtype: :class:`Record`
+        """
+        data = self.connection.request('/v2/domains/%s/records/%s' % (zone_id,
+                                       record_id)).object['domain_record']
+
+# TODO: Any way of not using get_zone which polls the API again
+#       without breaking the DNSDriver.get_record parameters?
+        return self._to_record(data, self.get_zone(zone_id))
+
+    def create_zone(self, domain, type='master', ttl=None, extra=None):
+        """
+        Create a new zone.
+
+        :param domain: Zone domain name (e.g. example.com)
+        :type domain: ``str``
+
+        :param type: Zone type (master / slave) (does nothing).
+        :type  type: ``str``
+
+        :param ttl: TTL for new records. (does nothing)
+        :type  ttl: ``int``
+
+        :param extra: Extra attributes (to set ip). (optional)
+                      Note: This can be used to set the default A record with
+                      {"ip" : "IP.AD.DR.ESS"} otherwise 127.0.0.1 is used
+        :type extra: ``dict``
+
+        :rtype: :class:`Zone`
+        """
+        params = {'name' : domain}
+        try:
+            params['ip_address'] = extra['ip']
+        except:
+            params['ip_address'] = '127.0.0.1'
+
+        res = self.connection.request('/v2/domains', params=params,
+                                      method='POST')
+
+        return Zone(id=res.object['domain']['name'],
+                    domain=res.object['domain']['name'],
+                    type='master', ttl=1800, driver=self, extra={})
+
+    def create_record(self, name, zone, type, data, extra=None):
+        """
+        Create a new record.
+
+        :param name: Record name without the domain name (e.g. www).
+                     Note: If you want to create a record for a base domain
+                     name, you should specify empty string ('') for this
+                     argument.
+        :type  name: ``str``
+
+        :param zone: Zone where the requested record is created.
+        :type  zone: :class:`Zone`
+
+        :param type: DNS record type (A, AAAA, ...).
+        :type  type: :class:`RecordType`
+
+        :param data: Data for the record (depends on the record type).
+        :type  data: ``str``
+
+        :param extra: Extra attributes for MX and SRV. (Depends on record)
+                      {"priority" : 0, "port" : 443, "weight" : 100}
+        :type extra: ``dict``
+
+        :rtype: :class:`Record`
+        """
+        params = {
+            "type" : self.RECORD_TYPE_MAP[type],
+            "name" : name,
+            "data" : data
+        }
+        if extra:
+            try:
+                params['priority'] = extra['priority']
+            except KeyError:
+                params['priority'] = 'null'
+            try:
+                params['port'] = extra['port']
+            except KeyError:
+                params['port'] = 'null'
+            try:
+                params['weight'] = extra['weight']
+            except KeyError:
+                params['weight'] = 'null'
+
+        res = self.connection.request('/v2/domains/%s/records' % zone.id,
+                                      params=params,
+                                      method='POST')
+
+        return Record(id=res.object['domain_record']['id'],
+                    name=res.object['domain_record']['id'],
+                    type=type, data=data, zone=zone, driver=self, extra=extra)
+
+    def delete_zone(self, zone):
+        """
+        Delete a zone.
+
+        Note: This will delete all the records belonging to this zone.
+
+        :param zone: Zone to delete.
+        :type  zone: :class:`Zone`
+
+        :rtype: ``bool``
+        """
+        params = {}
+
+        res = self.connection.request('/v2/domains/%s' % zone.id,
+                                      params=params, method='DELETE')
+
+        return res.status == httplib.NO_CONTENT
+
+    def delete_record(self, record):
+        """
+        Delete a record.
+
+        :param record: Record to delete.
+        :type  record: :class:`Record`
+
+        :rtype: ``bool``
+        """
+        params = {}
+
+        res = self.connection.request('/v2/domains/%s/records/%s' % (
+                                      record.zone.id, record.id), params=params,
+                                      method='DELETE')
+        return res.status == httplib.NO_CONTENT
+
+# TODO: If there is a way to push this into libcloud.common.digitalocean
+#       instead of having it in libcloud.dns.digitalocean and
+#       libcloud.compute.digitalocean
+    def _paginated_request(self, url, obj):
+        """
+        Perform multiple calls in order to have a full list of elements when
+        the API responses are paginated.
+
+        :param url: API endpoint
+        :type url: ``str``
+
+        :param obj: Result object key
+        :type obj: ``str``
+
+        :return: ``list`` of API response objects
+        """
+        params = {}
+        data = self.connection.request(url)
+        try:
+            pages = data.object['links']['pages']['last'].split('=')[-1]
+            values = data.object[obj]
+            for page in range(2, int(pages) + 1):
+                params.update({'page': page})
+                new_data = self.connection.request(url, params=params)
+
+                more_values = new_data.object[obj]
+                for value in more_values:
+                    values.append(value)
+            data = values
+        except KeyError:  # No pages.
+            data = data.object[obj]
+
+        return data
+
+    def _to_record(self, data, zone=None):
+        extra = {'port' : data['port'], 'priority' : data['priority'],
+                 'weight' : data['weight']}
+        return Record(id=data['id'], name=data['name'],
+                      type=self._string_to_record_type(data['type']),
+                      data=data['data'], zone=zone, driver=self, extra=extra)
+
+    def _to_zone(self, data):
+        extra = {'zone_file' : data['zone_file'],}
+        return Zone(id=data['name'], domain=data['name'], type='master',
+                    ttl=data['ttl'], driver=self, extra=extra)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f50b8d42/libcloud/dns/providers.py
----------------------------------------------------------------------
diff --git a/libcloud/dns/providers.py b/libcloud/dns/providers.py
index dc80460..a6c92a8 100644
--- a/libcloud/dns/providers.py
+++ b/libcloud/dns/providers.py
@@ -35,6 +35,8 @@ DRIVERS = {
     Provider.GOOGLE: ('libcloud.dns.drivers.google', 'GoogleDNSDriver'),
     Provider.SOFTLAYER:
     ('libcloud.dns.drivers.softlayer', 'SoftLayerDNSDriver'),
+    Provider.DIGITAL_OCEAN:
+    ('libcloud.dns.drivers.digitalocean', 'DigitalOceanDNSDriver'),
     # Deprecated
     Provider.RACKSPACE_US:
     ('libcloud.dns.drivers.rackspace', 'RackspaceUSDNSDriver'),

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f50b8d42/libcloud/dns/types.py
----------------------------------------------------------------------
diff --git a/libcloud/dns/types.py b/libcloud/dns/types.py
index 32bceb5..cd1ae85 100644
--- a/libcloud/dns/types.py
+++ b/libcloud/dns/types.py
@@ -37,6 +37,7 @@ class Provider(object):
     GANDI = 'gandi'
     GOOGLE = 'google'
     SOFTLAYER = 'softlayer'
+    DIGITAL_OCEAN = 'digitalocean'
 
     # Deprecated
     RACKSPACE_US = 'rackspace_us'


[04/21] libcloud git commit: Address build failures from provider matrix generation - Removed hack to load DigitalOcean_v2_NodeDriver as DigitalOceanNodeDriver will handle v1/v2 properly - Restored DigitalOceanNodeDriver (v1) ex_ssh* methods with Warning

Posted by to...@apache.org.
Address build failures from provider matrix generation - Removed hack to load DigitalOcean_v2_NodeDriver as DigitalOceanNodeDriver will handle v1/v2 properly - Restored DigitalOceanNodeDriver (v1) ex_ssh* methods with Warning of deprecation

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/003e0f67
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/003e0f67
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/003e0f67

Branch: refs/heads/trunk
Commit: 003e0f6781a37cc524f9ff9504ce288c98895857
Parents: 950fa94
Author: Javier Castillo II <j....@gmail.com>
Authored: Wed Apr 15 22:05:21 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 .../generate_provider_feature_matrix_table.py   |  4 --
 libcloud/compute/drivers/digitalocean.py        | 39 ++++++++++++++++++++
 libcloud/test/compute/test_digitalocean_v1.py   | 13 +++++++
 3 files changed, 52 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/003e0f67/contrib/generate_provider_feature_matrix_table.py
----------------------------------------------------------------------
diff --git a/contrib/generate_provider_feature_matrix_table.py b/contrib/generate_provider_feature_matrix_table.py
index 834a514..2538568 100755
--- a/contrib/generate_provider_feature_matrix_table.py
+++ b/contrib/generate_provider_feature_matrix_table.py
@@ -221,10 +221,6 @@ def generate_providers_table(api):
             from libcloud.compute.drivers.cloudsigma import \
                 CloudSigma_2_0_NodeDriver
             cls = CloudSigma_2_0_NodeDriver
-        elif name.lower() == 'digital_ocean':
-            from libcloud.compute.drivers.digitalocean import \
-                DigitalOcean_v2_NodeDriver
-            cls = DigitalOcean_v2_NodeDriver
         elif name.lower() == 'opennebula':
             from libcloud.compute.drivers.opennebula import \
                 OpenNebula_3_8_NodeDriver

http://git-wip-us.apache.org/repos/asf/libcloud/blob/003e0f67/libcloud/compute/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/digitalocean.py b/libcloud/compute/drivers/digitalocean.py
index 0d9c0e7..9176be9 100644
--- a/libcloud/compute/drivers/digitalocean.py
+++ b/libcloud/compute/drivers/digitalocean.py
@@ -15,6 +15,7 @@
 """
 Digital Ocean Driver
 """
+import warnings
 
 from libcloud.utils.py3 import httplib
 
@@ -157,6 +158,17 @@ class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver,
         data = self.connection.request('/v1/ssh_keys').object['ssh_keys']
         return list(map(self._to_key_pair, data))
 
+    def ex_list_ssh_keys(self):
+        """
+        List all the available SSH keys.
+        :return: Available SSH keys.
+        :rtype: ``list`` of :class:`SSHKey`
+        """
+        warnings.warn("This method has been deprecated in favor of the list_key_pairs method")
+
+        data = self.connection.request('/v1/ssh_keys').object['ssh_keys']
+        return list(map(self._to_ssh_key, data))
+
     def get_key_pair(self, name):
         """
         Retrieve a single key pair.
@@ -191,6 +203,22 @@ class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver,
         #      a return value. This looks like it should return a KeyPair
         return self._to_key_pair(data=data['ssh_key'])
 
+    def ex_create_ssh_key(self, name, ssh_key_pub):
+        """
+        Create a new SSH key.
+        :param      name: Key name (required)
+        :type       name: ``str``
+        :param      name: Valid public key string (required)
+        :type       name: ``str``
+        """
+        warnings.warn("This method has been deprecated in favor of the create_key_pair method")
+
+        params = {'name': name, 'ssh_pub_key': ssh_key_pub}
+        data = self.connection.request('/v1/ssh_keys/new/', method='GET',
+                                       params=params).object
+        assert 'ssh_key' in data
+        return self._to_ssh_key(data=data['ssh_key'])
+
     def delete_key_pair(self, key_pair):
         """
         Delete an existing key pair.
@@ -203,6 +231,17 @@ class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver,
         # TODO: This looks like it should return bool like the other delete_*
         return res.status == httplib.OK
 
+    def ex_destroy_ssh_key(self, key_id):
+        """
+        Delete an existing SSH key.
+        :param      key_id: SSH key id (required)
+        :type       key_id: ``str``
+        """
+        warnings.warn("This method has been deprecated in favor of the delete_key_pair method")
+
+        res = self.connection.request('/v1/ssh_keys/%s/destroy/' % (key_id))
+        return res.status == httplib.OK
+
     def _to_node(self, data):
         extra_keys = ['backups_active', 'region_id', 'image_id', 'size_id']
         if 'status' in data:

http://git-wip-us.apache.org/repos/asf/libcloud/blob/003e0f67/libcloud/test/compute/test_digitalocean_v1.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v1.py b/libcloud/test/compute/test_digitalocean_v1.py
index 654935e..33c7f1c 100644
--- a/libcloud/test/compute/test_digitalocean_v1.py
+++ b/libcloud/test/compute/test_digitalocean_v1.py
@@ -119,11 +119,24 @@ class DigitalOcean_v1_Tests(LibcloudTestCase):
         self.assertEqual(keys[0].name, 'test1')
         self.assertEqual(keys[0].public_key, None)
 
+    def test_ex_list_ssh_keys(self):
+        keys = self.driver.ex_list_ssh_keys()
+        self.assertEqual(len(keys), 1)
+
+        self.assertEqual(keys[0].id, 7717)
+        self.assertEqual(keys[0].name, 'test1')
+        self.assertEqual(keys[0].pub_key, None)
+
     def test_delete_key_pair(self):
         key = self.driver.list_key_pairs()[0]
         result = self.driver.delete_key_pair(key)
         self.assertTrue(result)
 
+    def test_ex_destroy_ssh_key(self):
+        key = self.driver.ex_list_ssh_keys()[0]
+        result = self.driver.ex_destroy_ssh_key(key.id)
+        self.assertTrue(result)
+
 
 class DigitalOceanMockHttp(MockHttpTestCase):
     fixtures = ComputeFileFixtures('digitalocean_v1')


[14/21] libcloud git commit: DigitalOceanNodeDriver minor revisions - Raise on api_version / key or key-secret mismatch - Added tests for v1 and v2 DigitalOceanNodeDriver using wrong keys - Updated examples to include explicit api_version values - Cleane

Posted by to...@apache.org.
DigitalOceanNodeDriver minor revisions - Raise on api_version / key or key-secret mismatch - Added tests for v1 and v2 DigitalOceanNodeDriver using wrong keys - Updated examples to include explicit api_version values - Cleaned up some whitespace lint

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/34bff99b
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/34bff99b
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/34bff99b

Branch: refs/heads/trunk
Commit: 34bff99b2280ccef4fd7fbfcdff7e234677c8161
Parents: af15645
Author: jcastillo2nd <j....@gmail.com>
Authored: Thu May 28 13:57:55 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------

----------------------------------------------------------------------



[18/21] libcloud git commit: DigitalOceanNodeDriver patch - v2 driver referenced object instead of response

Posted by to...@apache.org.
DigitalOceanNodeDriver patch - v2 driver referenced object instead of response

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/9baacf60
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/9baacf60
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/9baacf60

Branch: refs/heads/trunk
Commit: 9baacf602e4066a3c44b22da95f7729436486e17
Parents: fa66763
Author: jcastillo2nd <j....@gmail.com>
Authored: Thu May 28 15:42:58 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/compute/drivers/digitalocean.py | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/9baacf60/libcloud/compute/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/digitalocean.py b/libcloud/compute/drivers/digitalocean.py
index aa6dba4..69b683d 100644
--- a/libcloud/compute/drivers/digitalocean.py
+++ b/libcloud/compute/drivers/digitalocean.py
@@ -352,14 +352,15 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
         if ex_ssh_key_ids:
             params['ssh_key_ids'] = ','.join(ex_ssh_key_ids)
 
-        data = self.connection.request('/v2/droplets',
-                                       params=params, method='POST').object
+        res = self.connection.request('/v2/droplets',
+                                       params=params, method='POST')
 
+        data = res.object
         # TODO: Handle this in the response class
-        status = data.object.get('status', 'OK')
+        status = res.object.get('status', 'OK')
         if status == 'ERROR':
-            message = data.object.get('message', None)
-            error_message = data.object.get('error_message', message)
+            message = res.object.get('message', None)
+            error_message = res.object.get('error_message', message)
             raise ValueError('Failed to create node: %s' % (error_message))
 
         return self._to_node(data=data['droplet'])


[11/21] libcloud git commit: Added documentation for DigitalOceanDNSDriver and other doc updates - Includes driver instantiation example - Updated Node driver documentation to reflect duality of v1/v2 api in DigitalOceanNodeDriver

Posted by to...@apache.org.
Added documentation for DigitalOceanDNSDriver and other doc updates - Includes driver instantiation example - Updated Node driver documentation to reflect duality of v1/v2 api in DigitalOceanNodeDriver

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/f451f210
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/f451f210
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/f451f210

Branch: refs/heads/trunk
Commit: f451f210df5c3b32a2caff34a71f7d104c01eb8d
Parents: c7f00b4
Author: Javier Castillo II <j....@gmail.com>
Authored: Wed Apr 15 23:01:04 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 docs/compute/drivers/digital_ocean.rst          |  5 +--
 docs/dns/drivers/digital_ocean.rst              | 32 ++++++++++++++++++++
 .../digitalocean/instantiate_api_v1.0.py        |  2 +-
 .../digitalocean/instantiate_api_v2.0.py        |  3 --
 .../dns/digitalocean/instantiate_driver.py      |  5 +++
 5 files changed, 41 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/f451f210/docs/compute/drivers/digital_ocean.rst
----------------------------------------------------------------------
diff --git a/docs/compute/drivers/digital_ocean.rst b/docs/compute/drivers/digital_ocean.rst
index 6b71ed3..67e7ebc 100644
--- a/docs/compute/drivers/digital_ocean.rst
+++ b/docs/compute/drivers/digital_ocean.rst
@@ -14,8 +14,9 @@ Instantiating a driver
 ----------------------
 
 DigitalOcean driver supports two API versions - old API v1.0 and the new API
-v2.0 which is currently in beta. Since trunk (to be libcloud v0.18.0), the
-driver uses new API v2.0 by default.
+v2.0. Since trunk (to be libcloud v0.18.0), the driver uses the correct API
+based on the initialization with the Client ID (key) and Access Token (secret)
+for v1.0 or the Personal Access Token (key) in v2.0.
 
 Instantiating a driver using API v2.0
 -------------------------------------

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f451f210/docs/dns/drivers/digital_ocean.rst
----------------------------------------------------------------------
diff --git a/docs/dns/drivers/digital_ocean.rst b/docs/dns/drivers/digital_ocean.rst
new file mode 100644
index 0000000..b7ec3a6
--- /dev/null
+++ b/docs/dns/drivers/digital_ocean.rst
@@ -0,0 +1,32 @@
+DigitalOcean Compute Driver Documentation
+=========================================
+
+`DigitalOcean`_ is an American virtual private server provider based in New York
+City with data centers in New York, Amsterdam, San Francisco, London and
+Singapore.
+
+.. figure:: /_static/images/provider_logos/digitalocean.png
+    :align: center
+    :width: 300
+    :target: https://www.digitalocean.com/
+
+Instantiating a driver
+----------------------
+
+DigitalOcean dns driver supports only the v2.0 API requiring a Personal Access
+Token to initialize as the key.
+
+Instantiating the driver
+-------------------------------------
+
+.. literalinclude:: /examples/dns/digitalocean/instantiate_driver.py
+   :language: python
+
+API Docs
+--------
+
+.. autoclass:: libcloud.dns.drivers.digitalocean.DigitalOceanDNSDriver
+    :members:
+    :inherited-members:
+
+.. _`DigitalOcean`: https://www.digitalocean.com/

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f451f210/docs/examples/compute/digitalocean/instantiate_api_v1.0.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/digitalocean/instantiate_api_v1.0.py b/docs/examples/compute/digitalocean/instantiate_api_v1.0.py
index ea498d1..c1b822d 100644
--- a/docs/examples/compute/digitalocean/instantiate_api_v1.0.py
+++ b/docs/examples/compute/digitalocean/instantiate_api_v1.0.py
@@ -2,4 +2,4 @@ from libcloud.compute.types import Provider
 from libcloud.compute.providers import get_driver
 
 cls = get_driver(Provider.DIGITAL_OCEAN)
-driver = cls('client id', 'api key', api_version='v1')
+driver = cls('client id', 'api key')

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f451f210/docs/examples/compute/digitalocean/instantiate_api_v2.0.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/digitalocean/instantiate_api_v2.0.py b/docs/examples/compute/digitalocean/instantiate_api_v2.0.py
index c2c950a..1a29362 100644
--- a/docs/examples/compute/digitalocean/instantiate_api_v2.0.py
+++ b/docs/examples/compute/digitalocean/instantiate_api_v2.0.py
@@ -3,7 +3,4 @@ from libcloud.compute.providers import get_driver
 
 cls = get_driver(Provider.DIGITAL_OCEAN)
 
-driver = cls('access token', api_version='v2')
-# Note: Driver defaults to v2.0 so api_version argument can be omitted and the
-# following is the same
 driver = cls('access token')

http://git-wip-us.apache.org/repos/asf/libcloud/blob/f451f210/docs/examples/dns/digitalocean/instantiate_driver.py
----------------------------------------------------------------------
diff --git a/docs/examples/dns/digitalocean/instantiate_driver.py b/docs/examples/dns/digitalocean/instantiate_driver.py
new file mode 100644
index 0000000..e1b1191
--- /dev/null
+++ b/docs/examples/dns/digitalocean/instantiate_driver.py
@@ -0,0 +1,5 @@
+from libcloud.dns.types import Provider
+from libcloud.dns.providers import get_driver
+
+cls = get_driver(Provider.DIGITAL_OCEAN)
+driver = cls(key='access token')


[20/21] libcloud git commit: Add back a hack so table so compute table is generated correctly.

Posted by to...@apache.org.
Add back a hack so table so compute table is generated correctly.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/89522343
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/89522343
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/89522343

Branch: refs/heads/trunk
Commit: 89522343155b3b758657588c282b2cb80ccbf19e
Parents: fa6c99d
Author: Tomaz Muraus <to...@tomaz.me>
Authored: Sun Jun 14 18:17:47 2015 +0800
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:17:47 2015 +0800

----------------------------------------------------------------------
 contrib/generate_provider_feature_matrix_table.py | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/89522343/contrib/generate_provider_feature_matrix_table.py
----------------------------------------------------------------------
diff --git a/contrib/generate_provider_feature_matrix_table.py b/contrib/generate_provider_feature_matrix_table.py
index 2538568..bac9823 100755
--- a/contrib/generate_provider_feature_matrix_table.py
+++ b/contrib/generate_provider_feature_matrix_table.py
@@ -225,6 +225,10 @@ def generate_providers_table(api):
             from libcloud.compute.drivers.opennebula import \
                 OpenNebula_3_8_NodeDriver
             cls = OpenNebula_3_8_NodeDriver
+        elif name.lower() == 'digital_ocean' and api.startswith('compute'):
+            from libcloud.compute.drivers.digitalocean import \
+                DigitalOcean_v2_NodeDriver
+            cls = DigitalOcean_v2_NodeDriver
 
         if name.lower() in IGNORED_PROVIDERS:
             continue


[06/21] libcloud git commit: Broke apart string in warnings.warn to pass flake8 in build test

Posted by to...@apache.org.
Broke apart string in warnings.warn to pass flake8 in build test

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/c7f00b43
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/c7f00b43
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/c7f00b43

Branch: refs/heads/trunk
Commit: c7f00b437dabc239893db4b6c2d137c20096a74c
Parents: 003e0f6
Author: Javier Castillo II <j....@gmail.com>
Authored: Wed Apr 15 22:25:07 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/compute/drivers/digitalocean.py | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/c7f00b43/libcloud/compute/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/digitalocean.py b/libcloud/compute/drivers/digitalocean.py
index 9176be9..46355fb 100644
--- a/libcloud/compute/drivers/digitalocean.py
+++ b/libcloud/compute/drivers/digitalocean.py
@@ -164,7 +164,8 @@ class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver,
         :return: Available SSH keys.
         :rtype: ``list`` of :class:`SSHKey`
         """
-        warnings.warn("This method has been deprecated in favor of the list_key_pairs method")
+        warnings.warn("This method has been deprecated in "
+                      "favor of the list_key_pairs method")
 
         data = self.connection.request('/v1/ssh_keys').object['ssh_keys']
         return list(map(self._to_ssh_key, data))
@@ -211,7 +212,8 @@ class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver,
         :param      name: Valid public key string (required)
         :type       name: ``str``
         """
-        warnings.warn("This method has been deprecated in favor of the create_key_pair method")
+        warnings.warn("This method has been deprecated in "
+                      "favor of the create_key_pair method")
 
         params = {'name': name, 'ssh_pub_key': ssh_key_pub}
         data = self.connection.request('/v1/ssh_keys/new/', method='GET',
@@ -237,7 +239,9 @@ class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver,
         :param      key_id: SSH key id (required)
         :type       key_id: ``str``
         """
-        warnings.warn("This method has been deprecated in favor of the delete_key_pair method")
+        warnings.warn(
+            "This method has been deprecated in "
+            "favor of the delete_key_pair method")
 
         res = self.connection.request('/v1/ssh_keys/%s/destroy/' % (key_id))
         return res.status == httplib.OK


[08/21] libcloud git commit: Cleaned up some unused imports in tests, as well as removed redundant tests from dns/test_digitalocean performed in DigitalOceanBaseDriver

Posted by to...@apache.org.
Cleaned up some unused imports in tests, as well as removed redundant tests from dns/test_digitalocean performed in DigitalOceanBaseDriver

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d1a8e222
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d1a8e222
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d1a8e222

Branch: refs/heads/trunk
Commit: d1a8e2223d59c5b4c367234d06c62f28a612fb0b
Parents: a3a5f17
Author: Javier Castillo II <j....@gmail.com>
Authored: Sun Apr 12 02:06:32 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/test/common/test_digitalocean_v1.py | 2 --
 libcloud/test/common/test_digitalocean_v2.py | 2 --
 libcloud/test/dns/test_digitalocean.py       | 5 -----
 3 files changed, 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/d1a8e222/libcloud/test/common/test_digitalocean_v1.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_digitalocean_v1.py b/libcloud/test/common/test_digitalocean_v1.py
index e10f54d..424a594 100644
--- a/libcloud/test/common/test_digitalocean_v1.py
+++ b/libcloud/test/common/test_digitalocean_v1.py
@@ -12,13 +12,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 
-import os
 import sys
 import unittest
 
 from libcloud.common.types import InvalidCredsError
 from libcloud.common.digitalocean import DigitalOceanBaseDriver
-from libcloud.dns.types import RecordType
 from libcloud.test import LibcloudTestCase, MockHttpTestCase
 from libcloud.test.file_fixtures import FileFixtures
 from libcloud.test.secrets import DIGITALOCEAN_v1_PARAMS

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d1a8e222/libcloud/test/common/test_digitalocean_v2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_digitalocean_v2.py b/libcloud/test/common/test_digitalocean_v2.py
index c530b5b..b746c35 100644
--- a/libcloud/test/common/test_digitalocean_v2.py
+++ b/libcloud/test/common/test_digitalocean_v2.py
@@ -12,13 +12,11 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 
-import os
 import sys
 import unittest
 
 from libcloud.common.types import InvalidCredsError
 from libcloud.common.digitalocean import DigitalOceanBaseDriver
-from libcloud.dns.types import RecordType
 from libcloud.test import LibcloudTestCase, MockHttpTestCase
 from libcloud.test.file_fixtures import FileFixtures
 from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d1a8e222/libcloud/test/dns/test_digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_digitalocean.py b/libcloud/test/dns/test_digitalocean.py
index 7557db0..e618631 100644
--- a/libcloud/test/dns/test_digitalocean.py
+++ b/libcloud/test/dns/test_digitalocean.py
@@ -15,7 +15,6 @@
 import sys
 import unittest
 
-from libcloud.common.types import InvalidCredsError
 from libcloud.dns.drivers.digitalocean import DigitalOceanDNSDriver
 from libcloud.dns.types import RecordType
 from libcloud.test import LibcloudTestCase, MockHttpTestCase
@@ -32,10 +31,6 @@ class DigitalOceanDNSTests(LibcloudTestCase):
         DigitalOceanDNSMockHttp.type = None
         self.driver = DigitalOceanDNSDriver(*DIGITALOCEAN_v2_PARAMS)
 
-    def test_authentication(self):
-        DigitalOceanDNSMockHttp.type = 'UNAUTHORIZED'
-        self.assertRaises(InvalidCredsError, self.driver.list_zones)
-
     def test_list_zones(self):
         zones = self.driver.list_zones()
         self.assertTrue(len(zones) >= 1)


[03/21] libcloud git commit: DigitalOceanNodeDriver patch - v2 driver referenced object instead of response

Posted by to...@apache.org.
DigitalOceanNodeDriver patch - v2 driver referenced object instead of response

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/c6c87440
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/c6c87440
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/c6c87440

Branch: refs/heads/trunk
Commit: c6c8744007ebd512971bb5e9d5916e43e59feb8f
Parents: 9baacf6
Author: jcastillo2nd <j....@gmail.com>
Authored: Thu May 28 15:49:21 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/compute/drivers/digitalocean.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/c6c87440/libcloud/compute/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/digitalocean.py b/libcloud/compute/drivers/digitalocean.py
index 69b683d..0722748 100644
--- a/libcloud/compute/drivers/digitalocean.py
+++ b/libcloud/compute/drivers/digitalocean.py
@@ -353,7 +353,7 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
             params['ssh_key_ids'] = ','.join(ex_ssh_key_ids)
 
         res = self.connection.request('/v2/droplets',
-                                       params=params, method='POST')
+                                      params=params, method='POST')
 
         data = res.object
         # TODO: Handle this in the response class


[12/21] libcloud git commit: Updated DigitalOceanNodeDriver - Consistency in v2 for attributes -> json request data

Posted by to...@apache.org.
Updated DigitalOceanNodeDriver - Consistency in v2 for attributes -> json request data

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/8e16f417
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/8e16f417
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/8e16f417

Branch: refs/heads/trunk
Commit: 8e16f417d1557fb361b071a1a8c9ada90d8516ee
Parents: 33cbf99
Author: jcastillo2nd <j....@gmail.com>
Authored: Thu May 28 19:27:29 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/compute/drivers/digitalocean.py | 36 +++++++++++++--------------
 1 file changed, 18 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/8e16f417/libcloud/compute/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/digitalocean.py b/libcloud/compute/drivers/digitalocean.py
index 4f86ce6..05bb61c 100644
--- a/libcloud/compute/drivers/digitalocean.py
+++ b/libcloud/compute/drivers/digitalocean.py
@@ -347,16 +347,16 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
         :return: The newly created node.
         :rtype: :class:`Node`
         """
-        params = {'name': name, 'size': size.name, 'image': image.id,
-                  'region': location.id}
+        attr = {'name': name, 'size': size.name, 'image': image.id,
+                'region': location.id}
 
         if ex_ssh_key_ids:
-            params['ssh_keys'] = ex_ssh_key_ids
+            attr['ssh_keys'] = ex_ssh_key_ids
 
         res = self.connection.request('/v2/droplets',
-                                      data=json.dumps(params), method='POST')
+                                      data=json.dumps(attr), method='POST')
 
-        data = res.object
+        data = res.object['droplet']
         # TODO: Handle this in the response class
         status = res.object.get('status', 'OK')
         if status == 'ERROR':
@@ -364,12 +364,12 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
             error_message = res.object.get('error_message', message)
             raise ValueError('Failed to create node: %s' % (error_message))
 
-        return self._to_node(data=data['droplet'])
+        return self._to_node(data=data)
 
     def reboot_node(self, node):
-        params = {'type': 'reboot'}
+        attr = {'type': 'reboot'}
         res = self.connection.request('/v2/droplets/%s/actions' % (node.id),
-                                      data=json.dumps(params), method='POST')
+                                      data=json.dumps(attr), method='POST')
         return res.status == httplib.CREATED
 
     def destroy_node(self, node):
@@ -407,9 +407,9 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
 
         :rtype: ``bool``
         """
-        params = {'type': 'snapshot', 'name': name}
+        attr = {'type': 'snapshot', 'name': name}
         res = self.connection.request('/v2/droplets/%s/actions' % (node.id),
-                                      data=json.dumps(params), method='POST')
+                                      data=json.dumps(attr), method='POST')
         return res.status == httplib.CREATED
 
     def delete_image(self, image):
@@ -427,21 +427,21 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
         return res.status == httplib.NO_CONTENT
 
     def ex_rename_node(self, node, name):
-        params = {'type': 'rename', 'name': name}
+        attr = {'type': 'rename', 'name': name}
         res = self.connection.request('/v2/droplets/%s/actions' % (node.id),
-                                      data=json.dumps(params), method='POST')
+                                      data=json.dumps(attr), method='POST')
         return res.status == httplib.CREATED
 
     def ex_shutdown_node(self, node):
-        params = {'type': 'shutdown'}
+        attr = {'type': 'shutdown'}
         res = self.connection.request('/v2/droplets/%s/actions' % (node.id),
-                                      data=json.dumps(params), method='POST')
+                                      data=json.dumps(attr), method='POST')
         return res.status == httplib.CREATED
 
     def ex_power_on_node(self, node):
-        params = {'type': 'power_on'}
+        attr = {'type': 'power_on'}
         res = self.connection.request('/v2/droplets/%s/actions' % (node.id),
-                                      data=json.dumps(params), method='POST')
+                                      data=json.dumps(attr), method='POST')
         return res.status == httplib.CREATED
 
     def list_key_pairs(self):
@@ -478,9 +478,9 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
         :param      public_key: Valid public key string (required)
         :type       public_key: ``str``
         """
-        params = {'name': name, 'public_key': public_key}
+        attr = {'name': name, 'public_key': public_key}
         res = self.connection.request('/v2/account/keys', method='POST',
-                                      data=json.dumps(params))
+                                      data=json.dumps(attr))
 
         data = res.object['ssh_key']
 


[17/21] libcloud git commit: Cosmetic clean up

Posted by to...@apache.org.
Cosmetic clean up

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/950fa949
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/950fa949
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/950fa949

Branch: refs/heads/trunk
Commit: 950fa949641b4ad2dba599edfbd8955e31b3956f
Parents: 9224e8e
Author: Javier Castillo II <j....@gmail.com>
Authored: Sun Apr 12 20:31:02 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/common/digitalocean.py               |  5 +-
 libcloud/compute/drivers/digitalocean.py      | 21 ++++----
 libcloud/dns/drivers/digitalocean.py          | 54 +++++++++++----------
 libcloud/test/common/test_digitalocean_v1.py  | 14 +++---
 libcloud/test/common/test_digitalocean_v2.py  | 17 +++----
 libcloud/test/compute/test_digitalocean_v1.py |  6 ++-
 libcloud/test/compute/test_digitalocean_v2.py |  9 ++--
 libcloud/test/dns/test_digitalocean.py        | 56 +++++++++++-----------
 8 files changed, 98 insertions(+), 84 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/950fa949/libcloud/common/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/common/digitalocean.py b/libcloud/common/digitalocean.py
index 7d46881..53dcb60 100644
--- a/libcloud/common/digitalocean.py
+++ b/libcloud/common/digitalocean.py
@@ -109,6 +109,7 @@ class DigitalOcean_v2_Connection(ConnectionKey):
         headers['Content-Type'] = 'application/json'
         return headers
 
+
 class DigitalOceanConnection(DigitalOcean_v2_Connection):
     """
     Connection class for the DigitalOcean driver.
@@ -129,7 +130,7 @@ class DigitalOceanBaseDriver(BaseDriver):
 
     def __new__(cls, key, secret=None, api_version='v2', **kwargs):
         if cls is DigitalOceanBaseDriver:
-            if api_version == 'v1' or secret != None:
+            if api_version == 'v1' or secret is not None:
                 cls = DigitalOcean_v1_BaseDriver
             elif api_version == 'v2':
                 cls = DigitalOcean_v2_BaseDriver
@@ -150,7 +151,7 @@ class DigitalOceanBaseDriver(BaseDriver):
         raise NotImplementedError(
             'ex_get_event not implemented for this driver')
 
-    def _paginated_request(self, event_id):
+    def _paginated_request(self, url, obj):
         raise NotImplementedError(
             '_paginated_requests not implemented for this driver')
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/950fa949/libcloud/compute/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/digitalocean.py b/libcloud/compute/drivers/digitalocean.py
index 1cb209b..0d9c0e7 100644
--- a/libcloud/compute/drivers/digitalocean.py
+++ b/libcloud/compute/drivers/digitalocean.py
@@ -18,11 +18,9 @@ Digital Ocean Driver
 
 from libcloud.utils.py3 import httplib
 
-from libcloud.common.base import ConnectionUserAndKey, ConnectionKey
-from libcloud.common.base import JsonResponse
 from libcloud.common.digitalocean import DigitalOcean_v1_BaseDriver
 from libcloud.common.digitalocean import DigitalOcean_v2_BaseDriver
-from libcloud.compute.types import Provider, NodeState, InvalidCredsError
+from libcloud.compute.types import Provider, NodeState
 from libcloud.compute.base import NodeDriver, Node
 from libcloud.compute.base import NodeImage, NodeSize, NodeLocation, KeyPair
 
@@ -57,7 +55,7 @@ class DigitalOceanNodeDriver(NodeDriver):
 
     def __new__(cls, key, secret=None, api_version='v2', **kwargs):
         if cls is DigitalOceanNodeDriver:
-            if api_version == 'v1' or secret != None:
+            if api_version == 'v1' or secret is not None:
                 cls = DigitalOcean_v1_NodeDriver
             elif api_version == 'v2':
                 cls = DigitalOcean_v2_NodeDriver
@@ -66,6 +64,7 @@ class DigitalOceanNodeDriver(NodeDriver):
                                           (api_version))
         return super(DigitalOceanNodeDriver, cls).__new__(cls, **kwargs)
 
+
 # TODO Implement v1 driver using KeyPair
 class SSHKey(object):
     def __init__(self, id, name, pub_key):
@@ -78,7 +77,8 @@ class SSHKey(object):
                 (self.id, self.name, self.pub_key))
 
 
-class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver, DigitalOceanNodeDriver):
+class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver,
+                                 DigitalOceanNodeDriver):
     """
     DigitalOcean NodeDriver using v1 of the API.
     """
@@ -171,7 +171,7 @@ class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver, DigitalOceanNodeDri
                                        qkey.extra['id']).object['ssh_key']
         return self._to_key_pair(data=data)
 
-    #TODO: This adds the ssh_key_pub parameter. This puts the burden of making
+    # TODO: This adds the ssh_key_pub parameter. This puts the burden of making
     #      it within the function or on the API. The KeyPair API needs work.
     def create_key_pair(self, name, ssh_key_pub):
         """
@@ -187,7 +187,7 @@ class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver, DigitalOceanNodeDri
         data = self.connection.request('/v1/ssh_keys/new/', method='GET',
                                        params=params).object
         assert 'ssh_key' in data
-        #TODO: libcloud.compute.base.KeyPair.create_key_pair doesn't specify
+        # TODO: libcloud.compute.base.KeyPair.create_key_pair doesn't specify
         #      a return value. This looks like it should return a KeyPair
         return self._to_key_pair(data=data['ssh_key'])
 
@@ -200,7 +200,7 @@ class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver, DigitalOceanNodeDri
         """
         res = self.connection.request('/v1/ssh_keys/%s/destroy/' %
                                       key_pair.extra['id'])
-        #TODO: This looks like it should return bool like the other delete_*
+        # TODO: This looks like it should return bool like the other delete_*
         return res.status == httplib.OK
 
     def _to_node(self, data):
@@ -251,14 +251,15 @@ class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver, DigitalOceanNodeDri
         except KeyError:
             pubkey = None
         return KeyPair(data['name'], public_key=pubkey, fingerprint=None,
-                       driver=self, private_key=None, extra={'id':data['id']})
+                       driver=self, private_key=None, extra={'id': data['id']})
 
     def _to_ssh_key(self, data):
         return SSHKey(id=data['id'], name=data['name'],
                       pub_key=data.get('ssh_pub_key', None))
 
 
-class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver, DigitalOceanNodeDriver):
+class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
+                                 DigitalOceanNodeDriver):
     """
     DigitalOcean NodeDriver using v2 of the API.
     """

http://git-wip-us.apache.org/repos/asf/libcloud/blob/950fa949/libcloud/dns/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/dns/drivers/digitalocean.py b/libcloud/dns/drivers/digitalocean.py
index 81e313f..3470fa0 100644
--- a/libcloud/dns/drivers/digitalocean.py
+++ b/libcloud/dns/drivers/digitalocean.py
@@ -23,26 +23,25 @@ __all__ = [
 from libcloud.utils.py3 import httplib
 
 from libcloud.common.digitalocean import DigitalOcean_v2_BaseDriver
-from libcloud.common.digitalocean import DigitalOceanConnection
-from libcloud.common.digitalocean import DigitalOceanResponse
+from libcloud.common.digitalocean import DigitalOcean_v2_Connection
 from libcloud.dns.types import Provider, RecordType
-from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError
 from libcloud.dns.base import DNSDriver, Zone, Record
 
 
 class DigitalOceanDNSDriver(DigitalOcean_v2_BaseDriver, DNSDriver):
+    connectionCls = DigitalOcean_v2_Connection
     type = Provider.DIGITAL_OCEAN
     name = "DigitalOcean"
     website = 'https://www.digitalocean.com'
 
     RECORD_TYPE_MAP = {
-        RecordType.NS : 'NS',
-        RecordType.A : 'A',
-        RecordType.AAAA : 'AAAA',
-        RecordType.CNAME : 'CNAME',
-        RecordType.MX : 'MX',
-        RecordType.TXT : 'TXT',
-        RecordType.SRV : 'SRV',
+        RecordType.NS: 'NS',
+        RecordType.A: 'A',
+        RecordType.AAAA: 'AAAA',
+        RecordType.CNAME: 'CNAME',
+        RecordType.MX: 'MX',
+        RecordType.TXT: 'TXT',
+        RecordType.SRV: 'SRV',
     }
 
     def list_zones(self):
@@ -79,7 +78,7 @@ class DigitalOceanDNSDriver(DigitalOcean_v2_BaseDriver, DNSDriver):
         :rtype: :class:`Zone`
         """
         data = self.connection.request('/v2/domains/%s' %
-               (zone_id)).object['domain']
+                                       (zone_id)).object['domain']
 
         return self._to_zone(data)
 
@@ -122,7 +121,7 @@ class DigitalOceanDNSDriver(DigitalOcean_v2_BaseDriver, DNSDriver):
 
         :rtype: :class:`Zone`
         """
-        params = {'name' : domain}
+        params = {'name': domain}
         try:
             params['ip_address'] = extra['ip']
         except:
@@ -161,9 +160,9 @@ class DigitalOceanDNSDriver(DigitalOcean_v2_BaseDriver, DNSDriver):
         :rtype: :class:`Record`
         """
         params = {
-            "type" : self.RECORD_TYPE_MAP[type],
-            "name" : name,
-            "data" : data
+            "type": self.RECORD_TYPE_MAP[type],
+            "name": name,
+            "data": data
         }
         if extra:
             try:
@@ -184,10 +183,12 @@ class DigitalOceanDNSDriver(DigitalOcean_v2_BaseDriver, DNSDriver):
                                       method='POST')
 
         return Record(id=res.object['domain_record']['id'],
-                    name=res.object['domain_record']['name'],
-                    type=type, data=data, zone=zone, driver=self, extra=extra)
+                      name=res.object['domain_record']['name'],
+                      type=type, data=data, zone=zone,
+                      driver=self, extra=extra)
 
-    def update_record(self, record, name=None, type=None, data=None, extra=None):
+    def update_record(self, record, name=None, type=None,
+                      data=None, extra=None):
         """
         Update an existing record.
 
@@ -212,11 +213,11 @@ class DigitalOceanDNSDriver(DigitalOcean_v2_BaseDriver, DNSDriver):
         :rtype: :class:`Record`
         """
         params = {
-            "type" : record.type,
-            "name" : record.name,
-            "data" : data
+            "type": record.type,
+            "name": record.name,
+            "data": data
         }
-        if data == None:
+        if data is None:
             params['data'] = record.data
         if extra:
             try:
@@ -272,18 +273,19 @@ class DigitalOceanDNSDriver(DigitalOcean_v2_BaseDriver, DNSDriver):
         params = {}
 
         res = self.connection.request('/v2/domains/%s/records/%s' % (
-                                      record.zone.id, record.id), params=params,
+                                      record.zone.id, record.id),
+                                      params=params,
                                       method='DELETE')
         return res.status == httplib.NO_CONTENT
 
     def _to_record(self, data, zone=None):
-        extra = {'port' : data['port'], 'priority' : data['priority'],
-                 'weight' : data['weight']}
+        extra = {'port': data['port'], 'priority': data['priority'],
+                 'weight': data['weight']}
         return Record(id=data['id'], name=data['name'],
                       type=self._string_to_record_type(data['type']),
                       data=data['data'], zone=zone, driver=self, extra=extra)
 
     def _to_zone(self, data):
-        extra = {'zone_file' : data['zone_file'],}
+        extra = {'zone_file': data['zone_file']}
         return Zone(id=data['name'], domain=data['name'], type='master',
                     ttl=data['ttl'], driver=self, extra=extra)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/950fa949/libcloud/test/common/test_digitalocean_v1.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_digitalocean_v1.py b/libcloud/test/common/test_digitalocean_v1.py
index 424a594..9e99c7f 100644
--- a/libcloud/test/common/test_digitalocean_v1.py
+++ b/libcloud/test/common/test_digitalocean_v1.py
@@ -33,7 +33,8 @@ class DigitalOceanTests(LibcloudTestCase):
 
     def test_authentication(self):
         DigitalOceanMockHttp.type = 'UNAUTHORIZED'
-        self.assertRaises(InvalidCredsError, self.driver.ex_get_event, '12345670')
+        self.assertRaises(InvalidCredsError, self.driver.ex_get_event,
+                          '12345670')
 
     def test_ex_account_info(self):
         self.assertRaises(NotImplementedError, self.driver.ex_account_info)
@@ -48,7 +49,8 @@ class DigitalOceanTests(LibcloudTestCase):
         self.assertEqual(action["event"]["event_type_id"], 1)
 
     def test__paginated_request(self):
-        self.assertRaises(NotImplementedError, self.driver._paginated_request, '/v1/anything')
+        self.assertRaises(NotImplementedError, self.driver._paginated_request,
+                          '/v1/anything', 'anything')
 
 
 class DigitalOceanMockHttp(MockHttpTestCase):
@@ -58,7 +60,7 @@ class DigitalOceanMockHttp(MockHttpTestCase):
         None: httplib.OK,
         'CREATE': httplib.CREATED,
         'DELETE': httplib.NO_CONTENT,
-	'EMPTY': httplib.OK,
+        'EMPTY': httplib.OK,
         'NOT_FOUND': httplib.NOT_FOUND,
         'UNAUTHORIZED': httplib.UNAUTHORIZED,
         'UPDATE': httplib.OK
@@ -66,14 +68,14 @@ class DigitalOceanMockHttp(MockHttpTestCase):
 
     def _v1_events_12345670_UNAUTHORIZED(self, method, url, body, headers):
         body = self.fixtures.load(
-                   '_v1_events_12345670_UNAUTHORIZED.json')
+            '_v1_events_12345670_UNAUTHORIZED.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v1_events_12345670(self, method, url, body, headers):
         body = self.fixtures.load('_v1_events_12345670.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
 
 if __name__ == '__main__':

http://git-wip-us.apache.org/repos/asf/libcloud/blob/950fa949/libcloud/test/common/test_digitalocean_v2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_digitalocean_v2.py b/libcloud/test/common/test_digitalocean_v2.py
index b746c35..37b4929 100644
--- a/libcloud/test/common/test_digitalocean_v2.py
+++ b/libcloud/test/common/test_digitalocean_v2.py
@@ -37,7 +37,8 @@ class DigitalOceanTests(LibcloudTestCase):
 
     def test_ex_account_info(self):
         account_info = self.driver.ex_account_info()
-        self.assertEqual(account_info['uuid'], 'a1234567890b1234567890c1234567890d12345')
+        self.assertEqual(account_info['uuid'],
+                         'a1234567890b1234567890c1234567890d12345')
         self.assertTrue(account_info['email_verified'])
         self.assertEqual(account_info['email'], 'user@domain.tld')
         self.assertEqual(account_info['droplet_limit'], 10)
@@ -66,7 +67,7 @@ class DigitalOceanMockHttp(MockHttpTestCase):
         None: httplib.OK,
         'CREATE': httplib.CREATED,
         'DELETE': httplib.NO_CONTENT,
-	'EMPTY': httplib.OK,
+        'EMPTY': httplib.OK,
         'NOT_FOUND': httplib.NOT_FOUND,
         'UNAUTHORIZED': httplib.UNAUTHORIZED,
         'UPDATE': httplib.OK
@@ -75,28 +76,28 @@ class DigitalOceanMockHttp(MockHttpTestCase):
     def _v2_account(self, method, url, body, headers):
         body = self.fixtures.load('_v2_account.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_account_UNAUTHORIZED(self, method, url, body, headers):
         body = self.fixtures.load(
-                   '_v2_account_UNAUTHORIZED.json')
+            '_v2_account_UNAUTHORIZED.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_actions(self, method, url, body, headers):
         body = self.fixtures.load('_v2_actions.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_actions_12345670(self, method, url, body, headers):
         body = self.fixtures.load('_v2_actions_12345670.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_actions_page_1(self, method, url, body, headers):
         body = self.fixtures.load('_v2_actions_page_1.json')
         return (self.response[None], body, {},
-                    httplib.responses[self.response[None]])
+                httplib.responses[self.response[None]])
 
 
 if __name__ == '__main__':

http://git-wip-us.apache.org/repos/asf/libcloud/blob/950fa949/libcloud/test/compute/test_digitalocean_v1.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v1.py b/libcloud/test/compute/test_digitalocean_v1.py
index c8ff999..654935e 100644
--- a/libcloud/test/compute/test_digitalocean_v1.py
+++ b/libcloud/test/compute/test_digitalocean_v1.py
@@ -89,7 +89,8 @@ class DigitalOcean_v1_Tests(LibcloudTestCase):
         location = self.driver.list_locations()[0]
 
         DigitalOceanMockHttp.type = 'INVALID_IMAGE'
-        expected_msg = r'You specified an invalid image for Droplet creation. \(code: 404\)'
+        expected_msg = \
+            r'You specified an invalid image for Droplet creation. \(code: 404\)'
         self.assertRaisesRegexp(Exception, expected_msg,
                                 self.driver.create_node,
                                 name='test', size=size, image=image,
@@ -146,7 +147,8 @@ class DigitalOceanMockHttp(MockHttpTestCase):
     def _v1_droplets_new_INVALID_IMAGE(self, method, url, body, headers):
         # reboot_node
         body = self.fixtures.load('error_invalid_image.json')
-        return (httplib.NOT_FOUND, body, {}, httplib.responses[httplib.NOT_FOUND])
+        return (httplib.NOT_FOUND, body, {},
+                httplib.responses[httplib.NOT_FOUND])
 
     def _v1_droplets_119461_reboot(self, method, url, body, headers):
         # reboot_node

http://git-wip-us.apache.org/repos/asf/libcloud/blob/950fa949/libcloud/test/compute/test_digitalocean_v2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v2.py b/libcloud/test/compute/test_digitalocean_v2.py
index 127011a..0d00f41 100644
--- a/libcloud/test/compute/test_digitalocean_v2.py
+++ b/libcloud/test/compute/test_digitalocean_v2.py
@@ -88,7 +88,8 @@ class DigitalOcean_v2_Tests(LibcloudTestCase):
         location = self.driver.list_locations()[0]
 
         DigitalOceanMockHttp.type = 'INVALID_IMAGE'
-        expected_msg = r'You specified an invalid image for Droplet creation. \(code: 404\)'
+        expected_msg = \
+            r'You specified an invalid image for Droplet creation. \(code: 404\)'
         self.assertRaisesRegexp(Exception, expected_msg,
                                 self.driver.create_node,
                                 name='test', size=size, image=image,
@@ -216,7 +217,8 @@ class DigitalOceanMockHttp(MockHttpTestCase):
         body = self.fixtures.load('ex_rename_node.json')
         return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])
 
-    def _v2_droplets_3164444_actions_SNAPSHOT(self, method, url, body, headers):
+    def _v2_droplets_3164444_actions_SNAPSHOT(self, method, url,
+                                              body, headers):
         # create_image
         body = self.fixtures.load('create_image.json')
         return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])
@@ -236,7 +238,8 @@ class DigitalOceanMockHttp(MockHttpTestCase):
         body = self.fixtures.load('ex_power_on_node.json')
         return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])
 
-    def _v2_droplets_3164444_actions_SHUTDOWN(self, method, url, body, headers):
+    def _v2_droplets_3164444_actions_SHUTDOWN(self, method, url,
+                                              body, headers):
         # ex_shutdown_node
         body = self.fixtures.load('ex_shutdown_node.json')
         return (httplib.CREATED, body, {}, httplib.responses[httplib.CREATED])

http://git-wip-us.apache.org/repos/asf/libcloud/blob/950fa949/libcloud/test/dns/test_digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_digitalocean.py b/libcloud/test/dns/test_digitalocean.py
index e618631..f1bb92e 100644
--- a/libcloud/test/dns/test_digitalocean.py
+++ b/libcloud/test/dns/test_digitalocean.py
@@ -67,7 +67,8 @@ class DigitalOceanDNSTests(LibcloudTestCase):
         zone = self.driver.get_zone('testdomain')
 
         DigitalOceanDNSMockHttp.type = 'CREATE'
-        record = self.driver.create_record('sub', zone, RecordType.A, '234.56.78.90')
+        record = self.driver.create_record('sub', zone,
+                                           RecordType.A, '234.56.78.90')
         self.assertEqual(record.id, '1234565')
         self.assertEqual(record.type, RecordType.A)
         self.assertEqual(record.data, '234.56.78.90')
@@ -100,7 +101,7 @@ class DigitalOceanDNSMockHttp(MockHttpTestCase):
         None: httplib.OK,
         'CREATE': httplib.CREATED,
         'DELETE': httplib.NO_CONTENT,
-	'EMPTY': httplib.OK,
+        'EMPTY': httplib.OK,
         'NOT_FOUND': httplib.NOT_FOUND,
         'UNAUTHORIZED': httplib.UNAUTHORIZED,
         'UPDATE': httplib.OK
@@ -109,101 +110,102 @@ class DigitalOceanDNSMockHttp(MockHttpTestCase):
     def _v2_domains(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_CREATE(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_CREATE.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_EMPTY(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_EMPTY.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_UNAUTHORIZED(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_UNAUTHORIZED.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_testdomain.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain_DELETE(self, method, url, body, headers):
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain_NOT_FOUND(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_testdomain_NOT_FOUND.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain_records(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_testdomain_records.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
-    def _v2_domains_testdomain_records_CREATE(self, method, url, body, headers):
+    def _v2_domains_testdomain_records_CREATE(self, method, url,
+                                              body, headers):
         body = self.fixtures.load('_v2_domains_testdomain_records_CREATE.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain_records_1234560(
             self, method, url, body, headers):
         body = self.fixtures.load(
-                   '_v2_domains_testdomain_records_1234560.json')
+            '_v2_domains_testdomain_records_1234560.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain_records_1234561(
             self, method, url, body, headers):
         body = self.fixtures.load(
-                   '_v2_domains_testdomain_records_1234561.json')
+            '_v2_domains_testdomain_records_1234561.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain_records_1234562(
             self, method, url, body, headers):
         body = self.fixtures.load(
-                   '_v2_domains_testdomain_records_1234562.json')
+            '_v2_domains_testdomain_records_1234562.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain_records_1234563(
             self, method, url, body, headers):
         body = self.fixtures.load(
-                   '_v2_domains_testdomain_records_1234563.json')
+            '_v2_domains_testdomain_records_1234563.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain_records_1234564(
             self, method, url, body, headers):
         body = self.fixtures.load(
-                   '_v2_domains_testdomain_records_1234564.json')
+            '_v2_domains_testdomain_records_1234564.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain_records_1234564_DELETE(
             self, method, url, body, headers):
         self.type = 'DELETE'
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain_records_1234564_NOT_FOUND(
             self, method, url, body, headers):
         body = self.fixtures.load(
-                   '_v2_domains_testdomain_records_1234564_NOT_FOUND.json')
+            '_v2_domains_testdomain_records_1234564_NOT_FOUND.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
     def _v2_domains_testdomain_records_1234564_UPDATE(
             self, method, url, body, headers):
         body = self.fixtures.load(
-                   '_v2_domains_testdomain_records_1234564_UPDATE.json')
+            '_v2_domains_testdomain_records_1234564_UPDATE.json')
         return (self.response[self.type], body, {},
-                    httplib.responses[self.response[self.type]])
+                httplib.responses[self.response[self.type]])
 
 if __name__ == '__main__':
     sys.exit(unittest.main())


[15/21] libcloud git commit: DigitalOceanNodeDriver minor revisions - Raise on api_version / key or key-secret mismatch - Added tests for v1 and v2 DigitalOceanNodeDriver using wrong keys - Updated examples to include explicit api_version values

Posted by to...@apache.org.
DigitalOceanNodeDriver minor revisions - Raise on api_version / key or key-secret mismatch - Added tests for v1 and v2 DigitalOceanNodeDriver using wrong keys - Updated examples to include explicit api_version values

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/af15645b
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/af15645b
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/af15645b

Branch: refs/heads/trunk
Commit: af15645b556a32ec65d6c66805754bd5d9d48650
Parents: fbaaee7
Author: jcastillo2nd <j....@gmail.com>
Authored: Thu May 28 13:46:18 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 docs/examples/compute/digitalocean/instantiate_api_v1.0.py | 2 +-
 docs/examples/compute/digitalocean/instantiate_api_v2.0.py | 2 +-
 libcloud/compute/drivers/digitalocean.py                   | 7 +++++++
 libcloud/dns/drivers/digitalocean.py                       | 3 ++-
 libcloud/test/compute/test_digitalocean_v1.py              | 5 +++++
 libcloud/test/compute/test_digitalocean_v2.py              | 5 +++++
 libcloud/test/dns/test_digitalocean.py                     | 2 ++
 7 files changed, 23 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/af15645b/docs/examples/compute/digitalocean/instantiate_api_v1.0.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/digitalocean/instantiate_api_v1.0.py b/docs/examples/compute/digitalocean/instantiate_api_v1.0.py
index c1b822d..ea498d1 100644
--- a/docs/examples/compute/digitalocean/instantiate_api_v1.0.py
+++ b/docs/examples/compute/digitalocean/instantiate_api_v1.0.py
@@ -2,4 +2,4 @@ from libcloud.compute.types import Provider
 from libcloud.compute.providers import get_driver
 
 cls = get_driver(Provider.DIGITAL_OCEAN)
-driver = cls('client id', 'api key')
+driver = cls('client id', 'api key', api_version='v1')

http://git-wip-us.apache.org/repos/asf/libcloud/blob/af15645b/docs/examples/compute/digitalocean/instantiate_api_v2.0.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/digitalocean/instantiate_api_v2.0.py b/docs/examples/compute/digitalocean/instantiate_api_v2.0.py
index 1a29362..83e4e7a 100644
--- a/docs/examples/compute/digitalocean/instantiate_api_v2.0.py
+++ b/docs/examples/compute/digitalocean/instantiate_api_v2.0.py
@@ -3,4 +3,4 @@ from libcloud.compute.providers import get_driver
 
 cls = get_driver(Provider.DIGITAL_OCEAN)
 
-driver = cls('access token')
+driver = cls('access token', api_version='v2')

http://git-wip-us.apache.org/repos/asf/libcloud/blob/af15645b/libcloud/compute/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/digitalocean.py b/libcloud/compute/drivers/digitalocean.py
index 46355fb..aa6dba4 100644
--- a/libcloud/compute/drivers/digitalocean.py
+++ b/libcloud/compute/drivers/digitalocean.py
@@ -21,6 +21,7 @@ from libcloud.utils.py3 import httplib
 
 from libcloud.common.digitalocean import DigitalOcean_v1_BaseDriver
 from libcloud.common.digitalocean import DigitalOcean_v2_BaseDriver
+from libcloud.common.types import InvalidCredsError
 from libcloud.compute.types import Provider, NodeState
 from libcloud.compute.base import NodeDriver, Node
 from libcloud.compute.base import NodeImage, NodeSize, NodeLocation, KeyPair
@@ -57,6 +58,12 @@ class DigitalOceanNodeDriver(NodeDriver):
     def __new__(cls, key, secret=None, api_version='v2', **kwargs):
         if cls is DigitalOceanNodeDriver:
             if api_version == 'v1' or secret is not None:
+                if secret is None:
+                    raise InvalidCredsError(
+                        'secret missing for v1 authentication')
+                if secret is not None and api_version == 'v2':
+                    raise InvalidCredsError(
+                        'secret not accepted for v2 authentication')
                 cls = DigitalOcean_v1_NodeDriver
             elif api_version == 'v2':
                 cls = DigitalOcean_v2_NodeDriver

http://git-wip-us.apache.org/repos/asf/libcloud/blob/af15645b/libcloud/dns/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/dns/drivers/digitalocean.py b/libcloud/dns/drivers/digitalocean.py
index 3470fa0..ad8a297 100644
--- a/libcloud/dns/drivers/digitalocean.py
+++ b/libcloud/dns/drivers/digitalocean.py
@@ -65,7 +65,8 @@ class DigitalOceanDNSDriver(DigitalOcean_v2_BaseDriver, DNSDriver):
         data = self._paginated_request('/v2/domains/%s/records' % (zone.id),
                                        'domain_records')
 # TODO: Not use list comprehension to add zone to record for proper data map
-#       functionality?
+#       functionality? This passes a reference to zone for each data currently
+#       to _to_record which returns a Record. map() does not take keywords
         return list(map(self._to_record, data, [zone for z in data]))
 
     def get_zone(self, zone_id):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/af15645b/libcloud/test/compute/test_digitalocean_v1.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v1.py b/libcloud/test/compute/test_digitalocean_v1.py
index 33c7f1c..0dd0e3c 100644
--- a/libcloud/test/compute/test_digitalocean_v1.py
+++ b/libcloud/test/compute/test_digitalocean_v1.py
@@ -29,6 +29,7 @@ from libcloud.compute.drivers.digitalocean import DigitalOceanNodeDriver
 from libcloud.test import LibcloudTestCase, MockHttpTestCase
 from libcloud.test.file_fixtures import ComputeFileFixtures
 from libcloud.test.secrets import DIGITALOCEAN_v1_PARAMS
+from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS
 
 
 # class DigitalOceanTests(unittest.TestCase, TestCaseMixin):
@@ -41,6 +42,10 @@ class DigitalOcean_v1_Tests(LibcloudTestCase):
         self.driver = DigitalOceanNodeDriver(*DIGITALOCEAN_v1_PARAMS,
                                              api_version='v1')
 
+    def test_v1_uses_v2_key(self):
+        self.assertRaises(InvalidCredsError, DigitalOceanNodeDriver,
+            *DIGITALOCEAN_v2_PARAMS, api_version='v1')
+
     def test_authentication(self):
         DigitalOceanMockHttp.type = 'UNAUTHORIZED_CLIENT'
         self.assertRaises(InvalidCredsError, self.driver.list_nodes)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/af15645b/libcloud/test/compute/test_digitalocean_v2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v2.py b/libcloud/test/compute/test_digitalocean_v2.py
index 0d00f41..73db2af 100644
--- a/libcloud/test/compute/test_digitalocean_v2.py
+++ b/libcloud/test/compute/test_digitalocean_v2.py
@@ -28,6 +28,7 @@ from libcloud.compute.drivers.digitalocean import DigitalOceanNodeDriver
 
 from libcloud.test import LibcloudTestCase, MockHttpTestCase
 from libcloud.test.file_fixtures import ComputeFileFixtures
+from libcloud.test.secrets import DIGITALOCEAN_v1_PARAMS
 from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS
 
 
@@ -40,6 +41,10 @@ class DigitalOcean_v2_Tests(LibcloudTestCase):
         DigitalOceanMockHttp.type = None
         self.driver = DigitalOceanNodeDriver(*DIGITALOCEAN_v2_PARAMS)
 
+    def test_v2_uses_v1_key(self):
+        self.assertRaises(InvalidCredsError, DigitalOceanNodeDriver,
+            *DIGITALOCEAN_v1_PARAMS, api_version='v2')
+
     def test_authentication(self):
         DigitalOceanMockHttp.type = 'UNAUTHORIZED'
         self.assertRaises(InvalidCredsError, self.driver.list_nodes)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/af15645b/libcloud/test/dns/test_digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_digitalocean.py b/libcloud/test/dns/test_digitalocean.py
index f1bb92e..6a5f222 100644
--- a/libcloud/test/dns/test_digitalocean.py
+++ b/libcloud/test/dns/test_digitalocean.py
@@ -15,11 +15,13 @@
 import sys
 import unittest
 
+from libcloud.common.types import InvalidCredsError
 from libcloud.dns.drivers.digitalocean import DigitalOceanDNSDriver
 from libcloud.dns.types import RecordType
 from libcloud.test import LibcloudTestCase, MockHttpTestCase
 from libcloud.test.file_fixtures import DNSFileFixtures
 from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS
+from libcloud.test.secrets import DIGITALOCEAN_v1_PARAMS
 from libcloud.utils.py3 import httplib
 
 


[05/21] libcloud git commit: Implemented libcloud.dns.driver.digitalocean DigitalOceanDNSDriver.update_record

Posted by to...@apache.org.
Implemented libcloud.dns.driver.digitalocean DigitalOceanDNSDriver.update_record

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/66dc7cd1
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/66dc7cd1
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/66dc7cd1

Branch: refs/heads/trunk
Commit: 66dc7cd1f51d598a09594f207c0ccc7abab6443b
Parents: f50b8d4
Author: Javier Castillo II <j....@gmail.com>
Authored: Sat Apr 11 02:30:35 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/dns/drivers/digitalocean.py | 57 ++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/66dc7cd1/libcloud/dns/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/dns/drivers/digitalocean.py b/libcloud/dns/drivers/digitalocean.py
index 40357b9..7e70f11 100644
--- a/libcloud/dns/drivers/digitalocean.py
+++ b/libcloud/dns/drivers/digitalocean.py
@@ -183,9 +183,64 @@ class DigitalOceanDNSDriver(DNSDriver):
                                       method='POST')
 
         return Record(id=res.object['domain_record']['id'],
-                    name=res.object['domain_record']['id'],
+                    name=res.object['domain_record']['name'],
                     type=type, data=data, zone=zone, driver=self, extra=extra)
 
+    def update_record(self, record, name=None, type=None, data=None, extra=None):
+        """
+        Update an existing record.
+
+        :param record: Record to update.
+        :type  record: :class:`Record`
+
+        :param name: Record name without the domain name (e.g. www). (Ignored)
+                     Note: The value is pulled from the record being updated
+        :type  name: ``str``
+
+        :param type: DNS record type (A, AAAA, ...). (Ignored)
+                     Note: Updating records does not support changing type
+                     so this value is ignored
+        :type  type: :class:`RecordType`
+
+        :param data: Data for the record (depends on the record type).
+        :type  data: ``str``
+
+        :param extra: (optional) Extra attributes (driver specific).
+        :type  extra: ``dict``
+
+        :rtype: :class:`Record`
+        """
+        params = {
+            "type" : record.type,
+            "name" : record.name,
+            "data" : data
+        }
+        if data == None:
+            params['data'] = record.data
+        if extra:
+            try:
+                params['priority'] = extra['priority']
+            except KeyError:
+                params['priority'] = 'null'
+            try:
+                params['port'] = extra['port']
+            except KeyError:
+                params['port'] = 'null'
+            try:
+                params['weight'] = extra['weight']
+            except KeyError:
+                params['weight'] = 'null'
+
+        res = self.connection.request('/v2/domains/%s/records/%s' %
+                                      (record.zone.id, record.id),
+                                      params=params,
+                                      method='PUT')
+
+        return Record(id=res.object['domain_record']['id'],
+                      name=res.object['domain_record']['name'],
+                      type=record.type, data=data, zone=record.zone,
+                      driver=self, extra=extra)
+
     def delete_zone(self, zone):
         """
         Delete a zone.


[19/21] libcloud git commit: Update changelog.

Posted by to...@apache.org.
Update changelog.

Closes #505


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/fa6c99d6
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/fa6c99d6
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/fa6c99d6

Branch: refs/heads/trunk
Commit: fa6c99d6841e40ef74996d5258f555bbbd2c6526
Parents: 8e16f41
Author: Tomaz Muraus <to...@tomaz.me>
Authored: Sun Jun 14 18:17:37 2015 +0800
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:17:37 2015 +0800

----------------------------------------------------------------------
 CHANGES.rst | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/fa6c99d6/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index 42a5ff6..dfec2f8 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -261,6 +261,10 @@ DNS
   (GITHUB-461)
   [Vanč Levstik]
 
+- Add new driver for DigitalOcean DNS service.
+  (GITHUB-505)
+  [Javier Castillo II]
+
 Changes with Apache Libcloud 0.17.0
 -----------------------------------
 


[09/21] libcloud git commit: DO NodeDriver uses DO BaseDriver - Support for v1 and v2 initialization with authentication secret - Updated v1 DigitalOceanNodeDriver to use updated KeyPair Management - Updated tests to reflect KeyPair Management changes

Posted by to...@apache.org.
DO NodeDriver uses DO BaseDriver - Support for v1 and v2 initialization with authentication secret - Updated v1 DigitalOceanNodeDriver to use updated KeyPair Management - Updated tests to reflect KeyPair Management changes

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/9224e8e1
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/9224e8e1
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/9224e8e1

Branch: refs/heads/trunk
Commit: 9224e8e180133f4af499a77366d3ca2d640afeda
Parents: d1a8e22
Author: Javier Castillo II <j....@gmail.com>
Authored: Sun Apr 12 18:02:07 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/compute/drivers/digitalocean.py      | 172 +++++++++------------
 libcloud/test/compute/test_digitalocean_v1.py |  14 +-
 2 files changed, 79 insertions(+), 107 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/9224e8e1/libcloud/compute/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/digitalocean.py b/libcloud/compute/drivers/digitalocean.py
index 32dd199..1cb209b 100644
--- a/libcloud/compute/drivers/digitalocean.py
+++ b/libcloud/compute/drivers/digitalocean.py
@@ -20,6 +20,8 @@ from libcloud.utils.py3 import httplib
 
 from libcloud.common.base import ConnectionUserAndKey, ConnectionKey
 from libcloud.common.base import JsonResponse
+from libcloud.common.digitalocean import DigitalOcean_v1_BaseDriver
+from libcloud.common.digitalocean import DigitalOcean_v2_BaseDriver
 from libcloud.compute.types import Provider, NodeState, InvalidCredsError
 from libcloud.compute.base import NodeDriver, Node
 from libcloud.compute.base import NodeImage, NodeSize, NodeLocation, KeyPair
@@ -27,7 +29,7 @@ from libcloud.compute.base import NodeImage, NodeSize, NodeLocation, KeyPair
 __all__ = [
     'DigitalOceanNodeDriver',
     'DigitalOcean_v1_NodeDriver',
-    'DigitalOcean_v1_NodeDriver'
+    'DigitalOcean_v2_NodeDriver'
 ]
 
 
@@ -35,6 +37,15 @@ class DigitalOceanNodeDriver(NodeDriver):
     """
     DigitalOcean NodeDriver defaulting to using APIv2.
 
+    :keyword    key: Required for authentication. Used in both ``v1`` and
+                     ``v2`` implementations.
+    :type       key: ``str``
+
+    :keyword    secret: Used in driver authentication with key. Defaults to
+                        None and when set, will cause driver to use ``v1`` for
+                        connection and response. (optional)
+    :type       secret: ``str``
+
     :keyword    api_version: Specifies the API version to use. ``v1`` and
                              ``v2`` are the only valid options. Defaults to
                              using ``v2`` (optional)
@@ -46,7 +57,7 @@ class DigitalOceanNodeDriver(NodeDriver):
 
     def __new__(cls, key, secret=None, api_version='v2', **kwargs):
         if cls is DigitalOceanNodeDriver:
-            if api_version == 'v1':
+            if api_version == 'v1' or secret != None:
                 cls = DigitalOcean_v1_NodeDriver
             elif api_version == 'v2':
                 cls = DigitalOcean_v2_NodeDriver
@@ -55,45 +66,7 @@ class DigitalOceanNodeDriver(NodeDriver):
                                           (api_version))
         return super(DigitalOceanNodeDriver, cls).__new__(cls, **kwargs)
 
-
-class DigitalOcean_v1_Response(JsonResponse):
-    def parse_error(self):
-        if self.status == httplib.FOUND and '/api/error' in self.body:
-            # Hacky, but DigitalOcean error responses are awful
-            raise InvalidCredsError(self.body)
-        elif self.status == httplib.UNAUTHORIZED:
-            body = self.parse_body()
-            raise InvalidCredsError(body['message'])
-        else:
-            body = self.parse_body()
-
-            if 'error_message' in body:
-                error = '%s (code: %s)' % (body['error_message'], self.status)
-            else:
-                error = body
-            return error
-
-
-class DigitalOcean_v2_Response(JsonResponse):
-    valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
-                            httplib.NO_CONTENT]
-
-    def parse_error(self):
-        if self.status == httplib.UNAUTHORIZED:
-            body = self.parse_body()
-            raise InvalidCredsError(body['message'])
-        else:
-            body = self.parse_body()
-            if 'message' in body:
-                error = '%s (code: %s)' % (body['message'], self.status)
-            else:
-                error = body
-            return error
-
-    def success(self):
-        return self.status in self.valid_response_codes
-
-
+# TODO Implement v1 driver using KeyPair
 class SSHKey(object):
     def __init__(self, id, name, pub_key):
         self.id = id
@@ -105,52 +78,11 @@ class SSHKey(object):
                 (self.id, self.name, self.pub_key))
 
 
-class DigitalOcean_v1_Connection(ConnectionUserAndKey):
-    """
-    Connection class for the DigitalOcean (v1) driver.
-    """
-
-    host = 'api.digitalocean.com'
-    responseCls = DigitalOcean_v1_Response
-
-    def add_default_params(self, params):
-        """
-        Add parameters that are necessary for every request
-
-        This method adds ``client_id`` and ``api_key`` to
-        the request.
-        """
-        params['client_id'] = self.user_id
-        params['api_key'] = self.key
-        return params
-
-
-class DigitalOcean_v2_Connection(ConnectionKey):
-    """
-    Connection class for the DigitalOcean (v2) driver.
-    """
-
-    host = 'api.digitalocean.com'
-    responseCls = DigitalOcean_v2_Response
-
-    def add_default_headers(self, headers):
-        """
-        Add headers that are necessary for every request
-
-        This method adds ``token`` to the request.
-        """
-        headers['Authorization'] = 'Bearer %s' % (self.key)
-        headers['Content-Type'] = 'application/json'
-        return headers
-
-
-class DigitalOcean_v1_NodeDriver(DigitalOceanNodeDriver):
+class DigitalOcean_v1_NodeDriver(DigitalOcean_v1_BaseDriver, DigitalOceanNodeDriver):
     """
     DigitalOcean NodeDriver using v1 of the API.
     """
 
-    connectionCls = DigitalOcean_v1_Connection
-
     NODE_STATE_MAP = {'new': NodeState.PENDING,
                       'off': NodeState.REBOOTING,
                       'active': NodeState.RUNNING}
@@ -215,17 +147,33 @@ class DigitalOcean_v1_NodeDriver(DigitalOceanNodeDriver):
                                       params=params)
         return res.status == httplib.OK
 
-    def ex_list_ssh_keys(self):
+    def list_key_pairs(self):
         """
         List all the available SSH keys.
 
         :return: Available SSH keys.
-        :rtype: ``list`` of :class:`SSHKey`
+        :rtype: ``list`` of :class:`KeyPair`
         """
         data = self.connection.request('/v1/ssh_keys').object['ssh_keys']
-        return list(map(self._to_ssh_key, data))
+        return list(map(self._to_key_pair, data))
+
+    def get_key_pair(self, name):
+        """
+        Retrieve a single key pair.
+
+        :param name: Name of the key pair to retrieve.
+        :type name: ``str``
 
-    def ex_create_ssh_key(self, name, ssh_key_pub):
+        :rtype: :class:`.KeyPair`
+        """
+        qkey = [k for k in self.list_key_pairs() if k.name == name][0]
+        data = self.connection.request('/v1/ssh_keys/%s' %
+                                       qkey.extra['id']).object['ssh_key']
+        return self._to_key_pair(data=data)
+
+    #TODO: This adds the ssh_key_pub parameter. This puts the burden of making
+    #      it within the function or on the API. The KeyPair API needs work.
+    def create_key_pair(self, name, ssh_key_pub):
         """
         Create a new SSH key.
 
@@ -239,16 +187,20 @@ class DigitalOcean_v1_NodeDriver(DigitalOceanNodeDriver):
         data = self.connection.request('/v1/ssh_keys/new/', method='GET',
                                        params=params).object
         assert 'ssh_key' in data
-        return self._to_ssh_key(data=data['ssh_key'])
+        #TODO: libcloud.compute.base.KeyPair.create_key_pair doesn't specify
+        #      a return value. This looks like it should return a KeyPair
+        return self._to_key_pair(data=data['ssh_key'])
 
-    def ex_destroy_ssh_key(self, key_id):
+    def delete_key_pair(self, key_pair):
         """
-        Delete an existing SSH key.
+        Delete an existing key pair.
 
-        :param      key_id: SSH key id (required)
-        :type       key_id: ``str``
+        :param key_pair: Key pair object.
+        :type key_pair: :class:`.KeyPair`
         """
-        res = self.connection.request('/v1/ssh_keys/%s/destroy/' % (key_id))
+        res = self.connection.request('/v1/ssh_keys/%s/destroy/' %
+                                      key_pair.extra['id'])
+        #TODO: This looks like it should return bool like the other delete_*
         return res.status == httplib.OK
 
     def _to_node(self, data):
@@ -293,18 +245,24 @@ class DigitalOcean_v1_NodeDriver(DigitalOceanNodeDriver):
         return NodeSize(id=data['id'], name=data['name'], ram=ram, disk=0,
                         bandwidth=0, price=0, driver=self)
 
+    def _to_key_pair(self, data):
+        try:
+            pubkey = data['ssh_pub_key']
+        except KeyError:
+            pubkey = None
+        return KeyPair(data['name'], public_key=pubkey, fingerprint=None,
+                       driver=self, private_key=None, extra={'id':data['id']})
+
     def _to_ssh_key(self, data):
         return SSHKey(id=data['id'], name=data['name'],
                       pub_key=data.get('ssh_pub_key', None))
 
 
-class DigitalOcean_v2_NodeDriver(DigitalOceanNodeDriver):
+class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver, DigitalOceanNodeDriver):
     """
     DigitalOcean NodeDriver using v2 of the API.
     """
 
-    connectionCls = DigitalOcean_v2_Connection
-
     NODE_STATE_MAP = {'new': NodeState.PENDING,
                       'off': NodeState.STOPPED,
                       'active': NodeState.RUNNING,
@@ -440,8 +398,22 @@ class DigitalOcean_v2_NodeDriver(DigitalOceanNodeDriver):
         :return: Available SSH keys.
         :rtype: ``list`` of :class:`KeyPair`
         """
-        data = self.connection.request('/v2/account/keys').object['ssh_keys']
-        return list(map(self._to_key_pairs, data))
+        data = self._paginated_request('/v2/account/keys', 'ssh_keys')
+        return list(map(self._to_key_pair, data))
+
+    def get_key_pair(self, name):
+        """
+        Retrieve a single key pair.
+
+        :param name: Name of the key pair to retrieve.
+        :type name: ``str``
+
+        :rtype: :class:`.KeyPair`
+        """
+        qkey = [k for k in self.list_key_pairs() if k.name == name][0]
+        data = self.connection.request('/v2/account/keys/%s' %
+                                       qkey.extra['id']).object['ssh_key']
+        return self._to_key_pair(data=data)
 
     def create_key_pair(self, name, public_key):
         """
@@ -456,7 +428,7 @@ class DigitalOcean_v2_NodeDriver(DigitalOceanNodeDriver):
         params = {'name': name, 'public_key': public_key}
         data = self.connection.request('/v2/account/keys', method='POST',
                                        params=params).object['ssh_key']
-        return self._to_key_pairs(data=data)
+        return self._to_key_pair(data=data)
 
     def delete_key_pair(self, key):
         """
@@ -543,7 +515,7 @@ class DigitalOcean_v2_NodeDriver(DigitalOceanNodeDriver):
                         disk=data['disk'], bandwidth=data['transfer'],
                         price=data['price_hourly'], driver=self, extra=extra)
 
-    def _to_key_pairs(self, data):
+    def _to_key_pair(self, data):
         extra = {'id': data['id']}
         return KeyPair(name=data['name'],
                        fingerprint=data['fingerprint'],

http://git-wip-us.apache.org/repos/asf/libcloud/blob/9224e8e1/libcloud/test/compute/test_digitalocean_v1.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v1.py b/libcloud/test/compute/test_digitalocean_v1.py
index 030e2ee..c8ff999 100644
--- a/libcloud/test/compute/test_digitalocean_v1.py
+++ b/libcloud/test/compute/test_digitalocean_v1.py
@@ -110,17 +110,17 @@ class DigitalOcean_v1_Tests(LibcloudTestCase):
         result = self.driver.ex_rename_node(node, 'fedora helios')
         self.assertTrue(result)
 
-    def test_ex_list_ssh_keys(self):
-        keys = self.driver.ex_list_ssh_keys()
+    def test_list_key_pairs(self):
+        keys = self.driver.list_key_pairs()
         self.assertEqual(len(keys), 1)
 
-        self.assertEqual(keys[0].id, 7717)
+        self.assertEqual(keys[0].extra['id'], 7717)
         self.assertEqual(keys[0].name, 'test1')
-        self.assertEqual(keys[0].pub_key, None)
+        self.assertEqual(keys[0].public_key, None)
 
-    def test_ex_destroy_ssh_key(self):
-        key = self.driver.ex_list_ssh_keys()[0]
-        result = self.driver.ex_destroy_ssh_key(key.id)
+    def test_delete_key_pair(self):
+        key = self.driver.list_key_pairs()[0]
+        result = self.driver.delete_key_pair(key)
         self.assertTrue(result)
 
 


[07/21] libcloud git commit: Added unit tests and common/DigitalOceanBaseDriver - Added 'common' to FIXTURES_ROOT for FileFixtures in test/common - Modified DigitalOceanBaseDriver from compute/drivers/digitalocean into common/digitalocean to support v1 a

Posted by to...@apache.org.
Added unit tests and common/DigitalOceanBaseDriver - Added 'common' to FIXTURES_ROOT for FileFixtures in test/common - Modified DigitalOceanBaseDriver from compute/drivers/digitalocean into common/digitalocean to support v1 and v2 by initialization - Added dns/driver/digitalocean tests - Added common/digitalocean tests

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/a3a5f173
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/a3a5f173
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/a3a5f173

Branch: refs/heads/trunk
Commit: a3a5f173fe0992de263caff44bc370b051ecefb6
Parents: 66dc7cd
Author: Javier Castillo II <j....@gmail.com>
Authored: Sun Apr 12 01:57:29 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/common/digitalocean.py                 | 112 +++++++++-
 libcloud/dns/drivers/digitalocean.py            |  41 +---
 .../digitalocean/_v1_events_12345670.json       |   1 +
 .../_v1_events_12345670_UNAUTHORIZED.json       |   1 +
 .../fixtures/digitalocean/_v2_account.json      |   1 +
 .../digitalocean/_v2_account_UNAUTHORIZED.json  |   1 +
 .../fixtures/digitalocean/_v2_actions.json      |   1 +
 .../digitalocean/_v2_actions_12345670.json      |   1 +
 .../digitalocean/_v2_actions_page_1.json        |   1 +
 .../digitalocean/_v2_actions_page_2.json        |   1 +
 libcloud/test/common/test_digitalocean_v1.py    |  82 +++++++
 libcloud/test/common/test_digitalocean_v2.py    | 105 +++++++++
 .../dns/fixtures/digitalocean/_v2_domains.json  |   1 +
 .../digitalocean/_v2_domains_CREATE.json        |   1 +
 .../digitalocean/_v2_domains_EMPTY.json         |   1 +
 .../digitalocean/_v2_domains_UNAUTHORIZED.json  |   1 +
 .../digitalocean/_v2_domains_testdomain.json    |   1 +
 .../_v2_domains_testdomain_NOT_FOUND.json       |   1 +
 .../_v2_domains_testdomain_records.json         |   1 +
 .../_v2_domains_testdomain_records_1234560.json |   1 +
 .../_v2_domains_testdomain_records_1234561.json |   1 +
 .../_v2_domains_testdomain_records_1234562.json |   1 +
 .../_v2_domains_testdomain_records_1234564.json |   1 +
 ...ns_testdomain_records_1234564_NOT_FOUND.json |   1 +
 ...mains_testdomain_records_1234564_UPDATE.json |   1 +
 .../_v2_domains_testdomain_records_CREATE.json  |   1 +
 libcloud/test/dns/test_digitalocean.py          | 214 +++++++++++++++++++
 libcloud/test/file_fixtures.py                  |   1 +
 28 files changed, 537 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/common/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/common/digitalocean.py b/libcloud/common/digitalocean.py
index 097b207..7d46881 100644
--- a/libcloud/common/digitalocean.py
+++ b/libcloud/common/digitalocean.py
@@ -19,6 +19,7 @@ Common settings and connection objects for DigitalOcean Cloud
 
 from libcloud.utils.py3 import httplib
 
+from libcloud.common.base import BaseDriver
 from libcloud.common.base import ConnectionUserAndKey, ConnectionKey
 from libcloud.common.base import JsonResponse
 from libcloud.common.types import InvalidCredsError
@@ -26,12 +27,11 @@ from libcloud.common.types import InvalidCredsError
 __all__ = [
     'DigitalOcean_v1_Response',
     'DigitalOcean_v1_Connection',
-    'DigitalOcean_v2_Response'
+    'DigitalOcean_v2_Response',
     'DigitalOcean_v2_Connection',
+    'DigitalOceanBaseDriver'
 ]
 
-AUTH_URL = 'https://api.digitalocean.com'
-
 
 class DigitalOcean_v1_Response(JsonResponse):
     def parse_error(self):
@@ -118,3 +118,109 @@ class DigitalOceanConnection(DigitalOcean_v2_Connection):
 
 class DigitalOceanResponse(DigitalOcean_v2_Response):
     pass
+
+
+class DigitalOceanBaseDriver(BaseDriver):
+    """
+    DigitalOcean BaseDriver
+    """
+    name = 'DigitalOcean'
+    website = 'https://www.digitalocean.com'
+
+    def __new__(cls, key, secret=None, api_version='v2', **kwargs):
+        if cls is DigitalOceanBaseDriver:
+            if api_version == 'v1' or secret != None:
+                cls = DigitalOcean_v1_BaseDriver
+            elif api_version == 'v2':
+                cls = DigitalOcean_v2_BaseDriver
+            else:
+                raise NotImplementedError('Unsupported API version: %s' %
+                                          (api_version))
+        return super(DigitalOceanBaseDriver, cls).__new__(cls, **kwargs)
+
+    def ex_account_info(self):
+        raise NotImplementedError(
+            'ex_account_info not implemented for this driver')
+
+    def ex_list_events(self):
+        raise NotImplementedError(
+            'ex_list_events not implemented for this driver')
+
+    def ex_get_event(self, event_id):
+        raise NotImplementedError(
+            'ex_get_event not implemented for this driver')
+
+    def _paginated_request(self, event_id):
+        raise NotImplementedError(
+            '_paginated_requests not implemented for this driver')
+
+
+class DigitalOcean_v1_BaseDriver(DigitalOceanBaseDriver):
+    """
+    DigitalOcean BaseDriver using v1 of the API.
+    """
+    connectionCls = DigitalOcean_v1_Connection
+
+    def ex_get_event(self, event_id):
+        """
+        Get an event object
+
+        :param      event_id: Event id (required)
+        :type       event_id: ``str``
+        """
+        return self.connection.request('/v1/events/%s' % event_id).object
+
+
+class DigitalOcean_v2_BaseDriver(DigitalOceanBaseDriver):
+    """
+    DigitalOcean BaseDriver using v2 of the API.
+    """
+    connectionCls = DigitalOcean_v2_Connection
+
+    def ex_account_info(self):
+        return self.connection.request('/v2/account').object['account']
+
+    def ex_list_events(self):
+        return self._paginated_request('/v2/actions', 'actions')
+
+    def ex_get_event(self, event_id):
+        """
+        Get an event object
+
+        :param      event_id: Event id (required)
+        :type       event_id: ``str``
+        """
+        params = {}
+        return self.connection.request('/v2/actions/%s' % event_id,
+                                       params=params).object['action']
+
+    def _paginated_request(self, url, obj):
+        """
+        Perform multiple calls in order to have a full list of elements when
+        the API responses are paginated.
+
+        :param url: API endpoint
+        :type url: ``str``
+
+        :param obj: Result object key
+        :type obj: ``str``
+
+        :return: ``list`` of API response objects
+        """
+        params = {}
+        data = self.connection.request(url)
+        try:
+            pages = data.object['links']['pages']['last'].split('=')[-1]
+            values = data.object[obj]
+            for page in range(2, int(pages) + 1):
+                params.update({'page': page})
+                new_data = self.connection.request(url, params=params)
+
+                more_values = new_data.object[obj]
+                for value in more_values:
+                    values.append(value)
+            data = values
+        except KeyError:  # No pages.
+            data = data.object[obj]
+
+        return data

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/dns/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/dns/drivers/digitalocean.py b/libcloud/dns/drivers/digitalocean.py
index 7e70f11..81e313f 100644
--- a/libcloud/dns/drivers/digitalocean.py
+++ b/libcloud/dns/drivers/digitalocean.py
@@ -22,14 +22,15 @@ __all__ = [
 
 from libcloud.utils.py3 import httplib
 
-from libcloud.common.digitalocean import DigitalOceanConnection, DigitalOceanResponse
+from libcloud.common.digitalocean import DigitalOcean_v2_BaseDriver
+from libcloud.common.digitalocean import DigitalOceanConnection
+from libcloud.common.digitalocean import DigitalOceanResponse
 from libcloud.dns.types import Provider, RecordType
 from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError
 from libcloud.dns.base import DNSDriver, Zone, Record
 
 
-class DigitalOceanDNSDriver(DNSDriver):
-    connectionCls = DigitalOceanConnection
+class DigitalOceanDNSDriver(DigitalOcean_v2_BaseDriver, DNSDriver):
     type = Provider.DIGITAL_OCEAN
     name = "DigitalOcean"
     website = 'https://www.digitalocean.com'
@@ -275,40 +276,6 @@ class DigitalOceanDNSDriver(DNSDriver):
                                       method='DELETE')
         return res.status == httplib.NO_CONTENT
 
-# TODO: If there is a way to push this into libcloud.common.digitalocean
-#       instead of having it in libcloud.dns.digitalocean and
-#       libcloud.compute.digitalocean
-    def _paginated_request(self, url, obj):
-        """
-        Perform multiple calls in order to have a full list of elements when
-        the API responses are paginated.
-
-        :param url: API endpoint
-        :type url: ``str``
-
-        :param obj: Result object key
-        :type obj: ``str``
-
-        :return: ``list`` of API response objects
-        """
-        params = {}
-        data = self.connection.request(url)
-        try:
-            pages = data.object['links']['pages']['last'].split('=')[-1]
-            values = data.object[obj]
-            for page in range(2, int(pages) + 1):
-                params.update({'page': page})
-                new_data = self.connection.request(url, params=params)
-
-                more_values = new_data.object[obj]
-                for value in more_values:
-                    values.append(value)
-            data = values
-        except KeyError:  # No pages.
-            data = data.object[obj]
-
-        return data
-
     def _to_record(self, data, zone=None):
         extra = {'port' : data['port'], 'priority' : data['priority'],
                  'weight' : data['weight']}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/common/fixtures/digitalocean/_v1_events_12345670.json
----------------------------------------------------------------------
diff --git a/libcloud/test/common/fixtures/digitalocean/_v1_events_12345670.json b/libcloud/test/common/fixtures/digitalocean/_v1_events_12345670.json
new file mode 100644
index 0000000..6ff04b5
--- /dev/null
+++ b/libcloud/test/common/fixtures/digitalocean/_v1_events_12345670.json
@@ -0,0 +1 @@
+{"status":"OK","event":{"id":12345670,"event_type_id":1,"percentage":"100","droplet_id":1234560,"action_status":"done"}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/common/fixtures/digitalocean/_v1_events_12345670_UNAUTHORIZED.json
----------------------------------------------------------------------
diff --git a/libcloud/test/common/fixtures/digitalocean/_v1_events_12345670_UNAUTHORIZED.json b/libcloud/test/common/fixtures/digitalocean/_v1_events_12345670_UNAUTHORIZED.json
new file mode 100644
index 0000000..0994c93
--- /dev/null
+++ b/libcloud/test/common/fixtures/digitalocean/_v1_events_12345670_UNAUTHORIZED.json
@@ -0,0 +1 @@
+{"status":"ERROR","error_message":"Access Denied","message":"Access Denied"}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/common/fixtures/digitalocean/_v2_account.json
----------------------------------------------------------------------
diff --git a/libcloud/test/common/fixtures/digitalocean/_v2_account.json b/libcloud/test/common/fixtures/digitalocean/_v2_account.json
new file mode 100644
index 0000000..37083cf
--- /dev/null
+++ b/libcloud/test/common/fixtures/digitalocean/_v2_account.json
@@ -0,0 +1 @@
+{"account":{"droplet_limit":10,"email":"user@domain.tld","uuid":"a1234567890b1234567890c1234567890d12345","email_verified":true}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/common/fixtures/digitalocean/_v2_account_UNAUTHORIZED.json
----------------------------------------------------------------------
diff --git a/libcloud/test/common/fixtures/digitalocean/_v2_account_UNAUTHORIZED.json b/libcloud/test/common/fixtures/digitalocean/_v2_account_UNAUTHORIZED.json
new file mode 100644
index 0000000..415d9ef
--- /dev/null
+++ b/libcloud/test/common/fixtures/digitalocean/_v2_account_UNAUTHORIZED.json
@@ -0,0 +1 @@
+{"id":"unauthorized","message":"Unable to authenticate you."}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/common/fixtures/digitalocean/_v2_actions.json
----------------------------------------------------------------------
diff --git a/libcloud/test/common/fixtures/digitalocean/_v2_actions.json b/libcloud/test/common/fixtures/digitalocean/_v2_actions.json
new file mode 100644
index 0000000..3c36117
--- /dev/null
+++ b/libcloud/test/common/fixtures/digitalocean/_v2_actions.json
@@ -0,0 +1 @@
+{"actions":[],"links":{},"meta":{"total":0}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/common/fixtures/digitalocean/_v2_actions_12345670.json
----------------------------------------------------------------------
diff --git a/libcloud/test/common/fixtures/digitalocean/_v2_actions_12345670.json b/libcloud/test/common/fixtures/digitalocean/_v2_actions_12345670.json
new file mode 100644
index 0000000..9631675
--- /dev/null
+++ b/libcloud/test/common/fixtures/digitalocean/_v2_actions_12345670.json
@@ -0,0 +1 @@
+{"action":{"id":12345670,"status":"completed","type":"power_on","started_at":"2015-03-28T10:57:40Z","completed_at":"2015-03-28T10:57:42Z","resource_id":1234560,"resource_type":"droplet","region":{"name":"New York 3","slug":"nyc3","sizes":["512mb","1gb","2gb","4gb","8gb","16gb","32gb","48gb","64gb"],"features":["virtio","private_networking","backups","ipv6","metadata"],"available":true},"region_slug":"nyc3"}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/common/fixtures/digitalocean/_v2_actions_page_1.json
----------------------------------------------------------------------
diff --git a/libcloud/test/common/fixtures/digitalocean/_v2_actions_page_1.json b/libcloud/test/common/fixtures/digitalocean/_v2_actions_page_1.json
new file mode 100644
index 0000000..b9ebd61
--- /dev/null
+++ b/libcloud/test/common/fixtures/digitalocean/_v2_actions_page_1.json
@@ -0,0 +1 @@
+{"actions":[{"id":12345671,"status":"completed","type":"create","started_at":"2015-04-10T14:09:37Z","completed_at":"2015-04-10T14:10:03Z","resource_id":1234561,"resource_type":"droplet","region":{"name":"Frankfurt 1","slug":"fra1","sizes":["512mb","1gb","2gb","4gb","8gb","16gb","32gb","48gb","64gb"],"features":["virtio","private_networking","backups","ipv6","metadata"],"available":true},"region_slug":"fra1"}],"links":{"pages":{"last":"https://api.digitalocean.com/v2/actions/?page=2","next":"https://api.digitalocean.com/v2/actions/?page=2"}},"meta":{"total":2}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/common/fixtures/digitalocean/_v2_actions_page_2.json
----------------------------------------------------------------------
diff --git a/libcloud/test/common/fixtures/digitalocean/_v2_actions_page_2.json b/libcloud/test/common/fixtures/digitalocean/_v2_actions_page_2.json
new file mode 100644
index 0000000..3ddfad2
--- /dev/null
+++ b/libcloud/test/common/fixtures/digitalocean/_v2_actions_page_2.json
@@ -0,0 +1 @@
+{"actions":[{"id":12345670,"status":"completed","type":"create","started_at":"2015-04-10T14:09:12Z","completed_at":"2015-04-10T14:09:38Z","resource_id":1234560,"resource_type":"droplet","region":{"name":"Frankfurt 1","slug":"fra1","sizes":["512mb","1gb","2gb","4gb","8gb","16gb","32gb","48gb","64gb"],"features":["virtio","private_networking","backups","ipv6","metadata"],"available":true},"region_slug":"fra1"}],"links":{"pages":{"first":"https://api.digitalocean.com/v2/actions/?page=1","prev":"https://api.digitalocean.com/v2/actions/?page=1"}},"meta":{"total":2}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/common/test_digitalocean_v1.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_digitalocean_v1.py b/libcloud/test/common/test_digitalocean_v1.py
new file mode 100644
index 0000000..e10f54d
--- /dev/null
+++ b/libcloud/test/common/test_digitalocean_v1.py
@@ -0,0 +1,82 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+
+import os
+import sys
+import unittest
+
+from libcloud.common.types import InvalidCredsError
+from libcloud.common.digitalocean import DigitalOceanBaseDriver
+from libcloud.dns.types import RecordType
+from libcloud.test import LibcloudTestCase, MockHttpTestCase
+from libcloud.test.file_fixtures import FileFixtures
+from libcloud.test.secrets import DIGITALOCEAN_v1_PARAMS
+from libcloud.utils.py3 import httplib
+
+
+class DigitalOceanTests(LibcloudTestCase):
+
+    def setUp(self):
+        DigitalOceanBaseDriver.connectionCls.conn_classes = \
+            (None, DigitalOceanMockHttp)
+        DigitalOceanMockHttp.type = None
+        self.driver = DigitalOceanBaseDriver(*DIGITALOCEAN_v1_PARAMS)
+
+    def test_authentication(self):
+        DigitalOceanMockHttp.type = 'UNAUTHORIZED'
+        self.assertRaises(InvalidCredsError, self.driver.ex_get_event, '12345670')
+
+    def test_ex_account_info(self):
+        self.assertRaises(NotImplementedError, self.driver.ex_account_info)
+
+    def test_ex_list_events(self):
+        self.assertRaises(NotImplementedError, self.driver.ex_list_events)
+
+    def test_ex_get_event(self):
+        action = self.driver.ex_get_event('12345670')
+        self.assertEqual(action["status"], "OK")
+        self.assertEqual(action["event"]["id"], 12345670)
+        self.assertEqual(action["event"]["event_type_id"], 1)
+
+    def test__paginated_request(self):
+        self.assertRaises(NotImplementedError, self.driver._paginated_request, '/v1/anything')
+
+
+class DigitalOceanMockHttp(MockHttpTestCase):
+    fixtures = FileFixtures('common', 'digitalocean')
+
+    response = {
+        None: httplib.OK,
+        'CREATE': httplib.CREATED,
+        'DELETE': httplib.NO_CONTENT,
+	'EMPTY': httplib.OK,
+        'NOT_FOUND': httplib.NOT_FOUND,
+        'UNAUTHORIZED': httplib.UNAUTHORIZED,
+        'UPDATE': httplib.OK
+    }
+
+    def _v1_events_12345670_UNAUTHORIZED(self, method, url, body, headers):
+        body = self.fixtures.load(
+                   '_v1_events_12345670_UNAUTHORIZED.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v1_events_12345670(self, method, url, body, headers):
+        body = self.fixtures.load('_v1_events_12345670.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/common/test_digitalocean_v2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_digitalocean_v2.py b/libcloud/test/common/test_digitalocean_v2.py
new file mode 100644
index 0000000..c530b5b
--- /dev/null
+++ b/libcloud/test/common/test_digitalocean_v2.py
@@ -0,0 +1,105 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+
+import os
+import sys
+import unittest
+
+from libcloud.common.types import InvalidCredsError
+from libcloud.common.digitalocean import DigitalOceanBaseDriver
+from libcloud.dns.types import RecordType
+from libcloud.test import LibcloudTestCase, MockHttpTestCase
+from libcloud.test.file_fixtures import FileFixtures
+from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS
+from libcloud.utils.py3 import httplib
+
+
+class DigitalOceanTests(LibcloudTestCase):
+
+    def setUp(self):
+        DigitalOceanBaseDriver.connectionCls.conn_classes = \
+            (None, DigitalOceanMockHttp)
+        DigitalOceanMockHttp.type = None
+        self.driver = DigitalOceanBaseDriver(*DIGITALOCEAN_v2_PARAMS)
+
+    def test_authentication(self):
+        DigitalOceanMockHttp.type = 'UNAUTHORIZED'
+        self.assertRaises(InvalidCredsError, self.driver.ex_account_info)
+
+    def test_ex_account_info(self):
+        account_info = self.driver.ex_account_info()
+        self.assertEqual(account_info['uuid'], 'a1234567890b1234567890c1234567890d12345')
+        self.assertTrue(account_info['email_verified'])
+        self.assertEqual(account_info['email'], 'user@domain.tld')
+        self.assertEqual(account_info['droplet_limit'], 10)
+
+    def test_ex_list_events(self):
+        events = self.driver.ex_list_events()
+        self.assertEqual(events, [])
+
+    def test_ex_get_event(self):
+        action = self.driver.ex_get_event('12345670')
+        self.assertEqual(action["id"], 12345670)
+        self.assertEqual(action["status"], "completed")
+        self.assertEqual(action["type"], "power_on")
+
+    def test__paginated_request(self):
+        DigitalOceanMockHttp.type = 'page_1'
+        actions = self.driver._paginated_request('/v2/actions', 'actions')
+        self.assertEqual(actions[0]['id'], 12345671)
+        self.assertEqual(actions[0]['status'], 'completed')
+
+
+class DigitalOceanMockHttp(MockHttpTestCase):
+    fixtures = FileFixtures('common', 'digitalocean')
+
+    response = {
+        None: httplib.OK,
+        'CREATE': httplib.CREATED,
+        'DELETE': httplib.NO_CONTENT,
+	'EMPTY': httplib.OK,
+        'NOT_FOUND': httplib.NOT_FOUND,
+        'UNAUTHORIZED': httplib.UNAUTHORIZED,
+        'UPDATE': httplib.OK
+    }
+
+    def _v2_account(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_account.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_account_UNAUTHORIZED(self, method, url, body, headers):
+        body = self.fixtures.load(
+                   '_v2_account_UNAUTHORIZED.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_actions(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_actions.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_actions_12345670(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_actions_12345670.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_actions_page_1(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_actions_page_1.json')
+        return (self.response[None], body, {},
+                    httplib.responses[self.response[None]])
+
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains.json
new file mode 100644
index 0000000..f00d3a3
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains.json
@@ -0,0 +1 @@
+{"domains":[{"name":"testdomain","ttl":1800,"zone_file":"$ORIGIN testdomain.\n$TTL 1800\ntestdomain. IN SOA ns1.digitalocean.com. hostmaster.testdomain. 1428768671 10800 3600 604800 1800\ntestdomain. 1800 IN NS ns1.digitalocean.com.\ntestdomain. 1800 IN NS ns2.digitalocean.com.\ntestdomain. 1800 IN NS ns3.digitalocean.com.\ntestdomain. 1800 IN A 123.45.67.89\n"}],"links":{},"meta":{"total":1}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_CREATE.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_CREATE.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_CREATE.json
new file mode 100644
index 0000000..b5b37f0
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_CREATE.json
@@ -0,0 +1 @@
+{"domain":{"name":"testdomain","ttl":null,"zone_file":null}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_EMPTY.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_EMPTY.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_EMPTY.json
new file mode 100644
index 0000000..2b7209c
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_EMPTY.json
@@ -0,0 +1 @@
+{"domains":[],"links":{},"meta":{"total":0}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_UNAUTHORIZED.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_UNAUTHORIZED.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_UNAUTHORIZED.json
new file mode 100644
index 0000000..415d9ef
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_UNAUTHORIZED.json
@@ -0,0 +1 @@
+{"id":"unauthorized","message":"Unable to authenticate you."}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain.json
new file mode 100644
index 0000000..cf6cf37
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain.json
@@ -0,0 +1 @@
+{"domain":{"name":"testdomain","ttl":1800,"zone_file":"$ORIGIN testdomain.\n$TTL 1800\ntestdomain. IN SOA ns1.digitalocean.com. hostmaster.testdomain. 1428768671 10800 3600 604800 1800\ntestdomain. 1800 IN NS ns1.digitalocean.com.\ntestdomain. 1800 IN NS ns2.digitalocean.com.\ntestdomain. 1800 IN NS ns3.digitalocean.com.\ntestdomain. 1800 IN A 123.45.67.89\n"}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_NOT_FOUND.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_NOT_FOUND.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_NOT_FOUND.json
new file mode 100644
index 0000000..fa61040
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_NOT_FOUND.json
@@ -0,0 +1 @@
+{"id":"not_found","message":"The resource you were accessing could not be found."}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records.json
new file mode 100644
index 0000000..53093f6
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records.json
@@ -0,0 +1 @@
+{"domain_records":[{"id":1234560,"type":"NS","name":"@","data":"ns1.digitalocean.com","priority":null,"port":null,"weight":null},{"id":1234561,"type":"NS","name":"@","data":"ns2.digitalocean.com","priority":null,"port":null,"weight":null},{"id":1234562,"type":"NS","name":"@","data":"ns3.digitalocean.com","priority":null,"port":null,"weight":null},{"id":1234564,"type":"A","name":"@","data":"123.45.67.89","priority":null,"port":null,"weight":null}],"links":{},"meta":{"total":4}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234560.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234560.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234560.json
new file mode 100644
index 0000000..4e629dd
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234560.json
@@ -0,0 +1 @@
+{"domain_record":{"id":1234560,"type":"NS","name":"@","data":"ns1.digitalocean.com","priority":null,"port":null,"weight":null}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234561.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234561.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234561.json
new file mode 100644
index 0000000..4218337
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234561.json
@@ -0,0 +1 @@
+{"domain_record":{"id":1234561,"type":"NS","name":"@","data":"ns2.digitalocean.com","priority":null,"port":null,"weight":null}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234562.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234562.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234562.json
new file mode 100644
index 0000000..307218d
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234562.json
@@ -0,0 +1 @@
+{"domain_record":{"id":1234563,"type":"NS","name":"@","data":"ns3.digitalocean.com","priority":null,"port":null,"weight":null}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564.json
new file mode 100644
index 0000000..8d34cca
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564.json
@@ -0,0 +1 @@
+{"domain_record":{"id":1234564,"type":"A","name":"@","data":"123.45.67.89","priority":null,"port":null,"weight":null}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_NOT_FOUND.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_NOT_FOUND.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_NOT_FOUND.json
new file mode 100644
index 0000000..fa61040
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_NOT_FOUND.json
@@ -0,0 +1 @@
+{"id":"not_found","message":"The resource you were accessing could not be found."}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_UPDATE.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_UPDATE.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_UPDATE.json
new file mode 100644
index 0000000..8401c43
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_1234564_UPDATE.json
@@ -0,0 +1 @@
+{"domain_record":{"id":1234564,"type":"A","name":"@","data":"234.56.78.90","priority":null,"port":null,"weight":null}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_CREATE.json
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_CREATE.json b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_CREATE.json
new file mode 100644
index 0000000..4c032ab
--- /dev/null
+++ b/libcloud/test/dns/fixtures/digitalocean/_v2_domains_testdomain_records_CREATE.json
@@ -0,0 +1 @@
+{"domain_record":{"id":1234565,"type":"A","name":"sub","data":"234.56.78.90","priority":null,"port":null,"weight":null}}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/dns/test_digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_digitalocean.py b/libcloud/test/dns/test_digitalocean.py
new file mode 100644
index 0000000..7557db0
--- /dev/null
+++ b/libcloud/test/dns/test_digitalocean.py
@@ -0,0 +1,214 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+
+import sys
+import unittest
+
+from libcloud.common.types import InvalidCredsError
+from libcloud.dns.drivers.digitalocean import DigitalOceanDNSDriver
+from libcloud.dns.types import RecordType
+from libcloud.test import LibcloudTestCase, MockHttpTestCase
+from libcloud.test.file_fixtures import DNSFileFixtures
+from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS
+from libcloud.utils.py3 import httplib
+
+
+class DigitalOceanDNSTests(LibcloudTestCase):
+
+    def setUp(self):
+        DigitalOceanDNSDriver.connectionCls.conn_classes = \
+            (None, DigitalOceanDNSMockHttp)
+        DigitalOceanDNSMockHttp.type = None
+        self.driver = DigitalOceanDNSDriver(*DIGITALOCEAN_v2_PARAMS)
+
+    def test_authentication(self):
+        DigitalOceanDNSMockHttp.type = 'UNAUTHORIZED'
+        self.assertRaises(InvalidCredsError, self.driver.list_zones)
+
+    def test_list_zones(self):
+        zones = self.driver.list_zones()
+        self.assertTrue(len(zones) >= 1)
+
+    def test_get_zone(self):
+        zone = self.driver.get_zone('testdomain')
+        self.assertEqual(zone.id, 'testdomain')
+
+    def test_get_zone_not_found(self):
+        DigitalOceanDNSMockHttp.type = 'NOT_FOUND'
+        self.assertRaises(Exception, self.driver.get_zone, 'testdomain')
+
+    def test_list_records(self):
+        zone = self.driver.get_zone('testdomain')
+        records = self.driver.list_records(zone)
+        self.assertTrue(len(records) >= 1)
+
+    def test_get_record(self):
+        record = self.driver.get_record('testdomain', '1234564')
+        self.assertEqual(record.id, '1234564')
+        self.assertEqual(record.type, RecordType.A)
+        self.assertEqual(record.data, '123.45.67.89')
+
+    def test_get_record_not_found(self):
+        DigitalOceanDNSMockHttp.type = 'NOT_FOUND'
+        self.assertRaises(Exception, self.driver.get_zone, 'testdomain')
+
+    def test_create_zone(self):
+        DigitalOceanDNSMockHttp.type = 'CREATE'
+        zone = self.driver.create_zone('testdomain')
+        self.assertEqual(zone.id, 'testdomain')
+
+    def test_create_record(self):
+        zone = self.driver.get_zone('testdomain')
+
+        DigitalOceanDNSMockHttp.type = 'CREATE'
+        record = self.driver.create_record('sub', zone, RecordType.A, '234.56.78.90')
+        self.assertEqual(record.id, '1234565')
+        self.assertEqual(record.type, RecordType.A)
+        self.assertEqual(record.data, '234.56.78.90')
+
+    def test_update_record(self):
+        record = self.driver.get_record('testdomain', '1234564')
+
+        DigitalOceanDNSMockHttp.type = 'UPDATE'
+        record = self.driver.update_record(record, data="234.56.78.90")
+        self.assertEqual(record.id, '1234564')
+        self.assertEqual(record.data, "234.56.78.90")
+
+    def test_delete_zone(self):
+        zone = self.driver.get_zone('testdomain')
+
+        DigitalOceanDNSMockHttp.type = 'DELETE'
+        self.assertTrue(self.driver.delete_zone(zone))
+
+    def test_delete_record(self):
+        record = self.driver.get_record('testdomain', '1234564')
+
+        DigitalOceanDNSMockHttp.type = 'DELETE'
+        self.assertTrue(self.driver.delete_record(record))
+
+
+class DigitalOceanDNSMockHttp(MockHttpTestCase):
+    fixtures = DNSFileFixtures('digitalocean')
+
+    response = {
+        None: httplib.OK,
+        'CREATE': httplib.CREATED,
+        'DELETE': httplib.NO_CONTENT,
+	'EMPTY': httplib.OK,
+        'NOT_FOUND': httplib.NOT_FOUND,
+        'UNAUTHORIZED': httplib.UNAUTHORIZED,
+        'UPDATE': httplib.OK
+    }
+
+    def _v2_domains(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_domains.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_CREATE(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_domains_CREATE.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_EMPTY(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_domains_EMPTY.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_UNAUTHORIZED(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_domains_UNAUTHORIZED.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_domains_testdomain.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_DELETE(self, method, url, body, headers):
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_NOT_FOUND(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_domains_testdomain_NOT_FOUND.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_records(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_domains_testdomain_records.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_records_CREATE(self, method, url, body, headers):
+        body = self.fixtures.load('_v2_domains_testdomain_records_CREATE.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_records_1234560(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+                   '_v2_domains_testdomain_records_1234560.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_records_1234561(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+                   '_v2_domains_testdomain_records_1234561.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_records_1234562(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+                   '_v2_domains_testdomain_records_1234562.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_records_1234563(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+                   '_v2_domains_testdomain_records_1234563.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_records_1234564(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+                   '_v2_domains_testdomain_records_1234564.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_records_1234564_DELETE(
+            self, method, url, body, headers):
+        self.type = 'DELETE'
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_records_1234564_NOT_FOUND(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+                   '_v2_domains_testdomain_records_1234564_NOT_FOUND.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+    def _v2_domains_testdomain_records_1234564_UPDATE(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+                   '_v2_domains_testdomain_records_1234564_UPDATE.json')
+        return (self.response[self.type], body, {},
+                    httplib.responses[self.response[self.type]])
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/a3a5f173/libcloud/test/file_fixtures.py
----------------------------------------------------------------------
diff --git a/libcloud/test/file_fixtures.py b/libcloud/test/file_fixtures.py
index 42e3d36..a09639c 100644
--- a/libcloud/test/file_fixtures.py
+++ b/libcloud/test/file_fixtures.py
@@ -22,6 +22,7 @@ from libcloud.utils.py3 import PY3
 from libcloud.utils.py3 import u
 
 FIXTURES_ROOT = {
+    'common': 'common/fixtures',
     'compute': 'compute/fixtures',
     'storage': 'storage/fixtures',
     'loadbalancer': 'loadbalancer/fixtures',


[16/21] libcloud git commit: DigitalOceanNodeDriver minor revisions - Raise on api_version / key or key-secret mismatch - Added tests for v1 and v2 DigitalOceanNodeDriver using wrong keys - Updated examples to include explicit api_version values - Cleane

Posted by to...@apache.org.
DigitalOceanNodeDriver minor revisions - Raise on api_version / key or key-secret mismatch - Added tests for v1 and v2 DigitalOceanNodeDriver using wrong keys - Updated examples to include explicit api_version values - Cleaned up some whitespace lint - Cleaned up tests

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/fa667636
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/fa667636
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/fa667636

Branch: refs/heads/trunk
Commit: fa667636ed0750c040501a3ff9fc7deac5f6ba94
Parents: 34bff99
Author: jcastillo2nd <j....@gmail.com>
Authored: Thu May 28 14:15:24 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/test/compute/test_digitalocean_v1.py | 2 +-
 libcloud/test/compute/test_digitalocean_v2.py | 2 +-
 libcloud/test/dns/test_digitalocean.py        | 2 --
 3 files changed, 2 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/fa667636/libcloud/test/compute/test_digitalocean_v1.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v1.py b/libcloud/test/compute/test_digitalocean_v1.py
index 0dd0e3c..668e56e 100644
--- a/libcloud/test/compute/test_digitalocean_v1.py
+++ b/libcloud/test/compute/test_digitalocean_v1.py
@@ -44,7 +44,7 @@ class DigitalOcean_v1_Tests(LibcloudTestCase):
 
     def test_v1_uses_v2_key(self):
         self.assertRaises(InvalidCredsError, DigitalOceanNodeDriver,
-            *DIGITALOCEAN_v2_PARAMS, api_version='v1')
+                          *DIGITALOCEAN_v2_PARAMS, api_version='v1')
 
     def test_authentication(self):
         DigitalOceanMockHttp.type = 'UNAUTHORIZED_CLIENT'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/fa667636/libcloud/test/compute/test_digitalocean_v2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v2.py b/libcloud/test/compute/test_digitalocean_v2.py
index 73db2af..03a6425 100644
--- a/libcloud/test/compute/test_digitalocean_v2.py
+++ b/libcloud/test/compute/test_digitalocean_v2.py
@@ -43,7 +43,7 @@ class DigitalOcean_v2_Tests(LibcloudTestCase):
 
     def test_v2_uses_v1_key(self):
         self.assertRaises(InvalidCredsError, DigitalOceanNodeDriver,
-            *DIGITALOCEAN_v1_PARAMS, api_version='v2')
+                          *DIGITALOCEAN_v1_PARAMS, api_version='v2')
 
     def test_authentication(self):
         DigitalOceanMockHttp.type = 'UNAUTHORIZED'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/fa667636/libcloud/test/dns/test_digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_digitalocean.py b/libcloud/test/dns/test_digitalocean.py
index 6a5f222..f1bb92e 100644
--- a/libcloud/test/dns/test_digitalocean.py
+++ b/libcloud/test/dns/test_digitalocean.py
@@ -15,13 +15,11 @@
 import sys
 import unittest
 
-from libcloud.common.types import InvalidCredsError
 from libcloud.dns.drivers.digitalocean import DigitalOceanDNSDriver
 from libcloud.dns.types import RecordType
 from libcloud.test import LibcloudTestCase, MockHttpTestCase
 from libcloud.test.file_fixtures import DNSFileFixtures
 from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS
-from libcloud.test.secrets import DIGITALOCEAN_v1_PARAMS
 from libcloud.utils.py3 import httplib
 
 


[13/21] libcloud git commit: Vultr ssh key implementation - Added ex_ssh_key_ids to create_node - Implemented list_key_pairs with public key retreival

Posted by to...@apache.org.
Vultr ssh key implementation - Added ex_ssh_key_ids to create_node - Implemented list_key_pairs with public key retreival

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/33cbf992
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/33cbf992
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/33cbf992

Branch: refs/heads/trunk
Commit: 33cbf99218f4d884e260ce7fb02f6403dc84efe1
Parents: b70bbbd
Author: jcastillo2nd <j....@gmail.com>
Authored: Thu May 28 18:57:51 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/compute/drivers/vultr.py | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/33cbf992/libcloud/compute/drivers/vultr.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/vultr.py b/libcloud/compute/drivers/vultr.py
index ab47aa0..3823119 100644
--- a/libcloud/compute/drivers/vultr.py
+++ b/libcloud/compute/drivers/vultr.py
@@ -39,6 +39,17 @@ class VultrResponse(JsonResponse):
             raise LibcloudError(self.body)
 
 
+class SSHKey(object):
+    def __init__(self, id, name, pub_key):
+        self.id = id
+        self.name = name
+        self.pub_key = pub_key
+
+    def __repr__(self):
+        return (('<SSHKey: id=%s, name=%s, pub_key=%s>') %
+                (self.id, self.name, self.pub_key))
+
+
 class VultrConnection(ConnectionKey):
     """
     Connection class for the Vultr driver.
@@ -85,6 +96,14 @@ class VultrNodeDriver(NodeDriver):
     def list_nodes(self):
         return self._list_resources('/v1/server/list', self._to_node)
 
+    def list_key_pairs(self):
+        """
+        List all the available SSH keys.
+        :return: Available SSH keys.
+        :rtype: ``list`` of :class:`SSHKey`
+        """
+        return self._list_resources('/v1/sshkey/list', self._to_ssh_key)
+
     def list_locations(self):
         return self._list_resources('/v1/regions/list', self._to_location)
 
@@ -94,10 +113,13 @@ class VultrNodeDriver(NodeDriver):
     def list_images(self):
         return self._list_resources('/v1/os/list', self._to_image)
 
-    def create_node(self, name, size, image, location):
+    def create_node(self, name, size, image, location, ex_ssh_key_ids=None):
         params = {'DCID': location.id, 'VPSPLANID': size.id,
                   'OSID': image.id, 'label': name}
 
+        if ex_ssh_key_ids is not None:
+            params['SSHKEYID'] = ','.join(ex_ssh_key_ids)
+
         result = self.connection.post('/v1/server/create', params)
         if result.status != httplib.OK:
             return False
@@ -182,3 +204,7 @@ class VultrNodeDriver(NodeDriver):
         extra = {'arch': data['arch'], 'family': data['family']}
         return NodeImage(id=data['OSID'], name=data['name'], extra=extra,
                          driver=self)
+
+    def _to_ssh_key(self, data):
+        return SSHKey(id=data['SSHKEYID'], name=data['name'],
+                      pub_key=data['ssh_key'])


[21/21] libcloud git commit: Re-generate supported providers table.

Posted by to...@apache.org.
Re-generate supported providers table.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/ac75a302
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/ac75a302
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/ac75a302

Branch: refs/heads/trunk
Commit: ac75a302daec253d3ea9b45658e8b78252adcd52
Parents: 8952234
Author: Tomaz Muraus <to...@tomaz.me>
Authored: Sun Jun 14 18:18:16 2015 +0800
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:18:16 2015 +0800

----------------------------------------------------------------------
 .../_supported_methods_key_pair_management.rst  |  4 +--
 docs/dns/_supported_methods.rst                 |  2 ++
 docs/dns/_supported_providers.rst               | 30 +++++++++++---------
 3 files changed, 20 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/ac75a302/docs/compute/_supported_methods_key_pair_management.rst
----------------------------------------------------------------------
diff --git a/docs/compute/_supported_methods_key_pair_management.rst b/docs/compute/_supported_methods_key_pair_management.rst
index 646bdc6..f912982 100644
--- a/docs/compute/_supported_methods_key_pair_management.rst
+++ b/docs/compute/_supported_methods_key_pair_management.rst
@@ -10,7 +10,7 @@ Provider                              list key pairs get key pair create key pai
 `CloudSigma (API v2.0)`_              no             no           no              no                            no                          no             
 `CloudStack`_                         yes            yes          yes             yes                           no                          yes            
 `Cloudwatt`_                          yes            yes          yes             yes                           no                          yes            
-`DigitalOcean`_                       yes            no           yes             no                            no                          yes            
+`DigitalOcean`_                       yes            yes          yes             no                            no                          yes            
 `DimensionData`_                      no             no           no              no                            no                          no             
 `Dreamhost`_                          no             no           no              no                            no                          no             
 `Amazon EC2`_                         yes            yes          yes             yes                           no                          yes            
@@ -69,7 +69,7 @@ Provider                              list key pairs get key pair create key pai
 `Voxel VoxCLOUD`_                     no             no           no              no                            no                          no             
 `vps.net`_                            no             no           no              no                            no                          no             
 `VMware vSphere`_                     no             no           no              no                            no                          no             
-`Vultr`_                              no             no           no              no                            no                          no             
+`Vultr`_                              yes            no           no              no                            no                          no             
 ===================================== ============== ============ =============== ============================= =========================== ===============
 
 .. _`Abiquo`: http://www.abiquo.com/

http://git-wip-us.apache.org/repos/asf/libcloud/blob/ac75a302/docs/dns/_supported_methods.rst
----------------------------------------------------------------------
diff --git a/docs/dns/_supported_methods.rst b/docs/dns/_supported_methods.rst
index 507999a..ecc32d1 100644
--- a/docs/dns/_supported_methods.rst
+++ b/docs/dns/_supported_methods.rst
@@ -1,6 +1,7 @@
 ===================== ========== ============ =========== =========== ============= ============= =========== =============
 Provider              list zones list records create zone update zone create record update record delete zone delete record
 ===================== ========== ============ =========== =========== ============= ============= =========== =============
+`DigitalOcean`_       yes        yes          yes         no          yes           yes           yes         yes          
 `Gandi DNS`_          yes        yes          yes         yes         yes           yes           yes         yes          
 `Google DNS`_         yes        yes          yes         no          yes           no            yes         yes          
 `Host Virtual DNS`_   yes        yes          yes         yes         yes           yes           yes         yes          
@@ -13,6 +14,7 @@ Provider              list zones list records create zone update zone create rec
 `Zerigo DNS`_         yes        yes          yes         yes         yes           yes           yes         yes          
 ===================== ========== ============ =========== =========== ============= ============= =========== =============
 
+.. _`DigitalOcean`: https://www.digitalocean.com
 .. _`Gandi DNS`: http://www.gandi.net/domain
 .. _`Google DNS`: https://cloud.google.com/
 .. _`Host Virtual DNS`: https://www.hostvirtual.com/

http://git-wip-us.apache.org/repos/asf/libcloud/blob/ac75a302/docs/dns/_supported_providers.rst
----------------------------------------------------------------------
diff --git a/docs/dns/_supported_providers.rst b/docs/dns/_supported_providers.rst
index 0665a33..cf6d46b 100644
--- a/docs/dns/_supported_providers.rst
+++ b/docs/dns/_supported_providers.rst
@@ -1,18 +1,20 @@
-===================== ======================================= ================= ======================================= =============================
-Provider              Documentation                           Provider constant Module                                  Class Name                   
-===================== ======================================= ================= ======================================= =============================
-`Gandi DNS`_                                                  GANDI             :mod:`libcloud.dns.drivers.gandi`       :class:`GandiDNSDriver`      
-`Google DNS`_                                                 GOOGLE            :mod:`libcloud.dns.drivers.google`      :class:`GoogleDNSDriver`     
-`Host Virtual DNS`_   :doc:`Click </dns/drivers/hostvirtual>` HOSTVIRTUAL       :mod:`libcloud.dns.drivers.hostvirtual` :class:`HostVirtualDNSDriver`
-`Linode DNS`_                                                 LINODE            :mod:`libcloud.dns.drivers.linode`      :class:`LinodeDNSDriver`     
-`Rackspace DNS`_                                              RACKSPACE         :mod:`libcloud.dns.drivers.rackspace`   :class:`RackspaceDNSDriver`  
-`Rackspace DNS (UK)`_                                         RACKSPACE_UK      :mod:`libcloud.dns.drivers.rackspace`   :class:`RackspaceUKDNSDriver`
-`Rackspace DNS (US)`_                                         RACKSPACE_US      :mod:`libcloud.dns.drivers.rackspace`   :class:`RackspaceUSDNSDriver`
-`Route53 DNS`_                                                ROUTE53           :mod:`libcloud.dns.drivers.route53`     :class:`Route53DNSDriver`    
-`Softlayer DNS`_                                              SOFTLAYER         :mod:`libcloud.dns.drivers.softlayer`   :class:`SoftLayerDNSDriver`  
-`Zerigo DNS`_                                                 ZERIGO            :mod:`libcloud.dns.drivers.zerigo`      :class:`ZerigoDNSDriver`     
-===================== ======================================= ================= ======================================= =============================
+===================== ========================================= ================= ======================================== ==============================
+Provider              Documentation                             Provider constant Module                                   Class Name                    
+===================== ========================================= ================= ======================================== ==============================
+`DigitalOcean`_       :doc:`Click </dns/drivers/digital_ocean>` DIGITAL_OCEAN     :mod:`libcloud.dns.drivers.digitalocean` :class:`DigitalOceanDNSDriver`
+`Gandi DNS`_                                                    GANDI             :mod:`libcloud.dns.drivers.gandi`        :class:`GandiDNSDriver`       
+`Google DNS`_                                                   GOOGLE            :mod:`libcloud.dns.drivers.google`       :class:`GoogleDNSDriver`      
+`Host Virtual DNS`_   :doc:`Click </dns/drivers/hostvirtual>`   HOSTVIRTUAL       :mod:`libcloud.dns.drivers.hostvirtual`  :class:`HostVirtualDNSDriver` 
+`Linode DNS`_                                                   LINODE            :mod:`libcloud.dns.drivers.linode`       :class:`LinodeDNSDriver`      
+`Rackspace DNS`_                                                RACKSPACE         :mod:`libcloud.dns.drivers.rackspace`    :class:`RackspaceDNSDriver`   
+`Rackspace DNS (UK)`_                                           RACKSPACE_UK      :mod:`libcloud.dns.drivers.rackspace`    :class:`RackspaceUKDNSDriver` 
+`Rackspace DNS (US)`_                                           RACKSPACE_US      :mod:`libcloud.dns.drivers.rackspace`    :class:`RackspaceUSDNSDriver` 
+`Route53 DNS`_                                                  ROUTE53           :mod:`libcloud.dns.drivers.route53`      :class:`Route53DNSDriver`     
+`Softlayer DNS`_                                                SOFTLAYER         :mod:`libcloud.dns.drivers.softlayer`    :class:`SoftLayerDNSDriver`   
+`Zerigo DNS`_                                                   ZERIGO            :mod:`libcloud.dns.drivers.zerigo`       :class:`ZerigoDNSDriver`      
+===================== ========================================= ================= ======================================== ==============================
 
+.. _`DigitalOcean`: https://www.digitalocean.com
 .. _`Gandi DNS`: http://www.gandi.net/domain
 .. _`Google DNS`: https://cloud.google.com/
 .. _`Host Virtual DNS`: https://www.hostvirtual.com/


[02/21] libcloud git commit: DigitalOceanNodeDriver update - Update v2 Node driver to properly set data instead of parameters for API requests

Posted by to...@apache.org.
DigitalOceanNodeDriver update - Update v2 Node driver to properly set data instead of parameters for API requests

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/b70bbbd0
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/b70bbbd0
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/b70bbbd0

Branch: refs/heads/trunk
Commit: b70bbbd00a8c7a9996f0a09b1e18fd1b2c3aeceb
Parents: c6c8744
Author: jcastillo2nd <j....@gmail.com>
Authored: Thu May 28 18:18:19 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 libcloud/compute/drivers/digitalocean.py | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/b70bbbd0/libcloud/compute/drivers/digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/digitalocean.py b/libcloud/compute/drivers/digitalocean.py
index 0722748..4f86ce6 100644
--- a/libcloud/compute/drivers/digitalocean.py
+++ b/libcloud/compute/drivers/digitalocean.py
@@ -15,6 +15,7 @@
 """
 Digital Ocean Driver
 """
+import json
 import warnings
 
 from libcloud.utils.py3 import httplib
@@ -350,10 +351,10 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
                   'region': location.id}
 
         if ex_ssh_key_ids:
-            params['ssh_key_ids'] = ','.join(ex_ssh_key_ids)
+            params['ssh_keys'] = ex_ssh_key_ids
 
         res = self.connection.request('/v2/droplets',
-                                      params=params, method='POST')
+                                      data=json.dumps(params), method='POST')
 
         data = res.object
         # TODO: Handle this in the response class
@@ -368,7 +369,7 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
     def reboot_node(self, node):
         params = {'type': 'reboot'}
         res = self.connection.request('/v2/droplets/%s/actions' % (node.id),
-                                      params=params, method='POST')
+                                      data=json.dumps(params), method='POST')
         return res.status == httplib.CREATED
 
     def destroy_node(self, node):
@@ -408,7 +409,7 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
         """
         params = {'type': 'snapshot', 'name': name}
         res = self.connection.request('/v2/droplets/%s/actions' % (node.id),
-                                      params=params, method='POST')
+                                      data=json.dumps(params), method='POST')
         return res.status == httplib.CREATED
 
     def delete_image(self, image):
@@ -428,19 +429,19 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
     def ex_rename_node(self, node, name):
         params = {'type': 'rename', 'name': name}
         res = self.connection.request('/v2/droplets/%s/actions' % (node.id),
-                                      params=params, method='POST')
+                                      data=json.dumps(params), method='POST')
         return res.status == httplib.CREATED
 
     def ex_shutdown_node(self, node):
         params = {'type': 'shutdown'}
         res = self.connection.request('/v2/droplets/%s/actions' % (node.id),
-                                      params=params, method='POST')
+                                      data=json.dumps(params), method='POST')
         return res.status == httplib.CREATED
 
     def ex_power_on_node(self, node):
         params = {'type': 'power_on'}
         res = self.connection.request('/v2/droplets/%s/actions' % (node.id),
-                                      params=params, method='POST')
+                                      data=json.dumps(params), method='POST')
         return res.status == httplib.CREATED
 
     def list_key_pairs(self):
@@ -478,8 +479,11 @@ class DigitalOcean_v2_NodeDriver(DigitalOcean_v2_BaseDriver,
         :type       public_key: ``str``
         """
         params = {'name': name, 'public_key': public_key}
-        data = self.connection.request('/v2/account/keys', method='POST',
-                                       params=params).object['ssh_key']
+        res = self.connection.request('/v2/account/keys', method='POST',
+                                      data=json.dumps(params))
+
+        data = res.object['ssh_key']
+
         return self._to_key_pair(data=data)
 
     def delete_key_pair(self, key):


[10/21] libcloud git commit: Merged apache/libcloud trunk - Updated documentation for DigitalOcean regarding locations - Fixed type for DigitalOcean DNS documentation

Posted by to...@apache.org.
Merged apache/libcloud trunk - Updated documentation for DigitalOcean regarding locations - Fixed type for DigitalOcean DNS documentation

Signed-off-by: Tomaz Muraus <to...@tomaz.me>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/fbaaee77
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/fbaaee77
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/fbaaee77

Branch: refs/heads/trunk
Commit: fbaaee77eecfcce4d4a5fd780d765ffa769a6f60
Parents: f451f21
Author: Javier Castillo II <j....@gmail.com>
Authored: Wed Apr 22 18:55:02 2015 +0000
Committer: Tomaz Muraus <to...@tomaz.me>
Committed: Sun Jun 14 18:05:58 2015 +0800

----------------------------------------------------------------------
 docs/compute/drivers/digital_ocean.rst |  6 +++---
 docs/dns/drivers/digital_ocean.rst     | 12 ++++++------
 2 files changed, 9 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/fbaaee77/docs/compute/drivers/digital_ocean.rst
----------------------------------------------------------------------
diff --git a/docs/compute/drivers/digital_ocean.rst b/docs/compute/drivers/digital_ocean.rst
index 67e7ebc..cf0b07e 100644
--- a/docs/compute/drivers/digital_ocean.rst
+++ b/docs/compute/drivers/digital_ocean.rst
@@ -1,9 +1,9 @@
 DigitalOcean Compute Driver Documentation
 =========================================
 
-`DigitalOcean`_ is an American virtual private server provider based in New York
-City with data centers in New York, Amsterdam, San Francisco, London and
-Singapore.
+`DigitalOcean`_ is an American virtual private server provider based in New
+York City with data centers in New York, Amsterdam, San Francisco, London,
+Singapore and Frankfurt.
 
 .. figure:: /_static/images/provider_logos/digitalocean.png
     :align: center

http://git-wip-us.apache.org/repos/asf/libcloud/blob/fbaaee77/docs/dns/drivers/digital_ocean.rst
----------------------------------------------------------------------
diff --git a/docs/dns/drivers/digital_ocean.rst b/docs/dns/drivers/digital_ocean.rst
index b7ec3a6..cc06207 100644
--- a/docs/dns/drivers/digital_ocean.rst
+++ b/docs/dns/drivers/digital_ocean.rst
@@ -1,9 +1,9 @@
-DigitalOcean Compute Driver Documentation
-=========================================
+DigitalOcean DNS Driver Documentation
+=====================================
 
-`DigitalOcean`_ is an American virtual private server provider based in New York
-City with data centers in New York, Amsterdam, San Francisco, London and
-Singapore.
+`DigitalOcean`_ is an American virtual private server provider based in New
+York City with data centers in New York, Amsterdam, San Francisco, London,
+Singapore and Frankfurt.
 
 .. figure:: /_static/images/provider_logos/digitalocean.png
     :align: center
@@ -13,7 +13,7 @@ Singapore.
 Instantiating a driver
 ----------------------
 
-DigitalOcean dns driver supports only the v2.0 API requiring a Personal Access
+DigitalOcean dns driver only supports the v2.0 API requiring a Personal Access
 Token to initialize as the key.
 
 Instantiating the driver