localstack 4.14.0__tar.gz → 2026.4.0__tar.gz

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.
Files changed (148) hide show
  1. {localstack-4.14.0 → localstack-2026.4.0}/.github/workflows/tests-cli.yml +3 -4
  2. {localstack-4.14.0/localstack.egg-info → localstack-2026.4.0}/PKG-INFO +1 -1
  3. {localstack-4.14.0 → localstack-2026.4.0/localstack.egg-info}/PKG-INFO +1 -1
  4. {localstack-4.14.0 → localstack-2026.4.0}/localstack.egg-info/SOURCES.txt +1 -0
  5. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/cli/localstack.py +0 -10
  6. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/constants.py +1 -2
  7. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/licensingv2.py +1 -1
  8. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/replicator.py +12 -2
  9. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/config.py +4 -13
  10. localstack-2026.4.0/localstack_cli/pro/core/plugins.py +181 -0
  11. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/bootstrap.py +2 -7
  12. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/container_networking.py +1 -1
  13. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/container_utils/docker_cmd_client.py +2 -2
  14. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/docker_utils.py +2 -2
  15. localstack-2026.4.0/localstack_cli/version.py +24 -0
  16. {localstack-4.14.0 → localstack-2026.4.0}/tests/cli/test_cli.py +6 -29
  17. {localstack-4.14.0 → localstack-2026.4.0}/tests/cli/test_cli_pro.py +0 -24
  18. {localstack-4.14.0 → localstack-2026.4.0}/tests/integration/cli/test_cli.py +1 -1
  19. localstack-2026.4.0/tests/unit/pro/test_grace_period.py +101 -0
  20. localstack-4.14.0/localstack_cli/pro/core/plugins.py +0 -81
  21. localstack-4.14.0/localstack_cli/version.py +0 -34
  22. {localstack-4.14.0 → localstack-2026.4.0}/.gitignore +0 -0
  23. {localstack-4.14.0 → localstack-2026.4.0}/Makefile +0 -0
  24. {localstack-4.14.0 → localstack-2026.4.0}/README.md +0 -0
  25. {localstack-4.14.0 → localstack-2026.4.0}/bin/localstack +0 -0
  26. {localstack-4.14.0 → localstack-2026.4.0}/localstack.egg-info/dependency_links.txt +0 -0
  27. {localstack-4.14.0 → localstack-2026.4.0}/localstack.egg-info/entry_points.txt +0 -0
  28. {localstack-4.14.0 → localstack-2026.4.0}/localstack.egg-info/requires.txt +0 -0
  29. {localstack-4.14.0 → localstack-2026.4.0}/localstack.egg-info/top_level.txt +0 -0
  30. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/__init__.py +0 -0
  31. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/cli/__init__.py +0 -0
  32. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/cli/console.py +0 -0
  33. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/cli/core_plugin.py +0 -0
  34. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/cli/exceptions.py +0 -0
  35. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/cli/lpm.py +0 -0
  36. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/cli/main.py +0 -0
  37. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/cli/plugin.py +0 -0
  38. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/cli/plugins.py +0 -0
  39. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/cli/profiles.py +0 -0
  40. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/config.py +0 -0
  41. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/logging/__init__.py +0 -0
  42. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/logging/format.py +0 -0
  43. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/logging/setup.py +0 -0
  44. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/packages/__init__.py +0 -0
  45. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/packages/api.py +0 -0
  46. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/packages/core.py +0 -0
  47. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/__init__.py +0 -0
  48. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/__init__.py +0 -0
  49. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/__init__.py +0 -0
  50. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/auth.py +0 -0
  51. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/dns_utils.py +0 -0
  52. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/entitlements.py +0 -0
  53. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/extensions/__init__.py +0 -0
  54. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/extensions/__main__.py +0 -0
  55. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/extensions/autoinstall.py +0 -0
  56. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/extensions/bootstrap.py +0 -0
  57. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/extensions/repository.py +0 -0
  58. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/pods/__init__.py +0 -0
  59. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/pods/api_types.py +0 -0
  60. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/pods/constants.py +0 -0
  61. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/pods/remotes/__init__.py +0 -0
  62. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/pods/remotes/api.py +0 -0
  63. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/pods/remotes/configs.py +0 -0
  64. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/pods/remotes/params.py +0 -0
  65. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/bootstrap/pods_client.py +0 -0
  66. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/__init__.py +0 -0
  67. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/auth.py +0 -0
  68. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/aws.py +0 -0
  69. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/cli.py +0 -0
  70. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/click_utils.py +0 -0
  71. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/cloud_pods.py +0 -0
  72. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/diff_view.py +0 -0
  73. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/ephemeral.py +0 -0
  74. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/extensions.py +0 -0
  75. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/iam.py +0 -0
  76. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/license.py +0 -0
  77. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/localstack.py +0 -0
  78. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/state.py +0 -0
  79. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/cli/tree_view.py +0 -0
  80. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/pro/core/constants.py +0 -0
  81. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/runtime/__init__.py +0 -0
  82. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/runtime/exceptions.py +0 -0
  83. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/runtime/hooks.py +0 -0
  84. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/testing/__init__.py +0 -0
  85. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/testing/config.py +0 -0
  86. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/__init__.py +0 -0
  87. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/analytics/__init__.py +0 -0
  88. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/analytics/cli.py +0 -0
  89. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/analytics/client.py +0 -0
  90. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/analytics/events.py +0 -0
  91. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/analytics/logger.py +0 -0
  92. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/analytics/metadata.py +0 -0
  93. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/analytics/publisher.py +0 -0
  94. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/analytics/service_request_aggregator.py +0 -0
  95. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/archives.py +0 -0
  96. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/batching.py +0 -0
  97. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/checksum.py +0 -0
  98. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/collections.py +0 -0
  99. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/common.py +0 -0
  100. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/container_utils/__init__.py +0 -0
  101. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/container_utils/container_client.py +0 -0
  102. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/container_utils/docker_sdk_client.py +0 -0
  103. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/crypto.py +0 -0
  104. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/files.py +0 -0
  105. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/functions.py +0 -0
  106. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/http.py +0 -0
  107. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/json.py +0 -0
  108. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/net.py +0 -0
  109. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/no_exit_argument_parser.py +0 -0
  110. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/numbers.py +0 -0
  111. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/objects.py +0 -0
  112. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/patch.py +0 -0
  113. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/platform.py +0 -0
  114. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/run.py +0 -0
  115. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/server/__init__.py +0 -0
  116. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/server/tcp_proxy.py +0 -0
  117. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/serving.py +0 -0
  118. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/ssl.py +0 -0
  119. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/strings.py +0 -0
  120. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/sync.py +0 -0
  121. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/threads.py +0 -0
  122. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/time.py +0 -0
  123. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/urls.py +0 -0
  124. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/venv.py +0 -0
  125. {localstack-4.14.0 → localstack-2026.4.0}/localstack_cli/utils/xml.py +0 -0
  126. {localstack-4.14.0 → localstack-2026.4.0}/plux.ini +0 -0
  127. {localstack-4.14.0 → localstack-2026.4.0}/pyproject.toml +0 -0
  128. {localstack-4.14.0 → localstack-2026.4.0}/setup.cfg +0 -0
  129. {localstack-4.14.0 → localstack-2026.4.0}/tests/__init__.py +0 -0
  130. {localstack-4.14.0 → localstack-2026.4.0}/tests/bootstrap/__init__.py +0 -0
  131. {localstack-4.14.0 → localstack-2026.4.0}/tests/bootstrap/extensions/__init__.py +0 -0
  132. {localstack-4.14.0 → localstack-2026.4.0}/tests/bootstrap/extensions/test_extension_install.py +0 -0
  133. {localstack-4.14.0 → localstack-2026.4.0}/tests/cli/__init__.py +0 -0
  134. {localstack-4.14.0 → localstack-2026.4.0}/tests/cli/conftest.py +0 -0
  135. {localstack-4.14.0 → localstack-2026.4.0}/tests/conftest.py +0 -0
  136. {localstack-4.14.0 → localstack-2026.4.0}/tests/integration/__init__.py +0 -0
  137. {localstack-4.14.0 → localstack-2026.4.0}/tests/integration/cli/__init__.py +0 -0
  138. {localstack-4.14.0 → localstack-2026.4.0}/tests/integration/cli/test_lpm.py +0 -0
  139. {localstack-4.14.0 → localstack-2026.4.0}/tests/integration/replicator/__init__.py +0 -0
  140. {localstack-4.14.0 → localstack-2026.4.0}/tests/integration/replicator/core/__init__.py +0 -0
  141. {localstack-4.14.0 → localstack-2026.4.0}/tests/integration/replicator/core/test_replicator_cli.py +0 -0
  142. {localstack-4.14.0 → localstack-2026.4.0}/tests/unit/__init__.py +0 -0
  143. {localstack-4.14.0 → localstack-2026.4.0}/tests/unit/cli/__init__.py +0 -0
  144. {localstack-4.14.0 → localstack-2026.4.0}/tests/unit/cli/test_profiles.py +0 -0
  145. {localstack-4.14.0 → localstack-2026.4.0}/tests/unit/pro/__init__.py +0 -0
  146. {localstack-4.14.0 → localstack-2026.4.0}/tests/unit/pro/test_cli.py +0 -0
  147. {localstack-4.14.0 → localstack-2026.4.0}/tests/unit/replicator/__init__.py +0 -0
  148. {localstack-4.14.0 → localstack-2026.4.0}/tests/unit/replicator/test_profile_loading.py +0 -0
