Ejemplo n.º 1
0
    def test_validate_ignores_response_metadata(self):
        service_response = {'ResponseMetadata': {'foo': 'bar'}}
        service_model = ServiceModel({
            'documentation': '',
            'operations': {
                'foo': {
                    'name': 'foo',
                    'input': {'shape': 'StringShape'},
                    'output': {'shape': 'StringShape'}
                }
            },
            'shapes': {
                'StringShape': {'type': 'string'}
            }
        })
        op_name = service_model.operation_names[0]
        output_shape = service_model.operation_model(op_name).output_shape

        self.client.meta.service_model = service_model
        self.stubber.add_response('TestOperation', service_response)
        self.validate_parameters_mock.assert_called_with(
            {}, output_shape)

        # Make sure service response hasn't been mutated
        self.assertEqual(
            service_response, {'ResponseMetadata': {'foo': 'bar'}})
Ejemplo n.º 2
0
 def _load_service_model(self, service_name, api_version=None):
     json_model = self._loader.load_service_model(service_name,
                                                  'service-2',
                                                  api_version=api_version)
     service_model = ServiceModel(json_model, service_name=service_name)
     self._register_retries(service_model)
     return service_model
Ejemplo n.º 3
0
 def setUp(self):
     self.model = {
         'metadata': {'protocol': 'json', 'apiVersion': '2014-01-01',
                      'jsonVersion': '1.1', 'targetPrefix': 'foo'},
         'documentation': '',
         'operations': {
             'TestOperation': {
                 'name': 'TestOperation',
                 'http': {
                     'method': 'POST',
                     'requestUri': '/',
                 },
                 'input': {'shape': 'InputShape'},
             }
         },
         'shapes': {
             'InputShape': {
                 'type': 'structure',
                 'members': {
                     'Timestamp': {'shape': 'TimestampType'},
                 }
             },
             'TimestampType': {
                 'type': 'timestamp',
             }
         }
     }
     self.service_model = ServiceModel(self.model)
Ejemplo n.º 4
0
class TestCLIArgument(unittest.TestCase):
    def setUp(self):
        self.service_name = "baz"
        self.service_model = ServiceModel(
            {
                "metadata": {"endpointPrefix": "bad"},
                "operations": {"SampleOperation": {"name": "SampleOperation", "input": {"shape": "Input"}}},
                "shapes": {
                    "StringShape": {"type": "string"},
                    "Input": {"type": "structure", "members": {"Foo": {"shape": "StringShape"}}},
                },
            },
            self.service_name,
        )
        self.operation_model = self.service_model.operation_model("SampleOperation")
        self.argument_model = self.operation_model.input_shape.members["Foo"]
        self.event_emitter = mock.Mock()

    def create_argument(self):
        return arguments.CLIArgument(
            self.argument_model.name, self.argument_model, self.operation_model, self.event_emitter
        )

    def test_unpack_uses_service_name_in_event(self):
        self.event_emitter.emit.return_value = ["value"]
        argument = self.create_argument()
        params = {}
        argument.add_to_params(params, "value")
        expected_event_name = "process-cli-arg.%s.%s" % (self.service_name, "sample-operation")
        actual_event_name = self.event_emitter.emit.call_args[0][0]
        self.assertEqual(actual_event_name, expected_event_name)
Ejemplo n.º 5
0
class TestBinaryTypes(unittest.TestCase):

    def setUp(self):
        self.model = {
            'metadata': {'protocol': 'query', 'apiVersion': '2014-01-01'},
            'documentation': '',
            'operations': {
                'TestOperation': {
                    'name': 'TestOperation',
                    'http': {
                        'method': 'POST',
                        'requestUri': '/',
                    },
                    'input': {'shape': 'InputShape'},
                }
            },
            'shapes': {
                'InputShape': {
                    'type': 'structure',
                    'members': {
                        'Blob': {'shape': 'BlobType'},
                    }
                },
                'BlobType': {
                    'type': 'blob',
                }
            }
        }
        self.service_model = ServiceModel(self.model)

    def serialize_to_request(self, input_params):
        request_serializer = serialize.create_serializer(
            self.service_model.metadata['protocol'])
        return request_serializer.serialize_to_request(
            input_params, self.service_model.operation_model('TestOperation'))

    def assert_serialized_blob_equals(self, request, blob_bytes):
        # This method handles all the details of the base64 decoding.
        encoded = base64.b64encode(blob_bytes)
        # Now the serializers actually have the base64 encoded contents
        # as str types so we need to decode back.  We know that this is
        # ascii so it's safe to use the ascii encoding.
        expected = encoded.decode('ascii')
        self.assertEqual(request['body']['Blob'], expected)

    def test_blob_accepts_bytes_type(self):
        body = b'bytes body'
        request = self.serialize_to_request(input_params={'Blob': body})

    def test_blob_accepts_str_type(self):
        body = u'ascii text'
        request = self.serialize_to_request(input_params={'Blob': body})
        self.assert_serialized_blob_equals(
            request, blob_bytes=body.encode('ascii'))

    def test_blob_handles_unicode_chars(self):
        body = u'\u2713'
        request = self.serialize_to_request(input_params={'Blob': body})
        self.assert_serialized_blob_equals(
            request, blob_bytes=body.encode('utf-8'))
Ejemplo n.º 6
0
 def setUp(self):
     self.model = {
         'metadata': {'protocol': 'rest-xml', 'apiVersion': '2014-01-01'},
         'documentation': '',
         'operations': {
             'TestOperation': {
                 'name': 'TestOperation',
                 'http': {
                     'method': 'POST',
                     'requestUri': '/',
                 },
                 'input': {'shape': 'InputShape'},
             }
         },
         'shapes': {
             'InputShape': {
                 'type': 'structure',
                 'members': {
                     'TimestampHeader': {
                         'shape': 'TimestampType',
                         'location': 'header',
                         'locationName': 'x-timestamp'
                     },
                 }
             },
             'TimestampType': {
                 'type': 'timestamp',
             }
         }
     }
     self.service_model = ServiceModel(self.model)
Ejemplo n.º 7
0
 def setUp(self):
     self.model = {
         'metadata': {'protocol': 'rest-xml', 'apiVersion': '2014-01-01'},
         'documentation': '',
         'operations': {
             'TestOperation': {
                 'name': 'TestOperation',
                 'http': {
                     'method': 'POST',
                     'requestUri': '/',
                 },
                 'input': {'shape': 'InputShape'},
             }
         },
         'shapes': {
             'InputShape': {
                 'type': 'structure',
                 'members': {
                     'Foo': {
                         'shape': 'FooShape',
                         'locationName': 'Foo'
                     },
                 },
                 'payload': 'Foo'
             },
             'FooShape': {
                 'type': 'list',
                 'member': {'shape': 'StringShape'}
             },
             'StringShape': {
                 'type': 'string',
             }
         }
     }
     self.service_model = ServiceModel(self.model)
Ejemplo n.º 8
0
    def test_route53_resource_id(self):
        event = self.session.create_event('before-parameter-build', 'route53',
                                          'GetHostedZone')
        params = {
            'Id': '/hostedzone/ABC123',
            'HostedZoneId': '/hostedzone/ABC123',
            'ResourceId': '/hostedzone/DEF456',
            'DelegationSetId': '/hostedzone/GHI789',
            'Other': '/hostedzone/foo'
        }
        operation_def = {
            'name': 'GetHostedZone',
            'input': {
                'shape': 'GetHostedZoneInput'
            }
        }
        service_def = {
            'metadata': {},
            'shapes': {
                'GetHostedZoneInput': {
                    'type': 'structure',
                    'members': {
                        'Id': {
                            'shape': 'ResourceId'
                        },
                        'HostedZoneId': {
                            'shape': 'ResourceId'
                        },
                        'ResourceId': {
                            'shape': 'ResourceId'
                        },
                        'DelegationSetId': {
                            'shape': 'DelegationSetId'
                        },
                        'Other': {
                            'shape': 'String'
                        }
                    }
                },
                'ResourceId': {
                    'type': 'string'
                },
                'DelegationSetId': {
                    'type': 'string'
                },
                'String': {
                    'type': 'string'
                }
            }
        }
        model = OperationModel(operation_def, ServiceModel(service_def))
        self.session.emit(event, params=params, model=model)

        self.assertEqual(params['Id'], 'ABC123')
        self.assertEqual(params['HostedZoneId'], 'ABC123')
        self.assertEqual(params['ResourceId'], 'DEF456')
        self.assertEqual(params['DelegationSetId'], 'GHI789')

        # This one should have been left alone
        self.assertEqual(params['Other'], '/hostedzone/foo')
