localstack 4.13.2.dev53__tar.gz → 4.14.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 (145) hide show
  1. {localstack-4.13.2.dev53 → localstack-4.14.0}/.github/workflows/tests-cli.yml +8 -0
  2. {localstack-4.13.2.dev53/localstack.egg-info → localstack-4.14.0}/PKG-INFO +1 -1
  3. {localstack-4.13.2.dev53 → localstack-4.14.0/localstack.egg-info}/PKG-INFO +1 -1
  4. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack.egg-info/SOURCES.txt +3 -2
  5. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/replicator.py +67 -30
  6. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/version.py +3 -3
  7. localstack-4.14.0/tests/unit/replicator/__init__.py +0 -0
  8. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/unit/replicator/test_profile_loading.py +54 -5
  9. {localstack-4.13.2.dev53 → localstack-4.14.0}/.gitignore +0 -0
  10. {localstack-4.13.2.dev53 → localstack-4.14.0}/Makefile +0 -0
  11. {localstack-4.13.2.dev53 → localstack-4.14.0}/README.md +0 -0
  12. {localstack-4.13.2.dev53 → localstack-4.14.0}/bin/localstack +0 -0
  13. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack.egg-info/dependency_links.txt +0 -0
  14. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack.egg-info/entry_points.txt +0 -0
  15. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack.egg-info/requires.txt +0 -0
  16. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack.egg-info/top_level.txt +0 -0
  17. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/__init__.py +0 -0
  18. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/cli/__init__.py +0 -0
  19. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/cli/console.py +0 -0
  20. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/cli/core_plugin.py +0 -0
  21. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/cli/exceptions.py +0 -0
  22. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/cli/localstack.py +0 -0
  23. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/cli/lpm.py +0 -0
  24. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/cli/main.py +0 -0
  25. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/cli/plugin.py +0 -0
  26. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/cli/plugins.py +0 -0
  27. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/cli/profiles.py +0 -0
  28. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/config.py +0 -0
  29. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/constants.py +0 -0
  30. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/logging/__init__.py +0 -0
  31. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/logging/format.py +0 -0
  32. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/logging/setup.py +0 -0
  33. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/packages/__init__.py +0 -0
  34. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/packages/api.py +0 -0
  35. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/packages/core.py +0 -0
  36. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/__init__.py +0 -0
  37. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/__init__.py +0 -0
  38. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/__init__.py +0 -0
  39. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/auth.py +0 -0
  40. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/dns_utils.py +0 -0
  41. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/entitlements.py +0 -0
  42. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/extensions/__init__.py +0 -0
  43. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/extensions/__main__.py +0 -0
  44. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/extensions/autoinstall.py +0 -0
  45. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/extensions/bootstrap.py +0 -0
  46. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/extensions/repository.py +0 -0
  47. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/licensingv2.py +0 -0
  48. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/pods/__init__.py +0 -0
  49. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/pods/api_types.py +0 -0
  50. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/pods/constants.py +0 -0
  51. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/pods/remotes/__init__.py +0 -0
  52. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/pods/remotes/api.py +0 -0
  53. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/pods/remotes/configs.py +0 -0
  54. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/pods/remotes/params.py +0 -0
  55. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/bootstrap/pods_client.py +0 -0
  56. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/__init__.py +0 -0
  57. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/auth.py +0 -0
  58. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/aws.py +0 -0
  59. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/cli.py +0 -0
  60. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/click_utils.py +0 -0
  61. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/cloud_pods.py +0 -0
  62. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/diff_view.py +0 -0
  63. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/ephemeral.py +0 -0
  64. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/extensions.py +0 -0
  65. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/iam.py +0 -0
  66. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/license.py +0 -0
  67. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/localstack.py +0 -0
  68. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/state.py +0 -0
  69. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/cli/tree_view.py +0 -0
  70. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/config.py +0 -0
  71. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/constants.py +0 -0
  72. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/pro/core/plugins.py +0 -0
  73. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/runtime/__init__.py +0 -0
  74. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/runtime/exceptions.py +0 -0
  75. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/runtime/hooks.py +0 -0
  76. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/testing/__init__.py +0 -0
  77. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/testing/config.py +0 -0
  78. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/__init__.py +0 -0
  79. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/analytics/__init__.py +0 -0
  80. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/analytics/cli.py +0 -0
  81. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/analytics/client.py +0 -0
  82. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/analytics/events.py +0 -0
  83. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/analytics/logger.py +0 -0
  84. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/analytics/metadata.py +0 -0
  85. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/analytics/publisher.py +0 -0
  86. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/analytics/service_request_aggregator.py +0 -0
  87. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/archives.py +0 -0
  88. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/batching.py +0 -0
  89. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/bootstrap.py +0 -0
  90. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/checksum.py +0 -0
  91. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/collections.py +0 -0
  92. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/common.py +0 -0
  93. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/container_networking.py +0 -0
  94. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/container_utils/__init__.py +0 -0
  95. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/container_utils/container_client.py +0 -0
  96. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/container_utils/docker_cmd_client.py +0 -0
  97. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/container_utils/docker_sdk_client.py +0 -0
  98. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/crypto.py +0 -0
  99. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/docker_utils.py +0 -0
  100. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/files.py +0 -0
  101. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/functions.py +0 -0
  102. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/http.py +0 -0
  103. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/json.py +0 -0
  104. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/net.py +0 -0
  105. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/no_exit_argument_parser.py +0 -0
  106. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/numbers.py +0 -0
  107. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/objects.py +0 -0
  108. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/patch.py +0 -0
  109. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/platform.py +0 -0
  110. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/run.py +0 -0
  111. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/server/__init__.py +0 -0
  112. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/server/tcp_proxy.py +0 -0
  113. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/serving.py +0 -0
  114. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/ssl.py +0 -0
  115. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/strings.py +0 -0
  116. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/sync.py +0 -0
  117. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/threads.py +0 -0
  118. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/time.py +0 -0
  119. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/urls.py +0 -0
  120. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/venv.py +0 -0
  121. {localstack-4.13.2.dev53 → localstack-4.14.0}/localstack_cli/utils/xml.py +0 -0
  122. {localstack-4.13.2.dev53 → localstack-4.14.0}/plux.ini +0 -0
  123. {localstack-4.13.2.dev53 → localstack-4.14.0}/pyproject.toml +0 -0
  124. {localstack-4.13.2.dev53 → localstack-4.14.0}/setup.cfg +0 -0
  125. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/__init__.py +0 -0
  126. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/bootstrap/__init__.py +0 -0
  127. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/bootstrap/extensions/__init__.py +0 -0
  128. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/bootstrap/extensions/test_extension_install.py +0 -0
  129. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/cli/__init__.py +0 -0
  130. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/cli/conftest.py +0 -0
  131. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/cli/test_cli.py +0 -0
  132. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/cli/test_cli_pro.py +0 -0
  133. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/conftest.py +0 -0
  134. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/integration/__init__.py +0 -0
  135. {localstack-4.13.2.dev53/tests/integration/replicator → localstack-4.14.0/tests/integration/cli}/__init__.py +0 -0
  136. {localstack-4.13.2.dev53/tests/unit → localstack-4.14.0/tests/integration}/cli/test_cli.py +0 -0
  137. {localstack-4.13.2.dev53/tests/unit → localstack-4.14.0/tests/integration}/cli/test_lpm.py +0 -0
  138. {localstack-4.13.2.dev53/tests/integration/replicator/core → localstack-4.14.0/tests/integration/replicator}/__init__.py +0 -0
  139. {localstack-4.13.2.dev53/tests/unit → localstack-4.14.0/tests/integration/replicator/core}/__init__.py +0 -0
  140. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/integration/replicator/core/test_replicator_cli.py +0 -0
  141. {localstack-4.13.2.dev53/tests/unit/cli → localstack-4.14.0/tests/unit}/__init__.py +0 -0
  142. {localstack-4.13.2.dev53/tests/unit/pro → localstack-4.14.0/tests/unit/cli}/__init__.py +0 -0
  143. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/unit/cli/test_profiles.py +0 -0
  144. {localstack-4.13.2.dev53/tests/unit/replicator → localstack-4.14.0/tests/unit/pro}/__init__.py +0 -0
  145. {localstack-4.13.2.dev53 → localstack-4.14.0}/tests/unit/pro/test_cli.py +0 -0
