Skip to content

Commit f3e049e

Browse files
committed
feat(credentials): Initiate service based on credential file
1 parent a25669e commit f3e049e

File tree

3 files changed

+73
-1
lines changed

3 files changed

+73
-1
lines changed

test/unit/test_watson_service.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,9 @@ def test_has_bad_first_or_last_char():
217217
with pytest.raises(ValueError) as err:
218218
AnyServiceV1('2018-11-20', iam_apikey='apikey', url='"url"')
219219
assert str(err.value) == 'The URL shouldn\'t start or end with curly brackets or quotes. Be sure to remove any {} and \" characters surrounding your URL'
220+
221+
@responses.activate
222+
def test__set_credential_based_on_type():
223+
service = AnyServiceV1('2018-11-20', username='username', password='password')
224+
service._set_credential_based_on_type('test', 'test_apikey', 'xxx')
225+
assert service.iam_apikey == 'xxx'

watson_developer_cloud/iam_token_manager.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ def set_iam_apikey(self, iam_apikey):
111111
"""
112112
self.iam_apikey = iam_apikey
113113

114+
def set_iam_url(self, iam_url):
115+
"""
116+
Set the IAM url
117+
"""
118+
self.iam_url = iam_url
119+
114120
def _is_token_expired(self):
115121
"""
116122
Check if currently stored token is expired.

watson_developer_cloud/watson_service.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import json as json_import
1616
import platform
1717
import os
18+
from os.path import dirname, isfile, join, expanduser, abspath
1819
import requests
1920
import sys
2021
from requests.structures import CaseInsensitiveDict
@@ -33,7 +34,13 @@
3334
AUTH_HEADER_DEPRECATION_MESSAGE = 'Authenticating with the X-Watson-Authorization-Token header is deprecated. The token continues to work with Cloud Foundry services, but is not supported for services that use Identity and Access Management (IAM) authentication.'
3435
ICP_PREFIX = 'icp-'
3536
APIKEY = 'apikey'
37+
URL = 'url'
38+
USERNAME = 'username'
39+
PASSWORD = 'password'
40+
IAM_APIKEY = 'iam_apikey'
41+
IAM_URL = 'iam_url'
3642
APIKEY_DEPRECATION_MESSAGE = 'Authenticating with apikey is deprecated. Move to using Identity and Access Management (IAM) authentication.'
43+
DEFAULT_CREDENTIALS_FILE_NAME = 'ibm-credentials.env'
3744

3845
# Uncomment this to enable http debugging
3946
# try:
@@ -53,7 +60,6 @@ def load_from_vcap_services(service_name):
5360
else:
5461
return None
5562

56-
5763
class WatsonException(Exception):
5864
"""
5965
Custom exception class for Watson Services.
@@ -259,6 +265,8 @@ def __init__(self, vcap_services_name, url, username=None, password=None,
259265
elif iam_access_token is not None or iam_apikey is not None:
260266
self.set_token_manager(iam_apikey, iam_access_token, iam_url)
261267

268+
self.load_from_credential_file(vcap_services_name)
269+
262270
if use_vcap_services and not self.username and not self.api_key:
263271
self.vcap_service_credentials = load_from_vcap_services(
264272
vcap_services_name)
@@ -282,6 +290,50 @@ def __init__(self, vcap_services_name, url, username=None, password=None,
282290
'You must specify your IAM api key or username and password service '
283291
'credentials (Note: these are different from your Bluemix id)')
284292

293+
def load_from_credential_file(self, service_name, separator='='):
294+
"""
295+
Initiates the credentials based on the credential file
296+
297+
:param str service_name: The service name
298+
:param str separator: the separator for key value pair
299+
"""
300+
# File path specified by an env variable
301+
credential_file_path = os.getenv("IBM_CREDENTIALS_FILE")
302+
303+
# Home directory
304+
if credential_file_path is None:
305+
file_path = join(expanduser('~'), DEFAULT_CREDENTIALS_FILE_NAME)
306+
if isfile(file_path):
307+
credential_file_path = file_path
308+
309+
# Top-level of the project directory
310+
if credential_file_path is None:
311+
file_path = join(dirname(dirname(abspath(__file__))), DEFAULT_CREDENTIALS_FILE_NAME)
312+
if isfile(file_path):
313+
credential_file_path = file_path
314+
315+
if credential_file_path is not None:
316+
with open(credential_file_path, 'rb') as fp:
317+
for line in fp:
318+
key_val = line.strip().split(separator)
319+
self._set_credential_based_on_type(service_name, key_val[0].lower(), key_val[1].lower())
320+
321+
322+
def _set_credential_based_on_type(self, service_name, key, value):
323+
if service_name in key:
324+
if APIKEY in key:
325+
self.set_iam_apikey(value)
326+
elif URL in key:
327+
self.set_url(value)
328+
elif USERNAME in key:
329+
self.username = value
330+
elif PASSWORD in key:
331+
self.password = value
332+
elif IAM_APIKEY in key:
333+
self.set_iam_apikey(value)
334+
elif IAM_URL in key:
335+
self.set_iam_url(value)
336+
285337
def set_username_and_password(self, username=None, password=None):
286338
if username == 'YOUR SERVICE USERNAME':
287339
username = None
@@ -335,6 +387,14 @@ def set_iam_access_token(self, iam_access_token):
335387
self.iam_access_token = iam_access_token
336388
self.jar = CookieJar()
337389

390+
def set_iam_url(self, iam_url):
391+
if self.token_manager:
392+
self.token_manager.set_iam_url(iam_url)
393+
else:
394+
self.token_manager = IAMTokenManager(iam_url=iam_url)
395+
self.iam_url = iam_url
396+
self.jar = CookieJar()
397+
338398
def set_iam_apikey(self, iam_apikey):
339399
if _has_bad_first_or_last_char(iam_apikey):
340400
raise ValueError('The credentials shouldn\'t start or end with curly brackets or quotes. '

0 commit comments

Comments
 (0)