localstack 4.13.2.dev3__tar.gz → 4.13.2.dev36__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 (141) hide show
  1. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/Makefile +5 -1
  2. {localstack-4.13.2.dev3/localstack.egg-info → localstack-4.13.2.dev36}/PKG-INFO +2 -2
  3. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36/localstack.egg-info}/PKG-INFO +2 -2
  4. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack.egg-info/SOURCES.txt +11 -14
  5. localstack-4.13.2.dev36/localstack.egg-info/entry_points.txt +17 -0
  6. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack.egg-info/requires.txt +1 -1
  7. localstack-4.13.2.dev36/localstack_cli/pro/core/bootstrap/extensions/bootstrap.py +97 -0
  8. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/licensingv2.py +4 -143
  9. localstack-4.13.2.dev36/localstack_cli/pro/core/plugins.py +81 -0
  10. localstack-4.13.2.dev36/localstack_cli/runtime/__init__.py +6 -0
  11. localstack-4.13.2.dev36/localstack_cli/runtime/exceptions.py +7 -0
  12. localstack-4.13.2.dev36/localstack_cli/runtime/hooks.py +73 -0
  13. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/analytics/metadata.py +14 -20
  14. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/bootstrap.py +3 -8
  15. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/version.py +3 -3
  16. localstack-4.13.2.dev36/plux.ini +15 -0
  17. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/pyproject.toml +8 -6
  18. localstack-4.13.2.dev3/localstack.egg-info/entry_points.txt +0 -6
  19. localstack-4.13.2.dev3/localstack_cli/pro/core/bootstrap/decryption.py +0 -160
  20. localstack-4.13.2.dev3/localstack_cli/utils/analytics/metrics/__init__.py +0 -6
  21. localstack-4.13.2.dev3/localstack_cli/utils/analytics/metrics/api.py +0 -58
  22. localstack-4.13.2.dev3/localstack_cli/utils/analytics/metrics/counter.py +0 -212
  23. localstack-4.13.2.dev3/localstack_cli/utils/analytics/metrics/publisher.py +0 -45
  24. localstack-4.13.2.dev3/localstack_cli/utils/analytics/metrics/registry.py +0 -97
  25. localstack-4.13.2.dev3/localstack_cli/utils/analytics/service_providers.py +0 -22
  26. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/.github/workflows/tests-cli.yml +0 -0
  27. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/.gitignore +0 -0
  28. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/README.md +0 -0
  29. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/bin/localstack +0 -0
  30. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack.egg-info/dependency_links.txt +0 -0
  31. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack.egg-info/top_level.txt +0 -0
  32. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/__init__.py +0 -0
  33. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/cli/__init__.py +0 -0
  34. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/cli/console.py +0 -0
  35. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/cli/core_plugin.py +0 -0
  36. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/cli/exceptions.py +0 -0
  37. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/cli/localstack.py +0 -0
  38. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/cli/lpm.py +0 -0
  39. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/cli/main.py +0 -0
  40. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/cli/plugin.py +0 -0
  41. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/cli/plugins.py +0 -0
  42. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/cli/profiles.py +0 -0
  43. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/config.py +0 -0
  44. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/constants.py +0 -0
  45. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/logging/__init__.py +0 -0
  46. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/logging/format.py +0 -0
  47. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/logging/setup.py +0 -0
  48. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/packages/__init__.py +0 -0
  49. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/packages/api.py +0 -0
  50. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/packages/core.py +0 -0
  51. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/__init__.py +0 -0
  52. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/__init__.py +0 -0
  53. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/__init__.py +0 -0
  54. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/auth.py +0 -0
  55. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/dns_utils.py +0 -0
  56. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/entitlements.py +0 -0
  57. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/extensions/__init__.py +0 -0
  58. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/extensions/__main__.py +0 -0
  59. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/extensions/autoinstall.py +0 -0
  60. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/extensions/repository.py +0 -0
  61. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/pods/__init__.py +0 -0
  62. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/pods/api_types.py +0 -0
  63. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/pods/constants.py +0 -0
  64. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/pods/remotes/__init__.py +0 -0
  65. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/pods/remotes/api.py +0 -0
  66. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/pods/remotes/configs.py +0 -0
  67. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/pods/remotes/params.py +0 -0
  68. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/bootstrap/pods_client.py +0 -0
  69. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/__init__.py +0 -0
  70. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/auth.py +0 -0
  71. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/aws.py +0 -0
  72. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/cli.py +0 -0
  73. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/click_utils.py +0 -0
  74. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/cloud_pods.py +0 -0
  75. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/diff_view.py +0 -0
  76. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/ephemeral.py +0 -0
  77. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/extensions.py +0 -0
  78. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/iam.py +0 -0
  79. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/license.py +0 -0
  80. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/localstack.py +0 -0
  81. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/replicator.py +0 -0
  82. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/state.py +0 -0
  83. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/cli/tree_view.py +0 -0
  84. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/config.py +0 -0
  85. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/pro/core/constants.py +0 -0
  86. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/__init__.py +0 -0
  87. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/analytics/__init__.py +0 -0
  88. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/analytics/cli.py +0 -0
  89. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/analytics/client.py +0 -0
  90. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/analytics/events.py +0 -0
  91. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/analytics/logger.py +0 -0
  92. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/analytics/publisher.py +0 -0
  93. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/analytics/service_request_aggregator.py +0 -0
  94. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/archives.py +0 -0
  95. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/batching.py +0 -0
  96. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/checksum.py +0 -0
  97. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/collections.py +0 -0
  98. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/common.py +0 -0
  99. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/container_networking.py +0 -0
  100. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/container_utils/__init__.py +0 -0
  101. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/container_utils/container_client.py +0 -0
  102. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/container_utils/docker_cmd_client.py +0 -0
  103. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/container_utils/docker_sdk_client.py +0 -0
  104. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/crypto.py +0 -0
  105. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/docker_utils.py +0 -0
  106. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/files.py +0 -0
  107. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/functions.py +0 -0
  108. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/http.py +0 -0
  109. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/json.py +0 -0
  110. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/net.py +0 -0
  111. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/no_exit_argument_parser.py +0 -0
  112. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/numbers.py +0 -0
  113. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/objects.py +0 -0
  114. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/patch.py +0 -0
  115. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/platform.py +0 -0
  116. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/run.py +0 -0
  117. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/server/__init__.py +0 -0
  118. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/server/tcp_proxy.py +0 -0
  119. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/serving.py +0 -0
  120. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/ssl.py +0 -0
  121. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/strings.py +0 -0
  122. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/sync.py +0 -0
  123. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/threads.py +0 -0
  124. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/time.py +0 -0
  125. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/urls.py +0 -0
  126. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/venv.py +0 -0
  127. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/localstack_cli/utils/xml.py +0 -0
  128. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/setup.cfg +0 -0
  129. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/__init__.py +0 -0
  130. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/cli/__init__.py +0 -0
  131. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/cli/conftest.py +0 -0
  132. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/cli/test_cli.py +0 -0
  133. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/cli/test_cli_pro.py +0 -0
  134. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/conftest.py +0 -0
  135. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/unit/__init__.py +0 -0
  136. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/unit/cli/__init__.py +0 -0
  137. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/unit/cli/test_cli.py +0 -0
  138. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/unit/cli/test_lpm.py +0 -0
  139. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/unit/cli/test_profiles.py +0 -0
  140. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/unit/pro/__init__.py +0 -0
  141. {localstack-4.13.2.dev3 → localstack-4.13.2.dev36}/tests/unit/pro/test_cli.py +0 -0
