Example #1
0
def test_query_parser_flattened_list_structure():
    """Simple test with a flattened list of structures."""
    parser = QueryRequestParser(load_service("sqs"))
    request = HttpRequest(
        body=to_bytes(
            "Action=DeleteMessageBatch&"
            "Version=2012-11-05&"
            "QueueUrl=http%3A%2F%2Flocalhost%3A4566%2F000000000000%2Ftf-acc-test-queue&"
            "DeleteMessageBatchRequestEntry.1.Id=bar&"
            "DeleteMessageBatchRequestEntry.1.ReceiptHandle=foo&"
            "DeleteMessageBatchRequestEntry.2.Id=bar&"
            "DeleteMessageBatchRequestEntry.2.ReceiptHandle=foo"),
        method="POST",
        headers={},
        path="",
    )
    operation, params = parser.parse(request)
    assert operation.name == "DeleteMessageBatch"
    assert params == {
        "QueueUrl":
        "http://localhost:4566/000000000000/tf-acc-test-queue",
        "Entries": [{
            "Id": "bar",
            "ReceiptHandle": "foo"
        }, {
            "Id": "bar",
            "ReceiptHandle": "foo"
        }],
    }
Example #2
0
def test_s3_virtual_host_addressing():
    """Test the parsing of a map with the location trait 'headers'."""
    request = HttpRequest(
        method="PUT",
        headers={"host": s3_utils.get_bucket_hostname("test-bucket")})
    parser = create_parser(load_service("s3"))
    parsed_operation_model, parsed_request = parser.parse(request)
    assert parsed_operation_model.name == "CreateBucket"
    assert "Bucket" in parsed_request
    assert parsed_request["Bucket"] == "test-bucket"
Example #3
0
def _botocore_parser_integration_test(service: str,
                                      action: str,
                                      headers: dict = None,
                                      expected: dict = None,
                                      **kwargs):
    # Load the appropriate service
    service = load_service(service)
    # Use the serializer from botocore to serialize the request params
    serializer = create_serializer(service.protocol)

    operation_model = service.operation_model(action)
    serialized_request = serializer.serialize_to_request(
        kwargs, operation_model)
    prepare_request_dict(serialized_request, "")
    split_url = urlsplit(serialized_request.get("url"))
    path = split_url.path
    query_string = split_url.query
    body = serialized_request["body"]
    # use custom headers (if provided), or headers from serialized request as default
    headers = serialized_request.get("headers") if headers is None else headers

    if service.protocol in ["query", "ec2"]:
        # Serialize the body as query parameter
        body = urlencode(serialized_request["body"])

    # Use our parser to parse the serialized body
    parser = create_parser(service)
    parsed_operation_model, parsed_request = parser.parse(
        HttpRequest(
            method=serialized_request.get("method") or "GET",
            path=unquote(path),
            query_string=to_str(query_string),
            headers=headers,
            body=body,
            raw_path=path,
        ))

    # Check if the determined operation_model is correct
    assert parsed_operation_model == operation_model

    # Check if the result is equal to the given "expected" dict or the kwargs (if "expected" has not been set)
    expected = expected or kwargs
    # The parser adds None for none-existing members on purpose. Remove those for the assert
    expected = {
        key: value
        for key, value in expected.items() if value is not None
    }
    parsed_request = {
        key: value
        for key, value in parsed_request.items() if value is not None
    }
    assert parsed_request == expected
Example #4
0
def test_restjson_operation_detection_with_subpath():
    """
    Tests if the operation lookup correctly fails for a subpath of an operation.
    For example: The detection of a URL which is routed through API Gateway.
    """
    service = load_service("apigateway")
    parser = create_parser(service)
    with pytest.raises(OperationNotFoundParserError):
        parser.parse(
            HttpRequest(
                method="GET",
                path="/restapis/cmqinv79uh/local/_user_request_/",
                raw_path="/restapis/cmqinv79uh/local/_user_request_/",
            ))
