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.

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 ServiceRegion, ServerOSType
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
- "UUID",
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["name"],
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, with_deleted=with_deleted)
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
- "UUID",
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[ServiceRegion] = typer.Option(
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, ProjectResource
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 ProjectResource],
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
- False,
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="Turns on LAN with specified NAT mode.",
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
- local_network = True
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
- "is_local_network": local_network,
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(False),
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(None),
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
- """This module defines variables that depend on Timeweb Cloud products.
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"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: twc-cli
3
- Version: 2.3.0
3
+ Version: 2.4.1
4
4
  Summary: Timeweb Cloud Command Line Interface.
5
5
  Home-page: https://github.com/timeweb-cloud/twc
6
6
  License: MIT
@@ -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,,
@@ -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,,