Ejemplo n.º 9
0
def get_model_location(session, service_definition, service_name=None):
    """Gets the path of where a service-2.json file should go in ~/.aws/models

    :type session: botocore.session.Session
    :param session: A session object

    :type service_definition: dict
    :param service_definition: The json loaded service definition

    :type service_name: str
    :param service_name: The service name to use. If this not provided,
        this will be determined from a combination of available services
        and the service definition.

    :returns: The path to where are model should be placed based on
        the service defintion and the current services in botocore.
    """
    # Add the ServiceModel abstraction over the service json definition to
    # make it easier to work with.
    service_model = ServiceModel(service_definition)

    # Determine the service_name if not provided
    if service_name is None:
        endpoint_prefix = service_model.endpoint_prefix
        service_name = _get_service_name(session, endpoint_prefix)
    api_version = service_model.api_version

    # For the model location we only want the custom data path (~/.aws/models
    # not the one set by AWS_DATA_PATH)
    data_path = session.get_component('data_loader').CUSTOMER_DATA_PATH
    # Use the version of the model to determine the file's naming convention.
    service_model_name = ('service-%d.json' %
                          int(float(service_definition.get('version', '2.0'))))
    return os.path.join(data_path, service_name, api_version,
                        service_model_name)
Ejemplo n.º 10
0
class TestCLIArgument(unittest.TestCase):
    def setUp(self):
        self.service_name = 'baz'
        self.service_model = ServiceModel(
            {
                'metadata': {
                    'endpointPrefix': 'bad',
                },
                'operations': {
                    'SampleOperation': {
                        'name': 'SampleOperation',
                        'input': {
                            'shape': 'Input'
                        }
                    }
                },
                'shapes': {
                    'StringShape': {
                        'type': 'string'
                    },
                    'Input': {
                        'type': 'structure',
                        'members': {
                            'Foo': {
                                'shape': 'StringShape'
                            }
                        }
                    }
                }
            }, self.service_name)
        self.operation_model = self.service_model.operation_model(
            'SampleOperation')
        self.argument_model = self.operation_model.input_shape.members['Foo']
        self.event_emitter = mock.Mock()

    def create_argument(self):
        return arguments.CLIArgument(self.argument_model.name,
                                     self.argument_model, self.operation_model,
                                     self.event_emitter)

    def test_unpack_uses_service_name_in_event(self):
        self.event_emitter.emit.return_value = ['value']
        argument = self.create_argument()
        params = {}
        argument.add_to_params(params, 'value')
        expected_event_name = 'process-cli-arg.%s.%s' % (self.service_name,
                                                         'sample-operation')
        actual_event_name = self.event_emitter.emit.call_args[0][0]
        self.assertEqual(actual_event_name, expected_event_name)

    def test_list_type_has_correct_nargs_value(self):
        # We don't actually care about the values, we just need a ListArgument
        # type.
        arg = arguments.ListArgument(argument_model=self.argument_model,
                                     event_emitter=self.event_emitter,
                                     is_required=True,
                                     name='test-nargs',
                                     operation_model=None,
                                     serialized_name='TestNargs')
        self.assertEqual(arg.nargs, '*')
Ejemplo n.º 11
0
 def setUp(self):
     self.model = {
         'metadata': {'protocol': 'query', 'apiVersion': '2014-01-01'},
         'documentation': '',
         'operations': {
             'TestOperation': {
                 'name': 'TestOperation',
                 'http': {
                     'method': 'POST',
                     'requestUri': '/',
                 },
                 'input': {'shape': 'InputShape'},
             }
         },
         'shapes': {
             'InputShape': {
                 'type': 'structure',
                 'members': {
                     'Timestamp': {'shape': 'StringTestType'},
                 }
             },
             'StringTestType': {
                 'type': 'string',
                 'min': 15
             }
         }
     }
     self.service_model = ServiceModel(self.model)
Ejemplo n.º 12
0
 def get_service_model(self, service, api_version=None):
     """Get the service model for the service."""
     with mock.patch('botocore.loaders.Loader.list_available_services',
                     return_value=[service]):
         return ServiceModel(self.loader.load_service_model(
             service, type_name='service-2', api_version=api_version),
                             service_name=service)
 def setUp(self):
     self.model = {
         'metadata': {'protocol': 'rest-xml', 'apiVersion': '2014-01-01'},
         'documentation': '',
         'operations': {
             'TestOperation': {
                 'name': 'TestOperation',
                 'http': {
                     'method': 'POST',
                     'requestUri': '/',
                 },
                 'input': {'shape': 'InputShape'},
             }
         },
         'shapes': {
             'InputShape': {
                 'type': 'structure',
                 'members': {
                     'ContentLength': {
                         'shape': 'Integer',
                         'location': 'header',
                         'locationName': 'Content-Length'
                     },
                 }
             },
             'Integer': {
                 'type': 'integer'
             },
         }
     }
     self.service_model = ServiceModel(self.model)
Ejemplo n.º 14
0
    def test_resource_loads_collections(self, mock_model):
        model = {
            'hasMany': {
                u'Queues': {
                    'request': {
                        'operation': 'ListQueues'
                    },
                    'resource': {
                        'type': 'Queue'
                    }
                }
            }
        }
        defs = {
            'Queue': {}
        }
        service_model = ServiceModel({})
        mock_model.return_value.name = 'queues'

        resource = self.load('test', 'test', model, defs, service_model)()

        self.assertTrue(hasattr(resource, 'queues'),
            'Resource should expose queues collection')
        self.assertIsInstance(resource.queues, CollectionManager,
            'Queues collection should be a collection manager')
Ejemplo n.º 15
0
 def construct_manager(self, cache=None, time=None, side_effect=None):
     self.service_model = ServiceModel(self.service_description)
     self.meta = mock.Mock(spec=ClientMeta)
     self.meta.service_model = self.service_model
     self.client = mock.Mock()
     if side_effect is None:
         side_effect = [{
             'Endpoints': [{
                 'Address': 'new.com',
                 'CachePeriodInMinutes': 2,
             }]
         }]
     self.client.describe_endpoints.side_effect = side_effect
     self.client.meta = self.meta
     self.manager = EndpointDiscoveryManager(self.client,
                                             cache=cache,
                                             current_time=time)
Ejemplo n.º 16
0
 def test_glacier_version_header_added(self):
     request_dict = {
         'headers': {}
     }
     model = ServiceModel({'metadata': {'apiVersion': '2012-01-01'}})
     handlers.add_glacier_version(model, request_dict)
     self.assertEqual(request_dict['headers']['x-amz-glacier-version'],
                      '2012-01-01')
Ejemplo n.º 17
0
    def test_route53_resource_id_missing_input_shape(self):
        event = 'before-parameter-build.route53.GetHostedZone'
        params = {'HostedZoneId': '/hostedzone/ABC123'}
        operation_def = {'name': 'GetHostedZone'}
        service_def = {'metadata': {}, 'shapes': {}}
        model = OperationModel(operation_def, ServiceModel(service_def))
        self.session.emit(event, params=params, model=model)

        self.assertEqual(params['HostedZoneId'], '/hostedzone/ABC123')
Ejemplo n.º 18
0
def load_service(service: str,
                 version: str = None,
                 model_type="service-2") -> ServiceModel:
    """
    For example: load_service("sqs", "2012-11-05")
    """
    service_description = loader.load_service_model(service, model_type,
                                                    version)
    return ServiceModel(service_description, service)
