Skip to content

Commit

Permalink
Merge branch 'master' into create-multiple-droplets
Browse files Browse the repository at this point in the history
  • Loading branch information
Georgi Atsev authored Jul 14, 2016
2 parents d5e651d + e4801db commit 67f4044
Show file tree
Hide file tree
Showing 17 changed files with 556 additions and 8 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.pyc
*__pycache__
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ nosetests.xml
MANIFEST

.idea/*

.cache
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ python:
- "2.7"
- "3.4"
install: "pip install -U -r requirements.txt --use-mirrors"
script: py.test
script: python -m pytest
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ WORKDIR /root/python-digitalocean
RUN pip2 install -U -r requirements.txt
RUN pip3 install -U -r requirements.txt

CMD py.test-2.7 ; py.test-3.4
CMD python2 -m pytest ; python3 -m pytest
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,32 @@ for action in actions:
print action.status
```

### Add SSHKey into DigitalOcean Account
```python
from digitalocean import SSHKey

user_ssh_key = open('/home/<$USER>/.ssh/id_rsa.pub').read()
key = SSHKey(token='secretspecialuniquesnowflake',
name='uniquehostname',
public_key=user_ssh_key)
key.create()
```

### Creating a new droplet with all your SSH keys
```python
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
keys = manager.get_all_sshkeys()

droplet = digitalocean.Droplet(token="secretspecialuniquesnowflake",
name='DropletWithSSHKeys',
region='ams3', # Amster
image='ubuntu-14-04-x64', # Ubuntu 14.04 x64
size_slug='512mb', # 512MB
ssh_keys=keys, #Automatic conversion
backups=False)
droplet.create()
```

## Testing

### Test using Docker
Expand All @@ -100,7 +126,7 @@ Use [pytest](http://pytest.org/) to perform testing. It is recommended to use a

To run all the tests manually use py.test command:

$ py.test
$ python -m pytest


## Links
Expand Down
28 changes: 24 additions & 4 deletions digitalocean/Manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from urllib.parse import urlparse, parse_qs

from .baseapi import BaseAPI
from .baseapi import GET
from .Droplet import Droplet
from .Region import Region
from .Size import Size
Expand All @@ -14,7 +15,7 @@
from .Action import Action
from .Account import Account
from .FloatingIP import FloatingIP

from .Volume import Volume

class Manager(BaseAPI):
def __init__(self, *args, **kwargs):
Expand All @@ -36,9 +37,10 @@ def get_data(self, *args, **kwargs):

kwargs["params"] = params
data = super(Manager, self).get_data(*args, **kwargs)
unpaged_data = self.__deal_with_pagination(args[0], data, params)

return unpaged_data
if kwargs.get('type') == GET:
return self.__deal_with_pagination(args[0], data, params)
else:
return data

def __deal_with_pagination(self, url, data, params):
"""
Expand Down Expand Up @@ -266,5 +268,23 @@ def get_floating_ip(self, ip):
"""
return FloatingIP.get_object(api_token=self.token, ip=ip)

def get_all_volumes(self):
"""
This function returns a list of Volume objects.
"""
data = self.get_data("volumes")
volumes = list()
for jsoned in data['volumes']:
volume = Volume(**jsoned)
volume.token = self.token
volumes.append(volume)
return volumes

def get_volume(self, volume_id):
"""
Returns a Volume object by its ID.
"""
return Volume.get_object(api_token=self.token, volume_id=volume_id)

def __str__(self):
return "%s" % (self.token)
2 changes: 1 addition & 1 deletion digitalocean/SSHKey.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def load(self):
Requires either self.id or self.fingerprint to be set.
"""
identifier = None
if self.id is not None:
if self.id:
identifier = self.id
elif self.fingerprint is not None:
identifier = self.fingerprint
Expand Down
122 changes: 122 additions & 0 deletions digitalocean/Volume.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# -*- coding: utf-8 -*-
from .baseapi import BaseAPI, POST, DELETE


class Volume(BaseAPI):
def __init__(self, *args, **kwargs):
self.id = None
self.name = None
self.droplet_ids = []
self.region = None
self.description = None
self.size_gigabytes = None
self.created_at = None

super(Volume, self).__init__(*args, **kwargs)

@classmethod
def get_object(cls, api_token, volume_id):
"""
Class method that will return an Volume object by ID.
"""
volume = cls(token=api_token, id=volume_id)
volume.load()
return volume

def load(self):
data = self.get_data("volumes/%s" % self.id)
volume_dict = data['volume']

# Setting the attribute values
for attr in volume_dict.keys():
setattr(self, attr, volume_dict[attr])

return self

def create(self, *args, **kwargs):
"""
Creates a Block Storage volume
Note: Every argument and parameter given to this method will be
assigned to the object.
Args:
name: string - a name for the volume
region: string - slug identifier for the region
size_gigabytes: int - size of the Block Storage volume in GiB
Optional Args:
description: string - text field to describe a volume
"""
data = self.get_data('volumes/',
type=POST,
params={'name': self.name,
'region': self.region,
'size_gigabytes': self.size_gigabytes,
'description': self.description})

if data:
self.id = data['volume']['id']
self.created_at = data['volume']['created_at']

return self

def destroy(self):
"""
Destroy a volume
"""
return self.get_data("volumes/%s/" % self.id, type=DELETE)

def attach(self, droplet_id, region):
"""
Attach a Volume to a Droplet.
Args:
droplet_id: int - droplet id
region: string - slug identifier for the region
"""
return self.get_data(
"volumes/%s/actions/" % self.id,
type=POST,
params={"type": "attach",
"droplet_id": droplet_id,
"region": region}
)

def detach(self, droplet_id, region):
"""
Detach a Volume to a Droplet.
Args:
droplet_id: int - droplet id
region: string - slug identifier for the region
"""
return self.get_data(
"volumes/%s/actions/" % self.id,
type=POST,
params={"type": "detach",
"droplet_id": droplet_id,
"region": region}
)

def resize(self, size_gigabytes, region):
"""
Detach a Volume to a Droplet.
Args:
size_gigabytes: int - size of the Block Storage volume in GiB
region: string - slug identifier for the region
"""
return self.get_data(
"volumes/%s/actions/" % self.id,
type=POST,
params={"type": "resize",
"size_gigabytes": size_gigabytes,
"region": region}
)

def __str__(self):
return "%s %s %s" % (self.id, self.name, self.size_gigabytes)

def __repr__(self):
return "< %s %s %s >" % (self.id, self.name, self.size_gigabytes)
1 change: 1 addition & 0 deletions digitalocean/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@
from .SSHKey import SSHKey
from .Kernel import Kernel
from .FloatingIP import FloatingIP
from .Volume import Volume
from .baseapi import Error, TokenError, DataReadError
8 changes: 8 additions & 0 deletions digitalocean/tests/data/keys/newly_posted.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"ssh_key": {
"id": 1234,
"fingerprint": "ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff",
"public_key": "AAAAkey",
"name": "new_key"
}
}
73 changes: 73 additions & 0 deletions digitalocean/tests/data/volumes/all.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"volumes": [
{
"id": "506f78a4-e098-11e5-ad9f-000f53306ae1",
"region": {
"name": "New York 1",
"slug": "nyc1",
"sizes": [
"512mb",
"1gb",
"2gb",
"4gb",
"8gb",
"16gb",
"32gb",
"48gb",
"64gb"
],
"features": [
"private_networking",
"backups",
"ipv6",
"metadata"
],
"available": true
},
"droplet_ids": [

],
"name": "example",
"description": "Block store for examples",
"size_gigabytes": 100,
"created_at": "2016-03-02T17:00:49Z"
},
{
"id": "2d2967ff-491d-11e6-860c-000f53315870",
"region": {
"name": "New York 1",
"slug": "nyc1",
"sizes": [
"512mb",
"1gb",
"2gb",
"4gb",
"8gb",
"16gb",
"32gb",
"48gb",
"64gb"
],
"features": [
"private_networking",
"backups",
"ipv6",
"metadata"
],
"available": true
},
"droplet_ids": [
19486237
],
"name": "another-example",
"description": "A bigger example volume",
"size_gigabytes": 500,
"created_at": "2016-03-05T17:00:49Z"
}
],
"links": {
},
"meta": {
"total": 2
}
}
34 changes: 34 additions & 0 deletions digitalocean/tests/data/volumes/attach.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"action": {
"id": 72531856,
"status": "completed",
"type": "attach_volume",
"started_at": "2015-11-12T17:51:03Z",
"completed_at": "2015-11-12T17:51:14Z",
"resource_id": null,
"resource_type": "volume",
"region": {
"name": "New York 1",
"slug": "nyc1",
"sizes": [
"1gb",
"2gb",
"4gb",
"8gb",
"32gb",
"64gb",
"512mb",
"48gb",
"16gb"
],
"features": [
"private_networking",
"backups",
"ipv6",
"metadata"
],
"available": true
},
"region_slug": "nyc1"
}
}
Loading

0 comments on commit 67f4044

Please sign in to comment.