Giter Club home page Giter Club logo

python-digitalocean's Introduction

python-digitalocean

Easy access to Digital Ocean APIs to deploy droplets, images and more.

Build Status

Table of Contents

How to install

You can install python-digitalocean using pip

pip install -U python-digitalocean

or via sources:

python setup.py install

⬆ back to top

Configurations

Specify a custom provider using environment variable

export DIGITALOCEAN_END_POINT=http://example.com/

Specify the DIGITALOCEAN_ACCESS_TOKEN using environment variable

export DIGITALOCEAN_ACCESS_TOKEN='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

Note: Probably want to add the export line above to your .bashrc file.

⬆ back to top

Features

python-digitalocean support all the features provided via digitalocean.com APIs, such as:

  • Get user's Projects
  • Assign a resource to a user project
  • List the resources of user's project
  • Get user's Droplets
  • Get user's Images (Snapshot and Backups)
  • Get public Images
  • Get Droplet's event status
  • Create and Remove a Droplet
  • Create or Delete Reserve IP
  • Create, Add and Remove Tags from Droplets
  • Resize a Droplet
  • Shutdown, restart and boot a Droplet
  • Power off, power on and "power cycle" a Droplet
  • Perform Snapshot
  • Enable/Disable automatic Backups
  • Restore root password of a Droplet

⬆ back to top

## Examples

Listing the Projects

This example shows how to list all the projects:

import digitalocean
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
my_projects = manager.get_all_projects()
print(my_projects)

Assign a resource for specific project

import digitalocean
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
my_projects = manager.get_all_projects()
my_projects[0].assign_resource(["do:droplet:<Droplet Number>"])

List all the resources of a project

import digitalocean
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
my_projects = manager.get_all_projects()
resources = my_projects[0].get_all_resources()
print(resources)

Listing the droplets

This example shows how to list all the active droplets:

import digitalocean
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
my_droplets = manager.get_all_droplets()
print(my_droplets)

This example shows how to specify custom provider's end point URL:

import digitalocean
manager = digitalocean.Manager(token="secretspecialuniquesnowflake", end_point="http://example.com/")

⬆ back to top

Listing the droplets by tags

This example shows how to list all the active droplets:

import digitalocean
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
my_droplets = manager.get_all_droplets(tag_name="awesome")
print(my_droplets)

⬆ back to top

Add a tag to a droplet

This example shows how to add a tag to a droplet:

import digitalocean
tag = digitalocean.Tag(token="secretspecialuniquesnowflake", name="tag_name")
tag.create() # create tag if not already created
tag.add_droplets(["DROPLET_ID"])

⬆ back to top

Shutdown all droplets

This example shows how to shutdown all the active droplets:

import digitalocean
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
my_droplets = manager.get_all_droplets()
for droplet in my_droplets:
    droplet.shutdown()

⬆ back to top

Creating a Droplet and checking its status

This example shows how to create a droplet and how to check its status

import digitalocean
droplet = digitalocean.Droplet(token="secretspecialuniquesnowflake",
                               name='Example',
                               region='nyc2', # New York 2
                               image='ubuntu-20-04-x64', # Ubuntu 20.04 x64
                               size_slug='s-1vcpu-1gb',  # 1GB RAM, 1 vCPU
                               backups=True)
droplet.create()

⬆ back to top

Create or Delete Reserved IP

This example shows how to create a reserved ip in specific region and delete it

import digitalocean

floating_ip = digitalocean.FloatingIP(region_slug='nyc2', token="secretspecialuniquesnowflake")
         
# To Create IP
static_ip = floating_ip.reserve()
print(static_ip)

# To Delete IP
release_static_ip = floating_ip.destroy()
print(release_static_ip) # returns True on success
        

⬆ back to top

Checking the status of the droplet

actions = droplet.get_actions()
for action in actions:
    action.load()
    # Once it shows "completed", droplet is up and running
    print(action.status)

⬆ back to top

Listing the Projects

This example shows how to list all the projects:

import digitalocean
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
my_projects = manager.get_all_projects()
print(my_projects)

⬆ back to top

Assign a resource for specific project

import digitalocean
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
my_projects = manager.get_all_projects()
my_projects[0].assign_resource(["do:droplet:<Droplet Number>"])

⬆ back to top

List all the resources of a project

import digitalocean
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
my_projects = manager.get_all_projects()
resources = my_projects[0].get_all_resources()
print(resources)

⬆ back to top

Add SSHKey into DigitalOcean Account

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()

⬆ back to top

Creating a new droplet with all your SSH keys

manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
keys = manager.get_all_sshkeys()

