twc-cli 2.6.0__py3-none-any.whl → 2.7.0__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.
Potentially problematic release.
This version of twc-cli might be problematic. Click here for more details.
- CHANGELOG.md +21 -0
- twc/__main__.py +2 -0
- twc/__version__.py +1 -1
- twc/api/client.py +5 -4
- twc/apiwrap.py +6 -1
- twc/commands/__init__.py +1 -1
- twc/commands/account.py +30 -0
- twc/commands/domain.py +28 -12
- twc/commands/project.py +2 -8
- twc/commands/server.py +1 -3
- twc/commands/storage.py +6 -7
- twc/fmt.py +11 -4
- twc/vars.py +1 -1
- {twc_cli-2.6.0.dist-info → twc_cli-2.7.0.dist-info}/METADATA +1 -1
- {twc_cli-2.6.0.dist-info → twc_cli-2.7.0.dist-info}/RECORD +18 -18
- {twc_cli-2.6.0.dist-info → twc_cli-2.7.0.dist-info}/COPYING +0 -0
- {twc_cli-2.6.0.dist-info → twc_cli-2.7.0.dist-info}/WHEEL +0 -0
- {twc_cli-2.6.0.dist-info → twc_cli-2.7.0.dist-info}/entry_points.txt +0 -0
CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
В этом файле описаны все значимые изменения в Timeweb Cloud CLI. В выпусках мы придерживается правил [семантического версионирования](https://semver.org/lang/ru/).
|
|
4
4
|
|
|
5
|
+
# Версия 2.7.0 (2024.11.02)
|
|
6
|
+
|
|
7
|
+
## Добавлено
|
|
8
|
+
|
|
9
|
+
- Добавлена новая команда `twc whoami`, которая показывает логин аккаунта, в котором в текущий момент авторизован CLI.
|
|
10
|
+
|
|
11
|
+
## Изменено
|
|
12
|
+
|
|
13
|
+
- Команда `twc account status` теперь также отображает логин аккаунта.
|
|
14
|
+
|
|
15
|
+
## Исправлено
|
|
16
|
+
|
|
17
|
+
- Устранено падение программы при листинге образов (`twc image list`) и при создании сервера из образа.
|
|
18
|
+
- Исправлена ошибка при создании сервера с приватной сетью в зоне доступности SPB-3.
|
|
19
|
+
- Исправлены ошибки в командах `twc storage subdomain gencert` и `twc storage subdomain remove`, возникшие из-за нарушения обратной совместимости эндпоинтов API.
|
|
20
|
+
- Исправлена ошибка валидации приватного адреса при созаднии сервера — ошибочно запрещалось использовать 4-й по порядку адрес в подсети.
|
|
21
|
+
- Исправлена ошибка разбора JSON при выводе списка ресурсов в проекте.
|
|
22
|
+
- Исправлены ошибки добавления TXT записи для домена в команде `twc domain record add`.
|
|
23
|
+
- Исправлена ошибка парсинка субдомена в команде `twc domain record add`.
|
|
24
|
+
- Исправлены ошибки обновления DNS-записей на поддоменах.
|
|
25
|
+
|
|
5
26
|
# Версия 2.6.0 (2024.08.14)
|
|
6
27
|
|
|
7
28
|
## Добавлено
|
twc/__main__.py
CHANGED
|
@@ -21,6 +21,7 @@ from .commands import (
|
|
|
21
21
|
vpc,
|
|
22
22
|
firewall,
|
|
23
23
|
floating_ip,
|
|
24
|
+
whoami,
|
|
24
25
|
)
|
|
25
26
|
from .commands.common import version_callback, version_option, verbose_option
|
|
26
27
|
|
|
@@ -46,6 +47,7 @@ cli.add_typer(domain, name="domain", aliases=["domains", "d"])
|
|
|
46
47
|
cli.add_typer(vpc, name="vpc", aliases=["vpcs", "network", "networks"])
|
|
47
48
|
cli.add_typer(firewall, name="firewall", aliases=["fw"])
|
|
48
49
|
cli.add_typer(floating_ip, name="ip", aliases=["ips"])
|
|
50
|
+
cli.add_typer(whoami, name="whoami", aliases=[])
|
|
49
51
|
|
|
50
52
|
|
|
51
53
|
@cli.command("version")
|
twc/__version__.py
CHANGED
twc/api/client.py
CHANGED
|
@@ -469,14 +469,11 @@ class TimewebCloud(TimewebCloudBase):
|
|
|
469
469
|
# -----------------------------------------------------------------------
|
|
470
470
|
# Images
|
|
471
471
|
|
|
472
|
-
def get_images(
|
|
473
|
-
self, limit: int = 100, offset: int = 0, with_deleted: bool = False
|
|
474
|
-
):
|
|
472
|
+
def get_images(self, limit: int = 100, offset: int = 0):
|
|
475
473
|
"""Get list of images."""
|
|
476
474
|
params = {
|
|
477
475
|
"limit": limit,
|
|
478
476
|
"offset": offset,
|
|
479
|
-
"with_deleted": with_deleted,
|
|
480
477
|
}
|
|
481
478
|
return self._request("GET", f"{self.api_url}/images", params=params)
|
|
482
479
|
|
|
@@ -1416,6 +1413,8 @@ class TimewebCloud(TimewebCloudBase):
|
|
|
1416
1413
|
value: str,
|
|
1417
1414
|
subdomain: Optional[str] = None,
|
|
1418
1415
|
priority: Optional[int] = None,
|
|
1416
|
+
*,
|
|
1417
|
+
null_subdomain: bool = False,
|
|
1419
1418
|
):
|
|
1420
1419
|
"""Add DNS record to domain."""
|
|
1421
1420
|
payload = {
|
|
@@ -1424,6 +1423,8 @@ class TimewebCloud(TimewebCloudBase):
|
|
|
1424
1423
|
**({"subdomain": subdomain} if subdomain else {}),
|
|
1425
1424
|
**({"priority": priority} if priority else {}),
|
|
1426
1425
|
}
|
|
1426
|
+
if null_subdomain:
|
|
1427
|
+
payload["subdomain"] = None
|
|
1427
1428
|
return self._request(
|
|
1428
1429
|
"POST",
|
|
1429
1430
|
f"{self.api_url}/domains/{fqdn}/dns-records",
|
twc/apiwrap.py
CHANGED
|
@@ -4,7 +4,7 @@ import os
|
|
|
4
4
|
import sys
|
|
5
5
|
import textwrap
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from logging import debug
|
|
7
|
+
from logging import debug, warning
|
|
8
8
|
|
|
9
9
|
from .api import TimewebCloud
|
|
10
10
|
from .api import exceptions as exc
|
|
@@ -70,6 +70,11 @@ def create_client(config: Path, profile: str, **kwargs) -> TimewebCloud:
|
|
|
70
70
|
"""
|
|
71
71
|
token = os.getenv("TWC_TOKEN")
|
|
72
72
|
log_settings = os.getenv("TWC_LOG")
|
|
73
|
+
api_endpoint = os.getenv("TWC_ENDPOINT")
|
|
74
|
+
|
|
75
|
+
if api_endpoint:
|
|
76
|
+
warning("Using API URL from environment: %s", api_endpoint)
|
|
77
|
+
kwargs["api_base_url"] = api_endpoint
|
|
73
78
|
|
|
74
79
|
if log_settings:
|
|
75
80
|
for param in log_settings.split(","):
|
twc/commands/__init__.py
CHANGED
twc/commands/account.py
CHANGED
|
@@ -18,6 +18,35 @@ from .common import (
|
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
whoami = TyperAlias(help="Display current login.", no_args_is_help=False)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ------------------------------------------------------------- #
|
|
25
|
+
# $ twc whoami #
|
|
26
|
+
# ------------------------------------------------------------- #
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@whoami.callback(invoke_without_command=True)
|
|
30
|
+
def whoami_callback(
|
|
31
|
+
verbose: Optional[bool] = verbose_option,
|
|
32
|
+
config: Optional[Path] = config_option,
|
|
33
|
+
profile: Optional[str] = profile_option,
|
|
34
|
+
output_format: Optional[str] = output_format_option,
|
|
35
|
+
):
|
|
36
|
+
"""Display current login."""
|
|
37
|
+
client = create_client(config, profile)
|
|
38
|
+
response = client.get_account_status()
|
|
39
|
+
login = response.json()["status"]["login"]
|
|
40
|
+
fmt.printer(
|
|
41
|
+
{"login": login, "profile": profile},
|
|
42
|
+
output_format=output_format,
|
|
43
|
+
func=lambda data: print(data["login"]),
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# ------------------------------------------------------------- #
|
|
48
|
+
|
|
49
|
+
|
|
21
50
|
account = TyperAlias(help=__doc__)
|
|
22
51
|
account_access = TyperAlias(help="Manage account access restrictions.")
|
|
23
52
|
account.add_typer(account_access, name="access")
|
|
@@ -33,6 +62,7 @@ def print_account_status(response: Response):
|
|
|
33
62
|
status = response.json()["status"]
|
|
34
63
|
output = dedent(
|
|
35
64
|
f"""
|
|
65
|
+
Login: {status["login"]}
|
|
36
66
|
Provider: {status["company_info"]["name"]}
|
|
37
67
|
Yandex.Metrika ID: {status["ym_client_id"]}
|
|
38
68
|
Blocked: {status["is_blocked"]}
|
twc/commands/domain.py
CHANGED
|
@@ -195,7 +195,7 @@ def domain_delete(
|
|
|
195
195
|
# ------------------------------------------------------------- #
|
|
196
196
|
|
|
197
197
|
|
|
198
|
-
@domain.command("add")
|
|
198
|
+
@domain.command("add", "create")
|
|
199
199
|
def domain_add(
|
|
200
200
|
domain_name: str,
|
|
201
201
|
verbose: Optional[bool] = verbose_option,
|
|
@@ -316,7 +316,7 @@ def domain_remove_dns_record(
|
|
|
316
316
|
# ------------------------------------------------------------- #
|
|
317
317
|
|
|
318
318
|
|
|
319
|
-
@domain_record.command("add")
|
|
319
|
+
@domain_record.command("add", "create")
|
|
320
320
|
def domain_add_dns_record(
|
|
321
321
|
domain_name: str,
|
|
322
322
|
verbose: Optional[bool] = verbose_option,
|
|
@@ -346,29 +346,39 @@ def domain_add_dns_record(
|
|
|
346
346
|
"""Add dns record for domain or subdomain."""
|
|
347
347
|
client = create_client(config, profile)
|
|
348
348
|
|
|
349
|
+
null_subdomain = False
|
|
350
|
+
|
|
349
351
|
if second_ld:
|
|
350
352
|
offset = 3
|
|
351
353
|
else:
|
|
352
354
|
offset = 2
|
|
353
355
|
|
|
354
356
|
subdomain = domain_name
|
|
357
|
+
original_domain_name = domain_name
|
|
355
358
|
domain_name = ".".join(domain_name.split(".")[-offset:])
|
|
356
359
|
|
|
357
360
|
if subdomain == domain_name:
|
|
358
361
|
subdomain = None
|
|
359
362
|
|
|
360
|
-
# API issue: see text below
|
|
361
|
-
# API can add TXT record (only TXT, why?) with non-existent subdomain,
|
|
362
|
-
# but 'subdomain' option must not be passed as FQDN!
|
|
363
|
-
# API issue: You cannot create subdomains with underscore. Why?
|
|
364
|
-
# Use previous described bug for this! Pass your subdomain with
|
|
365
|
-
# underscores to this function.
|
|
366
363
|
if record_type.lower() == "txt":
|
|
367
|
-
|
|
368
|
-
|
|
364
|
+
if subdomain is None:
|
|
365
|
+
null_subdomain = True
|
|
366
|
+
else:
|
|
367
|
+
# 'ftp.example.org' --> 'ftp'
|
|
368
|
+
subdomain = ".".join(subdomain.split(".")[:-offset])
|
|
369
|
+
else:
|
|
370
|
+
subdomain = ".".join(original_domain_name.split(".")[:-offset])
|
|
371
|
+
if subdomain != "":
|
|
372
|
+
domain_name = original_domain_name
|
|
373
|
+
subdomain = None
|
|
369
374
|
|
|
370
375
|
response = client.add_domain_dns_record(
|
|
371
|
-
domain_name,
|
|
376
|
+
domain_name,
|
|
377
|
+
record_type,
|
|
378
|
+
value,
|
|
379
|
+
subdomain,
|
|
380
|
+
priority,
|
|
381
|
+
null_subdomain=null_subdomain,
|
|
372
382
|
)
|
|
373
383
|
fmt.printer(
|
|
374
384
|
response,
|
|
@@ -424,6 +434,12 @@ def domain_update_dns_records(
|
|
|
424
434
|
if subdomain == domain_name:
|
|
425
435
|
subdomain = None
|
|
426
436
|
|
|
437
|
+
if record_type.lower() == "txt" and subdomain is not None:
|
|
438
|
+
subdomain = ".".join(subdomain.split(".")[:-offset])
|
|
439
|
+
elif subdomain is not None:
|
|
440
|
+
domain_name = subdomain
|
|
441
|
+
subdomain = None
|
|
442
|
+
|
|
427
443
|
response = client.update_domain_dns_record(
|
|
428
444
|
domain_name, record_id, record_type, value, subdomain, priority
|
|
429
445
|
)
|
|
@@ -439,7 +455,7 @@ def domain_update_dns_records(
|
|
|
439
455
|
# ------------------------------------------------------------- #
|
|
440
456
|
|
|
441
457
|
|
|
442
|
-
@domain_subdomain.command("add")
|
|
458
|
+
@domain_subdomain.command("add", "create")
|
|
443
459
|
def domain_add_subdomain(
|
|
444
460
|
subdomain: str = typer.Argument(..., metavar="FQDN"),
|
|
445
461
|
verbose: Optional[bool] = verbose_option,
|
twc/commands/project.py
CHANGED
|
@@ -188,17 +188,11 @@ def print_resources(response: Response):
|
|
|
188
188
|
for key in resource_keys:
|
|
189
189
|
if resources[key]:
|
|
190
190
|
for resource in resources[key]:
|
|
191
|
-
try:
|
|
192
|
-
location = resource["location"]
|
|
193
|
-
except KeyError:
|
|
194
|
-
# Balancers, clusters, and databases has no 'location' field.
|
|
195
|
-
# These services is available only in 'ru-1' location.
|
|
196
|
-
location = "ru-1"
|
|
197
191
|
table.row(
|
|
198
192
|
[
|
|
199
193
|
resource["id"],
|
|
200
|
-
resource
|
|
201
|
-
location,
|
|
194
|
+
resource.get("name", resource.get("fqdn")),
|
|
195
|
+
resource.get("location", "ru-1"),
|
|
202
196
|
key[:-1], # this is resource name e.g. 'server'
|
|
203
197
|
]
|
|
204
198
|
)
|
twc/commands/server.py
CHANGED
|
@@ -584,9 +584,7 @@ def server_create(
|
|
|
584
584
|
net = IPv4Network(
|
|
585
585
|
client.get_vpc(network).json()["vpc"]["subnet_v4"]
|
|
586
586
|
)
|
|
587
|
-
if IPv4Address(private_ip)
|
|
588
|
-
int(net.network_address) + 4
|
|
589
|
-
):
|
|
587
|
+
if IPv4Address(private_ip) >= net.network_address + 4:
|
|
590
588
|
payload["network"]["ip"] = private_ip
|
|
591
589
|
else:
|
|
592
590
|
# First 3 addresses is reserved for networks OVN based networks
|
twc/commands/storage.py
CHANGED
|
@@ -500,7 +500,6 @@ def storage_subdomain_remove(
|
|
|
500
500
|
verbose: Optional[bool] = verbose_option,
|
|
501
501
|
config: Optional[Path] = config_option,
|
|
502
502
|
profile: Optional[str] = profile_option,
|
|
503
|
-
output_format: Optional[str] = output_format_option,
|
|
504
503
|
yes: Optional[bool] = yes_option,
|
|
505
504
|
):
|
|
506
505
|
"""Remove subdomains."""
|
|
@@ -509,11 +508,11 @@ def storage_subdomain_remove(
|
|
|
509
508
|
client = create_client(config, profile)
|
|
510
509
|
bucket_id = resolve_bucket_id(client, bucket)
|
|
511
510
|
response = client.delete_bucket_subdomains(bucket_id, subdomains)
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
511
|
+
if response.status_code == 204:
|
|
512
|
+
for subdomain in subdomains:
|
|
513
|
+
print(subdomain)
|
|
514
|
+
else:
|
|
515
|
+
sys.exit(fmt.printer(response))
|
|
517
516
|
|
|
518
517
|
|
|
519
518
|
# ------------------------------------------------------------- #
|
|
@@ -532,7 +531,7 @@ def storage_subdomain_gencert(
|
|
|
532
531
|
client = create_client(config, profile)
|
|
533
532
|
for subdomain in subdomains:
|
|
534
533
|
response = client.gen_cert_for_bucket_subdomain(subdomain)
|
|
535
|
-
if response.status_code ==
|
|
534
|
+
if response.status_code == 204:
|
|
536
535
|
print(subdomain)
|
|
537
536
|
else:
|
|
538
537
|
sys.exit(fmt.printer(response))
|
twc/fmt.py
CHANGED
|
@@ -67,6 +67,9 @@ class Printer:
|
|
|
67
67
|
|
|
68
68
|
def raw(self):
|
|
69
69
|
"""Print raw API response text (mostly raw JSON)."""
|
|
70
|
+
if isinstance(self._data, dict):
|
|
71
|
+
typer.echo(json.dumps(self._data))
|
|
72
|
+
return
|
|
70
73
|
typer.echo(self._data.text)
|
|
71
74
|
|
|
72
75
|
def colorize(self, data: str, lexer: object = JsonLexer()):
|
|
@@ -77,9 +80,12 @@ class Printer:
|
|
|
77
80
|
"""Print colorized JSON output. Fallback to non-color output if
|
|
78
81
|
Pygments not installed and fallback to raw output on JSONDecodeError.
|
|
79
82
|
"""
|
|
83
|
+
data = self._data
|
|
84
|
+
if not isinstance(self._data, dict):
|
|
85
|
+
data = self._data.json()
|
|
80
86
|
try:
|
|
81
87
|
json_data = json.dumps(
|
|
82
|
-
|
|
88
|
+
data, indent=4, sort_keys=True, ensure_ascii=False
|
|
83
89
|
)
|
|
84
90
|
self.colorize(json_data, lexer=JsonLexer())
|
|
85
91
|
except json.JSONDecodeError:
|
|
@@ -89,10 +95,11 @@ class Printer:
|
|
|
89
95
|
"""Print colorized YAML output. Fallback to non-color output if
|
|
90
96
|
Pygments not installed and fallback to raw output on YAMLError.
|
|
91
97
|
"""
|
|
98
|
+
data = self._data
|
|
99
|
+
if not isinstance(self._data, dict):
|
|
100
|
+
data = self._data.json()
|
|
92
101
|
try:
|
|
93
|
-
yaml_data = yaml.dump(
|
|
94
|
-
self._data.json(), sort_keys=True, allow_unicode=True
|
|
95
|
-
)
|
|
102
|
+
yaml_data = yaml.dump(data, sort_keys=True, allow_unicode=True)
|
|
96
103
|
self.colorize(yaml_data, lexer=YamlLexer())
|
|
97
104
|
except yaml.YAMLError:
|
|
98
105
|
self.raw()
|
twc/vars.py
CHANGED
|
@@ -11,4 +11,4 @@ CONTROL_PANEL_URL = "https://timeweb.cloud/my"
|
|
|
11
11
|
REGIONS_WITH_IPV6 = ["ru-1", "pl-1"]
|
|
12
12
|
REGIONS_WITH_IMAGES = ["ru-1", "ru-3", "kz-1", "pl-1", "nl-1"]
|
|
13
13
|
REGIONS_WITH_LAN = ["ru-1", "ru-3", "nl-1", "pl-1"]
|
|
14
|
-
ZONES_WITH_LAN = ["spb-1", "spb-4", "msk-1", "ams-1", "gdn-1"]
|
|
14
|
+
ZONES_WITH_LAN = ["spb-1", "spb-3", "spb-4", "msk-1", "ams-1", "gdn-1"]
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
CHANGELOG.md,sha256=
|
|
1
|
+
CHANGELOG.md,sha256=AnIkFEP7S8yrjLrgp1Vbsp47c79n6RQxz6-6OEwwEmk,26436
|
|
2
2
|
COPYING,sha256=fpJLxZS_kHr_659xkpmqEtqHeZp6lQR9CmKCwnYbsmE,1089
|
|
3
3
|
twc/__init__.py,sha256=NwPAMNw3NuHdWGQvWS9_lromVF6VM194oVOipojfJns,113
|
|
4
|
-
twc/__main__.py,sha256=
|
|
5
|
-
twc/__version__.py,sha256=
|
|
4
|
+
twc/__main__.py,sha256=ADHceaQUzgLmvhYHvb5O8urdJWj5IcEHLpTQkSExiD8,2468
|
|
5
|
+
twc/__version__.py,sha256=cJqV4mvQsKCOeicZYGqEH-nKLLWLVP_E-ByegiDQ9js,442
|
|
6
6
|
twc/api/__init__.py,sha256=SXew0Fe51M7nRBNQaaLRH4NjnRHkQUn7J26OCkQsftA,128
|
|
7
7
|
twc/api/base.py,sha256=QRefnIgmlbz8n37GLBKeAK1AtzkcNo1IFjZgHDDECJ4,7912
|
|
8
|
-
twc/api/client.py,sha256=
|
|
8
|
+
twc/api/client.py,sha256=8y3Q8zoZeNoKm8ywOXXbSXvMIvCXyAsU43HLy_nb4hQ,58514
|
|
9
9
|
twc/api/exceptions.py,sha256=UzK3pKRffcXlhnkPy6MDjP_DygVoV17DuZ_mdNbOzts,2369
|
|
10
10
|
twc/api/types.py,sha256=HCxdTi-o8nVq4ShPthd2fUvlYufEoXafx_6qrNHFH04,5406
|
|
11
|
-
twc/apiwrap.py,sha256=
|
|
12
|
-
twc/commands/__init__.py,sha256=
|
|
13
|
-
twc/commands/account.py,sha256=
|
|
11
|
+
twc/apiwrap.py,sha256=hKrg_o6rLfY32SEnWMc1BSXHnSAh7TGar1JQ90YnG5M,2970
|
|
12
|
+
twc/commands/__init__.py,sha256=a-6fHQQwOj--Z7uBZGZL3z1rvJiOGUMQMRET1UknIYo,430
|
|
13
|
+
twc/commands/account.py,sha256=6q9ri02oFbUUZuqNVXO-uHOX45B4ELJlPjyfVaEL5Qw,5960
|
|
14
14
|
twc/commands/balancer.py,sha256=QAouc74ZT5go11gB1vjjfYtd1luTmWrfpACPwokZ5sU,20278
|
|
15
15
|
twc/commands/common.py,sha256=Wph8cVogUNNvc456SQrASb7mv7G88I8ETwHgISVjLQQ,8282
|
|
16
16
|
twc/commands/config.py,sha256=hoRtxn2VRxIsuy9vgO6yd0Cu15Rbl-uYMZeU0Ix7dG0,8797
|
|
17
17
|
twc/commands/database.py,sha256=2NZ-TyRBkFgfYJyUdZUcfdqSaX7QVdWDU4k_yQNtUvo,16052
|
|
18
|
-
twc/commands/domain.py,sha256=
|
|
18
|
+
twc/commands/domain.py,sha256=uKr2rP9ajLiZrxA_Xl47Jn7Fh9IRODCtjwXwTfbo-EU,15943
|
|
19
19
|
twc/commands/firewall.py,sha256=KNolqbi2rsppOZwbs_j3yoZQt-0wKbj1JPGiZdfGxDE,27439
|
|
20
20
|
twc/commands/floating_ip.py,sha256=G9nD5BbHCZcuytbzeneDJWQDhd8c8WRtq9pAfwI9m7E,8747
|
|
21
21
|
twc/commands/image.py,sha256=OviQwegXK55H3TBlroCASVcgj2QUVCTo0ZhF5ug9eT8,8165
|
|
22
22
|
twc/commands/kubernetes.py,sha256=-Cgas1vFVMcrWGinjstuUz3sqX0ZNXv_4mwPwuwKeLE,20870
|
|
23
|
-
twc/commands/project.py,sha256=
|
|
24
|
-
twc/commands/server.py,sha256=
|
|
23
|
+
twc/commands/project.py,sha256=xnL3kLIumKzrI9EZ6r6m-PGOl3mZ9IhLQua7WZ3Rghg,10499
|
|
24
|
+
twc/commands/server.py,sha256=Cw8VxOcWEVPtcKZ53h9erhV3VOj7io9E8xQwVN0S53Y,70294
|
|
25
25
|
twc/commands/ssh_key.py,sha256=NHgTPhAQpDzt-iPHHVo4XqUJvujNqf019N6N9qYZ9Us,7941
|
|
26
|
-
twc/commands/storage.py,sha256=
|
|
26
|
+
twc/commands/storage.py,sha256=Pztk5iUBp9RtkdOwsfHaZFCnD8GuH6zOPtluawkRmiI,19404
|
|
27
27
|
twc/commands/vpc.py,sha256=SAht6UD17mU0d_AZY6W34VEYs7CqUsS2iDakPFxAFQU,8876
|
|
28
|
-
twc/fmt.py,sha256=
|
|
28
|
+
twc/fmt.py,sha256=nbuYZ8nVabYDwCmZqnL3-c6Tmri4B-R_sTCkG6sdfeI,7171
|
|
29
29
|
twc/typerx.py,sha256=AZ6BgTQvlrZYfKVYd9YqRNQnAR2XuyqImz4rf6di6f4,6737
|
|
30
30
|
twc/utils.py,sha256=uWizyUC4dHLwtk50q4Sub3zOvnVESfHKBbXYwk5t71w,651
|
|
31
|
-
twc/vars.py,sha256=
|
|
32
|
-
twc_cli-2.
|
|
33
|
-
twc_cli-2.
|
|
34
|
-
twc_cli-2.
|
|
35
|
-
twc_cli-2.
|
|
36
|
-
twc_cli-2.
|
|
31
|
+
twc/vars.py,sha256=fva3O2leMGtExb1aWiAk6sOV0O8et9_kEyRpYYIZ7CM,543
|
|
32
|
+
twc_cli-2.7.0.dist-info/COPYING,sha256=fpJLxZS_kHr_659xkpmqEtqHeZp6lQR9CmKCwnYbsmE,1089
|
|
33
|
+
twc_cli-2.7.0.dist-info/METADATA,sha256=w4WaXHt_EXUtrWRlRhntcYi0p5poZ7PM-ZfJGK4BZTY,2601
|
|
34
|
+
twc_cli-2.7.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
35
|
+
twc_cli-2.7.0.dist-info/entry_points.txt,sha256=tmTaVRhm8BkNrXC_9XJMum7O9wFVOvkXcBetxmahWvE,40
|
|
36
|
+
twc_cli-2.7.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|