Skip to content

Commit

Permalink
release 1.0.9 (#25)
Browse files Browse the repository at this point in the history
Support three new endpoints, which are released in [v1beta Release 20230328](https://docs.pingcap.com/tidbcloud/api/v1beta#section/API-Changelog/20230328):

- [Create a project](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Project/operation/CreateProject)
- [List AWS Customer-Managed Encryption Keys for a project](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/ListAwsCmek)
- [Configure AWS Customer-Managed Encryption Keys for a project](https://docs.pingcap.com/tidbcloud/api/v1beta#tag/Cluster/operation/CreateAwsCmek)
  • Loading branch information
Oreoxmt authored Oct 3, 2023
1 parent 9a0f998 commit 40f87c0
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 12 deletions.
57 changes: 55 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

- [Prerequisites](https://github.com/Oreoxmt/tidbcloudy#prerequisites)
- [List all resources in your organization](https://github.com/Oreoxmt/tidbcloudy#list-all-resources-in-your-organization)
- [Create a project and manage your AWS CMEK](https://github.com/Oreoxmt/tidbcloudy#create-a-project-and-manage-your-aws-cmek) **New in 1.0.9**
- [Create a cluster](https://github.com/Oreoxmt/tidbcloudy#create-a-cluster)
- [Connect to TiDB](https://github.com/Oreoxmt/tidbcloudy#connect-to-tidb)
- [Modify a cluster](https://github.com/Oreoxmt/tidbcloudy#modify-a-cluster)
Expand All @@ -35,15 +36,15 @@ If you do not have a TiDB Cloud account yet, you can sign up [here](https://tidb
You can use this SDK to access [TiDB Cloud](https://tidbcloud.com) and manage your billings, projects, clusters, backups and restores:

- manage your **billings** of your organization (_get_)
- manage your TiDB Cloud **projects** (only _list_ is supported now)
- manage your TiDB Cloud **projects** (_list_, _create_) and manage the **AWS CMEK** of your projects (_get_, _create_)
- list all available cloud providers (AWS and GCP), regions, and specifications before creating or modifying a cluster
- manage your TiDB Serverless or TiDB Dedicated **clusters** (_create_, _modify_, _pause_, _resume_, _get_, _list_, _delete_)
- manage your **backups** of a cluster (_create_, _get_, _list_, _delete_)
- manage your **restores** of a project (_create_, _get_, _list_)

### Compatibility with TiDB Cloud API

`tidbcloudy` is compatible with TiDB Cloud API. **Endpoints added in [v1beta Release 20230228](https://docs.pingcap.com/tidbcloud/api/v1beta#section/API-Changelog/20230228), [v1beta Release 20230328](https://docs.pingcap.com/tidbcloud/api/v1beta#section/API-Changelog/20230328), and [v1beta Release 20230905](https://docs.pingcap.com/tidbcloud/api/v1beta#section/API-Changelog/20230905) are not supported for now**. The following table lists the compatibility between `tidbcloudy` and TiDB Cloud API.
`tidbcloudy` is compatible with TiDB Cloud API. **Endpoints added in [v1beta Release 20230228](https://docs.pingcap.com/tidbcloud/api/v1beta#section/API-Changelog/20230228) and [v1beta Release 20230905](https://docs.pingcap.com/tidbcloud/api/v1beta#section/API-Changelog/20230905) are not supported for now**. The following table lists the compatibility between `tidbcloudy` and TiDB Cloud API.

<table>
<thead>
Expand All @@ -70,6 +71,23 @@ You can use this SDK to access [TiDB Cloud](https://tidbcloud.com) and manage yo
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://github.com/Oreoxmt/tidbcloudy/releases/tag/v1.0.9" target="_blank" rel="noopener noreferrer">1.0.9</a></td>
<td>✅</td>
<td>❌</td>
<td>✅</td>
<td>✅</td>
<td>✅</td>
<td>✅</td>
<td>❌</td>
<td>✅</td>
<td>✅</td>
<td>✅</td>
<td>✅</td>
<td>✅</td>
<td>✅</td>
<td>✅</td>
</tr>
<tr>
<td><a href="https://github.com/Oreoxmt/tidbcloudy/releases/tag/v1.0.8" target="_blank" rel="noopener noreferrer">1.0.8</a></td>
<td>✅</td>
Expand Down Expand Up @@ -316,6 +334,8 @@ To get full code examples, see the [`examples`](https://github.com/Oreoxmt/tidbc
### List all resources in your organization
**This feature is available in `tidbcloudy` 1.0.9 or later.**
To get the full code example of listing all projects, clusters, backup tasks, and restore tasks in your organization, see [`0_list_resources.py`](https://github.com/Oreoxmt/tidbcloudy/tree/main/examples/0_list_resources.py).
```python
Expand All @@ -331,6 +351,9 @@ api = tidbcloudy.TiDBCloud(public_key=public_key, private_key=private_key)
for project in api.iter_projects():
print(project)
if project.aws_cmek_enabled:
for aws_cmek in project.iter_aws_cmek():
print(aws_cmek)
for cluster in project.iter_clusters():
print(cluster)
if cluster.cluster_type == ClusterType.DEDICATED:
Expand All @@ -340,6 +363,32 @@ for project in api.iter_projects():
print(restore)
```
### Create a project and manage your AWS CMEK
To create a project, run the [`8_manage_project.py`](https://github.com/Oreoxmt/tidbcloudy/tree/main/examples/8_manage_project.py).
```python
import os
import tidbcloudy
public_key = os.environ.get("PUBLIC_KEY")
private_key = os.environ.get("PRIVATE_KEY")
debug_mode = os.environ.get("TIDBCLOUDY_LOG")
api = tidbcloudy.TiDBCloud(public_key=public_key, private_key=private_key)
# Create a project with AWS CMEK enabled
project = api.create_project(name="0", aws_cmek_enabled=True, update_from_server=True)
print(project)
# Configure AWS CMEK for the project
project.create_aws_cmek([("your_aws_region_1", "your_aws_kms_arn_1"), ("your_aws_region_2", "your_aws_kms_arn_2")])
# List all AWS CMEKs of the project
for cmek in project.iter_aws_cmek():
print(cmek)
```
### Create a cluster
Before creating a cluster, you should list all available provider regions and cluster configuration specifications. For more details, run the [`1_list_provider_regions.py`](https://github.com/Oreoxmt/tidbcloudy/tree/main/examples/1_list_provider_regions.py).
Expand Down Expand Up @@ -524,6 +573,8 @@ for restore in project.iter_restores():
### Pause or resume your cluster
**This feature is available in `tidbcloudy` 1.0.0 or later.**
To pause or resume your cluster, run the [`6_pause_cluster.py`](https://github.com/Oreoxmt/tidbcloudy/tree/main/examples/6_pause_cluster.py).
```python
Expand Down Expand Up @@ -554,6 +605,8 @@ if cluster.status.cluster_status == ClusterStatus.RESUMING:
### Get monthly bills of your organization
**This feature is available in `tidbcloudy` 1.0.8 or later.**
To get the billing information of your organization, run the [`v1beta1_get_monthly_bill.py`](https://github.com/Oreoxmt/tidbcloudy/tree/main/examples/v1beta1_get_monthly_bill.py).
```python
Expand Down
12 changes: 11 additions & 1 deletion examples/0_list_resources.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import os

import tidbcloudy
from tidbcloudy.backup import Backup
from tidbcloudy.cluster import Cluster
from tidbcloudy.project import Project
from tidbcloudy.specification import ClusterType
from tidbcloudy.restore import Restore
from tidbcloudy.specification import ClusterType, ProjectAWSCMEK

public_key = os.environ.get("PUBLIC_KEY")
private_key = os.environ.get("PRIVATE_KEY")
Expand All @@ -14,12 +17,19 @@
for project in api.iter_projects():
assert isinstance(project, Project)
print(project)
if project.aws_cmek_enabled:
for aws_cmek in project.iter_aws_cmek():
assert isinstance(aws_cmek, ProjectAWSCMEK)
print(aws_cmek)
for cluster in project.iter_clusters():
assert isinstance(cluster, Cluster)
print(cluster)
if cluster.cluster_type == ClusterType.DEDICATED:
for backup in cluster.iter_backups():
assert isinstance(backup, Backup)
print(backup)
for restore in project.iter_restores():
assert isinstance(restore, Restore)
print(restore)

# get_project() does not fetch full information of a project from the server by default
Expand Down
2 changes: 1 addition & 1 deletion examples/2_1_create_serverless_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
project = api.get_project(project_id, update_from_server=True)

config = CreateClusterConfig()
config\
config \
.set_name("serverless-0") \
.set_cluster_type("DEVELOPER") \
.set_cloud_provider("AWS") \
Expand Down
2 changes: 1 addition & 1 deletion examples/2_2_create_dedicated_cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
project = api.get_project(project_id, update_from_server=True)

config = CreateClusterConfig()
config\
config \
.set_name("dedicated-1") \
.set_cluster_type("DEDICATED") \
.set_cloud_provider("AWS") \
Expand Down
19 changes: 19 additions & 0 deletions examples/8_manage_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os

import tidbcloudy

public_key = os.environ.get("PUBLIC_KEY")
private_key = os.environ.get("PRIVATE_KEY")
debug_mode = os.environ.get("TIDBCLOUDY_LOG")

api = tidbcloudy.TiDBCloud(public_key=public_key, private_key=private_key)
# Create a project with AWS CMEK enabled
project = api.create_project(name="0", aws_cmek_enabled=True, update_from_server=True)
print(project)

# Configure AWS CMEK for the project
project.create_aws_cmek([("your_aws_region_1", "your_aws_kms_arn_1"), ("your_aws_region_2", "your_aws_kms_arn_2")])

# List all AWS CMEKs of the project
for cmek in project.iter_aws_cmek():
print(cmek)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "tidbcloudy"
version = "1.0.8"
version = "1.0.9"
description = "(Unofficial) Python SDK for TiDB Cloud"
readme = "README.md"
authors = ["Aolin <aolinz@outlook.com>"]
Expand Down
82 changes: 76 additions & 6 deletions tidbcloudy/project.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
from typing import Union, Iterator
from typing import Iterator, List, Tuple, Union

from ._base import TiDBCloudyBase, TiDBCloudyContextualBase, TiDBCloudyField
from .cluster import Cluster
from .restore import Restore
from .specification import CreateClusterConfig, UpdateClusterConfig
from .util.timestamp import timestamp_to_string
from .specification import CreateClusterConfig, ProjectAWSCMEK, UpdateClusterConfig
from .util.page import Page
from .util.timestamp import timestamp_to_string


# noinspection PyShadowingBuiltins
class Project(TiDBCloudyBase, TiDBCloudyContextualBase):
__slots__ = ["_id", "_org_id", "_name", "_cluster_count", "_user_count", "_create_timestamp"]
__slots__ = ["_id", "_org_id", "_name", "_cluster_count", "_user_count", "_create_timestamp", "_aws_cmek_enabled"]
id: str = TiDBCloudyField(str)
org_id: str = TiDBCloudyField(str)
name: str = TiDBCloudyField(str)
cluster_count: int = TiDBCloudyField(int)
user_count: int = TiDBCloudyField(int)
create_timestamp: int = TiDBCloudyField(int, convert_from=int, convert_to=str)
aws_cmek_enabled: bool = TiDBCloudyField(bool)

def create_cluster(self, config: Union[CreateClusterConfig, dict]) -> Cluster:
"""
Expand Down Expand Up @@ -248,6 +249,75 @@ def iter_restores(self, page_size: int = 10) -> Iterator[Restore]:
yield restore
page += 1

def create_aws_cmek(self, config: List[Tuple[str, str]]) -> None:
"""
Configure the AWS Customer-Managed Encryption Keys (CMEK) for the project.
Args:
config: the configuration of the CMEK. The format is [(region, kms_arn), ...]
Examples:
.. code-block:: python
import tidbcloudy
api = tidbcloudy.TiDBCloud(public_key="your_public_key", private_key="your_private_key")
project = api.create_project(name="your_project_name", aws_cmek_enabled=True, update_from_server=True)
project.create_aws_cmek([(region, kms_arn), ...]
for cmek in project.iter_aws_cmek():
print(cmek)
"""
payload = {
"specs": []
}
for region, kms_arn in config:
payload["specs"].append({
"region": region,
"kms_arn": kms_arn
})
path = f"projects/{self.id}/aws-cmek"
self.context.call_post(path=path, json=payload)

def list_aws_cmek(self) -> Page[ProjectAWSCMEK]:
"""
List all AWS Customer-Managed Encryption Keys (CMEK) in the project.
Returns:
The page of the CMEK in the project.
Examples:
.. code-block:: python
import tidbcloudy
api = tidbcloudy.TiDBCloud(public_key="your_public_key", private_key="your_private_key")
project = api.get_project(project_id)
cmeks = project.list_aws_cmek()
for cmek in cmeks.items:
print(cmek)
"""
path = f"projects/{self.id}/aws-cmek"
resp = self.context.call_get(path=path)
total = len(resp["items"])
return Page(
[ProjectAWSCMEK.from_object(self.context, item) for item in resp["items"]],
1, total, total)

def iter_aws_cmek(self) -> Iterator[ProjectAWSCMEK]:
"""
This is not a TiDB Cloud API official endpoint.
Iterate all AWS Customer-Managed Encryption Keys (CMEK) in the project.
Returns:
The iterator of the CMEK in the project.
Examples:
.. code-block:: python
import tidbcloudy
api = tidbcloudy.TiDBCloud(public_key="your_public_key", private_key="your_private_key")
project = api.get_project(project_id)
for cmek in project.iter_aws_cmek():
print(cmek)
"""
cmeks = self.list_aws_cmek()
for cmek in cmeks.items:
yield cmek

def __repr__(self):
return "<Project id={} name={} create_at={}>".format(
self.id, self.name, timestamp_to_string(self.create_timestamp))
return "<Project id={} name={} aws_cmek_enabled={} create_at={}>".format(
self.id, self.name, self.aws_cmek_enabled, timestamp_to_string(self.create_timestamp))
10 changes: 10 additions & 0 deletions tidbcloudy/specification.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,16 @@ def __repr__(self):
self.status.value if self.status is not None else None)


class ProjectAWSCMEK(TiDBCloudyBase):
__slots__ = ["_region", "_kms_arn"]
region: str = None
kms_arn: str = None

def __repr__(self):
return "<region={}, kms_arn={}>".format(
self.region, self.kms_arn)


class BillingBase(TiDBCloudyBase):
__slots__ = ["_credits", "_discounts", "_runningTotal", "_totalCost"]
credits: str = TiDBCloudyField(str)
Expand Down
29 changes: 29 additions & 0 deletions tidbcloudy/tidbcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,35 @@ class TiDBCloud:
def __init__(self, public_key: str, private_key: str):
self._context = Context(public_key, private_key)

def create_project(self, name: str, aws_cmek_enabled: bool = False, update_from_server: bool = False) -> Project:
"""
Create a project.
Args:
name: the project name.
aws_cmek_enabled: whether to enable AWS Customer-Managed Encryption Keys.
update_from_server: whether to update the project info after creating.
Returns:
If the update_from_server is False, return a Project object with only the context and project_id.
If the update_from_server is True, return a Project object with all the info.
Examples:
.. code-block:: python
import tidbcloudy
api = tidbcloudy.TiDBCloud(public_key="your_public_key", private_key="your_private_key")
project = api.create_project(name="your_project_name", aws_cmek_enabled=False, update_from_server=True)
print(project)
"""
config = {
"name": name,
"aws_cmek_enabled": aws_cmek_enabled
}
resp = self._context.call_post(path="projects", json=config)
project_id = resp["id"]
if update_from_server:
return self.get_project(project_id=project_id, update_from_server=True)
return Project(context=self._context, id=project_id)

def get_project(self, project_id: str, update_from_server: bool = False) -> Project:
"""
Get the project object by project_id.
Expand Down

0 comments on commit 40f87c0

Please sign in to comment.