Example #5
0
    def test_missing_required_field_restjson(self):
        parser = create_parser(load_service("opensearch"))

        op, params = parser.parse(
            HttpRequest(
                "POST",
                "/2021-01-01/tags",
                body='{"ARN":"somearn"}',
            ))

        with pytest.raises(MissingRequiredField) as e:
            validate_request(op, params).raise_first()

        assert e.value.error.reason == "missing required field"
        assert e.value.required_name == "TagList"
Example #6
0
def test_parser_error_on_protocol_error():
    """Test that the parser raises a ProtocolParserError in case of invalid data to parse."""
    parser = QueryRequestParser(load_service("sqs"))
    request = HttpRequest(
        body=to_bytes(
            "Action=UnknownOperation&Version=2012-11-05&"
            "QueueUrl=http%3A%2F%2Flocalhost%3A4566%2F000000000000%2Ftf-acc-test-queue&"
            "MessageBody=%7B%22foo%22%3A+%22bared%22%7D&"
            "DelaySeconds=2"),
        method="POST",
        headers={},
        path="",
    )
    with pytest.raises(ProtocolParserError):
        parser.parse(request)
Example #7
0
    def test_missing_required_field_restxml(self):
        parser = create_parser(load_service("route53"))

        op, params = parser.parse(
            HttpRequest(
                "POST",
                "/2013-04-01/hostedzone",
                body=
                "<CreateHostedZoneRequest><Name>foobar.com</Name></CreateHostedZoneRequest>",
            ))

        with pytest.raises(MissingRequiredField) as e:
            validate_request(op, params).raise_first()

        assert e.value.error.reason == "missing required field"
        assert e.value.required_name == "CallerReference"
Example #8
0
def test_query_parser_non_flattened_list_structure():
    """Simple test with a non-flattened list structure (CloudFormation CreateChangeSet)."""
    parser = QueryRequestParser(load_service("cloudformation"))
    request = HttpRequest(
        body=to_bytes(
            "Action=CreateChangeSet&"
            "ChangeSetName=SampleChangeSet&"
            "Parameters.member.1.ParameterKey=KeyName&"
            "Parameters.member.1.UsePreviousValue=true&"
            "Parameters.member.2.ParameterKey=Purpose&"
            "Parameters.member.2.ParameterValue=production&"
            "StackName=arn:aws:cloudformation:us-east-1:123456789012:stack/SampleStack/1a2345b6-0000-00a0-a123-00abc0abc000&"
            "UsePreviousTemplate=true&"
            "Version=2010-05-15&"
            "X-Amz-Algorithm=AWS4-HMAC-SHA256&"
            "X-Amz-Credential=[Access-key-ID-and-scope]&"
            "X-Amz-Date=20160316T233349Z&"
            "X-Amz-SignedHeaders=content-type;host&"
            "X-Amz-Signature=[Signature]"),
        method="POST",
        headers={},
        path="",
    )
    operation, params = parser.parse(request)
    assert operation.name == "CreateChangeSet"
    assert params == {
        "StackName":
        "arn:aws:cloudformation:us-east-1:123456789012:stack/SampleStack/1a2345b6-0000-00a0-a123-00abc0abc000",
        "UsePreviousTemplate":
        True,
        "Parameters": [
            {
                "ParameterKey": "KeyName",
                "UsePreviousValue": True
            },
            {
                "ParameterKey": "Purpose",
                "ParameterValue": "production"
            },
        ],
        "ChangeSetName":
        "SampleChangeSet",
    }
Example #9
0
    def test_invalid_length_query(self):
        parser = create_parser(load_service("sts"))

        op, params = parser.parse(
            HttpRequest(
                "POST",
                "/",
                body=urlencode(
                    query={
                        "Action": "AssumeRole",
                        "RoleArn": "arn:aws",  # min=8
                        "RoleSessionName": "foobared",
                    }),
                headers={"Content-Type": "application/x-www-form-urlencoded"},
            ))

        with pytest.raises(InvalidLength) as e:
            validate_request(op, params).raise_first()

        e.match("RoleArn")
