3232MOTO_VERSION = get_package_version_tuple ("moto" )
3333BOTOCORE_VERSION = get_package_version_tuple ("boto3" )
3434
35- URL = "kinesis.us-east-1.amazonaws.com"
35+ AWS_ACCESS_KEY_ID = "AAAAAAAAAAAACCESSKEY"
36+ AWS_SECRET_ACCESS_KEY = "AAAAAASECRETKEY" # nosec
37+ AWS_REGION = "us-east-1"
38+ AWS_ACCOUNT_ID = 123456789012
39+
40+ KINESIS_URL = "kinesis.us-east-1.amazonaws.com"
41+ KINESIS_CONTROL_URL = f"{ AWS_ACCOUNT_ID } .control-kinesis.{ AWS_REGION } .amazonaws.com"
42+ KINESIS_DATA_URL = f"{ AWS_ACCOUNT_ID } .data-kinesis.{ AWS_REGION } .amazonaws.com"
3643TEST_STREAM = f"python-agent-test-{ uuid .uuid4 ()} "
3744EXPECTED_AGENT_ATTRS = {
3845 "exact_agents" : {
3946 "cloud.platform" : "aws_kinesis_data_streams" ,
40- "cloud.resource_id" : f"arn:aws:kinesis:us-east-1:123456789012 :stream/{ TEST_STREAM } " ,
47+ "cloud.resource_id" : f"arn:aws:kinesis:us-east-1:{ AWS_ACCOUNT_ID } :stream/{ TEST_STREAM } " ,
4148 },
4249}
4350
44- AWS_ACCESS_KEY_ID = "AAAAAAAAAAAACCESSKEY"
45- AWS_SECRET_ACCESS_KEY = "AAAAAASECRETKEY" # nosec
46- AWS_REGION = "us-east-1"
47-
4851_kinesis_scoped_metrics = [
4952 (f"MessageBroker/Kinesis/Stream/Produce/Named/{ TEST_STREAM } " , 2 ),
5053 (f"MessageBroker/Kinesis/Stream/Consume/Named/{ TEST_STREAM } " , 1 ),
5154 (f"Kinesis/create_stream/{ TEST_STREAM } " , 1 ),
52- (f "Kinesis/list_streams" , 1 ),
55+ ("Kinesis/list_streams" , 1 ),
5356 (f"Kinesis/describe_stream/{ TEST_STREAM } " , 1 ),
57+ (f"Kinesis/put_resource_policy/{ TEST_STREAM } " , 2 ),
5458 (f"Kinesis/get_shard_iterator/{ TEST_STREAM } " , 1 ),
5559 (f"Kinesis/delete_stream/{ TEST_STREAM } " , 1 ),
56- (f"External/{ URL } /botocore/POST" , 3 ),
60+ (f"External/{ KINESIS_URL } /botocore/POST" , 3 ),
61+ (f"External/{ KINESIS_CONTROL_URL } /botocore/POST" , 3 ),
62+ (f"External/{ KINESIS_DATA_URL } /botocore/POST" , 1 ),
5763]
5864if BOTOCORE_VERSION < (1 , 29 , 0 ):
5965 _kinesis_scoped_metrics = [
6066 (f"MessageBroker/Kinesis/Stream/Produce/Named/{ TEST_STREAM } " , 2 ),
6167 (f"Kinesis/create_stream/{ TEST_STREAM } " , 1 ),
62- (f "Kinesis/list_streams" , 1 ),
68+ ("Kinesis/list_streams" , 1 ),
6369 (f"Kinesis/describe_stream/{ TEST_STREAM } " , 1 ),
6470 (f"Kinesis/get_shard_iterator/{ TEST_STREAM } " , 1 ),
6571 (f"Kinesis/delete_stream/{ TEST_STREAM } " , 1 ),
66- (f"External/{ URL } /botocore/POST" , 5 ),
72+ (f"External/{ KINESIS_URL } /botocore/POST" , 5 ),
6773 ]
6874
6975_kinesis_rollup_metrics = [
7076 (f"MessageBroker/Kinesis/Stream/Produce/Named/{ TEST_STREAM } " , 2 ),
7177 (f"MessageBroker/Kinesis/Stream/Consume/Named/{ TEST_STREAM } " , 1 ),
7278 (f"Kinesis/create_stream/{ TEST_STREAM } " , 1 ),
73- (f "Kinesis/list_streams" , 1 ),
79+ ("Kinesis/list_streams" , 1 ),
7480 (f"Kinesis/describe_stream/{ TEST_STREAM } " , 1 ),
81+ (f"Kinesis/put_resource_policy/{ TEST_STREAM } " , 2 ),
7582 (f"Kinesis/get_shard_iterator/{ TEST_STREAM } " , 1 ),
7683 (f"Kinesis/delete_stream/{ TEST_STREAM } " , 1 ),
77- ("External/all" , 5 ),
78- ("External/allOther" , 5 ),
79- (f"External/{ URL } /all" , 3 ),
80- (f"External/{ URL } /botocore/POST" , 3 ),
84+ ("External/all" , 7 ),
85+ ("External/allOther" , 7 ),
86+ (f"External/{ KINESIS_URL } /all" , 3 ),
87+ (f"External/{ KINESIS_URL } /botocore/POST" , 3 ),
88+ (f"External/{ KINESIS_CONTROL_URL } /all" , 3 ),
89+ (f"External/{ KINESIS_CONTROL_URL } /botocore/POST" , 3 ),
90+ (f"External/{ KINESIS_DATA_URL } /all" , 1 ),
91+ (f"External/{ KINESIS_DATA_URL } /botocore/POST" , 1 ),
8192]
8293if BOTOCORE_VERSION < (1 , 29 , 0 ):
8394 _kinesis_rollup_metrics = [
8495 (f"MessageBroker/Kinesis/Stream/Produce/Named/{ TEST_STREAM } " , 2 ),
8596 (f"Kinesis/create_stream/{ TEST_STREAM } " , 1 ),
86- (f "Kinesis/list_streams" , 1 ),
97+ ("Kinesis/list_streams" , 1 ),
8798 (f"Kinesis/describe_stream/{ TEST_STREAM } " , 1 ),
8899 (f"Kinesis/get_shard_iterator/{ TEST_STREAM } " , 1 ),
89100 (f"Kinesis/delete_stream/{ TEST_STREAM } " , 1 ),
90101 ("External/all" , 5 ),
91102 ("External/allOther" , 5 ),
92- (f"External/{ URL } /all" , 5 ),
93- (f"External/{ URL } /botocore/POST" , 5 ),
103+ (f"External/{ KINESIS_URL } /all" , 5 ),
104+ (f"External/{ KINESIS_URL } /botocore/POST" , 5 ),
94105 ]
95106
96107_kinesis_scoped_metrics_error = [
@@ -114,7 +125,13 @@ def test_instrumented_kinesis_methods():
114125
115126 ignored_methods = set (
116127 ("kinesis" , method )
117- for method in ("generate_presigned_url" , "close" , "get_waiter" , "can_paginate" , "get_paginator" )
128+ for method in (
129+ "generate_presigned_url" ,
130+ "close" ,
131+ "get_waiter" ,
132+ "can_paginate" ,
133+ "get_paginator" ,
134+ )
118135 )
119136 client_methods = inspect .getmembers (client , predicate = inspect .ismethod )
120137 methods = {("kinesis" , name ) for (name , method ) in client_methods if not name .startswith ("_" )}
@@ -128,7 +145,7 @@ def test_instrumented_kinesis_methods():
128145@validate_span_events (exact_agents = {"aws.operation" : "CreateStream" }, count = 1 )
129146@validate_span_events (
130147 ** EXPECTED_AGENT_ATTRS ,
131- count = 6 if BOTOCORE_VERSION < (1 , 29 , 0 ) else 7 ,
148+ count = 6 if BOTOCORE_VERSION < (1 , 29 , 0 ) else 9 ,
132149)
133150@validate_span_events (exact_agents = {"aws.operation" : "DeleteStream" }, count = 1 )
134151@validate_transaction_metrics (
@@ -147,7 +164,11 @@ def test_kinesis():
147164 region_name = AWS_REGION ,
148165 )
149166 # Create stream
150- resp = client .create_stream (StreamName = TEST_STREAM , ShardCount = 123 , StreamModeDetails = {"StreamMode" : "on-demand" })
167+ resp = client .create_stream (
168+ StreamName = TEST_STREAM ,
169+ ShardCount = 123 ,
170+ StreamModeDetails = {"StreamMode" : "on-demand" },
171+ )
151172 assert resp ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
152173
153174 # List streams
@@ -160,28 +181,55 @@ def test_kinesis():
160181 Limit = 123 ,
161182 )
162183 assert resp ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
163- ARN = resp ["StreamDescription" ]["StreamARN" ]
184+ STREAM_ARN = resp ["StreamDescription" ]["StreamARN" ]
185+ CONSUMER_ARN = f"{ STREAM_ARN } /consumer/my_consumer:123" # Mock ConsumerARN
164186
165187 # StreamARN is not supported in older versions of botocore.
166- stream_kwargs = {"StreamName" : TEST_STREAM } if BOTOCORE_VERSION < (1 , 29 , 0 ) else {"StreamARN" : ARN }
188+ stream_kwargs = {"StreamName" : TEST_STREAM } if BOTOCORE_VERSION < (1 , 29 , 0 ) else {"StreamARN" : STREAM_ARN }
167189
168190 # Send message
169191 resp = client .put_record (Data = b"foo1" , PartitionKey = "bar" , ** stream_kwargs )
170192 assert resp ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
171193
172194 # Send messages
173195 resp = client .put_records (
174- Records = [{"Data" : b"foo2" , "PartitionKey" : "bar" }, {"Data" : b"foo3" , "PartitionKey" : "bar" }], ** stream_kwargs
196+ Records = [
197+ {"Data" : b"foo2" , "PartitionKey" : "bar" },
198+ {"Data" : b"foo3" , "PartitionKey" : "bar" },
199+ ],
200+ ** stream_kwargs ,
175201 )
176202 assert resp ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
177203
204+ # Shards
178205 shard_iter = client .get_shard_iterator (
179206 ShardId = "shardId-000000000000" ,
180207 ShardIteratorType = "AT_SEQUENCE_NUMBER" ,
181208 StartingSequenceNumber = "0" ,
182209 ** stream_kwargs ,
183210 )["ShardIterator" ]
184211
212+ # TODO: Unfortunately we can't test client.subscribe_to_shard() yet as moto has not implemented it.
213+ # It's the only method that uses ConsumerARN as a parameter name, so extracting that parameter can't be tested.
214+ # ResourceARN, however, can be tested and can be either a StreamARN or ConsumerARN format. We can therefore
215+ # at least cover the parsing of ConsumerARNs for the underlying stream by exercising that.
216+
217+ if BOTOCORE_VERSION >= (1 , 29 , 0 ):
218+ # This was only made available in Botocore 1.29.0, no way to test ResourceARN before that
219+ # Use ResourceARN as StreamARN
220+ resp = client .put_resource_policy (
221+ ResourceARN = STREAM_ARN ,
222+ Policy = "some policy" ,
223+ )
224+ assert resp ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
225+
226+ # Use ResourceARN as ConsumerARN
227+ resp = client .put_resource_policy (
228+ ResourceARN = CONSUMER_ARN ,
229+ Policy = "some policy" ,
230+ )
231+ assert resp ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
232+
185233 # Receive message
186234 if BOTOCORE_VERSION < (1 , 29 , 0 ):
187235 resp = client .get_records (ShardIterator = shard_iter )
@@ -214,7 +262,11 @@ def test_kinesis_error():
214262 region_name = AWS_REGION ,
215263 )
216264 # Create stream
217- resp = client .create_stream (StreamName = TEST_STREAM , ShardCount = 123 , StreamModeDetails = {"StreamMode" : "on-demand" })
265+ resp = client .create_stream (
266+ StreamName = TEST_STREAM ,
267+ ShardCount = 123 ,
268+ StreamModeDetails = {"StreamMode" : "on-demand" },
269+ )
218270 assert resp ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
219271
220272 # Stream ARN is needed for rest of methods.
0 commit comments