278 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			278 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | """Route53 unit tests specific to query_logging_config APIs.""" | ||
|  | import pytest | ||
|  | 
 | ||
|  | import boto3 | ||
|  | from botocore.exceptions import ClientError | ||
|  | 
 | ||
|  | from moto import mock_logs | ||
|  | from moto import mock_route53 | ||
|  | from moto.core import ACCOUNT_ID | ||
|  | from moto.core.utils import get_random_hex | ||
|  | 
 | ||
|  | # The log group must be in the us-east-1 region. | ||
|  | TEST_REGION = "us-east-1" | ||
|  | 
 | ||
|  | 
 | ||
|  | def create_hosted_zone_id(route53_client, hosted_zone_test_name): | ||
|  |     """Return ID of a newly created Route53 public hosted zone""" | ||
|  |     response = route53_client.create_hosted_zone( | ||
|  |         Name=hosted_zone_test_name, | ||
|  |         CallerReference=f"test_caller_ref_{get_random_hex(6)}", | ||
|  |     ) | ||
|  |     assert response["ResponseMetadata"]["HTTPStatusCode"] == 201 | ||
|  |     assert "HostedZone" in response and response["HostedZone"]["Id"] | ||
|  |     return response["HostedZone"]["Id"] | ||
|  | 
 | ||
|  | 
 | ||
|  | def create_log_group_arn(logs_client, hosted_zone_test_name): | ||
|  |     """Return ARN of a newly created CloudWatch log group.""" | ||
|  |     log_group_name = f"/aws/route53/{hosted_zone_test_name}" | ||
|  |     response = logs_client.create_log_group(logGroupName=log_group_name) | ||
|  |     assert response["ResponseMetadata"]["HTTPStatusCode"] == 200 | ||
|  | 
 | ||
|  |     log_group_arn = None | ||
|  |     response = logs_client.describe_log_groups() | ||
|  |     for entry in response["logGroups"]: | ||
|  |         if entry["logGroupName"] == log_group_name: | ||
|  |             log_group_arn = entry["arn"] | ||
|  |             break | ||
|  |     return log_group_arn | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_logs | ||
|  | @mock_route53 | ||
|  | def test_create_query_logging_config_bad_args(): | ||
|  |     """Test bad arguments to create_query_logging_config().""" | ||
|  |     client = boto3.client("route53", region_name=TEST_REGION) | ||
|  |     logs_client = boto3.client("logs", region_name=TEST_REGION) | ||
|  | 
 | ||
|  |     hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test" | ||
|  |     hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name) | ||
|  |     log_group_arn = create_log_group_arn(logs_client, hosted_zone_test_name) | ||
|  | 
 | ||
|  |     # Check exception:  NoSuchHostedZone | ||
|  |     with pytest.raises(ClientError) as exc: | ||
|  |         client.create_query_logging_config( | ||
|  |             HostedZoneId="foo", CloudWatchLogsLogGroupArn=log_group_arn, | ||
|  |         ) | ||
|  |     err = exc.value.response["Error"] | ||
|  |     assert err["Code"] == "NoSuchHostedZone" | ||
|  |     assert "No hosted zone found with ID: foo" in err["Message"] | ||
|  | 
 | ||
|  |     # Check exception:  InvalidInput (bad CloudWatch Logs log ARN) | ||
|  |     with pytest.raises(ClientError) as exc: | ||
|  |         client.create_query_logging_config( | ||
|  |             HostedZoneId=hosted_zone_id, | ||
|  |             CloudWatchLogsLogGroupArn=f"arn:aws:logs:{TEST_REGION}:{ACCOUNT_ID}:foo-bar:foo", | ||
|  |         ) | ||
|  |     err = exc.value.response["Error"] | ||
|  |     assert err["Code"] == "InvalidInput" | ||
|  |     assert "The ARN for the CloudWatch Logs log group is invalid" in err["Message"] | ||
|  | 
 | ||
