Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added DO Database endpoints #292

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 57 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,32 @@

## Table of Contents

- [Table of Contents](#table-of-contents)
- [How to install](#how-to-install)
- [Configurations](#configurations)
- [Features](#features)
- [Features](#features)
- [Examples](#examples)
- [Listing the droplets](#listing-the-droplets)
- [Listing the droplets by tags](#listing-the-droplets-by-tags)
- [Add a tag to a droplet](#add-a-tag-to-a-droplet)
- [Shutdown all droplets](#shutdown-all-droplets)
- [Creating a Droplet and checking its status](#creating-a-droplet-and-checking-its-status)
- [Checking the status of the droplet](#checking-the-status-of-the-droplet)
- [Add SSHKey into DigitalOcean Account](#add-sshkey-into-digitalocean-account)
- [Creating a new droplet with all your SSH keys](#creating-a-new-droplet-with-all-your-ssh-keys)
- [Creating a Firewall](#creating-a-firewall)
- [Listing the domains](#listing-the-domains)
- [Listing records of a domain](#listing-records-of-a-domain)
- [Creating a domain record](#creating-a-domain-record)
- [Update a domain record](#update-a-domain-record)
- [Listing the droplets](#listing-the-droplets)
- [Listing the droplets by tags](#listing-the-droplets-by-tags)
- [Add a tag to a droplet](#add-a-tag-to-a-droplet)
- [Shutdown all droplets](#shutdown-all-droplets)
- [Creating a Droplet and checking its status](#creating-a-droplet-and-checking-its-status)
- [Checking the status of the droplet](#checking-the-status-of-the-droplet)
- [Add SSHKey into DigitalOcean Account](#add-sshkey-into-digitalocean-account)
- [Creating a new droplet with all your SSH keys](#creating-a-new-droplet-with-all-your-ssh-keys)
- [Creating a Firewall](#creating-a-firewall)
- [Get, create, list and destroy database clusters](#get-create-list-and-destroy-database-clusters)
- [Listing the domains](#listing-the-domains)
- [Listing records of a domain](#listing-records-of-a-domain)
- [Creating a domain record](#creating-a-domain-record)
- [Update a domain record](#update-a-domain-record)
- [Getting account requests/hour limits status](#getting-account-requestshour-limits-status)
- [Session customization](#session-customization)
- [Configure retries in case of connection error](#configure-retries-in-case-of-connection-error)
- [Configure a hook on specified answer](#configure-a-hook-on-specified-answer)
- [Testing](#testing)
- [Test using Docker](#test-using-docker)
- [Testing using pytest manually](#testing-using-pytest-manually)
- [Test using Docker](#test-using-docker)
- [Testing using pytest manually](#testing-using-pytest-manually)
- [Links](#links)

## How to install
Expand Down Expand Up @@ -69,6 +73,7 @@ python-digitalocean support all the features provided via digitalocean.com APIs,
* Perform Snapshot
* Enable/Disable automatic Backups
* Restore root password of a Droplet
* Get, create, list, and destroy database clusters

**[⬆ back to top](#table-of-contents)**

Expand Down Expand Up @@ -223,6 +228,42 @@ firewall.create()

**[⬆ back to top](#table-of-contents)**

### Get, create, list and destroy database clusters

This example shows how to get, create, list and destroy database clusters, replicas, databases, and database users:

```python
from digitalocean import Database

db = Database(token=TOKEN)

# Create a database cluster
print(db.create.cluster(name='test-db', engine='mysql', size='db-s-1vcpu-1gb', region='nyc1', num_nodes=1))

# Get a single database clusters
print(db.get.cluster('1e7a4056-9b2c-4ac0-96b1-6119f5ee9f10'))

# List all database clusters
print(db.list.clusters())

# Destroy a database cluster
print(db.destroy.cluster('1e7a4056-9b2c-4ac0-96b1-6119f5ee9f10'))

# Create a database replica
print(db.create.replica('test-db-replica', 'db-s-1vcpu-1gb'))

# Get a database replica
print(db.get.replica('1e7a4056-9b2c-4ac0-96b1-6119f5ee9f10', 'test-db-replica'))

# List all database replicas
print(db.list.replicas('1e7a4056-9b2c-4ac0-96b1-6119f5ee9f10'))

# Destroy a database cluster
print(db.destroy.cluster('1e7a4056-9b2c-4ac0-96b1-6119f5ee9f10', 'test-db-replica'))

# Additionally, you can do the same functionality with databases within a cluster and database users among other features
```

### Listing the domains

This example shows how to list all the active domains:
Expand Down
218 changes: 218 additions & 0 deletions digitalocean/Database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# -*- coding: utf-8 -*-
from .baseapi import BaseAPI, POST, DELETE, PUT

__SIZE_SLUG__ = [
'db-s-1vcpu-1gb',
'db-s-1vcpu-2gb',
'db-s-2vcpu-4gb',
'db-s-4vcpu-8gb',
'db-s-6vcpu-16gb',
'db-s-8vcpu-32gb',
'db-s-16vcpu-64gb'
]

__DB_ENGINES__ = {
'pq': {
koalalorenzo marked this conversation as resolved.
Show resolved Hide resolved
'versions': ['10','11']
},
'mysql': {
'versions': ['8']
},
'redis':{
'versions': ['5']
}
}


class DatabaseCreate(BaseAPI):

def __init__(self, *args, **kwargs):
super(DatabaseCreate, self).__init__(*args, **kwargs)


def cluster(self, name, engine, size, region, num_nodes, version=None, tags=None):
if __DB_ENGINES__[engine]:
params = {
"name": name,
"engine": engine,
"size": size,
"region": region,
"num_nodes": int(num_nodes)
}
if version:
if version in __DB_ENGINES__[engine]['versions']:
params['version'] = version
else:
raise AttributeError('Please provide a valid database version')
if tags and isinstance(tags, list):
params['tags'] = tags

data = self.get_data('databases/', type=POST, params=params)

if data:
return data['database']
else:
return 'Error creating database'

def replica(self, name, size, region=None, tags=None, db_id=None):
params = {}
params['name'] = name
if size in __SIZE_SLUG__:
params['size'] = size
if region:
params['region'] = region
if tags:
params['tags'] = tags

if db_id:
data = self.get_data("databases/{}/replicas".format(db_id), type='POST', params=params)
else:
data = self.get_data("databases/{}/replicas".format(self.id), type='POST', params=params)

if data:
return data['replica']
else:
return 'Error creating replica'

def user(self, name, db_id=None):
params = {}
params['name'] = name

if db_id:
data = self.get_data("databases/{}/users".format(db_id), type='POST', params=params)
else:
data = self.get_data("databases/{}/users".format(self.id), type='POST', params=params)

if data:
return data['users']
else:
return 'Error creating users'

def database(self, name, db_id=None):
params = {}
params['name'] = name

if db_id:
data = self.get_data("databases/{}/dbs".format(db_id), type='POST', params=params)
else:
data = self.get_data("databases/{}/dbs".format(self.id), type='POST', params=params)

if data:
return data['db']
else:
return 'Error creating database'


class DatabaseList(BaseAPI):

def __init__(self, *args, **kwargs):
super(DatabaseList, self).__init__(*args, **kwargs)

def clusters(self, tag_name=None):
if tag_name:
data = self.get_data("databases?tag_name={}".format(tag_name))
else:
data = self.get_data("databases")
return None if not data else data['databases']

def backups(self, db_id):
data = self.get_data("databases/{}/backups".format(db_id))
return None if not data else data['backups']

def replicas(self, db_id):
data = self.get_data("databases/{}/replicas".format(db_id))
return None if not data else data['replicas']

def users(self, db_id):
data = self.get_data("databases/{}/users".format(db_id))
return None if not data else data['users']

def databases(self, db_id):
data = self.get_data("databases/{}/dbs".format(db_id))
return None if not data else data['dbs']


class DatabaseGet(BaseAPI):

def __init__(self, *args, **kwargs):
super(DatabaseGet, self).__init__(*args, **kwargs)

def cluster(self, db_id):
data = self.get_data("databases/{}".format(db_id))
return None if not data else data['database']

def replica(self, db_id, replica_name):
data = self.get_data("databases/{}/replicas/{}".format(db_id, replica_name))
return None if not data else data['replica']

def user(self, db_id, username):
data = self.get_data("databases/{}/users/{}".format(db_id, username))
return None if not data else data['user']


class DatabaseDestroy(BaseAPI):

def __init__(self, *args, **kwargs):
super(DatabaseDestroy, self).__init__(*args, **kwargs)

def cluster(self, db_id):
data = self.get_data("databases/{}".format(db_id), type='DELETE')
return None if not data else True

def replica(self, db_id, replica_name):
data = self.get_data("databases/{}/replicas/{}".format(db_id, replica_name), type='DELETE')
return None if not data else True

def user(self, db_id, username):
data = self.get_data("databases/{}/users/{}".format(db_id, username), type='DELETE')
return None if not data else True

def database(self, db_id, db_name):
data = self.get_data("databases/{}/dbs/{}".format(db_id, db_name), type='DELETE')
return None if not data else True

class Database(BaseAPI):

def __init__(self, *args, **kwargs):
super(Database, self).__init__(*args, **kwargs)
self.args = args
self.kwargs = kwargs
pass

@property
def create(self):
return DatabaseCreate(*self.args, **self.kwargs)

@property
def destroy(self):
return DatabaseDestroy(*self.args, **self.kwargs)

@property
def list(self):
return DatabaseList(*self.args, **self.kwargs)

@property
def get(self):
return DatabaseGet(*self.args, **self.kwargs)

def resize(self, size, num_nodes, db_id):
params = {}
if size in __SIZE_SLUG__:
params['size'] = size
params['num_nodes'] = int(num_nodes)
data = self.get_data('databases/{}/resize'.format(db_id), type='PUT', params=params)
return None if not data else True

def migrate(self, region, db_id):
params = {}
params['region'] = region
data = self.get_data('databases/{}/migrate'.format(db_id), type='PUT', params=params)
return None if not data else True

def maintenance(self, day, hour, db_id):
params = {}
params['day'] = day
params['hour'] = hour
data = self.get_data('databases/{}/maintenance'.format(db_id), type='PUT', params=params)
return None if not data else True

1 change: 1 addition & 0 deletions digitalocean/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@
from .Certificate import Certificate
from .Snapshot import Snapshot
from .Firewall import Firewall, InboundRule, OutboundRule, Destinations, Sources
from .Database import Database