Skip to content

Commit

Permalink
feat(credentials): Initiate service based on credential file
Browse files Browse the repository at this point in the history
  • Loading branch information
ehdsouza committed Jan 30, 2019
1 parent a25669e commit f3e049e
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 1 deletion.
6 changes: 6 additions & 0 deletions test/unit/test_watson_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,9 @@ def test_has_bad_first_or_last_char():
with pytest.raises(ValueError) as err:
AnyServiceV1('2018-11-20', iam_apikey='apikey', url='"url"')
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'

@responses.activate
def test__set_credential_based_on_type():
service = AnyServiceV1('2018-11-20', username='username', password='password')
service._set_credential_based_on_type('test', 'test_apikey', 'xxx')
assert service.iam_apikey == 'xxx'
6 changes: 6 additions & 0 deletions watson_developer_cloud/iam_token_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ def set_iam_apikey(self, iam_apikey):
"""
self.iam_apikey = iam_apikey

def set_iam_url(self, iam_url):
"""
Set the IAM url
"""
self.iam_url = iam_url

def _is_token_expired(self):
"""
Check if currently stored token is expired.
Expand Down
62 changes: 61 additions & 1 deletion watson_developer_cloud/watson_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import json as json_import
import platform
import os
from os.path import dirname, isfile, join, expanduser, abspath
import requests
import sys
from requests.structures import CaseInsensitiveDict
Expand All @@ -33,7 +34,13 @@
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.'
ICP_PREFIX = 'icp-'
APIKEY = 'apikey'
URL = 'url'
USERNAME = 'username'
PASSWORD = 'password'
IAM_APIKEY = 'iam_apikey'
IAM_URL = 'iam_url'
APIKEY_DEPRECATION_MESSAGE = 'Authenticating with apikey is deprecated. Move to using Identity and Access Management (IAM) authentication.'
DEFAULT_CREDENTIALS_FILE_NAME = 'ibm-credentials.env'

# Uncomment this to enable http debugging
# try:
Expand All @@ -53,7 +60,6 @@ def load_from_vcap_services(service_name):
else:
return None


class WatsonException(Exception):
"""
Custom exception class for Watson Services.
Expand Down Expand Up @@ -259,6 +265,8 @@ def __init__(self, vcap_services_name, url, username=None, password=None,
elif iam_access_token is not None or iam_apikey is not None:
self.set_token_manager(iam_apikey, iam_access_token, iam_url)

self.load_from_credential_file(vcap_services_name)

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

def load_from_credential_file(self, service_name, separator='='):
"""
Initiates the credentials based on the credential file
:param str service_name: The service name
:param str separator: the separator for key value pair
"""
# File path specified by an env variable
credential_file_path = os.getenv("IBM_CREDENTIALS_FILE")

# Home directory
if credential_file_path is None:
file_path = join(expanduser('~'), DEFAULT_CREDENTIALS_FILE_NAME)
if isfile(file_path):
credential_file_path = file_path

# Top-level of the project directory
if credential_file_path is None:
file_path = join(dirname(dirname(abspath(__file__))), DEFAULT_CREDENTIALS_FILE_NAME)
if isfile(file_path):
credential_file_path = file_path

if credential_file_path is not None:
with open(credential_file_path, 'rb') as fp:
for line in fp:
key_val = line.strip().split(separator)
self._set_credential_based_on_type(service_name, key_val[0].lower(), key_val[1].lower())


def _set_credential_based_on_type(self, service_name, key, value):
if service_name in key:
if APIKEY in key:
self.set_iam_apikey(value)
elif URL in key:
self.set_url(value)
elif USERNAME in key:
self.username = value
elif PASSWORD in key:
self.password = value
elif IAM_APIKEY in key:
self.set_iam_apikey(value)
elif IAM_URL in key:
self.set_iam_url(value)

def set_username_and_password(self, username=None, password=None):
if username == 'YOUR SERVICE USERNAME':
username = None
Expand Down Expand Up @@ -335,6 +387,14 @@ def set_iam_access_token(self, iam_access_token):
self.iam_access_token = iam_access_token
self.jar = CookieJar()

def set_iam_url(self, iam_url):
if self.token_manager:
self.token_manager.set_iam_url(iam_url)
else:
self.token_manager = IAMTokenManager(iam_url=iam_url)
self.iam_url = iam_url
self.jar = CookieJar()

def set_iam_apikey(self, iam_apikey):
if _has_bad_first_or_last_char(iam_apikey):
raise ValueError('The credentials shouldn\'t start or end with curly brackets or quotes. '
Expand Down

0 comments on commit f3e049e

Please sign in to comment.