droplet = digitalocean.Droplet(token=manager.token,
                               name='DropletWithSSHKeys',
                               region='ams3', # Amster
                               image='ubuntu-20-04-x64', # Ubuntu 20.04 x64
                               size_slug='s-1vcpu-1gb',  # 1GB RAM, 1 vCPU
                               ssh_keys=keys, #Automatic conversion
                               backups=False)
droplet.create()

⬆ back to top

Creating a Firewall

This example creates a firewall that only accepts inbound tcp traffic on port 80 from a specific load balancer and allows outbound tcp traffic on all ports to all addresses.

from digitalocean import Firewall, InboundRule, OutboundRule, Destinations, Sources

inbound_rule = InboundRule(protocol="tcp", ports="80",
                           sources=Sources(
                               load_balancer_uids=[
                                   "4de7ac8b-495b-4884-9a69-1050c6793cd6"]
                               )
                           )

outbound_rule = OutboundRule(protocol="tcp", ports="all",
                             destinations=Destinations(
                               addresses=[
                                   "0.0.0.0/0",
                                   "::/0"]
                                 )
                             )

firewall = Firewall(token="secretspecialuniquesnowflake",
                    name="new-firewall",
                    inbound_rules=[inbound_rule],
                    outbound_rules=[outbound_rule],
                    droplet_ids=[8043964, 8043972])
firewall.create()

⬆ back to top

Listing the domains

This example shows how to list all the active domains:

import digitalocean
TOKEN="secretspecialuniquesnowflake"
manager = digitalocean.Manager(token=TOKEN)
my_domains = manager.get_all_domains()
print(my_domains)

⬆ back to top

Listing records of a domain

This example shows how to list all records of a domain:

import digitalocean
TOKEN="secretspecialuniquesnowflake"
domain = digitalocean.Domain(token=TOKEN, name="example.com")
records = domain.get_records()
for r in records:
    print(r.name, r.domain, r.type, r.data)

⬆ back to top

Creating a domain record

This example shows how to create new domain record (sub.example.com):

import digitalocean
TOKEN="secretspecialuniquesnowflake"
domain = digitalocean.Domain(token=TOKEN, name="example.com")
new_record =  domain.create_new_domain_record(
                type='A',
                name='sub',
                data='93.184.216.34'
                )
print(new_record)

⬆ back to top

Update a domain record

This example shows how to modify an existing domain record (sub.example.com):

import digitalocean
TOKEN="secretspecialuniquesnowflake"
domain = digitalocean.Domain(token=TOKEN, name="example.com")
records = domain.get_records()
id = None
for r in records:
    if r.name == 'sub':
        r.data = '1.1.1.1'
        r.save()

⬆ back to top

Getting account requests/hour limits status

Each request will also include the rate limit information:

import digitalocean
account = digitalocean.Account(token="secretspecialuniquesnowflake").load()
# or
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
account = manager.get_account()

Output:

droplet_limit: 25
email: '[email protected]'
email_verified: True
end_point: 'https://api.digitalocean.com/v2/'
floating_ip_limit: 3
ratelimit_limit: '5000'
ratelimit_remaining: '4995'
ratelimit_reset: '1505378973'
status: 'active'
status_message: ''
token:'my_secret_token'
uuid: 'my_id'

When using the Manager().get_all.. functions, the rate limit will be stored on the manager object:

import digitalocean
manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
domains = manager.get_all_domains()

print(manager.ratelimit_limit)

⬆ back to top

Session customization

You can take advantage of the requests library and configure the HTTP client under python-digitalocean.

Configure retries in case of connection error

This example shows how to configure your client to retry 3 times in case of ConnectionError:

import digitalocean
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
retry = Retry(connect=3)
adapter = HTTPAdapter(max_retries=retry)
manager._session.mount('https://', adapter)

See Retry object reference to get more details about all retries options.

Configure a hook on specified answer

This example shows how to launch custom actions if a HTTP 500 occurs:

import digitalocean

def handle_response(response, *args, **kwargs):
    if response.status_code == 500:
        # Make a lot things from the raw response
        pass
    return response

manager = digitalocean.Manager(token="secretspecialuniquesnowflake")
manager._session.hooks['response'].append(handle_response)

See event hooks documentation to get more details about this feature.

⬆ back to top

Testing

Test using Docker

To test this python-digitalocean you can use docker to have a clean environment automatically. First you have to build the container by running in your shell on the repository directory:

docker build -t "pdo-tests" .

Then you can run all the tests (for both python 2 and python 3)

docker run pdo-tests

