aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTommy Carpenter <tommy@research.att.com>2018-02-27 21:20:00 -0500
committerTommy Carpenter <tommy@research.att.com>2018-03-01 11:23:40 -0500
commit16841e4acee2cc31558bdaf618d68e4349c06168 (patch)
treea9bff5ca8af6256122cc0e406bac81f8fb6fba31
parent584b93a74f760beb51f973412a092533c838faeb (diff)
Add a new endpoint for getting arbitrary keys
Change-Id: I4888bf3c596bee72637a881830cef4835076bcb2 Issue-ID: DCAEGEN2-348 Signed-off-by: Tommy Carpenter <tommy@research.att.com>
-rw-r--r--Changelog.md5
-rw-r--r--Dockerfile1
-rw-r--r--config_binding_service/client.py117
-rw-r--r--config_binding_service/controller.py39
-rw-r--r--config_binding_service/swagger/swagger.yaml31
-rw-r--r--pom.xml2
-rw-r--r--requirements.txt4
-rw-r--r--setup.py18
-rw-r--r--tests/test_binding.py61
-rw-r--r--tox-local.ini1
-rw-r--r--tox.ini1
11 files changed, 197 insertions, 83 deletions
diff --git a/Changelog.md b/Changelog.md
index 2da00c9..53ccdf0 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.1.0]
+* Add a generic API for getting arbitrary keys
+* Some PEP8/Pylint compliance
+* Fix SONAR complaints
+
## [2.0.0]
* Remove policy and DTI APIs
* Add new API that returns Config, Policy, DTI, Everything
diff --git a/Dockerfile b/Dockerfile
index 6ae7150..1163e9f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -7,7 +7,6 @@ ADD . /tmp
RUN pip install --upgrade pip
#do the install
WORKDIR /tmp
-RUN pip install -r requirements.txt
RUN pip install -e .
EXPOSE 10000
diff --git a/config_binding_service/client.py b/config_binding_service/client.py
index 957b4be..8facf35 100644
--- a/config_binding_service/client.py
+++ b/config_binding_service/client.py
@@ -17,13 +17,13 @@
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
import re
-import requests
-import copy
+from functools import partial, reduce
import base64
+import copy
import json
+import requests
import six
from config_binding_service import get_consul_uri, get_logger
-from functools import partial, reduce
_logger = get_logger(__name__)
CONSUL = get_consul_uri()
@@ -34,13 +34,31 @@ 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):
"""
Use Consul's transaction API to get all keys of the form service_component_name:*
@@ -54,27 +72,26 @@ def _consul_get_all_as_transaction(service_component_name):
}
}]
- response = requests.put("{0}/v1/txn".format(CONSUL),
- json = payload)
+ response = requests.put("{0}/v1/txn".format(CONSUL), json=payload)
try:
response.raise_for_status()
- except requests.exceptions.HTTPError as e:
- raise CantGetConfig(e.response.status_code, e.response.text)
+ except requests.exceptions.HTTPError as exc:
+ raise CantGetConfig(exc.response.status_code, exc.response.text)
- res = json.loads(response.text)['Results']
+ result = 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"))
+ for res in result:
+ key = res["KV"]["Key"]
+ new_res[key] = json.loads(base64.b64decode(res["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]
@@ -82,6 +99,7 @@ def _get_config_rels_dmaap(service_component_name):
dmaap = allk.get(service_component_name + ":dmaap", {})
return config, rels, dmaap
+
def _get_connection_info_from_consul(service_component_name):
"""
Call consul's catalog
@@ -97,19 +115,18 @@ def _get_connection_info_from_consul(service_component_name):
if services == []:
_logger.info("Warning: config and rels keys were both valid, but there is no component named {0} registered in Consul!".format(service_component_name))
return None #later will get filtered out
- else:
- ip = services[0]["ServiceAddress"]
- port = services[0]["ServicePort"]
- if "cdap_app" in service_component_name:
- redirectish_url = "http://{0}:{1}/application/{2}".format(ip, port, service_component_name)
- _logger.info("component is a CDAP application; trying the broker redirect on {0}".format(redirectish_url))
- r = requests.get(redirectish_url)
- r.raise_for_status()
- details = r.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"] }
- else:
- return "{0}:{1}".format(ip, port)
+ 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)
+ _logger.info("component is a CDAP application; trying the broker redirect on {0}".format(redirectish_url))
+ 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):
"""
@@ -118,11 +135,12 @@ def _replace_rels_template(rels, template_identifier):
it resolve to the empty list. So, it does resolve it to empty list.
"""
returnl = []
- for r in rels:
- if template_identifier in r and template_identifier is not "":
- returnl.append(r)
+ for rel in rels:
+ if template_identifier in rel and template_identifier is not "":
+ 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)))
+ return list(filter(lambda x: x is not None, map(_get_connection_info_from_consul, returnl)))
+
def _replace_dmaap_template(dmaap, template_identifier):
"""
@@ -131,6 +149,7 @@ def _replace_dmaap_template(dmaap, template_identifier):
"""
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.
@@ -145,7 +164,7 @@ def _replace_value(v, rels, dmaap):
if match_on_rels:
template_identifier = match_on_rels.groups()[0].strip() #now holds just x,.. of {{x,...}}
rtpartial = partial(_replace_rels_template, rels)
- return reduce(lambda a,b: a+b, map(rtpartial, template_identifier.split(",")), [])
+ 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()
@@ -159,6 +178,7 @@ def _replace_value(v, rels, dmaap):
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.
@@ -169,19 +189,21 @@ def _recurse(config, rels, dmaap):
"""
if isinstance(config, list):
return [_recurse(item, rels, dmaap) for item in config]
- elif isinstance(config,dict):
+ if isinstance(config, dict):
for key in config:
config[key] = _recurse(config[key], rels, dmaap)
return config
- elif isinstance(config, six.string_types):
+ if isinstance(config, six.string_types):
return _replace_value(config, rels, dmaap)
- else:
- #not a dict, not a list, not a string, nothing to do.
- return config
+ #not a dict, not a list, not a string, nothing to do.
+ return config
+
#########
# PUBLIC API
#########
+
+
def resolve(service_component_name):
"""
Return the bound config of service_component_name
@@ -189,6 +211,7 @@ def resolve(service_component_name):
config, rels, dmaap = _get_config_rels_dmaap(service_component_name)
return _recurse(config, rels, dmaap)
+
def resolve_override(config, rels=[], dmaap={}):
"""
Explicitly take in a config, rels, dmaap and try to resolve it.
@@ -197,9 +220,10 @@ 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_all(service_component_name):
"""
- Return config, DTI, and policies, and any other key (other than :dmaap and :rels)
+ Return config, policies, and any other k such that service_component_name:k exists (other than :dmaap and :rels)
"""
allk = _consul_get_all_as_transaction(service_component_name)
returnk = {}
@@ -219,11 +243,24 @@ def resolve_all(service_component_name):
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]
+ if not(k == service_component_name or k.endswith(":rels") or k.endswith(":dmaap")):
+ 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 get_key(key, service_component_name):
+ """
+ Try to fetch a key k from Consul of the form service_component_name:k
+ """
+ if key == "policies":
+ raise BadRequest(":policies is a complex folder and should be retrieved using the service_component_all API")
+ response = requests.get("{0}/v1/kv/{1}:{2}".format(CONSUL, service_component_name, key))
+ 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/config_binding_service/controller.py b/config_binding_service/controller.py
index 4ece194..dbdb57b 100644
--- a/config_binding_service/controller.py
+++ b/config_binding_service/controller.py
@@ -16,13 +16,14 @@
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
-from config_binding_service import client, get_consul_uri, get_logger
import requests
-from flask import request, Response
+from flask import Response
import json
+from config_binding_service import client, get_consul_uri, get_logger
_logger = get_logger(__name__)
+
def bind_all(service_component_name):
try:
allk = client.resolve_all(service_component_name)
@@ -37,12 +38,13 @@ def bind_all(service_component_name):
return Response(response="Unknown error: please report",
status=500)
+
def bind_config_for_scn(service_component_name):
try:
bound = client.resolve(service_component_name)
return Response(response=json.dumps(bound),
- status=200,
- mimetype="application/json")
+ status=200,
+ mimetype="application/json")
except client.CantGetConfig as e:
return Response(status=e.code,
response=e.response)
@@ -51,14 +53,33 @@ def bind_config_for_scn(service_component_name):
return Response(response="Please report this error",
status=500)
+
+def get_key(key, service_component_name):
+ try:
+ bound = client.get_key(key, service_component_name)
+ return Response(response=json.dumps(bound),
+ status=200,
+ mimetype="application/json")
+ except client.CantGetConfig as e:
+ return Response(status=e.code,
+ response=e.response)
+ except client.BadRequest as exc:
+ return Response(status=exc.code,
+ response=exc.response,
+ mimetype="text/plain")
+ except Exception as e: #should never happen...
+ _logger.error(e)
+ return Response(response="Please report this error",
+ status=500)
+
+
def healthcheck():
#got this far, I must be alive... check my connection to Consul by checking myself
CONSUL = get_consul_uri()
res = requests.get("{0}/v1/catalog/service/config_binding_service".format(CONSUL))
if res.status_code == 200:
- return Response(response = "CBS is alive and Consul connection OK",
- status = 200)
+ return Response(response="CBS is alive and Consul connection OK",
+ status=200)
else:
- return Response(response = "CBS is alive but cannot reach Consul",
- status = 503)
-
+ return Response(response="CBS is alive but cannot reach Consul",
+ status=503)
diff --git a/config_binding_service/swagger/swagger.yaml b/config_binding_service/swagger/swagger.yaml
index ac7098f..cfe0944 100644
--- a/config_binding_service/swagger/swagger.yaml
+++ b/config_binding_service/swagger/swagger.yaml
@@ -20,7 +20,7 @@
---
swagger: "2.0"
info:
- version: "2.0.0"
+ version: "2.1.0"
title: "Config Binding Service"
paths:
/service_component/{service_component_name}:
@@ -59,6 +59,35 @@ paths:
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
+ type: "string"
+ - name: "service_component_name"
+ in: "path"
+ description: "Service Component Name."
+ required: true
+ 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"
+ schema:
+ type: object
+ 404:
+ description: "key does not exist"
+ schema:
+ type: string
+ 400:
+ description: "bad request. Currently this is only returned on :policies, which is a complex object, and should be gotten through service_component_all"
+ 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"
diff --git a/pom.xml b/pom.xml
index a007a46..be972e7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property.
<groupId>org.onap.dcaegen2.platform</groupId>
<artifactId>configbinding</artifactId>
<name>dcaegen2-platform-configbinding</name>
- <version>2.0.0</version>
+ <version>2.1.0</version>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 9aeb224..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Flask==0.12.2
-connexion==1.1.12
-requests==2.18.2
-six==1.10.0
diff --git a/setup.py b/setup.py
index 96f2718..2c4fd2e 100644
--- a/setup.py
+++ b/setup.py
@@ -16,21 +16,19 @@
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
-import os
from setuptools import setup, find_packages
-from pip.req import parse_requirements
-from pip.download import PipSession
setup(
name='config_binding_service',
- version='2.0.0',
+ version='2.1.0',
packages=find_packages(exclude=["tests.*", "tests"]),
- author = "Tommy Carpenter",
- author_email = "tommy@research.att.com",
+ author="Tommy Carpenter",
+ author_email="tommy@research.att.com",
description='Service to fetch and bind configurations',
- license = "",
- keywords = "",
- url = "https://gerrit.onap.org/r/#/admin/projects/dcaegen2/platform/configbinding",
+ license="",
+ keywords="",
+ url="https://gerrit.onap.org/r/#/admin/projects/dcaegen2/platform/configbinding",
zip_safe=False,
- scripts = ["bin/run.py"]
+ scripts=["bin/run.py"],
+ install_requires=["requests", "Flask", "connexion", "six"]
)
diff --git a/tests/test_binding.py b/tests/test_binding.py
index 4a7dd50..3f51285 100644
--- a/tests/test_binding.py
+++ b/tests/test_binding.py
@@ -16,18 +16,18 @@
#
# 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
+from requests.exceptions import HTTPError
+from config_binding_service import get_consul_uri
+from config_binding_service import client, controller
+
#####
# MONKEYPATCHES
#####
+
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":
@@ -45,31 +45,44 @@ def monkeyed_get_connection_info_from_consul(service_component_name):
broker_port = 444
return "http://{0}:{1}/application/{2}".format(broker_ip, broker_port, service_component_name)
+
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,""))
+ raise HTTPError(response=FakeResponse(404, ""))
+
+
+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="")
+
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}')
+ 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}')
+ 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}')
+ 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}')
+ 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")
@@ -83,18 +96,17 @@ def test_consul_get_all_as_transaction(monkeypatch):
'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('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")
+ 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_bind_config_for_scn(monkeypatch):
monkeypatch.setattr('requests.put', monkeyed_requests_put)
- assert(client.resolve("scn_exists") == {"foo3" : "bar3"})
+ assert(client.resolve("scn_exists") == {"foo3": "bar3"})
with pytest.raises(client.CantGetConfig):
client.resolve("scn_NOTexists")
@@ -108,6 +120,25 @@ def test_bind_config_for_scn(monkeypatch):
R = controller.bind_config_for_scn("asdfasdf")
assert(R.status_code == 500)
+
+def test_generic(monkeypatch):
+ monkeypatch.setattr('requests.put', monkeyed_requests_put)
+ monkeypatch.setattr('requests.get', monkeyed_requests_get)
+ assert client.get_key("dti", "test_service_component_name.unknown.unknown.unknown.dcae.onap.org") == json.loads('{"my": "dti"}')
+ with pytest.raises(client.CantGetConfig):
+ client.get_key("nokeyforyou", "test_service_component_name.unknown.unknown.unknown.dcae.onap.org")
+
+ R = controller.get_key("dti", "test_service_component_name.unknown.unknown.unknown.dcae.onap.org")
+ assert(json.loads(R.data) == {"my": "dti"})
+ assert(R.status_code == 200)
+
+ R = controller.get_key("nokeyforyou", "test_service_component_name.unknown.unknown.unknown.dcae.onap.org")
+ assert(R.status_code == 404)
+
+ R = controller.get_key("policies", "test_service_component_name.unknown.unknown.unknown.dcae.onap.org")
+ assert(R.status_code == 400)
+
+
def test_bad_config_http():
test_config = {'yeahhhhh' : "{{}}"}
test_rels = ["testing_bravo.somedomain.com"]
diff --git a/tox-local.ini b/tox-local.ini
index 9f66177..52b7916 100644
--- a/tox-local.ini
+++ b/tox-local.ini
@@ -4,7 +4,6 @@ envlist = py36
[testenv]
deps=
- -rrequirements.txt
pytest
coverage
pytest-cov
diff --git a/tox.ini b/tox.ini
index 3c0caf3..418de62 100644
--- a/tox.ini
+++ b/tox.ini
@@ -4,7 +4,6 @@ envlist = py36
[testenv]
deps=
- -rrequirements.txt
pytest
coverage
pytest-cov