We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Is it possible to support dynamodbstreams ListStreams?
See also  https://github.com/localstack/localstack/blob/master/localstack/services/dynamodbstreams/dynamodbstreams_api.py#L70 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `localstack/services/dynamodbstreams/dynamodbstreams_api.py`
Content:
```
1 import json
2 import uuid
3 import hashlib
4 import six
5 from flask import Flask, jsonify, request, make_response
6 from localstack.services import generic_proxy
7 from localstack.utils.aws import aws_stack
8 from localstack.utils.common import to_str, to_bytes
9 from localstack.utils.analytics import event_publisher
10 
11 APP_NAME = 'ddb_streams_api'
12 
13 app = Flask(APP_NAME)
14 
15 DDB_STREAMS = {}
16 
17 DDB_KINESIS_STREAM_NAME_PREFIX = '__ddb_stream_'
18 
19 ACTION_HEADER_PREFIX = 'DynamoDBStreams_20120810'
20 
21 SEQUENCE_NUMBER_COUNTER = 1
22 
23 
24 def add_dynamodb_stream(table_name, latest_stream_label=None, view_type='NEW_AND_OLD_IMAGES', enabled=True):
25     if enabled:
26         # create kinesis stream as a backend
27         stream_name = get_kinesis_stream_name(table_name)
28         aws_stack.create_kinesis_stream(stream_name)
29         latest_stream_label = latest_stream_label or 'latest'
30         stream = {
31             'StreamArn': aws_stack.dynamodb_stream_arn(
32                 table_name=table_name, latest_stream_label=latest_stream_label),
33             'TableName': table_name,
34             'StreamLabel': latest_stream_label,
35             'StreamStatus': 'ENABLED',
36             'KeySchema': [],
37             'Shards': []
38         }
39         table_arn = aws_stack.dynamodb_table_arn(table_name)
40         DDB_STREAMS[table_arn] = stream
41         # record event
42         event_publisher.fire_event(event_publisher.EVENT_DYNAMODB_CREATE_STREAM,
43             payload={'n': event_publisher.get_hash(table_name)})
44 
45 
46 def forward_events(records):
47     global SEQUENCE_NUMBER_COUNTER
48     kinesis = aws_stack.connect_to_service('kinesis')
49     for record in records:
50         if 'SequenceNumber' not in record['dynamodb']:
51             record['dynamodb']['SequenceNumber'] = str(SEQUENCE_NUMBER_COUNTER)
52             SEQUENCE_NUMBER_COUNTER += 1
53         table_arn = record['eventSourceARN']
54         stream = DDB_STREAMS.get(table_arn)
55         if stream:
56             table_name = table_name_from_stream_arn(stream['StreamArn'])
57             stream_name = get_kinesis_stream_name(table_name)
58             kinesis.put_record(StreamName=stream_name, Data=json.dumps(record), PartitionKey='TODO')
59 
60 
61 @app.route('/', methods=['POST'])
62 def post_request():
63     action = request.headers.get('x-amz-target')
64     data = json.loads(to_str(request.data))
65     result = {}
66     kinesis = aws_stack.connect_to_service('kinesis')
67     if action == '%s.ListStreams' % ACTION_HEADER_PREFIX:
68         result = {
69             'Streams': list(DDB_STREAMS.values()),
70             'LastEvaluatedStreamArn': 'TODO'
71         }
72     elif action == '%s.DescribeStream' % ACTION_HEADER_PREFIX:
73         for stream in DDB_STREAMS.values():
74             if stream['StreamArn'] == data['StreamArn']:
75                 result = {
76                     'StreamDescription': stream
77                 }
78                 # get stream details
79                 dynamodb = aws_stack.connect_to_service('dynamodb')
80                 table_name = table_name_from_stream_arn(stream['StreamArn'])
81                 stream_name = get_kinesis_stream_name(table_name)
82                 stream_details = kinesis.describe_stream(StreamName=stream_name)
83                 table_details = dynamodb.describe_table(TableName=table_name)
84                 stream['KeySchema'] = table_details['Table']['KeySchema']
85 
86                 # Replace Kinesis ShardIDs with ones that mimic actual
87                 # DynamoDBStream ShardIDs.
88                 stream_shards = stream_details['StreamDescription']['Shards']
89                 for shard in stream_shards:
90                     shard['ShardId'] = shard_id(stream_name, shard['ShardId'])
91                 stream['Shards'] = stream_shards
92                 break
93         if not result:
94             return error_response('Requested resource not found', error_type='ResourceNotFoundException')
95     elif action == '%s.GetShardIterator' % ACTION_HEADER_PREFIX:
96         # forward request to Kinesis API
97         stream_name = stream_name_from_stream_arn(data['StreamArn'])
98         stream_shard_id = kinesis_shard_id(data['ShardId'])
99         result = kinesis.get_shard_iterator(StreamName=stream_name,
100             ShardId=stream_shard_id, ShardIteratorType=data['ShardIteratorType'])
101     elif action == '%s.GetRecords' % ACTION_HEADER_PREFIX:
102         kinesis_records = kinesis.get_records(**data)
103         result = {'Records': [], 'NextShardIterator': kinesis_records.get('NextShardIterator')}
104         for record in kinesis_records['Records']:
105             result['Records'].append(json.loads(to_str(record['Data'])))
106     else:
107         print('WARNING: Unknown operation "%s"' % action)
108     return jsonify(result)
109 
110 
111 # -----------------
112 # HELPER FUNCTIONS
113 # -----------------
114 
115 def error_response(message=None, error_type=None, code=400):
116     if not message:
117         message = 'Unknown error'
118     if not error_type:
119         error_type = 'UnknownError'
120     if 'com.amazonaws.dynamodb' not in error_type:
121         error_type = 'com.amazonaws.dynamodb.v20120810#%s' % error_type
122     content = {
123         'message': message,
124         '__type': error_type
125     }
126     return make_response(jsonify(content), code)
127 
128 
129 def get_kinesis_stream_name(table_name):
130     return DDB_KINESIS_STREAM_NAME_PREFIX + table_name
131 
132 
133 def table_name_from_stream_arn(stream_arn):
134     return stream_arn.split(':table/')[1].split('/')[0]
135 
136 
137 def stream_name_from_stream_arn(stream_arn):
138     table_name = table_name_from_stream_arn(stream_arn)
139     return get_kinesis_stream_name(table_name)
140 
141 
142 def random_id(stream_arn, kinesis_shard_id):
143     namespace = uuid.UUID(bytes=hashlib.sha1(to_bytes(stream_arn)).digest()[:16])
144     if six.PY2:
145         kinesis_shard_id = to_bytes(kinesis_shard_id, 'utf-8')
146     return uuid.uuid5(namespace, kinesis_shard_id).hex
147 
148 
149 def shard_id(stream_arn, kinesis_shard_id):
150     return '-'.join([kinesis_shard_id, random_id(stream_arn, kinesis_shard_id)])
151 
152 
153 def kinesis_shard_id(dynamodbstream_shard_id):
154     return dynamodbstream_shard_id.rsplit('-', 1)[0]
155 
156 
157 def serve(port, quiet=True):
158     generic_proxy.serve_flask_app(app=app, port=port, quiet=quiet)
159
```

