twc-cli 2.3.0__py3-none-any.whl → 2.4.1__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 +24 -0
- twc/__main__.py +11 -1
- twc/__version__.py +1 -1
- twc/api/base.py +3 -2
- twc/api/client.py +349 -6
- twc/api/types.py +28 -2
- twc/commands/__init__.py +3 -0
- twc/commands/account.py +30 -40
- twc/commands/balancer.py +38 -36
- twc/commands/common.py +8 -4
- twc/commands/config.py +28 -1
- twc/commands/domain.py +519 -0
- twc/commands/firewall.py +654 -0
- twc/commands/image.py +14 -25
- twc/commands/project.py +2 -2
- twc/commands/server.py +16 -5
- twc/commands/vpc.py +293 -0
- twc/fmt.py +15 -0
- twc/typerx.py +7 -2
- twc/vars.py +3 -2
- {twc_cli-2.3.0.dist-info → twc_cli-2.4.1.dist-info}/METADATA +1 -1
- twc_cli-2.4.1.dist-info/RECORD +35 -0
- twc_cli-2.3.0.dist-info/RECORD +0 -32
- {twc_cli-2.3.0.dist-info → twc_cli-2.4.1.dist-info}/COPYING +0 -0
- {twc_cli-2.3.0.dist-info → twc_cli-2.4.1.dist-info}/WHEEL +0 -0
- {twc_cli-2.3.0.dist-info → twc_cli-2.4.1.dist-info}/entry_points.txt +0 -0
twc/commands/image.py
CHANGED
|
@@ -14,7 +14,7 @@ from requests import Response
|
|
|
14
14
|
from twc import fmt
|
|
15
15
|
from twc.typerx import TyperAlias
|
|
16
16
|
from twc.apiwrap import create_client
|
|
17
|
-
from twc.api import
|
|
17
|
+
from twc.api import ServerOSType
|
|
18
18
|
from .common import (
|
|
19
19
|
verbose_option,
|
|
20
20
|
config_option,
|
|
@@ -22,6 +22,7 @@ from .common import (
|
|
|
22
22
|
filter_option,
|
|
23
23
|
yes_option,
|
|
24
24
|
output_format_option,
|
|
25
|
+
region_option,
|
|
25
26
|
)
|
|
26
27
|
|
|
27
28
|
|
|
@@ -42,11 +43,11 @@ def print_images(response: Response, filters: Optional[str] = None):
|
|
|
42
43
|
table = fmt.Table()
|
|
43
44
|
table.header(
|
|
44
45
|
[
|
|
45
|
-
"
|
|
46
|
-
"NAME",
|
|
46
|
+
"ID",
|
|
47
|
+
# "NAME",
|
|
48
|
+
"TYPE",
|
|
47
49
|
"REGION",
|
|
48
50
|
"STATUS",
|
|
49
|
-
"DISK",
|
|
50
51
|
"SIZE",
|
|
51
52
|
]
|
|
52
53
|
)
|
|
@@ -54,10 +55,12 @@ def print_images(response: Response, filters: Optional[str] = None):
|
|
|
54
55
|
table.row(
|
|
55
56
|
[
|
|
56
57
|
img["id"],
|
|
57
|
-
img["
|
|
58
|
+
img["type"],
|
|
59
|
+
# img["name"][:18] + "..."
|
|
60
|
+
# if len(img["name"]) > 18
|
|
61
|
+
# else img["name"],
|
|
58
62
|
img["location"],
|
|
59
63
|
img["status"],
|
|
60
|
-
img["disk_id"],
|
|
61
64
|
str(round(img["size"] / 1024)) + "G",
|
|
62
65
|
]
|
|
63
66
|
)
|
|
@@ -72,22 +75,10 @@ def image_list(
|
|
|
72
75
|
output_format: Optional[str] = output_format_option,
|
|
73
76
|
limit: int = typer.Option(500, help="Items to display."),
|
|
74
77
|
filters: Optional[str] = filter_option,
|
|
75
|
-
region: Optional[ServiceRegion] = typer.Option(
|
|
76
|
-
None,
|
|
77
|
-
case_sensitive=False,
|
|
78
|
-
help="Use region (location).",
|
|
79
|
-
),
|
|
80
|
-
with_deleted: Optional[bool] = typer.Option(
|
|
81
|
-
False,
|
|
82
|
-
"--with-deleted",
|
|
83
|
-
help="Show all images including deleted images.",
|
|
84
|
-
),
|
|
85
78
|
):
|
|
86
79
|
"""List images."""
|
|
87
|
-
if region:
|
|
88
|
-
filters = f"{filters},location:{region}"
|
|
89
80
|
client = create_client(config, profile)
|
|
90
|
-
response = client.get_images(limit=limit
|
|
81
|
+
response = client.get_images(limit=limit)
|
|
91
82
|
fmt.printer(
|
|
92
83
|
response,
|
|
93
84
|
output_format=output_format,
|
|
@@ -106,8 +97,9 @@ def print_image(response: Response):
|
|
|
106
97
|
table = fmt.Table()
|
|
107
98
|
table.header(
|
|
108
99
|
[
|
|
109
|
-
"
|
|
100
|
+
"ID",
|
|
110
101
|
"NAME",
|
|
102
|
+
"TYPE",
|
|
111
103
|
"REGION",
|
|
112
104
|
"STATUS",
|
|
113
105
|
"DISK",
|
|
@@ -119,6 +111,7 @@ def print_image(response: Response):
|
|
|
119
111
|
[
|
|
120
112
|
img["id"],
|
|
121
113
|
img["name"],
|
|
114
|
+
img["type"],
|
|
122
115
|
img["location"],
|
|
123
116
|
img["status"],
|
|
124
117
|
img["disk_id"],
|
|
@@ -263,11 +256,7 @@ def image_upload(
|
|
|
263
256
|
case_sensitive=False,
|
|
264
257
|
help="OS type. This value is formal and not affects on server/image.",
|
|
265
258
|
),
|
|
266
|
-
region: Optional[
|
|
267
|
-
ServiceRegion.RU_1.value,
|
|
268
|
-
case_sensitive=False,
|
|
269
|
-
help="Region (location) to upload image.",
|
|
270
|
-
),
|
|
259
|
+
region: Optional[str] = region_option,
|
|
271
260
|
):
|
|
272
261
|
"""Upload image from URL."""
|
|
273
262
|
client = create_client(config, profile)
|
twc/commands/project.py
CHANGED
|
@@ -11,7 +11,7 @@ from requests import Response
|
|
|
11
11
|
from twc import fmt
|
|
12
12
|
from twc.typerx import TyperAlias
|
|
13
13
|
from twc.apiwrap import create_client
|
|
14
|
-
from twc.api import TimewebCloud,
|
|
14
|
+
from twc.api import TimewebCloud, ResourceType
|
|
15
15
|
from .common import (
|
|
16
16
|
verbose_option,
|
|
17
17
|
config_option,
|
|
@@ -28,7 +28,7 @@ project.add_typer(project_resource, name="resource", aliases=["rsrc"])
|
|
|
28
28
|
# API issue: Inconsistent resource naming
|
|
29
29
|
# Some entities have different names in cases.
|
|
30
30
|
RESOURCE_TYPES = [
|
|
31
|
-
*[r.value for r in
|
|
31
|
+
*[r.value for r in ResourceType],
|
|
32
32
|
"cluster", # also named 'kubernetes'
|
|
33
33
|
"bucket", # also named 'storage'
|
|
34
34
|
"dedicated_server", # also named 'dedicated'
|
twc/commands/server.py
CHANGED
|
@@ -515,17 +515,20 @@ def server_create(
|
|
|
515
515
|
show_default=True,
|
|
516
516
|
help="Enable DDoS-Guard.",
|
|
517
517
|
),
|
|
518
|
-
local_network: bool = typer.Option(
|
|
519
|
-
|
|
518
|
+
local_network: Optional[bool] = typer.Option(
|
|
519
|
+
# is_local_network paramenter is deprecated!
|
|
520
|
+
None,
|
|
520
521
|
"--local-network",
|
|
521
522
|
show_default=True,
|
|
522
523
|
help="Enable LAN.",
|
|
524
|
+
hidden=True,
|
|
523
525
|
),
|
|
526
|
+
network: Optional[str] = typer.Option(None, help="Private network ID."),
|
|
524
527
|
nat_mode: ServerNATMode = typer.Option(
|
|
525
528
|
None,
|
|
526
529
|
"--nat-mode",
|
|
527
530
|
metavar="MODE",
|
|
528
|
-
help="
|
|
531
|
+
help="Apply NAT mode.",
|
|
529
532
|
),
|
|
530
533
|
region: Optional[str] = region_option,
|
|
531
534
|
project_id: int = typer.Option(
|
|
@@ -540,7 +543,8 @@ def server_create(
|
|
|
540
543
|
client = create_client(config, profile)
|
|
541
544
|
|
|
542
545
|
if nat_mode:
|
|
543
|
-
|
|
546
|
+
if not network:
|
|
547
|
+
sys.exit("Error: Pass '--network' option first.")
|
|
544
548
|
|
|
545
549
|
payload = {
|
|
546
550
|
"name": name,
|
|
@@ -548,9 +552,16 @@ def server_create(
|
|
|
548
552
|
"avatar_id": avatar_id,
|
|
549
553
|
"software_id": software_id,
|
|
550
554
|
"is_ddos_guard": ddos_protection,
|
|
551
|
-
|
|
555
|
+
**(
|
|
556
|
+
{"is_local_network": local_network}
|
|
557
|
+
if local_network is not None
|
|
558
|
+
else {}
|
|
559
|
+
),
|
|
552
560
|
}
|
|
553
561
|
|
|
562
|
+
if network:
|
|
563
|
+
payload["network"] = {"id": network}
|
|
564
|
+
|
|
554
565
|
# Set server configuration parameters
|
|
555
566
|
if preset_id and (cpu or ram or disk):
|
|
556
567
|
raise UsageError(
|
twc/commands/vpc.py
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"""Manage virtual networks."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from typing import Optional, List
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from ipaddress import (
|
|
7
|
+
IPv4Network,
|
|
8
|
+
AddressValueError,
|
|
9
|
+
NetmaskValueError,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
import typer
|
|
13
|
+
from requests import Response
|
|
14
|
+
|
|
15
|
+
from twc import fmt
|
|
16
|
+
from twc.typerx import TyperAlias
|
|
17
|
+
from twc.apiwrap import create_client
|
|
18
|
+
from twc.vars import REGIONS_WITH_LAN
|
|
19
|
+
from .common import (
|
|
20
|
+
verbose_option,
|
|
21
|
+
config_option,
|
|
22
|
+
profile_option,
|
|
23
|
+
yes_option,
|
|
24
|
+
output_format_option,
|
|
25
|
+
filter_option,
|
|
26
|
+
region_option,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
vpc = TyperAlias(help=__doc__)
|
|
31
|
+
vpc_port = TyperAlias(help="Manage network ports.")
|
|
32
|
+
vpc.add_typer(vpc_port, name="port", aliases=["ports"])
|
|
33
|
+
|
|
34
|
+
ALLOWED_SUBNETS = [IPv4Network("10.0.0.0/16"), IPv4Network("192.168.0.0/16")]
|
|
35
|
+
MAX_PREFIXLEN = 16
|
|
36
|
+
MIN_PREFIXLEN = 32
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# ------------------------------------------------------------- #
|
|
40
|
+
# $ twc vpc list #
|
|
41
|
+
# ------------------------------------------------------------- #
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def print_networks(response: Response, filters: Optional[str] = None):
|
|
45
|
+
nets = response.json()["vpcs"]
|
|
46
|
+
if filters:
|
|
47
|
+
nets = fmt.filter_list(nets, filters)
|
|
48
|
+
table = fmt.Table()
|
|
49
|
+
table.header(["ID", "REGION", "SUBNET"])
|
|
50
|
+
for net in nets:
|
|
51
|
+
table.row(
|
|
52
|
+
[
|
|
53
|
+
net["id"],
|
|
54
|
+
net["location"],
|
|
55
|
+
net["subnet_v4"],
|
|
56
|
+
]
|
|
57
|
+
)
|
|
58
|
+
table.print()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@vpc.command("list", "ls")
|
|
62
|
+
def vpc_list(
|
|
63
|
+
verbose: Optional[bool] = verbose_option,
|
|
64
|
+
config: Optional[Path] = config_option,
|
|
65
|
+
profile: Optional[str] = profile_option,
|
|
66
|
+
output_format: Optional[str] = output_format_option,
|
|
67
|
+
filters: Optional[str] = filter_option,
|
|
68
|
+
):
|
|
69
|
+
"""List networks."""
|
|
70
|
+
client = create_client(config, profile)
|
|
71
|
+
response = client.get_vpcs()
|
|
72
|
+
fmt.printer(
|
|
73
|
+
response,
|
|
74
|
+
output_format=output_format,
|
|
75
|
+
filters=filters,
|
|
76
|
+
func=print_networks,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# ------------------------------------------------------------- #
|
|
81
|
+
# $ twc vpc create #
|
|
82
|
+
# ------------------------------------------------------------- #
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def validate_network(value):
|
|
86
|
+
if value:
|
|
87
|
+
try:
|
|
88
|
+
network = IPv4Network(value)
|
|
89
|
+
except (NetmaskValueError, AddressValueError, ValueError) as err:
|
|
90
|
+
sys.exit(f"Error: Invalid CIDR: {err}")
|
|
91
|
+
|
|
92
|
+
is_valid = False
|
|
93
|
+
for subnet in ALLOWED_SUBNETS:
|
|
94
|
+
if network.subnet_of(subnet):
|
|
95
|
+
is_valid = True
|
|
96
|
+
|
|
97
|
+
if is_valid is False:
|
|
98
|
+
sys.exit(
|
|
99
|
+
f"Error: Network {value} is not subnet of: "
|
|
100
|
+
f"{[n.with_prefixlen for n in ALLOWED_SUBNETS]}"
|
|
101
|
+
)
|
|
102
|
+
if network.prefixlen in range(MIN_PREFIXLEN, MAX_PREFIXLEN + 1):
|
|
103
|
+
sys.exit("Error: Minimum network prefix is 32, maximum is 16.")
|
|
104
|
+
return value
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@vpc.command("create")
|
|
108
|
+
def vpc_create(
|
|
109
|
+
subnet: str = typer.Argument(
|
|
110
|
+
...,
|
|
111
|
+
metavar="IP_NETWORK",
|
|
112
|
+
callback=validate_network,
|
|
113
|
+
help="IPv4 network CIDR.",
|
|
114
|
+
),
|
|
115
|
+
verbose: Optional[bool] = verbose_option,
|
|
116
|
+
config: Optional[Path] = config_option,
|
|
117
|
+
profile: Optional[str] = profile_option,
|
|
118
|
+
output_format: Optional[str] = output_format_option,
|
|
119
|
+
name: str = typer.Option(None, help="Network display name."),
|
|
120
|
+
desc: Optional[str] = typer.Option(None, help="Description."),
|
|
121
|
+
region: Optional[str] = region_option,
|
|
122
|
+
):
|
|
123
|
+
"""Create network."""
|
|
124
|
+
client = create_client(config, profile)
|
|
125
|
+
if region not in REGIONS_WITH_LAN:
|
|
126
|
+
sys.exit(
|
|
127
|
+
f"Error: Cannot create network in location '{region}'. "
|
|
128
|
+
f"Available regions is {REGIONS_WITH_LAN}"
|
|
129
|
+
)
|
|
130
|
+
if not name:
|
|
131
|
+
name = subnet
|
|
132
|
+
response = client.create_vpc(
|
|
133
|
+
name,
|
|
134
|
+
description=desc,
|
|
135
|
+
subnet=subnet,
|
|
136
|
+
location=region,
|
|
137
|
+
)
|
|
138
|
+
fmt.printer(
|
|
139
|
+
response,
|
|
140
|
+
output_format=output_format,
|
|
141
|
+
func=lambda response: print(response.json()["vpc"]["id"]),
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# ------------------------------------------------------------- #
|
|
146
|
+
# $ twc vpc remove #
|
|
147
|
+
# ------------------------------------------------------------- #
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@vpc.command("remove", "rm")
|
|
151
|
+
def vpc_remove(
|
|
152
|
+
vpc_ids: List[str] = typer.Argument(..., metavar="VPC_ID..."),
|
|
153
|
+
verbose: Optional[bool] = verbose_option,
|
|
154
|
+
config: Optional[Path] = config_option,
|
|
155
|
+
profile: Optional[str] = profile_option,
|
|
156
|
+
output_format: Optional[str] = output_format_option,
|
|
157
|
+
yes: Optional[bool] = yes_option,
|
|
158
|
+
):
|
|
159
|
+
"""Remove network."""
|
|
160
|
+
if not yes:
|
|
161
|
+
typer.confirm("This action cannot be undone. Continue?", abort=True)
|
|
162
|
+
client = create_client(config, profile)
|
|
163
|
+
for vpc_id in vpc_ids:
|
|
164
|
+
response = client.delete_vpc(vpc_id)
|
|
165
|
+
if response.status_code == 204:
|
|
166
|
+
print(vpc_id)
|
|
167
|
+
else:
|
|
168
|
+
sys.exit(fmt.printer(response))
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
# ------------------------------------------------------------- #
|
|
172
|
+
# $ twc vpc set #
|
|
173
|
+
# ------------------------------------------------------------- #
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
@vpc.command("set")
|
|
177
|
+
def vpc_set(
|
|
178
|
+
vpc_id: str,
|
|
179
|
+
verbose: Optional[bool] = verbose_option,
|
|
180
|
+
config: Optional[Path] = config_option,
|
|
181
|
+
profile: Optional[str] = profile_option,
|
|
182
|
+
output_format: Optional[str] = output_format_option,
|
|
183
|
+
name: Optional[str] = typer.Option(None, help="Network display name."),
|
|
184
|
+
desc: Optional[str] = typer.Option(None, help="Description."),
|
|
185
|
+
):
|
|
186
|
+
"""Set network properties."""
|
|
187
|
+
client = create_client(config, profile)
|
|
188
|
+
response = client.update_vpc(vpc_id, name=name, description=desc)
|
|
189
|
+
fmt.printer(
|
|
190
|
+
response,
|
|
191
|
+
output_format=output_format,
|
|
192
|
+
func=lambda response: print(response.json()["vpc"]["id"]),
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
# ------------------------------------------------------------- #
|
|
197
|
+
# $ twc vpc port list #
|
|
198
|
+
# ------------------------------------------------------------- #
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def print_ports(response: Response, filters: Optional[str] = None):
|
|
202
|
+
ports = response.json()["vpc_ports"]
|
|
203
|
+
if filters:
|
|
204
|
+
ports = fmt.filter_list(ports, filters)
|
|
205
|
+
table = fmt.Table()
|
|
206
|
+
table.header(
|
|
207
|
+
[
|
|
208
|
+
"ID",
|
|
209
|
+
"NAT",
|
|
210
|
+
"IP",
|
|
211
|
+
]
|
|
212
|
+
)
|
|
213
|
+
for port in ports:
|
|
214
|
+
table.row(
|
|
215
|
+
[
|
|
216
|
+
port["id"],
|
|
217
|
+
port["nat_mode"],
|
|
218
|
+
port["ipv4"],
|
|
219
|
+
]
|
|
220
|
+
)
|
|
221
|
+
table.print()
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@vpc_port.command("list", "ls")
|
|
225
|
+
def vpc_ports_list(
|
|
226
|
+
vpc_id: str,
|
|
227
|
+
verbose: Optional[bool] = verbose_option,
|
|
228
|
+
config: Optional[Path] = config_option,
|
|
229
|
+
profile: Optional[str] = profile_option,
|
|
230
|
+
output_format: Optional[str] = output_format_option,
|
|
231
|
+
filters: Optional[str] = filter_option,
|
|
232
|
+
):
|
|
233
|
+
"""List network ports."""
|
|
234
|
+
client = create_client(config, profile)
|
|
235
|
+
response = client.get_vpc_ports(vpc_id)
|
|
236
|
+
fmt.printer(
|
|
237
|
+
response,
|
|
238
|
+
output_format=output_format,
|
|
239
|
+
filters=filters,
|
|
240
|
+
func=print_ports,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# ------------------------------------------------------------- #
|
|
245
|
+
# $ twc vpc show #
|
|
246
|
+
# ------------------------------------------------------------- #
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def print_resources(response: Response, filters: Optional[str] = None):
|
|
250
|
+
resources = response.json()["services"]
|
|
251
|
+
if filters:
|
|
252
|
+
resources = fmt.filter_list(resources, filters)
|
|
253
|
+
table = fmt.Table()
|
|
254
|
+
table.header(
|
|
255
|
+
[
|
|
256
|
+
"ID",
|
|
257
|
+
"NAME",
|
|
258
|
+
"TYPE",
|
|
259
|
+
"PRIVATE IP",
|
|
260
|
+
"PUBLIC IP",
|
|
261
|
+
]
|
|
262
|
+
)
|
|
263
|
+
for res in resources:
|
|
264
|
+
table.row(
|
|
265
|
+
[
|
|
266
|
+
res["id"],
|
|
267
|
+
res["name"],
|
|
268
|
+
res["type"],
|
|
269
|
+
res["local_ip"],
|
|
270
|
+
res["public_ip"],
|
|
271
|
+
]
|
|
272
|
+
)
|
|
273
|
+
table.print()
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
@vpc.command("show")
|
|
277
|
+
def vpc_show(
|
|
278
|
+
vpc_id: str,
|
|
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
|
+
filters: Optional[str] = filter_option,
|
|
284
|
+
):
|
|
285
|
+
"""List resources in network."""
|
|
286
|
+
client = create_client(config, profile)
|
|
287
|
+
response = client.get_services_in_vpc(vpc_id)
|
|
288
|
+
fmt.printer(
|
|
289
|
+
response,
|
|
290
|
+
output_format=output_format,
|
|
291
|
+
filters=filters,
|
|
292
|
+
func=print_resources,
|
|
293
|
+
)
|
twc/fmt.py
CHANGED
|
@@ -174,6 +174,21 @@ def filter_list(objects: list, filters: str) -> list:
|
|
|
174
174
|
if val.lower().endswith("g"):
|
|
175
175
|
val = str(int(val[:-1]) * 1024)
|
|
176
176
|
|
|
177
|
+
# API Issue: Worst DTO design in /domains/{fqdn}/dns-records
|
|
178
|
+
# dns_records object 'data' key may have or not keys 'subdomain'
|
|
179
|
+
# and 'priority'. There is workaround that makes possible to
|
|
180
|
+
# filter 'data' object.
|
|
181
|
+
if key in ["data.priority", "data.subdomain"]:
|
|
182
|
+
# Add keys into source object
|
|
183
|
+
objects_fixed = []
|
|
184
|
+
for obj in objects:
|
|
185
|
+
if "subdomain" not in obj["data"].keys():
|
|
186
|
+
obj["data"]["subdomain"] = None
|
|
187
|
+
if "priority" not in obj["data"].keys():
|
|
188
|
+
obj["data"]["priority"] = None
|
|
189
|
+
objects_fixed.append(obj)
|
|
190
|
+
objects = objects_fixed
|
|
191
|
+
|
|
177
192
|
objects = list(
|
|
178
193
|
filter(
|
|
179
194
|
# pylint: disable=cell-var-from-loop
|
twc/typerx.py
CHANGED
|
@@ -7,6 +7,9 @@ from typer.models import CommandFunctionType, CommandInfo, TyperInfo, Default
|
|
|
7
7
|
from typer.core import TyperCommand, TyperGroup
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
CONTEXT_SETTINGS = {"help_option_names": ["-h", "--help"]}
|
|
11
|
+
|
|
12
|
+
|
|
10
13
|
class TyperAlias(Typer):
|
|
11
14
|
"""Commands and groups aliases support for Typer."""
|
|
12
15
|
|
|
@@ -30,6 +33,8 @@ class TyperAlias(Typer):
|
|
|
30
33
|
) -> Callable[[CommandFunctionType], CommandFunctionType]:
|
|
31
34
|
if cls is None:
|
|
32
35
|
cls = TyperCommand
|
|
36
|
+
if context_settings is None:
|
|
37
|
+
context_settings = CONTEXT_SETTINGS
|
|
33
38
|
|
|
34
39
|
name = None
|
|
35
40
|
aliases = []
|
|
@@ -98,12 +103,12 @@ class TyperAlias(Typer):
|
|
|
98
103
|
aliases: Optional[List[str]] = None,
|
|
99
104
|
cls: Optional[Type[TyperGroup]] = Default(None),
|
|
100
105
|
invoke_without_command: bool = Default(False),
|
|
101
|
-
no_args_is_help: bool = Default(
|
|
106
|
+
no_args_is_help: bool = Default(True),
|
|
102
107
|
subcommand_metavar: Optional[str] = Default(None),
|
|
103
108
|
chain: bool = Default(False),
|
|
104
109
|
result_callback: Optional[Callable[..., Any]] = Default(None),
|
|
105
110
|
# Command
|
|
106
|
-
context_settings: Optional[Dict[Any, Any]] = Default(
|
|
111
|
+
context_settings: Optional[Dict[Any, Any]] = Default(CONTEXT_SETTINGS),
|
|
107
112
|
callback: Optional[Callable[..., Any]] = Default(None),
|
|
108
113
|
help: Optional[str] = Default(None),
|
|
109
114
|
epilog: Optional[str] = Default(None),
|
twc/vars.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
This module defines variables that depend on Timeweb Cloud products.
|
|
2
3
|
They are subject to change at any time as cloud computing capabilities
|
|
3
4
|
expand or other infrastructure or product changes occur.
|
|
4
5
|
"""
|
|
@@ -10,6 +11,6 @@ S3_ENDPOINT = "s3.timeweb.com"
|
|
|
10
11
|
# Location specific parameters. May change later.
|
|
11
12
|
REGIONS_WITH_CONFIGURATOR = ["ru-1", "ru-2", "pl-1", "kz-1", "nl-1"]
|
|
12
13
|
REGIONS_WITH_IPV6 = ["ru-1", "pl-1"]
|
|
13
|
-
REGIONS_WITH_IMAGES = ["ru-1"]
|
|
14
|
+
REGIONS_WITH_IMAGES = ["ru-1", "pl-1", "nl-1"]
|
|
14
15
|
REGIONS_WITH_LAN = ["ru-1", "pl-1"]
|
|
15
16
|
REGIONS_WITH_DBAAS = ["ru-1", "pl-1"]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
CHANGELOG.md,sha256=zTYQURuVK_bCcGHFCvPv7fhrrx1AylMBXIoCHN5GjW8,21537
|
|
2
|
+
COPYING,sha256=fpJLxZS_kHr_659xkpmqEtqHeZp6lQR9CmKCwnYbsmE,1089
|
|
3
|
+
twc/__init__.py,sha256=NwPAMNw3NuHdWGQvWS9_lromVF6VM194oVOipojfJns,113
|
|
4
|
+
twc/__main__.py,sha256=jVkf0XyGIhn3oaWgEzknuUjktYk6ANYwbmrUID15vvc,2335
|
|
5
|
+
twc/__version__.py,sha256=wr1ehxX2XbcqynTOLEVk_co68MQI6SNEZSFm6jgxook,442
|
|
6
|
+
twc/api/__init__.py,sha256=SXew0Fe51M7nRBNQaaLRH4NjnRHkQUn7J26OCkQsftA,128
|
|
7
|
+
twc/api/base.py,sha256=9srQS7CrDlfg-CSioIRyW_QUbCBovDs2VqN_4V28YCc,8063
|
|
8
|
+
twc/api/client.py,sha256=Tkd9zdzsESCtvy-kdv012R-Q12btU4D0uDVOjXUy8Zc,55898
|
|
9
|
+
twc/api/exceptions.py,sha256=UzK3pKRffcXlhnkPy6MDjP_DygVoV17DuZ_mdNbOzts,2369
|
|
10
|
+
twc/api/types.py,sha256=vattozb_YI7A_igCd2dUkMcJQJQeegYsl_nQwrwNqVw,3917
|
|
11
|
+
twc/apiwrap.py,sha256=uh-G67a8C2KN3BdLCShMsk9AHgV_F75FkXmK-xz_plc,2780
|
|
12
|
+
twc/commands/__init__.py,sha256=IXCr-gXf7oxwu7CDUa5U0iUM8lraYq_YKpq1aGUqpcU,385
|
|
13
|
+
twc/commands/account.py,sha256=6T7J3McTXJKzT7Gi_AgRcKpWdeXcmBTcpwFF0GjzADo,4998
|
|
14
|
+
twc/commands/balancer.py,sha256=QAouc74ZT5go11gB1vjjfYtd1luTmWrfpACPwokZ5sU,20278
|
|
15
|
+
twc/commands/common.py,sha256=r3enPCYWMwkD8YNPgcXuXK_HrobiHgfpkn82j_uRDqY,7805
|
|
16
|
+
twc/commands/config.py,sha256=hoRtxn2VRxIsuy9vgO6yd0Cu15Rbl-uYMZeU0Ix7dG0,8797
|
|
17
|
+
twc/commands/database.py,sha256=2NZ-TyRBkFgfYJyUdZUcfdqSaX7QVdWDU4k_yQNtUvo,16052
|
|
18
|
+
twc/commands/domain.py,sha256=SHOERsEvmlkdKQV5kaiEgMOLZme5ykW8LCUd1IF1Zzo,15624
|
|
19
|
+
twc/commands/firewall.py,sha256=6tSOiOmDx3X-hbD_XwUt8cU6GiLh9gDVMtQ7O59PG14,20381
|
|
20
|
+
twc/commands/image.py,sha256=2TQ2tzkraggx7eR2OHU64qDFtgzV5YHtCHl4nLpRMqA,8140
|
|
21
|
+
twc/commands/kubernetes.py,sha256=-Cgas1vFVMcrWGinjstuUz3sqX0ZNXv_4mwPwuwKeLE,20870
|
|
22
|
+
twc/commands/project.py,sha256=iskODT3eKZ5CpAKdWnsQ104YMRcqhOCry6Omnr-a2TM,10792
|
|
23
|
+
twc/commands/server.py,sha256=dbrdMXnhe4sIQqF3P-Mm9uRjeqkp8-a054Cvs5FYkaU,68065
|
|
24
|
+
twc/commands/ssh_key.py,sha256=NHgTPhAQpDzt-iPHHVo4XqUJvujNqf019N6N9qYZ9Us,7941
|
|
25
|
+
twc/commands/storage.py,sha256=MRZfd2WzLI9HeIEupaMg01EQPih2BIAfjx0Tgx0yp0M,19216
|
|
26
|
+
twc/commands/vpc.py,sha256=fe7rNKeRAvGYiXIvgGxzxjV35bQ66MVsNnTp7CsJgYQ,8405
|
|
27
|
+
twc/fmt.py,sha256=cmo3EdFEAwl_JocfneIEHpD5c_bHQ6tAw_UJEC-vatY,6904
|
|
28
|
+
twc/typerx.py,sha256=AZ6BgTQvlrZYfKVYd9YqRNQnAR2XuyqImz4rf6di6f4,6737
|
|
29
|
+
twc/utils.py,sha256=uWizyUC4dHLwtk50q4Sub3zOvnVESfHKBbXYwk5t71w,651
|
|
30
|
+
twc/vars.py,sha256=zvSaojyihfDpScKLSb5ICVkXE3EHuU0UfwmZz7TTdrg,577
|
|
31
|
+
twc_cli-2.4.1.dist-info/COPYING,sha256=fpJLxZS_kHr_659xkpmqEtqHeZp6lQR9CmKCwnYbsmE,1089
|
|
32
|
+
twc_cli-2.4.1.dist-info/METADATA,sha256=Zxd8vRxwi1R_L5V9nJcuXJaQjNqq89N030c_qyYIfWE,1772
|
|
33
|
+
twc_cli-2.4.1.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
|
|
34
|
+
twc_cli-2.4.1.dist-info/entry_points.txt,sha256=tmTaVRhm8BkNrXC_9XJMum7O9wFVOvkXcBetxmahWvE,40
|
|
35
|
+
twc_cli-2.4.1.dist-info/RECORD,,
|
twc_cli-2.3.0.dist-info/RECORD
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
CHANGELOG.md,sha256=n25SxrhFpCqkglUuCF7GtkVLeETFzHmKgDWPAw6Hbmw,19635
|
|
2
|
-
COPYING,sha256=fpJLxZS_kHr_659xkpmqEtqHeZp6lQR9CmKCwnYbsmE,1089
|
|
3
|
-
twc/__init__.py,sha256=NwPAMNw3NuHdWGQvWS9_lromVF6VM194oVOipojfJns,113
|
|
4
|
-
twc/__main__.py,sha256=wlDuVnDYAyZf4S2xNYdZ2gbtm1abdxEGWze7-WSUwkI,2013
|
|
5
|
-
twc/__version__.py,sha256=6p2B1A4Hz-dMoB_r8SmHpH4upOlN6OxvuDMSnv0NULs,442
|
|
6
|
-
twc/api/__init__.py,sha256=SXew0Fe51M7nRBNQaaLRH4NjnRHkQUn7J26OCkQsftA,128
|
|
7
|
-
twc/api/base.py,sha256=pdAEmJa634NlPtKQ7Ux3IOjAam4gkW7AmicoE_VSutQ,7975
|
|
8
|
-
twc/api/client.py,sha256=ewCSLEBZNZy2yy_DI9SYBP2gES2pFy20FPjD-hgHZSg,44894
|
|
9
|
-
twc/api/exceptions.py,sha256=UzK3pKRffcXlhnkPy6MDjP_DygVoV17DuZ_mdNbOzts,2369
|
|
10
|
-
twc/api/types.py,sha256=3zn0KRl74VRwG2smYxwTsxR3FqSU2wrgEwlXG5gHZ3c,3499
|
|
11
|
-
twc/apiwrap.py,sha256=uh-G67a8C2KN3BdLCShMsk9AHgV_F75FkXmK-xz_plc,2780
|
|
12
|
-
twc/commands/__init__.py,sha256=b9NzbBJp6Kg5b2QVqYHtXrEFzeXChzyTlLvWy3yFNyk,306
|
|
13
|
-
twc/commands/account.py,sha256=TP_SyxsbR6ZGpPoL2qS2eidOF72mfnjzjS6TMvbIHXQ,5253
|
|
14
|
-
twc/commands/balancer.py,sha256=VLbjXHehoSuYnY-Ej1IZHdz-Syno9JCukuX-Xg4NscE,20070
|
|
15
|
-
twc/commands/common.py,sha256=sCh6DN9D-hH3nh0i7mHxJ_bNe8JAPi_N1ZCnTyvDX-g,7687
|
|
16
|
-
twc/commands/config.py,sha256=nCWUrGH95H1W2Z-QsNvR3rFrsUrNScxD8PCvI_Qsb0w,8057
|
|
17
|
-
twc/commands/database.py,sha256=2NZ-TyRBkFgfYJyUdZUcfdqSaX7QVdWDU4k_yQNtUvo,16052
|
|
18
|
-
twc/commands/image.py,sha256=5ZSvR84pIlNDzYBaWR2cUS1F2dqrK6u7OFHLWa4IazA,8522
|
|
19
|
-
twc/commands/kubernetes.py,sha256=-Cgas1vFVMcrWGinjstuUz3sqX0ZNXv_4mwPwuwKeLE,20870
|
|
20
|
-
twc/commands/project.py,sha256=n6F5TPRq89Wc_ntMWWezIyN94DqzMwf0JMkdrBoJ3aQ,10798
|
|
21
|
-
twc/commands/server.py,sha256=-WUKVCnF1YUgDiNv80QXaR5pfbiHy1dEzo-wR2vG_Jk,67719
|
|
22
|
-
twc/commands/ssh_key.py,sha256=NHgTPhAQpDzt-iPHHVo4XqUJvujNqf019N6N9qYZ9Us,7941
|
|
23
|
-
twc/commands/storage.py,sha256=MRZfd2WzLI9HeIEupaMg01EQPih2BIAfjx0Tgx0yp0M,19216
|
|
24
|
-
twc/fmt.py,sha256=tuCZoxFkM3RttqO4ysqMZGSm-nLuRZESSJS0qB8scdY,6148
|
|
25
|
-
twc/typerx.py,sha256=tz7S5e6jnuCTZGGCqQ4FKa7AF6otxmC0BiOO-4y2kR8,6580
|
|
26
|
-
twc/utils.py,sha256=uWizyUC4dHLwtk50q4Sub3zOvnVESfHKBbXYwk5t71w,651
|
|
27
|
-
twc/vars.py,sha256=-XonIykmWq6XAnYByeBkA7LAM1DyQ0RG3vHe6fL7zq0,560
|
|
28
|
-
twc_cli-2.3.0.dist-info/COPYING,sha256=fpJLxZS_kHr_659xkpmqEtqHeZp6lQR9CmKCwnYbsmE,1089
|
|
29
|
-
twc_cli-2.3.0.dist-info/METADATA,sha256=NZkefd0LMZAtWpD-mXewYFNYY1rhRm3UbBBeAYIEGgc,1772
|
|
30
|
-
twc_cli-2.3.0.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
|
|
31
|
-
twc_cli-2.3.0.dist-info/entry_points.txt,sha256=tmTaVRhm8BkNrXC_9XJMum7O9wFVOvkXcBetxmahWvE,40
|
|
32
|
-
twc_cli-2.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|