twc-cli 2.12.0__tar.gz → 2.13.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.
Potentially problematic release.
This version of twc-cli might be problematic. Click here for more details.
- {twc_cli-2.12.0 → twc_cli-2.13.0}/CHANGELOG.md +7 -1
- {twc_cli-2.12.0 → twc_cli-2.13.0}/PKG-INFO +4 -4
- {twc_cli-2.12.0 → twc_cli-2.13.0}/pyproject.toml +2 -2
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/__main__.py +2 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/__version__.py +1 -1
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/api/client.py +41 -2
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/__init__.py +1 -0
- twc_cli-2.13.0/twc/commands/apps.py +337 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/COPYING +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/README.md +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/__init__.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/api/__init__.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/api/base.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/api/exceptions.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/api/types.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/apiwrap.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/account.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/balancer.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/common.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/config.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/database.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/domain.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/firewall.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/floating_ip.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/image.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/kubernetes.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/project.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/server.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/ssh_key.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/storage.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/commands/vpc.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/fmt.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/typerx.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/utils.py +0 -0
- {twc_cli-2.12.0 → twc_cli-2.13.0}/twc/vars.py +0 -0
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
В этом файле описаны все значимые изменения в Timeweb Cloud CLI. В выпусках мы придерживается правил [семантического версионирования](https://semver.org/lang/ru/).
|
|
4
4
|
|
|
5
|
-
# Версия 2.
|
|
5
|
+
# Версия 2.13.0 (2025.06.17)
|
|
6
|
+
|
|
7
|
+
## Добавлено
|
|
8
|
+
|
|
9
|
+
- Добавлена новая команда `twc apps` для управления сервисом Cloud Apps.
|
|
10
|
+
|
|
11
|
+
# Версия 2.12.0 (2025.04.11)
|
|
6
12
|
|
|
7
13
|
## Добавлено
|
|
8
14
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: twc-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.13.0
|
|
4
4
|
Summary: Timeweb Cloud Command Line Interface.
|
|
5
|
-
Home-page: https://github.com/timeweb-cloud/twc
|
|
6
5
|
License: MIT
|
|
7
6
|
Author: ge
|
|
8
7
|
Author-email: dev@timeweb.cloud
|
|
@@ -17,10 +16,11 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
17
16
|
Requires-Dist: colorama (>=0.4.6,<0.5.0)
|
|
18
17
|
Requires-Dist: pygments (>=2.18.0,<3.0.0)
|
|
19
18
|
Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
|
|
20
|
-
Requires-Dist: requests (>=2.32.
|
|
19
|
+
Requires-Dist: requests (>=2.32.4,<3.0.0)
|
|
21
20
|
Requires-Dist: shellingham (>=1.5.4,<2.0.0)
|
|
22
21
|
Requires-Dist: toml (>=0.10.2,<0.11.0)
|
|
23
22
|
Requires-Dist: typer-slim (>=0.12.3,<0.13.0)
|
|
23
|
+
Project-URL: Homepage, https://github.com/timeweb-cloud/twc
|
|
24
24
|
Project-URL: Repository, https://github.com/timeweb-cloud/twc
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "twc-cli"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.13.0"
|
|
4
4
|
description = "Timeweb Cloud Command Line Interface."
|
|
5
5
|
authors = ["ge <dev@timeweb.cloud>"]
|
|
6
6
|
homepage = "https://github.com/timeweb-cloud/twc"
|
|
@@ -12,7 +12,7 @@ packages = [{ include = "twc", from = "." }]
|
|
|
12
12
|
|
|
13
13
|
[tool.poetry.dependencies]
|
|
14
14
|
python = "^3.8.19"
|
|
15
|
-
requests = "^2.32.
|
|
15
|
+
requests = "^2.32.4"
|
|
16
16
|
typer-slim = "^0.12.3"
|
|
17
17
|
shellingham = "^1.5.4"
|
|
18
18
|
colorama = "^0.4.6"
|
|
@@ -22,6 +22,7 @@ from .commands import (
|
|
|
22
22
|
firewall,
|
|
23
23
|
floating_ip,
|
|
24
24
|
whoami,
|
|
25
|
+
apps,
|
|
25
26
|
)
|
|
26
27
|
from .commands.common import version_callback, version_option, verbose_option
|
|
27
28
|
|
|
@@ -33,6 +34,7 @@ cli = TyperAlias(
|
|
|
33
34
|
)
|
|
34
35
|
cli.add_typer(config, name="config")
|
|
35
36
|
cli.add_typer(account, name="account")
|
|
37
|
+
cli.add_typer(apps, name="apps")
|
|
36
38
|
cli.add_typer(server, name="server", aliases=["servers", "s"])
|
|
37
39
|
cli.add_typer(ssh_key, name="ssh-key", aliases=["ssh-keys", "k"])
|
|
38
40
|
cli.add_typer(image, name="image", aliases=["images", "i"])
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
from ipaddress import IPv4Address, IPv6Address, IPv4Network, IPv6Network
|
|
5
6
|
from typing import Optional, Union, List
|
|
6
|
-
from uuid import UUID
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from
|
|
8
|
+
from uuid import UUID
|
|
9
|
+
|
|
10
|
+
import yaml
|
|
9
11
|
|
|
10
12
|
from .base import TimewebCloudBase
|
|
11
13
|
from .types import (
|
|
@@ -34,6 +36,43 @@ from .types import (
|
|
|
34
36
|
class TimewebCloud(TimewebCloudBase):
|
|
35
37
|
"""Timeweb Cloud API client class."""
|
|
36
38
|
|
|
39
|
+
# -----------------------------------------------------------------------
|
|
40
|
+
# Apps
|
|
41
|
+
|
|
42
|
+
def get_apps(self):
|
|
43
|
+
"""Return Timeweb Cloud apps list."""
|
|
44
|
+
return self._request("GET", f"{self.api_url}/apps")
|
|
45
|
+
|
|
46
|
+
def create_app(self, yaml_config_path: str):
|
|
47
|
+
"""Create Timeweb Cloud app."""
|
|
48
|
+
|
|
49
|
+
with open(yaml_config_path, "r", encoding="utf-8") as f:
|
|
50
|
+
payload = yaml.safe_load(f)
|
|
51
|
+
payload = payload["app"]
|
|
52
|
+
return self._request("POST", f"{self.api_url}/apps", json=payload)
|
|
53
|
+
|
|
54
|
+
def get_app(self, app_id: int):
|
|
55
|
+
"""Return Timeweb Cloud app."""
|
|
56
|
+
return self._request("GET", f"{self.api_url}/apps/{app_id}")
|
|
57
|
+
|
|
58
|
+
def get_vcs_providers(self):
|
|
59
|
+
"""Return Timeweb Cloud vcs providers."""
|
|
60
|
+
return self._request("GET", f"{self.api_url}/vcs-provider")
|
|
61
|
+
|
|
62
|
+
def get_repositories(self, vcs_provider_id: str):
|
|
63
|
+
"""Return Timeweb Cloud user vcs repositories."""
|
|
64
|
+
return self._request(
|
|
65
|
+
"GET", f"{self.api_url}/vcs-provider/{vcs_provider_id}"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
def get_apps_tarifs(self):
|
|
69
|
+
"""Return Timeweb Cloud Apps tarifs"""
|
|
70
|
+
return self._request("GET", f"{self.api_url}/presets/apps")
|
|
71
|
+
|
|
72
|
+
def delete_app(self, app_id: int):
|
|
73
|
+
"""Delete Timeweb Cloud app."""
|
|
74
|
+
return self._request("DELETE", f"{self.api_url}/apps/{app_id}")
|
|
75
|
+
|
|
37
76
|
# -----------------------------------------------------------------------
|
|
38
77
|
# Account
|
|
39
78
|
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
"""Manage apps."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from requests import Response
|
|
8
|
+
|
|
9
|
+
from twc import fmt
|
|
10
|
+
from twc.typerx import TyperAlias
|
|
11
|
+
from twc.apiwrap import create_client
|
|
12
|
+
from .common import (
|
|
13
|
+
verbose_option,
|
|
14
|
+
config_option,
|
|
15
|
+
profile_option,
|
|
16
|
+
filter_option,
|
|
17
|
+
output_format_option,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
apps = TyperAlias(help=__doc__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ------------------------------------------------------------- #
|
|
25
|
+
# $ twc apps list #
|
|
26
|
+
# ------------------------------------------------------------- #
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def print_apps(response: Response, filters: Optional[str]):
|
|
30
|
+
"""Print table with apps list."""
|
|
31
|
+
# pylint: disable=invalid-name
|
|
32
|
+
_apps = response.json()["apps"]
|
|
33
|
+
if filters:
|
|
34
|
+
_apps = fmt.filter_list(_apps, filters)
|
|
35
|
+
table = fmt.Table()
|
|
36
|
+
table.header(
|
|
37
|
+
[
|
|
38
|
+
"ID",
|
|
39
|
+
"NAME",
|
|
40
|
+
"STATUS",
|
|
41
|
+
"TYPE",
|
|
42
|
+
"IPV4",
|
|
43
|
+
]
|
|
44
|
+
)
|
|
45
|
+
for app in _apps:
|
|
46
|
+
table.row(
|
|
47
|
+
[
|
|
48
|
+
app["id"],
|
|
49
|
+
app["name"],
|
|
50
|
+
app["status"],
|
|
51
|
+
app["type"],
|
|
52
|
+
app["ip"],
|
|
53
|
+
]
|
|
54
|
+
)
|
|
55
|
+
table.print()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@apps.command("list", "ls")
|
|
59
|
+
def apps_list(
|
|
60
|
+
verbose: Optional[bool] = verbose_option,
|
|
61
|
+
config: Optional[Path] = config_option,
|
|
62
|
+
profile: Optional[str] = profile_option,
|
|
63
|
+
output_format: Optional[str] = output_format_option,
|
|
64
|
+
filters: Optional[str] = filter_option,
|
|
65
|
+
):
|
|
66
|
+
"""List apps."""
|
|
67
|
+
client = create_client(config, profile)
|
|
68
|
+
response = client.get_apps()
|
|
69
|
+
fmt.printer(
|
|
70
|
+
response,
|
|
71
|
+
output_format=output_format,
|
|
72
|
+
filters=filters,
|
|
73
|
+
func=print_apps,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@apps.command("create")
|
|
78
|
+
def app_create(
|
|
79
|
+
yml_config_path: str,
|
|
80
|
+
verbose: Optional[bool] = verbose_option,
|
|
81
|
+
config: Optional[Path] = config_option,
|
|
82
|
+
profile: Optional[str] = profile_option,
|
|
83
|
+
output_format: Optional[str] = output_format_option,
|
|
84
|
+
status: Optional[bool] = typer.Option(
|
|
85
|
+
False,
|
|
86
|
+
"--status",
|
|
87
|
+
help="Display status and exit with 0 if status is 'started'.",
|
|
88
|
+
),
|
|
89
|
+
):
|
|
90
|
+
"""Create app"""
|
|
91
|
+
client = create_client(config, profile)
|
|
92
|
+
response = client.create_app(yml_config_path)
|
|
93
|
+
fmt.printer(
|
|
94
|
+
response,
|
|
95
|
+
output_format=output_format,
|
|
96
|
+
func=lambda response: print(response.json()["app"]["id"]),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def print_vcs_providers(response: Response):
|
|
101
|
+
"""Print table with vcs list."""
|
|
102
|
+
# pylint: disable=invalid-name
|
|
103
|
+
providers = response.json()["providers"]
|
|
104
|
+
table = fmt.Table()
|
|
105
|
+
table.header(
|
|
106
|
+
[
|
|
107
|
+
"LOGIN",
|
|
108
|
+
"PROVIDER",
|
|
109
|
+
"PROVIDER_ID",
|
|
110
|
+
]
|
|
111
|
+
)
|
|
112
|
+
for provider in providers:
|
|
113
|
+
table.row(
|
|
114
|
+
[
|
|
115
|
+
provider["login"],
|
|
116
|
+
provider["provider"],
|
|
117
|
+
provider["provider_id"],
|
|
118
|
+
]
|
|
119
|
+
)
|
|
120
|
+
table.print()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@apps.command("get-vcs-providers")
|
|
124
|
+
def app_get_vcs_providers(
|
|
125
|
+
verbose: Optional[bool] = verbose_option,
|
|
126
|
+
config: Optional[Path] = config_option,
|
|
127
|
+
profile: Optional[str] = profile_option,
|
|
128
|
+
output_format: Optional[str] = output_format_option,
|
|
129
|
+
):
|
|
130
|
+
"""Get VCS providers."""
|
|
131
|
+
client = create_client(config, profile)
|
|
132
|
+
response = client.get_vcs_providers()
|
|
133
|
+
fmt.printer(
|
|
134
|
+
response, output_format=output_format, func=print_vcs_providers
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def print_vcs_repositories(response: Response):
|
|
139
|
+
"""Print table with vcs list."""
|
|
140
|
+
# pylint: disable=invalid-name
|
|
141
|
+
providers = response.json()["repositories"]
|
|
142
|
+
table = fmt.Table()
|
|
143
|
+
table.header(["FULL NAME", "ID", "NAME", "URL", "IS PRIVATE"])
|
|
144
|
+
for provider in providers:
|
|
145
|
+
table.row(
|
|
146
|
+
[
|
|
147
|
+
provider["full_name"],
|
|
148
|
+
provider["id"],
|
|
149
|
+
provider["name"],
|
|
150
|
+
provider["url"],
|
|
151
|
+
provider["is_private"],
|
|
152
|
+
]
|
|
153
|
+
)
|
|
154
|
+
table.print()
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@apps.command("get-repositories")
|
|
158
|
+
def app_get_repositories(
|
|
159
|
+
vcs_provider_id: str,
|
|
160
|
+
verbose: Optional[bool] = verbose_option,
|
|
161
|
+
config: Optional[Path] = config_option,
|
|
162
|
+
profile: Optional[str] = profile_option,
|
|
163
|
+
output_format: Optional[str] = output_format_option,
|
|
164
|
+
):
|
|
165
|
+
"""Get repositories."""
|
|
166
|
+
client = create_client(config, profile)
|
|
167
|
+
response = client.get_repositories(vcs_provider_id)
|
|
168
|
+
fmt.printer(
|
|
169
|
+
response, output_format=output_format, func=print_vcs_repositories
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def print_apps_tarifs(response: Response, typ: str):
|
|
174
|
+
"""Print Timeweb Cloud Apps tarifs."""
|
|
175
|
+
# pylint: disable=invalid-name
|
|
176
|
+
if typ == "backend":
|
|
177
|
+
key = "backend_presets"
|
|
178
|
+
elif typ == "frontend":
|
|
179
|
+
key = "frontend_presets"
|
|
180
|
+
else:
|
|
181
|
+
raise KeyError("Tarifs can be only backend or frontend")
|
|
182
|
+
|
|
183
|
+
providers = response.json()[key]
|
|
184
|
+
table = fmt.Table()
|
|
185
|
+
if key == "backend_presets":
|
|
186
|
+
table.header(
|
|
187
|
+
[
|
|
188
|
+
"CPU",
|
|
189
|
+
"CPU FREQUENCY",
|
|
190
|
+
"DESCRIPTION",
|
|
191
|
+
"DESCRIPTION SHORT",
|
|
192
|
+
"DISK",
|
|
193
|
+
"ID",
|
|
194
|
+
"LOCATION",
|
|
195
|
+
"PRICE",
|
|
196
|
+
"RAM",
|
|
197
|
+
]
|
|
198
|
+
)
|
|
199
|
+
for provider in providers:
|
|
200
|
+
table.row(
|
|
201
|
+
[
|
|
202
|
+
provider["cpu"],
|
|
203
|
+
provider["cpu_frequency"],
|
|
204
|
+
provider["description"],
|
|
205
|
+
provider["description_short"],
|
|
206
|
+
provider["disk"],
|
|
207
|
+
provider["id"],
|
|
208
|
+
provider["location"],
|
|
209
|
+
provider["price"],
|
|
210
|
+
provider["ram"],
|
|
211
|
+
]
|
|
212
|
+
)
|
|
213
|
+
elif key == "frontend_presets":
|
|
214
|
+
table.header(
|
|
215
|
+
[
|
|
216
|
+
"DESCRIPTION",
|
|
217
|
+
"DESCRIPTION_SHORT",
|
|
218
|
+
"DISK",
|
|
219
|
+
"ID",
|
|
220
|
+
"LOCATION",
|
|
221
|
+
"PRICE",
|
|
222
|
+
"REQUESTS",
|
|
223
|
+
]
|
|
224
|
+
)
|
|
225
|
+
for provider in providers:
|
|
226
|
+
table.row(
|
|
227
|
+
[
|
|
228
|
+
provider["description"],
|
|
229
|
+
provider["description_short"],
|
|
230
|
+
provider["disk"],
|
|
231
|
+
provider["id"],
|
|
232
|
+
provider["location"],
|
|
233
|
+
provider["price"],
|
|
234
|
+
provider["requests"],
|
|
235
|
+
]
|
|
236
|
+
)
|
|
237
|
+
table.print()
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
@apps.command("list-presets")
|
|
241
|
+
def get_apps_tarifs(
|
|
242
|
+
_type: str = typer.Argument(..., metavar="TYPE"),
|
|
243
|
+
verbose: Optional[bool] = verbose_option,
|
|
244
|
+
config: Optional[Path] = config_option,
|
|
245
|
+
profile: Optional[str] = profile_option,
|
|
246
|
+
output_format: Optional[str] = output_format_option,
|
|
247
|
+
):
|
|
248
|
+
"""Get tarifs; backend or frontend"""
|
|
249
|
+
client = create_client(config, profile)
|
|
250
|
+
response = client.get_apps_tarifs()
|
|
251
|
+
fmt.printer(
|
|
252
|
+
response,
|
|
253
|
+
output_format=output_format,
|
|
254
|
+
typ=_type,
|
|
255
|
+
func=print_apps_tarifs,
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def print_app_delete_response(response: Response, app_id: int):
|
|
260
|
+
"""Print table with apps list."""
|
|
261
|
+
# pylint: disable=invalid-name
|
|
262
|
+
table = fmt.Table()
|
|
263
|
+
table.header(
|
|
264
|
+
[
|
|
265
|
+
"ID",
|
|
266
|
+
]
|
|
267
|
+
)
|
|
268
|
+
table.row(
|
|
269
|
+
[
|
|
270
|
+
app_id,
|
|
271
|
+
]
|
|
272
|
+
)
|
|
273
|
+
table.print()
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
@apps.command("delete")
|
|
277
|
+
def delete_app(
|
|
278
|
+
app_id: int,
|
|
279
|
+
verbose: Optional[bool] = verbose_option,
|
|
280
|
+
config: Optional[Path] = config_option,
|
|
281
|
+
profile: Optional[str] = profile_option,
|
|
282
|
+
output_format: Optional[str] = output_format_option,
|
|
283
|
+
):
|
|
284
|
+
"""Delete apps."""
|
|
285
|
+
client = create_client(config, profile)
|
|
286
|
+
response = client.delete_app(app_id)
|
|
287
|
+
fmt.printer(
|
|
288
|
+
response,
|
|
289
|
+
output_format=output_format,
|
|
290
|
+
app_id=app_id,
|
|
291
|
+
func=print_app_delete_response,
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def get_app(response: Response):
|
|
296
|
+
"""Print table with apps list."""
|
|
297
|
+
# pylint: disable=invalid-name
|
|
298
|
+
app = response.json()["app"]
|
|
299
|
+
table = fmt.Table()
|
|
300
|
+
table.header(
|
|
301
|
+
[
|
|
302
|
+
"ID",
|
|
303
|
+
"LOCATION",
|
|
304
|
+
"STATUS",
|
|
305
|
+
"TYPE",
|
|
306
|
+
"IPV4",
|
|
307
|
+
]
|
|
308
|
+
)
|
|
309
|
+
table.row(
|
|
310
|
+
[
|
|
311
|
+
app["id"],
|
|
312
|
+
app["location"],
|
|
313
|
+
app["status"],
|
|
314
|
+
app["type"],
|
|
315
|
+
app["ip"],
|
|
316
|
+
]
|
|
317
|
+
)
|
|
318
|
+
table.print()
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
@apps.command("get")
|
|
322
|
+
def app_get(
|
|
323
|
+
app_id: int,
|
|
324
|
+
verbose: Optional[bool] = verbose_option,
|
|
325
|
+
config: Optional[Path] = config_option,
|
|
326
|
+
profile: Optional[str] = profile_option,
|
|
327
|
+
output_format: Optional[str] = output_format_option,
|
|
328
|
+
status: Optional[bool] = typer.Option(
|
|
329
|
+
False,
|
|
330
|
+
"--status",
|
|
331
|
+
help="Display status and exit with 0 if status is 'started'.",
|
|
332
|
+
),
|
|
333
|
+
):
|
|
334
|
+
"""Get database info."""
|
|
335
|
+
client = create_client(config, profile)
|
|
336
|
+
response = client.get_app(app_id)
|
|
337
|
+
fmt.printer(response, output_format=output_format, func=get_app)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|