Path: `localstack/constants.py`
Content:
```
1 import os
2 import localstack_client.config
3 
4 # LocalStack version
5 VERSION = '0.10.7'
6 
7 # constant to represent the "local" region, i.e., local machine
8 REGION_LOCAL = 'local'
9 
10 # dev environment
11 ENV_DEV = 'dev'
12 
13 # backend service ports, for services that are behind a proxy (counting down from 4566)
14 DEFAULT_PORT_APIGATEWAY_BACKEND = 4566
15 DEFAULT_PORT_KINESIS_BACKEND = 4565
16 DEFAULT_PORT_DYNAMODB_BACKEND = 4564
17 DEFAULT_PORT_S3_BACKEND = 4563
18 DEFAULT_PORT_SNS_BACKEND = 4562
19 DEFAULT_PORT_SQS_BACKEND = 4561
20 DEFAULT_PORT_ELASTICSEARCH_BACKEND = 4560
21 DEFAULT_PORT_CLOUDFORMATION_BACKEND = 4559
22 DEFAULT_PORT_STEPFUNCTIONS_BACKEND = 4558
23 DEFAULT_PORT_IAM_BACKEND = 4557
24 DEFAULT_PORT_EC2_BACKEND = 4556
25 DEFAULT_PORT_KMS_BACKEND = 4555
26 DEFAULT_PORT_EVENTS_BACKEND = 4554
27 DEFAULT_PORT_LOGS_BACKEND = 4553
28 
29 DEFAULT_PORT_WEB_UI = 8080
30 
31 LOCALHOST = 'localhost'
32 
33 # version of the Maven dependency with Java utility code
34 LOCALSTACK_MAVEN_VERSION = '0.2.0'
35 
36 # map of default service APIs and ports to be spun up (fetch map from localstack_client)
37 DEFAULT_SERVICE_PORTS = localstack_client.config.get_service_ports()
38 
39 # host to bind to when starting the services
40 BIND_HOST = '0.0.0.0'
41 
42 # AWS user account ID used for tests
43 if 'TEST_AWS_ACCOUNT_ID' not in os.environ:
44     os.environ['TEST_AWS_ACCOUNT_ID'] = '000000000000'
45 TEST_AWS_ACCOUNT_ID = os.environ['TEST_AWS_ACCOUNT_ID']
46 
47 # root code folder
48 LOCALSTACK_ROOT_FOLDER = os.path.realpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
49 
50 # virtualenv folder
51 LOCALSTACK_VENV_FOLDER = os.path.join(LOCALSTACK_ROOT_FOLDER, '.venv')
52 if not os.path.isdir(LOCALSTACK_VENV_FOLDER):
53     # assuming this package lives here: <python>/lib/pythonX.X/site-packages/localstack/
54     LOCALSTACK_VENV_FOLDER = os.path.realpath(os.path.join(LOCALSTACK_ROOT_FOLDER, '..', '..', '..'))
55 
56 # API Gateway path to indicate a user request sent to the gateway
57 PATH_USER_REQUEST = '_user_request_'
58 
59 # name of LocalStack Docker image
60 DOCKER_IMAGE_NAME = 'localstack/localstack'
61 
62 # backdoor API path used to retrieve or update config variables
63 CONFIG_UPDATE_PATH = '/?_config_'
64 
65 # environment variable name to tag local test runs
66 ENV_INTERNAL_TEST_RUN = 'LOCALSTACK_INTERNAL_TEST_RUN'
67 
68 # content types
69 APPLICATION_AMZ_JSON_1_0 = 'application/x-amz-json-1.0'
70 APPLICATION_AMZ_JSON_1_1 = 'application/x-amz-json-1.1'
71 APPLICATION_JSON = 'application/json'
72 APPLICATION_XML = 'application/xml'
73 APPLICATION_X_WWW_FORM_URLENCODED = 'application/x-www-form-urlencoded'
74 
75 # strings to indicate truthy/falsy values
76 TRUE_STRINGS = ('1', 'true', 'True')
77 FALSE_STRINGS = ('0', 'false', 'False')
78 
79 # Lambda defaults
80 LAMBDA_TEST_ROLE = 'arn:aws:iam::%s:role/lambda-test-role' % TEST_AWS_ACCOUNT_ID
81 
82 # installation constants
83 ELASTICSEARCH_JAR_URL = 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.7.0.zip'
84 # See https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/aes-supported-plugins.html
85 ELASTICSEARCH_PLUGIN_LIST = ['analysis-icu', 'ingest-attachment', 'analysis-kuromoji',
86  'mapper-murmur3', 'mapper-size', 'analysis-phonetic', 'analysis-smartcn', 'analysis-stempel', 'analysis-ukrainian']
87 # Default ES modules to exclude (save apprx 66MB in the final image)
88 ELASTICSEARCH_DELETE_MODULES = ['ingest-geoip']
89 ELASTICMQ_JAR_URL = 'https://s3-eu-west-1.amazonaws.com/softwaremill-public/elasticmq-server-0.15.4.jar'
90 STS_JAR_URL = 'https://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-sts/1.11.14/aws-java-sdk-sts-1.11.14.jar'
91 STEPFUNCTIONS_ZIP_URL = 'https://s3.amazonaws.com/stepfunctionslocal/StepFunctionsLocal.zip'
92 KMS_URL_PATTERN = 'https://s3-eu-west-2.amazonaws.com/local-kms/localstack/v3/local-kms.<arch>.bin'
93 
94 # TODO: Temporarily using a fixed version of DDB in Alpine, as we're hitting a SIGSEGV JVM crash with latest
95 DYNAMODB_JAR_URL_ALPINE = 'https://github.com/whummer/dynamodb-local/raw/master/etc/DynamoDBLocal.zip'
96 DYNAMODB_JAR_URL = 'https://s3-us-west-2.amazonaws.com/dynamodb-local/dynamodb_local_latest.zip'
97 
98 # API endpoint for analytics events
99 API_ENDPOINT = os.environ.get('API_ENDPOINT') or 'https://api.localstack.cloud/v1'
100 
101 # environment variable to indicates that this process is running the Web UI
102 LOCALSTACK_WEB_PROCESS = 'LOCALSTACK_WEB_PROCESS'
103 LOCALSTACK_INFRA_PROCESS = 'LOCALSTACK_INFRA_PROCESS'
104 
105 # Hardcoded AWS account ID used by moto
106 MOTO_ACCOUNT_ID = '123456789012'
107 
108 # Default lambda registry
109 DEFAULT_LAMBDA_CONTAINER_REGISTRY = 'lambci/lambda'
110
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/localstack/constants.py b/localstack/constants.py
--- a/localstack/constants.py
+++ b/localstack/constants.py
@@ -2,7 +2,7 @@
 import localstack_client.config
 
 # LocalStack version
-VERSION = '0.10.7'
+VERSION = '0.10.8'
 
 # constant to represent the "local" region, i.e., local machine
 REGION_LOCAL = 'local'
@@ -31,7 +31,7 @@
 LOCALHOST = 'localhost'
 
 # version of the Maven dependency with Java utility code
-LOCALSTACK_MAVEN_VERSION = '0.2.0'
+LOCALSTACK_MAVEN_VERSION = '0.2.1'
 
 # map of default service APIs and ports to be spun up (fetch map from localstack_client)
 DEFAULT_SERVICE_PORTS = localstack_client.config.get_service_ports()
diff --git a/localstack/services/dynamodbstreams/dynamodbstreams_api.py b/localstack/services/dynamodbstreams/dynamodbstreams_api.py
--- a/localstack/services/dynamodbstreams/dynamodbstreams_api.py
+++ b/localstack/services/dynamodbstreams/dynamodbstreams_api.py
@@ -66,8 +66,7 @@
     kinesis = aws_stack.connect_to_service('kinesis')
     if action == '%s.ListStreams' % ACTION_HEADER_PREFIX:
         result = {
-            'Streams': list(DDB_STREAMS.values()),
-            'LastEvaluatedStreamArn': 'TODO'
+            'Streams': list(DDB_STREAMS.values())
         }
     elif action == '%s.DescribeStream' % ACTION_HEADER_PREFIX:
         for stream in DDB_STREAMS.values():

{"golden_diff": "diff --git a/localstack/constants.py b/localstack/constants.py\n--- a/localstack/constants.py\n+++ b/localstack/constants.py\n@@ -2,7 +2,7 @@\n import localstack_client.config\n \n # LocalStack version\n-VERSION = '0.10.7'\n+VERSION = '0.10.8'\n \n # constant to represent the \"local\" region, i.e., local machine\n REGION_LOCAL = 'local'\n@@ -31,7 +31,7 @@\n LOCALHOST = 'localhost'\n \n # version of the Maven dependency with Java utility code\n-LOCALSTACK_MAVEN_VERSION = '0.2.0'\n+LOCALSTACK_MAVEN_VERSION = '0.2.1'\n \n # map of default service APIs and ports to be spun up (fetch map from localstack_client)\n DEFAULT_SERVICE_PORTS = localstack_client.config.get_service_ports()\ndiff --git a/localstack/services/dynamodbstreams/dynamodbstreams_api.py b/localstack/services/dynamodbstreams/dynamodbstreams_api.py\n--- a/localstack/services/dynamodbstreams/dynamodbstreams_api.py\n+++ b/localstack/services/dynamodbstreams/dynamodbstreams_api.py\n@@ -66,8 +66,7 @@\n     kinesis = aws_stack.connect_to_service('kinesis')\n     if action == '%s.ListStreams' % ACTION_HEADER_PREFIX:\n         result = {\n-            'Streams': list(DDB_STREAMS.values()),\n-            'LastEvaluatedStreamArn': 'TODO'\n+            'Streams': list(DDB_STREAMS.values())\n         }\n     elif action == '%s.DescribeStream' % ACTION_HEADER_PREFIX:\n         for stream in DDB_STREAMS.values():\n", "issue": "Is it possible to support dynamodbstreams ListStreams?\nSee also  https://github.com/localstack/localstack/blob/master/localstack/services/dynamodbstreams/dynamodbstreams_api.py#L70 \n", "before_files": [{"content": "import json\nimport uuid\nimport hashlib\nimport six\nfrom flask import Flask, jsonify, request, make_response\nfrom localstack.services import generic_proxy\nfrom localstack.utils.aws import aws_stack\nfrom localstack.utils.common import to_str, to_bytes\nfrom localstack.utils.analytics import event_publisher\n\nAPP_NAME = 'ddb_streams_api'\n\napp = Flask(APP_NAME)\n\nDDB_STREAMS = {}\n\nDDB_KINESIS_STREAM_NAME_PREFIX = '__ddb_stream_'\n\nACTION_HEADER_PREFIX = 'DynamoDBStreams_20120810'\n\nSEQUENCE_NUMBER_COUNTER = 1\n\n\ndef add_dynamodb_stream(table_name, latest_stream_label=None, view_type='NEW_AND_OLD_IMAGES', enabled=True):\n    if enabled:\n        # create kinesis stream as a backend\n        stream_name = get_kinesis_stream_name(table_name)\n        aws_stack.create_kinesis_stream(stream_name)\n        latest_stream_label = latest_stream_label or 'latest'\n        stream = {\n            'StreamArn': aws_stack.dynamodb_stream_arn(\n                table_name=table_name, latest_stream_label=latest_stream_label),\n            'TableName': table_name,\n            'StreamLabel': latest_stream_label,\n            'StreamStatus': 'ENABLED',\n            'KeySchema': [],\n            'Shards': []\n        }\n        table_arn = aws_stack.dynamodb_table_arn(table_name)\n        DDB_STREAMS[table_arn] = stream\n        # record event\n        event_publisher.fire_event(event_publisher.EVENT_DYNAMODB_CREATE_STREAM,\n            payload={'n': event_publisher.get_hash(table_name)})\n\n\ndef forward_events(records):\n    global SEQUENCE_NUMBER_COUNTER\n    kinesis = aws_stack.connect_to_service('kinesis')\n    for record in records:\n        if 'SequenceNumber' not in record['dynamodb']:\n            record['dynamodb']['SequenceNumber'] = str(SEQUENCE_NUMBER_COUNTER)\n            SEQUENCE_NUMBER_COUNTER += 1\n        table_arn = record['eventSourceARN']\n        stream = DDB_STREAMS.get(table_arn)\n        if stream:\n            table_name = table_name_from_stream_arn(stream['StreamArn'])\n            stream_name = get_kinesis_stream_name(table_name)\n            kinesis.put_record(StreamName=stream_name, Data=json.dumps(record), PartitionKey='TODO')\n\n\n@app.route('/', methods=['POST'])\ndef post_request():\n    action = request.headers.get('x-amz-target')\n    data = json.loads(to_str(request.data))\n    result = {}\n    kinesis = aws_stack.connect_to_service('kinesis')\n    if action == '%s.ListStreams' % ACTION_HEADER_PREFIX:\n        result = {\n            'Streams': list(DDB_STREAMS.values()),\n            'LastEvaluatedStreamArn': 'TODO'\n        }\n    elif action == '%s.DescribeStream' % ACTION_HEADER_PREFIX:\n        for stream in DDB_STREAMS.values():\n            if stream['StreamArn'] == data['StreamArn']:\n                result = {\n                    'StreamDescription': stream\n                }\n                # get stream details\n                dynamodb = aws_stack.connect_to_service('dynamodb')\n                table_name = table_name_from_stream_arn(stream['StreamArn'])\n                stream_name = get_kinesis_stream_name(table_name)\n                stream_details = kinesis.describe_stream(StreamName=stream_name)\n                table_details = dynamodb.describe_table(TableName=table_name)\n                stream['KeySchema'] = table_details['Table']['KeySchema']\n\n                # Replace Kinesis ShardIDs with ones that mimic actual\n                # DynamoDBStream ShardIDs.\n                stream_shards = stream_details['StreamDescription']['Shards']\n                for shard in stream_shards:\n                    shard['ShardId'] = shard_id(stream_name, shard['ShardId'])\n                stream['Shards'] = stream_shards\n                break\n        if not result:\n            return error_response('Requested resource not found', error_type='ResourceNotFoundException')\n    elif action == '%s.GetShardIterator' % ACTION_HEADER_PREFIX:\n        # forward request to Kinesis API\n        stream_name = stream_name_from_stream_arn(data['StreamArn'])\n        stream_shard_id = kinesis_shard_id(data['ShardId'])\n        result = kinesis.get_shard_iterator(StreamName=stream_name,\n            ShardId=stream_shard_id, ShardIteratorType=data['ShardIteratorType'])\n    elif action == '%s.GetRecords' % ACTION_HEADER_PREFIX:\n        kinesis_records = kinesis.get_records(**data)\n        result = {'Records': [], 'NextShardIterator': kinesis_records.get('NextShardIterator')}\n        for record in kinesis_records['Records']:\n            result['Records'].append(json.loads(to_str(record['Data'])))\n    else:\n        print('WARNING: Unknown operation \"%s\"' % action)\n    return jsonify(result)\n\n\n# -----------------\n# HELPER FUNCTIONS\n# -----------------\n\ndef error_response(message=None, error_type=None, code=400):\n    if not message:\n        message = 'Unknown error'\n    if not error_type:\n        error_type = 'UnknownError'\n    if 'com.amazonaws.dynamodb' not in error_type:\n        error_type = 'com.amazonaws.dynamodb.v20120810#%s' % error_type\n    content = {\n        'message': message,\n        '__type': error_type\n    }\n    return make_response(jsonify(content), code)\n\n\ndef get_kinesis_stream_name(table_name):\n    return DDB_KINESIS_STREAM_NAME_PREFIX + table_name\n\n\ndef table_name_from_stream_arn(stream_arn):\n    return stream_arn.split(':table/')[1].split('/')[0]\n\n\ndef stream_name_from_stream_arn(stream_arn):\n    table_name = table_name_from_stream_arn(stream_arn)\n    return get_kinesis_stream_name(table_name)\n\n\ndef random_id(stream_arn, kinesis_shard_id):\n    namespace = uuid.UUID(bytes=hashlib.sha1(to_bytes(stream_arn)).digest()[:16])\n    if six.PY2:\n        kinesis_shard_id = to_bytes(kinesis_shard_id, 'utf-8')\n    return uuid.uuid5(namespace, kinesis_shard_id).hex\n\n\ndef shard_id(stream_arn, kinesis_shard_id):\n    return '-'.join([kinesis_shard_id, random_id(stream_arn, kinesis_shard_id)])\n\n\ndef kinesis_shard_id(dynamodbstream_shard_id):\n    return dynamodbstream_shard_id.rsplit('-', 1)[0]\n\n\ndef serve(port, quiet=True):\n    generic_proxy.serve_flask_app(app=app, port=port, quiet=quiet)\n", "path": "localstack/services/dynamodbstreams/dynamodbstreams_api.py"}, {"content": "import os\nimport localstack_client.config\n\n# LocalStack version\nVERSION = '0.10.7'\n\n# constant to represent the \"local\" region, i.e., local machine\nREGION_LOCAL = 'local'\n\n# dev environment\nENV_DEV = 'dev'\n\n# backend service ports, for services that are behind a proxy (counting down from 4566)\nDEFAULT_PORT_APIGATEWAY_BACKEND = 4566\nDEFAULT_PORT_KINESIS_BACKEND = 4565\nDEFAULT_PORT_DYNAMODB_BACKEND = 4564\nDEFAULT_PORT_S3_BACKEND = 4563\nDEFAULT_PORT_SNS_BACKEND = 4562\nDEFAULT_PORT_SQS_BACKEND = 4561\nDEFAULT_PORT_ELASTICSEARCH_BACKEND = 4560\nDEFAULT_PORT_CLOUDFORMATION_BACKEND = 4559\nDEFAULT_PORT_STEPFUNCTIONS_BACKEND = 4558\nDEFAULT_PORT_IAM_BACKEND = 4557\nDEFAULT_PORT_EC2_BACKEND = 4556\nDEFAULT_PORT_KMS_BACKEND = 4555\nDEFAULT_PORT_EVENTS_BACKEND = 4554\nDEFAULT_PORT_LOGS_BACKEND = 4553\n\nDEFAULT_PORT_WEB_UI = 8080\n\nLOCALHOST = 'localhost'\n\n# version of the Maven dependency with Java utility code\nLOCALSTACK_MAVEN_VERSION = '0.2.0'\n\n# map of default service APIs and ports to be spun up (fetch map from localstack_client)\nDEFAULT_SERVICE_PORTS = localstack_client.config.get_service_ports()\n\n# host to bind to when starting the services\nBIND_HOST = '0.0.0.0'\n\n# AWS user account ID used for tests\nif 'TEST_AWS_ACCOUNT_ID' not in os.environ:\n    os.environ['TEST_AWS_ACCOUNT_ID'] = '000000000000'\nTEST_AWS_ACCOUNT_ID = os.environ['TEST_AWS_ACCOUNT_ID']\n\n# root code folder\nLOCALSTACK_ROOT_FOLDER = os.path.realpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))\n\n# virtualenv folder\nLOCALSTACK_VENV_FOLDER = os.path.join(LOCALSTACK_ROOT_FOLDER, '.venv')\nif not os.path.isdir(LOCALSTACK_VENV_FOLDER):\n    # assuming this package lives here: <python>/lib/pythonX.X/site-packages/localstack/\n    LOCALSTACK_VENV_FOLDER = os.path.realpath(os.path.join(LOCALSTACK_ROOT_FOLDER, '..', '..', '..'))\n\n# API Gateway path to indicate a user request sent to the gateway\nPATH_USER_REQUEST = '_user_request_'\n\n# name of LocalStack Docker image\nDOCKER_IMAGE_NAME = 'localstack/localstack'\n\n# backdoor API path used to retrieve or update config variables\nCONFIG_UPDATE_PATH = '/?_config_'\n\n# environment variable name to tag local test runs\nENV_INTERNAL_TEST_RUN = 'LOCALSTACK_INTERNAL_TEST_RUN'\n\n# content types\nAPPLICATION_AMZ_JSON_1_0 = 'application/x-amz-json-1.0'\nAPPLICATION_AMZ_JSON_1_1 = 'application/x-amz-json-1.1'\nAPPLICATION_JSON = 'application/json'\nAPPLICATION_XML = 'application/xml'\nAPPLICATION_X_WWW_FORM_URLENCODED = 'application/x-www-form-urlencoded'\n\n# strings to indicate truthy/falsy values\nTRUE_STRINGS = ('1', 'true', 'True')\nFALSE_STRINGS = ('0', 'false', 'False')\n\n# Lambda defaults\nLAMBDA_TEST_ROLE = 'arn:aws:iam::%s:role/lambda-test-role' % TEST_AWS_ACCOUNT_ID\n\n# installation constants\nELASTICSEARCH_JAR_URL = 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.7.0.zip'\n# See https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/aes-supported-plugins.html\nELASTICSEARCH_PLUGIN_LIST = ['analysis-icu', 'ingest-attachment', 'analysis-kuromoji',\n 'mapper-murmur3', 'mapper-size', 'analysis-phonetic', 'analysis-smartcn', 'analysis-stempel', 'analysis-ukrainian']\n# Default ES modules to exclude (save apprx 66MB in the final image)\nELASTICSEARCH_DELETE_MODULES = ['ingest-geoip']\nELASTICMQ_JAR_URL = 'https://s3-eu-west-1.amazonaws.com/softwaremill-public/elasticmq-server-0.15.4.jar'\nSTS_JAR_URL = 'https://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-sts/1.11.14/aws-java-sdk-sts-1.11.14.jar'\nSTEPFUNCTIONS_ZIP_URL = 'https://s3.amazonaws.com/stepfunctionslocal/StepFunctionsLocal.zip'\nKMS_URL_PATTERN = 'https://s3-eu-west-2.amazonaws.com/local-kms/localstack/v3/local-kms.<arch>.bin'\n\n# TODO: Temporarily using a fixed version of DDB in Alpine, as we're hitting a SIGSEGV JVM crash with latest\nDYNAMODB_JAR_URL_ALPINE = 'https://github.com/whummer/dynamodb-local/raw/master/etc/DynamoDBLocal.zip'\nDYNAMODB_JAR_URL = 'https://s3-us-west-2.amazonaws.com/dynamodb-local/dynamodb_local_latest.zip'\n\n# API endpoint for analytics events\nAPI_ENDPOINT = os.environ.get('API_ENDPOINT') or 'https://api.localstack.cloud/v1'\n\n# environment variable to indicates that this process is running the Web UI\nLOCALSTACK_WEB_PROCESS = 'LOCALSTACK_WEB_PROCESS'\nLOCALSTACK_INFRA_PROCESS = 'LOCALSTACK_INFRA_PROCESS'\n\n# Hardcoded AWS account ID used by moto\nMOTO_ACCOUNT_ID = '123456789012'\n\n# Default lambda registry\nDEFAULT_LAMBDA_CONTAINER_REGISTRY = 'lambci/lambda'\n", "path": "localstack/constants.py"}], "after_files": [{"content": "import json\nimport uuid\nimport hashlib\nimport six\nfrom flask import Flask, jsonify, request, make_response\nfrom localstack.services import generic_proxy\nfrom localstack.utils.aws import aws_stack\nfrom localstack.utils.common import to_str, to_bytes\nfrom localstack.utils.analytics import event_publisher\n\nAPP_NAME = 'ddb_streams_api'\n\napp = Flask(APP_NAME)\n\nDDB_STREAMS = {}\n\nDDB_KINESIS_STREAM_NAME_PREFIX = '__ddb_stream_'\n\nACTION_HEADER_PREFIX = 'DynamoDBStreams_20120810'\n\nSEQUENCE_NUMBER_COUNTER = 1\n\n\ndef add_dynamodb_stream(table_name, latest_stream_label=None, view_type='NEW_AND_OLD_IMAGES', enabled=True):\n    if enabled:\n        # create kinesis stream as a backend\n        stream_name = get_kinesis_stream_name(table_name)\n        aws_stack.create_kinesis_stream(stream_name)\n        latest_stream_label = latest_stream_label or 'latest'\n        stream = {\n            'StreamArn': aws_stack.dynamodb_stream_arn(\n                table_name=table_name, latest_stream_label=latest_stream_label),\n            'TableName': table_name,\n            'StreamLabel': latest_stream_label,\n            'StreamStatus': 'ENABLED',\n            'KeySchema': [],\n            'Shards': []\n        }\n        table_arn = aws_stack.dynamodb_table_arn(table_name)\n        DDB_STREAMS[table_arn] = stream\n        # record event\n        event_publisher.fire_event(event_publisher.EVENT_DYNAMODB_CREATE_STREAM,\n            payload={'n': event_publisher.get_hash(table_name)})\n\n\ndef forward_events(records):\n    global SEQUENCE_NUMBER_COUNTER\n    kinesis = aws_stack.connect_to_service('kinesis')\n    for record in records:\n        if 'SequenceNumber' not in record['dynamodb']:\n            record['dynamodb']['SequenceNumber'] = str(SEQUENCE_NUMBER_COUNTER)\n            SEQUENCE_NUMBER_COUNTER += 1\n        table_arn = record['eventSourceARN']\n        stream = DDB_STREAMS.get(table_arn)\n        if stream:\n            table_name = table_name_from_stream_arn(stream['StreamArn'])\n            stream_name = get_kinesis_stream_name(table_name)\n            kinesis.put_record(StreamName=stream_name, Data=json.dumps(record), PartitionKey='TODO')\n\n\n@app.route('/', methods=['POST'])\ndef post_request():\n    action = request.headers.get('x-amz-target')\n    data = json.loads(to_str(request.data))\n    result = {}\n    kinesis = aws_stack.connect_to_service('kinesis')\n    if action == '%s.ListStreams' % ACTION_HEADER_PREFIX:\n        result = {\n            'Streams': list(DDB_STREAMS.values())\n        }\n    elif action == '%s.DescribeStream' % ACTION_HEADER_PREFIX:\n        for stream in DDB_STREAMS.values():\n            if stream['StreamArn'] == data['StreamArn']:\n                result = {\n                    'StreamDescription': stream\n                }\n                # get stream details\n                dynamodb = aws_stack.connect_to_service('dynamodb')\n                table_name = table_name_from_stream_arn(stream['StreamArn'])\n                stream_name = get_kinesis_stream_name(table_name)\n                stream_details = kinesis.describe_stream(StreamName=stream_name)\n                table_details = dynamodb.describe_table(TableName=table_name)\n                stream['KeySchema'] = table_details['Table']['KeySchema']\n\n                # Replace Kinesis ShardIDs with ones that mimic actual\n                # DynamoDBStream ShardIDs.\n                stream_shards = stream_details['StreamDescription']['Shards']\n                for shard in stream_shards:\n                    shard['ShardId'] = shard_id(stream_name, shard['ShardId'])\n                stream['Shards'] = stream_shards\n                break\n        if not result:\n            return error_response('Requested resource not found', error_type='ResourceNotFoundException')\n    elif action == '%s.GetShardIterator' % ACTION_HEADER_PREFIX:\n        # forward request to Kinesis API\n        stream_name = stream_name_from_stream_arn(data['StreamArn'])\n        stream_shard_id = kinesis_shard_id(data['ShardId'])\n        result = kinesis.get_shard_iterator(StreamName=stream_name,\n            ShardId=stream_shard_id, ShardIteratorType=data['ShardIteratorType'])\n    elif action == '%s.GetRecords' % ACTION_HEADER_PREFIX:\n        kinesis_records = kinesis.get_records(**data)\n        result = {'Records': [], 'NextShardIterator': kinesis_records.get('NextShardIterator')}\n        for record in kinesis_records['Records']:\n            result['Records'].append(json.loads(to_str(record['Data'])))\n    else:\n        print('WARNING: Unknown operation \"%s\"' % action)\n    return jsonify(result)\n\n\n# -----------------\n# HELPER FUNCTIONS\n# -----------------\n\ndef error_response(message=None, error_type=None, code=400):\n    if not message:\n        message = 'Unknown error'\n    if not error_type:\n        error_type = 'UnknownError'\n    if 'com.amazonaws.dynamodb' not in error_type:\n        error_type = 'com.amazonaws.dynamodb.v20120810#%s' % error_type\n    content = {\n        'message': message,\n        '__type': error_type\n    }\n    return make_response(jsonify(content), code)\n\n\ndef get_kinesis_stream_name(table_name):\n    return DDB_KINESIS_STREAM_NAME_PREFIX + table_name\n\n\ndef table_name_from_stream_arn(stream_arn):\n    return stream_arn.split(':table/')[1].split('/')[0]\n\n\ndef stream_name_from_stream_arn(stream_arn):\n    table_name = table_name_from_stream_arn(stream_arn)\n    return get_kinesis_stream_name(table_name)\n\n\ndef random_id(stream_arn, kinesis_shard_id):\n    namespace = uuid.UUID(bytes=hashlib.sha1(to_bytes(stream_arn)).digest()[:16])\n    if six.PY2:\n        kinesis_shard_id = to_bytes(kinesis_shard_id, 'utf-8')\n    return uuid.uuid5(namespace, kinesis_shard_id).hex\n\n\ndef shard_id(stream_arn, kinesis_shard_id):\n    return '-'.join([kinesis_shard_id, random_id(stream_arn, kinesis_shard_id)])\n\n\ndef kinesis_shard_id(dynamodbstream_shard_id):\n    return dynamodbstream_shard_id.rsplit('-', 1)[0]\n\n\ndef serve(port, quiet=True):\n    generic_proxy.serve_flask_app(app=app, port=port, quiet=quiet)\n", "path": "localstack/services/dynamodbstreams/dynamodbstreams_api.py"}, {"content": "import os\nimport localstack_client.config\n\n# LocalStack version\nVERSION = '0.10.8'\n\n# constant to represent the \"local\" region, i.e., local machine\nREGION_LOCAL = 'local'\n\n# dev environment\nENV_DEV = 'dev'\n\n# backend service ports, for services that are behind a proxy (counting down from 4566)\nDEFAULT_PORT_APIGATEWAY_BACKEND = 4566\nDEFAULT_PORT_KINESIS_BACKEND = 4565\nDEFAULT_PORT_DYNAMODB_BACKEND = 4564\nDEFAULT_PORT_S3_BACKEND = 4563\nDEFAULT_PORT_SNS_BACKEND = 4562\nDEFAULT_PORT_SQS_BACKEND = 4561\nDEFAULT_PORT_ELASTICSEARCH_BACKEND = 4560\nDEFAULT_PORT_CLOUDFORMATION_BACKEND = 4559\nDEFAULT_PORT_STEPFUNCTIONS_BACKEND = 4558\nDEFAULT_PORT_IAM_BACKEND = 4557\nDEFAULT_PORT_EC2_BACKEND = 4556\nDEFAULT_PORT_KMS_BACKEND = 4555\nDEFAULT_PORT_EVENTS_BACKEND = 4554\nDEFAULT_PORT_LOGS_BACKEND = 4553\n\nDEFAULT_PORT_WEB_UI = 8080\n\nLOCALHOST = 'localhost'\n\n# version of the Maven dependency with Java utility code\nLOCALSTACK_MAVEN_VERSION = '0.2.1'\n\n# map of default service APIs and ports to be spun up (fetch map from localstack_client)\nDEFAULT_SERVICE_PORTS = localstack_client.config.get_service_ports()\n\n# host to bind to when starting the services\nBIND_HOST = '0.0.0.0'\n\n# AWS user account ID used for tests\nif 'TEST_AWS_ACCOUNT_ID' not in os.environ:\n    os.environ['TEST_AWS_ACCOUNT_ID'] = '000000000000'\nTEST_AWS_ACCOUNT_ID = os.environ['TEST_AWS_ACCOUNT_ID']\n\n# root code folder\nLOCALSTACK_ROOT_FOLDER = os.path.realpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))\n\n# virtualenv folder\nLOCALSTACK_VENV_FOLDER = os.path.join(LOCALSTACK_ROOT_FOLDER, '.venv')\nif not os.path.isdir(LOCALSTACK_VENV_FOLDER):\n    # assuming this package lives here: <python>/lib/pythonX.X/site-packages/localstack/\n    LOCALSTACK_VENV_FOLDER = os.path.realpath(os.path.join(LOCALSTACK_ROOT_FOLDER, '..', '..', '..'))\n\n# API Gateway path to indicate a user request sent to the gateway\nPATH_USER_REQUEST = '_user_request_'\n\n# name of LocalStack Docker image\nDOCKER_IMAGE_NAME = 'localstack/localstack'\n\n# backdoor API path used to retrieve or update config variables\nCONFIG_UPDATE_PATH = '/?_config_'\n\n# environment variable name to tag local test runs\nENV_INTERNAL_TEST_RUN = 'LOCALSTACK_INTERNAL_TEST_RUN'\n\n# content types\nAPPLICATION_AMZ_JSON_1_0 = 'application/x-amz-json-1.0'\nAPPLICATION_AMZ_JSON_1_1 = 'application/x-amz-json-1.1'\nAPPLICATION_JSON = 'application/json'\nAPPLICATION_XML = 'application/xml'\nAPPLICATION_X_WWW_FORM_URLENCODED = 'application/x-www-form-urlencoded'\n\n# strings to indicate truthy/falsy values\nTRUE_STRINGS = ('1', 'true', 'True')\nFALSE_STRINGS = ('0', 'false', 'False')\n\n# Lambda defaults\nLAMBDA_TEST_ROLE = 'arn:aws:iam::%s:role/lambda-test-role' % TEST_AWS_ACCOUNT_ID\n\n# installation constants\nELASTICSEARCH_JAR_URL = 'https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.7.0.zip'\n# See https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/aes-supported-plugins.html\nELASTICSEARCH_PLUGIN_LIST = ['analysis-icu', 'ingest-attachment', 'analysis-kuromoji',\n 'mapper-murmur3', 'mapper-size', 'analysis-phonetic', 'analysis-smartcn', 'analysis-stempel', 'analysis-ukrainian']\n# Default ES modules to exclude (save apprx 66MB in the final image)\nELASTICSEARCH_DELETE_MODULES = ['ingest-geoip']\nELASTICMQ_JAR_URL = 'https://s3-eu-west-1.amazonaws.com/softwaremill-public/elasticmq-server-0.15.4.jar'\nSTS_JAR_URL = 'https://repo1.maven.org/maven2/com/amazonaws/aws-java-sdk-sts/1.11.14/aws-java-sdk-sts-1.11.14.jar'\nSTEPFUNCTIONS_ZIP_URL = 'https://s3.amazonaws.com/stepfunctionslocal/StepFunctionsLocal.zip'\nKMS_URL_PATTERN = 'https://s3-eu-west-2.amazonaws.com/local-kms/localstack/v3/local-kms.<arch>.bin'\n\n# TODO: Temporarily using a fixed version of DDB in Alpine, as we're hitting a SIGSEGV JVM crash with latest\nDYNAMODB_JAR_URL_ALPINE = 'https://github.com/whummer/dynamodb-local/raw/master/etc/DynamoDBLocal.zip'\nDYNAMODB_JAR_URL = 'https://s3-us-west-2.amazonaws.com/dynamodb-local/dynamodb_local_latest.zip'\n\n# API endpoint for analytics events\nAPI_ENDPOINT = os.environ.get('API_ENDPOINT') or 'https://api.localstack.cloud/v1'\n\n# environment variable to indicates that this process is running the Web UI\nLOCALSTACK_WEB_PROCESS = 'LOCALSTACK_WEB_PROCESS'\nLOCALSTACK_INFRA_PROCESS = 'LOCALSTACK_INFRA_PROCESS'\n\n# Hardcoded AWS account ID used by moto\nMOTO_ACCOUNT_ID = '123456789012'\n\n# Default lambda registry\nDEFAULT_LAMBDA_CONTAINER_REGISTRY = 'lambci/lambda'\n", "path": "localstack/constants.py"}]}