@@ -64,8 +64,7 @@ jobs:
64
64
 
65
65
  - name: Pull Docker images
66
66
  run: |
67
- docker pull localstack/localstack-pro || true
68
- docker pull localstack/localstack
67
+ docker pull localstack/localstack-pro
69
68
 
70
69
  - name: Install dependencies
71
70
  run: |
@@ -82,7 +81,7 @@ jobs:
82
81
 
83
82
  - name: Run CLI tests
84
83
  env:
85
- LOCALSTACK_AUTH_TOKEN: ${{ secrets.TEST_LOCALSTACK_AUTH_TOKEN }}
84
+ LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
86
85
  run: |
87
86
  python -m pytest tests/cli/ \
88
87
  --log-cli-level=${{ env.PYTEST_LOGLEVEL }} \
@@ -90,7 +89,7 @@ jobs:
90
89
 
91
90
  - name: Run unit tests
92
91
  env:
93
- LOCALSTACK_AUTH_TOKEN: ${{ secrets.TEST_LOCALSTACK_AUTH_TOKEN }}
92
+ LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
94
93
  run: |
95
94
  python -m pytest tests/unit/ \
96
95
  --log-cli-level=${{ env.PYTEST_LOGLEVEL }} \
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: localstack
3
- Version: 4.14.0
3
+ Version: 2026.4.0
4
4
  Summary: The LocalStack Command Line Interface
