227 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			227 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | import boto3 | ||
|  | import json | ||
|  | import sure  # noqa | ||
|  | 
 | ||
|  | from copy import deepcopy | ||
|  | from moto import mock_cloudformation, mock_ec2, mock_route53 | ||
|  | from tests.test_cloudformation.fixtures import route53_ec2_instance_with_public_ip | ||
|  | from tests.test_cloudformation.fixtures import route53_health_check | ||
|  | from tests.test_cloudformation.fixtures import route53_roundrobin | ||
|  | 
 | ||
|  | template_hosted_zone = { | ||
|  |     "AWSTemplateFormatVersion": "2010-09-09", | ||
|  |     "Description": "Stack 1", | ||
|  |     "Parameters": {}, | ||
|  |     "Resources": { | ||
|  |         "Bar": { | ||
|  |             "Type": "AWS::Route53::HostedZone", | ||
|  |             "Properties": {"Name": "foo.bar.baz"}, | ||
|  |         } | ||
|  |     }, | ||
|  | } | ||
|  | template_record_set = { | ||
|  |     "AWSTemplateFormatVersion": "2010-09-09", | ||
|  |     "Description": "Stack 2", | ||
|  |     "Parameters": {"ZoneId": {"Type": "String"}}, | ||
|  |     "Resources": { | ||
|  |         "Foo": { | ||
|  |             "Properties": { | ||
|  |                 "HostedZoneId": {"Ref": "ZoneId"}, | ||
|  |                 "RecordSets": [ | ||
|  |                     { | ||
|  |                         "Name": "test.vpc.internal", | ||
|  |                         "Type": "A", | ||
|  |                         "SetIdentifier": "test1", | ||
|  |                         "Weight": 50, | ||
|  |                     } | ||
|  |                 ], | ||
|  |             }, | ||
|  |             "Type": "AWS::Route53::RecordSetGroup", | ||
|  |         } | ||
|  |     }, | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_cloudformation | ||
|  | @mock_route53 | ||
|  | def test_create_stack_hosted_zone_by_id(): | ||
|  |     cf_conn = boto3.client("cloudformation", region_name="us-east-1") | ||
|  |     conn = boto3.client("route53", region_name="us-east-1") | ||
|  | 
 | ||
|  |     # when creating a hosted zone via CF | ||
|  |     cf_conn.create_stack( | ||
|  |         StackName="test_stack1", TemplateBody=json.dumps(template_hosted_zone) | ||
|  |     ) | ||
|  | 
 | ||
|  |     # then a hosted zone should exist | ||
|  |     zone = conn.list_hosted_zones()["HostedZones"][0] | ||
|  |     zone.should.have.key("Name").equal("foo.bar.baz") | ||
|  |     zone.should.have.key("ResourceRecordSetCount").equal(0) | ||
|  | 
 | ||
|  |     # when adding a record set to this zone | ||
|  |     cf_conn.create_stack( | ||
|  |         StackName="test_stack2", | ||
|  |         TemplateBody=json.dumps(template_record_set), | ||
|  |         Parameters=[{"ParameterKey": "ZoneId", "ParameterValue": zone["Id"]}], | ||
|  |     ) | ||
|  | 
 | ||
|  |     # then the hosted zone should have a record | ||
|  |     updated_zone = conn.list_hosted_zones()["HostedZones"][0] | ||
|  |     updated_zone.should.have.key("Id").equal(zone["Id"]) | ||
|  |     updated_zone.should.have.key("Name").equal("foo.bar.baz") | ||
|  |     updated_zone.should.have.key("ResourceRecordSetCount").equal(1) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_cloudformation | ||
|  | @mock_route53 | ||
|  | def test_route53_roundrobin(): | ||
|  |     cf = boto3.client("cloudformation", region_name="us-west-1") | ||
|  |     route53 = boto3.client("route53", region_name="us-west-1") | ||
|  | 
 | ||
|  |     template_json = json.dumps(route53_roundrobin.template) | ||
|  |     cf.create_stack(StackName="test_stack", TemplateBody=template_json) | ||
|  | 
 | ||
|  |     zones = route53.list_hosted_zones()["HostedZones"] | ||
|  |     zones.should.have.length_of(1) | ||
|  |     zone_id = zones[0]["Id"].split("/")[2] | ||
|  | 
 | ||
|  |     rrsets = route53.list_resource_record_sets(HostedZoneId=zone_id)[ | ||
|  |         "ResourceRecordSets" | ||
|  |     ] | ||
|  |     rrsets.should.have.length_of(2) | ||
|  |     record_set1 = rrsets[0] | ||
|  |     record_set1["Name"].should.equal("test_stack.us-west-1.my_zone.") | ||
|  |     record_set1["SetIdentifier"].should.equal("test_stack AWS") | ||
|  |     record_set1["Type"].should.equal("CNAME") | ||
|  |     record_set1["TTL"].should.equal(900) | ||
|  |     record_set1["Weight"].should.equal(3) | ||
|  |     record_set1["ResourceRecords"][0]["Value"].should.equal("aws.amazon.com") | ||
|  | 
 | ||
|  |     record_set2 = rrsets[1] | ||
|  |     record_set2["Name"].should.equal("test_stack.us-west-1.my_zone.") | ||
|  |     record_set2["SetIdentifier"].should.equal("test_stack Amazon") | ||
|  |     record_set2["Type"].should.equal("CNAME") | ||
|  |     record_set2["TTL"].should.equal(900) | ||
|  |     record_set2["Weight"].should.equal(1) | ||
|  |     record_set2["ResourceRecords"][0]["Value"].should.equal("www.amazon.com") | ||
|  | 
 | ||
|  |     stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] | ||
|  |     output = stack["Outputs"][0] | ||
|  |     output["OutputKey"].should.equal("DomainName") | ||
|  |     output["OutputValue"].should.equal( | ||
|  |         "arn:aws:route53:::hostedzone/{0}".format(zone_id) | ||
|  |     ) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_cloudformation | ||
|  | @mock_ec2 | ||
|  | @mock_route53 | ||
|  | def test_route53_ec2_instance_with_public_ip(): | ||
|  |     route53 = boto3.client("route53", region_name="us-west-1") | ||
|  |     ec2 = boto3.client("ec2", region_name="us-west-1") | ||
|  | 
 | ||
