def test_delete_missing_rrset(self): """ It is an error to attempt to delete an rrset which does not exist. """ zone_name = u"{}.test_delete_missing_rrset.invalid.".format( uuid4()) rrset = RRSet( label=Name(u"foo.{}".format(zone_name)), type=u"CNAME", ttl=60, records={CNAME(canonical_name=Name(u"bar.example.invalid."))}, ) client = get_client(self) d = client.create_hosted_zone(u"{}".format(time()), zone_name) def created_zone(zone): self.addCleanup(lambda: self._cleanup(client, zone.identifier)) d = client.change_resource_record_sets(zone.identifier, [delete_rrset(rrset)]) self.assertFailure(d, Route53Error) return d d.addCallback(created_zone) def got_error(error): self.assertEqual(BAD_REQUEST, int(error.status)) d.addCallback(got_error) return d
def _cname_for_subscription(domain): return CNAME( Name( u"introducer.{domain}".format( domain=domain, ) ) )
def test_cname(self): """ L{CNAME} can round-trip a I{CNAME} record through XML. """ self._test_roundtrip( CNAME, CNAME(canonical_name=Name("sub.example.invalid.")), XML(self._cname_xml), )
def test_change_resource_record_sets_nonexistent_zone(self): """ You cannot interact with resource record sets for a non-existent zone. """ rrset = RRSet( label=Name(u"foo.example.invalid."), type=u"CNAME", ttl=60, records={CNAME(canonical_name=Name(u"bar.example.invalid."))}, ) client = get_client(self) d = client.change_resource_record_sets(u"abcdefg12345678", [create_rrset(rrset)]) self.assertFailure(d, Route53Error) def got_error(error): self.assertEqual(NOT_FOUND, int(error.status)) d.addCallback(got_error) return d
def _converge_route53_infrastructure(actual, config, subscriptions, k8s, aws): """ Converge on the desired Route53 state relating to general S4 infrastructure. Specifically, make sure there is an rrset for the ``introducer`` subdomain which points at the customer grid service's load balancer endpoint. """ if actual.service is None or actual.service.status is None: # Cannot do anything without a v1.Service or one without a populated # v1.ServiceStatus field. return [] if not actual.service.status.loadBalancer.ingress: # Also cannot do anything if we don't yet know what our ingress # address is. return [] loadbalancer_hostname = actual.service.status.loadBalancer.ingress[0].hostname introducer_key = RRSetKey(label=_introducer_domain(config.domain), type=u"CNAME") desired_rrset = RRSet( label=introducer_key.label, type=introducer_key.type, ttl=60, records={ CNAME(canonical_name=Name(loadbalancer_hostname)), }, ) actual_rrset = actual.zone.rrsets.get(introducer_key, None) if actual_rrset == desired_rrset: # Nothing to do. return [] # Create it or change it to what we want. route53 = aws.get_route53_client() return [ lambda: change_route53_rrsets(route53, actual.zone.zone, desired_rrset), ]
def test_resource_record_sets(self): zone_name = u"{}.example.invalid.".format(uuid4()) cname = CNAME(canonical_name=Name(u"example.invalid.")) client = get_client(self) zone = yield client.create_hosted_zone(u"{}".format(time()), zone_name) # At least try to clean up, to be as nice as possible. # This might fail and someone else might have to do the # cleanup - but it might not! self.addCleanup(lambda: self._cleanup(client, zone.identifier)) cname_label = Name(u"foo.\N{SNOWMAN}.{}".format(zone_name)) create = create_rrset( RRSet( label=cname_label, type=u"CNAME", ttl=60, records={cname}, )) yield client.change_resource_record_sets(zone.identifier, [create]) initial = yield client.list_resource_record_sets(zone.identifier) key = RRSetKey(cname_label, u"CNAME") self.assertIn(key, initial) cname_rrset = initial[key] self.assertEqual( RRSet(label=cname_label, type=u"CNAME", ttl=60, records={cname}), cname_rrset, ) # Zones start with an SOA and some NS records. key = RRSetKey(Name(zone_name), u"SOA") self.assertIn(key, initial) soa = initial[key] self.assertEqual( len(soa.records), 1, "Expected one SOA record, got {}".format(soa.records)) key = RRSetKey(Name(zone_name), u"NS") self.assertIn(key, initial) ns = initial[key] self.assertNotEqual(set(), ns.records, "Expected some NS records, got none") # Unrecognized change type # XXX This depends on _ChangeRRSet using attrs. bogus = attr.assoc(create, action=u"BOGUS") d = client.change_resource_record_sets(zone.identifier, [bogus]) error = yield self.assertFailure(d, Route53Error) self.assertEqual(BAD_REQUEST, int(error.status)) created_a = A(IPv4Address(u"10.0.0.1")) upsert_label = Name(u"upsert.{}".format(zone_name)) upsert_create = upsert_rrset( RRSet( upsert_label, u"A", 60, {created_a}, )) updated_a = A(IPv4Address(u"10.0.0.2")) upsert_update = upsert_rrset( RRSet( upsert_create.rrset.label, upsert_create.rrset.type, upsert_create.rrset.ttl, {updated_a}, )) yield client.change_resource_record_sets(zone.identifier, [upsert_create]) rrsets = yield client.list_resource_record_sets(zone.identifier) self.assertEqual(rrsets[RRSetKey(upsert_label, u"A")].records, {created_a}) yield client.change_resource_record_sets(zone.identifier, [upsert_update]) rrsets = yield client.list_resource_record_sets(zone.identifier) self.assertEqual(rrsets[RRSetKey(upsert_label, u"A")].records, {updated_a}) # Use the name and maxitems parameters to select exactly one resource record. rrsets = yield client.list_resource_record_sets( zone.identifier, maxitems=1, name=upsert_label, type=u"A", ) self.assertEqual(1, len(rrsets), "Expected 1 rrset") self.assertEqual({updated_a}, rrsets[RRSetKey(upsert_label, u"A")].records) # It's invalid to specify type without name. d = client.list_resource_record_sets(zone.identifier, type=u"A") error = yield self.assertFailure(d, Route53Error) self.assertEqual(BAD_REQUEST, int(error.status)) # It's invalid to delete the SOA record. d = client.change_resource_record_sets( zone.identifier, [delete_rrset(soa)], ) error = yield self.assertFailure(d, Route53Error) self.assertEqual(BAD_REQUEST, int(error.status)) # Likewise, the NS records. d = client.change_resource_record_sets( zone.identifier, [delete_rrset(ns)], ) error = yield self.assertFailure(d, Route53Error) self.assertEqual(BAD_REQUEST, int(error.status)) # Test deletion at the end so the zone is clean for the # naive cleanup logic. yield client.change_resource_record_sets( zone.identifier, [ delete_rrset(cname_rrset), delete_rrset(upsert_update.rrset), ], ) rrsets = yield client.list_resource_record_sets(zone.identifier) self.assertNotIn(cname_label, rrsets) self.assertNotIn(upsert_label, rrsets)