Updated DB_Helper by adding firebase methods.

This commit is contained in:
Batuhan Berk Başoğlu 2020-10-05 16:53:40 -04:00
parent 485cc3bbba
commit c82121d036
1810 changed files with 537281 additions and 1 deletions

View file

@ -0,0 +1,33 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Google Cloud DNS API wrapper.
The main concepts with this API are:
- :class:`gcloud.DNS.zone.ManagedZone` represents an collection of tables.
- :class:`gcloud.DNS.resource_record_set.ResourceRecordSet` represents a
single resource definition within a zone.
- :class:`gcloud.DNS.changes.Changes` represents a set of changes (adding/
deleting resource record sets) to a zone.
"""
from gcloud.dns.zone import Changes
from gcloud.dns.client import Client
from gcloud.dns.connection import Connection
from gcloud.dns.zone import ManagedZone
from gcloud.dns.resource_record_set import ResourceRecordSet
SCOPE = Connection.SCOPE

View file

@ -0,0 +1,256 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Define API ResourceRecordSets."""
import six
from gcloud._helpers import _rfc3339_to_datetime
from gcloud.exceptions import NotFound
from gcloud.dns.resource_record_set import ResourceRecordSet
class Changes(object):
"""Changes are bundled additions / deletions of DNS resource records.
Changes are owned by a :class:`gcloud.dns.zone.ManagedZone` instance.
See:
https://cloud.google.com/dns/api/v1/changes
:type zone: :class:`gcloud.dns.zone.ManagedZone`
:param zone: A zone which holds one or more record sets.
"""
def __init__(self, zone):
self.zone = zone
self._properties = {}
self._additions = self._deletions = ()
@classmethod
def from_api_repr(cls, resource, zone):
"""Factory: construct a change set given its API representation
:type resource: dict
:param resource: change set representation returned from the API
:type zone: :class:`gcloud.dns.zone.ManagedZone`
:param zone: A zone which holds zero or more change sets.
:rtype: :class:`gcloud.dns.changes.Changes`
:returns: RRS parsed from ``resource``.
"""
changes = cls(zone=zone)
changes._set_properties(resource)
return changes
def _set_properties(self, resource):
"""Helper method for :meth:`from_api_repr`, :meth:`create`, etc.
:type resource: dict
:param resource: change set representation returned from the API
"""
resource = resource.copy()
self._additions = tuple([
ResourceRecordSet.from_api_repr(added_res, self.zone)
for added_res in resource.pop('additions', ())])
self._deletions = tuple([
ResourceRecordSet.from_api_repr(added_res, self.zone)
for added_res in resource.pop('deletions', ())])
self._properties = resource
@property
def path(self):
"""URL path for change set APIs.
:rtype: string
:returns: the path based on project, zone, and change set names.
"""
return '/projects/%s/managedZones/%s/changes/%s' % (
self.zone.project, self.zone.name, self.name)
@property
def name(self):
"""Name of the change set.
:rtype: string or ``NoneType``
:returns: Name, as set by the back-end, or None.
"""
return self._properties.get('id')
@name.setter
def name(self, value):
"""Update name of the change set.
:type value: string
:param value: New name for the changeset.
"""
if not isinstance(value, six.string_types):
raise ValueError("Pass a string")
self._properties['id'] = value
@property
def status(self):
"""Status of the change set.
:rtype: string or ``NoneType``
:returns: Status, as set by the back-end, or None.
"""
return self._properties.get('status')
@property
def started(self):
"""Time when the change set was started.
:rtype: ``datetime.datetime`` or ``NoneType``
:returns: Time, as set by the back-end, or None.
"""
stamp = self._properties.get('startTime')
if stamp is not None:
return _rfc3339_to_datetime(stamp)
@property
def additions(self):
"""Resource record sets to be added to the zone.
:rtype: sequence of
:class:`gcloud.dns.resource_record_set.ResourceRecordSet`.
:returns: record sets appended via :meth:`add_record_set`
"""
return self._additions
@property
def deletions(self):
"""Resource record sets to be deleted from the zone.
:rtype: sequence of
:class:`gcloud.dns.resource_record_set.ResourceRecordSet`.
:returns: record sets appended via :meth:`delete_record_set`
"""
return self._deletions
def add_record_set(self, record_set):
"""Append a record set to the 'additions' for the change set.
:type record_set:
:class:`gcloud.dns.resource_record_set.ResourceRecordSet`
:param record_set: the record set to append
:raises: ``ValueError`` if ``record_set`` is not of the required type.
"""
if not isinstance(record_set, ResourceRecordSet):
raise ValueError("Pass a ResourceRecordSet")
self._additions += (record_set,)
def delete_record_set(self, record_set):
"""Append a record set to the 'deletions' for the change set.
:type record_set:
:class:`gcloud.dns.resource_record_set.ResourceRecordSet`
:param record_set: the record set to append
:raises: ``ValueError`` if ``record_set`` is not of the required type.
"""
if not isinstance(record_set, ResourceRecordSet):
raise ValueError("Pass a ResourceRecordSet")
self._deletions += (record_set,)
def _require_client(self, client):
"""Check client or verify over-ride.
:type client: :class:`gcloud.dns.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current zone.
:rtype: :class:`gcloud.dns.client.Client`
:returns: The client passed in or the currently bound client.
"""
if client is None:
client = self.zone._client
return client
def _build_resource(self):
"""Generate a resource for ``create``."""
additions = [{
'name': added.name,
'type': added.record_type,
'ttl': str(added.ttl),
'rrdatas': added.rrdatas,
} for added in self.additions]
deletions = [{
'name': deleted.name,
'type': deleted.record_type,
'ttl': str(deleted.ttl),
'rrdatas': deleted.rrdatas,
} for deleted in self.deletions]
return {
'additions': additions,
'deletions': deletions,
}
def create(self, client=None):
"""API call: create the change set via a POST request
See:
https://cloud.google.com/dns/api/v1/changes/create
:type client: :class:`gcloud.dns.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current zone.
"""
if len(self.additions) == 0 and len(self.deletions) == 0:
raise ValueError("No record sets added or deleted")
client = self._require_client(client)
path = '/projects/%s/managedZones/%s/changes' % (
self.zone.project, self.zone.name)
api_response = client.connection.api_request(
method='POST', path=path, data=self._build_resource())
self._set_properties(api_response)
def exists(self, client=None):
"""API call: test for the existence of the change set via a GET request
See
https://cloud.google.com/dns/api/v1/changes/get
:type client: :class:`gcloud.dns.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current zone.
"""
client = self._require_client(client)
try:
client.connection.api_request(method='GET', path=self.path,
query_params={'fields': 'id'})
except NotFound:
return False
else:
return True
def reload(self, client=None):
"""API call: refresh zone properties via a GET request
See
https://cloud.google.com/dns/api/v1/changes/get
:type client: :class:`gcloud.dns.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current zone.
"""
client = self._require_client(client)
api_response = client.connection.api_request(
method='GET', path=self.path)
self._set_properties(api_response)

View file