Ejemplo n.º 19
0
class TestRestXMLUnicodeSerialization(unittest.TestCase):
    def setUp(self):
        self.model = {
            'metadata': {
                'protocol': 'rest-xml',
                'apiVersion': '2014-01-01'
            },
            'documentation': '',
            'operations': {
                'TestOperation': {
                    'name': 'TestOperation',
                    'http': {
                        'method': 'POST',
                        'requestUri': '/',
                    },
                    'input': {
                        'shape': 'InputShape'
                    },
                }
            },
            'shapes': {
                'InputShape': {
                    'type': 'structure',
                    'members': {
                        'Foo': {
                            'shape': 'FooShape',
                            'locationName': 'Foo'
                        },
                    },
                    'payload': 'Foo'
                },
                'FooShape': {
                    'type': 'list',
                    'member': {
                        'shape': 'StringShape'
                    }
                },
                'StringShape': {
                    'type': 'string',
                }
            }
        }
        self.service_model = ServiceModel(self.model)

    def serialize_to_request(self, input_params):
        request_serializer = serialize.create_serializer(
            self.service_model.metadata['protocol'])
        return request_serializer.serialize_to_request(
            input_params, self.service_model.operation_model('TestOperation'))

    def test_restxml_serializes_unicode(self):
        params = {'Foo': [u'\u65e5\u672c\u8a9e\u3067\u304a\uff4b']}
        try:
            self.serialize_to_request(params)
        except UnicodeEncodeError:
            self.fail("RestXML serializer failed to serialize unicode text.")
Ejemplo n.º 20
0
class TestJSONTimestampSerialization(unittest.TestCase):

    def setUp(self):
        self.model = {
            'metadata': {'protocol': 'json', 'apiVersion': '2014-01-01',
                         'jsonVersion': '1.1', 'targetPrefix': 'foo'},
            'documentation': '',
            'operations': {
                'TestOperation': {
                    'name': 'TestOperation',
                    'http': {
                        'method': 'POST',
                        'requestUri': '/',
                    },
                    'input': {'shape': 'InputShape'},
                }
            },
            'shapes': {
                'InputShape': {
                    'type': 'structure',
                    'members': {
                        'Timestamp': {'shape': 'TimestampType'},
                    }
                },
                'TimestampType': {
                    'type': 'timestamp',
                }
            }
        }
        self.service_model = ServiceModel(self.model)

    def serialize_to_request(self, input_params):
        request_serializer = serialize.create_serializer(
            self.service_model.metadata['protocol'])
        return request_serializer.serialize_to_request(
            input_params, self.service_model.operation_model('TestOperation'))

    def test_accepts_iso_8601_format(self):
        body = json.loads(self.serialize_to_request(
            {'Timestamp': '1970-01-01T00:00:00'})['body'].decode('utf-8'))
        self.assertEqual(body['Timestamp'], 0)

    def test_accepts_epoch(self):
        body = json.loads(self.serialize_to_request(
            {'Timestamp': '0'})['body'].decode('utf-8'))
        self.assertEqual(body['Timestamp'], 0)
        # Can also be an integer 0.
        body = json.loads(self.serialize_to_request(
            {'Timestamp': 0})['body'].decode('utf-8'))
        self.assertEqual(body['Timestamp'], 0)

    def test_accepts_partial_iso_format(self):
        body = json.loads(self.serialize_to_request(
            {'Timestamp': '1970-01-01'})['body'].decode('utf-8'))
        self.assertEqual(body['Timestamp'], 0)
Ejemplo n.º 21
0
 def setUp(self):
     self.model = {
         "metadata": {
             'endpointPrefix': 'myservice',
             'serviceFullName': 'MyService',
         },
         'operations': {
             'OperationName': {
                 'name':
                 'OperationName',
                 'errors': [
                     {
                         'shape': 'ExceptionMissingCode'
                     },
                     {
                         'shape': 'ExceptionWithModeledCode'
                     },
                 ],
             },
             'AnotherOperationName': {
                 'name':
                 'AnotherOperationName',
                 'errors': [
                     {
                         'shape': 'ExceptionForAnotherOperation'
                     },
                     {
                         'shape': 'ExceptionWithModeledCode'
                     },
                 ],
             }
         },
         'shapes': {
             'ExceptionWithModeledCode': {
                 'type': 'structure',
                 'members': {},
                 'error': {
                     'code': 'ModeledCode'
                 },
                 'exception': True,
             },
             'ExceptionMissingCode': {
                 'type': 'structure',
                 'members': {},
                 'exception': True,
             },
             'ExceptionForAnotherOperation': {
                 'type': 'structure',
                 'members': {},
                 'exception': True,
             }
         }
     }
     self.service_model = ServiceModel(self.model)
     self.exceptions_factory = ClientExceptionsFactory()
class TestJSONTimestampSerialization(unittest.TestCase):

    def setUp(self):
        self.model = {
            'metadata': {'protocol': 'json', 'apiVersion': '2014-01-01',
                         'jsonVersion': '1.1', 'targetPrefix': 'foo'},
            'documentation': '',
            'operations': {
                'TestOperation': {
                    'name': 'TestOperation',
                    'http': {
                        'method': 'POST',
                        'requestUri': '/',
                    },
                    'input': {'shape': 'InputShape'},
                }
            },
            'shapes': {
                'InputShape': {
                    'type': 'structure',
                    'members': {
                        'Timestamp': {'shape': 'TimestampType'},
                    }
                },
                'TimestampType': {
                    'type': 'timestamp',
                }
            }
        }
        self.service_model = ServiceModel(self.model)

    def serialize_to_request(self, input_params):
        request_serializer = serialize.create_serializer(
            self.service_model.metadata['protocol'])
        return request_serializer.serialize_to_request(
            input_params, self.service_model.operation_model('TestOperation'))

    def test_accepts_iso_8601_format(self):
        body = json.loads(self.serialize_to_request(
            {'Timestamp': '1970-01-01T00:00:00'})['body'].decode('utf-8'))
        self.assertEqual(body['Timestamp'], 0)

    def test_accepts_epoch(self):
        body = json.loads(self.serialize_to_request(
            {'Timestamp': '0'})['body'].decode('utf-8'))
        self.assertEqual(body['Timestamp'], 0)
        # Can also be an integer 0.
        body = json.loads(self.serialize_to_request(
            {'Timestamp': 0})['body'].decode('utf-8'))
        self.assertEqual(body['Timestamp'], 0)

    def test_accepts_partial_iso_format(self):
        body = json.loads(self.serialize_to_request(
            {'Timestamp': '1970-01-01'})['body'].decode('utf-8'))
        self.assertEqual(body['Timestamp'], 0)
Ejemplo n.º 23
0
 def setUp(self):
     self.model = {
         'metadata': {
             'protocol': 'rest-xml',
             'apiVersion': '2014-01-01'
         },
         'documentation': '',
         'operations': {
             'TestOperation': {
                 'name': 'TestOperation',
                 'http': {
                     'method': 'POST',
                     'requestUri': '/',
                 },
                 'input': {
                     'shape': 'InputShape'
                 },
             }
         },
         'shapes': {
             'InputShape': {
                 'type': 'structure',
                 'members': {
                     'Foo': {
                         'shape': 'FooShape',
                         'locationName': 'Foo'
                     },
                 },
                 'payload': 'Foo'
             },
             'FooShape': {
                 'type': 'list',
                 'member': {
                     'shape': 'StringShape'
                 }
             },
             'StringShape': {
                 'type': 'string',
             }
         }
     }
     self.service_model = ServiceModel(self.model)
Ejemplo n.º 24
0
    def test_decode_json_policy(self):
        parsed = {
            'Document': '{"foo": "foobarbaz"}',
            'Other': 'bar',
        }
        service_def = {
            'operations': {
                'Foo': {
                    'output': {
                        'shape': 'PolicyOutput'
                    },
                }
            },
            'shapes': {
                'PolicyOutput': {
                    'type': 'structure',
                    'members': {
                        'Document': {
                            'shape': 'policyDocumentType'
                        },
                        'Other': {
                            'shape': 'stringType'
                        }
                    }
                },
                'policyDocumentType': {
                    'type': 'string'
                },
                'stringType': {
                    'type': 'string'
                },
            }
        }
        model = ServiceModel(service_def)
        op_model = model.operation_model('Foo')
        handlers.json_decode_policies(parsed, op_model)
        self.assertEqual(parsed['Document'], {'foo': 'foobarbaz'})

        no_document = {'Other': 'bar'}
        handlers.json_decode_policies(no_document, op_model)
        self.assertEqual(no_document, {'Other': 'bar'})
Ejemplo n.º 25
0
    def setUp(self):
        super(TestCollectionFactory, self).setUp()

        self.client = mock.Mock()
        self.client.can_paginate.return_value = False
        self.parent = mock.Mock()
        self.parent.meta = ResourceMeta('test', client=self.client)
        self.resource_factory = ResourceFactory()
        self.service_model = ServiceModel({})

        self.factory = CollectionFactory()
        self.load = self.factory.load_from_definition
