diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/app/config_binding_service/__init__.py | 46 | ||||
-rw-r--r-- | app/app/config_binding_service/client.py | 297 | ||||
-rw-r--r-- | app/app/config_binding_service/controller.py | 108 | ||||
-rw-r--r-- | app/app/config_binding_service/logging.py | 204 | ||||
-rw-r--r-- | app/app/config_binding_service/openapi.yaml | 112 | ||||
-rwxr-xr-x | app/app/main.py | 28 | ||||
-rw-r--r-- | app/app/pom.xml | 270 | ||||
-rw-r--r-- | app/app/setup.py | 34 | ||||
-rw-r--r-- | app/app/tests/__init__.py | 21 | ||||
-rw-r--r-- | app/app/tests/conftest.py | 70 | ||||
-rw-r--r-- | app/app/tests/test_api.py | 103 | ||||
-rw-r--r-- | app/app/tests/test_client.py | 206 | ||||
-rw-r--r-- | app/app/tox.ini | 26 | ||||
-rw-r--r-- | app/pom.xml | 80 | ||||
-rw-r--r-- | app/uwsgi.ini | 3 |
15 files changed, 0 insertions, 1608 deletions
diff --git a/app/app/config_binding_service/__init__.py b/app/app/config_binding_service/__init__.py deleted file mode 100644 index 306a762..0000000 --- a/app/app/config_binding_service/__init__.py +++ /dev/null @@ -1,46 +0,0 @@ -# ============LICENSE_START======================================================= -# Copyright (c) 2017-2019 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. -# 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. -# ============LICENSE_END========================================================= -# -# ECOMP is a trademark and service mark of AT&T Intellectual Property. - -import os -import connexion - - -class BadEnviornmentENVNotFound(Exception): - """ - Specific exception to be raised when a required ENV varaible is missing - """ - pass - - -def get_consul_uri(): - """ - This method waterfalls reads an envioronmental variable called CONSUL_HOST - If that doesn't work, it raises an Exception - """ - if "CONSUL_HOST" in os.environ: - # WARNING! TODO! Currently the env file does not include the port. - # But some other people think that the port should be a part of that. - # For now, I'm hardcoding 8500 until this gets resolved. - return "http://{0}:{1}".format(os.environ["CONSUL_HOST"], 8500) - else: - raise BadEnviornmentENVNotFound("CONSUL_HOST") - - -# this has to be here due to circular dependency -app = connexion.App(__name__, specification_dir='.') -app.add_api('openapi.yaml', arguments={'title': 'Config Binding Service'}) diff --git a/app/app/config_binding_service/client.py b/app/app/config_binding_service/client.py deleted file mode 100644 index c6a6753..0000000 --- a/app/app/config_binding_service/client.py +++ /dev/null @@ -1,297 +0,0 @@ -# ============LICENSE_START======================================================= -# Copyright (c) 2017-2018 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. -# 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. -# ============LICENSE_END========================================================= -# -# ECOMP is a trademark and service mark of AT&T Intellectual Property. - -import re -from functools import partial, reduce -import base64 -import copy -import json -import requests -import six -from config_binding_service import get_consul_uri -from config_binding_service.logging import utc, metrics - - -CONSUL = get_consul_uri() - -template_match_rels = re.compile("\{{2}([^\}\{]*)\}{2}") -template_match_dmaap = re.compile("<{2}([^><]*)>{2}") - -### -# Cusom Exception -### - - -class CantGetConfig(Exception): - """ - Represents an exception where a required key in consul isn't there - """ - - def __init__(self, code, response): - self.code = code - self.response = response - - -class BadRequest(Exception): - """ - Exception to be raised when the user tried to do something they shouldn't - """ - - def __init__(self, response): - self.code = 400 - self.response = response - - -### -# Private Functions -### - - -def _consul_get_all_as_transaction(service_component_name, raw_request, xer): - """ - Use Consul's transaction API to get all keys of the form service_component_name:* - Return a dict with all the values decoded - """ - payload = [ - { - "KV": { - "Verb": "get-tree", - "Key": service_component_name, - } - }] - - bts = utc() - response = requests.put("{0}/v1/txn".format(CONSUL), json=payload) - metrics(raw_request, bts, xer, "Consul", "/v1/txn".format(service_component_name), response.status_code, __name__, msg="Retrieving Consul transaction for all keys for {0}".format(service_component_name)) - - try: - response.raise_for_status() - except requests.exceptions.HTTPError as exc: - raise CantGetConfig(exc.response.status_code, exc.response.text) - - result = json.loads(response.text)['Results'] - - new_res = {} - for res in result: - key = res["KV"]["Key"] - val = base64.b64decode(res["KV"]["Value"]).decode("utf-8") - try: - new_res[key] = json.loads(val) - except json.decoder.JSONDecodeError: - new_res[key] = "INVALID JSON" # TODO, should we just include the original value somehow? - - if service_component_name not in new_res: - raise CantGetConfig(404, "") - - return new_res - - -def _get_config_rels_dmaap(service_component_name, raw_request, xer): - allk = _consul_get_all_as_transaction(service_component_name, raw_request, xer) - config = allk[service_component_name] - rels = allk.get(service_component_name + ":rels", []) - dmaap = allk.get(service_component_name + ":dmaap", {}) - return config, rels, dmaap - - -def _get_connection_info_from_consul(service_component_name): - """ - Call consul's catalog - TODO: currently assumes there is only one service - - DEPRECATION NOTE: - This function existed when DCAE was using Consul to resolve service component's connection information. - This relied on a "rels" key and a Cloudify relationship plugin to set up the magic. - The consensous is that this feature is no longer used. - This functionality is very likely deprecated by Kubernetes service discovery mechanism, and DMaaP. - - This function also includes logic related to CDAP, which is also likely deprecated. - - This code shall remain here for now but is at risk of being deleted in a future release. - """ - # Note: there should be a metrics log here, but see the deprecation note above; this function is due to be deleted. - res = requests.get("{0}/v1/catalog/service/{1}".format(CONSUL, service_component_name)) - res.raise_for_status() - services = res.json() - if services == []: - return None # later will get filtered out - ip_addr = services[0]["ServiceAddress"] - port = services[0]["ServicePort"] - - if "cdap_app" in service_component_name: - redirectish_url = "http://{0}:{1}/application/{2}".format(ip_addr, port, service_component_name) - res = requests.get(redirectish_url) - res.raise_for_status() - details = res.json() - # Pick out the details to expose to the component developers. These keys come from the broker API - return {key: details[key] for key in ["connectionurl", "serviceendpoints"]} - return "{0}:{1}".format(ip_addr, port) - - -def _replace_rels_template(rels, template_identifier): - """ - The magic. Replaces a template identifier {{...}} with the entrie(s) from the rels keys - NOTE: There was a discussion over whether the CBS should treat {{}} as invalid. Mike asked that - it resolve to the empty list. So, it does resolve it to empty list. - """ - returnl = [] - for rel in rels: - if template_identifier in rel and template_identifier != "": - returnl.append(rel) - # returnl now contains a list of DNS names (possible empty), now resolve them (or not if they are not regustered) - return list(filter(lambda x: x is not None, map(_get_connection_info_from_consul, returnl))) - - -def _replace_dmaap_template(dmaap, template_identifier): - """ - This one liner could have been just put inline in the caller but maybe this will get more complex in future - Talked to Mike, default value if key is not found in dmaap key should be {} - """ - return {} if (template_identifier not in dmaap or template_identifier == "<<>>") else dmaap[template_identifier] - - -def _replace_value(v, rels, dmaap): - """ - Takes a value v that was some value in the templatized configuration, determines whether it needs replacement (either {{}} or <<>>), and if so, replaces it. - Otherwise just returns v - - implementation notes: - - the split below sees if we have v = x,y,z... so we can support {{x,y,z,....}} - - the lambda is because we can't fold operators in Python, wanted fold(+, L) where + when applied to lists in python is list concatenation - """ - if isinstance(v, six.string_types): # do not try to replace anything that is not a string - match_on_rels = re.match(template_match_rels, v) - if match_on_rels: - # now holds just x,.. of {{x,...}} - template_identifier = match_on_rels.groups()[0].strip() - rtpartial = partial(_replace_rels_template, rels) - return reduce(lambda a, b: a + b, map(rtpartial, template_identifier.split(",")), []) - match_on_dmaap = re.match(template_match_dmaap, v) - if match_on_dmaap: - template_identifier = match_on_dmaap.groups()[0].strip() - """ - Here is what Mike said: - 1) want simple replacement of "<< >>" with dmaap key value - 2) never need to support <<f1,f2>> whereas we do support {{sct1,sct2}} - The consequence is that if you give the CBS a dmaap key like {"foo" : {...}} you are going to get back {...}, but rels always returns [...]. - So now component developers have to possible handle dicts and [], and we have to communicate that to them - """ - return _replace_dmaap_template(dmaap, template_identifier) - return v # was not a match or was not a string, return value as is - - -def _recurse(config, rels, dmaap): - """ - Recurse throug a configuration, or recursively a sub elemebt 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 none of the above, just return the item. - """ - if isinstance(config, list): - return [_recurse(item, rels, dmaap) for item in config] - if isinstance(config, dict): - for key in config: - config[key] = _recurse(config[key], rels, dmaap) - return config - if isinstance(config, six.string_types): - return _replace_value(config, rels, dmaap) - # not a dict, not a list, not a string, nothing to do. - return config - - -######### -# PUBLIC API -######### - - -def resolve(service_component_name, raw_request, xer): - """ - Return the bound config of service_component_name - - raw_request and xer are needed to form the correct metrics log - """ - config, rels, dmaap = _get_config_rels_dmaap(service_component_name, raw_request, xer) - return _recurse(config, rels, dmaap) - - -def resolve_override(config, rels=[], dmaap={}): - """ - Explicitly take in a config, rels, dmaap and try to resolve it. - Useful for testing where you dont want to put the test values in consul - """ - # use deepcopy to make sure that config is not touched - return _recurse(copy.deepcopy(config), rels, dmaap) - - -def resolve_all(service_component_name, raw_request, xer): - """ - Return config, policies, and any other k such that service_component_name:k exists (other than :dmaap and :rels) - - raw_request and xer are needed to form the correct metrics log - """ - allk = _consul_get_all_as_transaction(service_component_name, raw_request, xer) - returnk = {} - - # replace the config with the resolved config - returnk["config"] = resolve_override(allk[service_component_name], - allk.get("{0}:rels".format(service_component_name), []), - allk.get("{0}:dmaap".format(service_component_name), {})) - - # concatenate the items - for k in allk: - if "policies" in k: - if "policies" not in returnk: - returnk["policies"] = {} - returnk["policies"]["event"] = {} - returnk["policies"]["items"] = [] - - if k.endswith(":policies/event"): - returnk["policies"]["event"] = allk[k] - elif ":policies/items" in k: - returnk["policies"]["items"].append(allk[k]) - else: - if not(k == service_component_name or k.endswith(":rels") or k.endswith(":dmaap")): - # this would blow up if you had a key in consul without a : but this shouldnt happen - suffix = k.split(":")[1] - returnk[suffix] = allk[k] - - return returnk - - -def get_key(key, service_component_name, raw_request, xer): - """ - Try to fetch a key k from Consul of the form service_component_name:k - - raw_request and xer are needed to form the correct metrics log - """ - if key == "policies": - raise BadRequest( - ":policies is a complex folder and should be retrieved using the service_component_all API") - - bts = utc() - path = "v1/kv/{0}:{1}".format(service_component_name, key) - response = requests.get("{0}/{1}".format(CONSUL, path)) - metrics(raw_request, bts, xer, "Consul", path, response.status_code, __name__, msg="Retrieving single Consul key {0} for {1}".format(key, service_component_name)) - - try: - response.raise_for_status() - except requests.exceptions.HTTPError as exc: - raise CantGetConfig(exc.response.status_code, exc.response.text) - rest = json.loads(response.text)[0] - return json.loads(base64.b64decode(rest["Value"]).decode("utf-8")) diff --git a/app/app/config_binding_service/controller.py b/app/app/config_binding_service/controller.py deleted file mode 100644 index c2eb21c..0000000 --- a/app/app/config_binding_service/controller.py +++ /dev/null @@ -1,108 +0,0 @@ -# ============LICENSE_START======================================================= -# Copyright (c) 2017-2018 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. -# 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. -# ============LICENSE_END========================================================= -# -# ECOMP is a trademark and service mark of AT&T Intellectual Property. - -import json -import requests -import connexion -import uuid -from flask import Response -from config_binding_service import client, get_consul_uri -from config_binding_service.logging import audit, utc, error, metrics - - -def _get_helper(json_expecting_func, **kwargs): - """ - Helper function used by several functions below - """ - try: - payload = json_expecting_func(**kwargs) - response, status_code, mimetype = json.dumps(payload), 200, "application/json" - except client.BadRequest as exc: - response, status_code, mimetype = exc.response, exc.code, "text/plain" - except client.CantGetConfig as exc: - response, status_code, mimetype = exc.response, exc.code, "text/plain" - except Exception: - response, status_code, mimetype = "Unknown error", 500, "text/plain" - return response, status_code, mimetype - - -def _get_or_generate_xer(raw_request): - """get or generate the transaction id""" - xer = raw_request.headers.get("x-onap-requestid", None) - if xer is None: - # some components are still using the old name - xer = raw_request.headers.get("x-ecomp-requestid", None) - if xer is None: - # the user did NOT supply a request id, generate one - xer = str(uuid.uuid4()) - return xer - - -def bind_all(service_component_name): - """ - Get all the keys in Consul for this SCN, and bind the config - """ - xer = _get_or_generate_xer(connexion.request) - bts = utc() - response, status_code, mimetype = _get_helper(client.resolve_all, service_component_name=service_component_name, raw_request=connexion.request, xer=xer) - audit(connexion.request, bts, xer, status_code, __name__, "called for component {0}".format(service_component_name)) - # Even though some older components might be using the ecomp name, we return the proper one - return Response(response=response, status=status_code, mimetype=mimetype, headers={"x-onap-requestid": xer}) - - -def bind_config_for_scn(service_component_name): - """ - Bind just the config for this SCN - """ - xer = _get_or_generate_xer(connexion.request) - bts = utc() - response, status_code, mimetype = _get_helper(client.resolve, service_component_name=service_component_name, raw_request=connexion.request, xer=xer) - audit(connexion.request, bts, xer, status_code, __name__, "called for component {0}".format(service_component_name)) - return Response(response=response, status=status_code, mimetype=mimetype, headers={"x-onap-requestid": xer}) - - -def get_key(key, service_component_name): - """ - Get a single key k of the form service_component_name:k from Consul. - Should not be used and will return a BAD REQUEST for k=policies because it's a complex object - """ - xer = _get_or_generate_xer(connexion.request) - bts = utc() - response, status_code, mimetype = _get_helper(client.get_key, key=key, service_component_name=service_component_name, raw_request=connexion.request, xer=xer) - audit(connexion.request, bts, xer, status_code, __name__, "called for component {0}".format(service_component_name)) - return Response(response=response, status=status_code, mimetype=mimetype, headers={"x-onap-requestid": xer}) - - -def healthcheck(): - """ - CBS Healthcheck - """ - xer = _get_or_generate_xer(connexion.request) - path = "v1/catalog/service/config_binding_service" - bts = utc() - res = requests.get("{0}/{1}".format(get_consul_uri(), path)) - status = res.status_code - if status == 200: - msg = "CBS is alive and Consul connection OK" - else: - msg = "CBS is alive but cannot reach Consul" - # treating this as a WARN because this could be a temporary network glitch. Also per EELF guidelines this is a 200 ecode (availability) - error(connexion.request, xer, "WARN", 200, tgt_entity="Consul", tgt_path="/v1/catalog/service/config_binding_service", msg=msg) - metrics(connexion.request, bts, xer, "Consul", path, res.status_code, __name__, msg="Checking Consul connectivity during CBS healthcheck, {0}".format(msg)) - audit(connexion.request, bts, xer, status, __name__, msg=msg) - return Response(response=msg, status=status) diff --git a/app/app/config_binding_service/logging.py b/app/app/config_binding_service/logging.py deleted file mode 100644 index b6275a7..0000000 --- a/app/app/config_binding_service/logging.py +++ /dev/null @@ -1,204 +0,0 @@ -# ============LICENSE_START======================================================= -# Copyright (c) 2017-2018 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. -# 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. -# ============LICENSE_END========================================================= -# -# ECOMP is a trademark and service mark of AT&T Intellectual Property. - -from logging import getLogger, Formatter -from logging.handlers import RotatingFileHandler -from os import makedirs -import datetime - - -_AUDIT_LOGGER = getLogger("defaultlogger") -_ERROR_LOGGER = getLogger("defaultlogger") -_METRICS_LOGGER = getLogger("defaultlogger") - - -def _create_logger(name, logfile): - """ - Create a RotatingFileHandler and a streamhandler for stdout - https://docs.python.org/3/library/logging.handlers.html - what's with the non-pythonic naming in these stdlib methods? Shameful. - """ - logger = getLogger(name) - file_handler = RotatingFileHandler(logfile, - maxBytes=10000000, backupCount=2) # 10 meg with one backup.. - formatter = Formatter('%(message)s') - file_handler.setFormatter(formatter) - logger.setLevel("DEBUG") - logger.addHandler(file_handler) - return logger - - -def create_loggers(): - """ - Public method to set the global logger, launched from Run - This is *not* launched during unit testing, so unit tests do not create/write log files - """ - makedirs("/opt/logs", exist_ok=True) - - # create the audit log - aud_file = "/opt/logs/audit.log" - open(aud_file, 'a').close() # this is like "touch" - global _AUDIT_LOGGER - _AUDIT_LOGGER = _create_logger("config_binding_service_audit", aud_file) - - # create the error log - err_file = "/opt/logs/error.log" - open(err_file, 'a').close() # this is like "touch" - global _ERROR_LOGGER - _ERROR_LOGGER = _create_logger("config_binding_service_error", err_file) - - # create the metrics log - met_file = "/opt/logs/metrics.log" - open(met_file, 'a').close() # this is like "touch" - global _METRICS_LOGGER - _METRICS_LOGGER = _create_logger("config_binding_service_metrics", met_file) - - -def utc(): - """gets current time in utc""" - return datetime.datetime.utcnow() - - -def audit(raw_request, bts, xer, rcode, calling_mod, msg="n/a"): - """ - write an EELF audit record per https://wiki.onap.org/download/attachments/1015849/ONAP%20application%20logging%20guidelines.pdf?api=v2 - %The audit fields implemented: - - 1 BeginTimestamp Implemented (bts) - 2 EndTimestamp Auto Injected when this is called - 3 RequestID Implemented (xer) - 5 threadId n/a - 7 serviceName Implemented (from Req) - 9 StatusCode Auto injected based on rcode - 10 ResponseCode Implemented (rcode) - 13 Category log level - all audit records are INFO. - 15 Server IP address Implemented (from Req) - 16 ElapsedTime Auto Injected (milliseconds) - 17 Server This is running in a Docker container so this is not applicable, my HOSTNAME is always "config_binding_service" - 18 ClientIPaddress Implemented (from Req) - 19 class name Implemented (mod), though docs say OOP, I am using the python module here - 20 Unused ...implemented.... - 21-25 Custom n/a - 26 detailMessage Implemented (msg) - - Not implemented - 4 serviceInstanceID - ? - 6 physical/virtual server name (Optional) - 8 PartnerName - nothing in the request tells me this - 11 Response Description - the CBS follows standard HTTP error codes so look them up - 12 instanceUUID - Optional - 14 Severity (Optional) - """ - ets = utc() - - _AUDIT_LOGGER.info("{bts}|{ets}|{xer}||n/a||{path}||{status}|{rcode}|||INFO||{servip}|{et}|config_binding_service|{clientip}|{calling_mod}|||||||{msg}".format( - bts=bts.isoformat(), - ets=ets.isoformat(), - xer=xer, rcode=rcode, - path=raw_request.path.split("/")[1], - status="COMPLETE" if rcode < 400 else "ERROR", - servip=raw_request.host.split(":")[0], - et=int((ets - bts).microseconds / 1000), # supposed to be in milleseconds - clientip=raw_request.remote_addr, - calling_mod=calling_mod, msg=msg - )) - - -def error(raw_request, xer, severity, ecode, tgt_entity="n/a", tgt_path="n/a", msg="n/a", adv_msg="n/a"): - """ - write an EELF error record per - the error fields implemented: - - 1 Timestamp Auto Injected when this is called - 2 RequestID Implemented (xer) - 3 ThreadID n/a - 4 ServiceName Implemented (from Req) - 6 TargetEntity Implemented (tgt_entity) - 7 TargetServiceName Implemented (tgt_path)/ - 8 ErrorCategory Implemented (severity) - 9. ErrorCode Implemented (ecode) - 10 ErrorDescription Implemented (msg) - 11. detailMessage Implemented (adv_msg) - - Not implemented: - 5 PartnerName - nothing in the request tells me this - """ - ets = utc() - - _ERROR_LOGGER.error("{ets}|{xer}|n/a|{path}||{tge}|{tgp}|{sev}|{ecode}|{msg}|{amsg}".format( - ets=ets, - xer=xer, - path=raw_request.path.split("/")[1], - tge=tgt_entity, - tgp=tgt_path, - sev=severity, - ecode=ecode, - msg=msg, - amsg=adv_msg)) - - -def metrics(raw_request, bts, xer, target, target_path, rcode, calling_mod, msg="n/a"): - """ - write an EELF metrics record per https://wiki.onap.org/download/attachments/1015849/ONAP%20application%20logging%20guidelines.pdf?api=v2 - %The metrics fields implemented: - - 1 BeginTimestamp Implemented (bts) - 2 EndTimestamp Auto Injected when this is called - 3 RequestID Implemented (xer) - 5 threadId n/a - 7 serviceName Implemented (from Req) - 9 TargetEntity Implemented (target) - 10 TargetServiceName Implemented (target_path) - 11 StatusCode Implemented (based on rcode) - 12 Response Code Implemented (rcode) - 15 Category log level all metrics records are INFO. - 17 Server IP address Implemented (from Req) - 18 ElapsedTime Auto Injected (milliseconds) - 19 Server This is running in a Docker container so this is not applicable, my HOSTNAME is always "config_binding_service" - 20 ClientIPaddress Implemented (from Req) - 21 class name Implemented (mod), though docs say OOP, I am using the python module here - 22 Unused ...implemented.... - 24 TargetVirtualEntity n/a - 25-28 Custom n/a - 29 detailMessage Implemented (msg) - - Not implemented - 4 serviceInstanceID - ? - 6 physical/virtual server name (Optional) - 8 PartnerName - nothing in the request tells me this - 13 Response Description - the CBS follows standard HTTP error codes so look them up - 14 instanceUUID - Optional - 16 Severity (Optional) - 23 ProcessKey - optional - """ - ets = utc() - - _METRICS_LOGGER.info("{bts}|{ets}|{xer}||n/a||{path}||{tge}|{tgp}|{status}|{rcode}|||INFO||{servip}|{et}|config_binding_service|{clientip}|{calling_mod}|||n/a|||||{msg}".format( - bts=bts.isoformat(), - ets=ets.isoformat(), - xer=xer, - path=raw_request.path.split("/")[1], - tge=target, - tgp=target_path, - status="COMPLETE" if rcode < 400 else "ERROR", - rcode=rcode, - servip=raw_request.host.split(":")[0], - et=int((ets - bts).microseconds / 1000), # supposed to be in milleseconds - clientip=raw_request.remote_addr, - calling_mod=calling_mod, msg=msg - )) diff --git a/app/app/config_binding_service/openapi.yaml b/app/app/config_binding_service/openapi.yaml deleted file mode 100644 index bc4dd49..0000000 --- a/app/app/config_binding_service/openapi.yaml +++ /dev/null @@ -1,112 +0,0 @@ -openapi: 3.0.0 -info: - version: 2.3.0 - title: Config Binding Service -paths: - '/service_component/{service_component_name}': - parameters: - - name: service_component_name - in: path - description: >- - Service Component Name. service_component_name must be a key in - consul. - required: true - schema: - type: string - get: - description: >- - Binds the configuration for service_component_name and returns the bound - configuration as a JSON - operationId: config_binding_service.controller.bind_config_for_scn - responses: - '200': - description: OK; the bound config is returned as an object - content: - '*/*': - schema: - type: object - '404': - description: there is no configuration in Consul for this component - '/service_component_all/{service_component_name}': - parameters: - - name: service_component_name - in: path - description: >- - Service Component Name. service_component_name must be a key in - consul. - required: true - schema: - type: string - get: - description: >- - Binds the configuration for service_component_name and returns the bound - configuration, policies, and any other keys that are in Consul - operationId: config_binding_service.controller.bind_all - responses: - '200': - description: >- - OK; returns {config : ..., policies : ....., k : ...} for all other - k in Consul - content: - '*/*': - schema: - type: object - '404': - description: there is no configuration in Consul for this component - '/{key}/{service_component_name}': - parameters: - - name: key - in: path - description: >- - this endpoint tries to pull service_component_name:key; key is the key - after the colon - required: true - schema: - type: string - - name: service_component_name - in: path - description: Service Component Name. - required: true - schema: - type: string - get: - description: >- - this is an endpoint that fetches a generic service_component_name:key - out of Consul. The idea is that we don't want to tie components to - Consul directly in case we swap out the backend some day, so the CBS - abstracts Consul from clients. The structuring and weird collision of - this new API with the above is unfortunate but due to legacy concerns. - operationId: config_binding_service.controller.get_key - responses: - '200': - description: 'OK; returns service_component_name:key' - content: - '*/*': - schema: - type: object - '400': - description: >- - bad request. Currently this is only returned on :policies, which is - a complex object, and should be gotten through service_component_all - content: - '*/*': - schema: - type: string - '404': - description: key does not exist - content: - '*/*': - schema: - type: string - /healthcheck: - get: - description: >- - This is the health check endpoint. If this returns a 200, the server is - alive and consul can be reached. If not a 200, either dead, or no - connection to consul - operationId: config_binding_service.controller.healthcheck - responses: - '200': - description: Successful response - '503': - description: the config binding service cannot reach Consul diff --git a/app/app/main.py b/app/app/main.py deleted file mode 100755 index c7adaaf..0000000 --- a/app/app/main.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -# ============LICENSE_START======================================================= -# Copyright (c) 2017-2019 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. -# 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. -# ============LICENSE_END========================================================= -# -# ECOMP is a trademark and service mark of AT&T Intellectual Property. -from config_binding_service.logging import create_loggers -from config_binding_service import app - -if __name__ == "__main__": - # Only for debugging while developing - app.run(host='0.0.0.0', port=10000, debug=True) -else: - # Entrypoint in UWSGI - create_loggers() diff --git a/app/app/pom.xml b/app/app/pom.xml deleted file mode 100644 index 3b634a6..0000000 --- a/app/app/pom.xml +++ /dev/null @@ -1,270 +0,0 @@ -<?xml version="1.0"?> -<!-- -================================================================================ -Copyright (c) 2017-2019 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. -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. -============LICENSE_END========================================================= - -ECOMP is a trademark and service mark of AT&T Intellectual Property. ---> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.onap.dcaegen2.platform.configbinding</groupId> - <artifactId>app</artifactId> - <version>2.3.0-SNAPSHOT</version> - </parent> - <!--- CHANGE THE FOLLOWING 3 OBJECTS for your own repo --> - <groupId>org.onap.dcaegen2.platform.configbinding</groupId> - <artifactId>app-app</artifactId> - <name>dcaegen2-platform-configbinding-app-app</name> - <version>2.3.0-SNAPSHOT</version> - <url>http://maven.apache.org</url> - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <sonar.sources>.</sonar.sources> - <sonar.junit.reportsPath>xunit-results.xml</sonar.junit.reportsPath> - <sonar.python.coverage.reportPath>coverage.xml</sonar.python.coverage.reportPath> - <sonar.python.xunit.reportPath>xunit-results.xml</sonar.python.xunit.reportPath> - <sonar.language>py</sonar.language> - <sonar.pluginname>python</sonar.pluginname> - <sonar.inclusions>config_binding_service/*.py</sonar.inclusions> - <sonar.exclusions>tests/*,setup.py</sonar.exclusions> - </properties> - <build> - <finalName>${project.artifactId}-${project.version}</finalName> - <pluginManagement> - <plugins> - <!-- the following plugins are invoked from oparent, we do not need them --> - <plugin> - <groupId>org.sonatype.plugins</groupId> - <artifactId>nexus-staging-maven-plugin</artifactId> - <version>1.6.7</version> - <configuration> - <skipNexusStagingDeployMojo>true</skipNexusStagingDeployMojo> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-deploy-plugin</artifactId> - <!-- This version supports the "deployAtEnd" parameter --> - <version>2.8</version> - <configuration> - <skip>true</skip> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-enforcer-plugin</artifactId> - <version>3.0.0-M1</version> - <configuration> - <skip>true</skip> - </configuration> - </plugin> - <!-- first disable the default Java plugins at various stages --> - <!-- maven-resources-plugin is called during "*resource" phases by default behavior. it prepares the resources - dir. we do not need it --> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-resources-plugin</artifactId> - <version>2.6</version> - <configuration> - <skip>true</skip> - </configuration> - </plugin> - <!-- maven-compiler-plugin is called during "compile" phases by default behavior. we do not need it --> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.1</version> - <configuration> - <skip>true</skip> - </configuration> - </plugin> - <!-- maven-jar-plugin is called during "compile" phase by default behavior. we do not need it --> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <version>2.4</version> - <executions> - <execution> - <id>default-jar</id> - <phase/> - </execution> - </executions> - </plugin> - <!-- maven-install-plugin is called during "install" phase by default behavior. it tries to copy stuff under - target dir to ~/.m2. we do not need it --> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-install-plugin</artifactId> - <version>2.4</version> - <configuration> - <skip>true</skip> - </configuration> - </plugin> - <!-- maven-surefire-plugin is called during "test" phase by default behavior. it triggers junit test. - we do not need it --> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-surefire-plugin</artifactId> - <version>2.12.4</version> - <configuration> - <skipTests>true</skipTests> - </configuration> - </plugin> - <plugin> - <groupId>org.codehaus.mojo</groupId> - <artifactId>exec-maven-plugin</artifactId> - <version>1.2.1</version> - <configuration> - <executable>${session.executionRootDirectory}/mvn-phase-script.sh</executable> - <environmentVariables> - <!-- make mvn properties as env for our script --> - <MVN_PROJECT_GROUPID>${project.groupId}</MVN_PROJECT_GROUPID> - <MVN_PROJECT_ARTIFACTID>${project.artifactId}</MVN_PROJECT_ARTIFACTID> - <MVN_PROJECT_VERSION>${project.version}</MVN_PROJECT_VERSION> - <MVN_NEXUSPROXY>${onap.nexus.url}</MVN_NEXUSPROXY> - <MVN_RAWREPO_BASEURL_UPLOAD>${onap.nexus.rawrepo.baseurl.upload}</MVN_RAWREPO_BASEURL_UPLOAD> - <MVN_RAWREPO_BASEURL_DOWNLOAD>${onap.nexus.rawrepo.baseurl.download}</MVN_RAWREPO_BASEURL_DOWNLOAD> - <MVN_RAWREPO_SERVERID>${onap.nexus.rawrepo.serverid}</MVN_RAWREPO_SERVERID> - <MVN_DOCKERREGISTRY_DAILY>${onap.nexus.dockerregistry.daily}</MVN_DOCKERREGISTRY_DAILY> - <MVN_DOCKERREGISTRY_RELEASE>${onap.nexus.dockerregistry.release}</MVN_DOCKERREGISTRY_RELEASE> - </environmentVariables> - </configuration> - </plugin> - </plugins> - </pluginManagement> - <plugins> - <!-- plugin> - <artifactId>maven-assembly-plugin</artifactId> - <version>2.4.1</version> - <configuration> - <descriptors> - <descriptor>assembly/dep.xml</descriptor> - </descriptors> - </configuration> - <executions> - <execution> - <id>make-assembly</id> - <phase>package</phase> - <goals> - <goal>single</goal> - </goals> - </execution> - </executions> - </plugin --> - <!-- now we configure custom action (calling a script) at various lifecycle phases --> - <plugin> - <groupId>org.codehaus.mojo</groupId> - <artifactId>exec-maven-plugin</artifactId> - <version>1.2.1</version> - <executions> - <execution> - <id>clean phase script</id> - <phase>clean</phase> - <goals> - <goal>exec</goal> - </goals> - <configuration> - <arguments> - <argument>__</argument> - <argument>clean</argument> - </arguments> - </configuration> - </execution> - <execution> - <id>generate-sources script</id> - <phase>generate-sources</phase> - <goals> - <goal>exec</goal> - </goals> - <configuration> - <arguments> - <argument>__</argument> - <argument>generate-sources</argument> - </arguments> - </configuration> - </execution> - <execution> - <id>compile script</id> - <phase>compile</phase> - <goals> - <goal>exec</goal> - </goals> - <configuration> - <arguments> - <argument>__</argument> - <argument>compile</argument> - </arguments> - </configuration> - </execution> - <execution> - <id>package script</id> - <phase>package</phase> - <goals> - <goal>exec</goal> - </goals> - <configuration> - <arguments> - <argument>__</argument> - <argument>package</argument> - </arguments> - </configuration> - </execution> - <execution> - <id>test script</id> - <phase>test</phase> - <goals> - <goal>exec</goal> - </goals> - <configuration> - <arguments> - <argument>__</argument> - <argument>test</argument> - </arguments> - </configuration> - </execution> - <execution> - <id>install script</id> - <phase>install</phase> - <goals> - <goal>exec</goal> - </goals> - <configuration> - <arguments> - <argument>__</argument> - <argument>install</argument> - </arguments> - </configuration> - </execution> - <execution> - <id>deploy script</id> - <phase>deploy</phase> - <goals> - <goal>exec</goal> - </goals> - <configuration> - <arguments> - <argument>__</argument> - <argument>deploy</argument> - </arguments> - </configuration> - </execution> - </executions> - </plugin> - </plugins> - </build> -</project> diff --git a/app/app/setup.py b/app/app/setup.py deleted file mode 100644 index 38929c9..0000000 --- a/app/app/setup.py +++ /dev/null @@ -1,34 +0,0 @@ -# ============LICENSE_START======================================================= -# Copyright (c) 2017-2019 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. -# 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. -# ============LICENSE_END========================================================= -# -# ECOMP is a trademark and service mark of AT&T Intellectual Property. - -from setuptools import setup, find_packages - -setup( - name='config_binding_service', - version='2.3.0', - packages=find_packages(exclude=["tests.*", "tests"]), - author="Tommy Carpenter", - author_email="tommy@research.att.com", - description='Service to fetch and bind configurations', - url="https://gerrit.onap.org/r/#/admin/projects/dcaegen2/platform/configbinding", - install_requires=["requests", - "Flask", - "six", - "connexion[swagger-ui]"], - package_data={'config_binding_service': ['openapi.yaml']} -) diff --git a/app/app/tests/__init__.py b/app/app/tests/__init__.py deleted file mode 100644 index 1875bf6..0000000 --- a/app/app/tests/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# ================================================================================ -# Copyright (c) 2018 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. -# 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. -# ============LICENSE_END========================================================= -# -# ECOMP is a trademark and service mark of AT&T Intellectual Property. - - -# empty __init__.py so that pytest can add correct path to coverage report, -- per pytest -# best practice guideline diff --git a/app/app/tests/conftest.py b/app/app/tests/conftest.py deleted file mode 100644 index c8f2a06..0000000 --- a/app/app/tests/conftest.py +++ /dev/null @@ -1,70 +0,0 @@ -import pytest -from requests.exceptions import HTTPError -from config_binding_service import get_consul_uri - - -class FakeResponse(): - def __init__(self, status_code, text): - self.text = text - self.status_code = status_code - - def raise_for_status(self): - if self.status_code >= 400: - raise HTTPError(response=FakeResponse(404, "")) - - -@pytest.fixture -def expected_config(): - return {"deep": {"ALL YOUR SERVICE BELONG TO US": ['6.6.6.6:666', '7.7.7.7:777', '5.5.5.5:555', '5.5.5.5:555']}, - "doubledeep": {"sodeep": {"hello": "darkness"}}} - - -@pytest.fixture -def monkeyed_get_connection_info_from_consul(): - def _monkeyed_get_connection_info_from_consul(service_component_name): - # shared monkeypatch. probably somewhat lazy because the function htis patches can be broken up. - if service_component_name == "cdap": - return '666.666.666.666:666' - elif service_component_name == "testing_bravo.somedomain.com": - return '7.7.7.7:777' - elif service_component_name == "testing_alpha.somedomain.com": - return '6.6.6.6:666' - elif service_component_name == "testing_charlie.somedomain.com": - return '5.5.5.5:555' - elif service_component_name == "nonexistent_hope": - return None # the real function returns None here - elif service_component_name == "cdap_serv.dcae.ecomp.somedomain.com": - broker_ip = '1.1.1.1' - broker_port = 444 - return "http://{0}:{1}/application/{2}".format(broker_ip, broker_port, service_component_name) - return _monkeyed_get_connection_info_from_consul - - -@pytest.fixture -def monkeyed_requests_get(): - def _monkeyed_requests_get(url): - if url == "{0}/v1/kv/test_service_component_name.unknown.unknown.unknown.dcae.onap.org:dti".format(get_consul_uri()): - return FakeResponse(status_code=200, text='[{"LockIndex":0,"Key":"test_service_component_name.unknown.unknown.unknown.dcae.onap.org:dti","Flags":0,"Value": "eyJteSIgOiAiZHRpIn0=","CreateIndex":4066524,"ModifyIndex":4066524}]') - else: - return FakeResponse(status_code=404, text="") - return _monkeyed_requests_get - - -@pytest.fixture -def monkeyed_requests_put(): - def _monkeyed_requests_put(url, json): - if url == "{0}/v1/txn".format(get_consul_uri()): - key = json[0]["KV"]["Key"] - if key == "test_service_component_name.unknown.unknown.unknown.dcae.onap.org": - return FakeResponse(status_code=200, text='{"Results":[{"KV":{"LockIndex":0,"Key":"test_service_component_name.unknown.unknown.unknown.dcae.onap.org","Flags":0,"Value":"eyJteSIgOiAiYW1hemluZyBjb25maWcifQ==","CreateIndex":4051555,"ModifyIndex":4051555}},{"KV":{"LockIndex":0,"Key":"test_service_component_name.unknown.unknown.unknown.dcae.onap.org:dmaap","Flags":0,"Value":"eyJmb28iIDogImJhciJ9","CreateIndex":4051571,"ModifyIndex":4051571}},{"KV":{"LockIndex":0,"Key":"test_service_component_name.unknown.unknown.unknown.dcae.onap.org:dti","Flags":0,"Value":"eyJteSIgOiAiZHRpIn0=","CreateIndex":4066524,"ModifyIndex":4066524}},{"KV":{"LockIndex":0,"Key":"test_service_component_name.unknown.unknown.unknown.dcae.onap.org:policies/event","Flags":0,"Value":"eyJhY3Rpb24iOiAiZ2F0aGVyZWQiLCAidGltZXN0YW1wIjogIjIwMTgtMDItMTkgMTU6MzY6NDQuODc3MzgwIiwgInVwZGF0ZV9pZCI6ICJiYjczYzIwYS01ZmY4LTQ1MGYtODIyMy1kYTY3MjBhZGUyNjciLCAicG9saWNpZXNfY291bnQiOiAyfQ==","CreateIndex":4048564,"ModifyIndex":4048564}},{"KV":{"LockIndex":0,"Key":"test_service_component_name.unknown.unknown.unknown.dcae.onap.org:policies/items/DCAE_alex.Config_MS_alex_microservice","Flags":0,"Value":"eyJwb2xpY3lOYW1lIjogIkRDQUVfYWxleC5Db25maWdfTVNfYWxleF9taWNyb3NlcnZpY2UuMTMyLnhtbCIsICJwb2xpY3lDb25maWdNZXNzYWdlIjogIkNvbmZpZyBSZXRyaWV2ZWQhICIsICJyZXNwb25zZUF0dHJpYnV0ZXMiOiB7fSwgInBvbGljeUNvbmZpZ1N0YXR1cyI6ICJDT05GSUdfUkVUUklFVkVEIiwgIm1hdGNoaW5nQ29uZGl0aW9ucyI6IHsiT05BUE5hbWUiOiAiRENBRSIsICJOYW1lIjogIkRDQUUiLCAiQ29uZmlnTmFtZSI6ICJhbGV4X2NvbmZpZ19uYW1lIn0sICJjb25maWciOiB7InBvbGljeVNjb3BlIjogImFsZXhfcG9saWN5X3Njb3BlIiwgImNvbmZpZ05hbWUiOiAiYWxleF9jb25maWdfbmFtZSIsICJkZXNjcmlwdGlvbiI6ICJ0ZXN0IERDQUUgcG9saWN5LWhhbmRsZXIiLCAic2VydmljZSI6ICJhbGV4X3NlcnZpY2UiLCAicG9saWN5TmFtZSI6ICJhbGV4X3BvbGljeV9uYW1lIiwgInJpc2tMZXZlbCI6ICIzIiwgImtleTEiOiAidmFsdWUxIiwgInBvbGljeV9oZWxsbyI6ICJ3b3JsZCEiLCAiY29udGVudCI6IHsiZm9vIjogIm1pY3Jvc2VydmljZTMiLCAiZm9vX3VwZGF0ZWQiOiAiMjAxOC0wMS0zMFQxMzoyNTozMy4yMjJaIn0sICJyaXNrVHlwZSI6ICIxNzEyX0VURSIsICJndWFyZCI6ICJGYWxzZSIsICJ2ZXJzaW9uIjogIjAuMC4xIiwgImxvY2F0aW9uIjogIkNlbnRyYWwiLCAicG9saWN5X3VwZGF0ZWRfdHMiOiAiMjAxOC0wMi0xOVQxNTowOTo1NS4yMTdaIiwgInVwZGF0ZWRfcG9saWN5X2lkIjogIkRDQUVfYWxleC5Db25maWdfTVNfYWxleF9taWNyb3NlcnZpY2UiLCAicG9saWN5X3VwZGF0ZWRfdG9fdmVyIjogIjEzMiIsICJwcmlvcml0eSI6ICI0IiwgInBvbGljeV91cGRhdGVkX2Zyb21fdmVyIjogIjEzMSIsICJ0ZW1wbGF0ZVZlcnNpb24iOiAiMiIsICJ1dWlkIjogIjVlODdkN2M1LTBkYWYtNGI2Yi1hYjkyLTUzNjVjZjVkYjFlZiJ9LCAicHJvcGVydHkiOiBudWxsLCAidHlwZSI6ICJKU09OIiwgInBvbGljeVZlcnNpb24iOiAiMTMyIn0=","CreateIndex":4048564,"ModifyIndex":4065574}},{"KV":{"LockIndex":0,"Key":"test_service_component_name.unknown.unknown.unknown.dcae.onap.org:policies/items/DCAE_alex.Config_db_client_policy_id_value","Flags":0,"Value":"eyJwb2xpY3lOYW1lIjogIkRDQUVfYWxleC5Db25maWdfZGJfY2xpZW50X3BvbGljeV9pZF92YWx1ZS4xMzMueG1sIiwgInBvbGljeUNvbmZpZ01lc3NhZ2UiOiAiQ29uZmlnIFJldHJpZXZlZCEgIiwgInJlc3BvbnNlQXR0cmlidXRlcyI6IHt9LCAicG9saWN5Q29uZmlnU3RhdHVzIjogIkNPTkZJR19SRVRSSUVWRUQiLCAibWF0Y2hpbmdDb25kaXRpb25zIjogeyJPTkFQTmFtZSI6ICJEQ0FFIiwgIk5hbWUiOiAiRENBRSIsICJDb25maWdOYW1lIjogImFsZXhfY29uZmlnX25hbWUifSwgImNvbmZpZyI6IHsiZGJfY2xpZW50X3RzIjogIjIwMTctMTEtMjFUMTI6MTI6MTMuNjk2WiIsICJkYl9jbGllbnQiOiAiaXBzdW0iLCAicG9saWN5X2hlbGxvIjogIndvcmxkISIsICJwb2xpY3lfdXBkYXRlZF9mcm9tX3ZlciI6ICIxMzIiLCAidXBkYXRlZF9wb2xpY3lfaWQiOiAiRENBRV9hbGV4LkNvbmZpZ19kYl9jbGllbnRfcG9saWN5X2lkX3ZhbHVlIiwgInBvbGljeV91cGRhdGVkX3RzIjogIjIwMTgtMDItMTlUMTU6MDk6NTUuODEyWiIsICJwb2xpY3lfdXBkYXRlZF90b192ZXIiOiAiMTMzIn0sICJwcm9wZXJ0eSI6IG51bGwsICJ0eXBlIjogIkpTT04iLCAicG9saWN5VmVyc2lvbiI6ICIxMzMifQ==","CreateIndex":4048564,"ModifyIndex":4065570}},{"KV":{"LockIndex":0,"Key":"test_service_component_name.unknown.unknown.unknown.dcae.onap.org:rels","Flags":0,"Value":"WyJteS5hbWF6aW5nLnJlbGF0aW9uc2hpcCJd","CreateIndex":4051567,"ModifyIndex":4051567}}],"Errors":null,"Index":0,"LastContact":0,"KnownLeader":true}') - elif key == "scn_exists": - return FakeResponse(status_code=200, text='{"Results":[{"KV":{"LockIndex":0,"Key":"scn_exists","Flags":0,"Value":"eyJmb28zIiA6ICJiYXIzIn0=","CreateIndex":4067403,"ModifyIndex":4067403}},{"KV":{"LockIndex":0,"Key":"scn_exists:dmaap","Flags":0,"Value":"eyJmb280IiA6ICJiYXI0In0=","CreateIndex":4067410,"ModifyIndex":4067410}},{"KV":{"LockIndex":0,"Key":"scn_exists:rels","Flags":0,"Value":"WyJmb28iXQ==","CreateIndex":4067406,"ModifyIndex":4067406}},{"KV":{"LockIndex":0,"Key":"scn_exists_nord","Flags":0,"Value":"eyJmb281IiA6ICJiYXI1In0=","CreateIndex":4067340,"ModifyIndex":4067340}}],"Errors":null,"Index":0,"LastContact":0,"KnownLeader":true}') - elif key == "scn_exists_nord": - return FakeResponse(status_code=200, text='{"Results":[{"KV":{"LockIndex":0,"Key":"scn_exists_nord","Flags":0,"Value":"eyJmb281IiA6ICJiYXI1In0=","CreateIndex":4067340,"ModifyIndex":4067340}}],"Errors":null,"Index":0,"LastContact":0,"KnownLeader":true}') - elif key == "test_resolve_scn": - return FakeResponse(status_code=200, text='{"Results":[{"KV":{"LockIndex":0,"Key":"test_resolve_scn","Flags":0,"Value":"ewogICAgICAgICAgICAgICAgImRlZXAiIDogewogICAgICAgICAgICAgICAgICAgICJBTEwgWU9VUiBTRVJWSUNFIEJFTE9ORyBUTyBVUyIgOiAie3thbHBoYSxicmF2byxjaGFybGllfX0ifSwKICAgICAgICAgICAgICAgICJkb3VibGVkZWVwIiA6ICB7CiAgICAgICAgICAgICAgICAgICAgInNvZGVlcCIgOiB7ImhlbGxvIiA6ICI8PFdITz8+PiJ9fQogICAgICAgICAgICAgfQo=","CreateIndex":4068002,"ModifyIndex":4068002}},{"KV":{"LockIndex":0,"Key":"test_resolve_scn:dmaap","Flags":0,"Value":"eyJXSE8/IiA6ICJkYXJrbmVzcyJ9","CreateIndex":4068013,"ModifyIndex":4068013}},{"KV":{"LockIndex":0,"Key":"test_resolve_scn:rels","Flags":0,"Value":"WyJ0ZXN0aW5nX2FscGhhLnNvbWVkb21haW4uY29tIiwgInRlc3RpbmdfYnJhdm8uc29tZWRvbWFpbi5jb20iLCAidGVzdGluZ19jaGFybGllLnNvbWVkb21haW4uY29tIiwgInRlc3RpbmdfY2hhcmxpZS5zb21lZG9tYWluLmNvbSJd","CreateIndex":4068010,"ModifyIndex":4068010}}],"Errors":null,"Index":0,"LastContact":0,"KnownLeader":true}') - elif key == "cbs_test_messed_up": - return FakeResponse(status_code=200, text='{"Results":[{"KV":{"LockIndex":0,"Key":"cbs_test_messed_up","Flags":0,"Value":"eyJmb28iIDogImJhciJ9","CreateIndex":4864032,"ModifyIndex":4864052}},{"KV":{"LockIndex":0,"Key":"cbs_test_messed_up:badkey","Flags":0,"Value":"eyJub3QgYSBqc29ubm5uIFJFS1RUVFQ=","CreateIndex":4864075,"ModifyIndex":4864075}}],"Errors":null,"Index":0,"LastContact":0,"KnownLeader":true}') - elif key == "scn_NOTexists": - return FakeResponse(status_code=404, text="") - return _monkeyed_requests_put diff --git a/app/app/tests/test_api.py b/app/app/tests/test_api.py deleted file mode 100644 index 118a2a0..0000000 --- a/app/app/tests/test_api.py +++ /dev/null @@ -1,103 +0,0 @@ -# ============LICENSE_START======================================================= -# Copyright (c) 2017-2019 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. -# 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. -# ============LICENSE_END========================================================= -# -# ECOMP is a trademark and service mark of AT&T Intellectual Property. -import json -import pytest -import os -import tempfile -from config_binding_service import app - - -TEST_NAME = "test_service_component_name.unknown.unknown.unknown.dcae.onap.org" - - -# http://flask.pocoo.org/docs/1.0/testing/ -@pytest.fixture -def cbsclient(): - db_fd, app.app.config['DATABASE'] = tempfile.mkstemp() - app.app.config['TESTING'] = True - testclient = app.app.test_client() - - yield testclient - - os.close(db_fd) - os.unlink(app.app.config['DATABASE']) - - -def test_get(monkeypatch, cbsclient, monkeyed_requests_put): - monkeypatch.setattr('requests.put', monkeyed_requests_put) - - res = cbsclient.get('/service_component/scn_exists', - headers={"x-onap-requestid": 123456789}) - assert(json.loads(res.data) == {"foo3": "bar3"}) - assert(res.status_code == 200) - assert(res.headers["x-onap-requestid"] == "123456789") - - res = cbsclient.get('/service_component/scn_NOTexists', - headers={"x-onap-requestid": 123456789}) - assert(res.status_code == 404) - assert(res.headers["x-onap-requestid"] == "123456789") - - res = cbsclient.get('/service_component/asdfasdf', - headers={"x-onap-requestid": 123456789}) - assert(res.status_code == 500) - assert(res.headers["x-onap-requestid"] == "123456789") - - -def test_generic(monkeypatch, cbsclient, monkeyed_requests_get, monkeyed_requests_put): - monkeypatch.setattr('requests.put', monkeyed_requests_put) - monkeypatch.setattr('requests.get', monkeyed_requests_get) - - res = cbsclient.get('/dti/{0}'.format(TEST_NAME)) - assert json.loads(res.data) == {"my": "dti"} - assert res.json == {"my": "dti"} - assert res.status_code == 200 - assert "x-onap-requestid" in res.headers - - res = cbsclient.get('/nokeyforyou/{0}'.format(TEST_NAME)) - assert res.status_code == 404 - assert "x-onap-requestid" in res.headers - - res = cbsclient.get('/policies/{0}'.format(TEST_NAME)) - assert res.status_code == 400 - assert "x-onap-requestid" in res.headers - - -def test_resolve_all(monkeypatch, cbsclient, monkeyed_requests_put, monkeyed_get_connection_info_from_consul, expected_config): - monkeypatch.setattr('requests.put', monkeyed_requests_put) - monkeypatch.setattr('config_binding_service.client._get_connection_info_from_consul', monkeyed_get_connection_info_from_consul) - withstuff = {'config': {'my': 'amazing config'}, - 'dti': {'my': 'dti'}, - 'policies': {'items': [{'policyName': 'DCAE_alex.Config_MS_alex_microservice.132.xml', 'policyConfigMessage': 'Config Retrieved! ', 'responseAttributes': {}, 'policyConfigStatus': 'CONFIG_RETRIEVED', 'matchingConditions': {'ONAPName': 'DCAE', 'Name': 'DCAE', 'ConfigName': 'alex_config_name'}, 'config': {'policyScope': 'alex_policy_scope', 'configName': 'alex_config_name', 'description': 'test DCAE policy-handler', 'service': 'alex_service', 'policyName': 'alex_policy_name', 'riskLevel': '3', 'key1': 'value1', 'policy_hello': 'world!', 'content': {'foo': 'microservice3', 'foo_updated': '2018-01-30T13:25:33.222Z'}, 'riskType': '1712_ETE', 'guard': 'False', 'version': '0.0.1', 'location': 'Central', 'policy_updated_ts': '2018-02-19T15:09:55.217Z', 'updated_policy_id': 'DCAE_alex.Config_MS_alex_microservice', 'policy_updated_to_ver': '132', 'priority': '4', 'policy_updated_from_ver': '131', 'templateVersion': '2', 'uuid': '5e87d7c5-0daf-4b6b-ab92-5365cf5db1ef'}, 'property': None, 'type': 'JSON', 'policyVersion': '132'}, {'policyName': 'DCAE_alex.Config_db_client_policy_id_value.133.xml', 'policyConfigMessage': 'Config Retrieved! ', 'responseAttributes': {}, 'policyConfigStatus': 'CONFIG_RETRIEVED', 'matchingConditions': {'ONAPName': 'DCAE', 'Name': 'DCAE', 'ConfigName': 'alex_config_name'}, 'config': {'db_client_ts': '2017-11-21T12:12:13.696Z', 'db_client': 'ipsum', 'policy_hello': 'world!', 'policy_updated_from_ver': '132', 'updated_policy_id': 'DCAE_alex.Config_db_client_policy_id_value', 'policy_updated_ts': '2018-02-19T15:09:55.812Z', 'policy_updated_to_ver': '133'}, 'property': None, 'type': 'JSON', 'policyVersion': '133'}], 'event': {'action': 'gathered', 'timestamp': '2018-02-19 15:36:44.877380', 'update_id': 'bb73c20a-5ff8-450f-8223-da6720ade267', 'policies_count': 2}}} - - assert cbsclient.get('service_component_all/{0}'.format(TEST_NAME)).json == withstuff - - assert cbsclient.get('service_component_all/test_resolve_scn').json == {"config": expected_config} - - res = cbsclient.get('/service_component_all/{0}'.format(TEST_NAME)) - assert json.loads(res.data) == withstuff - assert res.json == withstuff - assert res.status_code == 200 - assert "x-onap-requestid" in res.headers - - res = cbsclient.get('/service_component_all/test_resolve_scn') - assert res.status_code == 200 - assert res.json == {"config": expected_config} - - res = cbsclient.get('/service_component_all/scn_NOTexists') - assert res.status_code == 404 - assert "x-onap-requestid" in res.headers diff --git a/app/app/tests/test_client.py b/app/app/tests/test_client.py deleted file mode 100644 index 96c3467..0000000 --- a/app/app/tests/test_client.py +++ /dev/null @@ -1,206 +0,0 @@ -# ============LICENSE_START======================================================= -# Copyright (c) 2017-2019 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. -# 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. -# ============LICENSE_END========================================================= -# - -from config_binding_service import client -import pytest - - -# pytest doesnt support objects in conftest -class FakeReq(object): - """used to fake the logging params""" - def __init__(self): - self.path = "/unittest in {0}".format(__name__) - self.host = "localhost" - self.remote_addr = "6.6.6.6" - - -# pytest doesnt support objects in conftest -class FakeConnexion(object): - def __init__(self, headers, path, host, remote_addr): - self.headers = headers - self.path = path - self.host = host - self.remote_addr = remote_addr - - -def test_consul_get_all_as_transaction(monkeypatch, monkeyed_requests_put): - """tests _consul_get_all_as_transaction""" - monkeypatch.setattr('requests.put', monkeyed_requests_put) - allk = client._consul_get_all_as_transaction( - "test_service_component_name.unknown.unknown.unknown.dcae.onap.org", FakeReq(), "unit test xer") - assert allk == { - 'test_service_component_name.unknown.unknown.unknown.dcae.onap.org': {'my': 'amazing config'}, - 'test_service_component_name.unknown.unknown.unknown.dcae.onap.org:dti': {'my': 'dti'}, - 'test_service_component_name.unknown.unknown.unknown.dcae.onap.org:dmaap': {'foo': 'bar'}, - 'test_service_component_name.unknown.unknown.unknown.dcae.onap.org:policies/event': {'action': 'gathered', 'timestamp': '2018-02-19 15:36:44.877380', 'update_id': 'bb73c20a-5ff8-450f-8223-da6720ade267', 'policies_count': 2}, - 'test_service_component_name.unknown.unknown.unknown.dcae.onap.org:policies/items/DCAE_alex.Config_MS_alex_microservice': {'policyName': 'DCAE_alex.Config_MS_alex_microservice.132.xml', 'policyConfigMessage': 'Config Retrieved! ', 'responseAttributes': {}, 'policyConfigStatus': 'CONFIG_RETRIEVED', 'matchingConditions': {'ONAPName': 'DCAE', 'Name': 'DCAE', 'ConfigName': 'alex_config_name'}, 'config': {'policyScope': 'alex_policy_scope', 'configName': 'alex_config_name', 'description': 'test DCAE policy-handler', 'service': 'alex_service', 'policyName': 'alex_policy_name', 'riskLevel': '3', 'key1': 'value1', 'policy_hello': 'world!', 'content': {'foo': 'microservice3', 'foo_updated': '2018-01-30T13:25:33.222Z'}, 'riskType': '1712_ETE', 'guard': 'False', 'version': '0.0.1', 'location': 'Central', 'policy_updated_ts': '2018-02-19T15:09:55.217Z', 'updated_policy_id': 'DCAE_alex.Config_MS_alex_microservice', 'policy_updated_to_ver': '132', 'priority': '4', 'policy_updated_from_ver': '131', 'templateVersion': '2', 'uuid': '5e87d7c5-0daf-4b6b-ab92-5365cf5db1ef'}, 'property': None, 'type': 'JSON', 'policyVersion': '132'}, - 'test_service_component_name.unknown.unknown.unknown.dcae.onap.org:policies/items/DCAE_alex.Config_db_client_policy_id_value': {'policyName': 'DCAE_alex.Config_db_client_policy_id_value.133.xml', 'policyConfigMessage': 'Config Retrieved! ', 'responseAttributes': {}, 'policyConfigStatus': 'CONFIG_RETRIEVED', 'matchingConditions': {'ONAPName': 'DCAE', 'Name': 'DCAE', 'ConfigName': 'alex_config_name'}, 'config': {'db_client_ts': '2017-11-21T12:12:13.696Z', 'db_client': 'ipsum', 'policy_hello': 'world!', 'policy_updated_from_ver': '132', 'updated_policy_id': 'DCAE_alex.Config_db_client_policy_id_value', 'policy_updated_ts': '2018-02-19T15:09:55.812Z', 'policy_updated_to_ver': '133'}, 'property': None, 'type': 'JSON', 'policyVersion': '133'}, - 'test_service_component_name.unknown.unknown.unknown.dcae.onap.org:rels': ['my.amazing.relationship'] - } - - allk = client._consul_get_all_as_transaction("cbs_test_messed_up", FakeReq(), "unit test xer") - assert allk == {'cbs_test_messed_up': {'foo': 'bar'}, - 'cbs_test_messed_up:badkey': 'INVALID JSON'} - - -def test_get_config_rels_dmaap(monkeypatch, monkeyed_requests_put): - monkeypatch.setattr('requests.put', monkeyed_requests_put) - assert ({"foo3": "bar3"}, ["foo"], {"foo4": "bar4"}) == client._get_config_rels_dmaap("scn_exists", FakeReq(), "unit test xer") - assert ({"foo5": "bar5"}, [], {}) == client._get_config_rels_dmaap("scn_exists_nord", FakeReq(), "unit test xer") - - -def test_bad_config_http(): - test_config = {'yeahhhhh': "{{}}"} - test_rels = ["testing_bravo.somedomain.com"] - assert {'yeahhhhh': []} == client.resolve_override(test_config, test_rels) - - -def test_bad_config_dmaap(): - test_config = {'darkness': "<<>>"} - test_dmaap = {"WHO?": "darkness"} - assert {'darkness': {}} == client.resolve_override(test_config, test_dmaap) - - -def test_config_with_list(monkeypatch, monkeyed_get_connection_info_from_consul): - monkeypatch.setattr('config_binding_service.client._get_connection_info_from_consul', - monkeyed_get_connection_info_from_consul) - test_config_1 = {"dcae_target_type": [ - "vhss-ems", "pcrf-oam"], "downstream-laika": "{{ laika }}", "some-param": "Lorem ipsum dolor sit amet"} - test_rels_1 = ["3df5292249ae4a949f173063617cea8d_docker-snmp-polling-firstnet-m"] - test_bind_1 = client.resolve_override(test_config_1, test_rels_1, {}) - assert(test_bind_1 == {'dcae_target_type': [ - 'vhss-ems', 'pcrf-oam'], 'downstream-laika': [], 'some-param': 'Lorem ipsum dolor sit amet'}) - - test_config_2 = {"foo": ["{{cdap}}", "notouching", "<<yo>>"]} - test_rels_2 = ["cdap"] - test_dmaap_2 = {"yo": "im here"} - test_bind_2 = client.resolve_override(test_config_2, test_rels_2, test_dmaap_2) - assert(test_bind_2 == {"foo": [['666.666.666.666:666'], "notouching", "im here"]}) - - -def test_cdap(monkeypatch, monkeyed_get_connection_info_from_consul): - # user override to test CDAP functionality - monkeypatch.setattr('config_binding_service.client._get_connection_info_from_consul', - monkeyed_get_connection_info_from_consul) - test_rels = ["testing_alpha.somedomain.com", "testing_bravo.somedomain.com", - "testing_charlie.somedomain.com", "testing_charlie.somedomain.com", "cdap"] - test_config = {"streams_publishes": "{{alpha}}", - # should be dumped - "services_calls": [{"somekey": "{{charlie}}"}], - "cdap_to_manage": {'some_nested_thing': "{{cdap}}"}} # no dumps - test_bind_1 = client.resolve_override(test_config, test_rels) - assert test_bind_1 == {'services_calls': [{"somekey": ["5.5.5.5:555", "5.5.5.5:555"]}], 'streams_publishes': [ - "6.6.6.6:666"], 'cdap_to_manage': {'some_nested_thing': ['666.666.666.666:666']}} - assert test_bind_1['services_calls'] == [{"somekey": ["5.5.5.5:555", "5.5.5.5:555"]}] - assert test_bind_1['streams_publishes'] == ["6.6.6.6:666"] - - -def test_multiple_service_types(monkeypatch, monkeyed_get_connection_info_from_consul): - # test {{x,y,z}} - monkeypatch.setattr('config_binding_service.client._get_connection_info_from_consul', - monkeyed_get_connection_info_from_consul) - - # test 1: they all resovle - test_rels = ["testing_alpha.somedomain.com", "testing_bravo.somedomain.com", - "testing_charlie.somedomain.com", "testing_charlie.somedomain.com"] - config = {"ALL YOUR SERVICE BELONG TO US": "{{alpha,bravo,charlie}}"} - test_bind_1 = client.resolve_override(config, test_rels) - assert(test_bind_1 == {"ALL YOUR SERVICE BELONG TO US": [ - '6.6.6.6:666', '7.7.7.7:777', '5.5.5.5:555', '5.5.5.5:555']}) - - # test 2: two resolve, one is missing from rels key - config2 = {"two there one not exist": "{{alpha,bravo,notexist}}"} - test_bind_2 = client.resolve_override(config2, test_rels) - assert(test_bind_2 == {"two there one not exist": [ - '6.6.6.6:666', '7.7.7.7:777']}) - - # test 3: two resolve, one is in rels key but not registered - config3 = {"two there one unregistered": "{{alpha,bravo,unregistered}}"} - test_rels3 = ["testing_alpha.somedomain.com", - "testing_bravo.somedomain.com", "unregistered.somedomain.com"] - test_bind_3 = client.resolve_override(config3, test_rels3) - assert(test_bind_3 == {"two there one unregistered": [ - '6.6.6.6:666', '7.7.7.7:777']}) - - -def test_dmaap(monkeypatch): - # test resolving dmaap key - config = {"TODAY IS YOUR LUCKY DAY": "<<XXX>>"} - # does not match - test_bind = client.resolve_override( - config, dmaap={"XX": "ABSOLVEME"}) # XX != XXX - assert(test_bind == {"TODAY IS YOUR LUCKY DAY": {}}) - # matches - test_bind_2 = client.resolve_override(config, dmaap={"XXX": "ABSOLVEME"}) - assert(test_bind_2 == {"TODAY IS YOUR LUCKY DAY": "ABSOLVEME"}) - - -def test_config(monkeypatch, monkeyed_get_connection_info_from_consul): - # test config override - monkeypatch.setattr('config_binding_service.client._get_connection_info_from_consul', - monkeyed_get_connection_info_from_consul) - test_config = {"autoderegisterafter": "10m", "cdap_to_manage": { - 'some_nested_thing': "{{cdap}}"}, "bindingttw": 5, "hcinterval": "5s"} - test_rels = ["cdap"] - test_bind_1 = client.resolve_override(test_config, test_rels) - assert test_bind_1 == {'autoderegisterafter': '10m', 'cdap_to_manage': { - 'some_nested_thing': ['666.666.666.666:666']}, 'bindingttw': 5, 'hcinterval': '5s'} - - -def test_non_existent(monkeypatch, monkeyed_get_connection_info_from_consul): - # test a valid config-rels but the key is not in Consul - monkeypatch.setattr('config_binding_service.client._get_connection_info_from_consul', - monkeyed_get_connection_info_from_consul) - test_config = {"you shall not be fufilled": "{{nonexistent_hope}}"} - # hopefully not registered in Consul.. - test_rels = ["nonexistent_hope.rework-central.ecomp.somedomain.com"] - test_bind_1 = client.resolve_override(test_config, test_rels, {}) - assert(test_bind_1 == {"you shall not be fufilled": []}) - - -def test_broker_redirect(monkeypatch, monkeyed_get_connection_info_from_consul): - # test the broker redirect - monkeypatch.setattr('config_binding_service.client._get_connection_info_from_consul', - monkeyed_get_connection_info_from_consul) - test_config = {"gimmie_dat_cdap": "{{cdap_serv}}"} - test_rels = ["cdap_serv.dcae.ecomp.somedomain.com"] - assert {"gimmie_dat_cdap": ['http://1.1.1.1:444/application/cdap_serv.dcae.ecomp.somedomain.com'] - } == client.resolve_override(test_config, test_rels) - - -def test_both(monkeypatch, monkeyed_get_connection_info_from_consul, expected_config): - # test rels and http - monkeypatch.setattr('config_binding_service.client._get_connection_info_from_consul', - monkeyed_get_connection_info_from_consul) - test_rels = ["testing_alpha.somedomain.com", "testing_bravo.somedomain.com", - "testing_charlie.somedomain.com", "testing_charlie.somedomain.com"] - test_dmaap = {"WHO?": "darkness"} - config = {"deep": {"ALL YOUR SERVICE BELONG TO US": "{{alpha,bravo,charlie}}"}, - "doubledeep": {"sodeep": {"hello": "<<WHO?>>"}}} - test_bind_1 = client.resolve_override(config, test_rels, test_dmaap) - assert(test_bind_1 == expected_config) - - -def test_failures(monkeypatch, monkeyed_requests_put, monkeyed_requests_get): - monkeypatch.setattr('requests.put', monkeyed_requests_put) - monkeypatch.setattr('requests.get', monkeyed_requests_get) - monkeypatch.setattr('connexion.request', FakeConnexion({"x-onap-requestid": 123456789}, "/service_component", "mytestingmachine", "myremoteclient")) - assert(client.resolve("scn_exists", FakeReq(), "unit test xer") == {"foo3": "bar3"}) - with pytest.raises(client.CantGetConfig): - client.resolve("scn_NOTexists", FakeReq(), "unit test xer") - with pytest.raises(client.CantGetConfig): - client.get_key("nokeyforyou", "test_service_component_name.unknown.unknown.unknown.dcae.onap.org", FakeReq(), "unit test xer") diff --git a/app/app/tox.ini b/app/app/tox.ini deleted file mode 100644 index 40fa3b3..0000000 --- a/app/app/tox.ini +++ /dev/null @@ -1,26 +0,0 @@ -# content of: tox.ini , put in same dir as setup.py -[tox] -envlist = py36,flake8 - -[testenv] -deps= - pytest - coverage - pytest-cov -setenv = - CONSUL_HOST = 8.8.8.8 - HOSTNAME = config_binding_service - PYTHONPATH={toxinidir} -commands= - pytest --junitxml xunit-results.xml --cov config_binding_service --cov-report xml --cov-report term --cov-fail-under=70 - coverage xml -i - -[testenv:flake8] -basepython = python3.6 -skip_install = true -deps = flake8 -commands = flake8 setup.py config_binding_service tests - -[flake8] -ignore = E501,W605 - diff --git a/app/pom.xml b/app/pom.xml deleted file mode 100644 index 3e9e65f..0000000 --- a/app/pom.xml +++ /dev/null @@ -1,80 +0,0 @@ -<?xml version="1.0"?> -<!-- -================================================================================ -Copyright (c) 2017-2019 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. -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. -============LICENSE_END========================================================= - -ECOMP is a trademark and service mark of AT&T Intellectual Property. ---> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.onap.dcaegen2.platform</groupId> - <artifactId>configbinding</artifactId> - <version>2.3.0-SNAPSHOT</version> - </parent> - - <!--- CHANGE THE FOLLOWING 3 OBJECTS for your own repo --> - <groupId>org.onap.dcaegen2.platform.configbinding</groupId> - <artifactId>app</artifactId> - <name>dcaegen2-platform-configbinding-app</name> - <version>2.3.0-SNAPSHOT</version> - <url>http://maven.apache.org</url> - - <packaging>pom</packaging> - <modules> - <module>app</module> - </modules> - - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <!-- customize the SONARQUBE URL --> - <sonar.host.url>http://localhost:9000</sonar.host.url> - <!-- taken care of in the children --> - </properties> - <build> - <finalName>${project.artifactId}-${project.version}</finalName> - <pluginManagement> - <plugins> - <plugin> - <groupId>org.codehaus.mojo</groupId> - <artifactId>exec-maven-plugin</artifactId> - <version>1.2.1</version> - <configuration> - <executable>${session.executionRootDirectory}/mvn-phase-script.sh</executable> - <environmentVariables> - <!-- make mvn properties as env for our script --> - <!-- make mvn properties as env for our script --> - <MVN_PROJECT_GROUPID>${project.groupId}</MVN_PROJECT_GROUPID> - <MVN_PROJECT_ARTIFACTID>${project.artifactId}</MVN_PROJECT_ARTIFACTID> - <MVN_PROJECT_VERSION>${project.version}</MVN_PROJECT_VERSION> - <MVN_NEXUSPROXY>${onap.nexus.url}</MVN_NEXUSPROXY> - <MVN_RAWREPO_BASEURL_UPLOAD>${onap.nexus.rawrepo.baseurl.upload}</MVN_RAWREPO_BASEURL_UPLOAD> - <MVN_RAWREPO_BASEURL_DOWNLOAD>${onap.nexus.rawrepo.baseurl.download}</MVN_RAWREPO_BASEURL_DOWNLOAD> - <MVN_RAWREPO_SERVERID>${onap.nexus.rawrepo.serverid}</MVN_RAWREPO_SERVERID> - <MVN_DOCKERREGISTRY_SNAPSHOT>${onap.nexus.dockerregistry.snapshot}</MVN_DOCKERREGISTRY_SNAPSHOT> - <MVN_DOCKERREGISTRY_RELEASE>${onap.nexus.dockerregistry.release}</MVN_DOCKERREGISTRY_RELEASE> - <MVN_DOCKERREGISTRY_SNAPSHOT_SERVERID>${onap.nexus.dockerregistry.snapshot.serverid}</MVN_DOCKERREGISTRY_SNAPSHOT_SERVERID> - <MVN_DOCKERREGISTRY_RELEASE_SERVERID>${onap.nexus.dockerregistry.release.serverid}</MVN_DOCKERREGISTRY_RELEASE_SERVERID> - <MVN_PYPISERVER_BASEURL>${onap.nexus.pypiserver.baseurl}</MVN_PYPISERVER_BASEURL> - <MVN_PYPISERVER_SERVERID>${onap.nexus.pypiserver.serverid}</MVN_PYPISERVER_SERVERID> - </environmentVariables> - </configuration> - </plugin> - </plugins> - </pluginManagement> - </build> - -</project> diff --git a/app/uwsgi.ini b/app/uwsgi.ini deleted file mode 100644 index f514897..0000000 --- a/app/uwsgi.ini +++ /dev/null @@ -1,3 +0,0 @@ -[uwsgi] -module = app.main -callable = app |