@@ -1,4 +1,4 @@
1
- .PHONY: install test test-unit test-integration lint clean
1
+ .PHONY: install test test-unit test-integration lint clean entrypoints
2
2
 
3
3
  VENV_DIR ?= .venv
4
4
  PYTHON ?= python3
@@ -29,6 +29,10 @@ format: install
29
29
  $(VENV_DIR)/bin/ruff check --fix localstack_cli tests
30
30
  $(VENV_DIR)/bin/ruff format localstack_cli tests
31
31
 
32
+ entrypoints: install
33
+ $(VENV_DIR)/bin/python -m plux entrypoints
34
+ @test -s plux.ini || (echo "Entrypoints not created correctly!" && exit 1)
35
+
32
36
  clean:
33
37
  rm -rf $(VENV_DIR)
34
38
  rm -rf build dist *.egg-info
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: localstack
3
- Version: 4.13.2.dev3
3
+ Version: 4.13.2.dev36
4
4
  Summary: The LocalStack Command Line Interface
5
5
  Author-email: LocalStack Contributors <info@localstack.cloud>
6
6
  License-Expression: Apache-2.0
@@ -24,7 +24,7 @@ Requires-Dist: cryptography
24
24
  Requires-Dist: dnslib>=0.9.10
25
25
  Requires-Dist: dnspython>=1.16.0
26
26
  Requires-Dist: docker>=6.1.1
27
- Requires-Dist: plux>=1.10
27
+ Requires-Dist: plux>=1.14.0
28
28
  Requires-Dist: psutil>=5.4.8
29
29
  Requires-Dist: python-dotenv>=0.19.1
30
30
  Requires-Dist: pyyaml>=5.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: localstack
3
- Version: 4.13.2.dev3
3
+ Version: 4.13.2.dev36
4
4
  Summary: The LocalStack Command Line Interface