Ejemplo n.º 26
0
 def __init__(self, service: ServiceModel) -> None:
     super().__init__(service)
     # When parsing a request, we need to lookup the operation based on the HTTP method and URI.
     # Therefore we create a mapping when the parser is initialized.
     self.operation_lookup = defaultdict(lambda: defaultdict(OperationModel))
     for operation in service.operation_names:
         operation_model = service.operation_model(operation)
         http = operation_model.http
         if len(http) > 0:
             method = http.get("method")
             request_uri = http.get("requestUri")
             self.operation_lookup[method][request_uri] = operation_model
Ejemplo n.º 27
0
def handle_shapes(service_model: ServiceModel, class_name, shapes_path):
    top_level_shapes = [(service_model.shape_for(name), class_name)
                        for name in service_model.shape_names]
    if not top_level_shapes:
        return
    docs_shapes_path = f'docs/{shapes_path}'
    create_new_file(docs_shapes_path)
    service_name = get_service_name(service_model)
    all_shapes = find_all_shapes(top_level_shapes)
    shape_docs = [get_shape_doc(shapes_path, shape) for shape in all_shapes]
    write_lines(docs_shapes_path,
                [f'# {service_name} data types'] + shape_docs)
Ejemplo n.º 28
0
    def test_decode_json_policy(self):
        parsed = {"Document": '{"foo": "foobarbaz"}', "Other": "bar"}
        service_def = {
            "operations": {"Foo": {"output": {"shape": "PolicyOutput"}}},
            "shapes": {
                "PolicyOutput": {
                    "type": "structure",
                    "members": {"Document": {"shape": "policyDocumentType"}, "Other": {"shape": "stringType"}},
                },
                "policyDocumentType": {"type": "string"},
                "stringType": {"type": "string"},
            },
        }
        model = ServiceModel(service_def)
        op_model = model.operation_model("Foo")
        handlers.json_decode_policies(parsed, op_model)
        self.assertEqual(parsed["Document"], {"foo": "foobarbaz"})

        no_document = {"Other": "bar"}
        handlers.json_decode_policies(no_document, op_model)
        self.assertEqual(no_document, {"Other": "bar"})
Ejemplo n.º 29
0
    def __init__(self, session: Session, service_name: ServiceName):
        loader = session._loader
        botocore_session: BotocoreSession = session._session
        service_data = botocore_session.get_service_data(
            service_name.boto3_name)
        self.service_name = service_name
        self.service_model = ServiceModel(service_data,
                                          service_name.boto3_name)
        self._typed_dict_map: dict[str, TypeTypedDict] = {}
        self._waiters_shape: Mapping[str, Any] | None = None
        try:
            self._waiters_shape = loader.load_service_model(
                service_name.boto3_name, "waiters-2")
        except UnknownServiceError:
            pass
        self._paginators_shape: Mapping[str, Any] | None = None
        try:
            self._paginators_shape = loader.load_service_model(
                service_name.boto3_name, "paginators-1")
        except UnknownServiceError:
            pass
        self._resources_shape: Mapping[str, Any] | None = None
        try:
            self._resources_shape = loader.load_service_model(
                service_name.boto3_name, "resources-1")
        except UnknownServiceError:
            pass

        self.logger = get_logger()
        self.response_metadata_typed_dict = TypeTypedDict(
            "ResponseMetadataTypeDef",
            [
                TypedDictAttribute("RequestId", Type.str, True),
                TypedDictAttribute("HostId", Type.str, True),
                TypedDictAttribute("HTTPStatusCode", Type.int, True),
                TypedDictAttribute("HTTPHeaders", Type.DictStrStr, True),
                TypedDictAttribute("RetryAttempts", Type.int, True),
            ],
        )
        self.proxy_operation_model = OperationModel({}, self.service_model)
Ejemplo n.º 30
0
def generate_service_types(output, service: ServiceModel, doc=True):
    output.write("import sys\n")
    output.write("from typing import Dict, List, Optional\n")
    output.write("from datetime import datetime\n")
    output.write("if sys.version_info >= (3, 8):\n")
    output.write("    from typing import TypedDict\n")
    output.write("else:\n")
    output.write("    from typing_extensions import TypedDict\n")
    output.write("\n")
    output.write(
        "from localstack.aws.api import handler, RequestContext, ServiceException, ServiceRequest"
    )
    output.write("\n")

    # ==================================== print type declarations
    nodes: Dict[str, ShapeNode] = {}

    for shape_name in service.shape_names:
        shape = service.shape_for(shape_name)
        nodes[shape_name] = ShapeNode(service, shape)

    # output.write("__all__ = [\n")
    # for name in nodes.keys():
    #     output.write(f'    "{name}",\n')
    # output.write("]\n")

    printed: Set[str] = set()
    visited: Set[str] = set()
    stack: List[str] = list(nodes.keys())

    stack = sorted(stack, key=lambda name: nodes[name].get_order())
    stack.reverse()

    while stack:
        name = stack.pop()
        if name in printed:
            continue
        node = nodes[name]

        dependencies = [dep for dep in node.dependencies if dep not in printed]

        if not dependencies:
            node.print_declaration(output, doc=doc)
            printed.add(name)
        elif name in visited:
            # break out of circular dependencies
            node.print_declaration(output, doc=doc, quote_types=True)
            printed.add(name)
        else:
            stack.append(name)
            stack.extend(dependencies)
            visited.add(name)
Ejemplo n.º 31
0
class TestRestXMLUnicodeSerialization(unittest.TestCase):

    def setUp(self):
        self.model = {
            'metadata': {'protocol': 'rest-xml', 'apiVersion': '2014-01-01'},
            'documentation': '',
            'operations': {
                'TestOperation': {
                    'name': 'TestOperation',
                    'http': {
                        'method': 'POST',
                        'requestUri': '/',
                    },
                    'input': {'shape': 'InputShape'},
                }
            },
            'shapes': {
                'InputShape': {
                    'type': 'structure',
                    'members': {
                        'Foo': {
                            'shape': 'FooShape',
                            'locationName': 'Foo'
                        },
                    },
                    'payload': 'Foo'
                },
                'FooShape': {
                    'type': 'list',
                    'member': {'shape': 'StringShape'}
                },
                'StringShape': {
                    'type': 'string',
                }
            }
        }
        self.service_model = ServiceModel(self.model)

    def serialize_to_request(self, input_params):
        request_serializer = serialize.create_serializer(
            self.service_model.metadata['protocol'])
        return request_serializer.serialize_to_request(
            input_params, self.service_model.operation_model('TestOperation'))

    def test_restxml_serializes_unicode(self):
        params = {
            'Foo': [u'\u65e5\u672c\u8a9e\u3067\u304a\uff4b']
        }
        try:
            self.serialize_to_request(params)
        except UnicodeEncodeError:
            self.fail("RestXML serializer failed to serialize unicode text.")
Ejemplo n.º 32
0
    def __init__(self, session: Session, service_name: ServiceName):
        loader = session._loader  # pylint: disable=protected-access
        botocore_session: BotocoreSession = session._session  # pylint: disable=protected-access
        service_data = botocore_session.get_service_data(
            service_name.boto3_name)
        self.service_name = service_name
        self.service_model = ServiceModel(service_data,
                                          service_name.boto3_name)
        self._typed_dict_map: Dict[str, TypeTypedDict] = {}
        self._waiters_shape: Optional[Shape] = None
        try:
            self._waiters_shape = loader.load_service_model(
                service_name.boto3_name, "waiters-2")
        except UnknownServiceError:
            pass
        self._paginators_shape: Optional[Shape] = None
        try:
            self._paginators_shape = loader.load_service_model(
                service_name.boto3_name, "paginators-1")
        except UnknownServiceError:
            pass
        self._resources_shape: Optional[Shape] = None
        try:
            self._resources_shape = loader.load_service_model(
                service_name.boto3_name, "resources-1")
        except UnknownServiceError:
            pass

        self.logger = get_logger()
        self.response_metadata_typed_dict = TypeTypedDict(
            "ResponseMetadata",
            [
                TypedDictAttribute("RequestId", Type.str, True),
                TypedDictAttribute("HostId", Type.str, True),
                TypedDictAttribute("HTTPStatusCode", Type.int, True),
                TypedDictAttribute("HTTPHeaders", Type.DictStrAny, True),
                TypedDictAttribute("RetryAttempts", Type.int, True),
            ],
        )