|  |     template_json = json.dumps(route53_ec2_instance_with_public_ip.template) | ||
|  |     cf = boto3.client("cloudformation", region_name="us-west-1") | ||
|  |     cf.create_stack(StackName="test_stack", TemplateBody=template_json) | ||
|  | 
 | ||
|  |     instance_id = ec2.describe_instances()["Reservations"][0]["Instances"][0][ | ||
|  |         "InstanceId" | ||
|  |     ] | ||
|  | 
 | ||
|  |     zones = route53.list_hosted_zones()["HostedZones"] | ||
|  |     zones.should.have.length_of(1) | ||
|  |     zone_id = zones[0]["Id"].split("/")[2] | ||
|  | 
 | ||
|  |     rrsets = route53.list_resource_record_sets(HostedZoneId=zone_id)[ | ||
|  |         "ResourceRecordSets" | ||
|  |     ] | ||
|  |     rrsets.should.have.length_of(1) | ||
|  | 
 | ||
|  |     record_set = rrsets[0] | ||
|  |     record_set["Name"].should.equal("{0}.us-west-1.my_zone.".format(instance_id)) | ||
|  |     record_set.shouldnt.have.key("SetIdentifier") | ||
|  |     record_set["Type"].should.equal("A") | ||
|  |     record_set["TTL"].should.equal(900) | ||
|  |     record_set.shouldnt.have.key("Weight") | ||
|  |     record_set["ResourceRecords"][0]["Value"].should.equal("10.0.0.25") | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_cloudformation | ||
|  | @mock_route53 | ||
|  | def test_route53_associate_health_check(): | ||
|  |     route53 = boto3.client("route53", region_name="us-west-1") | ||
|  | 
 | ||