@@ -88,6 +88,14 @@ jobs:
88
88
  --log-cli-level=${{ env.PYTEST_LOGLEVEL }} \
89
89
  -v -s
90
90
 
91
+ - name: Run unit tests
92
+ env:
93
+ LOCALSTACK_AUTH_TOKEN: ${{ secrets.TEST_LOCALSTACK_AUTH_TOKEN }}
94
+ run: |
95
+ python -m pytest tests/unit/ \
96
+ --log-cli-level=${{ env.PYTEST_LOGLEVEL }} \
97
+ -v -s
98
+
91
99
  publish:
92
100
  if: >-
93
101
  (github.event.inputs.publish_to_pypi == 'true' && github.ref == 'refs/heads/main') ||
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: localstack
3
- Version: 4.13.2.dev53
3
+ Version: 4.14.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.13.2.dev53
3
+ Version: 4.14.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
@@ -234,13 +234,14 @@ tests/cli/conftest.py
234
234
  tests/cli/test_cli.py
235
235
  tests/cli/test_cli_pro.py
236
236
  tests/integration/__init__.py
237
+ tests/integration/cli/__init__.py
238
+ tests/integration/cli/test_cli.py
239
+ tests/integration/cli/test_lpm.py
237
240
  tests/integration/replicator/__init__.py