Ejemplo n.º 33
0
    def test_validates_on_empty_output_shape(self):
        service_model = ServiceModel({
            'documentation': '',
            'operations': {
                'foo': {
                    'name': 'foo'
                }
            }
        })
        self.client.meta.service_model = service_model

        with self.assertRaises(ParamValidationError):
            self.stubber.add_response('TestOperation', {'foo': 'bar'})
Ejemplo n.º 34
0
    def test_decode_json_policy(self):
        parsed = {
            'Document': '{"foo": "foobarbaz"}',
            'Other': 'bar',
        }
        service_def = {
            'operations': {
                'Foo': {
                    'output': {'shape': 'PolicyOutput'},
                }
            },
            'shapes': {
                'PolicyOutput': {
                    'type': 'structure',
                    'members': {
                        'Document': {
                            'shape': 'policyDocumentType'
                        },
                        'Other': {
                            'shape': 'stringType'
                        }
                    }
                },
                'policyDocumentType': {
                    'type': 'string'
                },
                'stringType': {
                    'type': 'string'
                },
            }
        }
        model = ServiceModel(service_def)
        op_model = model.operation_model('Foo')
        handlers.json_decode_policies(parsed, op_model)
        self.assertEqual(parsed['Document'], {'foo': 'foobarbaz'})

        no_document = {'Other': 'bar'}
        handlers.json_decode_policies(no_document, op_model)
        self.assertEqual(no_document, {'Other': 'bar'})
Ejemplo n.º 35
0
 def setUp(self):
     self.service_description = {
         'metadata': {
             'serviceFullName': 'AWS MyService',
             'apiVersion': '2014-01-01',
             'endpointPrefix': 'myservice',
             'signatureVersion': 'v4',
             'protocol': 'query'
         },
         'operations': {},
         'shapes': {},
     }
     self.service_model = ServiceModel(self.service_description,
                                       'myservice')
Ejemplo n.º 36
0
class TestCLIArgument(unittest.TestCase):
    def setUp(self):
        self.service_name = 'baz'
        self.service_model = ServiceModel(
            {
                'metadata': {
                    'endpointPrefix': 'bad',
                },
                'operations': {
                    'SampleOperation': {
                        'name': 'SampleOperation',
                        'input': {
                            'shape': 'Input'
                        }
                    }
                },
                'shapes': {
                    'StringShape': {
                        'type': 'string'
                    },
                    'Input': {
                        'type': 'structure',
                        'members': {
                            'Foo': {
                                'shape': 'StringShape'
                            }
                        }
                    }
                }
            }, self.service_name)
        self.operation_model = self.service_model.operation_model(
            'SampleOperation')
        self.argument_model = self.operation_model.input_shape.members['Foo']
        self.event_emitter = mock.Mock()

    def create_argument(self):
        return arguments.CLIArgument(self.argument_model.name,
                                     self.argument_model, self.operation_model,
                                     self.event_emitter)

    def test_unpack_uses_service_name_in_event(self):
        self.event_emitter.emit.return_value = ['value']
        argument = self.create_argument()
        params = {}
        argument.add_to_params(params, 'value')
        expected_event_name = 'process-cli-arg.%s.%s' % (self.service_name,
                                                         'sample-operation')
        actual_event_name = self.event_emitter.emit.call_args[0][0]
        self.assertEqual(actual_event_name, expected_event_name)
Ejemplo n.º 37
0
 def setUp(self):
     self.model = {
         'metadata': {
             'protocol': 'json',
             'apiVersion': '2014-01-01',
             'jsonVersion': '1.1',
             'targetPrefix': 'foo'
         },
         'documentation': '',
         'operations': {
             'TestOperation': {
                 'name': 'TestOperation',
                 'http': {
                     'method': 'POST',
                     'requestUri': '/',
                 },
                 'input': {
                     'shape': 'InputShape'
                 },
             }
         },
         'shapes': {
             'InputShape': {
                 'type': 'structure',
                 'members': {
                     'Timestamp': {
                         'shape': 'TimestampType'
                     },
                 }
             },
             'TimestampType': {
                 'type': 'timestamp',
             }
         }
     }
     self.service_model = ServiceModel(self.model)
Ejemplo n.º 38
0
    def test_no_output(self):
        service_model = ServiceModel({
            'operations': {
                'SampleOperation': {
                    'name': 'SampleOperation',
                    'input': {'shape': 'SampleOperationInputOutput'},
                }
            },
            'shapes': {
                'SampleOperationInput': {
                    'type': 'structure',
                    'members': {}
                },
                'String': {
                    'type': 'string'
                }
            }
        })
        operation_model = service_model.operation_model('SampleOperation')

        parsed = {}
        self.injector.inject_attribute_value_output(
            parsed=parsed, model=operation_model)
        self.assertEqual(parsed, {})
Ejemplo n.º 39
0
    def test_no_output(self):
        service_model = ServiceModel({
            'operations': {
                'SampleOperation': {
                    'name': 'SampleOperation',
                    'input': {'shape': 'SampleOperationInputOutput'},
                }
            },
            'shapes': {
                'SampleOperationInput': {
                    'type': 'structure',
                    'members': {}
                },
                'String': {
                    'type': 'string'
                }
            }
        })
        operation_model = service_model.operation_model('SampleOperation')

        parsed = {}
        self.injector.inject_attribute_value_output(
            parsed=parsed, model=operation_model)
        assert parsed == {}
Ejemplo n.º 40
0
 def setUp(self):
     self.service_name = "baz"
     self.service_model = ServiceModel(
         {
             "metadata": {"endpointPrefix": "bad"},
             "operations": {"SampleOperation": {"name": "SampleOperation", "input": {"shape": "Input"}}},
             "shapes": {
                 "StringShape": {"type": "string"},
                 "Input": {"type": "structure", "members": {"Foo": {"shape": "StringShape"}}},
             },
         },
         self.service_name,
     )
     self.operation_model = self.service_model.operation_model("SampleOperation")
     self.argument_model = self.operation_model.input_shape.members["Foo"]
     self.event_emitter = mock.Mock()
Ejemplo n.º 41
0
    def get_service_model(self, service_name, api_version=None):
        """Get the service model object.

        :type service_name: string
        :param service_name: The service name

        :type api_version: string
        :param api_version: The API version of the service.  If none is
            provided, then the latest API version will be used.

        :rtype: L{botocore.model.ServiceModel}
        :return: The botocore service model for the service.

        """
        service_description = self.get_service_data(service_name, api_version)
        return ServiceModel(service_description, service_name=service_name)
Ejemplo n.º 42
0
class TestBinaryTypesJSON(unittest.TestCase):
    def setUp(self):
        self.model = {
            'metadata': {
                'protocol': 'json',
                'apiVersion': '2014-01-01',
                'jsonVersion': '1.1',
                'targetPrefix': 'foo'
            },
            'documentation': '',
            'operations': {
                'TestOperation': {
                    'name': 'TestOperation',
                    'http': {
                        'method': 'POST',
                        'requestUri': '/',
                    },
                    'input': {
                        'shape': 'InputShape'
                    },
                }
            },
            'shapes': {
                'InputShape': {
                    'type': 'structure',
                    'members': {
                        'Blob': {
                            'shape': 'BlobType'
                        },
                    }
                },
                'BlobType': {
                    'type': 'blob',
                }
            }
        }
        self.service_model = ServiceModel(self.model)

    def serialize_to_request(self, input_params):
        request_serializer = serialize.create_serializer(
            self.service_model.metadata['protocol'])
        return request_serializer.serialize_to_request(
            input_params, self.service_model.operation_model('TestOperation'))

    def test_blob_accepts_bytes_type(self):
        body = b'bytes body'
        self.serialize_to_request(input_params={'Blob': body})
Ejemplo n.º 43
0
 def test_can_generate_operation_with_describe_prefix(self):
     model = deepcopy(BASIC_MODEL)
     # Swap ListCertificates for DescribeCertificates.
     # We should still be able to generate auto-completion data.
     model['operations']['DescribeCertificates'] = model['operations'].pop(
         'ListCertificates')
     service_model = ServiceModel(model)
     completion_data = self.heuristic.generate_completion_descriptions(
         service_model)
     # Ensure we're using the swapped 'DescribeCertificates' operation.
     self.assertEqual(
         completion_data['resources']['Certificate']['operation'],
         'DescribeCertificates')
     self.assertEqual(list(sorted(completion_data['operations'])), [
         'DeleteCertificate', 'DescribeCertificate', 'ExportCertificate',
         'GetCertificate', 'ImportCertificate'
     ])
