playground-ls-cli 4.14.1.dev8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- localstack_cli/__init__.py +0 -0
- localstack_cli/cli/__init__.py +10 -0
- localstack_cli/cli/console.py +11 -0
- localstack_cli/cli/core_plugin.py +12 -0
- localstack_cli/cli/exceptions.py +19 -0
- localstack_cli/cli/localstack.py +951 -0
- localstack_cli/cli/lpm.py +138 -0
- localstack_cli/cli/main.py +22 -0
- localstack_cli/cli/plugin.py +39 -0
- localstack_cli/cli/plugins.py +134 -0
- localstack_cli/cli/profiles.py +65 -0
- localstack_cli/config.py +1689 -0
- localstack_cli/constants.py +165 -0
- localstack_cli/logging/__init__.py +0 -0
- localstack_cli/logging/format.py +194 -0
- localstack_cli/logging/setup.py +142 -0
- localstack_cli/packages/__init__.py +25 -0
- localstack_cli/packages/api.py +418 -0
- localstack_cli/packages/core.py +416 -0
- localstack_cli/pro/__init__.py +0 -0
- localstack_cli/pro/core/__init__.py +0 -0
- localstack_cli/pro/core/bootstrap/__init__.py +1 -0
- localstack_cli/pro/core/bootstrap/auth.py +213 -0
- localstack_cli/pro/core/bootstrap/dns_utils.py +55 -0
- localstack_cli/pro/core/bootstrap/entitlements.py +117 -0
- localstack_cli/pro/core/bootstrap/extensions/__init__.py +3 -0
- localstack_cli/pro/core/bootstrap/extensions/__main__.py +106 -0
- localstack_cli/pro/core/bootstrap/extensions/autoinstall.py +63 -0
- localstack_cli/pro/core/bootstrap/extensions/bootstrap.py +97 -0
- localstack_cli/pro/core/bootstrap/extensions/repository.py +374 -0
- localstack_cli/pro/core/bootstrap/licensingv2.py +1259 -0
- localstack_cli/pro/core/bootstrap/pods/__init__.py +0 -0
- localstack_cli/pro/core/bootstrap/pods/api_types.py +17 -0
- localstack_cli/pro/core/bootstrap/pods/constants.py +26 -0
- localstack_cli/pro/core/bootstrap/pods/remotes/__init__.py +0 -0
- localstack_cli/pro/core/bootstrap/pods/remotes/api.py +75 -0
- localstack_cli/pro/core/bootstrap/pods/remotes/configs.py +69 -0
- localstack_cli/pro/core/bootstrap/pods/remotes/params.py +86 -0
- localstack_cli/pro/core/bootstrap/pods_client.py +834 -0
- localstack_cli/pro/core/cli/__init__.py +0 -0
- localstack_cli/pro/core/cli/auth.py +226 -0
- localstack_cli/pro/core/cli/aws.py +16 -0
- localstack_cli/pro/core/cli/cli.py +99 -0
- localstack_cli/pro/core/cli/click_utils.py +21 -0
- localstack_cli/pro/core/cli/cloud_pods.py +465 -0
- localstack_cli/pro/core/cli/diff_view.py +41 -0
- localstack_cli/pro/core/cli/ephemeral.py +199 -0
- localstack_cli/pro/core/cli/extensions.py +492 -0
- localstack_cli/pro/core/cli/iam.py +180 -0
- localstack_cli/pro/core/cli/license.py +90 -0
- localstack_cli/pro/core/cli/localstack.py +118 -0
- localstack_cli/pro/core/cli/replicator.py +378 -0
- localstack_cli/pro/core/cli/state.py +183 -0
- localstack_cli/pro/core/cli/tree_view.py +235 -0
- localstack_cli/pro/core/config.py +556 -0
- localstack_cli/pro/core/constants.py +54 -0
- localstack_cli/pro/core/plugins.py +169 -0
- localstack_cli/runtime/__init__.py +6 -0
- localstack_cli/runtime/exceptions.py +7 -0
- localstack_cli/runtime/hooks.py +73 -0
- localstack_cli/testing/__init__.py +1 -0
- localstack_cli/testing/config.py +4 -0
- localstack_cli/utils/__init__.py +0 -0
- localstack_cli/utils/analytics/__init__.py +12 -0
- localstack_cli/utils/analytics/cli.py +67 -0
- localstack_cli/utils/analytics/client.py +111 -0
- localstack_cli/utils/analytics/events.py +30 -0
- localstack_cli/utils/analytics/logger.py +48 -0
- localstack_cli/utils/analytics/metadata.py +250 -0
- localstack_cli/utils/analytics/publisher.py +160 -0
- localstack_cli/utils/analytics/service_request_aggregator.py +133 -0
- localstack_cli/utils/archives.py +271 -0
- localstack_cli/utils/batching.py +258 -0
- localstack_cli/utils/bootstrap.py +1418 -0
- localstack_cli/utils/checksum.py +313 -0
- localstack_cli/utils/collections.py +554 -0
- localstack_cli/utils/common.py +229 -0
- localstack_cli/utils/container_networking.py +142 -0
- localstack_cli/utils/container_utils/__init__.py +0 -0
- localstack_cli/utils/container_utils/container_client.py +1585 -0
- localstack_cli/utils/container_utils/docker_cmd_client.py +987 -0
- localstack_cli/utils/container_utils/docker_sdk_client.py +1018 -0
- localstack_cli/utils/crypto.py +294 -0
- localstack_cli/utils/docker_utils.py +272 -0
- localstack_cli/utils/files.py +327 -0
- localstack_cli/utils/functions.py +92 -0
- localstack_cli/utils/http.py +326 -0
- localstack_cli/utils/json.py +219 -0
- localstack_cli/utils/net.py +516 -0
- localstack_cli/utils/no_exit_argument_parser.py +19 -0
- localstack_cli/utils/numbers.py +49 -0
- localstack_cli/utils/objects.py +235 -0
- localstack_cli/utils/patch.py +260 -0
- localstack_cli/utils/platform.py +77 -0
- localstack_cli/utils/run.py +514 -0
- localstack_cli/utils/server/__init__.py +0 -0
- localstack_cli/utils/server/tcp_proxy.py +108 -0
- localstack_cli/utils/serving.py +187 -0
- localstack_cli/utils/ssl.py +71 -0
- localstack_cli/utils/strings.py +245 -0
- localstack_cli/utils/sync.py +267 -0
- localstack_cli/utils/threads.py +163 -0
- localstack_cli/utils/time.py +81 -0
- localstack_cli/utils/urls.py +21 -0
- localstack_cli/utils/venv.py +100 -0
- localstack_cli/utils/xml.py +41 -0
- localstack_cli/version.py +34 -0
- playground_ls_cli-4.14.1.dev8.dist-info/METADATA +95 -0
- playground_ls_cli-4.14.1.dev8.dist-info/RECORD +112 -0
- playground_ls_cli-4.14.1.dev8.dist-info/WHEEL +5 -0
- playground_ls_cli-4.14.1.dev8.dist-info/entry_points.txt +17 -0
- playground_ls_cli-4.14.1.dev8.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
from click import ClickException
|
|
5
|
+
from localstack_cli.cli.localstack import LocalStackCliGroup
|
|
6
|
+
from localstack_cli.utils.analytics.cli import publish_invocation
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.group(
|
|
10
|
+
name="auth",
|
|
11
|
+
cls=LocalStackCliGroup,
|
|
12
|
+
short_help="Authenticate with your LocalStack account",
|
|
13
|
+
help="""
|
|
14
|
+
Authenticate with your LocalStack account.
|
|
15
|
+
|
|
16
|
+
Manage your credentials and authenticate with your LocalStack account.
|
|
17
|
+
""",
|
|
18
|
+
)
|
|
19
|
+
def auth() -> None:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@auth.command(
|
|
24
|
+
name="set-token",
|
|
25
|
+
short_help="Set your Localstack auth token to allow you to start LocalStack Pro",
|
|
26
|
+
help="""
|
|
27
|
+
Configure your auth token. Your auth token is used the license activation to activate LocalStack Pro.
|
|
28
|
+
This is different from `localstack auth login` which enables platform features such as pushing cloud pods to your
|
|
29
|
+
webapp account.
|
|
30
|
+
|
|
31
|
+
The auth token you configure here will be passed to the `LOCALSTACK_AUTH_TOKEN` environment variable of the
|
|
32
|
+
LocalStack container when you run `localstack start`.
|
|
33
|
+
|
|
34
|
+
AUTH_TOKEN: Your Localstack auth token that you can find in https://app.localstack.cloud.
|
|
35
|
+
""",
|
|
36
|
+
)
|
|
37
|
+
@click.argument("auth-token", type=str, required=True)
|
|
38
|
+
@publish_invocation
|
|
39
|
+
def set_token(auth_token: str):
|
|
40
|
+
from localstack_cli.pro.core.bootstrap.licensingv2 import AuthToken
|
|
41
|
+
|
|
42
|
+
token = AuthToken(auth_token)
|
|
43
|
+
if not token.is_syntax_valid():
|
|
44
|
+
raise ClickException(
|
|
45
|
+
"The format of the token you provided is invalid, please make sure to set a valid token. Auth "
|
|
46
|
+
"tokens start with `ls-` and are followed by a 36-character string. You can find your auth "
|
|
47
|
+
"token in the LocalStack web app https://app.localstack.cloud."
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if not token.is_checksum_valid():
|
|
51
|
+
raise ClickException(
|
|
52
|
+
"The token you provided appears to be invalid, please make sure to set a valid token. You can "
|
|
53
|
+
"find your auth token in the LocalStack web app https://app.localstack.cloud."
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
from localstack_cli.pro.core import config as pro_config
|
|
57
|
+
from localstack_cli.pro.core.bootstrap.auth import get_auth_cache
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
auth_config = get_auth_cache()
|
|
61
|
+
auth_config["LOCALSTACK_AUTH_TOKEN"] = token.encoded()
|
|
62
|
+
auth_config.save()
|
|
63
|
+
except Exception as e:
|
|
64
|
+
raise ClickException(
|
|
65
|
+
f"Could not save auth configuration into {pro_config.AUTH_CACHE_PATH}: {e}"
|
|
66
|
+
) from e
|
|
67
|
+
|
|
68
|
+
click.echo("Token configured successfully")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@auth.command(
|
|
72
|
+
name="clear-token",
|
|
73
|
+
short_help="Clear any existing LocalStack auth token from your environment",
|
|
74
|
+
)
|
|
75
|
+
@publish_invocation
|
|
76
|
+
def clear_token():
|
|
77
|
+
from localstack_cli.pro.core import config as pro_config
|
|
78
|
+
from localstack_cli.pro.core.bootstrap.auth import get_auth_cache
|
|
79
|
+
from localstack_cli.pro.core.bootstrap.licensingv2 import ENV_LOCALSTACK_AUTH_TOKEN, AuthToken
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
auth_config = get_auth_cache()
|
|
83
|
+
if ENV_LOCALSTACK_AUTH_TOKEN not in auth_config:
|
|
84
|
+
click.echo("No token in environment, no change necessary")
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
token = AuthToken(auth_config.pop(ENV_LOCALSTACK_AUTH_TOKEN))
|
|
88
|
+
auth_config.save()
|
|
89
|
+
click.echo(f"Token {token} cleared successfully")
|
|
90
|
+
except Exception as e:
|
|
91
|
+
raise ClickException(
|
|
92
|
+
f"Could not save auth configuration into {pro_config.AUTH_CACHE_PATH}: {e}"
|
|
93
|
+
) from e
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@auth.command(
|
|
97
|
+
name="show-token",
|
|
98
|
+
short_help="Show the auth token in your configuration",
|
|
99
|
+
help="""
|
|
100
|
+
Show the token that LocalStack picks up from your environment. This can either be the auth token set via
|
|
101
|
+
`localstack auth set-token`, or the value of `LOCALSTACK_AUTH_TOKEN`.
|
|
102
|
+
""",
|
|
103
|
+
)
|
|
104
|
+
@click.option(
|
|
105
|
+
"--plain",
|
|
106
|
+
is_flag=True,
|
|
107
|
+
required=False,
|
|
108
|
+
default=False,
|
|
109
|
+
help="""
|
|
110
|
+
Setting this flag will output only the value of the token in plain text, so it can be used as input
|
|
111
|
+
to other programs, like `LOCALSTACK_AUTH_TOKEN=$(localstack auth show-token --plain)`.
|
|
112
|
+
""",
|
|
113
|
+
)
|
|
114
|
+
@publish_invocation
|
|
115
|
+
def show_token(plain: bool):
|
|
116
|
+
from localstack_cli.pro.core import config as pro_config
|
|
117
|
+
from localstack_cli.pro.core.bootstrap.auth import get_auth_cache
|
|
118
|
+
from localstack_cli.pro.core.bootstrap.licensingv2 import ENV_LOCALSTACK_AUTH_TOKEN, AuthToken
|
|
119
|
+
|
|
120
|
+
def _print_token_info(_token: AuthToken):
|
|
121
|
+
is_valid = _token.is_valid()
|
|
122
|
+
click.echo(f"Valid: {is_valid}", err=True)
|
|
123
|
+
# will only show parts of the token (ls-xepA3110-****-****-...)
|
|
124
|
+
if plain:
|
|
125
|
+
click.echo(_token.token)
|
|
126
|
+
else:
|
|
127
|
+
click.echo(f"Token: {_token}")
|
|
128
|
+
|
|
129
|
+
env_token = os.getenv(ENV_LOCALSTACK_AUTH_TOKEN, "").strip()
|
|
130
|
+
if env_token:
|
|
131
|
+
click.echo(
|
|
132
|
+
f"Prioritizing auth token set in environment variable {ENV_LOCALSTACK_AUTH_TOKEN}",
|
|
133
|
+
err=True,
|
|
134
|
+
)
|
|
135
|
+
_print_token_info(AuthToken(env_token))
|
|
136
|
+
return
|
|
137
|
+
|
|
138
|
+
if not os.path.isfile(pro_config.AUTH_CACHE_PATH):
|
|
139
|
+
click.echo(
|
|
140
|
+
"Token not configured in environment yet, please run localstack auth set-token "
|
|
141
|
+
"<AUTH_TOKEN>, or set the environment variable LOCALSTACK_AUTH_TOKEN to a valid auth token. "
|
|
142
|
+
"You can find your auth token in the LocalStack web app https://app.localstack.cloud.",
|
|
143
|
+
err=True,
|
|
144
|
+
)
|
|
145
|
+
return
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
auth_config = get_auth_cache()
|
|
149
|
+
except Exception as e:
|
|
150
|
+
raise ClickException(
|
|
151
|
+
f"Could not load auth configuration from {pro_config.AUTH_CACHE_PATH}: {e}"
|
|
152
|
+
) from e
|
|
153
|
+
|
|
154
|
+
token = auth_config.get(ENV_LOCALSTACK_AUTH_TOKEN, "")
|
|
155
|
+
if not token:
|
|
156
|
+
click.echo(
|
|
157
|
+
"Token not configured in environment yet, please run localstack auth set-token "
|
|
158
|
+
"<AUTH_TOKEN>, or set the environment variable LOCALSTACK_AUTH_TOKEN to a valid auth token. "
|
|
159
|
+
"You can find your auth token in the LocalStack web app https://app.localstack.cloud.",
|
|
160
|
+
err=True,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
_print_token_info(AuthToken(token))
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@auth.command(
|
|
167
|
+
name="login",
|
|
168
|
+
short_help="Login to the your LocalStack account",
|
|
169
|
+
help="""
|
|
170
|
+
Login to the LocalStack Platform.
|
|
171
|
+
|
|
172
|
+
This command performs a login to your LocalStack account, giving you access to features that require
|
|
173
|
+
platform permissions, such as uploading cloud pods to your account.
|
|
174
|
+
|
|
175
|
+
This command is deprecated and it will be removed soon.
|
|
176
|
+
To use LocalStack features that requires authentication to the LocalStack platform
|
|
177
|
+
(e.g., Cloud Pods), please run `localstack auth set-token <AUTH_TOKEN>`, or set the
|
|
178
|
+
environment variable `LOCALSTACK_AUTH_TOKEN` to a valid auth token.
|
|
179
|
+
""",
|
|
180
|
+
deprecated=True,
|
|
181
|
+
)
|
|
182
|
+
@click.option(
|
|
183
|
+
"-u",
|
|
184
|
+
"--username",
|
|
185
|
+
help="Username (email address) for login",
|
|
186
|
+
metavar="USER",
|
|
187
|
+
required=True,
|
|
188
|
+
)
|
|
189
|
+
@click.option(
|
|
190
|
+
"-p",
|
|
191
|
+
"--password",
|
|
192
|
+
help="Password for login",
|
|
193
|
+
metavar="PWD",
|
|
194
|
+
prompt=True,
|
|
195
|
+
hide_input=True,
|
|
196
|
+
confirmation_prompt=False, # don't ask a second time
|
|
197
|
+
required=True,
|
|
198
|
+
)
|
|
199
|
+
@publish_invocation
|
|
200
|
+
def login(username: str, password: str) -> None:
|
|
201
|
+
from localstack_cli.pro.core.bootstrap import auth
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
auth.login(username, password)
|
|
205
|
+
click.echo("successfully logged in")
|
|
206
|
+
except Exception as e:
|
|
207
|
+
raise click.ClickException(f"Authentication Error: {e}")
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
@auth.command(
|
|
211
|
+
name="logout",
|
|
212
|
+
short_help="Log out from your LocalStack account",
|
|
213
|
+
help="""
|
|
214
|
+
Log out from the LocalStack Platform.
|
|
215
|
+
|
|
216
|
+
This command performs a logout from the LocalStack platform and deletes all session information on your
|
|
217
|
+
machine.
|
|
218
|
+
""",
|
|
219
|
+
deprecated=True,
|
|
220
|
+
)
|
|
221
|
+
@publish_invocation
|
|
222
|
+
def logout() -> None:
|
|
223
|
+
from localstack_cli.pro.core.bootstrap import auth
|
|
224
|
+
|
|
225
|
+
auth.logout()
|
|
226
|
+
click.echo("successfully logged out")
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from localstack_cli.pro.core.cli.cli import RequiresLicenseGroup
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@click.group(
|
|
6
|
+
name="aws",
|
|
7
|
+
short_help="Access additional functionality on LocalStack AWS Services",
|
|
8
|
+
help="""
|
|
9
|
+
Accesses additional functionality on LocalStack emulated AWS services.
|
|
10
|
+
|
|
11
|
+
This command provides tools to enhance your experience with certain emulated AWS services.
|
|
12
|
+
""",
|
|
13
|
+
cls=RequiresLicenseGroup,
|
|
14
|
+
)
|
|
15
|
+
def aws() -> None:
|
|
16
|
+
pass
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import typing as t
|
|
2
|
+
from gettext import gettext
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
import requests
|
|
6
|
+
from click import echo
|
|
7
|
+
from click._compat import get_text_stderr
|
|
8
|
+
from localstack_cli import config
|
|
9
|
+
from localstack_cli.cli.exceptions import CLIError
|
|
10
|
+
from localstack_cli.pro.core.bootstrap.licensingv2 import LicensingError, get_product_entitlements
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LicensingCLIError(CLIError):
|
|
14
|
+
"""A ClickException with a friendlier error message tailored to licensing errors."""
|
|
15
|
+
|
|
16
|
+
def format_message(self) -> str:
|
|
17
|
+
return (
|
|
18
|
+
click.style("👋 This feature is part of our paid offering!", fg="yellow") + self.message
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
def show(self, file: t.IO[t.Any] | None = None) -> None:
|
|
22
|
+
if file is None:
|
|
23
|
+
file = get_text_stderr()
|
|
24
|
+
|
|
25
|
+
echo(gettext(self.format_message()), file=file)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class RequiresLicenseGroup(click.Group):
|
|
29
|
+
"""
|
|
30
|
+
Special click command group that ensures a license was activated before invoking the command.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
is_pro_command = True
|
|
34
|
+
"""Needed for localstack to properly group commands"""
|
|
35
|
+
|
|
36
|
+
def invoke(self, ctx: click.Context) -> t.Any:
|
|
37
|
+
from localstack_cli.pro.core.bootstrap.licensingv2 import get_licensed_environment
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
get_licensed_environment().activate_license()
|
|
41
|
+
except LicensingError as e:
|
|
42
|
+
raise LicensingCLIError(e.get_user_friendly_cli())
|
|
43
|
+
|
|
44
|
+
return super().invoke(ctx)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class RequiresPlatformLicenseGroup(click.Group):
|
|
48
|
+
"""
|
|
49
|
+
Base class for special click command groups that ensures a license includes a specified product.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
namespace = "localstack.platform.plugin"
|
|
53
|
+
# "paid" isn't a tier, but it avoids exposing "Pro"
|
|
54
|
+
tier = "paid"
|
|
55
|
+
|
|
56
|
+
# Needs to be provided by the specific feature to be gated
|
|
57
|
+
name: str
|
|
58
|
+
|
|
59
|
+
is_pro_command = True
|
|
60
|
+
"""Needed for localstack to properly group commands"""
|
|
61
|
+
|
|
62
|
+
def invoke(self, ctx: click.Context) -> t.Any:
|
|
63
|
+
try:
|
|
64
|
+
if not self.is_feature_allowed():
|
|
65
|
+
# TODO make this message more feature agnostic to allow for feature gating instead of tier gating message
|
|
66
|
+
raise LicensingCLIError(f"""
|
|
67
|
+
=============================================
|
|
68
|
+
You tried to use a LocalStack feature that requires a {self.tier} subscription,
|
|
69
|
+
but the license did not contain the required subscription! 🔑❌
|
|
70
|
+
|
|
71
|
+
Due to this error, LocalStack has quit.
|
|
72
|
+
|
|
73
|
+
Please verify that your license includes the required tier for this feature. You can find your credentials in our
|
|
74
|
+
webapp at https://app.localstack.cloud.
|
|
75
|
+
""")
|
|
76
|
+
except LicensingError as e:
|
|
77
|
+
raise LicensingCLIError(e.get_user_friendly_cli())
|
|
78
|
+
return super().invoke(ctx)
|
|
79
|
+
|
|
80
|
+
def is_feature_allowed(self) -> bool:
|
|
81
|
+
from localstack_cli.pro.core.bootstrap.licensingv2 import get_licensed_environment
|
|
82
|
+
|
|
83
|
+
licensed_environment = get_licensed_environment()
|
|
84
|
+
licensed_environment.activate_license()
|
|
85
|
+
|
|
86
|
+
product_name = f"{self.namespace}/{self.name}"
|
|
87
|
+
return product_name in get_product_entitlements(licensed_environment)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _assert_host_reachable() -> None:
|
|
91
|
+
"""
|
|
92
|
+
Ensures the host is up by opening the edge url. If a ConnectionRefusedError is raised it raises a ClickException -
|
|
93
|
+
terminating with an error message.
|
|
94
|
+
:raises: ClickException if the URL could not be reached
|
|
95
|
+
"""
|
|
96
|
+
try:
|
|
97
|
+
requests.get(config.external_service_url())
|
|
98
|
+
except requests.ConnectionError:
|
|
99
|
+
raise CLIError("Destination host unreachable. Please make sure LocalStack is running.")
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from localstack_cli.cli import console
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def print_table(column_headers: list[str], columns: list[list]) -> None:
|
|
5
|
+
"""
|
|
6
|
+
Print a generic table to console
|
|
7
|
+
:param column_headers: the header of the columns
|
|
8
|
+
:param columns: the values in the columns
|
|
9
|
+
"""
|
|
10
|
+
from rich.table import Table
|
|
11
|
+
|
|
12
|
+
assert len(column_headers) == len(columns)
|
|
13
|
+
|
|
14
|
+
grid = Table(show_header=True, header_style="bold")
|
|
15
|
+
for column in column_headers:
|
|
16
|
+
grid.add_column(column)
|
|
17
|
+
|
|
18
|
+
for r in zip(*columns, strict=False):
|
|
19
|
+
grid.add_row(*r)
|
|
20
|
+
|
|
21
|
+
console.print(grid)
|