|  |     # Check exception:  InvalidInput (CloudWatch Logs log not in us-east-1) | ||
|  |     with pytest.raises(ClientError) as exc: | ||
|  |         client.create_query_logging_config( | ||
|  |             HostedZoneId=hosted_zone_id, | ||
|  |             CloudWatchLogsLogGroupArn=log_group_arn.replace(TEST_REGION, "us-west-1"), | ||
|  |         ) | ||
|  |     err = exc.value.response["Error"] | ||
|  |     assert err["Code"] == "InvalidInput" | ||
|  |     assert "The ARN for the CloudWatch Logs log group is invalid" in err["Message"] | ||
|  | 
 | ||
|  |     # Check exception:  NoSuchCloudWatchLogsLogGroup | ||
|  |     with pytest.raises(ClientError) as exc: | ||
|  |         client.create_query_logging_config( | ||
|  |             HostedZoneId=hosted_zone_id, | ||
|  |             CloudWatchLogsLogGroupArn=log_group_arn.replace( | ||
|  |                 hosted_zone_test_name, "foo" | ||
|  |             ), | ||
|  |         ) | ||
|  |     err = exc.value.response["Error"] | ||
|  |     assert err["Code"] == "NoSuchCloudWatchLogsLogGroup" | ||
|  |     assert "The specified CloudWatch Logs log group doesn't exist" in err["Message"] | ||
|  | 
 | ||
|  |     # Check exception:  QueryLoggingConfigAlreadyExists | ||
|  |     client.create_query_logging_config( | ||
|  |         HostedZoneId=hosted_zone_id, CloudWatchLogsLogGroupArn=log_group_arn, | ||
|  |     ) | ||
|  |     with pytest.raises(ClientError) as exc: | ||
|  |         client.create_query_logging_config( | ||
|  |             HostedZoneId=hosted_zone_id, CloudWatchLogsLogGroupArn=log_group_arn, | ||
|  |         ) | ||
|  |     err = exc.value.response["Error"] | ||
|  |     assert err["Code"] == "QueryLoggingConfigAlreadyExists" | ||
|  |     assert ( | ||
|  |         "A query logging configuration already exists for this hosted zone" | ||
|  |         in err["Message"] | ||
|  |     ) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_logs | ||
|  | @mock_route53 | ||
|  | def test_create_query_logging_config_good_args(): | ||
|  |     """Test a valid create_logging_config() request.""" | ||
|  |     client = boto3.client("route53", region_name=TEST_REGION) | ||
|  |     logs_client = boto3.client("logs", region_name=TEST_REGION) | ||
|  | 
 | ||
|  |     hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test" | ||
|  |     hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name) | ||
|  |     log_group_arn = create_log_group_arn(logs_client, hosted_zone_test_name) | ||
|  | 
 | ||
|  |     response = client.create_query_logging_config( | ||
|  |         HostedZoneId=hosted_zone_id, CloudWatchLogsLogGroupArn=log_group_arn, | ||
|  |     ) | ||
|  |     config = response["QueryLoggingConfig"] | ||
|  |     assert config["HostedZoneId"] == hosted_zone_id.split("/")[-1] | ||
|  |     assert config["CloudWatchLogsLogGroupArn"] == log_group_arn | ||
|  |     assert config["Id"] | ||
|  | 
 | ||
|  |     location = response["Location"] | ||
|  |     assert ( | ||
|  |         location | ||
|  |         == f"https://route53.amazonaws.com/2013-04-01/queryloggingconfig/{config['Id']}" | ||
|  |     ) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_logs | ||
|  | @mock_route53 | ||
|  | def test_delete_query_logging_config(): | ||
|  |     """Test valid and invalid delete_query_logging_config requests.""" | ||
|  |     client = boto3.client("route53", region_name=TEST_REGION) | ||
|  |     logs_client = boto3.client("logs", region_name=TEST_REGION) | ||
|  | 
 | ||
