localstack-core 4.9.3.dev39__py3-none-any.whl → 4.9.3.dev41__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -59,14 +59,21 @@ class EventRuleEngine:
59
59
  for flat_pattern in flat_pattern_conditions
60
60
  )
61
61
 
62
- def _evaluate_condition(self, value, condition, field_exists: bool):
62
+ def _evaluate_condition(self, value: t.Any, condition: t.Any, field_exists: bool) -> bool:
63
63
  if not isinstance(condition, dict):
64
64
  return field_exists and value == condition
65
+
65
66
  elif (must_exist := condition.get("exists")) is not None:
66
67
  # if must_exists is True then field_exists must be True
67
68
  # if must_exists is False then fields_exists must be False
68
69
  return must_exist == field_exists
70
+
69
71
  elif (anything_but := condition.get("anything-but")) is not None:
72
+ if not field_exists:
73
+ # anything-but can handle None `value`, but it needs to differentiate between user-set `null` and
74
+ # missing value
75
+ return False
76
+
70
77
  if isinstance(anything_but, dict):
71
78
  if (not_condition := anything_but.get("prefix")) is not None:
72
79
  predicate = self._evaluate_prefix
@@ -95,6 +102,7 @@ class EventRuleEngine:
95
102
  elif value is None:
96
103
  # the remaining conditions require the value to not be None
97
104
  return False
105
+
98
106
  elif (prefix := condition.get("prefix")) is not None:
99
107
  if isinstance(prefix, dict):
100
108
  if (prefix_equal_ignore_case := prefix.get("equals-ignore-case")) is not None:
@@ -104,7 +112,7 @@ class EventRuleEngine:
104
112
 
105
113
  elif (suffix := condition.get("suffix")) is not None:
106
114
  if isinstance(suffix, dict):
107
- if suffix_equal_ignore_case := suffix.get("equals-ignore-case"):
115
+ if (suffix_equal_ignore_case := suffix.get("equals-ignore-case")) is not None:
108
116
  return self._evaluate_suffix(suffix_equal_ignore_case.lower(), value.lower())
109
117
  else:
110
118
  return self._evaluate_suffix(suffix, value)
@@ -126,19 +134,19 @@ class EventRuleEngine:
126
134
  return False
127
135
 
128
136
  @staticmethod
129
- def _evaluate_prefix(condition: str | list, value: str) -> bool:
130
- return value.startswith(condition)
137
+ def _evaluate_prefix(condition: str | list, value: t.Any) -> bool:
138
+ return isinstance(value, str) and value.startswith(condition)
131
139
 
132
140
  @staticmethod
133
- def _evaluate_suffix(condition: str | list, value: str) -> bool:
134
- return value.endswith(condition)
141
+ def _evaluate_suffix(condition: str | list, value: t.Any) -> bool:
142
+ return isinstance(value, str) and value.endswith(condition)
135
143
 
136
144
  @staticmethod
137
- def _evaluate_equal_ignore_case(condition: str, value: str) -> bool:
138
- return condition.lower() == value.lower()
145
+ def _evaluate_equal_ignore_case(condition: str, value: t.Any) -> bool:
146
+ return isinstance(value, str) and condition.lower() == value.lower()
139
147
 
140
148
  @staticmethod
141
- def _evaluate_cidr(condition: str, value: str) -> bool:
149
+ def _evaluate_cidr(condition: str, value: t.Any) -> bool:
142
150
  try:
143
151
  ip = ipaddress.ip_address(value)
144
152
  return ip in ipaddress.ip_network(condition)
@@ -146,8 +154,10 @@ class EventRuleEngine:
146
154
  return False
147
155
 
148
156
  @staticmethod
149
- def _evaluate_wildcard(condition: str, value: str) -> bool:
150
- return bool(re.match(re.escape(condition).replace("\\*", ".+") + "$", value))
157
+ def _evaluate_wildcard(condition: str, value: t.Any) -> bool:
158
+ return isinstance(value, str) and bool(
159
+ re.match(re.escape(condition).replace("\\*", ".+") + "$", value)
160
+ )
151
161
 
152
162
  @staticmethod
153
163
  def _evaluate_numeric_condition(conditions: list, value: t.Any) -> bool:
@@ -457,10 +467,18 @@ class EventPatternCompiler:
457
467
  return
458
468
 
459
469
  elif operator == "anything-but":
460
- # anything-but can actually contain any kind of simple rule (str, number, and list)
470
+ # anything-but can actually contain any kind of simple rule (str, number, and list) except Null
471
+ if value is None:
472
+ raise InvalidEventPatternException(
473
+ f"{self.error_prefix}Value of anything-but must be an array or single string/number value."
474
+ )
461
475
  if isinstance(value, list):
462
476
  for v in value:
463
- self._validate_rule(v)
477
+ if v is None:
478
+ raise InvalidEventPatternException(
479
+ f"{self.error_prefix}Inside anything but list, start|null|boolean is not supported."
480
+ )
481
+ self._validate_rule(v, from_="anything-but")
464
482
 
465
483
  return
466
484
 
@@ -13,7 +13,7 @@ SNS_PROTOCOLS = [
13
13
  "firehose",
14
14
  ]
15
15
 
