Skip to content

Commit

Permalink
fix: silently ignore missing configuration file
Browse files Browse the repository at this point in the history
While attempting to read configuration properties from
the config file specified via ${IBM_CREDENTIALS_FILE}, the
read_external_sources() function should silently ignore
an error if the file doesn't exist, and then proceed
to the next step of the config algorithm.
This was not working correctly, but this commit fixes that.
  • Loading branch information
padamstx committed Feb 1, 2021
1 parent d6238b1 commit d438ade
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 17 deletions.
10 changes: 5 additions & 5 deletions Authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export EXAMPLE_SERVICE_PASSWORD=mypassword
```
Application code:
```python
from ibm_cloud_sdk_core.authenticators import get_authenticator_from_environment
from ibm_cloud_sdk_core import get_authenticator_from_environment

authenticator = get_authenticator_from_environment('example_service')
service = ExampleService(authenticator=authenticator)
Expand Down Expand Up @@ -80,7 +80,7 @@ export EXAMPLE_SERVICE_BEARER_TOKEN=<the bearer token value>
```
Application code:
```python
from ibm_cloud_sdk_core.authenticators import get_authenticator_from_environment
from ibm_cloud_sdk_core import get_authenticator_from_environment

authenticator = get_authenticator_from_environment('example_service')
service = ExampleService(authenticator=authenticator)
Expand Down Expand Up @@ -133,7 +133,7 @@ export EXAMPLE_SERVICE_APIKEY=myapikey
```
Application code:
```python
from ibm_cloud_sdk_core.authenticators import get_authenticator_from_environment
from ibm_cloud_sdk_core import get_authenticator_from_environment

authenticator = get_authenticator_from_environment('example_service')
service = ExampleService(authenticator=authenticator)
Expand Down Expand Up @@ -179,7 +179,7 @@ export EXAMPLE_SERVICE_URL=https://mycp4dhost.com/
```
Application code:
```python
from ibm_cloud_sdk_core.authenticators import get_authenticator_from_environment
from ibm_cloud_sdk_core import get_authenticator_from_environment

authenticator = get_authenticator_from_environment('example_service')
service = ExampleService(authenticator=authenticator)
Expand All @@ -203,7 +203,7 @@ export EXAMPLE_SERVICE_AUTH_TYPE=noauth
```
Application code:
```python
from ibm_cloud_sdk_core.authenticators import get_authenticator_from_environment
from ibm_cloud_sdk_core import get_authenticator_from_environment

authenticator = get_authenticator_from_environment('example_service')
service = ExampleService(authenticator=authenticator)
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

setup: deps dev_deps install_project

all: setup test-unit lint

deps:
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
Expand Down
29 changes: 17 additions & 12 deletions ibm_cloud_sdk_core/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# coding: utf-8

# Copyright 2019 IBM All Rights Reserved.
# Copyright 2019, 2021 IBM All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -234,31 +234,36 @@ def __read_from_credential_file(service_name: str,
"""
default_credentials_file_name = 'ibm-credentials.env'

# File path specified by an env variable
# 1. ${IBM_CREDENTIALS_FILE}
credential_file_path = getenv('IBM_CREDENTIALS_FILE')

# Current working directory
# 2. <current-working-directory>/ibm-credentials.env
if credential_file_path is None:
file_path = join(getcwd(), default_credentials_file_name)
if isfile(file_path):
credential_file_path = file_path

# Home directory
# 3. <user-home-directory>/ibm-credentials.env
if credential_file_path is None:
file_path = join(expanduser('~'), default_credentials_file_name)
if isfile(file_path):
credential_file_path = file_path

config = {}
if credential_file_path is not None:
with open(credential_file_path, 'r') as fobj:
for line in fobj:
key_val = line.strip().split(separator, 1)
if len(key_val) == 2:
key = key_val[0]
value = key_val[1]
_parse_key_and_update_config(config, service_name, key,
value)
try:
with open(credential_file_path, 'r') as fobj:
for line in fobj:
key_val = line.strip().split(separator, 1)
if len(key_val) == 2:
key = key_val[0]
value = key_val[1]
_parse_key_and_update_config(config, service_name, key,
value)
except OSError:
# just absorb the exception and make sure we return an empty response
config = {}

return config


Expand Down
42 changes: 42 additions & 0 deletions test/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
# pylint: disable=missing-docstring
# coding: utf-8

# Copyright 2019, 2021 IBM All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import datetime

from typing import Optional
from ibm_cloud_sdk_core import string_to_datetime, datetime_to_string, get_authenticator_from_environment
from ibm_cloud_sdk_core import string_to_date, date_to_string
from ibm_cloud_sdk_core import convert_model, convert_list
from ibm_cloud_sdk_core import read_external_sources
from ibm_cloud_sdk_core.authenticators import BasicAuthenticator, IAMAuthenticator


Expand Down Expand Up @@ -375,3 +392,28 @@ def test_multi_word_service_name():
assert authenticator is not None
assert authenticator.token_manager.apikey == '5678efgh'
del os.environ['PERSONALITY_INSIGHTS_APIKEY']


def test_read_external_sources_1():
# Set IBM_CREDENTIALS_FILE to a non-existent file (should be silently ignored).
bad_file_path = os.path.join(os.path.dirname(__file__), 'NOT_A_FILE')
os.environ['IBM_CREDENTIALS_FILE'] = bad_file_path

# This env var should take precendence since the config file wasn't found.
os.environ['SERVICE_1_URL'] = 'https://good-url.com'

config = read_external_sources('service_1')
assert config.get('URL') == 'https://good-url.com'


def test_read_external_sources_2():
# The config file should take precedence over the env variable.
config_file = os.path.join(os.path.dirname(__file__),
'../resources/ibm-credentials.env')
os.environ['IBM_CREDENTIALS_FILE'] = config_file

# This should be ignored since IBM_CREDENTIALS_FILE points to a valid file.
os.environ['SERVICE_1_URL'] = 'wrong-url'

config = read_external_sources('service_1')
assert config.get('URL') == 'service1.com/api'

0 comments on commit d438ade

Please sign in to comment.