238
241
  tests/integration/replicator/core/__init__.py
239
242
  tests/integration/replicator/core/test_replicator_cli.py
240
243
  tests/unit/__init__.py
241
244
  tests/unit/cli/__init__.py
242
- tests/unit/cli/test_cli.py
243
- tests/unit/cli/test_lpm.py
244
245
  tests/unit/cli/test_profiles.py
245
246
  tests/unit/pro/__init__.py
246
247
  tests/unit/pro/test_cli.py
@@ -1,5 +1,6 @@
1
1
  import json
2
2
  import os
3
+ import re
3
4
  import subprocess as sp
4
5
  import sys
5
6
  import time
@@ -40,6 +41,10 @@ The replicator command group allows you to replicate AWS resources into LocalSta
40
41
  )
41
42
 
42
43
 
44
+ def run_check_output(cmd) -> str:
45
+ return sp.check_output(cmd, stderr=sp.PIPE, env=os.environ).decode("utf-8").strip()
46
+
47
+
43
48
  class ProfileLoadError(RuntimeError):
44
49
  def __init__(self, profile_name: str):
45
50
  super().__init__(f"Could not find profile '{profile_name}'")
@@ -96,49 +101,58 @@ def get_awscli_config() -> AWSConfig | None:
96
101
  try:
97
102
  # get credentials values
98
103
  cmd = ["aws", "configure", "export-credentials"]
99
- output = sp.check_output(cmd, stderr=sp.PIPE)
100
- credentials = json.loads(output.decode("utf8"))
104
+ credentials = json.loads(run_check_output(cmd))
101
105
  except sp.CalledProcessError as exc:
102
106
  if b"AWS CLI version 2" in exc.stderr:
103
107
  print(
104
108
  "Warning: awscli v1 installed. Please use v2 for auto detection of credentials",
105
109
  file=sys.stderr,
106
110
  )
107
- return None
111
+ return None
108
112
 
109
113
  try:
110
114
  # try to get the endpoint url
111
115
  cmd = ["aws", "configure", "get", "endpoint_url"]
112
- endpoint_url = sp.check_output(cmd, stderr=sp.PIPE).decode("utf8")
116
+ endpoint_url = run_check_output(cmd)
113
117
  except sp.CalledProcessError:
114
118
  # If there are no endpoint configured an exception is raised we do a last
115
119
  # check in the environment to find the endpoint url
116
120
  endpoint_url = os.getenv("AWS_ENDPOINT_URL")
117
121
 
118
122
  try:
119
- # get default region
120
- cmd = ["aws", "configure", "list"]
121
- output = sp.check_output(cmd, stderr=sp.PIPE)
122
- for line in output.decode().splitlines():
123
- if "region" not in line:
124
- continue
125
-
126
- words = line.split()
127
- try:
128
- region = words[1]
129
- return AWSConfig(
130
- aws_access_key_id=credentials["AccessKeyId"],
131
- aws_secret_access_key=credentials["SecretAccessKey"],
132
- aws_session_token=credentials.get("SessionToken"),
133
- region_name=region,
134
- endpoint_url=endpoint_url,
135
- )
136
-
137
- except IndexError:
138
- return None
139
-
140
- except (sp.CalledProcessError, FileNotFoundError):
141
- return None
123
+ # try to get the region from configure
124
+ cmd = ["aws", "configure", "get", "region"]
125
+ region_name = run_check_output(cmd)
126
+ except sp.CalledProcessError:
127
+ # If there are no default configured an exception is raised we do a last
128
+ # check in the environment to find the region
129
+ region_name = os.getenv("AWS_DEFAULT_REGION")
130
+
131
+ if not region_name:
132
+ try:
133
+ # older awscli versions do not return the region to the command `aws configure get region`.
134
+ # We need to rely on the configure list in this case
135
+ cmd = ["aws", "configure", "list"]
136
+ for line in run_check_output(cmd).splitlines():
137
+ if "region" not in line:
138
+ continue
139
+ # aws changed the format of configure and added `:` in delimiters
140
+ words = re.split(r"[:\s]+", line)
141
+ try:
142
+ region_name = words[1]
143
+ break
144
+ except IndexError:
145
+ return None
146
+ except (sp.CalledProcessError, FileNotFoundError):
147
+ return None
148
+
149
+ return AWSConfig(
150
+ aws_access_key_id=credentials["AccessKeyId"],
151
+ aws_secret_access_key=credentials["SecretAccessKey"],
152
+ aws_session_token=credentials.get("SessionToken"),
153
+ region_name=region_name,
154
+ endpoint_url=endpoint_url,
155
+ )
142
156
 
143
157
 
144
158
  def get_source_config(profile_dir: Path | None = None) -> AWSConfig:
@@ -148,13 +162,36 @@ def get_source_config(profile_dir: Path | None = None) -> AWSConfig:
148
162
  return awscli_source_config
149
163
 
150
164
  source_config = get_aws_env_config("AWS")
165
+ profile_name = source_config.get("profile_name")
166
+
167
+ if source_config.get("aws_access_key_id") and not source_config.get("aws_secret_access_key"):
168
+ raise CLIError(
169
+ "Unable to retrieve credentials: Partial credentials found in env."
170
+ " Need both 'AWS_ACCESS_KEY_ID' and 'AWS_SECRET_ACCESS_KEY'"
171
+ )
172
+
173
+ if profile_name:
174
+ config_file_source_config = get_config_from_profile(
175
+ profile_name=profile_name, profile_dir=profile_dir
176
+ )
177
+ if source_config.get("aws_secret_access_key"):
178
+ # before merging, if the secret access key is in the env vars we need to ensure the session token from the
179
+ # config file isn't carried along
180
+ config_file_source_config.pop("aws_session_token", None)
181
+ config_file_source_config.update(source_config)
182
+ source_config = config_file_source_config
183
+
184
+ errors = []
151
185
 
152
186
  if not source_config.get("region_name"):
153
- raise CLIError("'AWS_DEFAULT_REGION' must bet set in environment.")
187
+ errors.append("'AWS_DEFAULT_REGION' must bet set in environment or in profile.")
154
188
  if not source_config.get("aws_access_key_id"):
155
- raise CLIError("'AWS_ACCESS_KEY_ID' must bet set in environment.")
189
+ errors.append("'AWS_ACCESS_KEY_ID' must bet set in environment or in profile.")
156
190
  if not source_config.get("aws_secret_access_key"):
157
- raise CLIError("'AWS_SECRET_ACCESS_KEY' must bet set in environment.")
191
+ errors.append("'AWS_SECRET_ACCESS_KEY' must bet set in environment or in profile.")
192
+
193
+ if errors:
194
+ raise CLIError("\n".join(errors))
158
195
 
159
196
  return source_config
160
197
 
@@ -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.13.2.dev53'
32
- __version_tuple__ = version_tuple = (4, 13, 2, 'dev53')
31
+ __version__ = version = '4.14.0'
32
+ __version_tuple__ = version_tuple = (4, 14, 0)
33
33
 
34
- __commit_id__ = commit_id = 'g9339dde9f'
34
+ __commit_id__ = commit_id = 'ga77cc7d02'
File without changes
@@ -1,8 +1,11 @@
1
1
  import pytest
