241 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import boto3
 | |
| import json
 | |
| 
 | |
| 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]
 | |
|     assert zone["Name"] == "foo.bar.baz"
 | |
|     assert zone["ResourceRecordSetCount"] == 2
 | |
| 
 | |
|     # 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]
 | |
|     assert updated_zone["Id"] == zone["Id"]
 | |
|     assert updated_zone["Name"] == "foo.bar.baz"
 | |
|     assert updated_zone["ResourceRecordSetCount"] == 3
 | |
| 
 | |
| 
 | |
| @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"]
 | |
|     assert len(zones) == 1
 | |
|     zone_id = zones[0]["Id"].split("/")[2]
 | |
| 
 | |
|     rrsets = route53.list_resource_record_sets(HostedZoneId=zone_id)[
 | |
|         "ResourceRecordSets"
 | |
|     ]
 | |
|     assert len(rrsets) == 4
 | |
|     record_set1 = rrsets[2]
 | |
|     assert record_set1["Name"] == "test_stack.us-west-1.my_zone."
 | |
|     assert record_set1["SetIdentifier"] == "test_stack AWS"
 | |
|     assert record_set1["Type"] == "CNAME"
 | |
|     assert record_set1["TTL"] == 900
 | |
|     assert record_set1["Weight"] == 3
 | |
|     assert record_set1["ResourceRecords"][0]["Value"] == "aws.amazon.com"
 | |
| 
 | |
|     record_set2 = rrsets[3]
 | |
|     assert record_set2["Name"] == "test_stack.us-west-1.my_zone."
 | |
|     assert record_set2["SetIdentifier"] == "test_stack Amazon"
 | |
|     assert record_set2["Type"] == "CNAME"
 | |
|     assert record_set2["TTL"] == 900
 | |
|     assert record_set2["Weight"] == 1
 | |
|     assert record_set2["ResourceRecords"][0]["Value"] == "www.amazon.com"
 | |
| 
 | |
|     stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0]
 | |
|     output = stack["Outputs"][0]
 | |
|     assert output["OutputKey"] == "DomainName"
 | |
|     assert output["OutputValue"] == f"arn:aws:route53:::hostedzone/{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"]
 | |
|     assert len(zones) == 1
 | |
|     zone_id = zones[0]["Id"].split("/")[2]
 | |
| 
 | |
|     rrsets = route53.list_resource_record_sets(HostedZoneId=zone_id)[
 | |
|         "ResourceRecordSets"
 | |
|     ]
 | |
|     assert len(rrsets) == 3
 | |
| 
 | |
|     record_set = rrsets[2]
 | |
|     assert record_set["Name"] == f"{instance_id}.us-west-1.my_zone."
 | |
|     assert record_set["Type"] == "A"
 | |
|     assert record_set["TTL"] == 900
 | |
|     assert record_set["ResourceRecords"][0]["Value"] == "10.0.0.25"
 | |
|     assert "SetIdentifier" not in record_set
 | |
|     assert "Weight" not in record_set
 | |
| 
 | |
| 
 | |
| @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"]
 | |
|     assert len(checks) == 1
 | |
|     check = checks[0]
 | |
|     health_check_id = check["Id"]
 | |
|     config = check["HealthCheckConfig"]
 | |
|     assert config["FailureThreshold"] == 3
 | |
|     assert config["IPAddress"] == "10.0.0.4"
 | |
|     assert config["Port"] == 80
 | |
|     assert config["RequestInterval"] == 10
 | |
|     assert config["ResourcePath"] == "/"
 | |
|     assert config["Type"] == "HTTP"
 | |
| 
 | |
|     zones = route53.list_hosted_zones()["HostedZones"]
 | |
|     assert len(zones) == 1
 | |
|     zone_id = zones[0]["Id"].split("/")[2]
 | |
| 
 | |
|     rrsets = route53.list_resource_record_sets(HostedZoneId=zone_id)[
 | |
|         "ResourceRecordSets"
 | |
|     ]
 | |
|     assert len(rrsets) == 3
 | |
|     record_set = rrsets[0]
 | |
|     assert record_set["HealthCheckId"] == 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"]
 | |
|     assert len(zones) == 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"
 | |
|     ]
 | |
|     assert len(rrsets) == 3
 | |
| 
 | |
|     record_set = rrsets[0]
 | |
|     assert record_set["ResourceRecords"][0]["Value"] == "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"]
 | |
|     assert len(zones) == 1
 | |
|     zone_id = zones[0]["Id"].split("/")[2]
 | |
| 
 | |
|     rrsets = route53.list_resource_record_sets(HostedZoneId=zone_id)[
 | |
|         "ResourceRecordSets"
 | |
|     ]
 | |
|     assert len(rrsets) == 3
 | |
| 
 | |
|     record_set = rrsets[0]
 | |
|     assert record_set["ResourceRecords"][0]["Value"] == "my_other.example.com"
 | |
| 
 | |
| 
 | |
| @mock_cloudformation
 | |
| @mock_route53
 | |
| def test_delete_route53_recordset():
 | |
|     cf = boto3.client("cloudformation", region_name="us-west-1")
 | |
| 
 | |
|     # given a stack with a record set
 | |
|     stack_name = "test_stack_recordset_delete"
 | |
|     template_json = json.dumps(route53_health_check.template)
 | |
| 
 | |
|     cf.create_stack(StackName=stack_name, TemplateBody=template_json)
 | |
| 
 | |
|     # when the stack is deleted
 | |
|     cf.delete_stack(StackName=stack_name)
 | |
| 
 | |
|     # then it should not error
 |