Note: This will use Ubuntu 14.04 as base and use your repository to run tests. So every time you edit some files, please run these commands to perform tests on your changes.

⬆ back to top

Testing using pytest manually

Use pytest to perform testing. It is recommended to use a dedicated virtualenv to perform tests, using these commands:

$ virtualenv /tmp/digitalocean_env
$ source /tmp/digitalocean_env/bin/activate
$ pip install -r requirements.txt

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

$ python -m pytest

⬆ back to top

Links

⬆ back to top

python-digitalocean's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-digitalocean's Issues

Droplet actions do not return an Action object

All the droplet actions (power_on, shutdown, take_snapshot, etc.) return actions. However the corresponding methods in Droplet return raw dictionaries. It might be a better idea to return Action objects instead.

Adding this feature might break backwards compatibility, since some people might depend on the fact that those methods return dictionaries.

I am willing to implement this myself, if you give the go ahead.

API request timeout not handled

It happened to me that API request hanged because I didn't receive any response from DigitalOcean. That was probably a glitch on their side, but such situation should be handled.

It should be simple to set a timeout for each request.
Also, in that case Action.wait() should tolerate some number of timeouts.

Power off droplet automaticly before attempting droplet.take_snapshot()

SInce the droplet snapshot requires the droplet to be off before it can create a snapshot, why not add that in the take_snapshot function?

This would allow us to create a snapshot without first having to check it's status, power it off, and wait for the action to complete before then calling the take_snapshot function separately.

Am I off the mark on this? What are your thoughts?

create with ssh key

does not work to create a droplet with ssh_key id, the error in the wrong ID.
when working with cURL - successfully

Domain.py:29 bug

"droplet" should be "domains" here.

29: setattr(self,attr,droplet[attr])

private networking issue

Hello,

Here is a code snippet I am trying to use to create a droplet:

droplet = digitalocean.Droplet(token=secret,
    name=domain,
    region='sgp1', # Singapore 1
    ssh_keys=[default_key],
    image='centos-6-5-x64', # Centos 6.5 x64
    size_slug='512mb',  # 512MB
    backups=False,
    private_networking=True)

My droplets are created successfully except private networking is always disabled.
I receive no error during droplet creation.

Thanks

Problem creating with ssh key

When attempting to create an instance with ssh-keys, it doesn't seem to work, the instance doesn't get provisioned with the key. v1.0.3

long and unicode not defined in python 3

Since python 3 is supported, it should be noted that long and unicode are not defined in python 3 (u'string literal' still works). This is a problem for __get_ssh_key_id_or_fingerprint in Droplet. A possible solution would be

       try:
            inttype = [int, long]
            strtype = [str, unicode]
        except NameError:
            inttype = [int]
            strtype = [str]

By the way, many of the unit tests fail on python 3.

Erroneous comments in droplet.destroy()

Currently droplet.destroy looks like this

    def destroy(self):
        """
            Destroy the droplet
            Optional Args:
                return_dict - bool : Return a dict when True (default),
                    otherwise return an Action.
            Returns dict or Action
        """
        return self.get_data("droplets/%s" % self.id, type=DELETE)

Either the comments should be corrected to reflect the actual situation (no args accepted), or the function should be changed to accept the optional arg return_dict and return a dict or an Action. Currently it returns a boolean?

InsecurePlatformWarning on OSX 10.10.3

after running manager.get_all_droplets(), I get the following error:

/Library/Python/2.7/site-packages/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning

Delete image url

I got "Exception: The resource you were accessing could not be found." when deleting an image.
The problem is in the v1 type url in Image.py on line 31. In the v2 API docs: To delete an image, send a DELETE request to /v2/images/$IMAGE_ID.
Made local changes and this worked nicely:
def destroy(self):
"""
Destroy the image
"""
return self.get_data(
"images/%s/" % self.id,
type="DELETE",
)

Few "completed" states

Hello. Thanks for your work.

Could you explain why I get 20 times "completed" state:

>>> actions = droplet.get_actions()
>>> for action in actions:
...     action.load()
...     # Once it shows complete, droplet is up and running
...     print action.status
... 
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed

What does these mean?

Thanks!

Add ability to wait for droplet creation/destruction

It would be desirable if there was a way to wait untill droplet creation and destroying are completed.

A good way would be to return an Action in the said functions.
Thus it would be possible to say

droplet.create().wait(5)

or

droplet.destroy.wait(5)

Those are the functions that I have interacted with, there could be more that want the same treatment.

manager.create_droplet() instead of digitalocean.Droplet(client_id, api_key, ...)