Ejemplo n.º 44
0
 def construct_manager(self, cache=None, time=None, side_effect=None):
     self.service_model = ServiceModel(self.service_description)
     self.meta = Mock(spec=ClientMeta)
     self.meta.service_model = self.service_model
     self.client = Mock()
     if side_effect is None:
         side_effect = [{
             'Endpoints': [{
                 'Address': 'new.com',
                 'CachePeriodInMinutes': 2,
             }]
         }]
     self.client.describe_endpoints.side_effect = side_effect
     self.client.meta = self.meta
     self.manager = EndpointDiscoveryManager(
         self.client, cache=cache, current_time=time
     )
Ejemplo n.º 45
0
class TestBinaryTypesJSON(unittest.TestCase):
    def setUp(self):
        self.model = {
            'metadata': {'protocol': 'json', 'apiVersion': '2014-01-01',
                         'jsonVersion': '1.1', 'targetPrefix': 'foo'},
            'documentation': '',
            'operations': {
                'TestOperation': {
                    'name': 'TestOperation',
                    'http': {
                        'method': 'POST',
                        'requestUri': '/',
                    },
                    'input': {'shape': 'InputShape'},
                }
            },
            'shapes': {
                'InputShape': {
                    'type': 'structure',
                    'members': {
                        'Blob': {'shape': 'BlobType'},
                    }
                },
                'BlobType': {
                    'type': 'blob',
                }
            }
        }
        self.service_model = ServiceModel(self.model)

    def serialize_to_request(self, input_params):
        request_serializer = serialize.create_serializer(
            self.service_model.metadata['protocol'])
        return request_serializer.serialize_to_request(
            input_params, self.service_model.operation_model('TestOperation'))

    def test_blob_accepts_bytes_type(self):
        body = b'bytes body'
        self.serialize_to_request(input_params={'Blob': body})
Ejemplo n.º 46
0
class TestTimestamps(unittest.TestCase):
    def setUp(self):
        self.model = {
            'metadata': {'protocol': 'query', 'apiVersion': '2014-01-01'},
            'documentation': '',
            'operations': {
                'TestOperation': {
                    'name': 'TestOperation',
                    'http': {
                        'method': 'POST',
                        'requestUri': '/',
                    },
                    'input': {'shape': 'InputShape'},
                }
            },
            'shapes': {
                'InputShape': {
                    'type': 'structure',
                    'members': {
                        'Timestamp': {'shape': 'TimestampType'},
                    }
                },
                'TimestampType': {
                    'type': 'timestamp',
                }
            }
        }
        self.service_model = ServiceModel(self.model)

    def serialize_to_request(self, input_params):
        request_serializer = serialize.create_serializer(
            self.service_model.metadata['protocol'])
        return request_serializer.serialize_to_request(
            input_params, self.service_model.operation_model('TestOperation'))

    def test_accepts_datetime_object(self):
        request = self.serialize_to_request(
            {'Timestamp': datetime.datetime(2014, 1, 1, 12, 12, 12,
                                            tzinfo=dateutil.tz.tzutc())})
        self.assertEqual(request['body']['Timestamp'], '2014-01-01T12:12:12Z')

    def test_accepts_naive_datetime_object(self):
        request = self.serialize_to_request(
            {'Timestamp': datetime.datetime(2014, 1, 1, 12, 12, 12)})
        self.assertEqual(request['body']['Timestamp'], '2014-01-01T12:12:12Z')

    def test_accepts_iso_8601_format(self):
        request = self.serialize_to_request({'Timestamp': '2014-01-01T12:12:12Z'})
        self.assertEqual(request['body']['Timestamp'], '2014-01-01T12:12:12Z')

    def test_accepts_timestamp_without_tz_info(self):
        # If a timezone/utc is not specified, assume they meant
        # UTC.  This is also the previous behavior from older versions
        # of botocore so we want to make sure we preserve this behavior.
        request = self.serialize_to_request({'Timestamp': '2014-01-01T12:12:12'})
        self.assertEqual(request['body']['Timestamp'], '2014-01-01T12:12:12Z')

    def test_microsecond_timestamp_without_tz_info(self):
        request = self.serialize_to_request(
            {'Timestamp': '2014-01-01T12:12:12.123456'})
        self.assertEqual(request['body']['Timestamp'],
                         '2014-01-01T12:12:12.123456Z')
Ejemplo n.º 47
0
class TestInstanceCreation(unittest.TestCase):
    def setUp(self):
        self.model = {
            'metadata': {'protocol': 'query', 'apiVersion': '2014-01-01'},
            'documentation': '',
            'operations': {
                'TestOperation': {
                    'name': 'TestOperation',
                    'http': {
                        'method': 'POST',
                        'requestUri': '/',
                    },
                    'input': {'shape': 'InputShape'},
                }
            },
            'shapes': {
                'InputShape': {
                    'type': 'structure',
                    'members': {
                        'Timestamp': {'shape': 'StringTestType'},
                    }
                },
                'StringTestType': {
                    'type': 'string',
                    'min': 15
                }
            }
        }
        self.service_model = ServiceModel(self.model)

    def assert_serialize_valid_parameter(self, request_serializer):
        valid_string = 'valid_string_with_min_15_chars'
        request = request_serializer.serialize_to_request(
            {'Timestamp': valid_string},
            self.service_model.operation_model('TestOperation'))

        self.assertEqual(request['body']['Timestamp'], valid_string)

    def assert_serialize_invalid_parameter(self, request_serializer):
        invalid_string = 'short string'
        request = request_serializer.serialize_to_request(
            {'Timestamp': invalid_string},
            self.service_model.operation_model('TestOperation'))

        self.assertEqual(request['body']['Timestamp'], invalid_string)

    def test_instantiate_without_validation(self):
        request_serializer = serialize.create_serializer(
            self.service_model.metadata['protocol'], False)

        try:
            self.assert_serialize_valid_parameter(request_serializer)
        except ParamValidationError as e:
            self.fail("Shouldn't fail serializing valid parameter without validation")

        try:
            self.assert_serialize_invalid_parameter(request_serializer)
        except ParamValidationError as e:
            self.fail("Shouldn't fail serializing invalid parameter without validation")

    def test_instantiate_with_validation(self):
        request_serializer = serialize.create_serializer(
            self.service_model.metadata['protocol'], True)
        try:
            self.assert_serialize_valid_parameter(request_serializer)
        except ParamValidationError as e:
            self.fail("Shouldn't fail serializing valid parameter with validation")

        with self.assertRaises(ParamValidationError):
            self.assert_serialize_invalid_parameter(request_serializer)
Ejemplo n.º 48
0
 def serialize_to_request(self, input_params):
     service_model = ServiceModel(self.model)
     request_serializer = serialize.create_serializer(
         service_model.metadata['protocol'])
     return request_serializer.serialize_to_request(
         input_params, service_model.operation_model('TestOperation'))
