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

Initialized gcloud dns. #71

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
84 changes: 84 additions & 0 deletions gcloud/connection.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import httplib2
import json
import urllib

import exceptions


class Connection(object):
Expand Down Expand Up @@ -42,3 +46,83 @@ def http(self):
self._http = self._credentials.authorize(self._http)
return self._http


class JsonConnection(Connection):

This comment was marked as spam.


API_BASE_URL = 'https://www.googleapis.com'
"""The base of the API call URL."""

_EMPTY = object()
"""A pointer to represent an empty value for default arguments."""

def __init__(self, project=None, *args, **kwargs):

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

self.project = project

def build_api_url(self, path, query_params=None, api_base_url=None,
api_version=None):

url = self.API_URL_TEMPLATE.format(
api_base_url=(api_base_url or self.API_BASE_URL),
api_version=(api_version or self.API_VERSION),
path=path)

query_params = query_params or {}
query_params.update({'project': self.project})
url += '?' + urllib.urlencode(query_params)

return url

def make_request(self, method, url, data=None, content_type=None,
headers=None):

headers = headers or {}
headers['Accept-Encoding'] = 'gzip'

if data:
content_length = len(str(data))
else:
content_length = 0

headers['Content-Length'] = content_length

if content_type:
headers['Content-Type'] = content_type

return self.http.request(uri=url, method=method, headers=headers,
body=data)

def api_request(self, method, path=None, query_params=None,
data=None, content_type=None,
api_base_url=None, api_version=None,
expect_json=True):

url = self.build_api_url(path=path, query_params=query_params,
api_base_url=api_base_url,
api_version=api_version)

# Making the executive decision that any dictionary
# data will be sent properly as JSON.
if data and isinstance(data, dict):
data = json.dumps(data)
content_type = 'application/json'

response, content = self.make_request(
method=method, url=url, data=data, content_type=content_type)

# TODO: Add better error handling.
if response.status == 404:
raise exceptions.NotFoundError(response, content)
elif not 200 <= response.status < 300:
raise exceptions.ConnectionError(response, content)

if content and expect_json:
# TODO: Better checking on this header for JSON.
content_type = response.get('content-type', '')
if not content_type.startswith('application/json'):
raise TypeError('Expected JSON, got %s' % content_type)
return json.loads(content)

return content
21 changes: 21 additions & 0 deletions gcloud/dns/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
__version__ = '0.1'

# TODO: Allow specific scopes and authorization levels.
SCOPE = ('https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/ndev.clouddns.readonly',
'https://www.googleapis.com/auth/ndev.clouddns.readwrite')
"""The scope required for authenticating as a Cloud DNS consumer."""


def get_connection(project, client_email, private_key_path):
from gcloud.credentials import Credentials
from gcloud.dns.connection import Connection

credentials = Credentials.get_for_service_account(
client_email, private_key_path, scope=SCOPE)
return Connection(project=project, credentials=credentials)


def get_zone(zone_name, project, client_email, private_key_path):
connection = get_connection(project, client_email, private_key_path)
return connection.get_zone(zone_name)
82 changes: 82 additions & 0 deletions gcloud/dns/connection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import json

from gcloud import connection
from gcloud.dns.zone import Zone


class Connection(connection.JsonConnection):
API_VERSION = 'v1beta1'
"""The version of the API, used in building the API call's URL."""

API_URL_TEMPLATE = ('{api_base_url}/dns/{api_version}/projects/{path}')
"""A template used to craft the URL pointing toward a particular API call."""

_EMPTY = object()
"""A pointer to represent an empty value for default arguments."""

def __init__(self, project=None, *args, **kwargs):

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

self.project = project

def create_zone(self, data):
zone = self.new_zone(data['name'])
response = self.api_request(method='POST', path=zone.path,
data=data)
return Zone.from_dict(response, connection=self)

def delete_zone(self, zone):
zone = self.new_zone(zone)
self.api_request(method='DELETE', path=zone.path +
zone.name)
return True

