diff --git a/.gitignore b/.gitignore index 234af93..83fb364 100644 --- a/.gitignore +++ b/.gitignore @@ -160,4 +160,5 @@ cython_debug/ #.idea/ .vscode -.ruff_cache \ No newline at end of file +.ruff_cache +examples/test* \ No newline at end of file diff --git a/bk_bscp/client.py b/bk_bscp/client.py index eb7a47c..64adf8a 100644 --- a/bk_bscp/client.py +++ b/bk_bscp/client.py @@ -14,6 +14,7 @@ # We undertake not to change the open source license (MIT license) applicable # to the current version of the project delivered to anyone in the future. """The client for bscp feed-server""" + import json import logging import random @@ -36,7 +37,7 @@ ) from bk_bscp.grpc_lib.core.base import base_pb2 from bk_bscp.grpc_lib.feed_server import feed_server_pb2, feed_server_pb2_grpc -from bk_bscp.models import KeyValuePair, KeyValueUpdatedEvent, WatchAppInputParams +from bk_bscp.models import AppOptions, KeyValuePair, KeyValueUpdatedEvent, Release, WatchAppInputParams from bk_bscp.utils import get_fingerprint logger = logging.getLogger("bk_bscp") @@ -153,6 +154,42 @@ def do_handshake(self): raise BscpClientHandshakeError("Unable to handshake", e) from e logger.debug("Handshake success, api_version: %s", response.api_version) + def pull_kvs(self, app: str, match: List[str], app_options: Optional[AppOptions] = None) -> Release: + """Pull key-value Release from the server. + :param app: The app name. + :param match: The key. + :param app_options: the app option params. + :return: A kv Release. + :raises BscpClientGetError: If get failed. + """ + total_labels = {**self.labels} + uid = self._fingerprint + + if app_options is not None: + uid = app_options.uid or self._fingerprint + total_labels = {**self.labels, **(app_options.labels or {})} + match = [*match, *(app_options.match or [])] + + msg = feed_server_pb2.PullKvMetaReq( + match=match, + biz_id=self.biz_id, + app_meta=feed_server_pb2.AppMeta( + uid=uid, + app=app, + labels=total_labels, + ), + ) + try: + response = self.stub.PullKvMeta(msg, metadata=self._get_req_metadata()) + except grpc.RpcError as e: + raise BscpClientGetError(f'Unable to get "{app}" release, details: {e.details()}', e) from e + + r = Release( + release_id=response.release_id, + kvs=response.kv_metas, + ) + return r + def get(self, app: str, key: str, labels: Optional[dict] = None) -> KeyValuePair: """Get a key-value pair from the server. diff --git a/bk_bscp/models.py b/bk_bscp/models.py index 26ac6a6..732b59f 100644 --- a/bk_bscp/models.py +++ b/bk_bscp/models.py @@ -16,6 +16,7 @@ from dataclasses import dataclass from typing import Any, Dict, List +from bk_bscp.grpc_lib.feed_server import feed_server_pb2 from bk_bscp.utils import dict_to_dataclass @@ -73,3 +74,20 @@ class KeyValuePair: key: str type: str value: Any + + +@dataclass +class AppOptions: + """AppOptions options for app pull and watch""" + + match: List[str] # Match matches config items + labels: Dict[str, str] # Labels instance labels + uid: str # UID instance unique uid + + +@dataclass +class Release: + """Release info returned by the bscp server.""" + + release_id: int + kvs: List[feed_server_pb2.KvMeta] diff --git a/examples/get_key.py b/examples/get_key.py index e5ca2c6..9f641f2 100644 --- a/examples/get_key.py +++ b/examples/get_key.py @@ -14,7 +14,8 @@ # We undertake not to change the open source license (MIT license) applicable # to the current version of the project delivered to anyone in the future. """Get a key.""" -from bk_bscp.client import BscpClient + +from bk_bscp.client import AppOptions, BscpClient SERVER_ADDRS = ["example.com:9090"] TOKEN = "your_token" @@ -27,6 +28,20 @@ def get_key(): print(pair) +def get_all_keys(): + app = AppOptions( + match=[], + labels={}, + uid="", + ) + + with BscpClient(SERVER_ADDRS, TOKEN, BIZ_ID) as client: + release = client.pull_kvs("app1", ["key1"], app) + for kv in release.kvs: + pair = client.get("app1", kv.key) + print(pair) + + def get_key_with_labels(): """Get a key with labels specified.""" # @@ -42,7 +57,7 @@ def get_key_with_labels(): def main(): - get_key() + get_all_keys() if __name__ == "__main__": diff --git a/readme.md b/readme.md index 27961cd..1a48fa5 100644 --- a/readme.md +++ b/readme.md @@ -58,6 +58,19 @@ with BscpClient(server_addrs, token, biz_id) as client: ### 开发指南 +安装环境 + +```bash +# 安装版本, 修改{version}为版本号, 如3.18, 如果已经有版本,步骤忽略 +uv python install {version} + +# 创建环境, 修改{path}为python真实路径 +uv venv -p {path}/python + +# 安装依赖 +uv sync --frozen +``` + 执行单元测试: ```bash diff --git a/readme_en.md b/readme_en.md index 4f5f29f..f90ec96 100644 --- a/readme_en.md +++ b/readme_en.md @@ -58,6 +58,20 @@ For more sample code, please refer to the examples/ directory. ### Development Guide +Installation environment + +```bash +# Install version, modify {version} to real version, such as 3.18. If there is already a version, ignore this step +uv python install {version} + +# Create environment, modify {path} to the real path of python + +uv venv -p {path}/python + +# Install dependencies +uv sync --frozen +``` + Execute unit tests: ```bash diff --git a/uv.lock b/uv.lock index c621e7c..d9539f1 100644 --- a/uv.lock +++ b/uv.lock @@ -3,7 +3,7 @@ requires-python = ">=3.8" [[package]] name = "bk-bscp" -version = "0.2.0" +version = "0.2.2" source = { editable = "." } dependencies = [ { name = "grpcio" },