pydo
is the official Python client library that allows
Python developers to interact with and manage their DigitalOcean
resources through a Python abstraction layer on top of the raw
DigitalOcean API HTTP Interface.
A top priority of this project is to ensure the client abides by the API contract. Therefore, the client itself wraps a generated client based on the DigitalOcean OpenAPI Specification to support all of DigitalOcean's HTTP APIs.
To install from pip:
pip install git+https://github.com/digitalocean/pydo.git
or, if repo is cloned locally:
pip install /<PATH>/<TO>/pydo
To install from source:
make install
pydo
QuickstartA quick guide to getting started with the client.
pydo
must be initialized with pydo.Client()
. A DigitalOcean API Token is required. The token can be passed explicitly to pydo.Client()
, as such:
import os
from pydo import Client
client = Client(token=os.getenv("DIGITALOCEAN_TOKEN"))
pydo
to Access DO ResourcesFind below a working example for GETting a ssh_key (per this http request) and printing the ID associated with the ssh key. If you'd like to try out this quick example, you can follow these instructions to add ssh keys to your DO account.
import os
from pydo import Client
client = Client(token=os.getenv("DIGITALOCEAN_TOKEN"))
ssh_keys_resp = client.ssh_keys.list()
for k in ssh_keys_resp["ssh_keys"]:
print(f"ID: {k['id']}, NAME: {k['name']}, FINGERPRINT: {k['fingerprint']}")
The above code snippet should output the following:
ID: 123456, NAME: my_test_ssh_key, FINGERPRINT: 5c:74:7e:60:28:69:34:ca:dd:74:67:c3:f3:00:7f:fe
ID: 123457, NAME: my_prod_ssh_key, FINGERPRINT: eb:76:c7:2a:d3:3e:80:5d:ef:2e:ca:86:d7:79:94:0d
Consult the full list of supported DigitalOcean API endpoints in PyDo's documentation.
Note: More working examples can be found here.
Below is an example on handling pagination. One must parse the URL to find the next page.
resp = self.client.ssh_keys.list(per_page=50, page=page)
pages = resp.links.pages
if 'next' in pages.keys():
parsed_url = urlparse(pages['next'])
page = parse_qs(parsed_url.query)['page'][0]
else:
paginated = False
By default the client uses the same retry policy as the Azure SDK for Python. retry policy. If you'd like to modify any of these values, you can pass them as keywords to your client initialization:
client = Client(token=os.getenv("DIGITALOCEAN_TOKEN"), retry_total=3)
or
client = Client(token=os.getenv("DIGITALOCEAN_TOKEN"), retry_policy=MyRetryPolicy())
Visit our Contribuing Guide for more information on getting involved in developing this client.
The tests included in this repo are used to validate the generated client. We use
pytest
to define and run the tests.
Requirements
There are two types of test suites in the tests/
directory.
tests/mocked/
Tests in the mocked
directory include:
These tests do not act against the real API so no real resources are created.
To run mocked tests, run:
make test-mocked
tests/integration/
Tests in the integration
directory include tests that simulate specific
scenarios a customer might use the client for to interact with the API.
IMPORTANT: these tests require a valid API token and DO create real
resources on the respective DigitalOcean account.
To run integration tests, run:
DIGITALOCEAN_TOKEN=... make test-integration
Some test values can be customized so integration tests can exercise different
scenarios. For example, test use a default region to create resources. All the
default values are managed in the
tests/integration/defaults.py file. Any value
that has environ.get()
can be overwritten by setting the respective environment
variable.
The included Dockerfile is a developler convenience to test the package in isolation.
To use it, first build the image. Run:
docker build -t pydo:dev .
Open the python shell:
docker run -it --rm --name pydo pydo:dev python
The above will launch an interactive python shell and display the following:
Skipping virtualenv creation, as specified in config file.
Python 3.10.5 | packaged by conda-forge | (main, Jun 14 2022, 07:06:46) [GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
From here you can use the client interactively:
>>> from pydo import Client
>>> c = Client(DIGITALOCEAN_TOKEN)
>>> c.droplets.list()
Alternatively, the tests can be run by attaching the tests as a volume and running pytest directly.
Run:
docker run -it --rm --name pydo -v $PWD/tests:/tests pydo:dev pytest tests/mocked
This selection lists the known issues of the client generator.
kubernetes.get_kubeconfig
Does not serialize response contentIn the generated python client, when calling client.kubernetes.get_kubeconfig(clust_id), the deserialization logic raises an error when the response content-type is applicaiton/yaml. We need to determine if the spec/schema can be configured such that the generator results in functions that properly handle the content. We will likely need to report the issue upstream to request support for the content-type.
invoices.get_pdf_by_uuid(invoice_uuid=invoice_uuid_param)
Does not return PDFIn the generated python client, when calling invoices.get_pdf_by_uuid
, the response returns a Iterator[bytes] that does not format correctly into a PDF.
Currently, calling the "help(
This is a backend issue with the API endpoint. The API endpoint expects the header content-type: application/json
to be set. If you do not set it you will receive a 415. Since the endpoint doesn't require a request or response body, it is an unnecessary header. For this to work in Pydo, ensure application/json
header is passed in, as such:
custom_headers = {"Content-Type": "application/json"}
delete_resp = client.projects.delete(
headers=custom_headers, project_id=project_id
)
This section lists short-term and long-term goals for the project. Note: These are goals, not necessarily commitments. The sections are not intended to represent exclusive focus during these terms.
Short term:
Usability, stability, and marketing.
Short term, we are focused on improving usability and user productivity (part of this is getting the word out).
help(<client function>)
documentation solutionLong term:
Model support, expand on supporting functions