twc-cli 2.9.2__tar.gz → 2.10.1__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.9.2 → twc_cli-2.10.1}/CHANGELOG.md +26 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/PKG-INFO +1 -1
- {twc_cli-2.9.2 → twc_cli-2.10.1}/pyproject.toml +1 -1
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/__version__.py +1 -1
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/api/client.py +154 -5
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/api/types.py +6 -10
- twc_cli-2.10.1/twc/commands/database.py +1042 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/server.py +16 -6
- twc_cli-2.10.1/twc/vars.py +32 -0
- twc_cli-2.9.2/twc/commands/database.py +0 -540
- twc_cli-2.9.2/twc/vars.py +0 -14
- {twc_cli-2.9.2 → twc_cli-2.10.1}/COPYING +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/README.md +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/__init__.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/__main__.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/api/__init__.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/api/base.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/api/exceptions.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/apiwrap.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/__init__.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/account.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/balancer.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/common.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/config.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/domain.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/firewall.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/floating_ip.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/image.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/kubernetes.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/project.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/ssh_key.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/storage.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/commands/vpc.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/fmt.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/typerx.py +0 -0
- {twc_cli-2.9.2 → twc_cli-2.10.1}/twc/utils.py +0 -0
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
В этом файле описаны все значимые изменения в Timeweb Cloud CLI. В выпусках мы придерживается правил [семантического версионирования](https://semver.org/lang/ru/).
|
|
4
4
|
|
|
5
|
+
# Версия 2.10.1 (2025.03.25)
|
|
6
|
+
|
|
7
|
+
## Исправлено
|
|
8
|
+
|
|
9
|
+
- Исправлена ошибка получения публичного IP при создании кластера СУБД.
|
|
10
|
+
|
|
11
|
+
# Версия 2.10.0 (2025.03.24)
|
|
12
|
+
|
|
13
|
+
## Добавлено
|
|
14
|
+
|
|
15
|
+
- Добавлена поддержка региона `de-1` (зона `fra-1`) для облачных серверов.
|
|
16
|
+
- Добавлены новые опции к команде `twc database create`:
|
|
17
|
+
- для создания пользователя СУБД: `--user-login`, `--user-password`, `--user-host`, `--user-privileges`, `--user-desc`;
|
|
18
|
+
- для создания первой базы данных: `--db-name`, `--db-desc`;
|
|
19
|
+
- для настроек сети в класетере СУБД: `--network-id`, `--private-ip`, `--public-ip`, `--no-public-ip`;
|
|
20
|
+
- для настройки автоматических бэкапов кластера: `--enable-backups`, `--backup-keep`, `--backup-start-date`, `--backup-interval`, `--backup-day-of-week`.
|
|
21
|
+
- Добавлена новая команда `twc database list-types` для вывода доступных к созданию управляемых баз данных.
|
|
22
|
+
- Добавлена новая команда `twc database backup schedule` позволяющая настроить параметры автоматического резервного копирования кластера.
|
|
23
|
+
- Добавлены новые команды для управления пользователями в кластерах СУБД: `twc database user list`, `twc database user get`, `twc database user create`, `twc database user remove`.
|
|
24
|
+
- Добавлены новые команды для управления базами данных в кластерах СУБД: `twc database instance list`, `twc database instance create`, `twc database instance remove`.
|
|
25
|
+
|
|
26
|
+
## Изменено
|
|
27
|
+
|
|
28
|
+
- Опция `--network` команды `twc server create` объявлена устаревшей и скрыта, добавлена эквивалентная опция `--network-id`.
|
|
29
|
+
- Опции `--login` и `--password` команды `twc database create` объявлены устаревшими и скрыты, вместо них теперь нужно использовать `--user-login` и `--user-password`.
|
|
30
|
+
|
|
5
31
|
# Версия 2.9.2 (2025.03.10)
|
|
6
32
|
|
|
7
33
|
## Исправлено
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Timeweb Cloud API client."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
from typing import Optional, Union, List
|
|
4
6
|
from uuid import UUID
|
|
5
7
|
from pathlib import Path
|
|
@@ -20,7 +22,6 @@ from .types import (
|
|
|
20
22
|
ServiceRegion,
|
|
21
23
|
ServiceAvailabilityZone,
|
|
22
24
|
ResourceType,
|
|
23
|
-
DBMS,
|
|
24
25
|
MySQLAuthPlugin,
|
|
25
26
|
LoadBalancerProto,
|
|
26
27
|
LoadBalancerAlgo,
|
|
@@ -727,19 +728,27 @@ class TimewebCloud(TimewebCloudBase):
|
|
|
727
728
|
"""Get database presets list."""
|
|
728
729
|
return self._request("GET", f"{self.api_url}/presets/dbs")
|
|
729
730
|
|
|
731
|
+
def get_database_types(self):
|
|
732
|
+
"""Get database types."""
|
|
733
|
+
return self._request("GET", f"{self.api_url}/database-types")
|
|
734
|
+
|
|
735
|
+
def get_database_configrators(self):
|
|
736
|
+
"""Get database_configurators."""
|
|
737
|
+
return self._request(
|
|
738
|
+
"GET", f"{self.api_url_v1}/configurator/databases"
|
|
739
|
+
)
|
|
740
|
+
|
|
730
741
|
def create_database(
|
|
731
742
|
self,
|
|
732
743
|
name: str,
|
|
733
|
-
dbms:
|
|
744
|
+
dbms: str,
|
|
734
745
|
preset_id: int,
|
|
735
746
|
password: str,
|
|
736
747
|
login: Optional[str] = None,
|
|
737
748
|
hash_type: Optional[MySQLAuthPlugin] = None,
|
|
738
749
|
config_parameters: Optional[dict] = None,
|
|
739
750
|
):
|
|
740
|
-
"""Create database."""
|
|
741
|
-
if dbms == "mysql8":
|
|
742
|
-
dbms = "mysql"
|
|
751
|
+
"""Create database. DEPRECATED."""
|
|
743
752
|
payload = {
|
|
744
753
|
"name": name,
|
|
745
754
|
"type": dbms,
|
|
@@ -751,6 +760,42 @@ class TimewebCloud(TimewebCloudBase):
|
|
|
751
760
|
}
|
|
752
761
|
return self._request("POST", f"{self.api_url}/dbs", json=payload)
|
|
753
762
|
|
|
763
|
+
def create_database2(
|
|
764
|
+
self,
|
|
765
|
+
name: str,
|
|
766
|
+
dbms: str,
|
|
767
|
+
network: Optional[dict[str, str]] = None,
|
|
768
|
+
preset_id: Optional[int] = None,
|
|
769
|
+
configurator_id: Optional[int] = None,
|
|
770
|
+
admin: Optional[dict[str, str]] = None,
|
|
771
|
+
instance: Optional[dict[str, str]] = None,
|
|
772
|
+
auto_backups: Optional[dict[str, str]] = None,
|
|
773
|
+
hash_type: Optional[MySQLAuthPlugin] = None,
|
|
774
|
+
config_parameters: Optional[dict] = None,
|
|
775
|
+
project_id: Optional[int] = None,
|
|
776
|
+
):
|
|
777
|
+
"""Create database cluster."""
|
|
778
|
+
payload = {
|
|
779
|
+
"name": name,
|
|
780
|
+
"type": dbms,
|
|
781
|
+
"hash_type": hash_type,
|
|
782
|
+
**({"network": network} if network else {}),
|
|
783
|
+
**(
|
|
784
|
+
{"config_parameters": config_parameters}
|
|
785
|
+
if config_parameters
|
|
786
|
+
else {}
|
|
787
|
+
),
|
|
788
|
+
**({"preset_id": preset_id} if preset_id else {}),
|
|
789
|
+
**(
|
|
790
|
+
{"configurator_id": configurator_id} if configurator_id else {}
|
|
791
|
+
),
|
|
792
|
+
**({"admin": admin} if admin else {}),
|
|
793
|
+
**({"auto_backups": auto_backups} if auto_backups else {}),
|
|
794
|
+
**({"instance": instance} if instance else {}),
|
|
795
|
+
**({"project_id": project_id} if project_id else {}),
|
|
796
|
+
}
|
|
797
|
+
return self._request("POST", f"{self.api_url}/databases", json=payload)
|
|
798
|
+
|
|
754
799
|
def update_database(
|
|
755
800
|
self,
|
|
756
801
|
db_id: int,
|
|
@@ -837,6 +882,110 @@ class TimewebCloud(TimewebCloudBase):
|
|
|
837
882
|
f"{self.api_url}/dbs/{db_id}/backups/{backup_id}",
|
|
838
883
|
)
|
|
839
884
|
|
|
885
|
+
def get_database_autobackup_settings(self, db_id: int):
|
|
886
|
+
"""Get database autobackup settings."""
|
|
887
|
+
return self._request(
|
|
888
|
+
"GET",
|
|
889
|
+
f"{self.api_url}/dbs/{db_id}/auto-backups",
|
|
890
|
+
)
|
|
891
|
+
|
|
892
|
+
def update_database_autobackup_settings(
|
|
893
|
+
self,
|
|
894
|
+
db_id: int,
|
|
895
|
+
is_enabled: Optional[bool] = None,
|
|
896
|
+
copy_count: Optional[int] = None,
|
|
897
|
+
creation_start_at: Optional[int] = None,
|
|
898
|
+
interval: Optional[BackupInterval] = None,
|
|
899
|
+
day_of_week: Optional[int] = None,
|
|
900
|
+
):
|
|
901
|
+
"""Set database autobackup settings."""
|
|
902
|
+
payload = {
|
|
903
|
+
**({"is_enabled": is_enabled} if is_enabled is not None else {}),
|
|
904
|
+
**({"copy_count": copy_count} if copy_count else {}),
|
|
905
|
+
**(
|
|
906
|
+
{"creation_start_at": creation_start_at}
|
|
907
|
+
if creation_start_at
|
|
908
|
+
else {}
|
|
909
|
+
),
|
|
910
|
+
**({"interval": interval} if interval else {}),
|
|
911
|
+
**({"day_of_week": day_of_week} if day_of_week else {}),
|
|
912
|
+
}
|
|
913
|
+
return self._request(
|
|
914
|
+
"PATCH",
|
|
915
|
+
f"{self.api_url}/dbs/{db_id}/auto-backups",
|
|
916
|
+
json=payload,
|
|
917
|
+
)
|
|
918
|
+
|
|
919
|
+
def create_database_user(
|
|
920
|
+
self,
|
|
921
|
+
db_id: int,
|
|
922
|
+
login: str,
|
|
923
|
+
password: str,
|
|
924
|
+
privileges: List[str],
|
|
925
|
+
host: Optional[str] = None,
|
|
926
|
+
instance_id: Optional[int] = None,
|
|
927
|
+
description: Optional[str] = None,
|
|
928
|
+
):
|
|
929
|
+
payload = {
|
|
930
|
+
"login": login,
|
|
931
|
+
"password": password,
|
|
932
|
+
"privileges": privileges,
|
|
933
|
+
}
|
|
934
|
+
if host:
|
|
935
|
+
payload["host"] = host
|
|
936
|
+
if instance_id:
|
|
937
|
+
payload["instance_id"] = instance_id
|
|
938
|
+
if description:
|
|
939
|
+
payload["description"] = description
|
|
940
|
+
return self._request(
|
|
941
|
+
"POST", f"{self.api_url}/databases/{db_id}/admins", json=payload
|
|
942
|
+
)
|
|
943
|
+
|
|
944
|
+
def get_database_users(self, db_id: int):
|
|
945
|
+
"""..."""
|
|
946
|
+
return self._request(
|
|
947
|
+
"GET", f"{self.api_url_v1}/databases/{db_id}/admins"
|
|
948
|
+
)
|
|
949
|
+
|
|
950
|
+
def get_database_user(self, db_id: int, user_id: int):
|
|
951
|
+
"""..."""
|
|
952
|
+
return self._request(
|
|
953
|
+
"GET", f"{self.api_url_v1}/databases/{db_id}/admins/{user_id}"
|
|
954
|
+
)
|
|
955
|
+
|
|
956
|
+
def delete_database_user(self, db_id: int, user_id: int):
|
|
957
|
+
"""..."""
|
|
958
|
+
return self._request(
|
|
959
|
+
"DELETE", f"{self.api_url_v1}/databases/{db_id}/admins/{user_id}"
|
|
960
|
+
)
|
|
961
|
+
|
|
962
|
+
def create_database_instance(
|
|
963
|
+
self,
|
|
964
|
+
db_id: int,
|
|
965
|
+
name: str,
|
|
966
|
+
description: Optional[str] = None,
|
|
967
|
+
):
|
|
968
|
+
"""..."""
|
|
969
|
+
payload = {"name": name}
|
|
970
|
+
if description:
|
|
971
|
+
payload["description"] = description
|
|
972
|
+
return self._request(
|
|
973
|
+
"POST", f"{self.api_url}/databases/{db_id}/instances"
|
|
974
|
+
)
|
|
975
|
+
|
|
976
|
+
def get_database_instances(self, db_id: int):
|
|
977
|
+
"""..."""
|
|
978
|
+
return self._request(
|
|
979
|
+
"GET", f"{self.api_url}/databases/{db_id}/instances"
|
|
980
|
+
)
|
|
981
|
+
|
|
982
|
+
def delete_database_instance(self, db_id: int, instance_id: int):
|
|
983
|
+
"""..."""
|
|
984
|
+
return self._request(
|
|
985
|
+
"DELETE",
|
|
986
|
+
f"{self.api_url}/databases/{db_id}/instances/{instance_id}",
|
|
987
|
+
)
|
|
988
|
+
|
|
840
989
|
# -----------------------------------------------------------------------
|
|
841
990
|
# Object Storage
|
|
842
991
|
|
|
@@ -13,6 +13,7 @@ class ServiceRegion(str, Enum):
|
|
|
13
13
|
KZ_1 = "kz-1"
|
|
14
14
|
PL_1 = "pl-1"
|
|
15
15
|
NL_1 = "nl-1"
|
|
16
|
+
DE_1 = "de-1"
|
|
16
17
|
|
|
17
18
|
@classmethod
|
|
18
19
|
def get_zones(cls, region: str) -> List[str]:
|
|
@@ -29,6 +30,8 @@ class ServiceRegion(str, Enum):
|
|
|
29
30
|
return ["gdn-1"]
|
|
30
31
|
if region == cls.NL_1:
|
|
31
32
|
return ["ams-1"]
|
|
33
|
+
if region == cls.DE_1:
|
|
34
|
+
return ["fra-1"]
|
|
32
35
|
return []
|
|
33
36
|
|
|
34
37
|
|
|
@@ -44,6 +47,7 @@ class ServiceAvailabilityZone(str, Enum):
|
|
|
44
47
|
ALA_1 = "ala-1"
|
|
45
48
|
GDN_1 = "gdn-1"
|
|
46
49
|
AMS_1 = "ams-1"
|
|
50
|
+
FRA_1 = "fra-1"
|
|
47
51
|
|
|
48
52
|
@classmethod
|
|
49
53
|
def get_region(cls, zone: str) -> Optional[str]:
|
|
@@ -60,6 +64,8 @@ class ServiceAvailabilityZone(str, Enum):
|
|
|
60
64
|
return ServiceRegion.PL_1
|
|
61
65
|
if zone == cls.AMS_1:
|
|
62
66
|
return ServiceRegion.NL_1
|
|
67
|
+
if zone == cls.FRA_1:
|
|
68
|
+
return ServiceRegion.DE_1
|
|
63
69
|
return None
|
|
64
70
|
|
|
65
71
|
|
|
@@ -170,16 +176,6 @@ class ResourceType(str, Enum):
|
|
|
170
176
|
DEDICATED_SERVER = "dedicated"
|
|
171
177
|
|
|
172
178
|
|
|
173
|
-
class DBMS(str, Enum):
|
|
174
|
-
"""Available DBMS in Timeweb Cloud managed databases service."""
|
|
175
|
-
|
|
176
|
-
MYSQL_5 = "mysql5"
|
|
177
|
-
MYSQL_8 = "mysql8"
|
|
178
|
-
POSTGRES = "postgres"
|
|
179
|
-
REDIS = "redis"
|
|
180
|
-
MONGODB = "mongodb"
|
|
181
|
-
|
|
182
|
-
|
|
183
179
|
class MySQLAuthPlugin(str, Enum):
|
|
184
180
|
"""MySQL auth plugin options in Timeweb Cloud managed databases
|
|
185
181
|
service.
|