|  |     # Create a query logging config that can then be deleted. | ||
|  |     hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test" | ||
|  |     hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name) | ||
|  |     log_group_arn = create_log_group_arn(logs_client, hosted_zone_test_name) | ||
|  | 
 | ||
|  |     query_response = client.create_query_logging_config( | ||
|  |         HostedZoneId=hosted_zone_id, CloudWatchLogsLogGroupArn=log_group_arn, | ||
|  |     ) | ||
|  | 
 | ||
|  |     # Test the deletion. | ||
|  |     query_id = query_response["QueryLoggingConfig"]["Id"] | ||
|  |     response = client.delete_query_logging_config(Id=query_id) | ||
|  |     # There is no response other than the usual ResponseMetadata. | ||
|  |     assert list(response.keys()) == ["ResponseMetadata"] | ||
|  | 
 | ||
|  |     # Test the deletion of a non-existent query logging config, i.e., the | ||
|  |     # one that was just deleted. | ||
|  |     with pytest.raises(ClientError) as exc: | ||
|  |         client.delete_query_logging_config(Id=query_id) | ||
|  |     err = exc.value.response["Error"] | ||
|  |     assert err["Code"] == "NoSuchQueryLoggingConfig" | ||
|  |     assert "The query logging configuration does not exist" in err["Message"] | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_logs | ||
|  | @mock_route53 | ||
|  | def test_get_query_logging_config(): | ||
|  |     """Test valid and invalid get_query_logging_config requests.""" | ||
|  |     client = boto3.client("route53", region_name=TEST_REGION) | ||
|  |     logs_client = boto3.client("logs", region_name=TEST_REGION) | ||
|  | 
 | ||
|  |     # Create a query logging config that can then be retrieved. | ||
|  |     hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test" | ||
|  |     hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name) | ||
|  |     log_group_arn = create_log_group_arn(logs_client, hosted_zone_test_name) | ||
|  | 
 | ||
|  |     query_response = client.create_query_logging_config( | ||
|  |         HostedZoneId=hosted_zone_id, CloudWatchLogsLogGroupArn=log_group_arn, | ||
|  |     ) | ||
|  | 
 | ||
|  |     # Test the retrieval. | ||
|  |     query_id = query_response["QueryLoggingConfig"]["Id"] | ||
|  |     response = client.get_query_logging_config(Id=query_id) | ||
|  |     config = response["QueryLoggingConfig"] | ||
|  |     assert config["HostedZoneId"] == hosted_zone_id.split("/")[-1] | ||
|  |     assert config["CloudWatchLogsLogGroupArn"] == log_group_arn | ||
|  |     assert config["Id"] | ||
|  | 
 | ||
|  |     # Test the retrieval of a non-existent query logging config. | ||
|  |     with pytest.raises(ClientError) as exc: | ||
|  |         client.get_query_logging_config(Id="1234567890") | ||
|  |     err = exc.value.response["Error"] | ||
|  |     assert err["Code"] == "NoSuchQueryLoggingConfig" | ||
|  |     assert "The query logging configuration does not exist" in err["Message"] | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_logs | ||
|  | @mock_route53 | ||
|  | def test_list_query_logging_configs_bad_args(): | ||
|  |     """Test bad arguments to list_query_logging_configs().""" | ||
|  |     client = boto3.client("route53", region_name=TEST_REGION) | ||
|  |     logs_client = boto3.client("logs", region_name=TEST_REGION) | ||
|  | 
 | ||
|  |     # Check exception:  NoSuchHostedZone | ||
|  |     with pytest.raises(ClientError) as exc: | ||
|  |         client.list_query_logging_configs(HostedZoneId="foo", MaxResults="10") | ||
|  |     err = exc.value.response["Error"] | ||
|  |     assert err["Code"] == "NoSuchHostedZone" | ||
|  |     assert "No hosted zone found with ID: foo" in err["Message"] | ||
|  | 
 | ||