5
5
  Author-email: LocalStack Contributors <info@localstack.cloud>
6
6
  License-Expression: Apache-2.0
@@ -24,7 +24,7 @@ Requires-Dist: cryptography
24
24
  Requires-Dist: dnslib>=0.9.10
25
25
  Requires-Dist: dnspython>=1.16.0
26
26
  Requires-Dist: docker>=6.1.1
27
- Requires-Dist: plux>=1.10
27
+ Requires-Dist: plux>=1.14.0
28
28
  Requires-Dist: psutil>=5.4.8
29
29
  Requires-Dist: python-dotenv>=0.19.1
30
30
  Requires-Dist: pyyaml>=5.1
@@ -1,6 +1,7 @@
1
1
  .gitignore
2
2
  Makefile
3
3
  README.md
4
+ plux.ini
4
5
  pyproject.toml
5
6
  ./localstack_cli/__init__.py
6
7
  ./localstack_cli/config.py
@@ -26,9 +27,9 @@ pyproject.toml
26
27
  ./localstack_cli/pro/core/__init__.py
27
28
  ./localstack_cli/pro/core/config.py
28
29
  ./localstack_cli/pro/core/constants.py
30
+ ./localstack_cli/pro/core/plugins.py
29
31
  ./localstack_cli/pro/core/bootstrap/__init__.py
30
32
  ./localstack_cli/pro/core/bootstrap/auth.py
31
- ./localstack_cli/pro/core/bootstrap/decryption.py
32
33
  ./localstack_cli/pro/core/bootstrap/dns_utils.py
33
34
  ./localstack_cli/pro/core/bootstrap/entitlements.py
34
35
  ./localstack_cli/pro/core/bootstrap/licensingv2.py
@@ -36,6 +37,7 @@ pyproject.toml
36
37
  ./localstack_cli/pro/core/bootstrap/extensions/__init__.py
37
38
  ./localstack_cli/pro/core/bootstrap/extensions/__main__.py
38
39
  ./localstack_cli/pro/core/bootstrap/extensions/autoinstall.py
40
+ ./localstack_cli/pro/core/bootstrap/extensions/bootstrap.py
39
41
  ./localstack_cli/pro/core/bootstrap/extensions/repository.py
40
42
  ./localstack_cli/pro/core/bootstrap/pods/__init__.py
41
43
  ./localstack_cli/pro/core/bootstrap/pods/api_types.py
@@ -59,6 +61,9 @@ pyproject.toml
59
61
  ./localstack_cli/pro/core/cli/replicator.py
60
62
  ./localstack_cli/pro/core/cli/state.py
61
63
  ./localstack_cli/pro/core/cli/tree_view.py
64
+ ./localstack_cli/runtime/__init__.py
65
+ ./localstack_cli/runtime/exceptions.py
66
+ ./localstack_cli/runtime/hooks.py
62
67
  ./localstack_cli/utils/__init__.py
63
68
  ./localstack_cli/utils/archives.py
64
69
  ./localstack_cli/utils/batching.py
@@ -96,13 +101,7 @@ pyproject.toml
96
101
  ./localstack_cli/utils/analytics/logger.py
97
102
  ./localstack_cli/utils/analytics/metadata.py
98
103
  ./localstack_cli/utils/analytics/publisher.py
99
- ./localstack_cli/utils/analytics/service_providers.py
100
104
  ./localstack_cli/utils/analytics/service_request_aggregator.py
101
- ./localstack_cli/utils/analytics/metrics/__init__.py
102
- ./localstack_cli/utils/analytics/metrics/api.py
103
- ./localstack_cli/utils/analytics/metrics/counter.py
104
- ./localstack_cli/utils/analytics/metrics/publisher.py
105
- ./localstack_cli/utils/analytics/metrics/registry.py
106
105
  ./localstack_cli/utils/container_utils/__init__.py
107
106
  ./localstack_cli/utils/container_utils/container_client.py
108
107
  ./localstack_cli/utils/container_utils/docker_cmd_client.py
@@ -140,9 +139,9 @@ localstack_cli/pro/__init__.py
140
139
  localstack_cli/pro/core/__init__.py
141
140
  localstack_cli/pro/core/config.py
142
141
  localstack_cli/pro/core/constants.py
142
+ localstack_cli/pro/core/plugins.py
143
143
  localstack_cli/pro/core/bootstrap/__init__.py
144
144
  localstack_cli/pro/core/bootstrap/auth.py
145
- localstack_cli/pro/core/bootstrap/decryption.py
146
145
  localstack_cli/pro/core/bootstrap/dns_utils.py
147
146
  localstack_cli/pro/core/bootstrap/entitlements.py
148
147
  localstack_cli/pro/core/bootstrap/licensingv2.py