5
5
  Author-email: LocalStack Contributors <info@localstack.cloud>
6
6
  License-Expression: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: localstack
3
- Version: 4.14.0
3
+ Version: 2026.4.0
4
4
  Summary: The LocalStack Command Line Interface
5
5
  Author-email: LocalStack Contributors <info@localstack.cloud>
6
6
  License-Expression: Apache-2.0
@@ -245,5 +245,6 @@ tests/unit/cli/__init__.py
245
245
  tests/unit/cli/test_profiles.py
246
246
  tests/unit/pro/__init__.py
247
247
  tests/unit/pro/test_cli.py
248
+ tests/unit/pro/test_grace_period.py
248
249
  tests/unit/replicator/__init__.py
249
250
  tests/unit/replicator/test_profile_loading.py
@@ -523,16 +523,6 @@ def cmd_start(
523
523
  print_app()
524
524
  console.line()
525
525
 
526
- # check if we are about to activate Pro, if not raise a warning about the upcoming changes
527
- # LOCALSTACK_ACTIVATE_PRO is set by the Pro config if the auth token is cached or explicitly set in the env
528
- if not config.is_env_true("LOCALSTACK_ACTIVATE_PRO"):
529
- console.log(
530
- "Warning: You are starting LocalStack without an auth token. "
531
- "Starting in March 2026, LocalStack will require an auth token. "
532
- "Go to this page for more infos: https://localstack.cloud/2026-updates",
533
- style="bold red",
534
- )
535
-
536
526
  from localstack_cli.utils import bootstrap
537
527
 
538
528
  if not no_banner:
@@ -64,9 +64,7 @@ DEFAULT_VOLUME_DIR = "/var/lib/localstack"
64
64
  PATH_USER_REQUEST = "_user_request_"
65
65
 
66
66
  # name of LocalStack Docker image
67
- DOCKER_IMAGE_NAME = "localstack/localstack"
68
67
  DOCKER_IMAGE_NAME_PRO = "localstack/localstack-pro"
69
- DOCKER_IMAGE_NAME_FULL = "localstack/localstack-full"
70
68
 
71
69
  # backdoor API path used to retrieve or update config variables
72
70
  CONFIG_UPDATE_PATH = "/?_config_"
@@ -142,6 +140,7 @@ TRACE_LOG_LEVELS = [LS_LOG_TRACE, LS_LOG_TRACE_INTERNAL]
142
140
  OFFICIAL_IMAGES = [
143
141
  "localstack/localstack",
144
142
  "localstack/localstack-pro",
143
+ "localstack/snowflake"
145
144
  ]
146
145
 
147
146
  # port for debug py
@@ -69,7 +69,7 @@ class LicensingError(Exception):
69
69
 
70
70
  - Please check that your credentials are set up correctly and that you have an active license.
71
71
  You can find your credentials in our webapp at https://app.localstack.cloud.
72
- - If you want to continue using LocalStack without pro features you can set `ACTIVATE_PRO=0`.
72
+ - If you want to continue using LocalStack without pro features, set `LOCALSTACK_ACKNOWLEDGE_ACCOUNT_REQUIREMENT=1` during the grace period.
73
73
  """
74
74
  )
75
75
 
@@ -11,6 +11,7 @@ from typing import TypedDict
11
11
 
12
12
  import click
13
13
  import requests
14
+
14
15
  from localstack_cli import config
15
16
  from localstack_cli.cli import console
16
17
  from localstack_cli.cli.exceptions import CLIError
@@ -255,10 +256,17 @@ At the moment only environment variables are recognized.
255
256
  )
256
257
  @click.option(
257
258
  "--replication-type",
258
- type=click.Choice(["MOCK", "SINGLE_RESOURCE", "BATCH"]),
259
+ type=click.Choice(["SINGLE_RESOURCE", "BATCH"]),
259
260
  default="SINGLE_RESOURCE",
260
261
  show_default=True,
261
- help="Type of replication job: MOCK, SINGLE_RESOURCE, BATCH",
262
+ help="Type of replication job: SINGLE_RESOURCE, BATCH",
263
+ )
264
+ @click.option(
265
+ "--explore-strategy",
266
+ type=click.Choice(["SIMPLE", "TREE"]),
267
+ default="SIMPLE",
268
+ show_default=True,
269
+ help="How we explore the resource tree. SIMPLE only replicates the resource requested.",
262
270
  )
263
271
  @click.option(
264
272
  "--resource-arn",
@@ -285,6 +293,7 @@ At the moment only environment variables are recognized.
285
293
  @click.option("--delay", help="Delay for the MOCK replication work")
286
294
  def start(
287
295
  replication_type: str,
296
+ explore_strategy: str,
288
297
  resource_arn: str | None = None,
289
298
  resource_type: str | None = None,
290
299
  resource_identifier: str | None = None,
@@ -314,6 +323,7 @@ def start(
314
323
 
315
324
  payload = {
316
325
  "replication_type": replication_type,
326
+ "explore_strategy": explore_strategy,
317
327
  "replication_job_config": replication_config,
318
328
  "source_aws_config": source_config,
319
329
  "target_aws_config": target_config,
@@ -368,10 +368,9 @@ def is_auth_token_configured() -> bool:
368
368
  return False
369
369
 
370
370
 
371
- # whether pro should be activated or not. this is set to true by default if using the pro image. if set to
372
- # true, localstack will fail to start if the key activation did not work. if set to false, then we will make
373
- # an attempt to start localstack community.
374
- ACTIVATE_PRO = localstack_config.is_env_not_false("ACTIVATE_PRO")
371
+ # pro plugins should always run. If license activation failed this will be set to false to avoid loading
372
+ # pro plugins after that.
373
+ ACTIVATE_PRO = True
375
374
 
376
375
  # a comma-separated list of cloud pods to be automatically loaded at startup
377
376
  AUTO_LOAD_POD = os.environ.get("AUTO_LOAD_POD", "")
@@ -394,14 +393,6 @@ ENABLE_POD_RESOURCES = is_env_true("ENABLE_POD_RESOURCES")
394
393
  # set of Cloud Pods.
395
394
  CLI_INJECT_POD_IDENTITY = localstack_config.is_env_not_false("CLI_INJECT_POD_IDENTITY")
396
395
 
397
- if is_env_true("LOCALSTACK_CLI"):
398
- # when we're in the CLI, we only want to activate pro code if an API key is set. this is because we are
399
- # always loading localstack/pro/core/config.py in the CLI, and we would otherwise always have ACTIVATE_PRO=1
400
- # when running `localstack start`.
401
- ACTIVATE_PRO = ACTIVATE_PRO and is_auth_token_configured()
402
- # we also need to update the environment so `ACTIVATE_PRO` is disabled in the container
403
- os.environ["LOCALSTACK_ACTIVATE_PRO"] = "1" if ACTIVATE_PRO else "0"
404
-
405
396
  # backend service ports
406
397
  DEFAULT_PORT_LOCAL_DAEMON = 4600
407
398
  DEFAULT_PORT_LOCAL_DAEMON_ROOT = 4601
@@ -471,8 +462,8 @@ APPINSPECTOR_ENABLE = is_env_true("APPINSPECTOR_ENABLE")
471
462
 
472
463
  # update variable names that need to be passed as arguments to Docker
473
464
  localstack_config.CONFIG_ENV_VARS += [
474
- "ACTIVATE_PRO",
475
465
  "APPSYNC_JS_LIBS_VERSION",
466
+ "ACKNOWLEDGE_ACCOUNT_REQUIREMENT",
476
467
  "APIGW_ENABLE_NEXT_GEN_WEBSOCKETS",
477
468
  "APIGW_ENABLE_NEXT_GEN_WEBSOCKETS_INVOCATION",
478
469
  "AUTO_LOAD_POD",
@@ -0,0 +1,181 @@
1
+ """
2
+ Pro plugin hooks for the LocalStack CLI.
3
+
4
+ These hooks are executed on the host machine when running CLI commands like `localstack start`.
5
+ They handle license activation, container configuration, and extension developer mode.
6
+
7
+ Note: This file was extracted from localstack-pro-core/localstack/pro/core/plugins.py
8
+ and rewritten to contain only CLI-relevant functionality.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import logging
14
+ import os
15
+
16
+ import requests
17
+ from localstack_cli import config as localstack_config
18
+ from localstack_cli.config import HostAndPort
19
+ from localstack_cli.constants import API_ENDPOINT
20
+ from localstack_cli.pro.core import config as pro_config
21
+ from localstack_cli.pro.core.bootstrap import licensingv2
22
+ from localstack_cli.runtime import hooks
23
+ from localstack_cli.runtime.exceptions import LocalstackExit
24
+ from localstack_cli.utils.bootstrap import Container
25
+
26
+ LOG = logging.getLogger(__name__)
27
+
28
+
29
+ def modify_gateway_listen_config(cfg):
30
+ """
31
+ Modifies the localstack config to additionally listen to port 443.
32
+ Needs to be called before any edge URLs are resolved using the config.
33
+ """
34
+ if os.getenv("GATEWAY_LISTEN") is None:
35
+ host = "0.0.0.0" if localstack_config.in_docker() else "127.0.0.1"
36
+ cfg.GATEWAY_LISTEN.append(HostAndPort(host=host, port=443))
37
+
38
+
39
+ @hooks.prepare_host(priority=200)
40
+ def patch_community_pro_detection():
41
+ """This is currently needed to make localstack core aware of the `localstack auth set-token`
42
+ functionality, where we set the key into the ``~/.localstack/auth.json`` file that community does not
43
+ yet know about. ``is_api_key_configured`` is used in the LocalStack CLI to determine whether to start
44
+ the localstack or localstack-pro container image."""
45
+ from localstack_cli.utils import bootstrap
46
+
47
+ bootstrap.is_auth_token_configured = pro_config.is_auth_token_configured
48
+
49
+
50
+ ## ---------------------------------------------------------------------------
51
+ ## Grace period helpers (temporary, to be removed once grace period expires)
52
+ ## ---------------------------------------------------------------------------
53
+
54
+ GRACE_PERIOD_ENDPOINT_PATH = "/license/grace-period-check"
55
+
56
+ LICENSE_ERROR_MESSAGE = """\
57
+ ===============================================
58
+ LocalStack requires an account to run.
59
+
60
+ ==> Have an account? Learn how to set LOCALSTACK_AUTH_TOKEN: https://app.localstack.cloud/settings/auth-tokens
61
+ ==> Need an account? Get started: https://www.localstack.cloud/pricing
62
+ ==> Want more time? Snooze until April 6, 2026 by setting LOCALSTACK_ACKNOWLEDGE_ACCOUNT_REQUIREMENT=1
63
+ """
64
+
65
+ GRACE_PERIOD_EXPIRED_MESSAGE = """\
66
+ ===============================================
67
+ LocalStack requires an account to run.
68
+
69
+ ==> Have an account? Learn how to set LOCALSTACK_AUTH_TOKEN: https://app.localstack.cloud/settings/auth-tokens
70
+ ==> Need an account? Get started: https://www.localstack.cloud/pricing
71
+ """
72
+
73
+
74
+ def _check_grace_period_active(ack: bool) -> bool:
75
+ """Call the platform grace period endpoint.
76
+
77
+ Returns True if the grace period is active (200 response).
78
+ Returns False for any other response (including 404 when the endpoint is removed).
79
+ """
80
+ from localstack_cli.pro.core.bootstrap.licensingv2 import get_system_information_summary
81
+ from localstack_cli.pro.core.constants import VERSION
82
+ from localstack_cli.utils.analytics.metadata import get_client_metadata
83
+ from localstack_cli.utils.http import get_proxies
84
+
85
+ metadata = get_client_metadata()
86
+ payload = {
87
+ "machine": {
88
+ "id": metadata.machine_id,
89
+ "ci": metadata.is_ci,
90
+ "system": get_system_information_summary(),
91
+ },
92
+ "version": VERSION,
93
+ "requesting_grace": ack,
94
+ }
95
+
96
+ url = f"{API_ENDPOINT}{GRACE_PERIOD_ENDPOINT_PATH}"
97
+ proxies = get_proxies()
98
+
99
+ try:
100
+ response = requests.post(
101
+ url,
102
+ json=payload,
103
+ verify=not localstack_config.is_env_true("SSL_NO_VERIFY"),
104
+ proxies=proxies,
105
+ timeout=10,
106
+ )
107
+ return response.ok
108
+ except requests.exceptions.RequestException:
109
+ LOG.debug("Failed to reach grace period endpoint at %s", url)
110
+ return False
111
+
112
+
113
+ ## ---------------------------------------------------------------------------
114
+
115
+
116
+ @hooks.prepare_host(priority=100, should_load=pro_config.ACTIVATE_PRO)
117
+ def activate_pro_key_on_host():
118
+ """Activate license on host (needed for DNS forward and EC2 daemon)."""
119
+ from localstack_cli.constants import OFFICIAL_IMAGES
120
+ from localstack_cli.utils.bootstrap import get_docker_image_to_start
121
+
122
+ image_name = get_docker_image_to_start().split(":")[0]
123
+ if image_name not in OFFICIAL_IMAGES:
124
+ LOG.debug(
125
+ "Skipping host license activation for custom image '%s' "
126
+ "(license expected to be baked into the image)",
127
+ image_name,
128
+ )
129
+ return
130
+
131
+ try:
132
+ licensingv2.get_licensed_environment().activate()
133
+ except licensingv2.LicensingError as e:
134
+ # license activation was unsuccessful (this can also be because no auth token was set)
135
+ # defensively set pro to False so that we don't load pro plugins
136
+ pro_config.ACTIVATE_PRO = False
137
+
138
+ # check also with LOCALSTACK_ prefix here because we don't have the handling from the docker entrypoint on the host
139
+ ack = localstack_config.is_env_true(
140
+ "LOCALSTACK_ACKNOWLEDGE_ACCOUNT_REQUIREMENT") or localstack_config.is_env_true(
141
+ "ACKNOWLEDGE_ACCOUNT_REQUIREMENT")
142
+ # Note: this can also fail because they've got their connection set up wrong.
143
+ active = _check_grace_period_active(ack)
144
+ if not ack and active:
145
+ # Grace period is active but unused. Prompt user to set up account or snooze.
146
+ raise LocalstackExit(reason=LICENSE_ERROR_MESSAGE, code=55)
147
+ if ack and active:
148
+ # Grace period is active, start in community mode (no pro features).
149
+ LOG.info("Grace period active: starting LocalStack in community mode")
150
+ return
151
+ if ack and not active:
152
+ # Grace period expired or endpoint unreachable
153
+ raise LocalstackExit(reason=GRACE_PERIOD_EXPIRED_MESSAGE, code=55)
154
+ raise LocalstackExit(reason=e.get_user_friendly(), code=55)
155
+
156
+
157
+ @hooks.configure_localstack_container(priority=10, should_load=pro_config.ACTIVATE_PRO)
158
+ def configure_pro_container(container: Container):
159
+ """Configure the LocalStack container for pro features."""
160
+ modify_gateway_listen_config(localstack_config)
161
+ container.configure(licensingv2.configure_container_licensing)
162
+
163
+
164
+ @hooks.prepare_host(should_load=pro_config.ACTIVATE_PRO and pro_config.EXTENSION_DEV_MODE)
165
+ def configure_extensions_dev_host():
166
+ """Load extension directories from ~/.localstack/extensions-dev.json."""
167
+ from localstack_cli.pro.core.bootstrap.extensions.bootstrap import run_on_configure_host_hook
168
+
169
+ run_on_configure_host_hook()
170
+
171
+
172
+ @hooks.configure_localstack_container(
173
+ should_load=pro_config.ACTIVATE_PRO and pro_config.EXTENSION_DEV_MODE
174
+ )
175
+ def configure_extensions_dev_container(container: Container):
176
+ """Configure container for extension developer mode."""
177
+ from localstack_cli.pro.core.bootstrap.extensions.bootstrap import (
178
+ run_on_configure_localstack_container_hook,
179
+ )
180
+
181
+ run_on_configure_localstack_container_hook(container)
@@ -428,7 +428,7 @@ def validate_localstack_config(name: str):
428
428
  image_name = ls_service_details.get("image", "")
429
429
  if image_name.split(":")[0] not in constants.OFFICIAL_IMAGES:
430
430
  warns.append(
431
- f'Using custom image "{image_name}", we recommend using an official image: {constants.OFFICIAL_IMAGES}'
431
+ f'Using custom image "{image_name}", we recommend using an officially supported image: {constants.OFFICIAL_IMAGES}'
432
432
  )
433
433
 
434
434
  # prepare config options
@@ -467,12 +467,7 @@ def validate_localstack_config(name: str):
467
467
 
468
468
 
469
469
  def get_docker_image_to_start():
470
- image_name = os.environ.get("IMAGE_NAME")
471
- if not image_name:
472
- image_name = constants.DOCKER_IMAGE_NAME
473
- if is_auth_token_configured():
474
- image_name = constants.DOCKER_IMAGE_NAME_PRO
475
- return image_name
470
+ return os.environ.get("IMAGE_NAME", constants.DOCKER_IMAGE_NAME_PRO)
476
471
 
477
472
 
478
473
  def extract_port_flags(user_flags, port_mappings: PortMappings):
@@ -78,7 +78,7 @@ def get_endpoint_for_network(network: str | None = None) -> str:
78
78
  else:
79
79
  # In a non-Linux host-mode environment, we need to determine the IP of the host by running a container
80
80
  # (basically macOS host mode, i.e. this is a feature to improve the developer experience)
81
- image_name = constants.DOCKER_IMAGE_NAME
81
+ image_name = constants.DOCKER_IMAGE_NAME_PRO
82
82
  out, _ = DOCKER_CLIENT.run_container(
83
83
  image_name,
84
84
  remove=True,
@@ -183,7 +183,7 @@ class CmdDockerClient(ContainerClient):
183
183
 
184
184
  def stop_container(self, container_name: str, timeout: int = 10) -> None:
185
185
  cmd = self._docker_cmd()
186
- cmd += ["stop", "--time", str(timeout), container_name]
186
+ cmd += ["stop", "--timeout", str(timeout), container_name]
187
187
  LOG.debug("Stopping container with cmd %s", cmd)
188
188
  try:
189
189
  run(cmd)
@@ -195,7 +195,7 @@ class CmdDockerClient(ContainerClient):
195
195
 
196
196
  def restart_container(self, container_name: str, timeout: int = 10) -> None:
197
197
  cmd = self._docker_cmd()
198
- cmd += ["restart", "--time", str(timeout), container_name]
198
+ cmd += ["restart", "--timeout", str(timeout), container_name]
199
199
  LOG.debug("Restarting container with cmd %s", cmd)
200
200
  try:
201
201
  run(cmd)
@@ -4,7 +4,7 @@ import platform
4
4
  import random
5
5
 
6
6
  from localstack_cli import config
7
- from localstack_cli.constants import DEFAULT_VOLUME_DIR, DOCKER_IMAGE_NAME
7
+ from localstack_cli.constants import DEFAULT_VOLUME_DIR, DOCKER_IMAGE_NAME_PRO
8
8
  from localstack_cli.utils.collections import ensure_list
9
9
  from localstack_cli.utils.container_utils.container_client import (
10
10
  ContainerClient,
@@ -266,7 +266,7 @@ def _get_ports_check_docker_image() -> str:
266
266
  return container["Config"]["Image"]
267
267
  except Exception:
268
268
  # fall back to using the default Docker image
269
- return DOCKER_IMAGE_NAME
269
+ return DOCKER_IMAGE_NAME_PRO
270
270
 
271
271
 
272
272
  DOCKER_CLIENT: ContainerClient = create_docker_client()
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '2026.4.0'
22
+ __version_tuple__ = version_tuple = (2026, 4, 0)
23
+
24
+ __commit_id__ = commit_id = 'g3e2666e1b'
@@ -60,8 +60,8 @@ def backup_and_remove_image(monkeypatch, container_client: ContainerClient):
60
60
  up" - i.e. tag it with another tag, and restore it afterwards.
61
61
  """
62
62
 
63
- source_image_name = f"{constants.DOCKER_IMAGE_NAME}:latest"
64
- tagged_image_name = f"{constants.DOCKER_IMAGE_NAME}:backup"
63
+ source_image_name = f"{constants.DOCKER_IMAGE_NAME_PRO}:latest"
64
+ tagged_image_name = f"{constants.DOCKER_IMAGE_NAME_PRO}:backup"
65
65
  container_client.tag_image(source_image_name, tagged_image_name)
66
66
  container_client.remove_image(source_image_name, force=True)
67
67
  monkeypatch.setenv("IMAGE_NAME", source_image_name)
@@ -74,7 +74,7 @@ def backup_and_remove_image(monkeypatch, container_client: ContainerClient):
74
74
  @pytest.fixture
75
75
  def create_container(container_client: ContainerClient):
76
76
  """Creates (but does not start) a docker container with the name 'localstack-main'"""
77
- container_client.create_container(image_name="localstack/localstack", name="localstack-main")
77
+ container_client.create_container(image_name="localstack/localstack-pro", name="localstack-main")
78
78
  yield
79
79
  container_client.remove_container("localstack-main", force=True)
80
80
 
@@ -106,7 +106,7 @@ class TestCliContainerLifecycle:
106
106
 
107
107
  @pytest.mark.usefixtures("backup_and_remove_image")
108
108
  def test_pulling_image_message(self, runner, container_client: ContainerClient):
109
- image_name_and_tag = f"{constants.DOCKER_IMAGE_NAME}:latest"
109
+ image_name_and_tag = f"{constants.DOCKER_IMAGE_NAME_PRO}:latest"
110
110
  with pytest.raises(NoSuchImage):
111
111
  container_client.inspect_image(image_name_and_tag, pull=False)
112
112
 
@@ -245,39 +245,16 @@ class TestCliContainerLifecycle:
245
245
  output = container_client.exec_in_container(config.MAIN_CONTAINER_NAME, ["ps", "-fu", user])
246
246
  assert "localstack-supervisor" in to_str(output[0])
247
247
 
248
- @pytest.mark.skip(reason="Test assumes localstack module name, not localstack_cli")
249
- def test_start_cli_within_container(self, runner, container_client, tmp_path):
250
- output = container_client.run_container(
251
- # CAVEAT: Updates to the Docker image are not immediately reflected when using the latest image from
252
- # DockerHub in the CI. Re-build the Docker image locally through
253
- # `IMAGE_NAME="localstack/localstack" ./bin/docker-helper.sh build` for local testing.
254
- "localstack/localstack",
255
- remove=True,
256
- entrypoint="",
257
- command=["bin/localstack", "start", "-d"],
258
- volumes=[
259
- ("/var/run/docker.sock", "/var/run/docker.sock"),
260
- (MODULE_MAIN_PATH, "/opt/code/localstack/localstack"),
261
- ],
262
- env_vars={"LOCALSTACK_VOLUME_DIR": f"{tmp_path}/ls-volume"},
263
- )
264
- stdout = to_str(output[0])
265
- assert "starting LocalStack" in stdout
266
- assert "detaching" in stdout
267
-
268
- # assert that container is running
269
- runner.invoke(cli, ["wait", "-t", "60"])
270
-
271
248
  def test_install_cli_in_container(self, container_client):
272
249
  """Test that the standalone CLI can be installed alongside the runtime in a container."""
273
250
  # Mount the CLI source code and install it, then run a simple command
274
251
  output = container_client.run_container(
275
- "localstack/localstack",
252
+ "localstack/localstack-pro",
276
253
  remove=True,
277
254
  entrypoint="",
278
255
  command=[
279
256
  "bash", "-c",
280
- "pip install -e /opt/code/localstack-cli && localstack --version"
257
+ "SETUPTOOLS_SCM_PRETEND_VERSION=1.0.0 pip install -e /opt/code/localstack-cli && localstack --version"
281
258
  ],
282
259
  volumes=[
283
260
  (os.path.dirname(MODULE_MAIN_PATH), "/opt/code/localstack-cli"),
@@ -153,30 +153,6 @@ class TestCliContainerLifecycle:
153
153
  output = container_client.exec_in_container(config.MAIN_CONTAINER_NAME, ["ps", "-fu", user])
154
154
  assert "localstack-supervisor" in to_str(output[0])
155
155
 
156
- @pytest.mark.skip(reason="Test assumes localstack module name, not localstack_cli")
157
- def test_start_cli_within_container(self, runner, container_client):
158
- output = container_client.run_container(
159
- # CAVEAT: Updates to the Docker image are not immediately reflected when using the latest image from
160
- # DockerHub in the CI.
161
- # Re-build the Docker image locally with `bin/docker-helper.sh build` in community for local testing.
162
- "localstack/localstack",
163
- remove=True,
164
- entrypoint="",
165
- command=["bin/localstack", "start", "-d"],
166
- volumes=[
167
- ("/var/run/docker.sock", "/var/run/docker.sock"),
168
- (MODULE_MAIN_PATH, "/opt/code/localstack/localstack"),
169
- ],
170
- env_vars={"LOCALSTACK_VOLUME_DIR": "/tmp/ls-volume"},
171
- )
172
- stdout = to_str(output[0])
173
- assert "starting LocalStack" in stdout
174
- assert "detaching" in stdout
175
-
176
- # assert that container is running
177
- runner.invoke(cli, ["wait", "-t", "180"])
178
-
179
-
180
156
  @pytest.mark.skip(reason="TODO: fix test setup - extensions tests need investigation")
181
157
  class TestExtensionsCli:
182
158
  def test_extensions_install_with_IMAGE_NAME_installs_correct_venv_version(
@@ -156,7 +156,7 @@ def test_validate_config(runner, monkeypatch, tmp_path):
156
156
  services:
157
157
  localstack:
158
158
  container_name: "${LOCALSTACK_DOCKER_NAME-localstack-main}"
159
- image: localstack/localstack
159
+ image: localstack/localstack-pro
160
160
  network_mode: bridge
161
161
  ports:
162
162
  - "127.0.0.1:53:53"