16
- VALID_SUBSCRIPTION_ATTR_NAME = [
16
+ VALID_SUBSCRIPTION_ATTR_NAME: list[str] = [
17
17
  "DeliveryPolicy",
18
18
  "FilterPolicy",
19
19
  "FilterPolicyScope",
@@ -39,3 +39,4 @@ SUBSCRIPTION_TOKENS_ENDPOINT = "/_aws/sns/subscription-tokens"
39
39
  SNS_CERT_ENDPOINT = "/_aws/sns/SimpleNotificationService-6c6f63616c737461636b69736e696365.pem"
40
40
 
41
41
  DUMMY_SUBSCRIPTION_PRINCIPAL = "arn:{partition}:iam::{account_id}:user/DummySNSPrincipal"
42
+ E164_REGEX = re.compile(r"^\+?[1-9]\d{1,14}$")
@@ -1,12 +1,24 @@
1
- from typing import TypedDict
1
+ import itertools
2
+ import time
3
+ from dataclasses import dataclass, field
4
+ from enum import StrEnum
5
+ from typing import Literal, TypedDict
2
6
 
3
- from localstack.aws.api.sns import TopicAttributesMap
7
+ from localstack.aws.api.sns import (
8
+ MessageAttributeMap,
9
+ PublishBatchRequestEntry,
10
+ TopicAttributesMap,
11
+ subscriptionARN,
12
+ topicARN,
13
+ )
4
14
  from localstack.services.stores import (
5
15
  AccountRegionBundle,
6
16
  BaseStore,
7
17
  CrossRegionAttribute,
8
18
  LocalAttribute,
9
19
  )
20
+ from localstack.utils.objects import singleton_factory
21
+ from localstack.utils.strings import long_uid
10
22
  from localstack.utils.tagging import TaggingService
11
23
 
12
24
 
@@ -14,11 +26,123 @@ class Topic(TypedDict, total=True):
14
26
  arn: str
15
27
  name: str
16
28
  attributes: TopicAttributesMap
29
+ subscriptions: list[str]
30
+
31
+
32
+ SnsProtocols = Literal[
33
+ "http", "https", "email", "email-json", "sms", "sqs", "application", "lambda", "firehose"
34
+ ]
35
+
36
+ SnsApplicationPlatforms = Literal[
37
+ "APNS", "APNS_SANDBOX", "ADM", "FCM", "Baidu", "GCM", "MPNS", "WNS"
38
+ ]
39
+ SnsMessageProtocols = Literal[SnsProtocols, SnsApplicationPlatforms]
40
+
41
+
42
+ class SnsSubscription(TypedDict, total=False):
43
+ """
44
+ In SNS, Subscription can be represented with only TopicArn, Endpoint, Protocol, SubscriptionArn and Owner, for
45
+ example in ListSubscriptions. However, when getting a subscription with GetSubscriptionAttributes, it will return
46
+ the Subscription object merged with its own attributes.
47
+ This represents this merged object, for internal use and in GetSubscriptionAttributes
48
+ https://docs.aws.amazon.com/cli/latest/reference/sns/get-subscription-attributes.html
49
+ """
50
+
51
+ TopicArn: topicARN
52
+ Endpoint: str
53
+ Protocol: SnsProtocols
54
+ SubscriptionArn: subscriptionARN
55
+ PendingConfirmation: Literal["true", "false"]
56
+ Owner: str | None
57
+ SubscriptionPrincipal: str | None
58
+ FilterPolicy: str | None
59
+ FilterPolicyScope: Literal["MessageAttributes", "MessageBody"]
60
+ RawMessageDelivery: Literal["true", "false"]
61
+ ConfirmationWasAuthenticated: Literal["true", "false"]
62
+ SubscriptionRoleArn: str | None
63
+ DeliveryPolicy: str | None
64
+
65
+
66
+ @singleton_factory
67
+ def global_sns_message_sequence():
68
+ # creates a 20-digit number used as the start for the global sequence, adds 100 for it to be different from SQS's
69
+ # mostly for testing purpose, both global sequence would be initialized at the same and be identical
70
+ start = int(time.time() + 100) << 33
71
+ # itertools.count is thread safe over the GIL since its getAndIncrement operation is a single python bytecode op
72
+ return itertools.count(start)
73
+
74
+
75
+ def get_next_sequence_number():
76
+ return next(global_sns_message_sequence())
77
+
78
+
79
+ class SnsMessageType(StrEnum):
80
+ Notification = "Notification"
81
+ SubscriptionConfirmation = "SubscriptionConfirmation"
82
+ UnsubscribeConfirmation = "UnsubscribeConfirmation"
83
+
84
+
85
+ @dataclass
86
+ class SnsMessage:
87
+ type: SnsMessageType
88
+ message: (
89
+ str | dict
90
+ ) # can be Dict if after being JSON decoded for validation if structure is `json`
91
+ message_attributes: MessageAttributeMap | None = None
92
+ message_structure: str | None = None
93
+ subject: str | None = None
94
+ message_deduplication_id: str | None = None
95
+ message_group_id: str | None = None
96
+ token: str | None = None
97
+ message_id: str = field(default_factory=long_uid)
98
+ is_fifo: bool | None = False
99
+ sequencer_number: str | None = None
100
+
101
+ def __post_init__(self):
102
+ if self.message_attributes is None:
103
+ self.message_attributes = {}
104
+ if self.is_fifo:
105
+ self.sequencer_number = str(get_next_sequence_number())
106
+
107
+ def message_content(self, protocol: SnsMessageProtocols) -> str:
108
+ """
109
+ Helper function to retrieve the message content for the right protocol if the StructureMessage is `json`
110
+ See https://docs.aws.amazon.com/sns/latest/dg/sns-send-custom-platform-specific-payloads-mobile-devices.html
111
+ https://docs.aws.amazon.com/sns/latest/dg/example_sns_Publish_section.html
112
+ :param protocol:
113
+ :return: message content as string
114
+ """
115
+ if self.message_structure == "json":
116
+ return self.message.get(protocol, self.message.get("default"))
117
+
118
+ return self.message
119
+
120
+ @classmethod
121
+ def from_batch_entry(cls, entry: PublishBatchRequestEntry, is_fifo=False) -> "SnsMessage":
122
+ return cls(
123
+ type=SnsMessageType.Notification,
124
+ message=entry["Message"],
125
+ subject=entry.get("Subject"),
126
+ message_structure=entry.get("MessageStructure"),
127
+ message_attributes=entry.get("MessageAttributes"),
128
+ message_deduplication_id=entry.get("MessageDeduplicationId"),
129
+ message_group_id=entry.get("MessageGroupId"),
130
+ is_fifo=is_fifo,
131
+ )
17
132
 
18
133
 
19
134
  class SnsStore(BaseStore):
20
135
  topics: dict[str, Topic] = LocalAttribute(default=dict)
21
136
 
137
+ # maps subscription ARN to SnsSubscription
138
+ subscriptions: dict[str, SnsSubscription] = LocalAttribute(default=dict)
139
+
140
+ # filter policy are stored as JSON string in subscriptions, store the decoded result Dict
141
+ subscription_filter_policy: dict[subscriptionARN, dict] = LocalAttribute(default=dict)
142
+
143
+ # maps confirmation token to subscription ARN
144
+ subscription_tokens: dict[str, str] = LocalAttribute(default=dict)
145
+
22
146
  TAGS: TaggingService = CrossRegionAttribute(default=TaggingService)
23
147
 
24
148
 
@@ -1,3 +1,5 @@
1
+ import contextlib
2
+ import copy
1
3
  import json
2
4
  import logging
3
5
  import re
@@ -6,23 +8,56 @@ from botocore.utils import InvalidArnException
6
8
 
7
9
  from localstack.aws.api import RequestContext
8
10
  from localstack.aws.api.sns import (
11
+ ConfirmSubscriptionResponse,
9
12
  CreateTopicResponse,
13
+ GetSubscriptionAttributesResponse,
10
14
  GetTopicAttributesResponse,
11
15
  InvalidParameterException,
16
+ ListSubscriptionsByTopicResponse,
17
+ ListSubscriptionsResponse,
12
18
  ListTopicsResponse,
13
19
  NotFoundException,
14
20
  SnsApi,
21
+ String,
22
+ SubscribeResponse,
23
+ Subscription,
24
+ SubscriptionAttributesMap,
15
25
  TagList,
16
26
  TopicAttributesMap,
17
27
  attributeName,
18
28
  attributeValue,
29
+ authenticateOnUnsubscribe,
30
+ endpoint,
19
31
  nextToken,
32
+ protocol,
33
+ subscriptionARN,
20
34
  topicARN,
21
35
  topicName,
22
36
  )
23
- from localstack.services.sns.v2.models import SnsStore, Topic, sns_stores
24
- from localstack.utils.aws.arns import ArnData, parse_arn, sns_topic_arn
25
- from localstack.utils.collections import PaginatedList
37
+ from localstack.services.sns import constants as sns_constants
38
+ from localstack.services.sns.certificate import SNS_SERVER_CERT
39
+ from localstack.services.sns.constants import DUMMY_SUBSCRIPTION_PRINCIPAL
40
+ from localstack.services.sns.filter import FilterPolicyValidator
41
+ from localstack.services.sns.publisher import PublishDispatcher, SnsPublishContext
42
+ from localstack.services.sns.v2.models import (
43
+ SnsMessage,
44
+ SnsMessageType,
45
+ SnsStore,
46
+ SnsSubscription,
47
+ Topic,
48
+ sns_stores,
49
+ )
50
+ from localstack.services.sns.v2.utils import (
51
+ create_subscription_arn,
52
+ encode_subscription_token_with_region,
53
+ get_next_page_token_from_arn,
54
+ get_region_from_subscription_token,
55
+ is_valid_e164_number,
56
+ parse_and_validate_topic_arn,
57
+ validate_subscription_attribute,
58
+ )
59
+ from localstack.utils.aws.arns import get_partition, parse_arn, sns_topic_arn
60
+ from localstack.utils.collections import PaginatedList, select_from_typed_dict
26
61
 
27
62
  # set up logger
28
63
  LOG = logging.getLogger(__name__)
@@ -32,6 +67,13 @@ SNS_TOPIC_NAME_PATTERN = r"^[a-zA-Z0-9_-]{1,256}$"
32
67
 
33
68
 
34
69
  class SnsProvider(SnsApi):
70
+ def __init__(self) -> None:
71
+ super().__init__()
72
+ self._publisher = PublishDispatcher()
73
+ self._signature_cert_pem: str = SNS_SERVER_CERT
74
+
75
+ ## Topic Operations
76
+
35
77
  def create_topic(
36
78
  self,
37
79
  context: RequestContext,
@@ -65,15 +107,17 @@ class SnsProvider(SnsApi):
65
107
  )
66
108
  else:
67
109
  # AWS does not seem to save explicit settings of fifo = false
110
+
68
111
  attributes.pop("FifoTopic", None)
69
112
  name_match = re.match(SNS_TOPIC_NAME_PATTERN, name)
70
113
  if not name_match:
71
114
  raise InvalidParameterException("Invalid parameter: Topic Name")
72
115
 
73
116
  topic = _create_topic(name=name, attributes=attributes, context=context)
74
- store.topics[topic_arn] = topic
75
117
  # todo: tags
76
118
 
119
+ store.topics[topic_arn] = topic
120
+
77
121
  return CreateTopicResponse(TopicArn=topic_arn)
78
122
 
79
123
  def get_topic_attributes(
@@ -98,7 +142,9 @@ class SnsProvider(SnsApi):
98
142
  topics = [{"TopicArn": t["arn"]} for t in list(store.topics.values())]
99
143
  topics = PaginatedList(topics)
100
144
  page, nxt = topics.get_page(
101
- lambda topic: topic["TopicArn"], next_token=next_token, page_size=100
145
+ token_generator=lambda x: get_next_page_token_from_arn(x["TopicArn"]),
146
+ next_token=next_token,
147
+ page_size=100,
102
148
  )
103
149
  topics = {"Topics": page, "NextToken": nxt}
104
150
  return ListTopicsResponse(**topics)
@@ -116,6 +162,361 @@ class SnsProvider(SnsApi):
116
162
  raise InvalidParameterException("Invalid parameter: AttributeName")
117
163
  topic["attributes"][attribute_name] = attribute_value
118
164
 
165
+ ## Subscribe operations
166
+
167
+ def subscribe(
168
+ self,
169
+ context: RequestContext,
170
+ topic_arn: topicARN,
171
+ protocol: protocol,
172
+ endpoint: endpoint | None = None,
173
+ attributes: SubscriptionAttributesMap | None = None,
174
+ return_subscription_arn: bool | None = None,
175
+ **kwargs,
176
+ ) -> SubscribeResponse:
177
+ parsed_topic_arn = parse_and_validate_topic_arn(topic_arn)
178
+ if context.region != parsed_topic_arn["region"]:
179
+ raise InvalidParameterException("Invalid parameter: TopicArn")
180
+
181
+ store = self.get_store(account_id=parsed_topic_arn["account"], region=context.region)
182
+
183
+ if topic_arn not in store.topics:
184
+ raise NotFoundException("Topic does not exist")
185
+
186
+ topic_subscriptions = store.topics[topic_arn]["subscriptions"]
187
+ if not endpoint:
188
+ # TODO: check AWS behaviour (because endpoint is optional)
189
+ raise NotFoundException("Endpoint not specified in subscription")
190
+ if protocol not in sns_constants.SNS_PROTOCOLS:
191
+ raise InvalidParameterException(
192
+ f"Invalid parameter: Amazon SNS does not support this protocol string: {protocol}"
193
+ )
194
+ elif protocol in ["http", "https"] and not endpoint.startswith(f"{protocol}://"):
195
+ raise InvalidParameterException(
196
+ "Invalid parameter: Endpoint must match the specified protocol"
197
+ )
198
+ elif protocol == "sms" and not is_valid_e164_number(endpoint):
199
+ raise InvalidParameterException(f"Invalid SMS endpoint: {endpoint}")
200
+
201
+ elif protocol == "sqs":
202
+ try:
203
+ parse_arn(endpoint)
204
+ except InvalidArnException:
205
+ raise InvalidParameterException("Invalid parameter: SQS endpoint ARN")
206
+
207
+ elif protocol == "application":
208
+ # TODO: This needs to be implemented once applications are ported from moto to the new provider
209
+ raise NotImplementedError(
210
+ "This functionality needs yet to be ported to the new SNS provider"
211
+ )
212
+
213
+ if ".fifo" in endpoint and ".fifo" not in topic_arn:
214
+ # TODO: move to sqs protocol block if possible
215
+ raise InvalidParameterException(
216
+ "Invalid parameter: Invalid parameter: Endpoint Reason: FIFO SQS Queues can not be subscribed to standard SNS topics"
217
+ )
218
+
219
+ sub_attributes = copy.deepcopy(attributes) if attributes else None
220
+ if sub_attributes:
221
+ for attr_name, attr_value in sub_attributes.items():
222
+ validate_subscription_attribute(
223
+ attribute_name=attr_name,
224
+ attribute_value=attr_value,
225
+ topic_arn=topic_arn,
226
+ endpoint=endpoint,
227
+ is_subscribe_call=True,
228
+ )
229
+ if raw_msg_delivery := sub_attributes.get("RawMessageDelivery"):
230
+ sub_attributes["RawMessageDelivery"] = raw_msg_delivery.lower()
231
+
232
+ # An endpoint may only be subscribed to a topic once. Subsequent
233
+ # subscribe calls do nothing (subscribe is idempotent), except if its attributes are different.
234
+ for existing_topic_subscription in topic_subscriptions:
235
+ sub = store.subscriptions.get(existing_topic_subscription, {})
236
+ if sub.get("Endpoint") == endpoint:
237
+ if sub_attributes:
238
+ # validate the subscription attributes aren't different
239
+ for attr in sns_constants.VALID_SUBSCRIPTION_ATTR_NAME:
240
+ # if a new attribute is present and different from an existent one, raise
241
+ if (new_attr := sub_attributes.get(attr)) and sub.get(attr) != new_attr:
242
+ raise InvalidParameterException(
243
+ "Invalid parameter: Attributes Reason: Subscription already exists with different attributes"
244
+ )
245
+
246
+ return SubscribeResponse(SubscriptionArn=sub["SubscriptionArn"])
247
+ principal = DUMMY_SUBSCRIPTION_PRINCIPAL.format(
248
+ partition=get_partition(context.region), account_id=context.account_id
249
+ )
250
+ subscription_arn = create_subscription_arn(topic_arn)
251
+ subscription = SnsSubscription(
252
+ # http://docs.aws.amazon.com/cli/latest/reference/sns/get-subscription-attributes.html
253
+ TopicArn=topic_arn,
254
+ Endpoint=endpoint,
255
+ Protocol=protocol,
256
+ SubscriptionArn=subscription_arn,
257
+ PendingConfirmation="true",
258
+ Owner=context.account_id,
259
+ RawMessageDelivery="false", # default value, will be overridden if set
260
+ FilterPolicyScope="MessageAttributes", # default value, will be overridden if set
261
+ SubscriptionPrincipal=principal, # dummy value, could be fetched with a call to STS?
262
+ )
263
+ if sub_attributes:
264
+ subscription.update(sub_attributes)
265
+ if "FilterPolicy" in sub_attributes:
266
+ filter_policy = (
267
+ json.loads(sub_attributes["FilterPolicy"])
268
+ if sub_attributes["FilterPolicy"]
269
+ else None
270
+ )
271
+ if filter_policy:
272
+ validator = FilterPolicyValidator(
273
+ scope=subscription.get("FilterPolicyScope", "MessageAttributes"),
274
+ is_subscribe_call=True,
275
+ )
276
+ validator.validate_filter_policy(filter_policy)
277
+
278
+ store.subscription_filter_policy[subscription_arn] = filter_policy
279
+
280
+ store.subscriptions[subscription_arn] = subscription
281
+
282
+ topic_subscriptions.append(subscription_arn)
283
+
284
+ # store the token and subscription arn
285
+ # TODO: the token is a 288 hex char string
286
+ subscription_token = encode_subscription_token_with_region(region=context.region)
287
+ store.subscription_tokens[subscription_token] = subscription_arn
288
+
289
+ response_subscription_arn = subscription_arn
290
+ # Send out confirmation message for HTTP(S), fix for https://github.com/localstack/localstack/issues/881
291
+ if protocol in ["http", "https"]:
292
+ message_ctx = SnsMessage(
293
+ type=SnsMessageType.SubscriptionConfirmation,
294
+ token=subscription_token,
295
+ message=f"You have chosen to subscribe to the topic {topic_arn}.\nTo confirm the subscription, visit the SubscribeURL included in this message.",
296
+ )
297
+ publish_ctx = SnsPublishContext(
298
+ message=message_ctx,
299
+ store=store,
300
+ request_headers=context.request.headers,
301
+ # TODO: add topic attributes once they are ported from moto to LocalStack
302
+ # topic_attributes=vars(self._get_topic(topic_arn, context)),
303
+ )
304
+ self._publisher.publish_to_topic_subscriber(
305
+ ctx=publish_ctx,
306
+ topic_arn=topic_arn,
307
+ subscription_arn=subscription_arn,
308
+ )
309
+ if not return_subscription_arn:
310
+ response_subscription_arn = "pending confirmation"
311
+
312
+ elif protocol not in ["email", "email-json"]:
313
+ # Only HTTP(S) and email subscriptions are not auto validated
314
+ # Except if the endpoint and the topic are not in the same AWS account, then you'd need to manually confirm
315
+ # the subscription with the token
316
+ # TODO: revisit for multi-account
317
+ # TODO: test with AWS for email & email-json confirmation message
318
+ # we need to add the following check:
319
+ # if parsed_topic_arn["account"] == endpoint account (depending on the type, SQS, lambda, parse the arn)
320
+ subscription["PendingConfirmation"] = "false"
321
+ subscription["ConfirmationWasAuthenticated"] = "true"
322
+
323
+ return SubscribeResponse(SubscriptionArn=response_subscription_arn)
324
+
325
+ def unsubscribe(
326
+ self, context: RequestContext, subscription_arn: subscriptionARN, **kwargs
327
+ ) -> None:
328
+ if subscription_arn is None:
329
+ raise InvalidParameterException(
330
+ "Invalid parameter: SubscriptionArn Reason: no value for required parameter",
331
+ )
332
+ count = len(subscription_arn.split(":"))
333
+ try:
334
+ parsed_arn = parse_arn(subscription_arn)
335
+ except InvalidArnException:
336
+ # TODO: check for invalid SubscriptionGUID
337
+ raise InvalidParameterException(
338
+ f"Invalid parameter: SubscriptionArn Reason: An ARN must have at least 6 elements, not {count}"
339
+ )
340
+
341
+ account_id = parsed_arn["account"]
342
+ region_name = parsed_arn["region"]
343
+
344
+ store = self.get_store(account_id=account_id, region=region_name)
345
+ if count == 6 and subscription_arn not in store.subscriptions:
346
+ raise InvalidParameterException("Invalid parameter: SubscriptionId")
347
+
348
+ # TODO: here was a moto_backend.unsubscribe call, check correct functionality and remove this comment
349
+ # before switching to v2 for production
350
+
351
+ # pop the subscription at the end, to avoid race condition by iterating over the topic subscriptions
352
+ subscription = store.subscriptions.get(subscription_arn)
353
+
354
+ if not subscription:
355
+ # unsubscribe is idempotent, so unsubscribing from a non-existing topic does nothing
356
+ return
357
+
358
+ if subscription["Protocol"] in ["http", "https"]:
359
+ # TODO: actually validate this (re)subscribe behaviour somehow (localhost.run?)
360
+ # we might need to save the sub token in the store
361
+ # TODO: AWS only sends the UnsubscribeConfirmation if the call is unauthenticated or the requester is not
362
+ # the owner
363
+ subscription_token = encode_subscription_token_with_region(region=context.region)
364
+ message_ctx = SnsMessage(
365
+ type=SnsMessageType.UnsubscribeConfirmation,
366
+ token=subscription_token,
367
+ message=f"You have chosen to deactivate subscription {subscription_arn}.\nTo cancel this operation and restore the subscription, visit the SubscribeURL included in this message.",
368
+ )
369
+ publish_ctx = SnsPublishContext(
370
+ message=message_ctx,
371
+ store=store,
372
+ request_headers=context.request.headers,
373
+ # TODO: add the topic attributes once we ported them from moto to LocalStack
374
+ # topic_attributes=vars(moto_topic),
375
+ )
376
+ self._publisher.publish_to_topic_subscriber(
377
+ publish_ctx,
378
+ topic_arn=subscription["TopicArn"],
379
+ subscription_arn=subscription_arn,
380
+ )
381
+
382
+ with contextlib.suppress(KeyError):
383
+ store.topics[subscription["TopicArn"]]["subscriptions"].remove(subscription_arn)
384
+ store.subscription_filter_policy.pop(subscription_arn, None)
385
+ store.subscriptions.pop(subscription_arn, None)
386
+
387
+ def get_subscription_attributes(
388
+ self, context: RequestContext, subscription_arn: subscriptionARN, **kwargs
389
+ ) -> GetSubscriptionAttributesResponse:
390
+ store = self.get_store(account_id=context.account_id, region=context.region)
391
+ sub = store.subscriptions.get(subscription_arn)
392
+ if not sub:
393
+ raise NotFoundException("Subscription does not exist")
394
+ removed_attrs = ["sqs_queue_url"]
395
+ if "FilterPolicyScope" in sub and not sub.get("FilterPolicy"):
396
+ removed_attrs.append("FilterPolicyScope")
397
+ removed_attrs.append("FilterPolicy")
398
+ elif "FilterPolicy" in sub and "FilterPolicyScope" not in sub:
399
+ sub["FilterPolicyScope"] = "MessageAttributes"
400
+
401
+ attributes = {k: v for k, v in sub.items() if k not in removed_attrs}
402
+ return GetSubscriptionAttributesResponse(Attributes=attributes)
403
+
404
+ def set_subscription_attributes(
405
+ self,
406
+ context: RequestContext,
407
+ subscription_arn: subscriptionARN,
408
+ attribute_name: attributeName,
409
+ attribute_value: attributeValue = None,
410
+ **kwargs,
411
+ ) -> None:
412
+ store = self.get_store(account_id=context.account_id, region=context.region)
413
+ sub = store.subscriptions.get(subscription_arn)
414
+ if not sub:
415
+ raise NotFoundException("Subscription does not exist")
416
+
417
+ validate_subscription_attribute(
418
+ attribute_name=attribute_name,
419
+ attribute_value=attribute_value,
420
+ topic_arn=sub["TopicArn"],
421
+ endpoint=sub["Endpoint"],
422
+ )
423
+ if attribute_name == "RawMessageDelivery":
424
+ attribute_value = attribute_value.lower()
425
+
426
+ elif attribute_name == "FilterPolicy":
427
+ filter_policy = json.loads(attribute_value) if attribute_value else None
428
+ if filter_policy:
429
+ validator = FilterPolicyValidator(
430
+ scope=sub.get("FilterPolicyScope", "MessageAttributes"),
431
+ is_subscribe_call=False,
432
+ )
433
+ validator.validate_filter_policy(filter_policy)
434
+
435
+ store.subscription_filter_policy[subscription_arn] = filter_policy
436
+
437
+ sub[attribute_name] = attribute_value
438
+
439
+ def confirm_subscription(
440
+ self,
441
+ context: RequestContext,
442
+ topic_arn: topicARN,
443
+ token: String,
444
+ authenticate_on_unsubscribe: authenticateOnUnsubscribe = None,
445
+ **kwargs,
446
+ ) -> ConfirmSubscriptionResponse:
447
+ # TODO: validate format on the token (seems to be 288 hex chars)
448
+ # this request can come from any http client, it might not be signed (we would need to implement
449
+ # `authenticate_on_unsubscribe` to force a signing client to do this request.
450
+ # so, the region and account_id might not be in the request. Use the ones from the topic_arn
451
+ try:
452
+ parsed_arn = parse_arn(topic_arn)
453
+ except InvalidArnException:
454
+ raise InvalidParameterException("Invalid parameter: Topic")
455
+
456
+ store = self.get_store(account_id=parsed_arn["account"], region=parsed_arn["region"])
457
+
458
+ # it seems SNS is able to know what the region of the topic should be, even though a wrong topic is accepted
459
+ if parsed_arn["region"] != get_region_from_subscription_token(token):
460
+ raise InvalidParameterException("Invalid parameter: Topic")
461
+
462
+ subscription_arn = store.subscription_tokens.get(token)
463
+ if not subscription_arn:
464
+ raise InvalidParameterException("Invalid parameter: Token")
465
+
466
+ subscription = store.subscriptions.get(subscription_arn)
467
+ if not subscription:
468
+ # subscription could have been deleted in the meantime
469
+ raise InvalidParameterException("Invalid parameter: Token")
470
+
471
+ # ConfirmSubscription is idempotent
472
+ if subscription.get("PendingConfirmation") == "false":
473
+ return ConfirmSubscriptionResponse(SubscriptionArn=subscription_arn)
474
+
475
+ subscription["PendingConfirmation"] = "false"
476
+ subscription["ConfirmationWasAuthenticated"] = "true"
477
+
478
+ return ConfirmSubscriptionResponse(SubscriptionArn=subscription_arn)
479
+
480
+ def list_subscriptions(
481
+ self, context: RequestContext, next_token: nextToken = None, **kwargs
482
+ ) -> ListSubscriptionsResponse:
483
+ store = self.get_store(context.account_id, context.region)
484
+ subscriptions = [
485
+ select_from_typed_dict(Subscription, sub) for sub in list(store.subscriptions.values())
486
+ ]
487
+ paginated_subscriptions = PaginatedList(subscriptions)
488
+ page, next_token = paginated_subscriptions.get_page(
489
+ token_generator=lambda x: get_next_page_token_from_arn(x["SubscriptionArn"]),
490
+ page_size=100,
491
+ next_token=next_token,
492
+ )
493
+
494
+ response = ListSubscriptionsResponse(Subscriptions=page)
495
+ if next_token:
496
+ response["NextToken"] = next_token
497
+ return response
498
+
499
+ def list_subscriptions_by_topic(
500
+ self, context: RequestContext, topic_arn: topicARN, next_token: nextToken = None, **kwargs
501
+ ) -> ListSubscriptionsByTopicResponse:
502
+ topic: Topic = self._get_topic(topic_arn, context)
503
+ parsed_topic_arn = parse_and_validate_topic_arn(topic_arn)
504
+ store = self.get_store(parsed_topic_arn["account"], parsed_topic_arn["region"])
505
+ sub_arns: list[str] = topic.get("subscriptions", [])
506
+ subscriptions = [store.subscriptions[k] for k in sub_arns if k in store.subscriptions]
507
+
508
+ paginated_subscriptions = PaginatedList(subscriptions)
509
+ page, next_token = paginated_subscriptions.get_page(
510
+ token_generator=lambda x: get_next_page_token_from_arn(x["SubscriptionArn"]),
511
+ page_size=100,
512
+ next_token=next_token,
513
+ )
514
+
515
+ response = ListSubscriptionsResponse(Subscriptions=page)
516
+ if next_token:
517
+ response["NextToken"] = next_token
518
+ return response
519
+
119
520
  @staticmethod
120
521
  def get_store(account_id: str, region: str) -> SnsStore:
121
522
  return sns_stores[account_id][region]
@@ -138,17 +539,6 @@ class SnsProvider(SnsApi):
138
539
  raise NotFoundException("Topic does not exist")
139
540
 
140
541
 
141
- def parse_and_validate_topic_arn(topic_arn: str | None) -> ArnData:
142
- topic_arn = topic_arn or ""
143
- try:
144
- return parse_arn(topic_arn)
145
- except InvalidArnException:
146
- count = len(topic_arn.split(":"))
147
- raise InvalidParameterException(
148
- f"Invalid parameter: TopicArn Reason: An ARN must have at least 6 elements, not {count}"
149
- )
150
-
151
-
152
542
  def _create_topic(name: str, attributes: dict, context: RequestContext) -> Topic:
153
543
  topic_arn = sns_topic_arn(
154
544
  topic_name=name, region_name=context.region, account_id=context.account_id
@@ -157,6 +547,7 @@ def _create_topic(name: str, attributes: dict, context: RequestContext) -> Topic
157
547
  "name": name,
158
548
  "arn": topic_arn,
159
549
  "attributes": {},
550
+ "subscriptions": [],
160
551
  }
161
552
  attrs = _default_attributes(topic, context)
162
553
  attrs.update(attributes or {})
@@ -0,0 +1,122 @@
1
+ import base64
2
+ import json
3
+ from uuid import uuid4
4
+
5
+ from botocore.utils import InvalidArnException
6
+
7
+ from localstack.aws.api.sns import InvalidParameterException
8
+ from localstack.services.sns.constants import E164_REGEX, VALID_SUBSCRIPTION_ATTR_NAME
9
+ from localstack.utils.aws.arns import ArnData, parse_arn
10
+ from localstack.utils.strings import short_uid, to_bytes, to_str
11
+
12
+
13
+ def parse_and_validate_topic_arn(topic_arn: str | None) -> ArnData:
14
+ topic_arn = topic_arn or ""
15
+ try:
16
+ return parse_arn(topic_arn)
17
+ except InvalidArnException:
18
+ count = len(topic_arn.split(":"))
19
+ raise InvalidParameterException(
20
+ f"Invalid parameter: TopicArn Reason: An ARN must have at least 6 elements, not {count}"
21
+ )
22
+
23
+
24
+ def is_valid_e164_number(number: str) -> bool:
25
+ return E164_REGEX.match(number) is not None
26
+
27
+
28
+ def validate_subscription_attribute(
29
+ attribute_name: str,
30
+ attribute_value: str,
31
+ topic_arn: str,
32
+ endpoint: str,
33
+ is_subscribe_call: bool = False,
34
+ ) -> None:
35
+ """
36
+ Validate the subscription attribute to be set. See:
37
+ https://docs.aws.amazon.com/sns/latest/api/API_SetSubscriptionAttributes.html
38
+ :param attribute_name: the subscription attribute name, must be in VALID_SUBSCRIPTION_ATTR_NAME
39
+ :param attribute_value: the subscription attribute value
40
+ :param topic_arn: the topic_arn of the subscription, needed to know if it is FIFO
41
+ :param endpoint: the subscription endpoint (like an SQS queue ARN)
42
+ :param is_subscribe_call: the error message is different if called from Subscribe or SetSubscriptionAttributes
43
+ :raises InvalidParameterException
44
+ :return:
45
+ """
46
+ error_prefix = (
47
+ "Invalid parameter: Attributes Reason: " if is_subscribe_call else "Invalid parameter: "
48
+ )
49
+ if attribute_name not in VALID_SUBSCRIPTION_ATTR_NAME:
50
+ raise InvalidParameterException(f"{error_prefix}AttributeName")
51
+
52
+ if attribute_name == "FilterPolicy":
53
+ try:
54
+ json.loads(attribute_value or "{}")
55
+ except json.JSONDecodeError:
56
+ raise InvalidParameterException(f"{error_prefix}FilterPolicy: failed to parse JSON.")
57
+ elif attribute_name == "FilterPolicyScope":
58
+ if attribute_value not in ("MessageAttributes", "MessageBody"):
59
+ raise InvalidParameterException(
60
+ f"{error_prefix}FilterPolicyScope: Invalid value [{attribute_value}]. "
61
+ f"Please use either MessageBody or MessageAttributes"
62
+ )
63
+ elif attribute_name == "RawMessageDelivery":
64
+ # TODO: only for SQS and https(s) subs, + firehose
65
+ if attribute_value.lower() not in ("true", "false"):
66
+ raise InvalidParameterException(
67
+ f"{error_prefix}RawMessageDelivery: Invalid value [{attribute_value}]. "
68
+ f"Must be true or false."
69
+ )
70
+
71
+ elif attribute_name == "RedrivePolicy":
72
+ try:
73
+ dlq_target_arn = json.loads(attribute_value).get("deadLetterTargetArn", "")
74
+ except json.JSONDecodeError:
75
+ raise InvalidParameterException(f"{error_prefix}RedrivePolicy: failed to parse JSON.")
76
+ try:
77
+ parsed_arn = parse_arn(dlq_target_arn)
78
+ except InvalidArnException:
79
+ raise InvalidParameterException(
80
+ f"{error_prefix}RedrivePolicy: deadLetterTargetArn is an invalid arn"
81
+ )
82
+
83
+ if topic_arn.endswith(".fifo"):
84
+ if endpoint.endswith(".fifo") and (
85
+ not parsed_arn["resource"].endswith(".fifo") or "sqs" not in parsed_arn["service"]
86
+ ):
87
+ raise InvalidParameterException(
88
+ f"{error_prefix}RedrivePolicy: must use a FIFO queue as DLQ for a FIFO Subscription to a FIFO Topic."
89
+ )
90
+
91
+
92
+ def create_subscription_arn(topic_arn: str) -> str:
93
+ # This is the format of a Subscription ARN
94
+ # arn:aws:sns:us-west-2:123456789012:my-topic:8a21d249-4329-4871-acc6-7be709c6ea7f
95
+ return f"{topic_arn}:{uuid4()}"
96
+
97
+
98
+ def encode_subscription_token_with_region(region: str) -> str:
99
+ """
100
+ Create a 64 characters Subscription Token with the region encoded
101
+ :param region:
102
+ :return: a subscription token with the region encoded
103
+ """
104
+ return ((region.encode() + b"/").hex() + short_uid() * 8)[:64]
105
+
106
+
107
+ def get_next_page_token_from_arn(resource_arn: str) -> str:
108
+ return to_str(base64.b64encode(to_bytes(resource_arn)))
109
+
110
+
111
+ def get_region_from_subscription_token(token: str) -> str:
112
+ """
113
+ Try to decode and return the region from a subscription token
114
+ :param token:
115
+ :return: the region if able to decode it
116
+ :raises: InvalidParameterException if the token is invalid
117
+ """
118
+ try:
119
+ region = token.split("2f", maxsplit=1)[0]
120
+ return bytes.fromhex(region).decode("utf-8")
121
+ except (IndexError, ValueError, TypeError, UnicodeDecodeError):
122
+ raise InvalidParameterException("Invalid parameter: Token")
localstack/version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '4.9.3.dev39'
32
- __version_tuple__ = version_tuple = (4, 9, 3, 'dev39')
31
+ __version__ = version = '4.9.3.dev41'
32
+ __version_tuple__ = version_tuple = (4, 9, 3, 'dev41')
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: localstack-core
3
- Version: 4.9.3.dev39
3
+ Version: 4.9.3.dev41
4
4
  Summary: The core library and runtime of LocalStack
5
5
  Author-email: LocalStack Contributors <info@localstack.cloud>
6
6
  License-Expression: Apache-2.0
@@ -4,7 +4,7 @@ localstack/deprecations.py,sha256=78Sf99fgH3ckJ20a9SMqsu01r1cm5GgcomkuY4yDMDo,15
4
4
  localstack/openapi.yaml,sha256=B803NmpwsxG8PHpHrdZYBrUYjnrRh7B_JX0XuNynuFs,30237
5
5
  localstack/plugins.py,sha256=BIJC9dlo0WbP7lLKkCiGtd_2q5oeqiHZohvoRTcejXM,2457
6
6
  localstack/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- localstack/version.py,sha256=n5X6981kaXdnWnvKOgqr5rnSUHtsgOzr1XeLTZmVkp8,719
7
+ localstack/version.py,sha256=2Yp-Hr1ASXaHs_17a-4AfeSDTlDXF216r5XvoJXEjsw,719
8
8
  localstack/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  localstack/aws/accounts.py,sha256=102zpGowOxo0S6UGMpfjw14QW7WCLVAGsnFK5xFMLoo,3043
10
10
  localstack/aws/app.py,sha256=n9bJCfJRuMz_gLGAH430c3bIQXgUXeWO5NPfcdL2MV8,5145
@@ -448,7 +448,7 @@ localstack/services/events/api_destination.py,sha256=55S5t23Kt3wHWk8RxLHhHoGGcIS
448
448
  localstack/services/events/archive.py,sha256=4m6zrik4I4Hp5bhbN_F4l0lUHXlgg1mBnw83pNC7U8A,6149
449
449
  localstack/services/events/connection.py,sha256=O6-r8egH1nrTF195UwkMTP5oppPKInhOBBFKG-etz9I,13337
450
450
  localstack/services/events/event_bus.py,sha256=KVaQmsCQDQP6YCyABj0NHUhRhEeFM5lllJ7A7d5neIY,4136
451
- localstack/services/events/event_rule_engine.py,sha256=y00JStGykaVwqtsuYlgLnEVs0m5zAzrCrVWnJJIuyLs,27360
451
+ localstack/services/events/event_rule_engine.py,sha256=7ffH10SrR6FTU_cg8x8NAofP6Rsd03vw8FXyUbzByXc,28291
452
452
  localstack/services/events/models.py,sha256=Myw_uQU8SR20Hj6or2_92KaxciuzF1f0GpMAfboeoOY,9722
453
453
  localstack/services/events/provider.py,sha256=g9lavX3Lr002ymjHoYihly3X5NMQpSOuJQ8ZQunf9jk,76679
454
454
  localstack/services/events/replay.py,sha256=FcX5L89Gb-wNJwjdynPZYWT0TyHgRJLUKIoZ2OAW8NU,2958
@@ -741,7 +741,7 @@ localstack/services/ses/resource_providers/aws_ses_emailidentity_plugin.py,sha25
741
741
  localstack/services/sns/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
742
742
  localstack/services/sns/analytics.py,sha256=ecVRQ1l722ppZiKPny3m3rbNM0SKxO90rdyYWE5SI78,379
743
743
  localstack/services/sns/certificate.py,sha256=g30Pi4CMu9u4hFTGUPua6JG5f-kOFmRIJdDu0RpIj7I,1882
744
- localstack/services/sns/constants.py,sha256=iAQLU6qVkA6DumYytm3pHkNLzjh4BubXHIHBK91Ix_M,1216
744
+ localstack/services/sns/constants.py,sha256=8CeBPRg8pvFtd441tOWJm3ifPSzSCmQdW3S8oWD-hhk,1274
745
745
  localstack/services/sns/executor.py,sha256=VRaoalDYwo-K_1iDAMkeNZ6uXHo_WtGv4qPgNMxmAAk,4134
746
746
  localstack/services/sns/filter.py,sha256=aHkd3oF2RTvuHiFZvVv1dD2qVpLUQkAeU2hJBQnW4xU,22990
747
747
  localstack/services/sns/models.py,sha256=X0CMwm04vwIIK2Kj9ooP_2van1cA5fMvualDiq6guf4,6888
@@ -757,8 +757,9 @@ localstack/services/sns/resource_providers/aws_sns_topic_plugin.py,sha256=6I9qK7
757
757
  localstack/services/sns/resource_providers/aws_sns_topicpolicy.py,sha256=su9pOM3M0sh24yGSdrm-QjM5G7B0n7zh4b3__KcR5Co,3471
758
758
  localstack/services/sns/resource_providers/aws_sns_topicpolicy.schema.json,sha256=Q5XQbEaVKxIfvm_6GlYzl3BtezcE6hET8MuJmlGwohY,1677
759
759
  localstack/services/sns/resource_providers/aws_sns_topicpolicy_plugin.py,sha256=7VfQhlKCLiYpI9_6qo2pKm4Al-ihxtoOGlpC7sWcTmc,527
760
- localstack/services/sns/v2/models.py,sha256=LsgDV5a5QSF5oPM_kYQhp_524eRVwFXvDIktyN35ABg,579
761
- localstack/services/sns/v2/provider.py,sha256=kIlZUwTol3PN4qGpTU6rlA5ueYO9Gd33tM1Hf9wYxQ8,7785
760
+ localstack/services/sns/v2/models.py,sha256=8deGSW3EDFKyX5q3Er0qKMSQHH6wawBGoMJpXnQDDKw,5341
761
+ localstack/services/sns/v2/provider.py,sha256=_C-9aeIydFgWmFWGv3Xa0IHoaX-_b4Gy_s5LhK2EwJs,25810
762
+ localstack/services/sns/v2/utils.py,sha256=_bb1bYRXWqDLbpG9Yuq6x_apiAAjYf5AMHp85KiK_qs,4919
762
763
  localstack/services/sqs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
763
764
  localstack/services/sqs/constants.py,sha256=9MLAOW4-hcbZlP2qYMY3giUnubHD_mgoORT0nh5W04Q,2826
764
765
  localstack/services/sqs/developer_api.py,sha256=fNQNMqCkDyvobRm8g4-ErXjSYQ4O-myYobXA_RneC9o,8004
@@ -1296,13 +1297,13 @@ localstack/utils/server/tcp_proxy.py,sha256=y2NJAmvftTiAYsLU_8qe4W5LGqwUw21i90Pu
1296
1297
  localstack/utils/xray/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1297
1298
  localstack/utils/xray/trace_header.py,sha256=ahXk9eonq7LpeENwlqUEPj3jDOCiVRixhntQuxNor-Q,6209
1298
1299
  localstack/utils/xray/traceid.py,sha256=GKO-R2sMMjlrH2UaLPXlQlZ6flbE7ZKb6IZMtMu_M5U,1110
1299
- localstack_core-4.9.3.dev39.data/scripts/localstack,sha256=WyL11vp5CkuP79iIR-L8XT7Cj8nvmxX7XRAgxhbmXNE,529
1300
- localstack_core-4.9.3.dev39.data/scripts/localstack-supervisor,sha256=nm1Il2d6ASyOB6Vo4CRHd90w7TK9FdRl9VPp0NN6hUk,6378
1301
- localstack_core-4.9.3.dev39.data/scripts/localstack.bat,sha256=tlzZTXtveHkMX_s_fa7VDfvdNdS8iVpEz2ER3uk9B_c,29
1302
- localstack_core-4.9.3.dev39.dist-info/licenses/LICENSE.txt,sha256=3PC-9Z69UsNARuQ980gNR_JsLx8uvMjdG6C7cc4LBYs,606
1303
- localstack_core-4.9.3.dev39.dist-info/METADATA,sha256=WAW7-GlF3QAQEP0fvAVAdp49wgxMLtjtjiHTs90mtaM,5539
1304
- localstack_core-4.9.3.dev39.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1305
- localstack_core-4.9.3.dev39.dist-info/entry_points.txt,sha256=5IoyjalZoY-PWY5Lk_AeEjEEQ-rKQJhijLe697GVlnM,20953
1306
- localstack_core-4.9.3.dev39.dist-info/plux.json,sha256=9Tgz25uJK1MkPdtow2YL2GcP2NDbHL1o_cmjnKJEFNw,21181
1307
- localstack_core-4.9.3.dev39.dist-info/top_level.txt,sha256=3sqmK2lGac8nCy8nwsbS5SpIY_izmtWtgaTFKHYVHbI,11
1308
- localstack_core-4.9.3.dev39.dist-info/RECORD,,
1300
+ localstack_core-4.9.3.dev41.data/scripts/localstack,sha256=WyL11vp5CkuP79iIR-L8XT7Cj8nvmxX7XRAgxhbmXNE,529
1301
+ localstack_core-4.9.3.dev41.data/scripts/localstack-supervisor,sha256=nm1Il2d6ASyOB6Vo4CRHd90w7TK9FdRl9VPp0NN6hUk,6378
1302
+ localstack_core-4.9.3.dev41.data/scripts/localstack.bat,sha256=tlzZTXtveHkMX_s_fa7VDfvdNdS8iVpEz2ER3uk9B_c,29
1303
+ localstack_core-4.9.3.dev41.dist-info/licenses/LICENSE.txt,sha256=3PC-9Z69UsNARuQ980gNR_JsLx8uvMjdG6C7cc4LBYs,606
1304
+ localstack_core-4.9.3.dev41.dist-info/METADATA,sha256=mYXHKkdAlEFmTCsxIFdYsxHp3IZsh1sh99-F_06pwQA,5539
1305
+ localstack_core-4.9.3.dev41.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1306
+ localstack_core-4.9.3.dev41.dist-info/entry_points.txt,sha256=5IoyjalZoY-PWY5Lk_AeEjEEQ-rKQJhijLe697GVlnM,20953
1307
+ localstack_core-4.9.3.dev41.dist-info/plux.json,sha256=YUrztsWn3cs8aBniYCEuG3ctvJgi-AZQwvMxhnJ3DkQ,21181
1308
+ localstack_core-4.9.3.dev41.dist-info/top_level.txt,sha256=3sqmK2lGac8nCy8nwsbS5SpIY_izmtWtgaTFKHYVHbI,11
1309
+ localstack_core-4.9.3.dev41.dist-info/RECORD,,
@@ -0,0 +1 @@
1
+ {"localstack.cloudformation.resource_providers": ["AWS::ApiGateway::UsagePlanKey=localstack.services.apigateway.resource_providers.aws_apigateway_usageplankey_plugin:ApiGatewayUsagePlanKeyProviderPlugin", "AWS::SecretsManager::Secret=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_secret_plugin:SecretsManagerSecretProviderPlugin", "AWS::ECR::Repository=localstack.services.ecr.resource_providers.aws_ecr_repository_plugin:ECRRepositoryProviderPlugin", "AWS::Events::EventBus=localstack.services.events.resource_providers.aws_events_eventbus_plugin:EventsEventBusProviderPlugin", "AWS::ApiGateway::Deployment=localstack.services.apigateway.resource_providers.aws_apigateway_deployment_plugin:ApiGatewayDeploymentProviderPlugin", "AWS::ResourceGroups::Group=localstack.services.resource_groups.resource_providers.aws_resourcegroups_group_plugin:ResourceGroupsGroupProviderPlugin", "AWS::SSM::MaintenanceWindow=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindow_plugin:SSMMaintenanceWindowProviderPlugin", "AWS::IAM::InstanceProfile=localstack.services.iam.resource_providers.aws_iam_instanceprofile_plugin:IAMInstanceProfileProviderPlugin", "AWS::CloudFormation::Stack=localstack.services.cloudformation.resource_providers.aws_cloudformation_stack_plugin:CloudFormationStackProviderPlugin", "AWS::IAM::ServiceLinkedRole=localstack.services.iam.resource_providers.aws_iam_servicelinkedrole_plugin:IAMServiceLinkedRoleProviderPlugin", "AWS::CloudFormation::Macro=localstack.services.cloudformation.resource_providers.aws_cloudformation_macro_plugin:CloudFormationMacroProviderPlugin", "AWS::ApiGateway::RestApi=localstack.services.apigateway.resource_providers.aws_apigateway_restapi_plugin:ApiGatewayRestApiProviderPlugin", "AWS::Elasticsearch::Domain=localstack.services.opensearch.resource_providers.aws_elasticsearch_domain_plugin:ElasticsearchDomainProviderPlugin", "AWS::StepFunctions::StateMachine=localstack.services.stepfunctions.resource_providers.aws_stepfunctions_statemachine_plugin:StepFunctionsStateMachineProviderPlugin", "AWS::Logs::LogStream=localstack.services.logs.resource_providers.aws_logs_logstream_plugin:LogsLogStreamProviderPlugin", "AWS::EC2::InternetGateway=localstack.services.ec2.resource_providers.aws_ec2_internetgateway_plugin:EC2InternetGatewayProviderPlugin", "AWS::ApiGateway::ApiKey=localstack.services.apigateway.resource_providers.aws_apigateway_apikey_plugin:ApiGatewayApiKeyProviderPlugin", "AWS::EC2::RouteTable=localstack.services.ec2.resource_providers.aws_ec2_routetable_plugin:EC2RouteTableProviderPlugin", "AWS::Scheduler::Schedule=localstack.services.scheduler.resource_providers.aws_scheduler_schedule_plugin:SchedulerScheduleProviderPlugin", "AWS::ApiGateway::Account=localstack.services.apigateway.resource_providers.aws_apigateway_account_plugin:ApiGatewayAccountProviderPlugin", "AWS::ApiGateway::Method=localstack.services.apigateway.resource_providers.aws_apigateway_method_plugin:ApiGatewayMethodProviderPlugin", "AWS::Lambda::Permission=localstack.services.lambda_.resource_providers.aws_lambda_permission_plugin:LambdaPermissionProviderPlugin", "AWS::EC2::TransitGatewayAttachment=localstack.services.ec2.resource_providers.aws_ec2_transitgatewayattachment_plugin:EC2TransitGatewayAttachmentProviderPlugin", "AWS::EC2::SecurityGroup=localstack.services.ec2.resource_providers.aws_ec2_securitygroup_plugin:EC2SecurityGroupProviderPlugin", "AWS::ApiGateway::Model=localstack.services.apigateway.resource_providers.aws_apigateway_model_plugin:ApiGatewayModelProviderPlugin", "AWS::SSM::Parameter=localstack.services.ssm.resource_providers.aws_ssm_parameter_plugin:SSMParameterProviderPlugin", "AWS::IAM::AccessKey=localstack.services.iam.resource_providers.aws_iam_accesskey_plugin:IAMAccessKeyProviderPlugin", "AWS::EC2::VPC=localstack.services.ec2.resource_providers.aws_ec2_vpc_plugin:EC2VPCProviderPlugin", "AWS::CertificateManager::Certificate=localstack.services.certificatemanager.resource_providers.aws_certificatemanager_certificate_plugin:CertificateManagerCertificateProviderPlugin", "AWS::KMS::Alias=localstack.services.kms.resource_providers.aws_kms_alias_plugin:KMSAliasProviderPlugin", "AWS::Logs::LogGroup=localstack.services.logs.resource_providers.aws_logs_loggroup_plugin:LogsLogGroupProviderPlugin", "AWS::StepFunctions::Activity=localstack.services.stepfunctions.resource_providers.aws_stepfunctions_activity_plugin:StepFunctionsActivityProviderPlugin", "AWS::EC2::Instance=localstack.services.ec2.resource_providers.aws_ec2_instance_plugin:EC2InstanceProviderPlugin", "AWS::EC2::Subnet=localstack.services.ec2.resource_providers.aws_ec2_subnet_plugin:EC2SubnetProviderPlugin", "AWS::IAM::ManagedPolicy=localstack.services.iam.resource_providers.aws_iam_managedpolicy_plugin:IAMManagedPolicyProviderPlugin", "AWS::IAM::Policy=localstack.services.iam.resource_providers.aws_iam_policy_plugin:IAMPolicyProviderPlugin", "AWS::EC2::NetworkAcl=localstack.services.ec2.resource_providers.aws_ec2_networkacl_plugin:EC2NetworkAclProviderPlugin", "AWS::CloudFormation::WaitCondition=localstack.services.cloudformation.resource_providers.aws_cloudformation_waitcondition_plugin:CloudFormationWaitConditionProviderPlugin", "AWS::Route53::HealthCheck=localstack.services.route53.resource_providers.aws_route53_healthcheck_plugin:Route53HealthCheckProviderPlugin", "AWS::Lambda::LayerVersion=localstack.services.lambda_.resource_providers.aws_lambda_layerversion_plugin:LambdaLayerVersionProviderPlugin", "AWS::SSM::MaintenanceWindowTarget=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindowtarget_plugin:SSMMaintenanceWindowTargetProviderPlugin", "AWS::S3::Bucket=localstack.services.s3.resource_providers.aws_s3_bucket_plugin:S3BucketProviderPlugin", "AWS::EC2::VPCEndpoint=localstack.services.ec2.resource_providers.aws_ec2_vpcendpoint_plugin:EC2VPCEndpointProviderPlugin", "AWS::Kinesis::StreamConsumer=localstack.services.kinesis.resource_providers.aws_kinesis_streamconsumer_plugin:KinesisStreamConsumerProviderPlugin", "AWS::Lambda::Url=localstack.services.lambda_.resource_providers.aws_lambda_url_plugin:LambdaUrlProviderPlugin", "AWS::Kinesis::Stream=localstack.services.kinesis.resource_providers.aws_kinesis_stream_plugin:KinesisStreamProviderPlugin", "AWS::SecretsManager::SecretTargetAttachment=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_secrettargetattachment_plugin:SecretsManagerSecretTargetAttachmentProviderPlugin", "AWS::Route53::RecordSet=localstack.services.route53.resource_providers.aws_route53_recordset_plugin:Route53RecordSetProviderPlugin", "AWS::KinesisFirehose::DeliveryStream=localstack.services.kinesisfirehose.resource_providers.aws_kinesisfirehose_deliverystream_plugin:KinesisFirehoseDeliveryStreamProviderPlugin", "AWS::SNS::Topic=localstack.services.sns.resource_providers.aws_sns_topic_plugin:SNSTopicProviderPlugin", "AWS::Events::ApiDestination=localstack.services.events.resource_providers.aws_events_apidestination_plugin:EventsApiDestinationProviderPlugin", "AWS::Lambda::CodeSigningConfig=localstack.services.lambda_.resource_providers.aws_lambda_codesigningconfig_plugin:LambdaCodeSigningConfigProviderPlugin", "AWS::SecretsManager::ResourcePolicy=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_resourcepolicy_plugin:SecretsManagerResourcePolicyProviderPlugin", "AWS::SecretsManager::RotationSchedule=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_rotationschedule_plugin:SecretsManagerRotationScheduleProviderPlugin", "AWS::Logs::SubscriptionFilter=localstack.services.logs.resource_providers.aws_logs_subscriptionfilter_plugin:LogsSubscriptionFilterProviderPlugin", "AWS::SSM::MaintenanceWindowTask=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindowtask_plugin:SSMMaintenanceWindowTaskProviderPlugin", "AWS::Lambda::Version=localstack.services.lambda_.resource_providers.aws_lambda_version_plugin:LambdaVersionProviderPlugin", "AWS::SES::EmailIdentity=localstack.services.ses.resource_providers.aws_ses_emailidentity_plugin:SESEmailIdentityProviderPlugin", "AWS::ApiGateway::BasePathMapping=localstack.services.apigateway.resource_providers.aws_apigateway_basepathmapping_plugin:ApiGatewayBasePathMappingProviderPlugin", "AWS::Events::Connection=localstack.services.events.resource_providers.aws_events_connection_plugin:EventsConnectionProviderPlugin", "AWS::CloudFormation::WaitConditionHandle=localstack.services.cloudformation.resource_providers.aws_cloudformation_waitconditionhandle_plugin:CloudFormationWaitConditionHandleProviderPlugin", "AWS::EC2::VPCGatewayAttachment=localstack.services.ec2.resource_providers.aws_ec2_vpcgatewayattachment_plugin:EC2VPCGatewayAttachmentProviderPlugin", "AWS::Lambda::Function=localstack.services.lambda_.resource_providers.aws_lambda_function_plugin:LambdaFunctionProviderPlugin", "AWS::IAM::ServerCertificate=localstack.services.iam.resource_providers.aws_iam_servercertificate_plugin:IAMServerCertificateProviderPlugin", "AWS::EC2::TransitGateway=localstack.services.ec2.resource_providers.aws_ec2_transitgateway_plugin:EC2TransitGatewayProviderPlugin", "AWS::SSM::PatchBaseline=localstack.services.ssm.resource_providers.aws_ssm_patchbaseline_plugin:SSMPatchBaselineProviderPlugin", "AWS::DynamoDB::Table=localstack.services.dynamodb.resource_providers.aws_dynamodb_table_plugin:DynamoDBTableProviderPlugin", "AWS::Lambda::LayerVersionPermission=localstack.services.lambda_.resource_providers.aws_lambda_layerversionpermission_plugin:LambdaLayerVersionPermissionProviderPlugin", "AWS::DynamoDB::GlobalTable=localstack.services.dynamodb.resource_providers.aws_dynamodb_globaltable_plugin:DynamoDBGlobalTableProviderPlugin", "AWS::KMS::Key=localstack.services.kms.resource_providers.aws_kms_key_plugin:KMSKeyProviderPlugin", "AWS::ApiGateway::Stage=localstack.services.apigateway.resource_providers.aws_apigateway_stage_plugin:ApiGatewayStageProviderPlugin", "AWS::CloudWatch::CompositeAlarm=localstack.services.cloudwatch.resource_providers.aws_cloudwatch_compositealarm_plugin:CloudWatchCompositeAlarmProviderPlugin", "AWS::ApiGateway::UsagePlan=localstack.services.apigateway.resource_providers.aws_apigateway_usageplan_plugin:ApiGatewayUsagePlanProviderPlugin", "AWS::Scheduler::ScheduleGroup=localstack.services.scheduler.resource_providers.aws_scheduler_schedulegroup_plugin:SchedulerScheduleGroupProviderPlugin", "AWS::Lambda::EventSourceMapping=localstack.services.lambda_.resource_providers.aws_lambda_eventsourcemapping_plugin:LambdaEventSourceMappingProviderPlugin", "AWS::Redshift::Cluster=localstack.services.redshift.resource_providers.aws_redshift_cluster_plugin:RedshiftClusterProviderPlugin", "AWS::SQS::Queue=localstack.services.sqs.resource_providers.aws_sqs_queue_plugin:SQSQueueProviderPlugin", "AWS::Events::EventBusPolicy=localstack.services.events.resource_providers.aws_events_eventbuspolicy_plugin:EventsEventBusPolicyProviderPlugin", "AWS::EC2::PrefixList=localstack.services.ec2.resource_providers.aws_ec2_prefixlist_plugin:EC2PrefixListProviderPlugin", "AWS::CloudWatch::Alarm=localstack.services.cloudwatch.resource_providers.aws_cloudwatch_alarm_plugin:CloudWatchAlarmProviderPlugin", "AWS::ApiGateway::RequestValidator=localstack.services.apigateway.resource_providers.aws_apigateway_requestvalidator_plugin:ApiGatewayRequestValidatorProviderPlugin", "AWS::CDK::Metadata=localstack.services.cdk.resource_providers.cdk_metadata_plugin:LambdaAliasProviderPlugin", "AWS::Lambda::Alias=localstack.services.lambda_.resource_providers.lambda_alias_plugin:LambdaAliasProviderPlugin", "AWS::EC2::Route=localstack.services.ec2.resource_providers.aws_ec2_route_plugin:EC2RouteProviderPlugin", "AWS::S3::BucketPolicy=localstack.services.s3.resource_providers.aws_s3_bucketpolicy_plugin:S3BucketPolicyProviderPlugin", "AWS::SNS::TopicPolicy=localstack.services.sns.resource_providers.aws_sns_topicpolicy_plugin:SNSTopicPolicyProviderPlugin", "AWS::Events::Rule=localstack.services.events.resource_providers.aws_events_rule_plugin:EventsRuleProviderPlugin", "AWS::Lambda::EventInvokeConfig=localstack.services.lambda_.resource_providers.aws_lambda_eventinvokeconfig_plugin:LambdaEventInvokeConfigProviderPlugin", "AWS::IAM::Role=localstack.services.iam.resource_providers.aws_iam_role_plugin:IAMRoleProviderPlugin", "AWS::EC2::KeyPair=localstack.services.ec2.resource_providers.aws_ec2_keypair_plugin:EC2KeyPairProviderPlugin", "AWS::EC2::DHCPOptions=localstack.services.ec2.resource_providers.aws_ec2_dhcpoptions_plugin:EC2DHCPOptionsProviderPlugin", "AWS::OpenSearchService::Domain=localstack.services.opensearch.resource_providers.aws_opensearchservice_domain_plugin:OpenSearchServiceDomainProviderPlugin", "AWS::IAM::Group=localstack.services.iam.resource_providers.aws_iam_group_plugin:IAMGroupProviderPlugin", "AWS::EC2::SubnetRouteTableAssociation=localstack.services.ec2.resource_providers.aws_ec2_subnetroutetableassociation_plugin:EC2SubnetRouteTableAssociationProviderPlugin", "AWS::ApiGateway::Resource=localstack.services.apigateway.resource_providers.aws_apigateway_resource_plugin:ApiGatewayResourceProviderPlugin", "AWS::SNS::Subscription=localstack.services.sns.resource_providers.aws_sns_subscription_plugin:SNSSubscriptionProviderPlugin", "AWS::EC2::NatGateway=localstack.services.ec2.resource_providers.aws_ec2_natgateway_plugin:EC2NatGatewayProviderPlugin", "AWS::ApiGateway::DomainName=localstack.services.apigateway.resource_providers.aws_apigateway_domainname_plugin:ApiGatewayDomainNameProviderPlugin", "AWS::SQS::QueuePolicy=localstack.services.sqs.resource_providers.aws_sqs_queuepolicy_plugin:SQSQueuePolicyProviderPlugin", "AWS::IAM::User=localstack.services.iam.resource_providers.aws_iam_user_plugin:IAMUserProviderPlugin", "AWS::ApiGateway::GatewayResponse=localstack.services.apigateway.resource_providers.aws_apigateway_gatewayresponse_plugin:ApiGatewayGatewayResponseProviderPlugin"], "localstack.hooks.on_infra_shutdown": ["publish_metrics=localstack.utils.analytics.metrics.publisher:publish_metrics", "stop_server=localstack.dns.plugins:stop_server", "remove_custom_endpoints=localstack.services.lambda_.plugins:remove_custom_endpoints", "run_on_after_service_shutdown_handlers=localstack.runtime.shutdown:run_on_after_service_shutdown_handlers", "run_shutdown_handlers=localstack.runtime.shutdown:run_shutdown_handlers", "shutdown_services=localstack.runtime.shutdown:shutdown_services", "_run_init_scripts_on_shutdown=localstack.runtime.init:_run_init_scripts_on_shutdown"], "localstack.hooks.on_infra_start": ["register_swagger_endpoints=localstack.http.resources.swagger.plugins:register_swagger_endpoints", "_patch_botocore_endpoint_in_memory=localstack.aws.client:_patch_botocore_endpoint_in_memory", "_patch_botocore_json_parser=localstack.aws.client:_patch_botocore_json_parser", "_patch_cbor2=localstack.aws.client:_patch_cbor2", "setup_dns_configuration_on_host=localstack.dns.plugins:setup_dns_configuration_on_host", "start_dns_server=localstack.dns.plugins:start_dns_server", "apply_aws_runtime_patches=localstack.aws.patches:apply_aws_runtime_patches", "eager_load_services=localstack.services.plugins:eager_load_services", "register_custom_endpoints=localstack.services.lambda_.plugins:register_custom_endpoints", "validate_configuration=localstack.services.lambda_.plugins:validate_configuration", "conditionally_enable_debugger=localstack.dev.debugger.plugins:conditionally_enable_debugger", "delete_cached_certificate=localstack.plugins:delete_cached_certificate", "deprecation_warnings=localstack.plugins:deprecation_warnings", "init_response_mutation_handler=localstack.aws.handlers.response:init_response_mutation_handler", "_publish_config_as_analytics_event=localstack.runtime.analytics:_publish_config_as_analytics_event", "_publish_container_info=localstack.runtime.analytics:_publish_container_info", "apply_runtime_patches=localstack.runtime.patches:apply_runtime_patches", "register_cloudformation_deploy_ui=localstack.services.cloudformation.plugins:register_cloudformation_deploy_ui", "_run_init_scripts_on_start=localstack.runtime.init:_run_init_scripts_on_start"], "localstack.hooks.on_infra_ready": ["publish_provider_assignment=localstack.utils.analytics.service_providers:publish_provider_assignment", "_run_init_scripts_on_ready=localstack.runtime.init:_run_init_scripts_on_ready"], "localstack.lambda.runtime_executor": ["docker=localstack.services.lambda_.invocation.plugins:DockerRuntimeExecutorPlugin"], "localstack.packages": ["lambda-java-libs/community=localstack.services.lambda_.plugins:lambda_java_libs", "lambda-runtime/community=localstack.services.lambda_.plugins:lambda_runtime_package", "kinesis-mock/community=localstack.services.kinesis.plugins:kinesismock_package", "vosk/community=localstack.services.transcribe.plugins:vosk_package", "dynamodb-local/community=localstack.services.dynamodb.plugins:dynamodb_local_package", "ffmpeg/community=localstack.packages.plugins:ffmpeg_package", "java/community=localstack.packages.plugins:java_package", "jpype-jsonata/community=localstack.services.stepfunctions.plugins:jpype_jsonata_package", "opensearch/community=localstack.services.opensearch.plugins:opensearch_package", "elasticsearch/community=localstack.services.es.plugins:elasticsearch_package"], "localstack.openapi.spec": ["localstack=localstack.plugins:CoreOASPlugin"], "localstack.utils.catalog": ["aws-catalog-remote-state=localstack.utils.catalog.catalog:AwsCatalogRemoteStatePlugin", "aws-catalog-runtime-only=localstack.utils.catalog.catalog:AwsCatalogRuntimePlugin"], "localstack.runtime.components": ["aws=localstack.aws.components:AwsComponents"], "localstack.hooks.configure_localstack_container": ["_mount_machine_file=localstack.utils.analytics.metadata:_mount_machine_file"], "localstack.hooks.prepare_host": ["prepare_host_machine_id=localstack.utils.analytics.metadata:prepare_host_machine_id"], "localstack.aws.provider": ["acm:default=localstack.services.providers:acm", "apigateway:default=localstack.services.providers:apigateway", "apigateway:legacy=localstack.services.providers:apigateway_legacy", "apigateway:next_gen=localstack.services.providers:apigateway_next_gen", "config:default=localstack.services.providers:awsconfig", "cloudformation:engine-legacy=localstack.services.providers:cloudformation", "cloudformation:default=localstack.services.providers:cloudformation_v2", "cloudwatch:default=localstack.services.providers:cloudwatch", "cloudwatch:v1=localstack.services.providers:cloudwatch_v1", "cloudwatch:v2=localstack.services.providers:cloudwatch_v2", "dynamodb:default=localstack.services.providers:dynamodb", "dynamodb:v2=localstack.services.providers:dynamodb_v2", "dynamodbstreams:default=localstack.services.providers:dynamodbstreams", "dynamodbstreams:v2=localstack.services.providers:dynamodbstreams_v2", "ec2:default=localstack.services.providers:ec2", "es:default=localstack.services.providers:es", "events:default=localstack.services.providers:events", "events:legacy=localstack.services.providers:events_legacy", "events:v1=localstack.services.providers:events_v1", "events:v2=localstack.services.providers:events_v2", "firehose:default=localstack.services.providers:firehose", "iam:default=localstack.services.providers:iam", "kinesis:default=localstack.services.providers:kinesis", "kms:default=localstack.services.providers:kms", "lambda:default=localstack.services.providers:lambda_", "lambda:asf=localstack.services.providers:lambda_asf", "lambda:v2=localstack.services.providers:lambda_v2", "logs:default=localstack.services.providers:logs", "opensearch:default=localstack.services.providers:opensearch", "redshift:default=localstack.services.providers:redshift", "resource-groups:default=localstack.services.providers:resource_groups", "resourcegroupstaggingapi:default=localstack.services.providers:resourcegroupstaggingapi", "route53:default=localstack.services.providers:route53", "route53resolver:default=localstack.services.providers:route53resolver", "s3:default=localstack.services.providers:s3", "s3control:default=localstack.services.providers:s3control", "scheduler:default=localstack.services.providers:scheduler", "secretsmanager:default=localstack.services.providers:secretsmanager", "ses:default=localstack.services.providers:ses", "sns:default=localstack.services.providers:sns", "sns:v2=localstack.services.providers:sns_v2", "sqs:default=localstack.services.providers:sqs", "ssm:default=localstack.services.providers:ssm", "stepfunctions:default=localstack.services.providers:stepfunctions", "stepfunctions:v2=localstack.services.providers:stepfunctions_v2", "sts:default=localstack.services.providers:sts", "support:default=localstack.services.providers:support", "swf:default=localstack.services.providers:swf", "transcribe:default=localstack.services.providers:transcribe"], "localstack.runtime.server": ["hypercorn=localstack.runtime.server.plugins:HypercornRuntimeServerPlugin", "twisted=localstack.runtime.server.plugins:TwistedRuntimeServerPlugin"], "localstack.init.runner": ["py=localstack.runtime.init:PythonScriptRunner", "sh=localstack.runtime.init:ShellScriptRunner"]}
@@ -1 +0,0 @@
1
- {"localstack.cloudformation.resource_providers": ["AWS::IAM::User=localstack.services.iam.resource_providers.aws_iam_user_plugin:IAMUserProviderPlugin", "AWS::EC2::TransitGatewayAttachment=localstack.services.ec2.resource_providers.aws_ec2_transitgatewayattachment_plugin:EC2TransitGatewayAttachmentProviderPlugin", "AWS::Events::EventBus=localstack.services.events.resource_providers.aws_events_eventbus_plugin:EventsEventBusProviderPlugin", "AWS::SSM::PatchBaseline=localstack.services.ssm.resource_providers.aws_ssm_patchbaseline_plugin:SSMPatchBaselineProviderPlugin", "AWS::Lambda::Alias=localstack.services.lambda_.resource_providers.lambda_alias_plugin:LambdaAliasProviderPlugin", "AWS::S3::Bucket=localstack.services.s3.resource_providers.aws_s3_bucket_plugin:S3BucketProviderPlugin", "AWS::Logs::SubscriptionFilter=localstack.services.logs.resource_providers.aws_logs_subscriptionfilter_plugin:LogsSubscriptionFilterProviderPlugin", "AWS::Logs::LogGroup=localstack.services.logs.resource_providers.aws_logs_loggroup_plugin:LogsLogGroupProviderPlugin", "AWS::Kinesis::StreamConsumer=localstack.services.kinesis.resource_providers.aws_kinesis_streamconsumer_plugin:KinesisStreamConsumerProviderPlugin", "AWS::Events::ApiDestination=localstack.services.events.resource_providers.aws_events_apidestination_plugin:EventsApiDestinationProviderPlugin", "AWS::Route53::HealthCheck=localstack.services.route53.resource_providers.aws_route53_healthcheck_plugin:Route53HealthCheckProviderPlugin", "AWS::IAM::Role=localstack.services.iam.resource_providers.aws_iam_role_plugin:IAMRoleProviderPlugin", "AWS::SSM::MaintenanceWindowTask=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindowtask_plugin:SSMMaintenanceWindowTaskProviderPlugin", "AWS::IAM::ManagedPolicy=localstack.services.iam.resource_providers.aws_iam_managedpolicy_plugin:IAMManagedPolicyProviderPlugin", "AWS::ApiGateway::Account=localstack.services.apigateway.resource_providers.aws_apigateway_account_plugin:ApiGatewayAccountProviderPlugin", "AWS::ApiGateway::Stage=localstack.services.apigateway.resource_providers.aws_apigateway_stage_plugin:ApiGatewayStageProviderPlugin", "AWS::DynamoDB::Table=localstack.services.dynamodb.resource_providers.aws_dynamodb_table_plugin:DynamoDBTableProviderPlugin", "AWS::Lambda::LayerVersionPermission=localstack.services.lambda_.resource_providers.aws_lambda_layerversionpermission_plugin:LambdaLayerVersionPermissionProviderPlugin", "AWS::SNS::Topic=localstack.services.sns.resource_providers.aws_sns_topic_plugin:SNSTopicProviderPlugin", "AWS::SQS::QueuePolicy=localstack.services.sqs.resource_providers.aws_sqs_queuepolicy_plugin:SQSQueuePolicyProviderPlugin", "AWS::ApiGateway::DomainName=localstack.services.apigateway.resource_providers.aws_apigateway_domainname_plugin:ApiGatewayDomainNameProviderPlugin", "AWS::S3::BucketPolicy=localstack.services.s3.resource_providers.aws_s3_bucketpolicy_plugin:S3BucketPolicyProviderPlugin", "AWS::ApiGateway::ApiKey=localstack.services.apigateway.resource_providers.aws_apigateway_apikey_plugin:ApiGatewayApiKeyProviderPlugin", "AWS::Events::Rule=localstack.services.events.resource_providers.aws_events_rule_plugin:EventsRuleProviderPlugin", "AWS::ECR::Repository=localstack.services.ecr.resource_providers.aws_ecr_repository_plugin:ECRRepositoryProviderPlugin", "AWS::ApiGateway::Method=localstack.services.apigateway.resource_providers.aws_apigateway_method_plugin:ApiGatewayMethodProviderPlugin", "AWS::Lambda::Url=localstack.services.lambda_.resource_providers.aws_lambda_url_plugin:LambdaUrlProviderPlugin", "AWS::CloudWatch::CompositeAlarm=localstack.services.cloudwatch.resource_providers.aws_cloudwatch_compositealarm_plugin:CloudWatchCompositeAlarmProviderPlugin", "AWS::Lambda::Function=localstack.services.lambda_.resource_providers.aws_lambda_function_plugin:LambdaFunctionProviderPlugin", "AWS::EC2::Instance=localstack.services.ec2.resource_providers.aws_ec2_instance_plugin:EC2InstanceProviderPlugin", "AWS::EC2::VPCGatewayAttachment=localstack.services.ec2.resource_providers.aws_ec2_vpcgatewayattachment_plugin:EC2VPCGatewayAttachmentProviderPlugin", "AWS::KMS::Alias=localstack.services.kms.resource_providers.aws_kms_alias_plugin:KMSAliasProviderPlugin", "AWS::IAM::ServerCertificate=localstack.services.iam.resource_providers.aws_iam_servercertificate_plugin:IAMServerCertificateProviderPlugin", "AWS::ApiGateway::Deployment=localstack.services.apigateway.resource_providers.aws_apigateway_deployment_plugin:ApiGatewayDeploymentProviderPlugin", "AWS::EC2::PrefixList=localstack.services.ec2.resource_providers.aws_ec2_prefixlist_plugin:EC2PrefixListProviderPlugin", "AWS::SecretsManager::SecretTargetAttachment=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_secrettargetattachment_plugin:SecretsManagerSecretTargetAttachmentProviderPlugin", "AWS::Lambda::LayerVersion=localstack.services.lambda_.resource_providers.aws_lambda_layerversion_plugin:LambdaLayerVersionProviderPlugin", "AWS::KMS::Key=localstack.services.kms.resource_providers.aws_kms_key_plugin:KMSKeyProviderPlugin", "AWS::SNS::TopicPolicy=localstack.services.sns.resource_providers.aws_sns_topicpolicy_plugin:SNSTopicPolicyProviderPlugin", "AWS::SSM::Parameter=localstack.services.ssm.resource_providers.aws_ssm_parameter_plugin:SSMParameterProviderPlugin", "AWS::KinesisFirehose::DeliveryStream=localstack.services.kinesisfirehose.resource_providers.aws_kinesisfirehose_deliverystream_plugin:KinesisFirehoseDeliveryStreamProviderPlugin", "AWS::Events::Connection=localstack.services.events.resource_providers.aws_events_connection_plugin:EventsConnectionProviderPlugin", "AWS::IAM::AccessKey=localstack.services.iam.resource_providers.aws_iam_accesskey_plugin:IAMAccessKeyProviderPlugin", "AWS::EC2::DHCPOptions=localstack.services.ec2.resource_providers.aws_ec2_dhcpoptions_plugin:EC2DHCPOptionsProviderPlugin", "AWS::DynamoDB::GlobalTable=localstack.services.dynamodb.resource_providers.aws_dynamodb_globaltable_plugin:DynamoDBGlobalTableProviderPlugin", "AWS::Elasticsearch::Domain=localstack.services.opensearch.resource_providers.aws_elasticsearch_domain_plugin:ElasticsearchDomainProviderPlugin", "AWS::EC2::VPCEndpoint=localstack.services.ec2.resource_providers.aws_ec2_vpcendpoint_plugin:EC2VPCEndpointProviderPlugin", "AWS::ResourceGroups::Group=localstack.services.resource_groups.resource_providers.aws_resourcegroups_group_plugin:ResourceGroupsGroupProviderPlugin", "AWS::EC2::InternetGateway=localstack.services.ec2.resource_providers.aws_ec2_internetgateway_plugin:EC2InternetGatewayProviderPlugin", "AWS::CloudWatch::Alarm=localstack.services.cloudwatch.resource_providers.aws_cloudwatch_alarm_plugin:CloudWatchAlarmProviderPlugin", "AWS::StepFunctions::Activity=localstack.services.stepfunctions.resource_providers.aws_stepfunctions_activity_plugin:StepFunctionsActivityProviderPlugin", "AWS::EC2::TransitGateway=localstack.services.ec2.resource_providers.aws_ec2_transitgateway_plugin:EC2TransitGatewayProviderPlugin", "AWS::ApiGateway::GatewayResponse=localstack.services.apigateway.resource_providers.aws_apigateway_gatewayresponse_plugin:ApiGatewayGatewayResponseProviderPlugin", "AWS::Redshift::Cluster=localstack.services.redshift.resource_providers.aws_redshift_cluster_plugin:RedshiftClusterProviderPlugin", "AWS::Scheduler::Schedule=localstack.services.scheduler.resource_providers.aws_scheduler_schedule_plugin:SchedulerScheduleProviderPlugin", "AWS::OpenSearchService::Domain=localstack.services.opensearch.resource_providers.aws_opensearchservice_domain_plugin:OpenSearchServiceDomainProviderPlugin", "AWS::Kinesis::Stream=localstack.services.kinesis.resource_providers.aws_kinesis_stream_plugin:KinesisStreamProviderPlugin", "AWS::StepFunctions::StateMachine=localstack.services.stepfunctions.resource_providers.aws_stepfunctions_statemachine_plugin:StepFunctionsStateMachineProviderPlugin", "AWS::SSM::MaintenanceWindow=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindow_plugin:SSMMaintenanceWindowProviderPlugin", "AWS::SecretsManager::ResourcePolicy=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_resourcepolicy_plugin:SecretsManagerResourcePolicyProviderPlugin", "AWS::SES::EmailIdentity=localstack.services.ses.resource_providers.aws_ses_emailidentity_plugin:SESEmailIdentityProviderPlugin", "AWS::Events::EventBusPolicy=localstack.services.events.resource_providers.aws_events_eventbuspolicy_plugin:EventsEventBusPolicyProviderPlugin", "AWS::IAM::InstanceProfile=localstack.services.iam.resource_providers.aws_iam_instanceprofile_plugin:IAMInstanceProfileProviderPlugin", "AWS::CloudFormation::WaitCondition=localstack.services.cloudformation.resource_providers.aws_cloudformation_waitcondition_plugin:CloudFormationWaitConditionProviderPlugin", "AWS::EC2::NatGateway=localstack.services.ec2.resource_providers.aws_ec2_natgateway_plugin:EC2NatGatewayProviderPlugin", "AWS::Lambda::Permission=localstack.services.lambda_.resource_providers.aws_lambda_permission_plugin:LambdaPermissionProviderPlugin", "AWS::SecretsManager::Secret=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_secret_plugin:SecretsManagerSecretProviderPlugin", "AWS::EC2::VPC=localstack.services.ec2.resource_providers.aws_ec2_vpc_plugin:EC2VPCProviderPlugin", "AWS::Logs::LogStream=localstack.services.logs.resource_providers.aws_logs_logstream_plugin:LogsLogStreamProviderPlugin", "AWS::ApiGateway::UsagePlan=localstack.services.apigateway.resource_providers.aws_apigateway_usageplan_plugin:ApiGatewayUsagePlanProviderPlugin", "AWS::ApiGateway::BasePathMapping=localstack.services.apigateway.resource_providers.aws_apigateway_basepathmapping_plugin:ApiGatewayBasePathMappingProviderPlugin", "AWS::Route53::RecordSet=localstack.services.route53.resource_providers.aws_route53_recordset_plugin:Route53RecordSetProviderPlugin", "AWS::IAM::Group=localstack.services.iam.resource_providers.aws_iam_group_plugin:IAMGroupProviderPlugin", "AWS::EC2::Subnet=localstack.services.ec2.resource_providers.aws_ec2_subnet_plugin:EC2SubnetProviderPlugin", "AWS::ApiGateway::Resource=localstack.services.apigateway.resource_providers.aws_apigateway_resource_plugin:ApiGatewayResourceProviderPlugin", "AWS::EC2::RouteTable=localstack.services.ec2.resource_providers.aws_ec2_routetable_plugin:EC2RouteTableProviderPlugin", "AWS::SQS::Queue=localstack.services.sqs.resource_providers.aws_sqs_queue_plugin:SQSQueueProviderPlugin", "AWS::EC2::SubnetRouteTableAssociation=localstack.services.ec2.resource_providers.aws_ec2_subnetroutetableassociation_plugin:EC2SubnetRouteTableAssociationProviderPlugin", "AWS::ApiGateway::UsagePlanKey=localstack.services.apigateway.resource_providers.aws_apigateway_usageplankey_plugin:ApiGatewayUsagePlanKeyProviderPlugin", "AWS::CloudFormation::Macro=localstack.services.cloudformation.resource_providers.aws_cloudformation_macro_plugin:CloudFormationMacroProviderPlugin", "AWS::ApiGateway::Model=localstack.services.apigateway.resource_providers.aws_apigateway_model_plugin:ApiGatewayModelProviderPlugin", "AWS::Scheduler::ScheduleGroup=localstack.services.scheduler.resource_providers.aws_scheduler_schedulegroup_plugin:SchedulerScheduleGroupProviderPlugin", "AWS::SecretsManager::RotationSchedule=localstack.services.secretsmanager.resource_providers.aws_secretsmanager_rotationschedule_plugin:SecretsManagerRotationScheduleProviderPlugin", "AWS::ApiGateway::RequestValidator=localstack.services.apigateway.resource_providers.aws_apigateway_requestvalidator_plugin:ApiGatewayRequestValidatorProviderPlugin", "AWS::IAM::Policy=localstack.services.iam.resource_providers.aws_iam_policy_plugin:IAMPolicyProviderPlugin", "AWS::EC2::Route=localstack.services.ec2.resource_providers.aws_ec2_route_plugin:EC2RouteProviderPlugin", "AWS::SSM::MaintenanceWindowTarget=localstack.services.ssm.resource_providers.aws_ssm_maintenancewindowtarget_plugin:SSMMaintenanceWindowTargetProviderPlugin", "AWS::CDK::Metadata=localstack.services.cdk.resource_providers.cdk_metadata_plugin:LambdaAliasProviderPlugin", "AWS::Lambda::Version=localstack.services.lambda_.resource_providers.aws_lambda_version_plugin:LambdaVersionProviderPlugin", "AWS::CloudFormation::WaitConditionHandle=localstack.services.cloudformation.resource_providers.aws_cloudformation_waitconditionhandle_plugin:CloudFormationWaitConditionHandleProviderPlugin", "AWS::EC2::SecurityGroup=localstack.services.ec2.resource_providers.aws_ec2_securitygroup_plugin:EC2SecurityGroupProviderPlugin", "AWS::SNS::Subscription=localstack.services.sns.resource_providers.aws_sns_subscription_plugin:SNSSubscriptionProviderPlugin", "AWS::EC2::NetworkAcl=localstack.services.ec2.resource_providers.aws_ec2_networkacl_plugin:EC2NetworkAclProviderPlugin", "AWS::CertificateManager::Certificate=localstack.services.certificatemanager.resource_providers.aws_certificatemanager_certificate_plugin:CertificateManagerCertificateProviderPlugin", "AWS::CloudFormation::Stack=localstack.services.cloudformation.resource_providers.aws_cloudformation_stack_plugin:CloudFormationStackProviderPlugin", "AWS::ApiGateway::RestApi=localstack.services.apigateway.resource_providers.aws_apigateway_restapi_plugin:ApiGatewayRestApiProviderPlugin", "AWS::IAM::ServiceLinkedRole=localstack.services.iam.resource_providers.aws_iam_servicelinkedrole_plugin:IAMServiceLinkedRoleProviderPlugin", "AWS::Lambda::EventInvokeConfig=localstack.services.lambda_.resource_providers.aws_lambda_eventinvokeconfig_plugin:LambdaEventInvokeConfigProviderPlugin", "AWS::Lambda::CodeSigningConfig=localstack.services.lambda_.resource_providers.aws_lambda_codesigningconfig_plugin:LambdaCodeSigningConfigProviderPlugin", "AWS::Lambda::EventSourceMapping=localstack.services.lambda_.resource_providers.aws_lambda_eventsourcemapping_plugin:LambdaEventSourceMappingProviderPlugin", "AWS::EC2::KeyPair=localstack.services.ec2.resource_providers.aws_ec2_keypair_plugin:EC2KeyPairProviderPlugin"], "localstack.packages": ["kinesis-mock/community=localstack.services.kinesis.plugins:kinesismock_package", "jpype-jsonata/community=localstack.services.stepfunctions.plugins:jpype_jsonata_package", "dynamodb-local/community=localstack.services.dynamodb.plugins:dynamodb_local_package", "lambda-java-libs/community=localstack.services.lambda_.plugins:lambda_java_libs", "lambda-runtime/community=localstack.services.lambda_.plugins:lambda_runtime_package", "vosk/community=localstack.services.transcribe.plugins:vosk_package", "elasticsearch/community=localstack.services.es.plugins:elasticsearch_package", "opensearch/community=localstack.services.opensearch.plugins:opensearch_package", "ffmpeg/community=localstack.packages.plugins:ffmpeg_package", "java/community=localstack.packages.plugins:java_package"], "localstack.hooks.on_infra_start": ["_publish_config_as_analytics_event=localstack.runtime.analytics:_publish_config_as_analytics_event", "_publish_container_info=localstack.runtime.analytics:_publish_container_info", "register_cloudformation_deploy_ui=localstack.services.cloudformation.plugins:register_cloudformation_deploy_ui", "apply_runtime_patches=localstack.runtime.patches:apply_runtime_patches", "register_custom_endpoints=localstack.services.lambda_.plugins:register_custom_endpoints", "validate_configuration=localstack.services.lambda_.plugins:validate_configuration", "register_swagger_endpoints=localstack.http.resources.swagger.plugins:register_swagger_endpoints", "setup_dns_configuration_on_host=localstack.dns.plugins:setup_dns_configuration_on_host", "start_dns_server=localstack.dns.plugins:start_dns_server", "_run_init_scripts_on_start=localstack.runtime.init:_run_init_scripts_on_start", "_patch_botocore_endpoint_in_memory=localstack.aws.client:_patch_botocore_endpoint_in_memory", "_patch_botocore_json_parser=localstack.aws.client:_patch_botocore_json_parser", "_patch_cbor2=localstack.aws.client:_patch_cbor2", "init_response_mutation_handler=localstack.aws.handlers.response:init_response_mutation_handler", "conditionally_enable_debugger=localstack.dev.debugger.plugins:conditionally_enable_debugger", "apply_aws_runtime_patches=localstack.aws.patches:apply_aws_runtime_patches", "eager_load_services=localstack.services.plugins:eager_load_services", "delete_cached_certificate=localstack.plugins:delete_cached_certificate", "deprecation_warnings=localstack.plugins:deprecation_warnings"], "localstack.hooks.on_infra_shutdown": ["remove_custom_endpoints=localstack.services.lambda_.plugins:remove_custom_endpoints", "publish_metrics=localstack.utils.analytics.metrics.publisher:publish_metrics", "run_on_after_service_shutdown_handlers=localstack.runtime.shutdown:run_on_after_service_shutdown_handlers", "run_shutdown_handlers=localstack.runtime.shutdown:run_shutdown_handlers", "shutdown_services=localstack.runtime.shutdown:shutdown_services", "stop_server=localstack.dns.plugins:stop_server", "_run_init_scripts_on_shutdown=localstack.runtime.init:_run_init_scripts_on_shutdown"], "localstack.lambda.runtime_executor": ["docker=localstack.services.lambda_.invocation.plugins:DockerRuntimeExecutorPlugin"], "localstack.hooks.configure_localstack_container": ["_mount_machine_file=localstack.utils.analytics.metadata:_mount_machine_file"], "localstack.hooks.prepare_host": ["prepare_host_machine_id=localstack.utils.analytics.metadata:prepare_host_machine_id"], "localstack.hooks.on_infra_ready": ["publish_provider_assignment=localstack.utils.analytics.service_providers:publish_provider_assignment", "_run_init_scripts_on_ready=localstack.runtime.init:_run_init_scripts_on_ready"], "localstack.init.runner": ["py=localstack.runtime.init:PythonScriptRunner", "sh=localstack.runtime.init:ShellScriptRunner"], "localstack.utils.catalog": ["aws-catalog-remote-state=localstack.utils.catalog.catalog:AwsCatalogRemoteStatePlugin", "aws-catalog-runtime-only=localstack.utils.catalog.catalog:AwsCatalogRuntimePlugin"], "localstack.aws.provider": ["acm:default=localstack.services.providers:acm", "apigateway:default=localstack.services.providers:apigateway", "apigateway:legacy=localstack.services.providers:apigateway_legacy", "apigateway:next_gen=localstack.services.providers:apigateway_next_gen", "config:default=localstack.services.providers:awsconfig", "cloudformation:engine-legacy=localstack.services.providers:cloudformation", "cloudformation:default=localstack.services.providers:cloudformation_v2", "cloudwatch:default=localstack.services.providers:cloudwatch", "cloudwatch:v1=localstack.services.providers:cloudwatch_v1", "cloudwatch:v2=localstack.services.providers:cloudwatch_v2", "dynamodb:default=localstack.services.providers:dynamodb", "dynamodb:v2=localstack.services.providers:dynamodb_v2", "dynamodbstreams:default=localstack.services.providers:dynamodbstreams", "dynamodbstreams:v2=localstack.services.providers:dynamodbstreams_v2", "ec2:default=localstack.services.providers:ec2", "es:default=localstack.services.providers:es", "events:default=localstack.services.providers:events", "events:legacy=localstack.services.providers:events_legacy", "events:v1=localstack.services.providers:events_v1", "events:v2=localstack.services.providers:events_v2", "firehose:default=localstack.services.providers:firehose", "iam:default=localstack.services.providers:iam", "kinesis:default=localstack.services.providers:kinesis", "kms:default=localstack.services.providers:kms", "lambda:default=localstack.services.providers:lambda_", "lambda:asf=localstack.services.providers:lambda_asf", "lambda:v2=localstack.services.providers:lambda_v2", "logs:default=localstack.services.providers:logs", "opensearch:default=localstack.services.providers:opensearch", "redshift:default=localstack.services.providers:redshift", "resource-groups:default=localstack.services.providers:resource_groups", "resourcegroupstaggingapi:default=localstack.services.providers:resourcegroupstaggingapi", "route53:default=localstack.services.providers:route53", "route53resolver:default=localstack.services.providers:route53resolver", "s3:default=localstack.services.providers:s3", "s3control:default=localstack.services.providers:s3control", "scheduler:default=localstack.services.providers:scheduler", "secretsmanager:default=localstack.services.providers:secretsmanager", "ses:default=localstack.services.providers:ses", "sns:default=localstack.services.providers:sns", "sns:v2=localstack.services.providers:sns_v2", "sqs:default=localstack.services.providers:sqs", "ssm:default=localstack.services.providers:ssm", "stepfunctions:default=localstack.services.providers:stepfunctions", "stepfunctions:v2=localstack.services.providers:stepfunctions_v2", "sts:default=localstack.services.providers:sts", "support:default=localstack.services.providers:support", "swf:default=localstack.services.providers:swf", "transcribe:default=localstack.services.providers:transcribe"], "localstack.openapi.spec": ["localstack=localstack.plugins:CoreOASPlugin"], "localstack.runtime.components": ["aws=localstack.aws.components:AwsComponents"], "localstack.runtime.server": ["hypercorn=localstack.runtime.server.plugins:HypercornRuntimeServerPlugin", "twisted=localstack.runtime.server.plugins:TwistedRuntimeServerPlugin"]}