Ejemplo n.º 49
0
class TestEndpointDiscoveryManager(BaseEndpointDiscoveryTest):
    def setUp(self):
        super(TestEndpointDiscoveryManager, self).setUp()
        self.construct_manager()

    def construct_manager(self, cache=None, time=None, side_effect=None):
        self.service_model = ServiceModel(self.service_description)
        self.meta = Mock(spec=ClientMeta)
        self.meta.service_model = self.service_model
        self.client = Mock()
        if side_effect is None:
            side_effect = [{
                'Endpoints': [{
                    'Address': 'new.com',
                    'CachePeriodInMinutes': 2,
                }]
            }]
        self.client.describe_endpoints.side_effect = side_effect
        self.client.meta = self.meta
        self.manager = EndpointDiscoveryManager(
            self.client, cache=cache, current_time=time
        )

    def test_injects_api_version_if_endpoint_operation(self):
        model = self.service_model.operation_model('DescribeEndpoints')
        params = {'headers': {}}
        inject_api_version_header_if_needed(model, params)
        self.assertEqual(params['headers'].get('x-amz-api-version'),
                         '2018-08-31')

    def test_no_inject_api_version_if_not_endpoint_operation(self):
        model = self.service_model.operation_model('TestDiscoveryRequired')
        params = {'headers': {}}
        inject_api_version_header_if_needed(model, params)
        self.assertNotIn('x-amz-api-version', params['headers'])

    def test_gather_identifiers(self):
        params = {
            'Foo': 'value1',
            'Nested': {'Bar': 'value2'}
        }
        operation = self.service_model.operation_model('TestDiscoveryRequired')
        ids = self.manager.gather_identifiers(operation, params)
        self.assertEqual(ids, {'Foo': 'value1', 'Bar': 'value2'})

    def test_gather_identifiers_none(self):
        operation = self.service_model.operation_model('TestDiscovery')
        ids = self.manager.gather_identifiers(operation, {})
        self.assertEqual(ids, {})

    def test_describe_endpoint(self):
        kwargs = {
            'Operation': 'FooBar',
            'Identifiers': {'Foo': 'value1', 'Bar': 'value2'},
        }
        self.manager.describe_endpoint(**kwargs)
        self.client.describe_endpoints.assert_called_with(**kwargs)

    def test_describe_endpoint_no_input(self):
        describe = self.service_description['operations']['DescribeEndpoints']
        del describe['input']
        self.construct_manager()
        self.manager.describe_endpoint(Operation='FooBar', Identifiers={})
        self.client.describe_endpoints.assert_called_with()

    def test_describe_endpoint_empty_input(self):
        describe = self.service_description['operations']['DescribeEndpoints']
        describe['input'] = {'shape': 'EmptyStruct'}
        self.construct_manager()
        self.manager.describe_endpoint(Operation='FooBar', Identifiers={})
        self.client.describe_endpoints.assert_called_with()

    def test_describe_endpoint_ids_and_operation(self):
        cache = {}
        self.construct_manager(cache=cache)
        ids = {'Foo': 'value1', 'Bar': 'value2'}
        kwargs = {
            'Operation': 'TestDiscoveryRequired',
            'Identifiers': ids,
        }
        self.manager.describe_endpoint(**kwargs)
        self.client.describe_endpoints.assert_called_with(**kwargs)
        key = ((('Bar', 'value2'), ('Foo', 'value1')), 'TestDiscoveryRequired')
        self.assertIn(key, cache)
        self.assertEqual(cache[key][0]['Address'], 'new.com')
        self.manager.describe_endpoint(**kwargs)
        call_count = self.client.describe_endpoints.call_count
        self.assertEqual(call_count, 1)

    def test_describe_endpoint_no_ids_or_operation(self):
        cache = {}
        describe = self.service_description['operations']['DescribeEndpoints']
        describe['input'] = {'shape': 'EmptyStruct'}
        self.construct_manager(cache=cache)
        self.manager.describe_endpoint(
            Operation='TestDiscoveryRequired', Identifiers={}
        )
        self.client.describe_endpoints.assert_called_with()
        key = ()
        self.assertIn(key, cache)
        self.assertEqual(cache[key][0]['Address'], 'new.com')
        self.manager.describe_endpoint(
            Operation='TestDiscoveryRequired', Identifiers={}
        )
        call_count = self.client.describe_endpoints.call_count
        self.assertEqual(call_count, 1)

    def test_describe_endpoint_expired_entry(self):
        current_time = time.time()
        key = ()
        cache = {
            key: [{'Address': 'old.com', 'Expiration': current_time - 10}]
        }
        self.construct_manager(cache=cache)
        kwargs = {
            'Identifiers': {},
            'Operation': 'TestDiscoveryRequired',
        }
        self.manager.describe_endpoint(**kwargs)
        self.client.describe_endpoints.assert_called_with()
        self.assertIn(key, cache)
        self.assertEqual(cache[key][0]['Address'], 'new.com')
        self.manager.describe_endpoint(**kwargs)
        call_count = self.client.describe_endpoints.call_count
        self.assertEqual(call_count, 1)

    def test_describe_endpoint_cache_expiration(self):
        def _time():
            return float(0)
        cache = {}
        self.construct_manager(cache=cache, time=_time)
        self.manager.describe_endpoint(
            Operation='TestDiscoveryRequired', Identifiers={}
        )
        key = ()
        self.assertIn(key, cache)
        self.assertEqual(cache[key][0]['Expiration'], float(120))

    def test_delete_endpoints_present(self):
        key = ()
        cache = {
            key: [{'Address': 'old.com', 'Expiration': 0}]
        }
        self.construct_manager(cache=cache)
        kwargs = {
            'Identifiers': {},
            'Operation': 'TestDiscoveryRequired',
        }
        self.manager.delete_endpoints(**kwargs)
        self.assertEqual(cache, {})

    def test_delete_endpoints_absent(self):
        cache = {}
        self.construct_manager(cache=cache)
        kwargs = {
            'Identifiers': {},
            'Operation': 'TestDiscoveryRequired',
        }
        self.manager.delete_endpoints(**kwargs)
        self.assertEqual(cache, {})

    def test_describe_endpoint_optional_fails_no_cache(self):
        side_effect = [ConnectionError(error=None)]
        self.construct_manager(side_effect=side_effect)
        kwargs = {'Operation': 'TestDiscoveryOptional'}
        endpoint = self.manager.describe_endpoint(**kwargs)
        self.assertIsNone(endpoint)
        # This second call should be blocked as we just failed
        endpoint = self.manager.describe_endpoint(**kwargs)
        self.assertIsNone(endpoint)
        self.client.describe_endpoints.call_args_list == [call()]

    def test_describe_endpoint_optional_fails_stale_cache(self):
        key = ()
        cache = {
            key: [{'Address': 'old.com', 'Expiration': 0}]
        }
        side_effect = [ConnectionError(error=None)] * 2
        self.construct_manager(cache=cache, side_effect=side_effect)
        kwargs = {'Operation': 'TestDiscoveryOptional'}
        endpoint = self.manager.describe_endpoint(**kwargs)
        self.assertEqual(endpoint, 'old.com')
        # This second call shouldn't go through as we just failed
        endpoint = self.manager.describe_endpoint(**kwargs)
        self.assertEqual(endpoint, 'old.com')
        self.client.describe_endpoints.call_args_list == [call()]

    def test_describe_endpoint_required_fails_no_cache(self):
        side_effect = [ConnectionError(error=None)] * 2
        self.construct_manager(side_effect=side_effect)
        kwargs = {'Operation': 'TestDiscoveryRequired'}
        with self.assertRaises(EndpointDiscoveryRefreshFailed):
            self.manager.describe_endpoint(**kwargs)
        # This second call should go through, as we have no cache
        with self.assertRaises(EndpointDiscoveryRefreshFailed):
            self.manager.describe_endpoint(**kwargs)
        describe_count = self.client.describe_endpoints.call_count
        self.assertEqual(describe_count, 2)

    def test_describe_endpoint_required_fails_stale_cache(self):
        key = ()
        cache = {
            key: [{'Address': 'old.com', 'Expiration': 0}]
        }
        side_effect = [ConnectionError(error=None)] * 2
        self.construct_manager(cache=cache, side_effect=side_effect)
        kwargs = {'Operation': 'TestDiscoveryRequired'}
        endpoint = self.manager.describe_endpoint(**kwargs)
        self.assertEqual(endpoint, 'old.com')
        # We have a stale endpoint, so this shouldn't fail or force a refresh
        endpoint = self.manager.describe_endpoint(**kwargs)
        self.assertEqual(endpoint, 'old.com')
        self.client.describe_endpoints.call_args_list == [call()]

    def test_describe_endpoint_required_force_refresh_success(self):
        side_effect = [
            ConnectionError(error=None),
            {'Endpoints': [{
                'Address': 'new.com',
                'CachePeriodInMinutes': 2,
            }]},
        ]
        self.construct_manager(side_effect=side_effect)
        kwargs = {'Operation': 'TestDiscoveryRequired'}
        # First call will fail
        with self.assertRaises(EndpointDiscoveryRefreshFailed):
            self.manager.describe_endpoint(**kwargs)
        self.client.describe_endpoints.call_args_list == [call()]
        # Force a refresh if the cache is empty but discovery is required
        endpoint = self.manager.describe_endpoint(**kwargs)
        self.assertEqual(endpoint, 'new.com')

    def test_describe_endpoint_retries_after_failing(self):
        fake_time = Mock()
        fake_time.side_effect = [0, 100, 200]
        side_effect = [
            ConnectionError(error=None),
            {'Endpoints': [{
                'Address': 'new.com',
                'CachePeriodInMinutes': 2,
            }]},
        ]
        self.construct_manager(side_effect=side_effect, time=fake_time)
        kwargs = {'Operation': 'TestDiscoveryOptional'}
        endpoint = self.manager.describe_endpoint(**kwargs)
        self.assertIsNone(endpoint)
        self.client.describe_endpoints.call_args_list == [call()]
        # Second time should try again as enough time has elapsed
        endpoint = self.manager.describe_endpoint(**kwargs)
        self.assertEqual(endpoint, 'new.com')