def get_zone(self, zone):
zone = self.new_zone(zone)
response = self.api_request(method='GET', path=zone.path)
return Zone.from_dict(response['managedZones'][0],
connection=self)

def list_zones(self):
zone = self.new_zone('test')
response = self.api_request(method='GET', path=zone.path)
print json.dumps(response, indent=2)

def new_zone(self, zone):
if isinstance(zone, Zone):
return zone

# Support Python 2 and 3.
try:
string_type = basestring
except NameError:
string_type = str

if isinstance(zone, string_type):
return Zone(connection=self, name=zone)

def create_changes(self, zone, data):
zone = self.new_zone(zone)
self.api_request(method='POST', path=zone.path + zone.name + '/changes',
data=data)
return True

def new_resource(self, name, type, ttl, rrdatas):
return {'kind': 'dns#resourceRecordSet', 'name': name, 'type': type,
'ttl': ttl, 'rrdatas': rrdatas}

def new_change(self):
return {'kind': "dns#change", 'additions': [], 'deletions': []}

def create_record(self, zone, data):
zone = self.new_zone(zone)
self.api_request(method='POST', path=zone.path + zone.name + '/changes',
data=data)
return True

def list_records(self, zone):
zone = self.new_zone(zone)
response = self.api_request(method='GET',
path=zone.path + zone.name + '/changes')
print json.dumps(response, indent=2)
19 changes: 19 additions & 0 deletions gcloud/dns/demo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os
from gcloud import dns


__all__ = ['get_connection', 'get_zone' 'CLIENT_EMAIL', 'PRIVATE_KEY_PATH',
'PROJECT']


CLIENT_EMAIL = ''
PRIVATE_KEY_PATH = os.path.join(os.path.dirname(__file__), 'demo.key')
PROJECT = ''


def get_connection():
return dns.get_connection(PROJECT, CLIENT_EMAIL, PRIVATE_KEY_PATH)


def get_zone(zone_name):
return dns.get_zone(zone_name, PROJECT, CLIENT_EMAIL, PRIVATE_KEY_PATH)
8 changes: 8 additions & 0 deletions gcloud/dns/demo/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Welcome to the gCloud DNS Demo! (hit enter)

# We're going to walk through some of the basics...,
# Don't worry though. You don't need to do anything, just keep hitting enter...

# Let's start by importing the demo module and getting a connection:
from gcloud.dns import demo
connection = demo.get_connection()
6 changes: 6 additions & 0 deletions gcloud/dns/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from gcloud.exceptions import gcloudError
# TODO: Make these super useful.


class DNSError(gcloudError):
pass
38 changes: 38 additions & 0 deletions gcloud/dns/zone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class Zone(object):

def __init__(self, connection=None, creation_time=None, description=None,
dns_name=None, id=None, kind=None, name=None,
name_servers=None):
self.connection = connection
self.creation_time = creation_time
self.description = description
self.dns_name = dns_name
self.id = id
self.kind = kind
self.name = name
self.name_servers = name_servers

@classmethod
def from_dict(cls, zone_dict, connection=None):

return cls(connection=connection,
creation_time=zone_dict['creationTime'],
description=zone_dict['description'],
dns_name=zone_dict['dnsName'], id=zone_dict['id'],
kind=zone_dict['kind'], name=zone_dict['name'],
name_servers=zone_dict['nameServers'])

@property
def path(self):
"""The URL path to this zone."""

if not self.connection.project:
raise ValueError('Cannot determine path without project name.')

return self.connection.project + '/managedZones/'

def delete(self):
return self.connection.delete_zone(self)

def get(self):
return self.connection.get_zone(self)
18 changes: 18 additions & 0 deletions gcloud/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# TODO: Make these super useful.


class gcloudError(Exception):
pass


class ConnectionError(gcloudError):

def __init__(self, response, content):
message = str(response) + content
super(ConnectionError, self).__init__(message)


class NotFoundError(gcloudError):

def __init__(self, response, content):
self.message = 'GET %s returned a 404.' % (response.url)