|  |     template_json = json.dumps(route53_health_check.template) | ||
|  |     cf = boto3.client("cloudformation", region_name="us-west-1") | ||
|  |     cf.create_stack(StackName="test_stack", TemplateBody=template_json) | ||
|  | 
 | ||
|  |     checks = route53.list_health_checks()["HealthChecks"] | ||
|  |     checks.should.have.length_of(1) | ||
|  |     check = checks[0] | ||
|  |     health_check_id = check["Id"] | ||
|  |     config = check["HealthCheckConfig"] | ||
|  |     config["FailureThreshold"].should.equal(3) | ||
|  |     config["IPAddress"].should.equal("10.0.0.4") | ||
|  |     config["Port"].should.equal(80) | ||
|  |     config["RequestInterval"].should.equal(10) | ||
|  |     config["ResourcePath"].should.equal("/") | ||
|  |     config["Type"].should.equal("HTTP") | ||
|  | 
 | ||
|  |     zones = route53.list_hosted_zones()["HostedZones"] | ||
|  |     zones.should.have.length_of(1) | ||
|  |     zone_id = zones[0]["Id"].split("/")[2] | ||
|  | 
 | ||
|  |     rrsets = route53.list_resource_record_sets(HostedZoneId=zone_id)[ | ||
|  |         "ResourceRecordSets" | ||
|  |     ] | ||
|  |     rrsets.should.have.length_of(1) | ||
|  |     record_set = rrsets[0] | ||
|  |     record_set["HealthCheckId"].should.equal(health_check_id) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_cloudformation | ||
|  | @mock_route53 | ||
|  | def test_route53_with_update(): | ||
|  |     route53 = boto3.client("route53", region_name="us-west-1") | ||
|  | 
 | ||
|  |     template_json = json.dumps(route53_health_check.template) | ||
|  |     cf = boto3.client("cloudformation", region_name="us-west-1") | ||
|  |     cf.create_stack(StackName="test_stack", TemplateBody=template_json) | ||
|  | 
 | ||
|  |     zones = route53.list_hosted_zones()["HostedZones"] | ||
|  |     zones.should.have.length_of(1) | ||
|  |     zone_id = zones[0]["Id"] | ||
|  |     zone_id = zone_id.split("/") | ||
|  |     zone_id = zone_id[2] | ||
|  | 
 | ||
|  |     rrsets = route53.list_resource_record_sets(HostedZoneId=zone_id)[ | ||
|  |         "ResourceRecordSets" | ||
|  |     ] | ||
|  |     rrsets.should.have.length_of(1) | ||
|  | 
 | ||
|  |     record_set = rrsets[0] | ||
|  |     record_set["ResourceRecords"][0]["Value"].should.equal("my.example.com") | ||
|  | 
 | ||
|  |     # given | ||
|  |     template = deepcopy(route53_health_check.template) | ||
|  |     template["Resources"]["myDNSRecord"]["Properties"]["ResourceRecords"] = [ | ||
|  |         "my_other.example.com" | ||
|  |     ] | ||
|  |     template_json = json.dumps(template) | ||
|  | 
 | ||
|  |     # when | ||
|  |     cf.update_stack(StackName="test_stack", TemplateBody=template_json) | ||
|  | 
 | ||
|  |     # then | ||
|  |     zones = route53.list_hosted_zones()["HostedZones"] | ||
|  |     zones.should.have.length_of(1) | ||
|  |     zone_id = zones[0]["Id"].split("/")[2] | ||
|  | 
 | ||
|  |     rrsets = route53.list_resource_record_sets(HostedZoneId=zone_id)[ | ||
|  |         "ResourceRecordSets" | ||
|  |     ] | ||
|  |     rrsets.should.have.length_of(1) | ||
|  | 
 | ||
|  |     record_set = rrsets[0] | ||
|  |     record_set["ResourceRecords"][0]["Value"].should.equal("my_other.example.com") |