summaryrefslogtreecommitdiffstats
path: root/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client
diff options
context:
space:
mode:
authorHansen, Tony (th1395) <th1395@att.com>2021-06-22 21:12:32 +0000
committerHansen, Tony (th1395) <th1395@att.com>2021-07-01 16:42:05 +0000
commit876d17be6b1916c08fb36edcdf924859cb04e3cc (patch)
tree0ca229505a333fa20392a3cec411fa34782ffecf /onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client
parent1002e423a67cc4c22846ffc333b8027230e55dcb (diff)
support local config and policy files
* DCAEGEN2-2733/DCAEGEN2-2753 - onap-dcae-cbs-docker-client support local config and policy files Support $CBS_CLIENT_CONFIG_PATH and $CBS_CLIENT_POLICY_PATH, Default paths are /app-config/application_config.yaml and /etc/policies/policies.json. If files are missing or malformed, drop back to the current behavior. Change-Id: Iba2484f6be7fc54e412f7de302bb79a4d7bfde17 Signed-off-by: Hansen, Tony (th1395) <th1395@att.com> Issue-ID: DCAEGEN2-2733 Issue-ID: DCAEGEN2-2753 Signed-off-by: Hansen, Tony (th1395) <th1395@att.com>
Diffstat (limited to 'onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client')
-rw-r--r--onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/client.py137
-rw-r--r--onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/exceptions.py6
2 files changed, 129 insertions, 14 deletions
diff --git a/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/client.py b/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/client.py
index 7f36169..c42b4ae 100644
--- a/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/client.py
+++ b/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/client.py
@@ -1,5 +1,5 @@
# ================================================================================
-# Copyright (c) 2017-2019 AT&T Intellectual Property. All rights reserved.
+# Copyright (c) 2017-2021 AT&T Intellectual Property. All rights reserved.
# Copyright (C) 2021 Nokia. All rights reserved.
# ================================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,18 +14,36 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ============LICENSE_END=========================================================
-#
-# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+""" provide a means to return a configuration to CBS """
import json
import os
import requests
+import sys
+import yaml
+
from onap_dcae_cbs_docker_client import get_module_logger
from onap_dcae_cbs_docker_client.exceptions import ENVsMissing, CantGetConfig, CBSUnreachable
logger = get_module_logger(__name__)
+DEFAULT_CONFIG_PATH = "/app-config/application_config.yaml"
+DEFAULT_POLICY_PATH = "/etc/policies/policies.json"
+
+
+# provide a means to import the default paths into unit tests
+# For some reason, tox does not like
+# from onap_dcae_cbs_docker_client.client import DEFAULT_CONFIG_PATH, DEFAULT_POLICY_PATH
+
+def default_config_path():
+ return DEFAULT_CONFIG_PATH
+
+
+def default_policy_path():
+ return DEFAULT_POLICY_PATH
+
#########
# HELPERS
@@ -35,7 +53,7 @@ def _recurse(config):
Recurse through a configuration, or recursively a sub element of it.
If it's a dict: recurse over all the values
If it's a list: recurse over all the values
- If it's a string: return the replacement
+ If it's a string: expand the string and return its replacement
If none of the above, just return the item.
"""
if isinstance(config, list):
@@ -96,11 +114,13 @@ def change_envs(value):
"""
Replace env reference by actual value and return it
"""
- if value.startswith('$'):
- try:
- value = os.environ[value.replace('${', '').replace('}', '')]
- except KeyError as e:
- raise ENVsMissing("Required ENV Variable {0} missing".format(e))
+ if value.startswith('${'):
+ name = value[2:-1]
+ if name in os.environ:
+ return os.environ[name]
+
+ logger.error(f"Required ENV Variable '{name}' missing. Is '{value}' properly formatted?")
+ raise ENVsMissing(f"Required ENV Variable {name} missing. Is '{value}' properly formatted?")
return value
@@ -108,18 +128,113 @@ def change_envs(value):
# Public
def get_all():
"""
- Hit the CBS service_component_all endpoint
+ If not configured locally,
+ hit the CBS service_component_all endpoint
+
+ Local configuration comes from $CBS_CLIENT_CONFIG_PATH and $CBS_CLIENT_POLICY_PATH,
+ defaulted to /app-config/application_config.yaml and /etc/policies/policies.json.
"""
+ config_path = os.getenv("CBS_CLIENT_CONFIG_PATH", DEFAULT_CONFIG_PATH)
+ if config_path == "":
+ config_path = DEFAULT_CONFIG_PATH
+ policy_path = os.getenv("CBS_CLIENT_POLICY_PATH", DEFAULT_POLICY_PATH)
+ if policy_path == "":
+ policy_path = DEFAULT_POLICY_PATH
+
+ try:
+ logger.debug(f"opening config_path={config_path}")
+ with open(config_path) as fp:
+ config = yaml.safe_load(fp)
+
+ policies = None
+ try:
+ logger.debug(f"opening policy_path={policy_path}")
+ with open(policy_path) as fp:
+ policies = json.load(fp)
+
+ except FileNotFoundError:
+ logger.debug("Policy File Not Found exception received")
+ pass
+
+ except (json.decoder.JSONDecodeError, ValueError) as e:
+ logger.error(f"The policy file '{policy_path}' has invalid JSON: %s", e)
+ pass
+
+ except Exception as e:
+ logger.error(f"An error occurred processing the policy file '{policy_path}': %s", e)
+ import traceback
+ traceback.print_exc(file=sys.stderr)
+ pass
+
+ if policies is not None:
+ if "policies" in policies:
+ logger.debug(f"Returning config read from {config_path} an policy read from {policy_path}")
+ ret = {"config": _recurse(config), "policies": policies["policies"]}
+ else:
+ logger.error(f"The policy file '{policy_path}' does NOT have a 'policies' block in it.")
+ ret = {"config": _recurse(config)}
+ else:
+ logger.debug(f"Returning config read from {config_path}")
+ ret = {"config": _recurse(config)}
+
+ return ret
+
+ except yaml.scanner.ScannerError as e:
+ logger.error(f"The configuration file '{config_path}' has invalid YAML: {e}")
+ pass
+
+ except FileNotFoundError:
+ logger.debug("Config File Not Found exception received")
+ pass
+
+ except Exception as e:
+ logger.error(f"An error occurred processing the configuration file '{config_path}': {e}")
+ import traceback
+ traceback.print_exc(file=sys.stderr)
+ pass
+
+ logger.debug("Fallback to using REST call")
config = _get_path("service_component_all")
return _recurse(config)
def get_config():
"""
- Hit the CBS service_component endpoint
+ If not configured locally,
+ hit the CBS service_component endpoint for the configuration.
+
+ Local configuration comes from $CBS_CLIENT_CONFIG_PATH,
+ defaulted to /app-config/application_config.yaml.
TODO: should we take in a "retry" boolean, and retry on behalf of the caller?
Currently, we return an exception and let the application decide how it wants to proceed (Crash, try again, etc).
"""
+ config_path = os.getenv("CBS_CLIENT_CONFIG_PATH", DEFAULT_CONFIG_PATH)
+ if config_path == "":
+ config_path = DEFAULT_CONFIG_PATH
+
+ try:
+ logger.debug(f"opening config_path={config_path}")
+ with open(config_path) as fp:
+ config = yaml.safe_load(fp)
+
+ logger.debug(f"Returning config read from {config_path}")
+ return _recurse({"config": config})
+
+ except yaml.scanner.ScannerError as e:
+ logger.error(f"The configuration file '{config_path}' has invalid YAML: {e}")
+ pass
+
+ except FileNotFoundError:
+ logger.debug("Config File Not Found exception received")
+ pass
+
+ except Exception as e:
+ logger.error(f"An error occurred processing the configuration file '{config_path}': {e}")
+ import traceback
+ traceback.print_exc(file=sys.stderr)
+ pass
+
+ logger.debug("Fallback to using REST call")
config = _get_path("service_component")
return _recurse(config)
diff --git a/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/exceptions.py b/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/exceptions.py
index 6b73b91..0cd19fd 100644
--- a/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/exceptions.py
+++ b/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/exceptions.py
@@ -1,5 +1,5 @@
# ================================================================================
-# Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
+# Copyright (c) 2019-2021 AT&T Intellectual Property. 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.
@@ -13,8 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ============LICENSE_END=========================================================
-#
-# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+
+""" exceptions used by the Config Binding Server """
class ENVsMissing(Exception):