Skip to content

Commit 12d5666

Browse files
author
Petr Reznikov
committed
Support GRPC user-agent in SDK
* Prepend User-Agent set by grpc library with `yandex-cloud-python-sdk/$VERSION` entry. Version is taken from pkg_resources * Allow SDK clients to add their own User-Agent entry, which will be prepended to previous result.
1 parent 35f39f0 commit 12d5666

File tree

4 files changed

+42
-9
lines changed

4 files changed

+42
-9
lines changed

examples/dataproc/main.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,17 @@
2020

2121
import yandexcloud
2222

23+
USER_AGENT = 'ycloud-python-sdk:dataproc.example.main'
24+
2325

2426
def main():
2527
logging.basicConfig(level=logging.INFO)
2628
arguments = parse_cmd()
2729
if arguments.token:
28-
sdk = yandexcloud.SDK(token=arguments.token)
30+
sdk = yandexcloud.SDK(token=arguments.token, user_agent=USER_AGENT)
2931
else:
3032
with open(arguments.sa_json_path) as infile:
31-
sdk = yandexcloud.SDK(service_account_key=json.load(infile))
33+
sdk = yandexcloud.SDK(service_account_key=json.load(infile), user_agent=USER_AGENT)
3234

3335
fill_missing_arguments(sdk, arguments)
3436

examples/dataproc/using_wrapper.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@
88
import yandexcloud
99
from yandexcloud.operations import OperationError
1010

11+
USER_AGENT = 'ycloud-python-sdk:dataproc.example.using_wrapper'
12+
1113

1214
def main():
1315
logging.basicConfig(level=logging.INFO)
1416
arguments = parse_cmd()
1517
if arguments.token:
16-
sdk = yandexcloud.SDK(token=arguments.token)
18+
sdk = yandexcloud.SDK(token=arguments.token, user_agent=USER_AGENT)
1719
else:
1820
with open(arguments.sa_json_path) as infile:
19-
sdk = yandexcloud.SDK(service_account_key=json.load(infile))
21+
sdk = yandexcloud.SDK(service_account_key=json.load(infile), user_agent=USER_AGENT)
2022
fill_missing_arguments(sdk, arguments)
2123

2224
dataproc = sdk.wrappers.Dataproc(

yandexcloud/_channels.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,17 @@
66
from yandexcloud import _auth_plugin
77
from yandexcloud._auth_fabric import get_auth_token_requester
88

9+
import pkg_resources
10+
try:
11+
VERSION = pkg_resources.get_distribution('yandexcloud').version
12+
except pkg_resources.DistributionNotFound:
13+
VERSION = '0.0.0'
14+
15+
SDK_USER_AGENT = 'yandex-cloud-python-sdk/{version}'.format(version=VERSION)
16+
917

1018
class Channels(object):
11-
def __init__(self, **kwargs):
19+
def __init__(self, client_user_agent=None, **kwargs):
1220
self._channel_creds = grpc.ssl_channel_credentials(
1321
root_certificates=kwargs.get('root_certificates'),
1422
private_key=kwargs.get('private_key'),
@@ -20,11 +28,19 @@ def __init__(self, **kwargs):
2028

2129
self._unauthenticated_channel = None
2230
self._channels = None
31+
self._client_user_agent = client_user_agent
32+
33+
def channel_options(self):
34+
return tuple(
35+
('grpc.primary_user_agent', user_agent)
36+
for user_agent in [self._client_user_agent, SDK_USER_AGENT]
37+
if user_agent is not None
38+
)
2339

2440
def channel(self, endpoint):
2541
if not self._channels:
2642
self._unauthenticated_channel = grpc.secure_channel(
27-
self._endpoint, self._channel_creds)
43+
self._endpoint, self._channel_creds, options=self.channel_options())
2844
endpoint_service = ApiEndpointServiceStub(
2945
self._unauthenticated_channel)
3046
resp = endpoint_service.List(ListApiEndpointsRequest())
@@ -37,7 +53,7 @@ def channel(self, endpoint):
3753
self._channel_creds, call_creds)
3854

3955
self._channels = {
40-
ep.id: grpc.secure_channel(ep.address, creds)
56+
ep.id: grpc.secure_channel(ep.address, creds, options=self.channel_options())
4157
for ep in endpoints
4258
}
4359

yandexcloud/_sdk.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,21 @@
1010

1111

1212
class SDK(object):
13-
def __init__(self, interceptor=None, **kwargs):
14-
self._channels = _channels.Channels(**kwargs)
13+
def __init__(self, interceptor=None, user_agent=None, **kwargs):
14+
"""
15+
API entry-point object.
16+
17+
:param interceptor: GRPC interceptor to be used instead of default RetryInterceptor
18+
:type interceptor: Union[
19+
UnaryUnaryClientInterceptor,
20+
UnaryStreamClientInterceptor,
21+
StreamUnaryClientInterceptor,
22+
StreamStreamClientInterceptor
23+
]
24+
:param user_agent: String to prepend User-Agent metadata header for all GRPC requests made via SDK object
25+
:type user_agent: Optional[str]
26+
"""
27+
self._channels = _channels.Channels(client_user_agent=user_agent, **kwargs)
1528
if interceptor is None:
1629
interceptor = RetryInterceptor(
1730
max_retry_count=5,

0 commit comments

Comments
 (0)