The manager already has the client_id and the api_key, why doesn't the manager also handle Droplet creation?

    manager = digitalocean.Manager(client_id="...", api_key="...")
    manager.create_droplet(name='Example',
                               region_id=1,  # New York
                               image_id=2676,  # Ubuntu 12.04 x64 Server
                               size_id=66,  # 512MB
                               backup_active=False)

looks cleaner to me

Change to use json parameter breaks on request < 2.4.2

The json parameter wasn't added to requests until version 2.4.2 So python-digitalocean is currently broken on systems with older versions like Ubuntu 14.04:

$ apt-cache policy python-requests
python-requests:
  Installed: 2.2.1-1ubuntu0.1
  Candidate: 2.2.1-1ubuntu0.1
  Version table:
 *** 2.2.1-1ubuntu0.1 0
        500 http://us.archive.ubuntu.com/ubuntu/ trusty-updates/main amd64 Packages
        500 http://security.ubuntu.com/ubuntu/ trusty-security/main amd64 Packages
        100 /var/lib/dpkg/status
     2.2.1-1 0
        500 http://us.archive.ubuntu.com/ubuntu/ trusty/main amd64 Packages
======================================================================
ERROR: test_take_snapshot_action (digitalocean.tests.test_droplet.TestDroplet)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<string>", line 2, in _wrapper_
  File "/usr/lib/python2.7/dist-packages/responses.py", line 167, in wrapped
    return func(*args, **kwargs)
  File "/home/asb/projects/python-digitalocean/digitalocean/tests/test_droplet.py", line 338, in test_take_snapshot_action
    response = self.droplet.take_snapshot("New Snapshot", return_dict=False)
  File "/home/asb/projects/python-digitalocean/digitalocean/Droplet.py", line 274, in take_snapshot
    return_dict
  File "/home/asb/projects/python-digitalocean/digitalocean/Droplet.py", line 159, in _perform_action
    params=params
  File "/home/asb/projects/python-digitalocean/digitalocean/Droplet.py", line 118, in get_data
    data = super(Droplet, self).get_data(*args, **kwargs)
  File "/home/asb/projects/python-digitalocean/digitalocean/baseapi.py", line 95, in get_data
    req = self.__perform_request(url, type, params)
  File "/home/asb/projects/python-digitalocean/digitalocean/baseapi.py", line 80, in __perform_request
    r = self.__perform_post(url, headers=headers, params=params)
  File "/home/asb/projects/python-digitalocean/digitalocean/baseapi.py", line 48, in __perform_post
    return requests.post(url, headers=headers, json=params)
  File "/usr/lib/python2.7/dist-packages/requests/api.py", line 88, in post
    return request('post', url, data=data, **kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
TypeError: request() got an unexpected keyword argument 'json'

I'm a bit conflicted on this issue as using json instead of query params is definitely the "right" thing to do, but Ubuntu 14.04 is an important target for me personally (https://github.com/andrewsomething/digitalocean-indicator) A more graceful fall back would be best.

issue with droplet.take_snapshot()

droplet.take_snapshot(
    "test-snapshot",
    return_dict=False,
    power_off=True ).wait(update_every_seconds=10)

is causing this:

File "digitalocean/baseapi.py", line 113, in get_data
    raise DataReadError(msg)
digitalocean.baseapi.DataReadError: Droplet is currently on. Please power it off to run this event.

This only just started happening a few days ago, and I can't find any changes that may have caused this.

Methods for retrieving asingle action and droplet by id

Hi!
Im playing with creating a Qt gui using your lib. Great work!
But I would like to have functions to retrieve a single action and droplet instead of having to loop through all of them each time. Or, am I missing something?

Missing attributes in droplet object after creating new droplet

After creating a droplet using the piece of code from the README:

import digitalocean
droplet = digitalocean.Droplet(token="secretspecialuniquesnowflake",
                               name='Example',
                               region='nyc2', # New York 2
                               image='ubuntu-14-04-x64', # Ubuntu 14.04 x64
                               size_slug='512mb',  # 512MB
                               backups=True)
droplet.create()

the response from the API provides data about the just created instance like the id. The id is setted as attribute of the droplet object, as seen here:

https://github.com/koalalorenzo/python-digitalocean/blob/master/digitalocean/Droplet.py#L495

however other attributes are not setted. I find interesting to be able to access to droplet.ip_address at least. Does it make sense that I submit a patch for this? Other attributes could be set too, like memory or ip_v6_address.

More information about returned data at https://developers.digitalocean.com/documentation/v2/#create-a-new-droplet (see Response Body)

Should be able to specify ssh key by fingerprint

When creating a droplet you should be able to give a key fingerprint to Droplet.create(). The current code tries to interpret any string as an actual public key.

Adding an additional check to see if it's a fingerprint, instead of a full public key, after finding a string in Droplet.__get_ssh_keys_id and then directly adding the fingerprint to the id list allows it to work.

Private networking not enabled when requested

Tested this in two regions that offer private networking. The code below reproduces the problem. SSH_KEY_ID is a valid ssh key fingerprint. Droplets are successfully created, but private networking is not enabled.

    new_droplet = Droplet(
            name='newserver',
            size_slug='1gb',
            image='ubuntu-14-04-x64',
            region='nyc2',
            private_networking=True,
            ssh_keys=[SSH_KEY_ID],
            backups_enabled=False,
            token=TOKEN)
    new_droplet.create()

License

Can you add a license.txt file?

cant create droplet with ssh_keys

have you managed to create a droplet with ssh_keys ? like coreos

the examples in the REAME work perfectly for me except when I want to create an image with ssh_keys.

Missing 0.7 tag

Hey,

PyPi has an 0.7 release, but there doesn't seem to be a corresponding tag in git. Could you please tag the appropriate commit (or git push the tag if you just forgot)?

It helps users to know the difference between the latest release on PyPi and git master. That way you can decide whether to install from source or use pip.

Thanks!

TypeError: object.__init__() takes no parameters

In [2]: manager = digitalocean.Manager(token = "XXXXXX")

TypeError Traceback (most recent call last)
in ()
----> 1 manager = digitalocean.Manager(token = "XXXXXX")

/root/python-digitalocean/digitalocean/Manager.py in init(self, _args, *_kwargs)
10 class Manager(BaseAPI):
11 def init(self, _args, *_kwargs):
---> 12 super(Manager, self).init(_args, *_kwargs)
13
14 def get_data(self, _args, *_kwargs):

/root/python-digitalocean/digitalocean/baseapi.py in init(self, _args, *_kwargs)
11
12 def init(self, _args, *_kwargs):
---> 13 super(BaseAPI, self).init(_args, *_kwargs)
14 self.token = ""
15 self.call_response = None

TypeError: object.init() takes no parameters

python -V

Python 2.7.5

went through new modified example posted, call to get_events only returns one object

[crazybill@centos-xx home]# python2.6 new-code.py
Gonna check status in about 10 seconds
Number of events returned by call to droplet.get_events()
1
73

I modified the code to sleep for 10 seconds before calling:
events = droplet.get_events()

I then print the # of events returned on the get_events() call
and print the percentage.

Gonna look deeper to make sure this is not a weird dependency on python build.
Cheers mate.

SSH keys by name

I just came across this library and find it very well put together. There is one feature I would like to see. I would like to create a droplet referencing the ssh key by name. I have several keys stored at DO and add one or several of them to each droplet I create. Using the key name to reference the key just makes sense to me. I will look into what it would take to do this.

wrong url in Record.py for record creation

In API v2 doc: To create a new record to a domain, send a POST request to /v2/domains/$DOMAIN_NAME/records.
So in Record.py line 31 should be:
"domains/%s/records/" % self.domain,

Btw, do you in general prefer issue reports or pull requests for such issues?

Module "re" should be imported in Droplet.py

This one is my fault. I used regular expressions in Droplet.__get_ssh_keys_id_or_fingerprint, but forgot to import re. Just add

import re

to the top of Droplet.py

Note [https://github.com//pull/81] also fixes this issue. But you can add this as a separate commit.

I'm really sorry, this was such a stupid mistake.

Requests is not doing its job (decoding gzip encoded stuff)

The following snippet says it all:

import requests
import zlib

headers = {"Content-Type": "application/json",
... "Authorization": "Bearer "+DIGITALOCEAN_TOKEN}

r = requests.get("https://api.digitalocean.com/v2/account/keys", headers=headers)
print (r.text) # Binary gibberish
u'\x1f\ufffd\x08\x00\x00\x00\x00\x00\x00\x03mR\u066e\ufffd@\x14\ufffd\ufffd\ufffd~\ufffd\x19\ufffd\x06\ufffdNn2(^\x14\ufffd\ufffd\x05\ufffd\ufffdd\ufffdt\ufffd\n\ufffd\u0266h\ufffd\ufffda\ufffdy\ufffd\ufffdIUN\ufffd\ufffd\ufffd\x0bT\ufffd\ufffd\ufffd\ufffdu\x15@?_ \ufffd\x00)P\ufffd<\x1c\ufffdS\ufffd\ufffdYY\ufffdQV\x03\x04h\ufffd\ufffd\ufffd DPA#\x01\x11\x19i<\x12\t\ufffd\x1aR%D)\x12\x05D\x05\ufffd\ufffd(<!\ufffd\ufffd!(\ufffd0\ufffd\ufffd_\ufffd^\u07a7|++\ufffd\ufffd\ufffd3\ufffd\ufffd\x13O\ufffd\ufffd\ufffd\ufffd\x7ft~\ufffd7\u0545\ufffd\ufffd^\x07\ufffd\ufffd(\u04f9f\ufffd\ufffd(\ufffd\x06\u0409oYP\ufffd\ufffd\ufffd\ufffd\ufffd\x10\ufffdR\ufffdu#\ufffd.EM.}>\ufffd\ufffd$\ufffd\ufffd\x0e\ufffd\ufffd:\ufffd5\ufffdz!\ufffd\ufffdd\ufffd\x19\ufffd{\ufffd1ek\ufffd\ufffd\x05\ufffd3w\u04d1_\ufffd{\ufffdc\ufffd\x11f>]\ufffd\ufffdym\ufffd\ufffd\ufffd\u0792\ufffd\ufffd\ufffd\ufffd\x15\ufffd\x14\ufffd\ufffd\u06d6O\ufffd\ufffd/rT\ufffd\ufffd\x13\ufffd\ufffdQ7\ufffd\ufffd|\ufffd|\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\u051et%\x0e\ufffd\ufffd\x02{\ufffd\ufffd\ufffd\ufffd\ufffd\x06\ufffdk\ufffd\x10\ufffd_\ufffd\ufffd\ufffdf\ufffd\x15\ufffd\ufffd\ufffdY\ufffdT\ufffd:[c\ufffd\ufffd\x0bC\ufffd\u02fd2\ufffd\x13\xe8!\ufffd6\u0725\ufffd\x1232\ufffd\ufffd\u02a0\ufffd\u019e\ufffd1~\u06a9\ufffd5\ufffd\ufffdN\ufffd\ufffdAg~\u05b9\ufffdVI\ufffd\x04\ufffd\u2b0e\u0311\ufffd\ufffd5\ufffd}u\ufffd\v\ufffdWp\x0f\ufffd?,\x0f\ufffd\ufffd4\x0e\u072ea\ufffd\ufffd\ufffd=\u0359S\ufffdj\ufffd\ufffd;\ufffdx\ufffd\ufffd\ufffd y\u05b2G\ufffd\ufffd\x1f\ufffd\x14G\ufffdw\ufffd\ufffd}?\x19NY\ufffd\ufffd\ufffd\ufffd\ufffd_C\ufffdD\u0675\x7f\ufffd\ufffd{\x08RV\ufffd\x1e\ufffd:\ufffdq\x02\ufffd\ufffd~\ufffd\x01T\ufffd#\ufffd7\x02\x00\x00'
r.content # Binary gibberish
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03mR\xd9\xae\xa2@\x14\xfc\x95\x9b~\xd5\x19\x96\x06\x81Nn2(^\x14\x95\xc5\x05\xc5\xc9d\xd2t\xb7\n\xb2\xc9\xa6h\xfc\xf7a\xe6y\xce\xc3IUN\xaa\xea\xa1\xce\x0bT\xd5\xe5\xf7\x95u\x15@?_ \xa2\x00)P\x82<\x1c\x82S\x94\x9dYY\x94QV\x03\x04h\x88\xa0\x8c DPA#\x01\x11\x19i<\x12\t\xc2\x1aR%D)\x12\x05D\x05\xa4\xa9(<!\x85\x81!(\x9a0\x89\xc8_\xef^\xde\xa7|++\xfc\xa1\xf73\x86\xf6\x13O\x84\x8e\x88\xd3\x7ft~\xef\xb77\xd5\x85\x8b\x95^\x07\x83\xbd(\xd3\xb9f\xc0\xe7(\xd0\x06\xd0\x89oYP\xe4\xb9\xc2\xf9\xfb\xfc\x10\xedR\xe8u#\xb8.EM.}>\xc6\xce$\x9c\x8d\x0e\xc1\xed:\xad5\xee\xacz!\x9d\xc8d\x99\x19\xb9{\xbc1ek\x8a\xc6\x05\xe3\xb83w\xd3\x91_\xeb{\xb1c\xa4\x11f>]\x96\xf1ym\xca\xde\xf3\xde\x92\xb0\xb1\xa5\xa7\x15\xef\x14\x87\x97\xdb\x96O\x9d\x9d/rT\xa2\xf1\xa2\x13\x85\xbcQ7\xb6\xd9|\xe9\x87|\x99\xa8\xae\xa4\xb1\x95\xd4\x9et%\x0e\xd2\xc3\x02{\xa2\xdb\xf8\xb2\xe9\x06\xe3k\x97\x10\xb9_\x83\x88\x8ef\x92\x15\x84\xba\x91Y\xedT\xf8:[c\xc1\xa5\x0bC\x80\xcb\xbd2\xd8\x13\xc3\xa8!\x966\xdc\xa5\xd8\x1232\xb9\xc5\xca\xa0\xeb\xc6\x9e\x901~\xda\xa9\xee5\xbc\xbcN\xac\xbbAg~\xd6\xb9\xf3\xa2VI\xf2\x9c\x04\x85\xe2\xac\x8e\xcc\x91\xac\xf95\xc8}u\x93\v\xb6Wp\x0f\x9a?,\x0f\x87\xcb4\x0e\xdc\xaea\x99\xfe\xb5=\xcd\x99S\xb5j\xa9\xdc;\xeex\xff\xfc\xfc y\xd6\xb2G\xc5\xea\x1f\xe7\x14G\xc9w\x92\xa7}?\x19NY\xdf\xcc\xff\x8e\xef_C\x90D\xd9\xb5\x7f\x8a\xd7{\x08RV\xe3\x1e\x81:\xafq\x02\x90\xf0~\xff\x01T\xdb#\x867\x02\x00\x00'
print (zlib.decompress(r.content, 16+zlib.MAX_WBITS)) # Decompress and say hello to my public key.
{"ssh_keys":[{"id":734303,"fingerprint":"db:35:33:37:61:c5:90:2c:a9:84:dd:21:d1:98:bf:7e","public_key":"ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA1hJmk++W25dI9D3z6Y9+3OjqnYpoo7/VWoXiUm3Qy63Rr295rV0jaOCbH6XYqkEt9/g8QbdC5cLnDoPZqe7TG2DhaajyGUE6VtAW2yecu1HVdLrjgRG5QzwvcbuN4zJjU7O05vv0mOUV2/d4djKy21ou8SNGuFAXoLl8P49eM4vfA7jYmXKaQ2PuV5GPYBkylc5srYid6H4JYbADnJvE1FgJB1PdKD13LW7+WcDDt3a4S/hpTcGiG/KMDdRuNCcBazNmAQu05RlJwDdHVnyPIpt8clzCYp7OMZeO4JIkYoV8SlhUNQp/xdoxJQabLmjYPyuenAFTfIeOsv8r7wy/Zw== [email protected]","name":"[email protected]"}],"links":{},"meta":{"total":1}}

Here's what's in r.headers (note content-encoding):

{'cache-control': 'max-age=0, private, must-revalidate',
'cf-ray': '1dba5fd98f7a17b6-SIN',
'connection': 'keep-alive',
'content-encoding': 'gzip',
'content-type': 'application/json; charset=utf-8',
'date': 'Thu, 23 Apr 2015 14:49:20 GMT',
'ratelimit-limit': '5000',
'ratelimit-remaining': '4981',
'ratelimit-reset': '1429801676',
'server': 'cloudflare-nginx',
'set-cookie': '__cfduid=d5df7a2d5f73dd12bdd87d2f9cec562c41429800559; expires=Fri, 22-Apr-16 14:49:19 GMT; path=/; domain=.digitalocean.com; HttpOnly',
'status': '200 OK',
'transfer-encoding': 'chunked',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-request-id': 'e8292c02-5fcc-4105-b7e6-4643dca05ac7',
'x-runtime': '0.027317',
'x-xss-protection': '1; mode=block'}

Add a snapshots property to the Droplet class?

Curious if you can add a snapshots property to the Droplet class. I would like to be able to access the snapshots for a specific droplet.

Unless there is a way to do it currently in Manager.get_my_images()

TypeError: 'dict_values' object does not support indexing

I use Python 3.4 in Windows and I got this error while I was trying to list all of user images. Traceback is here:

Traceback (most recent call last):
  File "C:\Users\YusufTuğrul\Desktop\digitalocean.py\digitaloceancli.py", line 216, in <module>
    DigitalOcean().cmdloop()
  File "C:\Python34\lib\cmd.py", line 138, in cmdloop
    stop = self.onecmd(line)
  File "C:\Python34\lib\cmd.py", line 217, in onecmd
    return func(arg)
  File "C:\Users\YusufTuğrul\Desktop\digitalocean.py\digitaloceancli.py", line 204, in do_lsimages
    images = self.manager.get_all_images()
  File "C:\Python34\lib\site-packages\python_digitalocean-1.1-py3.4.egg\digitalocean\Manager.py", line 113, in get_all_images
    data = self.get_data("images/")
  File "C:\Python34\lib\site-packages\python_digitalocean-1.1-py3.4.egg\digitalocean\Manager.py", line 26, in get_data
    unpaged_data = self.__deal_with_pagination(args[0], data, params)
  File "C:\Python34\lib\site-packages\python_digitalocean-1.1-py3.4.egg\digitalocean\Manager.py", line 43, in __deal_with_pagination
    more_values = new_data.values()[0]
TypeError: 'dict_values' object does not support indexing

License Change?

I suppose it's too late to suggest a license change? I would think this library would be much better suited for a Apache, BSD, or LGPL license over the GPL.

I noticed there are several contributers, so a change in license might be tricky, but thought I'd throw it as an idea in case others feel the same.

example code

Hi I tried the sample code, but I believe there are some typos:

// I had to change this to be events.load()
event.load()

Once it shows 100, droplet is up and running

// I had to change this to be events.percentage
print event.percentage

I also tried to fetch new status updates, and was unable to.
I resorted to accomplishing this task using digitalocean.Manager
instead.

record destroy not working correctly, but thyere is a work around.

Having an issue with record.destroy, here is my code:

        manager = digitalocean.Manager(token=args.token)
        my_domains = manager.get_all_domains()
        for domain in my_domains:
            dns = domain.get_records()
            for dr in dns:
                logging.debug("dr domain is %s", dr.domain)
                if args.id:
                    logging.debug("looking for %d in %d:%s", args.id, dr.id, dr.name)
                    if dr.id == args.id:
                        logging.info("deleting the dns record %d, %s", dr.id, dr.name)
                        dr.domain = domain.name
                        dr.destroy()

I looked at the source, the destroy() method needs the self.domain and self.id to prime the digitalocean api. The id is there, but, self.domain is "". In the init method is it set to blank, I didn't look any further because I don't know what is going on there. I could force it to work using the line before the destroy call 'dr.domain = domain.name'.

Access Denied

After installing, and running the following test code:

manager = digitalocean.Manager(token="MYDOTOKEN")
my_droplets = manager.get_all_droplets()

I get an "access denied" message. I can reproduce this error 100% and I cannot get the token to authenticate. Will I need to do something in the DO control panel to allow this app?

Thanks

oh... the call trace may help....

Traceback (most recent call last):
File "C:\Workspace\mypy\src\TestProgram.py", line 22, in
my_droplets = manager.get_all_droplets()
File "C:\Python34\lib\site-packages\digitalocean\Manager.py", line 46, in get_all_droplets
data = self.__call_api("/droplets/")
File "C:\Python34\lib\site-packages\digitalocean\Manager.py", line 24, in __call_api
raise Exception(msg)
Exception: Access Denied

tests break when run the old-fashioned way

python2.7 in a virtualenv

python-digitalocean$ python digitalocean/tests/test_droplet.py 
Traceback (most recent call last):
  File "digitalocean/tests/test_droplet.py", line 7, in <module>
    from .BaseTest import BaseTest
ValueError: Attempted relative import in non-package

Also it would be nice if there was a single test file to run instead of 3 separate ones.

Command line interface

Any plan to have a cli script ? I'm currently working on a script for my own use:-

import os
import baker
import digitalocean

token = open('/Users/kamal/.python-do.rc').read().strip()
manager = digitalocean.Manager(token=token)

@baker.command
def list_droplets():
    my_droplets = manager.get_all_droplets()
    for droplet in my_droplets:
        print droplet

    return my_droplets

def get_droplet(name):
    droplets = list_droplets()
    for droplet in droplets:
        if droplet.name == name:
            return droplet

def poweroff_droplet(name):
    droplet = get_droplet(name)
    confirm = raw_input('Poweroff %s ? [Y/n]' % (name))
    if confirm == 'Y':
        droplet.power_off()

def poweron_droplet(name):
    droplet = get_droplet(name)
    confirm = raw_input('Poweroff %s ? [Y/n]' % (name))
    if confirm == 'Y':
        droplet.power_on()

@baker.command
def resize_droplet(name, size, disk=False):
    droplet = get_droplet(name)
    confirm = raw_input('Resize %s to %s ? [Y/n]' % (name, size))
    if confirm == 'Y':
        droplet.resize(size, disk=disk)

baker.run()

I can make it into proper PR if you're interested.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.