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/balancer.py
CHANGED
|
@@ -48,8 +48,8 @@ def print_balancers(response: Response, filters: Optional[str]):
|
|
|
48
48
|
"ID",
|
|
49
49
|
"NAME",
|
|
50
50
|
"STATUS",
|
|
51
|
-
"EXTERNAL IP",
|
|
52
51
|
"INTERNAL IP",
|
|
52
|
+
"EXTERNAL IP",
|
|
53
53
|
]
|
|
54
54
|
)
|
|
55
55
|
for lb in balancers:
|
|
@@ -58,8 +58,8 @@ def print_balancers(response: Response, filters: Optional[str]):
|
|
|
58
58
|
lb["id"],
|
|
59
59
|
lb["name"],
|
|
60
60
|
lb["status"],
|
|
61
|
-
lb["ip"],
|
|
62
61
|
lb["local_ip"],
|
|
62
|
+
lb["ip"],
|
|
63
63
|
]
|
|
64
64
|
)
|
|
65
65
|
table.print()
|
|
@@ -98,8 +98,8 @@ def print_balancer(response: Response):
|
|
|
98
98
|
"ID",
|
|
99
99
|
"NAME",
|
|
100
100
|
"STATUS",
|
|
101
|
-
"EXTERNAL IP",
|
|
102
101
|
"INTERNAL IP",
|
|
102
|
+
"EXTERNAL IP",
|
|
103
103
|
]
|
|
104
104
|
)
|
|
105
105
|
table.row(
|
|
@@ -107,8 +107,8 @@ def print_balancer(response: Response):
|
|
|
107
107
|
lb["id"],
|
|
108
108
|
lb["name"],
|
|
109
109
|
lb["status"],
|
|
110
|
-
lb["ip"],
|
|
111
110
|
lb["local_ip"],
|
|
111
|
+
lb["ip"],
|
|
112
112
|
]
|
|
113
113
|
)
|
|
114
114
|
table.print()
|
|
@@ -164,7 +164,7 @@ def balancer_create(
|
|
|
164
164
|
port: int = typer.Option(80, help="Load balancer listen port."),
|
|
165
165
|
path: str = typer.Option("/", help="URL path."),
|
|
166
166
|
proto: LoadBalancerProto = typer.Option(
|
|
167
|
-
|
|
167
|
+
LoadBalancerProto.HTTP.value, help="Health check protocol."
|
|
168
168
|
),
|
|
169
169
|
inter: int = typer.Option(10, help="Health checks interval in seconds."),
|
|
170
170
|
timeout: int = typer.Option(5, help="Health check timeout in seconds."),
|
|
@@ -187,6 +187,7 @@ def balancer_create(
|
|
|
187
187
|
callback=load_from_config_callback,
|
|
188
188
|
help="Add load balancer to specific project.",
|
|
189
189
|
),
|
|
190
|
+
network: Optional[str] = typer.Option(None, help="Private network ID."),
|
|
190
191
|
):
|
|
191
192
|
"""Create load balancer."""
|
|
192
193
|
client = create_client(config, profile)
|
|
@@ -206,22 +207,28 @@ def balancer_create(
|
|
|
206
207
|
]:
|
|
207
208
|
sys.exit(f"Wrong project ID: Project '{project_id}' not found.")
|
|
208
209
|
|
|
209
|
-
|
|
210
|
-
name
|
|
211
|
-
preset_id
|
|
212
|
-
algo
|
|
213
|
-
proto
|
|
214
|
-
port
|
|
215
|
-
path
|
|
216
|
-
inter
|
|
217
|
-
timeout
|
|
218
|
-
fall
|
|
219
|
-
rise
|
|
220
|
-
sticky
|
|
221
|
-
proxy_protocol
|
|
222
|
-
force_https
|
|
223
|
-
backend_keepalive
|
|
224
|
-
|
|
210
|
+
payload = {
|
|
211
|
+
"name": name,
|
|
212
|
+
"preset_id": preset_id,
|
|
213
|
+
"algo": algo,
|
|
214
|
+
"proto": proto,
|
|
215
|
+
"port": port,
|
|
216
|
+
"path": path,
|
|
217
|
+
"inter": inter,
|
|
218
|
+
"timeout": timeout,
|
|
219
|
+
"fall": fall,
|
|
220
|
+
"rise": rise,
|
|
221
|
+
"sticky": sticky,
|
|
222
|
+
"proxy_protocol": proxy_protocol,
|
|
223
|
+
"force_https": force_https,
|
|
224
|
+
"backend_keepalive": backend_keepalive,
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if network:
|
|
228
|
+
payload["network"] = {"id": network}
|
|
229
|
+
|
|
230
|
+
# Create LB
|
|
231
|
+
response = client.create_load_balancer(**payload)
|
|
225
232
|
|
|
226
233
|
# Add created LB to project if set
|
|
227
234
|
if project_id:
|
|
@@ -478,23 +485,18 @@ def balancer_rule_list(
|
|
|
478
485
|
# ------------------------------------------------------------- #
|
|
479
486
|
|
|
480
487
|
|
|
481
|
-
def
|
|
488
|
+
def validate_balancer_port_proto_callback(value):
|
|
482
489
|
"""Typer callback for PORT/PROTO validation."""
|
|
483
490
|
if value:
|
|
484
|
-
if not re.match(r"^\d+\/(http|http2|https|tcp)$", value):
|
|
491
|
+
if not re.match(r"^\d+\/(http|http2|https|tcp)$", value, re.I):
|
|
485
492
|
sys.exit(
|
|
486
493
|
f"Error: Malformed argument: '{value}': "
|
|
487
|
-
"Correct patterns: '443/
|
|
494
|
+
"Correct patterns: '443/HTTPS', '2000/TCP', etc.\n"
|
|
495
|
+
"Available protocols: "
|
|
496
|
+
f"{', '.join([lb.value for lb in LoadBalancerProto])}"
|
|
488
497
|
)
|
|
489
498
|
port, proto = value.split("/")
|
|
490
|
-
|
|
491
|
-
port = int(port)
|
|
492
|
-
else:
|
|
493
|
-
raise typer.BadParameter("Port number must be integer.")
|
|
494
|
-
try:
|
|
495
|
-
LoadBalancerProto(proto)
|
|
496
|
-
except ValueError as e:
|
|
497
|
-
raise typer.BadParameter(f"Protocol {e}")
|
|
499
|
+
port = int(port)
|
|
498
500
|
return port, proto
|
|
499
501
|
return value
|
|
500
502
|
|
|
@@ -508,13 +510,13 @@ def balancer_rule_add(
|
|
|
508
510
|
output_format: Optional[str] = output_format_option,
|
|
509
511
|
frontend: str = typer.Option(
|
|
510
512
|
...,
|
|
511
|
-
callback=
|
|
513
|
+
callback=validate_balancer_port_proto_callback,
|
|
512
514
|
metavar="PORT/PROTO",
|
|
513
515
|
help="Frontend port and protocol.",
|
|
514
516
|
),
|
|
515
517
|
backend: str = typer.Option(
|
|
516
518
|
...,
|
|
517
|
-
callback=
|
|
519
|
+
callback=validate_balancer_port_proto_callback,
|
|
518
520
|
metavar="PORT/PROTO",
|
|
519
521
|
help="Backend port and protocol.",
|
|
520
522
|
),
|
|
@@ -566,13 +568,13 @@ def balancer_rule_update(
|
|
|
566
568
|
output_format: Optional[str] = output_format_option,
|
|
567
569
|
frontend: Optional[str] = typer.Option(
|
|
568
570
|
None,
|
|
569
|
-
callback=
|
|
571
|
+
callback=validate_balancer_port_proto_callback,
|
|
570
572
|
metavar="PORT/PROTO",
|
|
571
573
|
help="Frontend port and protocol.",
|
|
572
574
|
),
|
|
573
575
|
backend: Optional[str] = typer.Option(
|
|
574
576
|
None,
|
|
575
|
-
callback=
|
|
577
|
+
callback=validate_balancer_port_proto_callback,
|
|
576
578
|
metavar="PORT/PROTO",
|
|
577
579
|
help="Backend port and protocol.",
|
|
578
580
|
),
|
twc/commands/common.py
CHANGED
|
@@ -152,13 +152,17 @@ def profile_callback(value: str, ctx: typer.Context) -> str:
|
|
|
152
152
|
def filter_callback(value: str) -> str:
|
|
153
153
|
"""Validate filters format."""
|
|
154
154
|
if value:
|
|
155
|
-
if not re.match(
|
|
155
|
+
if not re.match(
|
|
156
|
+
r"^(([a-z0-9._-]+:[a-z0-9._\-/+%]+),?)+$", value, re.I
|
|
157
|
+
):
|
|
156
158
|
raise UsageError(
|
|
157
159
|
"Invalid filter format. Filter must contain comma separated "
|
|
158
|
-
+ "KEY:VALUE pairs. Allowed characters: [a-zA-Z0-9_
|
|
160
|
+
+ "KEY:VALUE pairs. Allowed characters: [a-zA-Z0-9_.-/+%]"
|
|
159
161
|
)
|
|
160
|
-
# Make
|
|
161
|
-
value = value.replace("region", "location")
|
|
162
|
+
# Make aliases
|
|
163
|
+
value = value.replace("region:", "location:")
|
|
164
|
+
value = value.replace("proto:", "protocol:")
|
|
165
|
+
value = value.replace("rule_id:", "id:")
|
|
162
166
|
return value
|
|
163
167
|
|
|
164
168
|
|
twc/commands/config.py
CHANGED
|
@@ -24,7 +24,7 @@ from .common import (
|
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
config = typer.Typer(help=__doc__)
|
|
27
|
+
config = typer.Typer(help=__doc__, no_args_is_help=False)
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
DEFAULT_CONFIG = {"default": {"token": None}}
|
|
@@ -277,3 +277,30 @@ def config_edit(
|
|
|
277
277
|
):
|
|
278
278
|
"""Open configuration file in default editor."""
|
|
279
279
|
typer.launch(str(config))
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
# ------------------------------------------------------------- #
|
|
283
|
+
# $ twc config profiles #
|
|
284
|
+
# ------------------------------------------------------------- #
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@config.command("profiles")
|
|
288
|
+
def config_profile(
|
|
289
|
+
# pylint: disable=redefined-outer-name
|
|
290
|
+
config: Optional[Path] = typer.Option(
|
|
291
|
+
None,
|
|
292
|
+
"--config",
|
|
293
|
+
"-c",
|
|
294
|
+
envvar="TWC_CONFIG_FILE",
|
|
295
|
+
show_envvar=False,
|
|
296
|
+
exists=True,
|
|
297
|
+
dir_okay=False,
|
|
298
|
+
callback=config_callback,
|
|
299
|
+
hidden=True,
|
|
300
|
+
help="Use config.",
|
|
301
|
+
),
|
|
302
|
+
):
|
|
303
|
+
"""Display configuration profiles."""
|
|
304
|
+
config_dict = load_config(config)
|
|
305
|
+
for key in config_dict.keys():
|
|
306
|
+
print(key)
|