@ -0,0 +1,116 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Client for interacting with the Google Cloud DNS API."""
from gcloud.client import JSONClient
from gcloud.dns.connection import Connection
from gcloud.dns.zone import ManagedZone
class Client(JSONClient):
"""Client to bundle configuration needed for API requests.
:type project: string
:param project: the project which the client acts on behalf of. Will be
passed when creating a zone. If not passed,
falls back to the default inferred from the environment.
:type credentials: :class:`oauth2client.client.OAuth2Credentials` or
:class:`NoneType`
:param credentials: The OAuth2 Credentials to use for the connection
owned by this client. If not passed (and if no ``http``
object is passed), falls back to the default inferred
from the environment.
:type http: :class:`httplib2.Http` or class that defines ``request()``.
:param http: An optional HTTP object to make requests. If not passed, an
``http`` object is created that is bound to the
``credentials`` for the current object.
"""
_connection_class = Connection
def quotas(self):
"""Return DNS quots for the project associated with this client.
See:
https://cloud.google.com/dns/api/v1/projects/get
:rtype: mapping
:returns: keys for the mapping correspond to those of the ``quota``
sub-mapping of the project resource.
"""
path = '/projects/%s' % (self.project,)
resp = self.connection.api_request(method='GET', path=path)
return dict([(key, int(value))
for key, value in resp['quota'].items() if key != 'kind'])
def list_zones(self, max_results=None, page_token=None):
"""List zones for the project associated with this client.
See:
https://cloud.google.com/dns/api/v1/managedZones/list
:type max_results: int
:param max_results: maximum number of zones to return, If not
passed, defaults to a value set by the API.
:type page_token: string
:param page_token: opaque marker for the next "page" of zones. If
not passed, the API will return the first page of
zones.
:rtype: tuple, (list, str)
:returns: list of :class:`gcloud.dns.zone.ManagedZone`, plus a
"next page token" string: if the token is not None,
indicates that more zones can be retrieved with another
call (pass that value as ``page_token``).
"""
params = {}
if max_results is not None:
params['maxResults'] = max_results
if page_token is not None:
params['pageToken'] = page_token
path = '/projects/%s/managedZones' % (self.project,)
resp = self.connection.api_request(method='GET', path=path,
query_params=params)
zones = [ManagedZone.from_api_repr(resource, self)
for resource in resp['managedZones']]
return zones, resp.get('nextPageToken')
def zone(self, name, dns_name=None, description=None):
"""Construct a zone bound to this client.
:type name: string
:param name: Name of the zone.
:type dns_name: string or :class:`NoneType`
:param dns_name: DNS name of the zone. If not passed, then calls
to :meth:`zone.create` will fail.
:type description: string or :class:`NoneType`
:param description: the description for the zone. If not passed,
defaults to the value of 'dns_name'.
:rtype: :class:`gcloud.dns.zone.ManagedZone`
:returns: a new ``ManagedZone`` instance
"""
return ManagedZone(name, dns_name, client=self,
description=description)

View file

@ -0,0 +1,33 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Create / interact with gcloud dns connections."""
from gcloud import connection as base_connection
class Connection(base_connection.JSONConnection):
"""A connection to Google Cloud DNS via the JSON REST API."""
API_BASE_URL = 'https://www.googleapis.com'
"""The base of the API call URL."""
API_VERSION = 'v1'
"""The version of the API, used in building the API call's URL."""
API_URL_TEMPLATE = '{api_base_url}/dns/{api_version}{path}'
"""A template for the URL of a particular API call."""
SCOPE = ('https://www.googleapis.com/auth/ndev.clouddns.readwrite',)
"""The scopes required for authenticating as a Cloud DNS consumer."""

View file

