32
32
MOTO_VERSION = get_package_version_tuple ("moto" )
33
33
BOTOCORE_VERSION = get_package_version_tuple ("boto3" )
34
34
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"
36
43
TEST_STREAM = f"python-agent-test-{ uuid .uuid4 ()} "
37
44
EXPECTED_AGENT_ATTRS = {
38
45
"exact_agents" : {
39
46
"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 } " ,
41
48
},
42
49
}
43
50
44
- AWS_ACCESS_KEY_ID = "AAAAAAAAAAAACCESSKEY"
45
- AWS_SECRET_ACCESS_KEY = "AAAAAASECRETKEY" # nosec
46
- AWS_REGION = "us-east-1"
47
-
48
51
_kinesis_scoped_metrics = [
49
52
(f"MessageBroker/Kinesis/Stream/Produce/Named/{ TEST_STREAM } " , 2 ),
50
53
(f"MessageBroker/Kinesis/Stream/Consume/Named/{ TEST_STREAM } " , 1 ),
51
54
(f"Kinesis/create_stream/{ TEST_STREAM } " , 1 ),
52
- (f "Kinesis/list_streams" , 1 ),
55
+ ("Kinesis/list_streams" , 1 ),
53
56
(f"Kinesis/describe_stream/{ TEST_STREAM } " , 1 ),
57
+ (f"Kinesis/put_resource_policy/{ TEST_STREAM } " , 2 ),
54
58
(f"Kinesis/get_shard_iterator/{ TEST_STREAM } " , 1 ),
55
59
(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 ),
57
63
]
58
64
if BOTOCORE_VERSION < (1 , 29 , 0 ):
59
65
_kinesis_scoped_metrics = [
60
66
(f"MessageBroker/Kinesis/Stream/Produce/Named/{ TEST_STREAM } " , 2 ),
61
67
(f"Kinesis/create_stream/{ TEST_STREAM } " , 1 ),
62
- (f "Kinesis/list_streams" , 1 ),
68
+ ("Kinesis/list_streams" , 1 ),
63
69
(f"Kinesis/describe_stream/{ TEST_STREAM } " , 1 ),
64
70
(f"Kinesis/get_shard_iterator/{ TEST_STREAM } " , 1 ),
65
71
(f"Kinesis/delete_stream/{ TEST_STREAM } " , 1 ),
66
- (f"External/{ URL } /botocore/POST" , 5 ),
72
+ (f"External/{ KINESIS_URL } /botocore/POST" , 5 ),
67
73
]
68
74
69
75
_kinesis_rollup_metrics = [
70
76
(f"MessageBroker/Kinesis/Stream/Produce/Named/{ TEST_STREAM } " , 2 ),
71
77
(f"MessageBroker/Kinesis/Stream/Consume/Named/{ TEST_STREAM } " , 1 ),
72
78
(f"Kinesis/create_stream/{ TEST_STREAM } " , 1 ),
73
- (f "Kinesis/list_streams" , 1 ),
79
+ ("Kinesis/list_streams" , 1 ),
74
80
(f"Kinesis/describe_stream/{ TEST_STREAM } " , 1 ),
81
+ (f"Kinesis/put_resource_policy/{ TEST_STREAM } " , 2 ),
75
82
(f"Kinesis/get_shard_iterator/{ TEST_STREAM } " , 1 ),
76
83
(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 ),
81
92
]
82
93
if BOTOCORE_VERSION < (1 , 29 , 0 ):
83
94
_kinesis_rollup_metrics = [
84
95
(f"MessageBroker/Kinesis/Stream/Produce/Named/{ TEST_STREAM } " , 2 ),
85
96
(f"Kinesis/create_stream/{ TEST_STREAM } " , 1 ),
86
- (f "Kinesis/list_streams" , 1 ),
97
+ ("Kinesis/list_streams" , 1 ),
87
98
(f"Kinesis/describe_stream/{ TEST_STREAM } " , 1 ),
88
99
(f"Kinesis/get_shard_iterator/{ TEST_STREAM } " , 1 ),
89
100
(f"Kinesis/delete_stream/{ TEST_STREAM } " , 1 ),
90
101
("External/all" , 5 ),
91
102
("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 ),
94
105
]
95
106
96
107
_kinesis_scoped_metrics_error = [
@@ -114,7 +125,13 @@ def test_instrumented_kinesis_methods():
114
125
115
126
ignored_methods = set (
116
127
("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
+ )
118
135
)
119
136
client_methods = inspect .getmembers (client , predicate = inspect .ismethod )
120
137
methods = {("kinesis" , name ) for (name , method ) in client_methods if not name .startswith ("_" )}
@@ -128,7 +145,7 @@ def test_instrumented_kinesis_methods():
128
145
@validate_span_events (exact_agents = {"aws.operation" : "CreateStream" }, count = 1 )
129
146
@validate_span_events (
130
147
** 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 ,
132
149
)
133
150
@validate_span_events (exact_agents = {"aws.operation" : "DeleteStream" }, count = 1 )
134
151
@validate_transaction_metrics (
@@ -147,7 +164,11 @@ def test_kinesis():
147
164
region_name = AWS_REGION ,
148
165
)
149
166
# 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
+ )
151
172
assert resp ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
152
173
153
174
# List streams
@@ -160,28 +181,55 @@ def test_kinesis():
160
181
Limit = 123 ,
161
182
)
162
183
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
164
186
165
187
# 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 }
167
189
168
190
# Send message
169
191
resp = client .put_record (Data = b"foo1" , PartitionKey = "bar" , ** stream_kwargs )
170
192
assert resp ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
171
193
172
194
# Send messages
173
195
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 ,
175
201
)
176
202
assert resp ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
177
203
204
+ # Shards
178
205
shard_iter = client .get_shard_iterator (
179
206
ShardId = "shardId-000000000000" ,
180
207
ShardIteratorType = "AT_SEQUENCE_NUMBER" ,
181
208
StartingSequenceNumber = "0" ,
182
209
** stream_kwargs ,
183
210
)["ShardIterator" ]
184
211
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
+
185
233
# Receive message
186
234
if BOTOCORE_VERSION < (1 , 29 , 0 ):
187
235
resp = client .get_records (ShardIterator = shard_iter )
@@ -214,7 +262,11 @@ def test_kinesis_error():
214
262
region_name = AWS_REGION ,
215
263
)
216
264
# 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
+ )
218
270
assert resp ["ResponseMetadata" ]["HTTPStatusCode" ] == 200
219
271
220
272
# Stream ARN is needed for rest of methods.
0 commit comments