Example #10
0
def test_query_parser():
    """Basic test for the QueryParser with a simple example (SQS SendMessage request)."""
    parser = QueryRequestParser(load_service("sqs"))
    request = HttpRequest(
        body=to_bytes(
            "Action=SendMessage&Version=2012-11-05&"
            "QueueUrl=http%3A%2F%2Flocalhost%3A4566%2F000000000000%2Ftf-acc-test-queue&"
            "MessageBody=%7B%22foo%22%3A+%22bared%22%7D&"
            "DelaySeconds=2"),
        method="POST",
        headers={},
        path="",
    )
    operation, params = parser.parse(request)
    assert operation.name == "SendMessage"
    assert params == {
        "QueueUrl": "http://localhost:4566/000000000000/tf-acc-test-queue",
        "MessageBody": '{"foo": "bared"}',
        "DelaySeconds": 2,
    }
Example #11
0
    def test_invalid_range_query(self):
        parser = create_parser(load_service("sts"))

        op, params = parser.parse(
            HttpRequest(
                "POST",
                "/",
                body=urlencode(
                    query={
                        "Action": "AssumeRole",
                        "RoleArn": "arn:aws:iam::000000000000:role/foobared",
                        "RoleSessionName": "foobared",
                        "DurationSeconds": "100",
                    }),
                headers={"Content-Type": "application/x-www-form-urlencoded"},
            ))

        with pytest.raises(InvalidRange) as e:
            validate_request(op, params).raise_first()

        e.match("DurationSeconds")
Example #12
0
def test_parser_error_on_unknown_error():
    """Test that the parser raises a UnknownParserError in case of an unknown exception."""
    parser = QueryRequestParser(load_service("sqs"))

    request = HttpRequest(
        body=to_bytes(
            "Action=SendMessage&Version=2012-11-05&"
            "QueueUrl=http%3A%2F%2Flocalhost%3A4566%2F000000000000%2Ftf-acc-test-queue&"
            "MessageBody=%7B%22foo%22%3A+%22bared%22%7D&"
            "DelaySeconds=2"),
        method="POST",
        headers={},
        path="",
    )

    # An unknown error is obviously hard to trigger (because we would fix it if we would know of a way to trigger it),
    # therefore we patch a function to raise an unexpected error
    def raise_error(*args, **kwargs):
        raise NotImplementedError()

    parser._process_member = raise_error
    with pytest.raises(UnknownParserError):
        parser.parse(request)
Example #13
0
def test_query_parser_non_flattened_list_structure_changed_name():
    """Simple test with a non-flattened list structure where the name of the list differs from the shape's name
    (CloudWatch PutMetricData)."""
    parser = QueryRequestParser(load_service("cloudwatch"))
    request = HttpRequest(
        body=to_bytes(
            "Action=PutMetricData&"
            "Version=2010-08-01&"
            "Namespace=TestNamespace&"
            "MetricData.member.1.MetricName=buffers&"
            "MetricData.member.1.Unit=Bytes&"
            "MetricData.member.1.Value=231434333&"
            "MetricData.member.1.Dimensions.member.1.Name=InstanceType&"
            "MetricData.member.1.Dimensions.member.1.Value=m1.small&"
            "AUTHPARAMS"),
        method="POST",
        headers={},
        path="",
    )
    operation, params = parser.parse(request)
    assert operation.name == "PutMetricData"
    assert params == {
        "MetricData": [{
            "Dimensions": [{
                "Name": "InstanceType",
                "Value": "m1.small"
            }],
            "MetricName":
            "buffers",
            "Unit":
            "Bytes",
            "Value":
            231434333.0,
        }],
        "Namespace":
        "TestNamespace",
    }
