Add support for 'changes' to a ManagedZone's resource record sets by tseaver · Pull Request #1145 · googleapis/google-cloud-python

@@ -0,0 +1,260 @@ # 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 datetime
import six
from gcloud._helpers import UTC from gcloud._helpers import _RFC3339_MICROS 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 datetime.datetime.strptime(stamp, _RFC3339_MICROS).replace( tzinfo=UTC)
@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)