|  |     # Create a couple of query logging configs to work with. | ||
|  |     for _ in range(3): | ||
|  |         hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test" | ||
|  |         hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name) | ||
|  |         log_group_arn = create_log_group_arn(logs_client, hosted_zone_test_name) | ||
|  |         client.create_query_logging_config( | ||
|  |             HostedZoneId=hosted_zone_id, CloudWatchLogsLogGroupArn=log_group_arn, | ||
|  |         ) | ||
|  | 
 | ||
|  |     # Retrieve a query logging config, then request more with an invalid token. | ||
|  |     client.list_query_logging_configs(MaxResults="1") | ||
|  |     with pytest.raises(ClientError) as exc: | ||
|  |         client.list_query_logging_configs(NextToken="foo") | ||
|  |     err = exc.value.response["Error"] | ||
|  |     assert err["Code"] == "InvalidPaginationToken" | ||
|  |     assert ( | ||
|  |         "Route 53 can't get the next page of query logging configurations " | ||
|  |         "because the specified value for NextToken is invalid." in err["Message"] | ||
|  |     ) | ||
|  | 
 | ||
|  | 
 | ||
|  | @mock_logs | ||
|  | @mock_route53 | ||
|  | def test_list_query_logging_configs_good_args(): | ||
|  |     """Test valid arguments to list_query_logging_configs().""" | ||
|  |     client = boto3.client("route53", region_name=TEST_REGION) | ||
|  |     logs_client = boto3.client("logs", region_name=TEST_REGION) | ||
|  | 
 | ||
|  |     # Test when there are no query logging configs. | ||
|  |     response = client.list_query_logging_configs() | ||
|  |     query_logging_configs = response["QueryLoggingConfigs"] | ||
|  |     assert len(query_logging_configs) == 0 | ||
|  | 
 | ||
|  |     # Create a couple of query logging configs to work with. | ||
|  |     zone_ids = [] | ||
|  |     for _ in range(10): | ||
|  |         hosted_zone_test_name = f"route53_query_log_{get_random_hex(6)}.test" | ||
|  |         hosted_zone_id = create_hosted_zone_id(client, hosted_zone_test_name) | ||
|  |         zone_ids.append(hosted_zone_id) | ||
|  | 
 | ||
|  |         log_group_arn = create_log_group_arn(logs_client, hosted_zone_test_name) | ||
|  |         client.create_query_logging_config( | ||
|  |             HostedZoneId=hosted_zone_id, CloudWatchLogsLogGroupArn=log_group_arn, | ||
|  |         ) | ||
|  | 
 | ||
|  |     # Verify all 10 of the query logging configs can be retrieved in one go. | ||
|  |     response = client.list_query_logging_configs() | ||
|  |     query_logging_configs = response["QueryLoggingConfigs"] | ||
|  |     assert len(query_logging_configs) == 10 | ||
|  |     for idx, query_logging_config in enumerate(query_logging_configs): | ||
|  |         assert query_logging_config["HostedZoneId"] == zone_ids[idx].split("/")[-1] | ||
|  | 
 | ||
|  |     # Request only two of the query logging configs and verify there's a | ||
|  |     # next_token. | ||
|  |     response = client.list_query_logging_configs(MaxResults="2") | ||
|  |     assert len(response["QueryLoggingConfigs"]) == 2 | ||
|  |     assert response["NextToken"] | ||
|  | 
 | ||
|  |     # Request the remaining 8 query logging configs and verify there is | ||
|  |     # no next token. | ||
|  |     response = client.list_query_logging_configs( | ||
|  |         MaxResults="8", NextToken=response["NextToken"] | ||
|  |     ) | ||
|  |     assert len(response["QueryLoggingConfigs"]) == 8 | ||
|  |     assert "NextToken" not in response |