Example #14
0
    def test_missing_required_field_query(self):
        parser = create_parser(load_service("sqs"))

        op, params = parser.parse(
            HttpRequest(
                "POST",
                "/",
                body=
                ("Action=SendMessage&Version=2012-11-05&"
                 "QueueUrl=http%3A%2F%2Flocalhost%3A4566%2F000000000000%2Ftf-acc-test-queue&"
                 ),
                headers={"Content-Type": "application/x-www-form-urlencoded"},
            ))

        validator = ParamValidator()
        errors = validator.validate(params, op.input_shape)
        assert errors.has_errors()

        with pytest.raises(MissingRequiredField) as e:
            errors.raise_first()

        assert e.match("MessageBody")
        assert e.value.error.reason == "missing required field"
        assert e.value.required_name == "MessageBody"
Example #15
0
def test_query_parser_flattened_map():
    """Simple test with a flattened map (SQS SetQueueAttributes request)."""
    parser = QueryRequestParser(load_service("sqs"))
    request = HttpRequest(
        body=to_bytes(
            "Action=SetQueueAttributes&Version=2012-11-05&"
            "QueueUrl=http%3A%2F%2Flocalhost%3A4566%2F000000000000%2Ftf-acc-test-queue&"
            "Attribute.1.Name=DelaySeconds&"
            "Attribute.1.Value=10&"
            "Attribute.2.Name=MaximumMessageSize&"
            "Attribute.2.Value=131072&"
            "Attribute.3.Name=MessageRetentionPeriod&"
            "Attribute.3.Value=259200&"
            "Attribute.4.Name=ReceiveMessageWaitTimeSeconds&"
            "Attribute.4.Value=20&"
            "Attribute.5.Name=RedrivePolicy&"
            "Attribute.5.Value=%7B%22deadLetterTargetArn%22%3A%22arn%3Aaws%3Asqs%3Aus-east-1%3A80398EXAMPLE%3AMyDeadLetterQueue%22%2C%22maxReceiveCount%22%3A%221000%22%7D&"
            "Attribute.6.Name=VisibilityTimeout&Attribute.6.Value=60"),
        method="POST",
        headers={},
        path="",
    )
    operation, params = parser.parse(request)
    assert operation.name == "SetQueueAttributes"
    assert params == {
        "QueueUrl": "http://localhost:4566/000000000000/tf-acc-test-queue",
        "Attributes": {
            "DelaySeconds": "10",
            "MaximumMessageSize": "131072",
            "MessageRetentionPeriod": "259200",
            "ReceiveMessageWaitTimeSeconds": "20",
            "RedrivePolicy":
            '{"deadLetterTargetArn":"arn:aws:sqs:us-east-1:80398EXAMPLE:MyDeadLetterQueue","maxReceiveCount":"1000"}',
            "VisibilityTimeout": "60",
        },
    }
Example #16
0
def test_query_parser_non_flattened_map():
    """Simple test with a flattened map (SQS SetQueueAttributes request)."""
    parser = QueryRequestParser(load_service("sns"))
    request = HttpRequest(
        body=to_bytes(
            "Action=SetEndpointAttributes&"
            "EndpointArn=arn%3Aaws%3Asns%3Aus-west-2%3A123456789012%3Aendpoint%2FGCM%2Fgcmpushapp%2F5e3e9847-3183-3f18-a7e8-671c3a57d4b3&"
            "Attributes.entry.1.key=CustomUserData&"
            "Attributes.entry.1.value=My+custom+userdata&"
            "Version=2010-03-31&"
            "AUTHPARAMS"),
        method="POST",
        headers={},
        path="",
    )
    operation, params = parser.parse(request)
    assert operation.name == "SetEndpointAttributes"
    assert params == {
        "Attributes": {
            "CustomUserData": "My custom userdata"
        },
        "EndpointArn":
        "arn:aws:sns:us-west-2:123456789012:endpoint/GCM/gcmpushapp/5e3e9847-3183-3f18-a7e8-671c3a57d4b3",
    }