2
+
3
+ from localstack_cli.cli.exceptions import CLIError
2
4
  from localstack_cli.pro.core.cli.replicator import (
3
5
  ProfileLoadError,
4
6
  get_config_from_profile,
5
7
  get_source_config,
8
+ get_awscli_config,
6
9
  )
7
10
  from localstack_cli.utils.strings import short_uid
8
11
 
@@ -24,7 +27,7 @@ def secret_key():
24
27
 
25
28
  @pytest.fixture
26
29
  def profile_region():
27
- return "us-east-1"
30
+ return "us-east-7"
28
31
 
29
32
 
30
33
  @pytest.fixture
@@ -50,7 +53,9 @@ aws_secret_access_key = {secret_key}
50
53
  return tmpdir
51
54
 
52
55
 
53
- def test_load_profile(tmpdir, profile_name, profile_dir, profile_region, access_key_id, secret_key):
56
+ def test_load_profile_from_config_file(
57
+ profile_name, profile_dir, profile_region, access_key_id, secret_key
58
+ ):
54
59
  config = get_config_from_profile(profile_name, profile_dir)
55
60
 
56
61
  assert config["aws_access_key_id"] == access_key_id
@@ -68,9 +73,7 @@ def test_load_missing_profile(tmpdir, profile_dir):
68
73
  assert str(exc_info.value) == f"Could not find profile '{invalid_profile_name}'"
69
74
 
70
75
 
71
- def test_envars_override_profile(
72
- tmpdir, access_key_id, profile_dir, secret_key, profile_name, profile_region, monkeypatch
73
- ):
76
+ def test_envars_override_profile(profile_dir, profile_name, monkeypatch):
74
77
  monkeypatch.setenv("AWS_PROFILE", profile_name)
75
78
 
76
79
  test_access_key = short_uid()
@@ -85,3 +88,49 @@ def test_envars_override_profile(
85
88
  assert env.get("aws_access_key_id") == test_access_key
86
89
  assert env.get("aws_secret_access_key") == test_secret_key
87
90
  assert env.get("region_name") == test_region
91
+
92
+
93
+ def test_envars_partial_override_profile(
94
+ access_key_id, profile_dir, profile_name, profile_region, monkeypatch
95
+ ):
96
+ monkeypatch.setenv("AWS_PROFILE", profile_name)
97
+
98
+ test_access_key = short_uid()
99
+ monkeypatch.setenv("AWS_ACCESS_KEY_ID", test_access_key)
100
+ test_secret_key = short_uid()
101
+ monkeypatch.setenv("AWS_SECRET_ACCESS_KEY", test_secret_key)
102
+
103
+ env = get_source_config(profile_dir=profile_dir)
104
+
105
+ assert env.get("aws_access_key_id") == test_access_key
106
+ assert env.get("aws_secret_access_key") == test_secret_key
107
+ assert env.get("region_name") == profile_region
108
+
109
+
110
+ def test_envars_partial_override_profile_error(
111
+ access_key_id, profile_dir, profile_name, profile_region, monkeypatch
112
+ ):
113
+ monkeypatch.setenv("AWS_PROFILE", profile_name)
114
+
115
+ test_access_key = short_uid()
116
+ monkeypatch.setenv("AWS_ACCESS_KEY_ID", test_access_key)
117
+
118
+ with pytest.raises(CLIError) as e:
119
+ get_source_config(profile_dir=profile_dir)
120
+
121
+ assert "Partial credentials found in env" in e.value.message
122
+
123
+
124
+ def test_loading_from_aws_cli(
125
+ profile_name, profile_dir, profile_region, access_key_id, secret_key, monkeypatch
126
+ ):
127
+ monkeypatch.setenv("AWS_CONFIG_FILE", str(profile_dir / "config"))
128
+ monkeypatch.setenv("AWS_SHARED_CREDENTIALS_FILE", str(profile_dir / "credentials"))
129
+ monkeypatch.setenv("AWS_PROFILE", profile_name)
130
+
131
+ config = get_awscli_config()
132
+
133
+ assert config["aws_access_key_id"] == access_key_id
134
+ assert config["aws_secret_access_key"] == secret_key
135
+ assert config.get("aws_session_token") is None
136
+ assert config["region_name"] == profile_region
File without changes
File without changes
File without changes
File without changes