@ -0,0 +1,66 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Define API ResourceRecordSets."""
class ResourceRecordSet(object):
"""ResourceRecordSets are DNS resource records.
RRS are owned by a :class:`gcloud.dns.zone.ManagedZone` instance.
See:
https://cloud.google.com/dns/api/v1/resourceRecordSets
:type name: string
:param name: the name of the record set
:type record_type: string
:param record_type: the RR type of the zone
:type ttl: integer
:param ttl: TTL (in seconds) for caching the record sets
:type rrdatas: list of string
:param rrdatas: one or more lines containing the resource data
:type zone: :class:`gcloud.dns.zone.ManagedZone`
:param zone: A zone which holds one or more record sets.
"""
def __init__(self, name, record_type, ttl, rrdatas, zone):
self.name = name
self.record_type = record_type
self.ttl = ttl
self.rrdatas = rrdatas
self.zone = zone
@classmethod
def from_api_repr(cls, resource, zone):
"""Factory: construct a record set given its API representation
:type resource: dict
:param resource: record sets representation returned from the API
:type zone: :class:`gcloud.dns.zone.ManagedZone`
:param zone: A zone which holds one or more record sets.
:rtype: :class:`gcloud.dns.zone.ResourceRecordSet`
:returns: RRS parsed from ``resource``.
"""
name = resource['name']
record_type = resource['type']
ttl = int(resource['ttl'])
rrdatas = resource['rrdatas']
return cls(name, record_type, ttl, rrdatas, zone=zone)

View file

@ -0,0 +1,344 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest2
class TestChanges(unittest2.TestCase):
PROJECT = 'project'
ZONE_NAME = 'example.com'
CHANGES_NAME = 'changeset_id'
def _getTargetClass(self):
from gcloud.dns.changes import Changes
return Changes
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def _setUpConstants(self):
from gcloud._helpers import UTC
from gcloud._helpers import _NOW
self.WHEN = _NOW().replace(tzinfo=UTC)
def _makeResource(self):
from gcloud._helpers import _datetime_to_rfc3339
when_str = _datetime_to_rfc3339(self.WHEN)
return {
'kind': 'dns#change',
'id': self.CHANGES_NAME,
'startTime': when_str,
'status': 'done',
'additions': [
{'name': 'test.example.com',
'type': 'CNAME',
'ttl': '3600',
'rrdatas': ['www.example.com']},
],
'deletions': [
{'name': 'test.example.com',
'type': 'CNAME',
'ttl': '86400',
'rrdatas': ['other.example.com']},
],
}
def _verifyResourceProperties(self, changes, resource, zone):
from gcloud._helpers import _rfc3339_to_datetime
from gcloud._helpers import UTC
self.assertEqual(changes.name, resource['id'])
started = _rfc3339_to_datetime(resource['startTime'])
self.assertEqual(changes.started, started)
self.assertEqual(changes.status, resource['status'])
r_additions = resource.get('additions', ())
self.assertEqual(len(changes.additions), len(r_additions))
for found, expected in zip(changes.additions, r_additions):
self.assertEqual(found.name, expected['name'])
self.assertEqual(found.record_type, expected['type'])
self.assertEqual(found.ttl, int(expected['ttl']))
self.assertEqual(found.rrdatas, expected['rrdatas'])
self.assertTrue(found.zone is zone)
r_deletions = resource.get('deletions', ())
self.assertEqual(len(changes.deletions), len(r_deletions))
for found, expected in zip(changes.deletions, r_deletions):
self.assertEqual(found.name, expected['name'])
self.assertEqual(found.record_type, expected['type'])
self.assertEqual(found.ttl, int(expected['ttl']))
self.assertEqual(found.rrdatas, expected['rrdatas'])
self.assertTrue(found.zone is zone)
def test_ctor(self):
zone = _Zone()
changes = self._makeOne(zone)
self.assertTrue(changes.zone is zone)
self.assertEqual(changes.name, None)
self.assertEqual(changes.status, None)
self.assertEqual(changes.started, None)
self.assertEqual(list(changes.additions), [])
self.assertEqual(list(changes.deletions), [])
def test_from_api_repr_missing_additions_deletions(self):
self._setUpConstants()
RESOURCE = self._makeResource()
del RESOURCE['additions']
del RESOURCE['deletions']
zone = _Zone()
klass = self._getTargetClass()
changes = klass.from_api_repr(RESOURCE, zone=zone)
self._verifyResourceProperties(changes, RESOURCE, zone)
def test_from_api_repr(self):
self._setUpConstants()
RESOURCE = self._makeResource()
zone = _Zone()
klass = self._getTargetClass()
changes = klass.from_api_repr(RESOURCE, zone=zone)
self._verifyResourceProperties(changes, RESOURCE, zone)
def test_name_setter_bad_value(self):
zone = _Zone()
changes = self._makeOne(zone)
with self.assertRaises(ValueError):
changes.name = 12345
def test_name_setter(self):
zone = _Zone()
changes = self._makeOne(zone)
changes.name = 'NAME'
self.assertEqual(changes.name, 'NAME')
def test_add_record_set_invalid_value(self):
zone = _Zone()
changes = self._makeOne(zone)
with self.assertRaises(ValueError):
changes.add_record_set(object())
def test_add_record_set(self):
from gcloud.dns.resource_record_set import ResourceRecordSet
zone = _Zone()
changes = self._makeOne(zone)
rrs = ResourceRecordSet('test.example.com', 'CNAME', 3600,
['www.example.com'], zone)
changes.add_record_set(rrs)
self.assertEqual(list(changes.additions), [rrs])
def test_delete_record_set_invalid_value(self):
zone = _Zone()
changes = self._makeOne(zone)
with self.assertRaises(ValueError):
changes.delete_record_set(object())
def test_delete_record_set(self):
from gcloud.dns.resource_record_set import ResourceRecordSet
zone = _Zone()
changes = self._makeOne(zone)
rrs = ResourceRecordSet('test.example.com', 'CNAME', 3600,
['www.example.com'], zone)
changes.delete_record_set(rrs)
self.assertEqual(list(changes.deletions), [rrs])
def test_create_wo_additions_or_deletions(self):
self._setUpConstants()
RESOURCE = self._makeResource()
conn = _Connection(RESOURCE)
client = _Client(project=self.PROJECT, connection=conn)
zone = _Zone(client)
changes = self._makeOne(zone)
with self.assertRaises(ValueError):
changes.create()
self.assertEqual(len(conn._requested), 0)
def test_create_w_bound_client(self):
from gcloud.dns.resource_record_set import ResourceRecordSet
self._setUpConstants()
RESOURCE = self._makeResource()
PATH = 'projects/%s/managedZones/%s/changes' % (
self.PROJECT, self.ZONE_NAME)
conn = _Connection(RESOURCE)
client = _Client(project=self.PROJECT, connection=conn)
zone = _Zone(client)
changes = self._makeOne(zone)
changes.add_record_set(ResourceRecordSet(
'test.example.com', 'CNAME', 3600, ['www.example.com'], zone))
changes.delete_record_set(ResourceRecordSet(
'test.example.com', 'CNAME', 86400, ['other.example.com'], zone))
changes.create()
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'POST')
self.assertEqual(req['path'], '/%s' % PATH)
SENT = {
'additions': RESOURCE['additions'],
'deletions': RESOURCE['deletions'],
}
self.assertEqual(req['data'], SENT)
self._verifyResourceProperties(changes, RESOURCE, zone)
def test_create_w_alternate_client(self):
from gcloud.dns.resource_record_set import ResourceRecordSet
self._setUpConstants()
RESOURCE = self._makeResource()
PATH = 'projects/%s/managedZones/%s/changes' % (
self.PROJECT, self.ZONE_NAME)
conn1 = _Connection()
client1 = _Client(project=self.PROJECT, connection=conn1)
conn2 = _Connection(RESOURCE)
client2 = _Client(project=self.PROJECT, connection=conn2)
zone = _Zone(client1)
changes = self._makeOne(zone)
changes.add_record_set(ResourceRecordSet(
'test.example.com', 'CNAME', 3600, ['www.example.com'], zone))
changes.delete_record_set(ResourceRecordSet(
'test.example.com', 'CNAME', 86400, ['other.example.com'], zone))
changes.create(client=client2)
self.assertEqual(len(conn1._requested), 0)
self.assertEqual(len(conn2._requested), 1)
req = conn2._requested[0]
self.assertEqual(req['method'], 'POST')
self.assertEqual(req['path'], '/%s' % PATH)
SENT = {
'additions': RESOURCE['additions'],
'deletions': RESOURCE['deletions'],
}
self.assertEqual(req['data'], SENT)
self._verifyResourceProperties(changes, RESOURCE, zone)
def test_exists_miss_w_bound_client(self):
PATH = 'projects/%s/managedZones/%s/changes/%s' % (
self.PROJECT, self.ZONE_NAME, self.CHANGES_NAME)
self._setUpConstants()
conn = _Connection()
client = _Client(project=self.PROJECT, connection=conn)
zone = _Zone(client)
changes = self._makeOne(zone)
changes.name = self.CHANGES_NAME
self.assertFalse(changes.exists())
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self.assertEqual(req['query_params'], {'fields': 'id'})
def test_exists_hit_w_alternate_client(self):
PATH = 'projects/%s/managedZones/%s/changes/%s' % (
self.PROJECT, self.ZONE_NAME, self.CHANGES_NAME)
conn1 = _Connection()
client1 = _Client(project=self.PROJECT, connection=conn1)
conn2 = _Connection({})
client2 = _Client(project=self.PROJECT, connection=conn2)
zone = _Zone(client1)
changes = self._makeOne(zone)
changes.name = self.CHANGES_NAME
self.assertTrue(changes.exists(client=client2))
self.assertEqual(len(conn1._requested), 0)
self.assertEqual(len(conn2._requested), 1)
req = conn2._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self.assertEqual(req['query_params'], {'fields': 'id'})
def test_reload_w_bound_client(self):
PATH = 'projects/%s/managedZones/%s/changes/%s' % (
self.PROJECT, self.ZONE_NAME, self.CHANGES_NAME)
self._setUpConstants()
RESOURCE = self._makeResource()
conn = _Connection(RESOURCE)
client = _Client(project=self.PROJECT, connection=conn)
zone = _Zone(client)
changes = self._makeOne(zone)
changes.name = self.CHANGES_NAME
changes.reload()
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self._verifyResourceProperties(changes, RESOURCE, zone)
def test_reload_w_alternate_client(self):
PATH = 'projects/%s/managedZones/%s/changes/%s' % (
self.PROJECT, self.ZONE_NAME, self.CHANGES_NAME)
self._setUpConstants()
RESOURCE = self._makeResource()
conn1 = _Connection()
client1 = _Client(project=self.PROJECT, connection=conn1)
conn2 = _Connection(RESOURCE)
client2 = _Client(project=self.PROJECT, connection=conn2)
zone = _Zone(client1)
changes = self._makeOne(zone)
changes.name = self.CHANGES_NAME
changes.reload(client=client2)
self.assertEqual(len(conn1._requested), 0)
self.assertEqual(len(conn2._requested), 1)
req = conn2._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self._verifyResourceProperties(changes, RESOURCE, zone)
class _Zone(object):
def __init__(self, client=None, project=TestChanges.PROJECT,
name=TestChanges.ZONE_NAME):
self._client = client
self.project = project
self.name = name
class _Client(object):
def __init__(self, project='project', connection=None):
self.project = project
self.connection = connection
class _Connection(object):
def __init__(self, *responses):
self._responses = responses
self._requested = []
def api_request(self, **kw):
from gcloud.exceptions import NotFound
self._requested.append(kw)
try:
response, self._responses = self._responses[0], self._responses[1:]
except:
raise NotFound('miss')
else:
return response

View file

@ -0,0 +1,252 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest2
class TestClient(unittest2.TestCase):
PROJECT = 'PROJECT'
ZONE_NAME = 'zone-name'
def _getTargetClass(self):
from gcloud.dns.client import Client
return Client
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_ctor(self):
from gcloud.dns.connection import Connection
creds = _Credentials()
http = object()
client = self._makeOne(project=self.PROJECT, credentials=creds,
http=http)
self.assertTrue(isinstance(client.connection, Connection))
self.assertTrue(client.connection.credentials is creds)
self.assertTrue(client.connection.http is http)
def test_quotas_defaults(self):
PATH = 'projects/%s' % (self.PROJECT,)
MANAGED_ZONES = 1234
RRS_PER_RRSET = 23
RRSETS_PER_ZONE = 345
RRSET_ADDITIONS = 456
RRSET_DELETIONS = 567
TOTAL_SIZE = 67890
DATA = {
'quota': {
'managedZones': str(MANAGED_ZONES),
'resourceRecordsPerRrset': str(RRS_PER_RRSET),
'rrsetsPerManagedZone': str(RRSETS_PER_ZONE),
'rrsetAdditionsPerChange': str(RRSET_ADDITIONS),
'rrsetDeletionsPerChange': str(RRSET_DELETIONS),
'totalRrdataSizePerChange': str(TOTAL_SIZE),
}
}
CONVERTED = dict([(key, int(value))
for key, value in DATA['quota'].items()])
creds = _Credentials()
client = self._makeOne(self.PROJECT, creds)
conn = client.connection = _Connection(DATA)
quotas = client.quotas()
self.assertEqual(quotas, CONVERTED)
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
def test_quotas_w_kind_key(self):
PATH = 'projects/%s' % (self.PROJECT,)
MANAGED_ZONES = 1234
RRS_PER_RRSET = 23
RRSETS_PER_ZONE = 345
RRSET_ADDITIONS = 456
RRSET_DELETIONS = 567
TOTAL_SIZE = 67890
DATA = {
'quota': {
'managedZones': str(MANAGED_ZONES),
'resourceRecordsPerRrset': str(RRS_PER_RRSET),
'rrsetsPerManagedZone': str(RRSETS_PER_ZONE),
'rrsetAdditionsPerChange': str(RRSET_ADDITIONS),
'rrsetDeletionsPerChange': str(RRSET_DELETIONS),
'totalRrdataSizePerChange': str(TOTAL_SIZE),
}
}
CONVERTED = dict([(key, int(value))
for key, value in DATA['quota'].items()])
WITH_KIND = {'quota': DATA['quota'].copy()}
WITH_KIND['quota']['kind'] = 'dns#quota'
creds = _Credentials()
client = self._makeOne(self.PROJECT, creds)
conn = client.connection = _Connection(WITH_KIND)
quotas = client.quotas()
self.assertEqual(quotas, CONVERTED)
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
def test_list_zones_defaults(self):
from gcloud.dns.zone import ManagedZone
ID_1 = '123'
ZONE_1 = 'zone_one'
DNS_1 = 'one.example.com'
ID_2 = '234'
ZONE_2 = 'zone_two'
DNS_2 = 'two.example.com'
PATH = 'projects/%s/managedZones' % (self.PROJECT,)
TOKEN = 'TOKEN'
DATA = {
'nextPageToken': TOKEN,
'managedZones': [
{'kind': 'dns#managedZone',
'id': ID_1,
'name': ZONE_1,
'dnsName': DNS_1},
{'kind': 'dns#managedZone',
'id': ID_2,
'name': ZONE_2,
'dnsName': DNS_2},
]
}
creds = _Credentials()
client = self._makeOne(self.PROJECT, creds)
conn = client.connection = _Connection(DATA)
zones, token = client.list_zones()
self.assertEqual(len(zones), len(DATA['managedZones']))
for found, expected in zip(zones, DATA['managedZones']):
self.assertTrue(isinstance(found, ManagedZone))
self.assertEqual(found.zone_id, expected['id'])
self.assertEqual(found.name, expected['name'])
self.assertEqual(found.dns_name, expected['dnsName'])
self.assertEqual(token, TOKEN)
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
def test_list_zones_explicit(self):
from gcloud.dns.zone import ManagedZone
ID_1 = '123'
ZONE_1 = 'zone_one'
DNS_1 = 'one.example.com'
ID_2 = '234'
ZONE_2 = 'zone_two'
DNS_2 = 'two.example.com'
PATH = 'projects/%s/managedZones' % (self.PROJECT,)
TOKEN = 'TOKEN'
DATA = {
'managedZones': [
{'kind': 'dns#managedZone',
'id': ID_1,
'name': ZONE_1,
'dnsName': DNS_1},
{'kind': 'dns#managedZone',
'id': ID_2,
'name': ZONE_2,
'dnsName': DNS_2},
]
}
creds = _Credentials()
client = self._makeOne(self.PROJECT, creds)
conn = client.connection = _Connection(DATA)
zones, token = client.list_zones(max_results=3, page_token=TOKEN)
self.assertEqual(len(zones), len(DATA['managedZones']))
for found, expected in zip(zones, DATA['managedZones']):
self.assertTrue(isinstance(found, ManagedZone))
self.assertEqual(found.zone_id, expected['id'])
self.assertEqual(found.name, expected['name'])
self.assertEqual(found.dns_name, expected['dnsName'])
self.assertEqual(token, None)
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self.assertEqual(req['query_params'],
{'maxResults': 3, 'pageToken': TOKEN})
def test_zone_explicit(self):
from gcloud.dns.zone import ManagedZone
DESCRIPTION = 'DESCRIPTION'
DNS_NAME = 'test.example.com'
creds = _Credentials()
client = self._makeOne(self.PROJECT, creds)
zone = client.zone(self.ZONE_NAME, DNS_NAME, DESCRIPTION)
self.assertTrue(isinstance(zone, ManagedZone))
self.assertEqual(zone.name, self.ZONE_NAME)
self.assertEqual(zone.dns_name, DNS_NAME)
self.assertEqual(zone.description, DESCRIPTION)
self.assertTrue(zone._client is client)
def test_zone_w_dns_name_wo_description(self):
from gcloud.dns.zone import ManagedZone
DNS_NAME = 'test.example.com'
creds = _Credentials()
client = self._makeOne(self.PROJECT, creds)
zone = client.zone(self.ZONE_NAME, DNS_NAME)
self.assertTrue(isinstance(zone, ManagedZone))
self.assertEqual(zone.name, self.ZONE_NAME)
self.assertEqual(zone.dns_name, DNS_NAME)
self.assertEqual(zone.description, DNS_NAME)
self.assertTrue(zone._client is client)
def test_zone_wo_dns_name(self):
from gcloud.dns.zone import ManagedZone
creds = _Credentials()
client = self._makeOne(self.PROJECT, creds)
zone = client.zone(self.ZONE_NAME)
self.assertTrue(isinstance(zone, ManagedZone))
self.assertEqual(zone.name, self.ZONE_NAME)
self.assertEqual(zone.dns_name, None)
self.assertEqual(zone.description, None)
self.assertTrue(zone._client is client)
class _Credentials(object):
_scopes = None
@staticmethod
def create_scoped_required():
return True
def create_scoped(self, scope):
self._scopes = scope
return self
class _Connection(object):
def __init__(self, *responses):
self._responses = responses
self._requested = []
def api_request(self, **kw):
self._requested.append(kw)
response, self._responses = self._responses[0], self._responses[1:]
return response

View file

@ -0,0 +1,47 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest2
class TestConnection(unittest2.TestCase):
def _getTargetClass(self):
from gcloud.dns.connection import Connection
return Connection
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_build_api_url_no_extra_query_params(self):
conn = self._makeOne()
URI = '/'.join([
conn.API_BASE_URL,
'dns',
conn.API_VERSION,
'foo',
])
self.assertEqual(conn.build_api_url('/foo'), URI)
def test_build_api_url_w_extra_query_params(self):
from six.moves.urllib.parse import parse_qsl
from six.moves.urllib.parse import urlsplit
conn = self._makeOne()
uri = conn.build_api_url('/foo', {'bar': 'baz'})
scheme, netloc, path, qs, _ = urlsplit(uri)
self.assertEqual('%s://%s' % (scheme, netloc), conn.API_BASE_URL)
self.assertEqual(path,
'/'.join(['', 'dns', conn.API_VERSION, 'foo']))
parms = dict(parse_qsl(qs))
self.assertEqual(parms['bar'], 'baz')

View file

@ -0,0 +1,94 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest2
class TestResourceRecordSet(unittest2.TestCase):
def _getTargetClass(self):
from gcloud.dns.resource_record_set import ResourceRecordSet
return ResourceRecordSet
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def test_ctor(self):
zone = _Zone()
rrs = self._makeOne('test.example.com', 'CNAME', 3600,
['www.example.com'], zone)
self.assertEqual(rrs.name, 'test.example.com')
self.assertEqual(rrs.record_type, 'CNAME')
self.assertEqual(rrs.ttl, 3600)
self.assertEqual(rrs.rrdatas, ['www.example.com'])
self.assertTrue(rrs.zone is zone)
def test_from_api_repr_missing_rrdatas(self):
zone = _Zone()
klass = self._getTargetClass()
with self.assertRaises(KeyError):
klass.from_api_repr({'name': 'test.example.com',
'type': 'CNAME',
'ttl': 3600}, zone=zone)
def test_from_api_repr_missing_ttl(self):
zone = _Zone()
klass = self._getTargetClass()
with self.assertRaises(KeyError):
klass.from_api_repr({'name': 'test.example.com',
'type': 'CNAME',
'rrdatas': ['www.example.com']}, zone=zone)
def test_from_api_repr_missing_type(self):
zone = _Zone()
klass = self._getTargetClass()
with self.assertRaises(KeyError):
klass.from_api_repr({'name': 'test.example.com',
'ttl': 3600,
'rrdatas': ['www.example.com']}, zone=zone)
def test_from_api_repr_missing_name(self):
zone = _Zone()
klass = self._getTargetClass()
with self.assertRaises(KeyError):
klass.from_api_repr({'type': 'CNAME',
'ttl': 3600,
'rrdatas': ['www.example.com']}, zone=zone)
def test_from_api_repr_bare(self):
zone = _Zone()
RESOURCE = {
'kind': 'dns#resourceRecordSet',
'name': 'test.example.com',
'type': 'CNAME',
'ttl': '3600',
'rrdatas': ['www.example.com'],
}
klass = self._getTargetClass()
rrs = klass.from_api_repr(RESOURCE, zone=zone)
self.assertEqual(rrs.name, 'test.example.com')
self.assertEqual(rrs.record_type, 'CNAME')
self.assertEqual(rrs.ttl, 3600)
self.assertEqual(rrs.rrdatas, ['www.example.com'])
self.assertTrue(rrs.zone is zone)
class _Zone(object):
pass

View file

@ -0,0 +1,692 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest2
class TestManagedZone(unittest2.TestCase):
PROJECT = 'project'
ZONE_NAME = 'zone-name'
DESCRIPTION = 'ZONE DESCRIPTION'
DNS_NAME = 'test.example.com'
def _getTargetClass(self):
from gcloud.dns.zone import ManagedZone
return ManagedZone
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
def _setUpConstants(self):
import datetime
from gcloud._helpers import UTC
year = 2015
month = 7
day = 24
hour = 19
minute = 53
seconds = 19
micros = 6000
self.WHEN_STR = '%d-%02d-%02dT%02d:%02d:%02d.%06dZ' % (
year, month, day, hour, minute, seconds, micros)
self.WHEN = datetime.datetime(
year, month, day, hour, minute, seconds, micros, tzinfo=UTC)
self.ZONE_ID = 12345
def _makeResource(self):
self._setUpConstants()
return {
'name': self.ZONE_NAME,
'dnsName': self.DNS_NAME,
'description': self.DESCRIPTION,
'id': self.ZONE_ID,
'creationTime': self.WHEN_STR,
'nameServers': [
'ns-cloud1.googledomains.com',
'ns-cloud2.googledomains.com',
],
}
def _verifyReadonlyResourceProperties(self, zone, resource):
self.assertEqual(zone.zone_id, resource.get('id'))
if 'creationTime' in resource:
self.assertEqual(zone.created, self.WHEN)
else:
self.assertEqual(zone.created, None)
if 'nameServers' in resource:
self.assertEqual(zone.name_servers, resource['nameServers'])
else:
self.assertEqual(zone.name_servers, None)
def _verifyResourceProperties(self, zone, resource):
self._verifyReadonlyResourceProperties(zone, resource)
self.assertEqual(zone.name, resource.get('name'))
self.assertEqual(zone.dns_name, resource.get('dnsName'))
self.assertEqual(zone.description, resource.get('description'))
self.assertEqual(zone.zone_id, resource.get('id'))
self.assertEqual(zone.name_server_set, resource.get('nameServerSet'))
def test_ctor_defaults(self):
zone = self._makeOne(self.ZONE_NAME)
self.assertEqual(zone.name, self.ZONE_NAME)
self.assertEqual(zone.dns_name, None)
self.assertTrue(zone._client is None)
with self.assertRaises(AttributeError):
_ = zone.project
with self.assertRaises(AttributeError):
_ = zone.path
self.assertEqual(zone.zone_id, None)
self.assertEqual(zone.created, None)
self.assertEqual(zone.description, None)
def test_ctor_wo_description(self):
client = _Client(self.PROJECT)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
self.assertEqual(zone.name, self.ZONE_NAME)
self.assertEqual(zone.dns_name, self.DNS_NAME)
self.assertTrue(zone._client is client)
self.assertEqual(zone.project, client.project)
self.assertEqual(
zone.path,
'/projects/%s/managedZones/%s' % (self.PROJECT, self.ZONE_NAME))
self.assertEqual(zone.zone_id, None)
self.assertEqual(zone.created, None)
self.assertEqual(zone.description, self.DNS_NAME)
def test_ctor_explicit(self):
DESCRIPTION = 'DESCRIPTION'
client = _Client(self.PROJECT)
zone = self._makeOne(
self.ZONE_NAME, self.DNS_NAME, client, DESCRIPTION)
self.assertEqual(zone.name, self.ZONE_NAME)
self.assertEqual(zone.dns_name, self.DNS_NAME)
self.assertTrue(zone._client is client)
self.assertEqual(zone.project, client.project)
self.assertEqual(
zone.path,
'/projects/%s/managedZones/%s' % (self.PROJECT, self.ZONE_NAME))
self.assertEqual(zone.zone_id, None)
self.assertEqual(zone.created, None)
self.assertEqual(zone.description, DESCRIPTION)
def test_from_api_repr_missing_identity(self):
self._setUpConstants()
client = _Client(self.PROJECT)
RESOURCE = {}
klass = self._getTargetClass()
with self.assertRaises(KeyError):
klass.from_api_repr(RESOURCE, client=client)
def test_from_api_repr_bare(self):
self._setUpConstants()
client = _Client(self.PROJECT)
RESOURCE = {
'name': self.ZONE_NAME,
'dnsName': self.DNS_NAME,
}
klass = self._getTargetClass()
zone = klass.from_api_repr(RESOURCE, client=client)
self.assertTrue(zone._client is client)
self._verifyResourceProperties(zone, RESOURCE)
def test_from_api_repr_w_properties(self):
self._setUpConstants()
client = _Client(self.PROJECT)
RESOURCE = self._makeResource()
klass = self._getTargetClass()
zone = klass.from_api_repr(RESOURCE, client=client)
self.assertTrue(zone._client is client)
self._verifyResourceProperties(zone, RESOURCE)
def test_description_setter_bad_value(self):
client = _Client(self.PROJECT)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
with self.assertRaises(ValueError):
zone.description = 12345
def test_description_setter(self):
client = _Client(self.PROJECT)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
zone.description = 'DESCRIPTION'
self.assertEqual(zone.description, 'DESCRIPTION')
def test_name_server_set_setter_bad_value(self):
client = _Client(self.PROJECT)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
with self.assertRaises(ValueError):
zone.name_server_set = 12345
def test_name_server_set_setter(self):
client = _Client(self.PROJECT)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
zone.name_server_set = 'NAME_SERVER_SET'
self.assertEqual(zone.name_server_set, 'NAME_SERVER_SET')
def test_resource_record_set(self):
from gcloud.dns.resource_record_set import ResourceRecordSet
RRS_NAME = 'other.example.com'
RRS_TYPE = 'CNAME'
TTL = 3600
RRDATAS = ['www.example.com']
client = _Client(self.PROJECT)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
rrs = zone.resource_record_set(RRS_NAME, RRS_TYPE, TTL, RRDATAS)
self.assertTrue(isinstance(rrs, ResourceRecordSet))
self.assertEqual(rrs.name, RRS_NAME)
self.assertEqual(rrs.record_type, RRS_TYPE)
self.assertEqual(rrs.ttl, TTL)
self.assertEqual(rrs.rrdatas, RRDATAS)
self.assertTrue(rrs.zone is zone)
def test_changes(self):
from gcloud.dns.changes import Changes
client = _Client(self.PROJECT)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
changes = zone.changes()
self.assertTrue(isinstance(changes, Changes))
self.assertTrue(changes.zone is zone)
def test_create_w_bound_client(self):
PATH = 'projects/%s/managedZones' % self.PROJECT
RESOURCE = self._makeResource()
conn = _Connection(RESOURCE)
client = _Client(project=self.PROJECT, connection=conn)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
zone.create()
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'POST')
self.assertEqual(req['path'], '/%s' % PATH)
SENT = {
'name': self.ZONE_NAME,
'dnsName': self.DNS_NAME,
'description': self.DNS_NAME,
}
self.assertEqual(req['data'], SENT)
self._verifyResourceProperties(zone, RESOURCE)
def test_create_w_alternate_client(self):
PATH = 'projects/%s/managedZones' % self.PROJECT
DESCRIPTION = 'DESCRIPTION'
NAME_SERVER_SET = 'NAME_SERVER_SET'
RESOURCE = self._makeResource()
RESOURCE['nameServerSet'] = NAME_SERVER_SET
RESOURCE['description'] = DESCRIPTION
conn1 = _Connection()
client1 = _Client(project=self.PROJECT, connection=conn1)
conn2 = _Connection(RESOURCE)
client2 = _Client(project=self.PROJECT, connection=conn2)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client1)
zone.name_server_set = NAME_SERVER_SET
zone.description = DESCRIPTION
zone.create(client=client2)
self.assertEqual(len(conn1._requested), 0)
self.assertEqual(len(conn2._requested), 1)
req = conn2._requested[0]
self.assertEqual(req['method'], 'POST')
self.assertEqual(req['path'], '/%s' % PATH)
SENT = {
'name': self.ZONE_NAME,
'dnsName': self.DNS_NAME,
'nameServerSet': NAME_SERVER_SET,
'description': DESCRIPTION,
}
self.assertEqual(req['data'], SENT)
self._verifyResourceProperties(zone, RESOURCE)
def test_create_wo_dns_name_or_description(self):
from gcloud.exceptions import BadRequest
PATH = 'projects/%s/managedZones' % self.PROJECT
_requested = []
def _api_request(**kw):
_requested.append(kw)
raise BadRequest('missing dns_name / description')
conn = _Connection()
conn.api_request = _api_request
client = _Client(project=self.PROJECT, connection=conn)
zone = self._makeOne(self.ZONE_NAME, client=client)
with self.assertRaises(BadRequest):
zone.create()
self.assertEqual(len(_requested), 1)
req = _requested[0]
self.assertEqual(req['method'], 'POST')
self.assertEqual(req['path'], '/%s' % PATH)
SENT = {
'name': self.ZONE_NAME,
}
self.assertEqual(req['data'], SENT)
def test_create_w_missing_output_properties(self):
# In the wild, the resource returned from 'zone.create' sometimes
# lacks 'creationTime' / 'lastModifiedTime'
PATH = 'projects/%s/managedZones' % (self.PROJECT,)
RESOURCE = self._makeResource()
del RESOURCE['creationTime']
del RESOURCE['id']
del RESOURCE['nameServers']
self.WHEN = None
conn = _Connection(RESOURCE)
client = _Client(project=self.PROJECT, connection=conn)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
zone.create()
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'POST')
self.assertEqual(req['path'], '/%s' % PATH)
SENT = {
'name': self.ZONE_NAME,
'dnsName': self.DNS_NAME,
'description': self.DNS_NAME,
}
self.assertEqual(req['data'], SENT)
self._verifyResourceProperties(zone, RESOURCE)
def test_exists_miss_w_bound_client(self):
PATH = 'projects/%s/managedZones/%s' % (self.PROJECT, self.ZONE_NAME)
conn = _Connection()
client = _Client(project=self.PROJECT, connection=conn)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
self.assertFalse(zone.exists())
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self.assertEqual(req['query_params'], {'fields': 'id'})
def test_exists_hit_w_alternate_client(self):
PATH = 'projects/%s/managedZones/%s' % (self.PROJECT, self.ZONE_NAME)
conn1 = _Connection()
client1 = _Client(project=self.PROJECT, connection=conn1)
conn2 = _Connection({})
client2 = _Client(project=self.PROJECT, connection=conn2)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client1)
self.assertTrue(zone.exists(client=client2))
self.assertEqual(len(conn1._requested), 0)
self.assertEqual(len(conn2._requested), 1)
req = conn2._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self.assertEqual(req['query_params'], {'fields': 'id'})
def test_reload_w_bound_client(self):
PATH = 'projects/%s/managedZones/%s' % (self.PROJECT, self.ZONE_NAME)
RESOURCE = self._makeResource()
conn = _Connection(RESOURCE)
client = _Client(project=self.PROJECT, connection=conn)
zone = self._makeOne(self.ZONE_NAME, client=client)
zone.reload()
self.assertEqual(zone.dns_name, self.DNS_NAME)
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self._verifyResourceProperties(zone, RESOURCE)
def test_reload_w_alternate_client(self):
PATH = 'projects/%s/managedZones/%s' % (self.PROJECT, self.ZONE_NAME)
RESOURCE = self._makeResource()
conn1 = _Connection()
client1 = _Client(project=self.PROJECT, connection=conn1)
conn2 = _Connection(RESOURCE)
client2 = _Client(project=self.PROJECT, connection=conn2)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client1)
zone.reload(client=client2)
self.assertEqual(len(conn1._requested), 0)
self.assertEqual(len(conn2._requested), 1)
req = conn2._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self._verifyResourceProperties(zone, RESOURCE)
def test_delete_w_bound_client(self):
PATH = 'projects/%s/managedZones/%s' % (self.PROJECT, self.ZONE_NAME)
conn = _Connection({})
client = _Client(project=self.PROJECT, connection=conn)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
zone.delete()
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'DELETE')
self.assertEqual(req['path'], '/%s' % PATH)
def test_delete_w_alternate_client(self):
PATH = 'projects/%s/managedZones/%s' % (self.PROJECT, self.ZONE_NAME)
conn1 = _Connection()
client1 = _Client(project=self.PROJECT, connection=conn1)
conn2 = _Connection({})
client2 = _Client(project=self.PROJECT, connection=conn2)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client1)
zone.delete(client=client2)
self.assertEqual(len(conn1._requested), 0)
self.assertEqual(len(conn2._requested), 1)
req = conn2._requested[0]
self.assertEqual(req['method'], 'DELETE')
self.assertEqual(req['path'], '/%s' % PATH)
def test_list_resource_record_sets_defaults(self):
from gcloud.dns.resource_record_set import ResourceRecordSet
PATH = 'projects/%s/managedZones/%s/rrsets' % (
self.PROJECT, self.ZONE_NAME)
TOKEN = 'TOKEN'
NAME_1 = 'www.example.com'
TYPE_1 = 'A'
TTL_1 = '86400'
RRDATAS_1 = ['123.45.67.89']
NAME_2 = 'alias.example.com'
TYPE_2 = 'CNAME'
TTL_2 = '3600'
RRDATAS_2 = ['www.example.com']
DATA = {
'nextPageToken': TOKEN,
'rrsets': [
{'kind': 'dns#resourceRecordSet',
'name': NAME_1,
'type': TYPE_1,
'ttl': TTL_1,
'rrdatas': RRDATAS_1},
{'kind': 'dns#resourceRecordSet',
'name': NAME_2,
'type': TYPE_2,
'ttl': TTL_2,
'rrdatas': RRDATAS_2},
]
}
conn = _Connection(DATA)
client = _Client(project=self.PROJECT, connection=conn)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
rrsets, token = zone.list_resource_record_sets()
self.assertEqual(len(rrsets), len(DATA['rrsets']))
for found, expected in zip(rrsets, DATA['rrsets']):
self.assertTrue(isinstance(found, ResourceRecordSet))
self.assertEqual(found.name, expected['name'])
self.assertEqual(found.record_type, expected['type'])
self.assertEqual(found.ttl, int(expected['ttl']))
self.assertEqual(found.rrdatas, expected['rrdatas'])
self.assertEqual(token, TOKEN)
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
def test_list_resource_record_sets_explicit(self):
from gcloud.dns.resource_record_set import ResourceRecordSet
PATH = 'projects/%s/managedZones/%s/rrsets' % (
self.PROJECT, self.ZONE_NAME)
TOKEN = 'TOKEN'
NAME_1 = 'www.example.com'
TYPE_1 = 'A'
TTL_1 = '86400'
RRDATAS_1 = ['123.45.67.89']
NAME_2 = 'alias.example.com'
TYPE_2 = 'CNAME'
TTL_2 = '3600'
RRDATAS_2 = ['www.example.com']
DATA = {
'rrsets': [
{'kind': 'dns#resourceRecordSet',
'name': NAME_1,
'type': TYPE_1,
'ttl': TTL_1,
'rrdatas': RRDATAS_1},
{'kind': 'dns#resourceRecordSet',
'name': NAME_2,
'type': TYPE_2,
'ttl': TTL_2,
'rrdatas': RRDATAS_2},
]
}
conn1 = _Connection()
client1 = _Client(project=self.PROJECT, connection=conn1)
conn2 = _Connection(DATA)
client2 = _Client(project=self.PROJECT, connection=conn2)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client1)
rrsets, token = zone.list_resource_record_sets(
max_results=3, page_token=TOKEN, client=client2)
self.assertEqual(len(rrsets), len(DATA['rrsets']))
for found, expected in zip(rrsets, DATA['rrsets']):
self.assertTrue(isinstance(found, ResourceRecordSet))
self.assertEqual(found.name, expected['name'])
self.assertEqual(found.record_type, expected['type'])
self.assertEqual(found.ttl, int(expected['ttl']))
self.assertEqual(found.rrdatas, expected['rrdatas'])
self.assertEqual(token, None)
self.assertEqual(len(conn1._requested), 0)
self.assertEqual(len(conn2._requested), 1)
req = conn2._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self.assertEqual(req['query_params'],
{'maxResults': 3, 'pageToken': TOKEN})
def test_list_changes_defaults(self):
from gcloud._helpers import _datetime_to_rfc3339
from gcloud.dns.changes import Changes
from gcloud.dns.resource_record_set import ResourceRecordSet
self._setUpConstants()
PATH = 'projects/%s/managedZones/%s/changes' % (
self.PROJECT, self.ZONE_NAME)
TOKEN = 'TOKEN'
NAME_1 = 'www.example.com'
TYPE_1 = 'A'
TTL_1 = '86400'
RRDATAS_1 = ['123.45.67.89']
NAME_2 = 'alias.example.com'
TYPE_2 = 'CNAME'
TTL_2 = '3600'
RRDATAS_2 = ['www.example.com']
CHANGES_NAME = 'changeset_id'
DATA = {
'nextPageToken': TOKEN,
'changes': [{
'kind': 'dns#change',
'id': CHANGES_NAME,
'status': 'pending',
'startTime': _datetime_to_rfc3339(self.WHEN),
'additions': [
{'kind': 'dns#resourceRecordSet',
'name': NAME_1,
'type': TYPE_1,
'ttl': TTL_1,
'rrdatas': RRDATAS_1}],
'deletions': [
{'kind': 'dns#change',
'name': NAME_2,
'type': TYPE_2,
'ttl': TTL_2,
'rrdatas': RRDATAS_2}],
}]
}
conn = _Connection(DATA)
client = _Client(project=self.PROJECT, connection=conn)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client)
changes, token = zone.list_changes()
self.assertEqual(len(changes), len(DATA['changes']))
for found, expected in zip(changes, DATA['changes']):
self.assertTrue(isinstance(found, Changes))
self.assertEqual(found.name, CHANGES_NAME)
self.assertEqual(found.status, 'pending')
self.assertEqual(found.started, self.WHEN)
self.assertEqual(len(found.additions), len(expected['additions']))
for found_rr, expected_rr in zip(found.additions,
expected['additions']):
self.assertTrue(isinstance(found_rr, ResourceRecordSet))
self.assertEqual(found_rr.name, expected_rr['name'])
self.assertEqual(found_rr.record_type, expected_rr['type'])
self.assertEqual(found_rr.ttl, int(expected_rr['ttl']))
self.assertEqual(found_rr.rrdatas, expected_rr['rrdatas'])
self.assertEqual(len(found.deletions), len(expected['deletions']))
for found_rr, expected_rr in zip(found.deletions,
expected['deletions']):
self.assertTrue(isinstance(found_rr, ResourceRecordSet))
self.assertEqual(found_rr.name, expected_rr['name'])
self.assertEqual(found_rr.record_type, expected_rr['type'])
self.assertEqual(found_rr.ttl, int(expected_rr['ttl']))
self.assertEqual(found_rr.rrdatas, expected_rr['rrdatas'])
self.assertEqual(token, TOKEN)
self.assertEqual(len(conn._requested), 1)
req = conn._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
def test_list_changes_explicit(self):
from gcloud._helpers import _datetime_to_rfc3339
from gcloud.dns.changes import Changes
from gcloud.dns.resource_record_set import ResourceRecordSet
self._setUpConstants()
PATH = 'projects/%s/managedZones/%s/changes' % (
self.PROJECT, self.ZONE_NAME)
TOKEN = 'TOKEN'
NAME_1 = 'www.example.com'
TYPE_1 = 'A'
TTL_1 = '86400'
RRDATAS_1 = ['123.45.67.89']
NAME_2 = 'alias.example.com'
TYPE_2 = 'CNAME'
TTL_2 = '3600'
RRDATAS_2 = ['www.example.com']
CHANGES_NAME = 'changeset_id'
DATA = {
'changes': [{
'kind': 'dns#change',
'id': CHANGES_NAME,
'status': 'pending',
'startTime': _datetime_to_rfc3339(self.WHEN),
'additions': [
{'kind': 'dns#resourceRecordSet',
'name': NAME_1,
'type': TYPE_1,
'ttl': TTL_1,
'rrdatas': RRDATAS_1}],
'deletions': [
{'kind': 'dns#change',
'name': NAME_2,
'type': TYPE_2,
'ttl': TTL_2,
'rrdatas': RRDATAS_2}],
}]
}
conn1 = _Connection()
client1 = _Client(project=self.PROJECT, connection=conn1)
conn2 = _Connection(DATA)
client2 = _Client(project=self.PROJECT, connection=conn2)
zone = self._makeOne(self.ZONE_NAME, self.DNS_NAME, client1)
changes, token = zone.list_changes(
max_results=3, page_token=TOKEN, client=client2)
self.assertEqual(len(changes), len(DATA['changes']))
for found, expected in zip(changes, DATA['changes']):
self.assertTrue(isinstance(found, Changes))
self.assertEqual(found.name, CHANGES_NAME)
self.assertEqual(found.status, 'pending')
self.assertEqual(found.started, self.WHEN)
self.assertEqual(len(found.additions), len(expected['additions']))
for found_rr, expected_rr in zip(found.additions,
expected['additions']):
self.assertTrue(isinstance(found_rr, ResourceRecordSet))
self.assertEqual(found_rr.name, expected_rr['name'])
self.assertEqual(found_rr.record_type, expected_rr['type'])
self.assertEqual(found_rr.ttl, int(expected_rr['ttl']))
self.assertEqual(found_rr.rrdatas, expected_rr['rrdatas'])
self.assertEqual(len(found.deletions), len(expected['deletions']))
for found_rr, expected_rr in zip(found.deletions,
expected['deletions']):
self.assertTrue(isinstance(found_rr, ResourceRecordSet))
self.assertEqual(found_rr.name, expected_rr['name'])
self.assertEqual(found_rr.record_type, expected_rr['type'])
self.assertEqual(found_rr.ttl, int(expected_rr['ttl']))
self.assertEqual(found_rr.rrdatas, expected_rr['rrdatas'])
self.assertEqual(token, None)
self.assertEqual(len(conn1._requested), 0)
self.assertEqual(len(conn2._requested), 1)
req = conn2._requested[0]
self.assertEqual(req['method'], 'GET')
self.assertEqual(req['path'], '/%s' % PATH)
self.assertEqual(req['query_params'],
{'maxResults': 3, 'pageToken': TOKEN})
class _Client(object):
def __init__(self, project='project', connection=None):
self.project = project
self.connection = connection
class _Connection(object):
def __init__(self, *responses):
self._responses = responses
self._requested = []
def api_request(self, **kw):
from gcloud.exceptions import NotFound
self._requested.append(kw)
try:
response, self._responses = self._responses[0], self._responses[1:]
except:
raise NotFound('miss')
else:
return response

View file

@ -0,0 +1,395 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Define API ManagedZones."""
import six
from gcloud._helpers import _rfc3339_to_datetime
from gcloud.exceptions import NotFound
from gcloud.dns.changes import Changes
from gcloud.dns.resource_record_set import ResourceRecordSet
class ManagedZone(object):
"""ManagedZones are containers for DNS resource records.
See:
https://cloud.google.com/dns/api/v1/managedZones
:type name: string
:param name: the name of the zone
:type dns_name: string or :class:`NoneType`
:param dns_name: the DNS name of the zone. If not passed, then calls
to :meth:`create` will fail.
:type client: :class:`gcloud.dns.client.Client`
:param client: A client which holds credentials and project configuration
for the zone (which requires a project).
:type description: string or :class:`NoneType`
:param description: the description for the zone. If not passed, defaults
to the value of 'dns_name'.
"""
def __init__(self, name, dns_name=None, client=None, description=None):
self.name = name
self.dns_name = dns_name
self._client = client
self._properties = {}
if description is None:
description = dns_name
self.description = description
@classmethod
def from_api_repr(cls, resource, client):
"""Factory: construct a zone given its API representation
:type resource: dict
:param resource: zone resource representation returned from the API
:type client: :class:`gcloud.dns.client.Client`
:param client: Client which holds credentials and project
configuration for the zone.
:rtype: :class:`gcloud.dns.zone.ManagedZone`
:returns: Zone parsed from ``resource``.
"""
name = resource.get('name')
dns_name = resource.get('dnsName')
if name is None or dns_name is None:
raise KeyError('Resource lacks required identity information:'
'["name"]["dnsName"]')
zone = cls(name, dns_name, client=client)
zone._set_properties(resource)
return zone
@property
def project(self):
"""Project bound to the zone.
:rtype: string
:returns: the project (derived from the client).
"""
return self._client.project
@property
def path(self):
"""URL path for the zone's APIs.
:rtype: string
:returns: the path based on project and dataste name.
"""
return '/projects/%s/managedZones/%s' % (self.project, self.name)
@property
def created(self):
"""Datetime at which the zone was created.
:rtype: ``datetime.datetime``, or ``NoneType``
:returns: the creation time (None until set from the server).
"""
return self._properties.get('creationTime')
@property
def name_servers(self):
"""Datetime at which the zone was created.
:rtype: list of strings, or ``NoneType``.
:returns: the assigned name servers (None until set from the server).
"""
return self._properties.get('nameServers')
@property
def zone_id(self):
"""ID for the zone resource.
:rtype: string, or ``NoneType``
:returns: the ID (None until set from the server).
"""
return self._properties.get('id')
@property
def description(self):
"""Description of the zone.
:rtype: string, or ``NoneType``
:returns: The description as set by the user, or None (the default).
"""
return self._properties.get('description')
@description.setter
def description(self, value):
"""Update description of the zone.
:type value: string, or ``NoneType``
:param value: new description
:raises: ValueError for invalid value types.
"""
if not isinstance(value, six.string_types) and value is not None:
raise ValueError("Pass a string, or None")
self._properties['description'] = value
@property
def name_server_set(self):
"""Named set of DNS name servers that all host the same ManagedZones.
Most users will leave this blank.
See:
https://cloud.google.com/dns/api/v1/managedZones#nameServerSet
:rtype: string, or ``NoneType``
:returns: The name as set by the user, or None (the default).
"""
return self._properties.get('nameServerSet')
@name_server_set.setter
def name_server_set(self, value):
"""Update named set of DNS name servers.
:type value: string, or ``NoneType``
:param value: new title
:raises: ValueError for invalid value types.
"""
if not isinstance(value, six.string_types) and value is not None:
raise ValueError("Pass a string, or None")
self._properties['nameServerSet'] = value
def resource_record_set(self, name, record_type, ttl, rrdatas):
"""Construct a resource record set bound to this zone.
:type name: string
:param name: Name of the record set.
:type record_type: string
:param record_type: RR type
:type ttl: integer
:param ttl: TTL for the RR, in seconds
:type rrdatas: list of string
:param rrdatas: resource data for the RR
:rtype: :class:`gcloud.dns.resource_record_set.ResourceRecordSet`
:returns: a new ``ResourceRecordSet`` instance
"""
return ResourceRecordSet(name, record_type, ttl, rrdatas, zone=self)
def changes(self):
"""Construct a change set bound to this zone.
:rtype: :class:`gcloud.dns.changes.Changes`
:returns: a new ``Changes`` instance
"""
return Changes(zone=self)
def _require_client(self, client):
"""Check client or verify over-ride.
:type client: :class:`gcloud.dns.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current zone.
:rtype: :class:`gcloud.dns.client.Client`
:returns: The client passed in or the currently bound client.
"""
if client is None:
client = self._client
return client
def _set_properties(self, api_response):
"""Update properties from resource in body of ``api_response``
:type api_response: httplib2.Response
:param api_response: response returned from an API call
"""
self._properties.clear()
cleaned = api_response.copy()
self.dns_name = cleaned.pop('dnsName', None)
if 'creationTime' in cleaned:
cleaned['creationTime'] = _rfc3339_to_datetime(
cleaned['creationTime'])
self._properties.update(cleaned)
def _build_resource(self):
"""Generate a resource for ``create`` or ``update``."""
resource = {
'name': self.name,
}
if self.dns_name is not None:
resource['dnsName'] = self.dns_name
if self.description is not None:
resource['description'] = self.description
if self.name_server_set is not None:
resource['nameServerSet'] = self.name_server_set
return resource
def create(self, client=None):
"""API call: create the zone via a PUT request
See:
https://cloud.google.com/dns/api/v1/managedZones/create
:type client: :class:`gcloud.dns.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current zone.
"""
client = self._require_client(client)
path = '/projects/%s/managedZones' % (self.project,)
api_response = client.connection.api_request(
method='POST', path=path, data=self._build_resource())
self._set_properties(api_response)
def exists(self, client=None):
"""API call: test for the existence of the zone via a GET request
See
https://cloud.google.com/dns/api/v1/managedZones/get
:type client: :class:`gcloud.dns.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current zone.
"""
client = self._require_client(client)
try:
client.connection.api_request(method='GET', path=self.path,
query_params={'fields': 'id'})
except NotFound:
return False
else:
return True
def reload(self, client=None):
"""API call: refresh zone properties via a GET request
See
https://cloud.google.com/dns/api/v1/managedZones/get
:type client: :class:`gcloud.dns.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current zone.
"""
client = self._require_client(client)
api_response = client.connection.api_request(
method='GET', path=self.path)
self._set_properties(api_response)
def delete(self, client=None):
"""API call: delete the zone via a DELETE request
See:
https://cloud.google.com/dns/api/v1/managedZones/delete
:type client: :class:`gcloud.dns.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current zone.
"""
client = self._require_client(client)
client.connection.api_request(method='DELETE', path=self.path)
def list_resource_record_sets(self, max_results=None, page_token=None,
client=None):
"""List resource record sets for this zone.
See:
https://cloud.google.com/dns/api/v1/resourceRecordSets/list
:type max_results: int
:param max_results: maximum number of zones to return, If not
passed, defaults to a value set by the API.
:type page_token: string
:param page_token: opaque marker for the next "page" of zones. If
not passed, the API will return the first page of
zones.
:type client: :class:`gcloud.dns.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current zone.
:rtype: tuple, (list, str)
:returns: list of
:class:`gcloud.dns.resource_record_set.ResourceRecordSet`,
plus a "next page token" string: if the token is not None,
indicates that more zones can be retrieved with another
call (pass that value as ``page_token``).
"""
params = {}
if max_results is not None:
params['maxResults'] = max_results
if page_token is not None:
params['pageToken'] = page_token
path = '/projects/%s/managedZones/%s/rrsets' % (
self.project, self.name)
client = self._require_client(client)
conn = client.connection
resp = conn.api_request(method='GET', path=path, query_params=params)
zones = [ResourceRecordSet.from_api_repr(resource, self)
for resource in resp['rrsets']]
return zones, resp.get('nextPageToken')
def list_changes(self, max_results=None, page_token=None, client=None):
"""List change sets for this zone.
See:
https://cloud.google.com/dns/api/v1/resourceRecordSets/list
:type max_results: int
:param max_results: maximum number of zones to return, If not
passed, defaults to a value set by the API.
:type page_token: string
:param page_token: opaque marker for the next "page" of zones. If
not passed, the API will return the first page of
zones.
:type client: :class:`gcloud.dns.client.Client` or ``NoneType``
:param client: the client to use. If not passed, falls back to the
``client`` stored on the current zone.
:rtype: tuple, (list, str)
:returns: list of
:class:`gcloud.dns.resource_record_set.ResourceRecordSet`,
plus a "next page token" string: if the token is not None,
indicates that more zones can be retrieved with another
call (pass that value as ``page_token``).
"""
params = {}
if max_results is not None:
params['maxResults'] = max_results
if page_token is not None:
params['pageToken'] = page_token
path = '/projects/%s/managedZones/%s/changes' % (
self.project, self.name)
client = self._require_client(client)
conn = client.connection
resp = conn.api_request(method='GET', path=path, query_params=params)
zones = [Changes.from_api_repr(resource, self)
for resource in resp['changes']]
return zones, resp.get('nextPageToken')