mirror of
				https://github.com/github/octodns.git
				synced 2024-05-11 05:55:00 +00:00 
			
		
		
		
	Merge pull request #32 from github/route53-geo-conv-fixes
Route53 geo conv fixes
This commit is contained in:
		| @@ -417,7 +417,7 @@ class Route53Provider(BaseProvider): | ||||
|         # We've got a cached version use it | ||||
|         return self._health_checks | ||||
|  | ||||
|     def _get_health_check_id(self, record, ident, geo): | ||||
|     def _get_health_check_id(self, record, ident, geo, create): | ||||
|         # fqdn & the first value are special, we use them to match up health | ||||
|         # checks to their records. Route53 health checks check a single ip and | ||||
|         # we're going to assume that ips are interchangeable to avoid | ||||
| @@ -445,6 +445,10 @@ class Route53Provider(BaseProvider): | ||||
|                 # this is the health check we're looking for | ||||
|                 return id | ||||
|  | ||||
|         if not create: | ||||
|             # no existing matches and not allowed to create, return none | ||||
|             return | ||||
|  | ||||
|         # no existing matches, we need to create a new health check | ||||
|         config = { | ||||
|             'EnableSNI': True, | ||||
| @@ -493,7 +497,7 @@ class Route53Provider(BaseProvider): | ||||
|                 self.log.info('_gc_health_checks:   deleting id=%s', id) | ||||
|                 self._conn.delete_health_check(HealthCheckId=id) | ||||
|  | ||||
|     def _gen_records(self, record, new=False): | ||||
|     def _gen_records(self, record, creating=False): | ||||
|         ''' | ||||
|         Turns an octodns.Record into one or more `_Route53Record`s | ||||
|         ''' | ||||
| @@ -504,13 +508,8 @@ class Route53Provider(BaseProvider): | ||||
|         if getattr(record, 'geo', False): | ||||
|             base.is_geo_default = True | ||||
|             for ident, geo in record.geo.items(): | ||||
|                 if new: | ||||
|                     # only find health checks for records that are going to be | ||||
|                     # around after the run | ||||
|                     health_check_id = self._get_health_check_id(record, ident, | ||||
|                                                                 geo) | ||||
|                 else: | ||||
|                     health_check_id = None | ||||
|                 health_check_id = self._get_health_check_id(record, ident, geo, | ||||
|                                                             creating) | ||||
|                 records.add(_Route53Record(record.fqdn, record._type, | ||||
|                                            record.ttl, values=geo.values, | ||||
|                                            geo=geo, | ||||
| @@ -520,7 +519,7 @@ class Route53Provider(BaseProvider): | ||||
|  | ||||
|     def _mod_Create(self, change): | ||||
|         # New is the stuff that needs to be created | ||||
|         new_records = self._gen_records(change.new, True) | ||||
|         new_records = self._gen_records(change.new, creating=True) | ||||
|         # Now is a good time to clear out any unused health checks since we | ||||
|         # know what we'll be using going forward | ||||
|         self._gc_health_checks(change.new, new_records) | ||||
| @@ -529,8 +528,8 @@ class Route53Provider(BaseProvider): | ||||
|     def _mod_Update(self, change): | ||||
|         # See comments in _Route53Record for how the set math is made to do our | ||||
|         # bidding here. | ||||
|         existing_records = self._gen_records(change.existing) | ||||
|         new_records = self._gen_records(change.new, True) | ||||
|         existing_records = self._gen_records(change.existing, creating=False) | ||||
|         new_records = self._gen_records(change.new, creating=True) | ||||
|         # Now is a good time to clear out any unused health checks since we | ||||
|         # know what we'll be using going forward | ||||
|         self._gc_health_checks(change.new, new_records) | ||||
| @@ -540,14 +539,34 @@ class Route53Provider(BaseProvider): | ||||
|         creates = new_records - existing_records | ||||
|         # Things in both need updating, we could optimize this and filter out | ||||
|         # things that haven't actually changed, but that's for another day. | ||||
|         upserts = existing_records & new_records | ||||
|         # We can't use set math here b/c we won't be able to control which of | ||||
|         # the two objects will be in the result and we need to ensure it's the | ||||
|         # new one and we have to include some special handling when converting | ||||
|         # to/from a GEO enabled record | ||||
|         upserts = set() | ||||
|         existing_records = {r: r for r in existing_records} | ||||
|         for new_record in new_records: | ||||
|             try: | ||||
|                 existing_record = existing_records[new_record] | ||||
|                 if new_record.is_geo_default != existing_record.is_geo_default: | ||||
|                     # going from normal to geo or geo to normal, need a delete | ||||
|                     # and create | ||||
|                     deletes.add(existing_record) | ||||
|                     creates.add(new_record) | ||||
|                 else: | ||||
|                     # just an update | ||||
|                     upserts.add(new_record) | ||||
|             except KeyError: | ||||
|                 # Completely new record, ignore | ||||
|                 pass | ||||
|  | ||||
|         return self._gen_mods('DELETE', deletes) + \ | ||||
|             self._gen_mods('CREATE', creates) + \ | ||||
|             self._gen_mods('UPSERT', upserts) | ||||
|  | ||||
|     def _mod_Delete(self, change): | ||||
|         # Existing is the thing that needs to be deleted | ||||
|         existing_records = self._gen_records(change.existing) | ||||
|         existing_records = self._gen_records(change.existing, creating=False) | ||||
|         # Now is a good time to clear out all the health checks since we know | ||||
|         # we're done with them | ||||
|         self._gc_health_checks(change.existing, []) | ||||
|   | ||||
| @@ -430,6 +430,7 @@ class TestRoute53Provider(TestCase): | ||||
|                     'ResourceRecordSet': { | ||||
|                         'GeoLocation': {'CountryCode': 'US', | ||||
|                                         'SubdivisionCode': 'KY'}, | ||||
|                         'HealthCheckId': u'44', | ||||
|                         'Name': 'unit.tests.', | ||||
|                         'ResourceRecords': [{'Value': '7.2.3.4'}], | ||||
|                         'SetIdentifier': 'NA-US-KY', | ||||
| @@ -499,6 +500,70 @@ class TestRoute53Provider(TestCase): | ||||
|         self.assertEquals(1, provider.apply(plan)) | ||||
|         stubber.assert_no_pending_responses() | ||||
|  | ||||
|         # Update converting to non-geo by monkey patching in a populate that | ||||
|         # modifies the A record with geos | ||||
|         def mod_add_geo_populate(existing, target): | ||||
|             for record in self.expected.records: | ||||
|                 if record._type != 'A' or record.geo: | ||||
|                     existing.records.add(record) | ||||
|             record = Record.new(existing, 'simple', { | ||||
|                 'ttl': 61, | ||||
|                 'type': 'A', | ||||
|                 'values': ['1.2.3.4', '2.2.3.4'], | ||||
|                 'geo': { | ||||
|                     'OC': ['3.2.3.4', '4.2.3.4'], | ||||
|                 } | ||||
|             }) | ||||
|             existing.records.add(record) | ||||
|  | ||||
|         provider.populate = mod_add_geo_populate | ||||
|         change_resource_record_sets_params = { | ||||
|             'ChangeBatch': { | ||||
|                 'Changes': [{ | ||||
|                     'Action': 'DELETE', | ||||
|                     'ResourceRecordSet': { | ||||
|                         'GeoLocation': {'ContinentCode': 'OC'}, | ||||
|                         'Name': 'simple.unit.tests.', | ||||
|                         'ResourceRecords': [{'Value': '3.2.3.4'}, | ||||
|                                             {'Value': '4.2.3.4'}], | ||||
|                         'SetIdentifier': 'OC', | ||||
|                         'TTL': 61, | ||||
|                         'Type': 'A'} | ||||
|                 }, { | ||||
|                     'Action': 'DELETE', | ||||
|                     'ResourceRecordSet': { | ||||
|                         'GeoLocation': {'CountryCode': '*'}, | ||||
|                         'Name': 'simple.unit.tests.', | ||||
|                         'ResourceRecords': [{'Value': '1.2.3.4'}, | ||||
|                                             {'Value': '2.2.3.4'}], | ||||
|                         'SetIdentifier': 'default', | ||||
|                         'TTL': 61, | ||||
|                         'Type': 'A'} | ||||
|                 }, { | ||||
|                     'Action': 'CREATE', | ||||
|                     'ResourceRecordSet': { | ||||
|                         'Name': 'simple.unit.tests.', | ||||
|                         'ResourceRecords': [{'Value': '1.2.3.4'}, | ||||
|                                             {'Value': '2.2.3.4'}], | ||||
|                         'TTL': 60, | ||||
|                         'Type': 'A'} | ||||
|                 }], | ||||
|                 'Comment': ANY | ||||
|             }, | ||||
|             'HostedZoneId': 'z42' | ||||
|         } | ||||
|         stubber.add_response('change_resource_record_sets', | ||||
|                              {'ChangeInfo': { | ||||
|                                  'Id': 'id', | ||||
|                                  'Status': 'PENDING', | ||||
|                                  'SubmittedAt': '2017-01-29T01:02:03Z', | ||||
|                              }}, change_resource_record_sets_params) | ||||
|         plan = provider.plan(self.expected) | ||||
|         self.assertEquals(1, len(plan.changes)) | ||||
|         self.assertIsInstance(plan.changes[0], Update) | ||||
|         self.assertEquals(1, provider.apply(plan)) | ||||
|         stubber.assert_no_pending_responses() | ||||
|  | ||||
|     def test_sync_create(self): | ||||
|         provider, stubber = self._get_stubbed_provider() | ||||
|  | ||||
| @@ -629,7 +694,8 @@ class TestRoute53Provider(TestCase): | ||||
|                 'AF': ['4.2.3.4'], | ||||
|             } | ||||
|         }) | ||||
|         id = provider._get_health_check_id(record, 'AF', record.geo['AF']) | ||||
|         id = provider._get_health_check_id(record, 'AF', record.geo['AF'], | ||||
|                                            True) | ||||
|         self.assertEquals('42', id) | ||||
|  | ||||
|     def test_health_check_create(self): | ||||
| @@ -697,7 +763,15 @@ class TestRoute53Provider(TestCase): | ||||
|                 'AF': ['4.2.3.4'], | ||||
|             } | ||||
|         }) | ||||
|         id = provider._get_health_check_id(record, 'AF', record.geo['AF']) | ||||
|  | ||||
|         # if not allowed to create returns none | ||||
|         id = provider._get_health_check_id(record, 'AF', record.geo['AF'], | ||||
|                                            False) | ||||
|         self.assertFalse(id) | ||||
|  | ||||
|         # when allowed to create we do | ||||
|         id = provider._get_health_check_id(record, 'AF', record.geo['AF'], | ||||
|                                            True) | ||||
|         self.assertEquals('42', id) | ||||
|         stubber.assert_no_pending_responses() | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user