# 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