Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Add [CONTRIBUTING.md] and [SECURITY.md] [#92]
* This project is now following the [Best Practices] set forth by the
Core Infrastructure Initiative! See [CII badge details]. [#92]
* Add `construct_from_cf_env` method to construct client instances from
Data Attribute Recommendation service binding on SAP Business Technology
Platform. [#97]

[CONTRIBUTING.md]: /CONTRIBUTING.md
[SECURITY.md]: /SECURITY.md
[Best Practices]: https://www.coreinfrastructure.org/programs/best-practices-program/
[CII badge details]: https://bestpractices.coreinfrastructure.org/en/projects/4514

[#92]: https://github.com/SAP/data-attribute-recommendation-python-sdk/pull/92
[#97]: https://github.com/SAP/data-attribute-recommendation-python-sdk/pull/92

### Changed

Expand Down
5 changes: 3 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
requests==2.23.0
typing-extensions==3.7.4.1
cfenv==0.5.3
requests==2.25.1
typing-extensions==3.10.0.0
19 changes: 19 additions & 0 deletions sap/aibus/dar/client/base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"""
from typing import TypeVar, Type

from cfenv import AppEnv

from sap.aibus.dar.client.util.credentials import (
CredentialsSource,
OnlineCredentialsSource,
Expand Down Expand Up @@ -87,6 +89,23 @@ def construct_from_jwt(cls: Type[DARClient], dar_url: str, token: str) -> DARCli
source = StaticCredentialsSource(token)
return cls(dar_url, source)

@classmethod
def construct_from_cf_env(cls: Type[DARClient]) -> DARClient:
"""
Constructs a DARClient from service binding in a CloudFoundry app.

This is useful when the SDK is used in a CloudFoundry application on the
SAP Business Technology Platform where the application is bound to an instance
of the Data Attribute Recommendation service.

This constructor assumes that only one instance of the service is bound
to the app.
:return: the client instance
"""
env = AppEnv()
dar = env.get_service(label="data-attribute-recommendation")
return cls.construct_from_service_key(dar.credentials)


class BaseClientWithSession(BaseClient):
"""
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def get_long_version():
author="Michael Haas",
author_email="michael.haas01@sap.com",
url="https://github.com/sap/data-attribute-recommendation-python-sdk",
install_requires=["requests>=2.20.0", "typing-extensions>=3.7.4.1"],
install_requires=["requests~=2.20.0", "typing-extensions~=3.7.4.1", "cfenv~=0.5.3"],
packages=find_packages(exclude=["tests"]),
include_package_data=True,
python_requires="~=3.5",
Expand Down
46 changes: 46 additions & 0 deletions tests/sap/aibus/dar/client/test_data_manager_client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from io import BytesIO, StringIO
import json
from typing import Any
from unittest.mock import create_autospec, call, Mock, MagicMock

Expand Down Expand Up @@ -122,6 +123,51 @@ def test_create_from_jwt_enforces_https(self):
# RFC 4266 URLs should also be rejected
self.clazz.construct_from_jwt("gopher://host:70/1", jwt)

def test_create_from_cf_env(self, monkeypatch):
vcap_services = {
"data-attribute-recommendation-staging": [
{
"binding_guid": "XXXX",
"binding_name": None,
"credentials": {
"swagger": {
"dm": self.dar_url + "data-manager/doc/ui",
"inference": self.dar_url + "inference/doc/ui",
"mm": self.dar_url + "model-manager/doc/ui",
},
"uaa": {
"clientid": self.clientid,
"clientsecret": self.clientsecret,
"identityzone": "dar-saas-test-app",
"identityzoneid": "XXX",
"subaccountid": "XXX",
"tenantid": "XXX",
"tenantmode": "dedicated",
"uaadomain": "authentication.sap.hana.ondemand.com",
"url": self.uaa_url,
"verificationkey": "XXX",
"xsappname": "XXX",
"zoneid": "XXXX",
},
"url": self.dar_url,
},
"instance_guid": "XXX",
"instance_name": "dar-instance-3",
"label": "data-attribute-recommendation",
"name": "dar-instance-3",
"plan": "standard",
"provider": None,
"syslog_drain_url": None,
"tags": [],
"volume_mounts": [],
}
]
}

monkeypatch.setenv("VCAP_SERVICES", json.dumps(vcap_services))
client = self.clazz.construct_from_cf_env()
self._assert_fields_initialized(client)

def _assert_fields_initialized(self, client):
assert isinstance(client.credentials_source, OnlineCredentialsSource)
assert client.credentials_source.clientid == self.clientid
Expand Down