From e0117d81950cb8fdb5e56858d11fbfab6f3766a2 Mon Sep 17 00:00:00 2001 From: Tommy Carpenter Date: Tue, 20 Feb 2018 07:47:25 -0500 Subject: Implement the new api service_component_all Change-Id: I50cc54f65023d61e1a085fdd2b13654553f7b7ad Issue-ID: DCAEGEN2-348 Signed-off-by: Tommy Carpenter --- .gitignore | 1 + Changelog.md | 5 + config_binding_service/client.py | 105 ++++++++++++-------- config_binding_service/controller.py | 19 +--- config_binding_service/swagger/swagger.yaml | 35 ++----- pom.xml | 2 +- setup.py | 2 +- tests/test_binding.py | 145 ++++++++++++++-------------- tox-local.ini | 10 +- tox.ini | 3 +- 10 files changed, 162 insertions(+), 165 deletions(-) diff --git a/.gitignore b/.gitignore index c86ccf6..4f07413 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.pytest_cache/ xunit-results.xml .DS_Store # Byte-compiled / optimized / DLL files diff --git a/Changelog.md b/Changelog.md index 7fe9f96..2da00c9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [2.0.0] +* Remove policy and DTI APIs +* Add new API that returns Config, Policy, DTI, Everything +* Test coverage 82% + ## [1.3.1] * Add more tests (Currently 75%) * Fix liscenses diff --git a/config_binding_service/client.py b/config_binding_service/client.py index a78a993..957b4be 100644 --- a/config_binding_service/client.py +++ b/config_binding_service/client.py @@ -41,31 +41,45 @@ class CantGetConfig(Exception): ### # Private Functions ### -def _consul_get_key(key): +def _consul_get_all_as_transaction(service_component_name): """ - Try to fetch a key from Consul. - No error checking here, let caller deal with it + Use Consul's transaction API to get all keys of the form service_component_name:* + Return a dict with all the values decoded """ - _logger.info("Fetching {0}".format(key)) - response = requests.get("{0}/v1/kv/{1}".format(CONSUL, key)) - response.raise_for_status() - D = json.loads(response.text)[0] - return json.loads(base64.b64decode(D["Value"]).decode("utf-8")) + payload = [ + { + "KV": { + "Verb": "get-tree", + "Key": service_component_name, + } + }] + + response = requests.put("{0}/v1/txn".format(CONSUL), + json = payload) -def _get_config_rels_dmaap(service_component_name): - #this one is critical, if we hit an error, blow up and raise to the caller - config = _consul_get_key(service_component_name) #not ok if no config - - rels = [] - dmaap = {} - try: #Not all nodes have relationships, so catch the error here and return [] if so - rels = _consul_get_key("{0}:rel".format(service_component_name)) - except requests.exceptions.HTTPError: #ok if no rels key, might just have dmaap key - pass try: - dmaap = _consul_get_key("{0}:dmaap".format(service_component_name)) - except requests.exceptions.HTTPError: #ok if no dmaap key - pass + response.raise_for_status() + except requests.exceptions.HTTPError as e: + raise CantGetConfig(e.response.status_code, e.response.text) + + res = json.loads(response.text)['Results'] + + new_res = {} + for r in res: + key = r["KV"]["Key"] + val = r["KV"]["Value"] + new_res[key] = json.loads(base64.b64decode(r["KV"]["Value"]).decode("utf-8")) + + if service_component_name not in new_res: + raise CantGetConfig(404, "") + + return new_res + +def _get_config_rels_dmaap(service_component_name): + allk = _consul_get_all_as_transaction(service_component_name) + 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): @@ -172,11 +186,7 @@ def resolve(service_component_name): """ Return the bound config of service_component_name """ - try: - config, rels, dmaap = _get_config_rels_dmaap(service_component_name) - except requests.exceptions.HTTPError as e: - raise CantGetConfig(e.response.status_code, e.response.text) - _logger.info("Fetching {0}: config={1}, rels={2}".format(service_component_name, json.dumps(config), rels)) + config, rels, dmaap = _get_config_rels_dmaap(service_component_name) return _recurse(config, rels, dmaap) def resolve_override(config, rels=[], dmaap={}): @@ -187,18 +197,33 @@ def resolve_override(config, rels=[], dmaap={}): #use deepcopy to make sure that config is not touched return _recurse(copy.deepcopy(config), rels, dmaap) -def resolve_DTI(service_component_name): - try: - config = _consul_get_key("{}:dti".format(service_component_name)) - except requests.exceptions.HTTPError as e: - #might be a 404, or could be not even able to reach consul (503?), bubble up the requests error - raise CantGetConfig(e.response.status_code, e.response.text) - return config +def resolve_all(service_component_name): + """ + Return config, DTI, and policies, and any other key (other than :dmaap and :rels) + """ + allk = _consul_get_all_as_transaction(service_component_name) + returnk = {} + + #replace the config with the resolved config + returnk["config"] = resolve(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]) + elif k == service_component_name or k.endswith(":rels") or k.endswith(":dmaap"): + pass + else: + suffix = k.split(":")[1] #this would blow up if you had a key in consul without a : but this shouldnt happen + returnk[suffix] = allk[k] + + return returnk -def resolve_policies(service_component_name): - try: - config = _consul_get_key("{}:policies".format(service_component_name)) - except requests.exceptions.HTTPError as e: - #might be a 404, or could be not even able to reach consul (503?), bubble up the requests error - raise CantGetConfig(e.response.status_code, e.response.text) - return config diff --git a/config_binding_service/controller.py b/config_binding_service/controller.py index 1841bed..4ece194 100644 --- a/config_binding_service/controller.py +++ b/config_binding_service/controller.py @@ -23,10 +23,10 @@ import json _logger = get_logger(__name__) -def dtievents(service_component_name): +def bind_all(service_component_name): try: - dti = client.resolve_DTI(service_component_name) - return Response(response=json.dumps(dti), + allk = client.resolve_all(service_component_name) + return Response(response=json.dumps(allk), status=200, mimetype="application/json") except client.CantGetConfig as e: @@ -37,19 +37,6 @@ def dtievents(service_component_name): return Response(response="Unknown error: please report", status=500) -def policies(service_component_name): - try: - dti = client.resolve_policies(service_component_name) - return Response(response=json.dumps(dti), - status=200, - mimetype="application/json") - except client.CantGetConfig as e: - return Response(status=e.code, - response=e.response) - except Exception as e: - _logger.error(e) - return Response(response="Unknown error: please report", - status=500) def bind_config_for_scn(service_component_name): try: bound = client.resolve(service_component_name) diff --git a/config_binding_service/swagger/swagger.yaml b/config_binding_service/swagger/swagger.yaml index ce6cf7d..ac7098f 100644 --- a/config_binding_service/swagger/swagger.yaml +++ b/config_binding_service/swagger/swagger.yaml @@ -20,14 +20,14 @@ --- swagger: "2.0" info: - version: "1.3.1" + version: "2.0.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 and service_component_name:rels must be keys in consul." + description: "Service Component Name. service_component_name must be a key in consul." required: true type: "string" get: @@ -40,40 +40,25 @@ paths: type: object 404: description: there is no configuration in Consul for this component - /dti/{service_component_name}: - parameters: - - name: "service_component_name" - in: "path" - description: "Service Component Name. service_component_name:dti must be a key in consul." - required: true - type: "string" - get: - description: "Returns as JSON the value for service_component_name:dti" - operationId: "config_binding_service.controller.dtievents" - responses: - 200: - description: OK; the KV value is returned as an object - schema: - type: object - 404: - description: there is no configuration in Consul for this component's DTI events - /policies/{service_component_name}: + + /service_component_all/{service_component_name}: parameters: - name: "service_component_name" in: "path" - description: "Service Component Name. service_component_name:policies must be a key in consul." + description: "Service Component Name. service_component_name must be a key in consul." required: true type: "string" get: - description: "Returns as JSON the value for service_component_name:policies" - operationId: "config_binding_service.controller.policies" + 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; the KV value is returned as an object + description: "OK; returns {config : ..., policies : ....., k : ...} for all other k in Consul" schema: type: object 404: - description: there is no configuration in Consul for this component's policies + description: there is no configuration in Consul for this component + /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" diff --git a/pom.xml b/pom.xml index a85ca40..53ec939 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property. org.onap.dcaegen2.platform configbinding dcaegen2-platform-configbinding - 1.3.2 + 2.0.0 http://maven.apache.org UTF-8 diff --git a/setup.py b/setup.py index 51e41be..96f2718 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ from pip.download import PipSession setup( name='config_binding_service', - version='1.3.2', + version='2.0.0', packages=find_packages(exclude=["tests.*", "tests"]), author = "Tommy Carpenter", author_email = "tommy@research.att.com", diff --git a/tests/test_binding.py b/tests/test_binding.py index 0e5d05a..4a7dd50 100644 --- a/tests/test_binding.py +++ b/tests/test_binding.py @@ -17,10 +17,12 @@ # ECOMP is a trademark and service mark of AT&T Intellectual Property. from config_binding_service import client, controller +from config_binding_service import get_consul_uri import pytest import json from requests.exceptions import HTTPError, RequestException from requests import Response +import base64 ##### # MONKEYPATCHES @@ -47,85 +49,50 @@ class FakeResponse(): def __init__(self, status_code, text): self.text = text self.status_code = status_code - -def monkeyed_consul_get(k): - if k == "dti_exists_test:dti": - return {"foo" : "bar"} - elif k == "dti_NOTexists_test:dti": - raise HTTPError(response = FakeResponse(text= "", status_code = 404)) - elif k == "policies_exists_test:policies": - return {"foo2" : "bar2"} - elif k == "policies_NOTexists_test:policies": - raise HTTPError(response = FakeResponse(text= "", status_code = 404)) - else: - raise Exception("BLOW UP IN FIRE") - -def monkeyed_resolve(k): - if k == "scn_NOTexists": - raise client.CantGetConfig(code = 404, response = "") - elif k == "scn_exists": - return {"foo3" : "bar3"} - elif k == "scn_exists:rel": - return ["foo"] - elif k == "scn_exists:dmaap": - return {"foo4" : "bar4"} - - elif k == "scn_exists_nord": - return {"foo5" : "bar5"} - elif k == "scn_exists_nord:rel": - raise HTTPError(response = FakeResponse(text= "", status_code = 404)) - elif k == "scn_exists_nord:dmaap": - raise HTTPError(response = FakeResponse(text= "", status_code = 404)) - - else: - raise Exception("BLOW UP IN FIRE") + def raise_for_status(self): + if self.status_code >= 400: + raise HTTPError(response=FakeResponse(404,"")) + +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 == "scn_NOTexists": + return FakeResponse(status_code=404, text="") ####### # TESTS ####### +def test_consul_get_all_as_transaction(monkeypatch): + monkeypatch.setattr('requests.put', monkeyed_requests_put) + allk = client._consul_get_all_as_transaction("test_service_component_name.unknown.unknown.unknown.dcae.onap.org") + 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'] + } + +def test_controller_allk(): + pass def test_get_config_rels_dmaap(monkeypatch): - monkeypatch.setattr('config_binding_service.client._consul_get_key', monkeyed_resolve) + monkeypatch.setattr('requests.put', monkeyed_requests_put) assert ({"foo3" : "bar3"}, ["foo"], {"foo4" : "bar4"}) == client._get_config_rels_dmaap("scn_exists") assert ({"foo5" : "bar5"}, [], {}) == client._get_config_rels_dmaap("scn_exists_nord") -def test_dti(monkeypatch): - monkeypatch.setattr('config_binding_service.client._consul_get_key', monkeyed_consul_get) - - assert client.resolve_DTI("dti_exists_test") == {"foo" : "bar"} - with pytest.raises(client.CantGetConfig): - client.resolve_DTI("dti_NOTexists_test") - - R = controller.dtievents("dti_exists_test") - assert(json.loads(R.data) == {"foo" : "bar"}) - assert(R.status_code == 200) - - R = controller.dtievents("dti_NOTexists_test") - assert(R.status_code == 404) - - R = controller.dtievents("asdfasdf") - assert(R.status_code == 500) - - -def test_policies(monkeypatch): - monkeypatch.setattr('config_binding_service.client._consul_get_key', monkeyed_consul_get) - - assert client.resolve_policies("policies_exists_test") == {"foo2" : "bar2"} - with pytest.raises(client.CantGetConfig): - client.resolve_policies("policies_NOTexists_test") - - R = controller.policies("policies_exists_test") - assert(json.loads(R.data) == {"foo2" : "bar2"}) - assert(R.status_code == 200) - - R = controller.policies("policies_NOTexists_test") - assert(R.status_code == 404) - - R = controller.policies("asdfasdf") - assert(R.status_code == 500) - def test_bind_config_for_scn(monkeypatch): - monkeypatch.setattr('config_binding_service.client.resolve', monkeyed_resolve) + monkeypatch.setattr('requests.put', monkeyed_requests_put) assert(client.resolve("scn_exists") == {"foo3" : "bar3"}) with pytest.raises(client.CantGetConfig): @@ -231,6 +198,12 @@ def test_dmaap(monkeypatch): test_bind_2 = client.resolve_override(config, dmaap={"XXX" : "ABSOLVEME"}) assert(test_bind_2 == {"TODAY IS YOUR LUCKY DAY" : "ABSOLVEME"}) +expected_config = { + "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"}} + } def test_both(monkeypatch): #test rels and http @@ -244,12 +217,34 @@ def test_both(monkeypatch): "sodeep" : {"hello" : "<>"}} } test_bind_1 = client.resolve_override(config, test_rels, test_dmaap) - expected_config = { - "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"}} - } assert(test_bind_1 == expected_config) +def test_resolve_all(monkeypatch): + monkeypatch.setattr('requests.put', monkeyed_requests_put) + allk = client.resolve_all("test_service_component_name.unknown.unknown.unknown.dcae.onap.org") + 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 allk == withstuff + + monkeypatch.setattr('config_binding_service.client._get_connection_info_from_consul', monkeyed_get_connection_info_from_consul) + allk = client.resolve_all("test_resolve_scn") + print(allk) + assert allk == {"config" : expected_config} + + R = controller.bind_all("test_service_component_name.unknown.unknown.unknown.dcae.onap.org") + assert(json.loads(R.data) == withstuff) + assert(R.status_code == 200) + + R = controller.bind_all("test_resolve_scn") + assert(json.loads(R.data) == {"config" : expected_config}) + assert(R.status_code == 200) + + R = controller.bind_all("scn_NOTexists") + assert(R.status_code == 404) + + R = controller.bind_all("asdfasdf") + assert(R.status_code == 500) + diff --git a/tox-local.ini b/tox-local.ini index 978634d..9f66177 100644 --- a/tox-local.ini +++ b/tox-local.ini @@ -1,5 +1,6 @@ +# content of: tox.ini , put in same dir as setup.py [tox] -envlist = py27,py36 +envlist = py36 [testenv] deps= @@ -7,9 +8,8 @@ deps= pytest coverage pytest-cov -setenv = +setenv = CONSUL_HOST = 8.8.8.8 HOSTNAME = config_binding_service -commands=pytest --cov {envsitepackagesdir}/config_binding_service --cov-report html - - +commands= + pytest --verbose --cov config_binding_service --cov-report=html diff --git a/tox.ini b/tox.ini index 7ba18f6..33a528b 100644 --- a/tox.ini +++ b/tox.ini @@ -8,9 +8,8 @@ deps= pytest coverage pytest-cov -setenv = +setenv = CONSUL_HOST = 8.8.8.8 HOSTNAME = config_binding_service commands= - #pytest --cov {envsitepackagesdir}/config_binding_service --cov-report=xml tests --verbose pytest --verbose --cov config_binding_service --cov-report=xml --cov-report=term tests -- cgit 1.2.3-korg