@@ -150,6 +149,7 @@ localstack_cli/pro/core/bootstrap/pods_client.py
150
149
  localstack_cli/pro/core/bootstrap/extensions/__init__.py
151
150
  localstack_cli/pro/core/bootstrap/extensions/__main__.py
152
151
  localstack_cli/pro/core/bootstrap/extensions/autoinstall.py
152
+ localstack_cli/pro/core/bootstrap/extensions/bootstrap.py
153
153
  localstack_cli/pro/core/bootstrap/extensions/repository.py
154
154
  localstack_cli/pro/core/bootstrap/pods/__init__.py
155
155
  localstack_cli/pro/core/bootstrap/pods/api_types.py
@@ -173,6 +173,9 @@ localstack_cli/pro/core/cli/localstack.py
173
173
  localstack_cli/pro/core/cli/replicator.py
174
174
  localstack_cli/pro/core/cli/state.py
175
175
  localstack_cli/pro/core/cli/tree_view.py
176
+ localstack_cli/runtime/__init__.py
177
+ localstack_cli/runtime/exceptions.py
178
+ localstack_cli/runtime/hooks.py
176
179
  localstack_cli/utils/__init__.py
177
180
  localstack_cli/utils/archives.py
178
181
  localstack_cli/utils/batching.py
@@ -210,13 +213,7 @@ localstack_cli/utils/analytics/events.py
210
213
  localstack_cli/utils/analytics/logger.py
211
214
  localstack_cli/utils/analytics/metadata.py
212
215
  localstack_cli/utils/analytics/publisher.py
213
- localstack_cli/utils/analytics/service_providers.py
214
216
  localstack_cli/utils/analytics/service_request_aggregator.py
215
- localstack_cli/utils/analytics/metrics/__init__.py
216
- localstack_cli/utils/analytics/metrics/api.py
217
- localstack_cli/utils/analytics/metrics/counter.py
218
- localstack_cli/utils/analytics/metrics/publisher.py
219
- localstack_cli/utils/analytics/metrics/registry.py
220
217
  localstack_cli/utils/container_utils/__init__.py
221
218
  localstack_cli/utils/container_utils/container_client.py
222
219
  localstack_cli/utils/container_utils/docker_cmd_client.py
@@ -0,0 +1,17 @@
1
+ [console_scripts]
2
+ localstack = localstack_cli.cli.main:main
3
+
4
+ [localstack.hooks.configure_localstack_container]
5
+ configure_extensions_dev_container = localstack_cli.pro.core.plugins:configure_extensions_dev_container
6
+ configure_pro_container = localstack_cli.pro.core.plugins:configure_pro_container
7
+ set_analytics_header = localstack_cli.utils.analytics.metadata:set_analytics_header
8
+
9
+ [localstack.hooks.prepare_host]
10
+ activate_pro_key_on_host = localstack_cli.pro.core.plugins:activate_pro_key_on_host
11
+ configure_extensions_dev_host = localstack_cli.pro.core.plugins:configure_extensions_dev_host
12
+ patch_community_pro_detection = localstack_cli.pro.core.plugins:patch_community_pro_detection
13
+ publish_invocation_metadata = localstack_cli.utils.analytics.metadata:publish_invocation_metadata
14
+
15
+ [localstack_cli.plugins.cli]
16
+ core = localstack_cli.cli.core_plugin:CoreCliPlugin
17
+ pro = localstack_cli.pro.core.cli.localstack:ProCliPlugins
@@ -5,7 +5,7 @@ cryptography
5
5
  dnslib>=0.9.10
6
6
  dnspython>=1.16.0
7
7
  docker>=6.1.1
8
- plux>=1.10
8
+ plux>=1.14.0
9
9
  psutil>=5.4.8
10
10
  python-dotenv>=0.19.1
11
11
  pyyaml>=5.1