Ejemplo n.º 50
0
class TestEndpointDiscoveryHandler(BaseEndpointDiscoveryTest):
    def setUp(self):
        super(TestEndpointDiscoveryHandler, self).setUp()
        self.manager = Mock(spec=EndpointDiscoveryManager)
        self.handler = EndpointDiscoveryHandler(self.manager)
        self.service_model = ServiceModel(self.service_description)

    def test_register_handler(self):
        events = Mock(spec=HierarchicalEmitter)
        self.handler.register(events, 'foo-bar')
        events.register.assert_any_call(
            'before-parameter-build.foo-bar', self.handler.gather_identifiers
        )
        events.register.assert_any_call(
            'needs-retry.foo-bar', self.handler.handle_retries
        )
        events.register_first.assert_called_with(
            'request-created.foo-bar', self.handler.discover_endpoint
        )

    def test_discover_endpoint(self):
        request = AWSRequest()
        request.context = {
            'discovery': {'identifiers': {}}
        }
        self.manager.describe_endpoint.return_value = 'https://new.foo'
        self.handler.discover_endpoint(request, 'TestOperation')
        self.assertEqual(request.url, 'https://new.foo')
        self.manager.describe_endpoint.assert_called_with(
            Operation='TestOperation', Identifiers={}
        )

    def test_discover_endpoint_fails(self):
        request = AWSRequest()
        request.context = {
            'discovery': {'identifiers': {}}
        }
        request.url = 'old.com'
        self.manager.describe_endpoint.return_value = None
        self.handler.discover_endpoint(request, 'TestOperation')
        self.assertEqual(request.url, 'old.com')
        self.manager.describe_endpoint.assert_called_with(
            Operation='TestOperation', Identifiers={}
        )

    def test_discover_endpoint_no_protocol(self):
        request = AWSRequest()
        request.context = {
            'discovery': {'identifiers': {}}
        }
        self.manager.describe_endpoint.return_value = 'new.foo'
        self.handler.discover_endpoint(request, 'TestOperation')
        self.assertEqual(request.url, 'https://new.foo')
        self.manager.describe_endpoint.assert_called_with(
            Operation='TestOperation', Identifiers={}
        )

    def test_inject_no_context(self):
        request = AWSRequest(url='https://original.foo')
        self.handler.discover_endpoint(request, 'TestOperation')
        self.assertEqual(request.url, 'https://original.foo')
        self.manager.describe_endpoint.assert_not_called()

    def test_gather_identifiers(self):
        context = {}
        params = {
            'Foo': 'value1',
            'Nested': {'Bar': 'value2'}
        }
        ids = {
            'Foo': 'value1',
            'Bar': 'value2'
        }
        model = self.service_model.operation_model('TestDiscoveryRequired')
        self.manager.gather_identifiers.return_value = ids
        self.handler.gather_identifiers(params, model, context)
        self.assertEqual(context['discovery']['identifiers'], ids)

    def test_gather_identifiers_not_discoverable(self):
        context = {}
        model = self.service_model.operation_model('DescribeEndpoints')
        self.handler.gather_identifiers({}, model, context)
        self.assertEqual(context, {})

    def test_discovery_disabled_but_required(self):
        model = self.service_model.operation_model('TestDiscoveryRequired')
        with self.assertRaises(EndpointDiscoveryRequired):
            block_endpoint_discovery_required_operations(model)

    def test_discovery_disabled_but_optional(self):
        context = {}
        model = self.service_model.operation_model('TestDiscoveryOptional')
        block_endpoint_discovery_required_operations(model, context=context)
        self.assertEqual(context, {})

    def test_does_not_retry_no_response(self):
        retry = self.handler.handle_retries(None, None, None)
        self.assertIsNone(retry)

    def test_does_not_retry_other_errors(self):
        parsed_response = {
            'ResponseMetadata': {'HTTPStatusCode': 200}
        }
        response = (None, parsed_response)
        retry = self.handler.handle_retries(None, response, None)
        self.assertIsNone(retry)

    def test_does_not_retry_if_no_context(self):
        request_dict = {'context': {}}
        parsed_response = {
            'ResponseMetadata': {'HTTPStatusCode': 421}
        }
        response = (None, parsed_response)
        retry = self.handler.handle_retries(request_dict, response, None)
        self.assertIsNone(retry)

    def _assert_retries(self, parsed_response):
        request_dict = {
            'context': {
                'discovery': {'identifiers': {}}
            }
        }
        response = (None, parsed_response)
        model = self.service_model.operation_model('TestDiscoveryOptional')
        retry = self.handler.handle_retries(request_dict, response, model)
        self.assertEqual(retry, 0)
        self.manager.delete_endpoints.assert_called_with(
            Operation='TestDiscoveryOptional', Identifiers={}
        )

    def test_retries_421_status_code(self):
        parsed_response = {
            'ResponseMetadata': {'HTTPStatusCode': 421}
        }
        self._assert_retries(parsed_response)

    def test_retries_invalid_endpoint_exception(self):
        parsed_response = {'Error': {'Code': 'InvalidEndpointException'}}
        self._assert_retries(parsed_response)
Ejemplo n.º 51
0
class TestTimestampHeadersWithRestXML(unittest.TestCase):

    def setUp(self):
        self.model = {
            'metadata': {'protocol': 'rest-xml', 'apiVersion': '2014-01-01'},
            'documentation': '',
            'operations': {
                'TestOperation': {
                    'name': 'TestOperation',
                    'http': {
                        'method': 'POST',
                        'requestUri': '/',
                    },
                    'input': {'shape': 'InputShape'},
                }
            },
            'shapes': {
                'InputShape': {
                    'type': 'structure',
                    'members': {
                        'TimestampHeader': {
                            'shape': 'TimestampType',
                            'location': 'header',
                            'locationName': 'x-timestamp'
                        },
                    }
                },
                'TimestampType': {
                    'type': 'timestamp',
                }
            }
        }
        self.service_model = ServiceModel(self.model)

    def serialize_to_request(self, input_params):
        request_serializer = serialize.create_serializer(
            self.service_model.metadata['protocol'])
        return request_serializer.serialize_to_request(
            input_params, self.service_model.operation_model('TestOperation'))

    def test_accepts_datetime_object(self):
        request = self.serialize_to_request(
            {'TimestampHeader': datetime.datetime(2014, 1, 1, 12, 12, 12,
                                                  tzinfo=dateutil.tz.tzutc())})
        self.assertEqual(request['headers']['x-timestamp'],
                         'Wed, 01 Jan 2014 12:12:12 GMT')

    def test_accepts_iso_8601_format(self):
        request = self.serialize_to_request(
            {'TimestampHeader': '2014-01-01T12:12:12+00:00'})
        self.assertEqual(request['headers']['x-timestamp'],
                         'Wed, 01 Jan 2014 12:12:12 GMT')

    def test_accepts_iso_8601_format_non_utc(self):
        request = self.serialize_to_request(
            {'TimestampHeader': '2014-01-01T07:12:12-05:00'})
        self.assertEqual(request['headers']['x-timestamp'],
                         'Wed, 01 Jan 2014 12:12:12 GMT')

    def test_accepts_rfc_822_format(self):
        request = self.serialize_to_request(
            {'TimestampHeader': 'Wed, 01 Jan 2014 12:12:12 GMT'})
        self.assertEqual(request['headers']['x-timestamp'],
                         'Wed, 01 Jan 2014 12:12:12 GMT')

    def test_accepts_unix_timestamp_integer(self):
        request = self.serialize_to_request(
            {'TimestampHeader': 1388578332})
        self.assertEqual(request['headers']['x-timestamp'],
                         'Wed, 01 Jan 2014 12:12:12 GMT')
Ejemplo n.º 52
0
 def setUp(self):
     super(TestEndpointDiscoveryHandler, self).setUp()
     self.manager = Mock(spec=EndpointDiscoveryManager)
     self.handler = EndpointDiscoveryHandler(self.manager)
     self.service_model = ServiceModel(self.service_description)