-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #62 from netboxlabs/OBS-411-diode-sdk-python
- Loading branch information
Showing
35 changed files
with
1,100 additions
and
150 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.PHONY: gen-diode-sdk-go gen-diode-sdk-python | ||
|
||
gen-diode-sdk-go: | ||
@cd diode-proto/ && buf format -w && buf generate --template buf.gen.go.yaml | ||
|
||
gen-diode-sdk-python: | ||
@cd diode-proto/ && buf format -w && buf generate --template buf.gen.py.yaml --include-imports | ||
@find diode-sdk-python/netboxlabs/diode/sdk \( -name '*.py' -o -name '*.pyi' \) \ | ||
-exec sed -i '' 's/^from diode.v1/from netboxlabs.diode.sdk.diode.v1/; s/^from validate/from netboxlabs.diode.sdk.validate/' {} \; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
version: v1 | ||
plugins: | ||
- plugin: buf.build/protocolbuffers/python:v26.1 | ||
out: ../diode-sdk-python/netboxlabs/diode/sdk/ | ||
- plugin: buf.build/protocolbuffers/pyi:v26.1 | ||
out: ../diode-sdk-python/netboxlabs/diode/sdk/ | ||
- plugin: buf.build/grpc/python:v1.62.1 | ||
out: ../diode-sdk-python/netboxlabs/diode/sdk/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#!/usr/bin/env python | ||
# Copyright 2024 NetBox Labs Inc | ||
"""NetBox Labs, Diode - SDK - Client.""" | ||
|
||
import logging | ||
import os | ||
import uuid | ||
from typing import Iterable, Optional | ||
|
||
import grpc | ||
|
||
from netboxlabs.diode.sdk.diode.v1 import distributor_pb2, distributor_pb2_grpc | ||
from netboxlabs.diode.sdk.exceptions import DiodeClientError, DiodeConfigError | ||
|
||
_DIODE_API_KEY_ENVVAR_NAME = "DIODE_API_KEY" | ||
_DIODE_SDK_LOG_LEVEL_ENVVAR_NAME = "DIODE_SDK_LOG_LEVEL" | ||
_DEFAULT_STREAM = "latest" | ||
_LOGGER = logging.getLogger(__name__) | ||
|
||
|
||
class DiodeClient: | ||
"""Diode Client.""" | ||
|
||
_name = "diode-sdk-python" | ||
_version = "0.0.1" | ||
_app_name = None | ||
_app_version = None | ||
_channel = None | ||
_stub = None | ||
|
||
def __init__( | ||
self, | ||
target: str, | ||
app_name: str, | ||
app_version: str, | ||
api_key: Optional[str] = None, | ||
): | ||
"""Initiate a new client.""" | ||
log_level = os.getenv(_DIODE_SDK_LOG_LEVEL_ENVVAR_NAME, "INFO").upper() | ||
logging.basicConfig(level=log_level) | ||
|
||
# TODO: validate target | ||
self._target = target | ||
|
||
self._app_name = app_name | ||
self._app_version = app_version | ||
|
||
if api_key is None: | ||
api_key = os.getenv(_DIODE_API_KEY_ENVVAR_NAME) | ||
if api_key is None: | ||
raise DiodeConfigError("API key is required") | ||
|
||
self._auth_metadata = (("diode-api-key", api_key),) | ||
# TODO: add support for secure channel (TLS verify flag and cert) | ||
self._channel = grpc.insecure_channel(target) | ||
self._stub = distributor_pb2_grpc.DistributorServiceStub(self._channel) | ||
# TODO: obtain meta data about the environment; Python version, CPU arch, OS | ||
|
||
@property | ||
def name(self) -> str: | ||
"""Retrieve the name.""" | ||
return self._name | ||
|
||
@property | ||
def version(self) -> str: | ||
"""Retrieve the version.""" | ||
return self._version | ||
|
||
@property | ||
def target(self) -> str: | ||
"""Retrieve the target.""" | ||
return self._target | ||
|
||
@property | ||
def app_name(self) -> str: | ||
"""Retrieve the app name.""" | ||
return self._app_name | ||
|
||
@property | ||
def app_version(self) -> str: | ||
"""Retrieve the app version.""" | ||
return self._app_version | ||
|
||
@property | ||
def channel(self) -> grpc.Channel: | ||
"""Retrieve the channel.""" | ||
return self._channel | ||
|
||
def __enter__(self): | ||
"""Enters the runtime context related to the channel object.""" | ||
return self | ||
|
||
def __exit__(self, exc_type, exc_value, exc_traceback): | ||
"""Exits the runtime context related to the channel object.""" | ||
self.close() | ||
|
||
def close(self): | ||
"""Close the channel.""" | ||
self._channel.close() | ||
|
||
def ingest( | ||
self, | ||
entities: Iterable[distributor_pb2.IngestEntity], | ||
stream: Optional[str] = _DEFAULT_STREAM, | ||
) -> distributor_pb2.PushResponse: | ||
"""Push a message.""" | ||
try: | ||
request = distributor_pb2.PushRequest( | ||
stream=stream, | ||
id=str(uuid.uuid4()), | ||
data=entities, | ||
sdk_name=self.name, | ||
sdk_version=self.version, | ||
producer_app_name=self.app_name, | ||
producer_app_version=self.app_version, | ||
) | ||
|
||
return self._stub.Push(request, metadata=self._auth_metadata) | ||
except grpc.RpcError as err: | ||
raise DiodeClientError(err) from err |
This file was deleted.
Oops, something went wrong.
Empty file.
Empty file.
24 changes: 12 additions & 12 deletions
24
diode-sdk-python/netboxlabs/diode/sdk/diode/v1/device_pb2.py
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
30 changes: 30 additions & 0 deletions
30
diode-sdk-python/netboxlabs/diode/sdk/diode/v1/device_pb2.pyi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from netboxlabs.diode.sdk.diode.v1 import device_type_pb2 as _device_type_pb2 | ||
from netboxlabs.diode.sdk.diode.v1 import platform_pb2 as _platform_pb2 | ||
from netboxlabs.diode.sdk.diode.v1 import role_pb2 as _role_pb2 | ||
from netboxlabs.diode.sdk.diode.v1 import site_pb2 as _site_pb2 | ||
from netboxlabs.diode.sdk.validate import validate_pb2 as _validate_pb2 | ||
from google.protobuf import descriptor as _descriptor | ||
from google.protobuf import message as _message | ||
from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union | ||
|
||
DESCRIPTOR: _descriptor.FileDescriptor | ||
|
||
class Device(_message.Message): | ||
__slots__ = ("name", "device_fqdn", "device_type", "role", "platform", "serial", "site", "vc_position") | ||
NAME_FIELD_NUMBER: _ClassVar[int] | ||
DEVICE_FQDN_FIELD_NUMBER: _ClassVar[int] | ||
DEVICE_TYPE_FIELD_NUMBER: _ClassVar[int] | ||
ROLE_FIELD_NUMBER: _ClassVar[int] | ||
PLATFORM_FIELD_NUMBER: _ClassVar[int] | ||
SERIAL_FIELD_NUMBER: _ClassVar[int] | ||
SITE_FIELD_NUMBER: _ClassVar[int] | ||
VC_POSITION_FIELD_NUMBER: _ClassVar[int] | ||
name: str | ||
device_fqdn: str | ||
device_type: _device_type_pb2.DeviceType | ||
role: _role_pb2.Role | ||
platform: _platform_pb2.Platform | ||
serial: str | ||
site: _site_pb2.Site | ||
vc_position: int | ||
def __init__(self, name: _Optional[str] = ..., device_fqdn: _Optional[str] = ..., device_type: _Optional[_Union[_device_type_pb2.DeviceType, _Mapping]] = ..., role: _Optional[_Union[_role_pb2.Role, _Mapping]] = ..., platform: _Optional[_Union[_platform_pb2.Platform, _Mapping]] = ..., serial: _Optional[str] = ..., site: _Optional[_Union[_site_pb2.Site, _Mapping]] = ..., vc_position: _Optional[int] = ...) -> None: ... |
32 changes: 0 additions & 32 deletions
32
diode-sdk-python/netboxlabs/diode/sdk/diode/v1/device_role_pb2.py
This file was deleted.
Oops, something went wrong.
14 changes: 7 additions & 7 deletions
14
diode-sdk-python/netboxlabs/diode/sdk/diode/v1/device_type_pb2.py
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
17 changes: 17 additions & 0 deletions
17
diode-sdk-python/netboxlabs/diode/sdk/diode/v1/device_type_pb2.pyi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from netboxlabs.diode.sdk.diode.v1 import manufacturer_pb2 as _manufacturer_pb2 | ||
from netboxlabs.diode.sdk.validate import validate_pb2 as _validate_pb2 | ||
from google.protobuf import descriptor as _descriptor | ||
from google.protobuf import message as _message | ||
from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union | ||
|
||
DESCRIPTOR: _descriptor.FileDescriptor | ||
|
||
class DeviceType(_message.Message): | ||
__slots__ = ("manufacturer", "model", "slug") | ||
MANUFACTURER_FIELD_NUMBER: _ClassVar[int] | ||
MODEL_FIELD_NUMBER: _ClassVar[int] | ||
SLUG_FIELD_NUMBER: _ClassVar[int] | ||
manufacturer: _manufacturer_pb2.Manufacturer | ||
model: str | ||
slug: str | ||
def __init__(self, manufacturer: _Optional[_Union[_manufacturer_pb2.Manufacturer, _Mapping]] = ..., model: _Optional[str] = ..., slug: _Optional[str] = ...) -> None: ... |
Oops, something went wrong.