@@ -0,0 +1,97 @@
1
+ """Hooks for extension developer mode on the host CLI."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import os
7
+ from pathlib import Path
8
+ from tempfile import gettempdir
9
+
10
+ from localstack_cli import config
11
+ from localstack_cli.utils.bootstrap import Container
12
+ from localstack_cli.utils.container_utils.container_client import BindMount
13
+ from localstack_cli.utils.json import FileMappedDocument
14
+ from localstack_cli.utils.strings import md5
15
+
16
+ LOG = logging.getLogger(__name__)
17
+
18
+ _ENTRYPOINT_SCRIPT = """#!/bin/bash
19
+ echo "=================================================="
20
+ echo "LocalStack extension developer mode enabled"
21
+ shopt -s nullglob
22
+
23
+ pkgs=$(echo /opt/code/localstack/.venv/lib/python3*/site-packages)
24
+
25
+ echo "import localstack_extensions_resolve;localstack_extensions_resolve.resolve()" > ${pkgs}/localstack-extensions-resolve.pth
26
+
27
+ cat << EOF >> ${pkgs}/localstack_extensions_resolve.py
28
+ import os
29
+ import sys
30
+ import glob
31
+
32
+ base_dirs_visited = set()
33
+
34
+ def append_pth_recursively(base_dir):
35
+ if base_dir in base_dirs_visited:
36
+ return
37
+ base_dirs_visited.add(base_dir)
38
+
39
+ for f in glob.glob(f"{base_dir}/*.pth", recursive=True):
40
+ with open(f, "r") as fd:
41
+ abs_path = os.path.abspath(os.path.dirname(f))
42
+ lines = fd.readlines()
43
+ for line in lines:
44
+ if line := line.strip():
45
+ if "import" in line:
46
+ continue
47
+ module_dir = os.path.abspath(os.path.join(abs_path, line)) if not os.path.isabs(line) else line
48
+ if os.path.exists(module_dir) and os.path.isdir(module_dir):
49
+ if module_dir not in sys.path:
50
+ sys.path.append(module_dir)
51
+ append_pth_recursively(module_dir)
52
+
53
+
54
+ def resolve():
55
+ append_pth_recursively(os.path.dirname(__file__))
56
+ EOF
57
+
58
+ for d in /opt/code/extensions/* ;
59
+ do
60
+ echo "- mounting extension ${d}"
61
+ find ${d} -type d -name "site-packages" >> ${pkgs}/localstack-extensions-venv.pth
62
+ echo ${d} >> ${pkgs}/localstack-extensions-venv.pth
63
+ done
64
+ echo "Resuming normal execution, ..."
65
+ echo "=================================================="
66
+ exec /usr/local/bin/docker-entrypoint.sh
67
+ """
68
+
69
+ _host_extension_dirs: list[str] = []
70
+
71
+
72
+ def run_on_configure_host_hook():
73
+ """Load extension directories from ~/.localstack/extensions-dev.json."""
74
+ doc = FileMappedDocument(os.path.join(config.CONFIG_DIR, "extensions-dev.json"))
75
+
76
+ for extensions_spec in doc.get("extensions", []):
77
+ path = extensions_spec.get("host_path")
78
+ if path and os.path.exists(path):
79
+ _host_extension_dirs.append(path)
80
+
81
+
82
+ def run_on_configure_localstack_container_hook(container: Container):
83
+ """Configure container for extension dev mode."""
84
+ # Create and mount custom entrypoint script
85
+ h = md5(_ENTRYPOINT_SCRIPT)
86
+ file = Path(gettempdir(), f"docker-entrypoint-{h}.sh")
87
+ if not file.exists():
88
+ file.write_text(_ENTRYPOINT_SCRIPT, newline="\n", encoding="utf-8")
89
+ file.chmod(0o777)
90
+
91
+ container.config.volumes.add(BindMount(str(file), f"/tmp/{file.name}"))
92
+ container.config.entrypoint = f"/tmp/{file.name}"
93
+
94
+ # Mount extension directories
95
+ for ext_dir in _host_extension_dirs:
96
+ target = os.path.join("/opt/code/extensions", os.path.basename(ext_dir))
97
+ container.config.volumes.add(BindMount(ext_dir, target, read_only=True))
@@ -1,8 +1,6 @@
1
1
  import base64
2
- import binascii
3
2
  import copy
4
3
  import dataclasses
5
- import hashlib
6
4
  import hmac
7
5
  import json
8
6
  import logging
@@ -26,9 +24,8 @@ from localstack_cli.pro.core.bootstrap.entitlements import (
26
24
  ProductInfo,
27
25
  )
28
26
  from localstack_cli.pro.core.constants import PLATFORM_PLUGIN_NAMESPACE
29
- from localstack_cli.utils.files import load_file
30
27
  from localstack_cli.utils.objects import singleton_factory
31
- from localstack_cli.utils.strings import md5, to_str
28
+ from localstack_cli.utils.strings import md5
32
29
  from plux import Plugin, PluginDisabled, PluginLifecycleListener, PluginSpec
33
30
 
34
31
  LOG = logging.getLogger(__name__)
@@ -446,20 +443,6 @@ class LicensingClient:
446
443
  """
447
444
  raise NotImplementedError
448
445
 
449
- def decode_decryption_key(self, credentials: Credentials, license: License) -> bytes:
450
- raise NotImplementedError
451
-
452
-
453
- class LicenseSecretDecoder:
454
- """
455
- Class to decode the ``license_secret`` field from the given license. The field contains a secret which is
456
- the decryption key for the localstack code.
457
- """
458
-
459
- def decode_license_secret(self, license: LicenseV1) -> bytes: # noqa
460
- raise NotImplementedError
461
-
462
-
463
446
  #####################
464
447
  # v1 implementation #
465
448
  #####################
@@ -518,64 +501,6 @@ class LicenseParser:
518
501
  raise LicenseFormatError(f"error parsing license file: {e}") from e
519
502
 
520
503
 
521
- class AESLicenseV1SecretDecoder(LicenseSecretDecoder):
522
- """
523
- Uses a custom AES encryption scheme to decode the source decryption key from the license key. This is
524
- mostly obfuscation and not really a trust mechanism.
525
-
526
- The shared key is the sha256 digest of the licensing credentials concatenated with the license signature.
527
- """
528
-
529
- scheme = "LS1.0"
530
-
531
- def __init__(self, credentials: Credentials):
532
- self.credentials = credentials
533
-
534
- def decode_license_secret(self, license: LicenseV1) -> bytes: # noqa
535
- if not license.signature:
536
- raise LicenseFormatError("license is not signed")
537
-
538
- # use the signature of the license as well as the credentials to encode the license key
539
- hash_ = hashlib.sha256()
540
- hash_.update(self.credentials.to_bytes())
541
- hash_.update(binascii.unhexlify(license.signature)) # use the byte value, not the string
542
- key = hash_.digest()
543
-
544
- # extract the scheme from the base64 encoded string
545
- license_secret = base64.b64decode(license.license_secret)
546
- parts = license_secret.split(b":", maxsplit=1)
547
- if len(parts) != 2: # noqa PLR2004
548
- raise LicenseFormatError("invalid license key format")
549
- scheme, secret = parts
550
-
551
- if scheme.decode("utf-8") != self.scheme:
552
- raise ValueError(f"unknown scheme {scheme}")
553
-
554
- iv = secret[:16]
555
- encrypted_data = secret[16:]
556
-
557
- return self._aes_decrypt(key, iv, encrypted_data)
558
-
559
- def _aes_decrypt(self, key: bytes, iv: bytes, encrypted_data: bytes):
560
- from cryptography.hazmat.primitives import padding
561
- from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
562
-
563
- # Create an AES cipher with the provided key and CBC mode
564
- cipher = Cipher(algorithms.AES(key), modes.CBC(iv))
565
-
566
- # Create a decryptor object using the AES cipher
567
- decryptor = cipher.decryptor()
568
-
569
- # Decrypt the encrypted data
570
- decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize()
571
-
572
- # Remove PKCS7 padding from the decrypted data
573
- unpadder = padding.PKCS7(128).unpadder()
574
- unpadded_data = unpadder.update(decrypted_data)
575
-
576
- return unpadded_data + unpadder.finalize()
577
-
578
-
579
504
  class LicenseV1ClientBase(LicensingClient):
580
505
  def validate_license(self, credentials: Credentials, license: LicenseV1):
581
506
  try:
@@ -640,17 +565,6 @@ class LicenseV1Client(LicenseV1ClientBase):
640
565
  license_.offline_data["localstack_version"] = VERSION
641
566
  return license_
642
567
 
643
- def decode_decryption_key(self, credentials: Credentials, license: LicenseV1) -> bytes:
644
- key = base64.b64decode(license.license_secret)
645
- parts = key.split(b":", maxsplit=1)
646
- scheme = to_str(parts[0])
647
- if scheme == AESLicenseV1SecretDecoder.scheme:
648
- decoder = AESLicenseV1SecretDecoder(credentials)
649
- else:
650
- raise LicenseFormatError(f"unknown license key scheme {scheme}")
651
-
652
- return decoder.decode_license_secret(license)
653
-
654
568
  def _get_machine_data(self) -> dict:
655
569
  from localstack_cli.utils.analytics.metadata import get_client_metadata
656
570
 
@@ -826,10 +740,9 @@ class LicensedLocalstackEnvironment:
826
740
 
827
741
  def activate(self, offline_only: bool = False):
828
742
  """
829
- This high-level method first activates the license using credentials from the environment, and then
830
- enables code decryption if necessary. Once completed, it sets ``self.license`` to the license document
831
- that was activated. This method will also set the env var ``PRO_ACTIVATED=1`` after successful license
832
- activation and code decryption.
743
+ This high-level method activates the license using credentials from the environment.
744
+ Once completed, it sets ``self.license`` to the license document that was activated.
745
+ This method will also set the env var ``PRO_ACTIVATED=1`` after successful license activation.
833
746
 
834
747
  See ``activate_license`` for the activation algorithm.
835
748
 
@@ -854,9 +767,6 @@ class LicensedLocalstackEnvironment:
854
767
 
855
768
  self.activate_license(offline_only)
856
769
 
857
- if not self.is_decryption_enabled():
858
- self.enable_decryption()
859
-
860
770
  os.environ[constants.ENV_PRO_ACTIVATED] = "1"
861
771
 
862
772
  def activate_license(self, offline_only: bool = False):
@@ -974,55 +884,6 @@ class LicensedLocalstackEnvironment:
974
884
  """
975
885
  return self.product_entitlements.has_entitlement(product_name)
976
886
 
977
- def enable_decryption(self):
978
- """
979
- Called by ``activate`` to read the source decryption key from the license key and register the
980
- ``DecryptionHandler`` into the sys path.
981
- """
982
- if not self.activated or not self.license:
983
- raise ValueError("license not yet activated")
984
-
985
- from localstack_cli.pro.core.bootstrap.decryption import (
986
- DecryptionHandler,
987
- init_source_decryption,
988
- )
989
- from localstack_cli.pro.core.config import ROOT_FOLDER
990
-
991
- decryption_handler = DecryptionHandler(
992
- self.client.decode_decryption_key(self.require_valid_credentials(), self.license)
993
- )
994
-
995
- try:
996
- file_name = f"{ROOT_FOLDER}/localstack/pro/core/utils/decryption_check.py.enc"
997
- encrypted_file_content = load_file(file_name, mode="rb")
998
- if not encrypted_file_content:
999
- raise ValueError(
1000
- "Decryption check file not found. Are you using localstack pro in host mode?"
1001
- )
1002
- file_content = decryption_handler.decrypt(encrypted_file_content)
1003
- if b"decryption_check" not in file_content:
1004
- raise ValueError("Decryption resulted in invalid python file")
1005
- except Exception as e:
1006
- raise LicenseActivationError(
1007
- "Error while trying to perform code activation. You may be using a "
1008
- "version of LocalStack that is not within your license agreement."
1009
- ) from e
1010
-
1011
- init_source_decryption(decryption_handler)
1012
-
1013
- def is_decryption_enabled(self) -> bool:
1014
- """
1015
- Checks whether decryption is enabled. Decryption can be enabled in a test environment when the
1016
- source code is available. So this can return true even if a license has not been activated.
1017
-
1018
- :return: true if the normally encrypted source code can be accessed.
1019
- """
1020
- try:
1021
- from localstack_cli.pro.core.utils.decryption_check import decryption_check # noqa
1022
-
1023
- return True
1024
- except ImportError:
1025
- return False
1026
887
 
1027
888
  def save_license(self):
1028
889
  """
@@ -0,0 +1,81 @@
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
+ from localstack_cli import config as localstack_config
17
+ from localstack_cli.config import HostAndPort
18
+ from localstack_cli.pro.core import config as pro_config
19
+ from localstack_cli.pro.core.bootstrap import licensingv2
20
+ from localstack_cli.runtime import hooks
21
+ from localstack_cli.runtime.exceptions import LocalstackExit
22
+ from localstack_cli.utils.bootstrap import Container
23
+
24
+ LOG = logging.getLogger(__name__)
25
+
26
+
27
+ def modify_gateway_listen_config(cfg):
28
+ """
29
+ Modifies the localstack config to additionally listen to port 443.
30
+ Needs to be called before any edge URLs are resolved using the config.
31
+ """
32
+ if os.getenv("GATEWAY_LISTEN") is None:
33
+ host = "0.0.0.0" if localstack_config.in_docker() else "127.0.0.1"
34
+ cfg.GATEWAY_LISTEN.append(HostAndPort(host=host, port=443))
35
+
36
+
37
+ @hooks.prepare_host(priority=200)
38
+ def patch_community_pro_detection():
39
+ """This is currently needed to make localstack core aware of the `localstack auth set-token`
40
+ functionality, where we set the key into the ``~/.localstack/auth.json`` file that community does not
41
+ yet know about. ``is_api_key_configured`` is used in the LocalStack CLI to determine whether to start
42
+ the localstack or localstack-pro container image."""
43
+ from localstack_cli.utils import bootstrap
44
+
45
+ bootstrap.is_auth_token_configured = pro_config.is_auth_token_configured
46
+
47
+
48
+ @hooks.prepare_host(priority=100, should_load=pro_config.ACTIVATE_PRO)
49
+ def activate_pro_key_on_host():
50
+ """Activate license on host (needed for DNS forward and EC2 daemon)."""
51
+ try:
52
+ licensingv2.get_licensed_environment().activate()
53
+ except licensingv2.LicensingError as e:
54
+ raise LocalstackExit(reason=e.get_user_friendly(), code=55)
55
+
56
+
57
+ @hooks.configure_localstack_container(priority=10, should_load=pro_config.ACTIVATE_PRO)
58
+ def configure_pro_container(container: Container):
59
+ """Configure the LocalStack container for pro features."""
60
+ modify_gateway_listen_config(localstack_config)
61
+ container.configure(licensingv2.configure_container_licensing)
62
+
63
+
64
+ @hooks.prepare_host(should_load=pro_config.ACTIVATE_PRO and pro_config.EXTENSION_DEV_MODE)
65
+ def configure_extensions_dev_host():
66
+ """Load extension directories from ~/.localstack/extensions-dev.json."""
67
+ from localstack_cli.pro.core.bootstrap.extensions.bootstrap import run_on_configure_host_hook
68
+
69
+ run_on_configure_host_hook()
70
+
71
+
72
+ @hooks.configure_localstack_container(
73
+ should_load=pro_config.ACTIVATE_PRO and pro_config.EXTENSION_DEV_MODE
74
+ )
75
+ def configure_extensions_dev_container(container: Container):
76
+ """Configure container for extension developer mode."""
77
+ from localstack_cli.pro.core.bootstrap.extensions.bootstrap import (
78
+ run_on_configure_localstack_container_hook,
79
+ )
80
+
81
+ run_on_configure_localstack_container_hook(container)
@@ -0,0 +1,6 @@
1
+ """Runtime utilities for the LocalStack CLI."""
2
+
3
+ from localstack_cli.runtime import hooks # noqa: F401
4
+
5
+ # get_current_runtime is not available in the standalone CLI - only in the full LocalStack runtime
6
+ get_current_runtime = None
@@ -0,0 +1,7 @@
1
+ class LocalstackExit(Exception):
2
+ """Raised to gracefully exit LocalStack."""
3
+
4
+ def __init__(self, reason: str = None, code: int = 1):
5
+ self.reason = reason
6
+ self.code = code
7
+ super().__init__(reason)
@@ -0,0 +1,73 @@
1
+ import functools
2
+
3
+ from plux import PluginManager, plugin
4
+
5
+ # plugin namespace constants
6
+ HOOKS_CONFIGURE_LOCALSTACK_CONTAINER = "localstack.hooks.configure_localstack_container"
7
+ HOOKS_PREPARE_HOST = "localstack.hooks.prepare_host"
8
+
9
+
10
+ def hook(namespace: str, priority: int = 0, **kwargs):
11
+ """
12
+ Decorator for creating functional plugins that have a hook_priority attribute. Hooks with a higher priority value
13
+ will be executed earlier.
14
+ """
15
+
16
+ def wrapper(fn):
17
+ fn.hook_priority = priority
18
+ return plugin(namespace=namespace, **kwargs)(fn)
19
+
20
+ return wrapper
21
+
22
+
23
+ def hook_spec(namespace: str):
24
+ """
25
+ Creates a new hook decorator bound to a namespace.
26
+
27
+ on_infra_start = hook_spec("localstack.hooks.on_infra_start")
28
+
29
+ @on_infra_start()
30
+ def foo():
31
+ pass
32
+
33
+ # run all hooks in order
34
+ on_infra_start.run()
35
+ """
36
+ fn = functools.partial(hook, namespace=namespace)
37
+ # attach hook manager and run method to decorator for convenience calls
38
+ fn.manager = HookManager(namespace)
39
+ fn.run = fn.manager.run_in_order
40
+ return fn
41
+
42
+
43
+ class HookManager(PluginManager):
44
+ def load_all_sorted(self, propagate_exceptions=False):
45
+ """
46
+ Loads all hook plugins and sorts them by their hook_priority attribute.
47
+ """
48
+ plugins = self.load_all(propagate_exceptions)
49
+ # the hook_priority attribute is part of the function wrapped in the FunctionPlugin
50
+ plugins.sort(
51
+ key=lambda _fn_plugin: getattr(_fn_plugin.fn, "hook_priority", 0), reverse=True
52
+ )
53
+ return plugins
54
+
55
+ def run_in_order(self, *args, **kwargs):
56
+ """
57
+ Loads and runs all plugins in order them with the given arguments.
58
+ """
59
+ for fn_plugin in self.load_all_sorted():
60
+ fn_plugin(*args, **kwargs)
61
+
62
+ def __str__(self):
63
+ return f"HookManager({self.namespace})"
64
+
65
+ def __repr__(self):
66
+ return self.__str__()
67
+
68
+
69
+ configure_localstack_container = hook_spec(HOOKS_CONFIGURE_LOCALSTACK_CONTAINER)
70
+ """Hooks to configure the LocalStack container before it starts. Executed on the host when invoking the CLI."""
71
+
72
+ prepare_host = hook_spec(HOOKS_PREPARE_HOST)
73
+ """Hooks to prepare the host that's starting LocalStack. Executed on the host when invoking the CLI."""