diff options
-rw-r--r-- | onap-dcae-cbs-docker-client/.gitignore | 1 | ||||
-rw-r--r-- | onap-dcae-cbs-docker-client/Changelog.md | 3 | ||||
-rw-r--r-- | onap-dcae-cbs-docker-client/README.md | 9 | ||||
-rw-r--r-- | onap-dcae-cbs-docker-client/example/README.md | 21 | ||||
-rw-r--r-- | onap-dcae-cbs-docker-client/example/testclient.py | 5 | ||||
-rw-r--r-- | onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/client.py | 11 | ||||
-rw-r--r-- | onap-dcae-cbs-docker-client/pom.xml | 4 | ||||
-rw-r--r-- | onap-dcae-cbs-docker-client/setup.py | 5 | ||||
-rw-r--r-- | onap-dcae-cbs-docker-client/tests/conftest.py | 50 | ||||
-rw-r--r-- | onap-dcae-cbs-docker-client/tests/test_client.py | 22 | ||||
-rw-r--r-- | onap-dcae-cbs-docker-client/tox.ini | 4 |
11 files changed, 100 insertions, 35 deletions
diff --git a/onap-dcae-cbs-docker-client/.gitignore b/onap-dcae-cbs-docker-client/.gitignore index 4f07413..6181519 100644 --- a/onap-dcae-cbs-docker-client/.gitignore +++ b/onap-dcae-cbs-docker-client/.gitignore @@ -1,3 +1,4 @@ +tox-local.ini .pytest_cache/ xunit-results.xml .DS_Store diff --git a/onap-dcae-cbs-docker-client/Changelog.md b/onap-dcae-cbs-docker-client/Changelog.md index d108e85..fa4764d 100644 --- a/onap-dcae-cbs-docker-client/Changelog.md +++ b/onap-dcae-cbs-docker-client/Changelog.md @@ -4,6 +4,9 @@ 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] - 6/24/2019 +* Add support for connecting to the CBS if it is running as HTTPS instead of HTTP + ## [2.0.0] - 6/19/2019 * The env variable CONFIG_BINDING_SERVICE now has a different meaning per DCAEGEN2-1537. Specifically this variable now holds a resolvable hostname for the CBS, rather than a consul lookup key * Since the API was broken anyway, the decision not to throw an exception was revisted and overturned. This was causing problems for some users, who were getting `{}` back in their configuration, but without knowing why; either the config wasn't set up, the config was set but as `{}`, or the CBS being unreachable altogether. This client library now throws native python exceptions, rather than logging and returning `{}`. The application client code can handle the exceptions, and retry if they choose. diff --git a/onap-dcae-cbs-docker-client/README.md b/onap-dcae-cbs-docker-client/README.md index 5c5c986..d38c515 100644 --- a/onap-dcae-cbs-docker-client/README.md +++ b/onap-dcae-cbs-docker-client/README.md @@ -4,16 +4,14 @@ Used for DCAE Dockerized microservices written in Python. Pulls your configurati # Client Usage -The environment that this client runs in, whether it be in Docker or "natievely", needs to have the following env variables: +The environment that this client runs in, whether it be in Docker or "natively", needs to have the following env variables: 1. `HOSTNAME` is the name of your component in Consul 2. `CONFIG_BINDING_SERVICE` a resolvable hostname to the CBS +3. If the CBS is running as HTTPS: `DCAE_CA_CERTPATH`: a path to a cacert file to verify the running CBS ## Usage in your code - >>> from onap_dcae_cbs_docker_client import client - >>> client.get_config() - >>> client.get_all() - +See the `example` folder for a simple test client. If the CBS is reachable, but your configuration key is not there, you will get a CantGetConfig exception: @@ -25,7 +23,6 @@ If the CBS is unreachable, you will get an exception: onap_dcae_cbs_docker_client.exceptions.CBSUnreachable - # Installation ## Via pip diff --git a/onap-dcae-cbs-docker-client/example/README.md b/onap-dcae-cbs-docker-client/example/README.md new file mode 100644 index 0000000..64f1b71 --- /dev/null +++ b/onap-dcae-cbs-docker-client/example/README.md @@ -0,0 +1,21 @@ +# Example +Shows example usage + +(`set -x` is fish's notation for bash's `export`) + +## No https +Example: + + set -x HOSTNAME <<yourhostname>>; set -x CONFIG_BINDING_SERVICE <<cbshost>>; python testclient.py + +## Https +The value of the environment variable `DCAE_CA_CERTPATH` must be a path to a cacert file to verify the running CBS. +The following excerpt is from the curl manpage: + + --cacert <file> + (TLS) Tells curl to use the specified certificate file to verify the peer. + The file may contain multiple CA certificates. + +Example: + + set -x HOSTNAME <<yourhostname>>; set -x CONFIG_BINDING_SERVICE <<cbshost>>; set -x DCAE_CA_CERTPATH /opt/onapcacert.pem; python testclient.py diff --git a/onap-dcae-cbs-docker-client/example/testclient.py b/onap-dcae-cbs-docker-client/example/testclient.py new file mode 100644 index 0000000..91eb7a2 --- /dev/null +++ b/onap-dcae-cbs-docker-client/example/testclient.py @@ -0,0 +1,5 @@ +from onap_dcae_cbs_docker_client import client + +client.get_config() + +client.get_all() diff --git a/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/client.py b/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/client.py index ef0dfbc..c1193d9 100644 --- a/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/client.py +++ b/onap-dcae-cbs-docker-client/onap_dcae_cbs_docker_client/client.py @@ -36,17 +36,20 @@ def _get_path(path): hostname = os.environ["HOSTNAME"] # this is the name of the component itself # in most cases, this is the K8s service name which is a resolvable DNS name # if running outside k8s, this name needs to be resolvable by DNS via other means. - cbs_resolvable_hostname = os.environ["CONFIG_BINDING_SERVICE"] + cbs_name = os.environ["CONFIG_BINDING_SERVICE"] except KeyError as e: raise ENVsMissing("Required ENV Variable {0} missing".format(e)) - # TODO: https - cbs_url = "http://{0}:10000".format(cbs_resolvable_hostname) + # See if we are using https + https_cacert = os.environ.get("DCAE_CA_CERTPATH", None) + + # Get the CBS URL. + cbs_url = "https://{0}:10443".format(cbs_name) if https_cacert else "http://{0}:10000".format(cbs_name) # get my config try: my_config_endpoint = "{0}/{1}/{2}".format(cbs_url, path, hostname) - res = requests.get(my_config_endpoint) + res = requests.get(my_config_endpoint, verify=https_cacert) if https_cacert else requests.get(my_config_endpoint) res.raise_for_status() config = res.json() logger.debug( diff --git a/onap-dcae-cbs-docker-client/pom.xml b/onap-dcae-cbs-docker-client/pom.xml index f76b872..34cf2db 100644 --- a/onap-dcae-cbs-docker-client/pom.xml +++ b/onap-dcae-cbs-docker-client/pom.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- ================================================================================ -Copyright (c) 2017 AT&T Intellectual Property. All rights reserved. +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. @@ -28,7 +28,7 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property. <groupId>org.onap.dcaegen2.utils</groupId> <artifactId>onap-dcae-cbs-docker-client</artifactId> <name>dcaegen2-utils-python-cbs-docker-client</name> - <version>2.0.0-SNAPSHOT</version> + <version>2.1.0-SNAPSHOT</version> <url>http://maven.apache.org</url> <properties> diff --git a/onap-dcae-cbs-docker-client/setup.py b/onap-dcae-cbs-docker-client/setup.py index 2f04827..77518ee 100644 --- a/onap-dcae-cbs-docker-client/setup.py +++ b/onap-dcae-cbs-docker-client/setup.py @@ -19,12 +19,11 @@ from setuptools import setup, find_packages setup( name="onap_dcae_cbs_docker_client", description="very lightweight client for a DCAE dockerized component to get it's config from the CBS", - version="2.0.0", + version="2.1.0", packages=find_packages(), author="Tommy Carpenter", author_email="tommy@research.att.com", license="Apache 2", - keywords="", - url="", + url="https://gerrit.onap.org/r/#/admin/projects/dcaegen2/utils", install_requires=["requests>= 2.0.0, < 3.0.0"], ) diff --git a/onap-dcae-cbs-docker-client/tests/conftest.py b/onap-dcae-cbs-docker-client/tests/conftest.py index 05d2eb5..b927412 100644 --- a/onap-dcae-cbs-docker-client/tests/conftest.py +++ b/onap-dcae-cbs-docker-client/tests/conftest.py @@ -33,6 +33,18 @@ class FakeResponse: return self.thejson +good_resp_all = FakeResponse( + status_code=200, + thejson={ + "config": {"key_to_your_heart": 666}, + "dti": {"some amazing": "dti stuff"}, + "policies": {"event": {"foo": "bar"}, "items": [{"foo2": "bar2"}]}, + "otherkey": {"foo3": "bar3"}, + }, +) +good_resp_conf = FakeResponse(status_code=200, thejson={"key_to_your_heart": 666}) + + @pytest.fixture def monkeyed_requests_get(): """ @@ -40,19 +52,10 @@ def monkeyed_requests_get(): """ def _monkeyed_requests_get(url): - if url == "http://config_binding_service:10000/service_component_all/mybestfrienddotcom": - return FakeResponse( - status_code=200, - thejson={ - "config": {"key_to_your_heart": 666}, - "dti": {"some amazing": "dti stuff"}, - "policies": {"event": {"foo": "bar"}, "items": [{"foo2": "bar2"}]}, - "otherkey": {"foo3": "bar3"}, - }, - ) - - elif url == "http://config_binding_service:10000/service_component/mybestfrienddotcom": - return FakeResponse(status_code=200, thejson={"key_to_your_heart": 666}) + if url == "http://config-binding-service:10000/service_component_all/testhostname": + return good_resp_all + elif url == "http://config-binding-service:10000/service_component/testhostname": + return good_resp_conf else: raise Exception("Unexpected URL {0}!".format(url)) @@ -60,14 +63,31 @@ def monkeyed_requests_get(): @pytest.fixture +def monkeyed_requests_get_https(): + """ + mock for the CBS get + """ + + def _monkeyed_requests_get_https(url, verify=""): + if url == "https://config-binding-service:10443/service_component_all/testhostname": + return good_resp_all + elif url == "https://config-binding-service:10443/service_component/testhostname": + return good_resp_conf + else: + raise Exception("Unexpected URL {0}!".format(url)) + + return _monkeyed_requests_get_https + + +@pytest.fixture def monkeyed_requests_get_404(): def _monkeyed_requests_get_404(url): """ get that pretends that key doesnt exist """ if url in [ - "http://config_binding_service:10000/service_component_all/mybestfrienddotcom", - "http://config_binding_service:10000/service_component/mybestfrienddotcom", + "http://config-binding-service:10000/service_component_all/testhostname", + "http://config-binding-service:10000/service_component/testhostname", ]: return FakeResponse(status_code=404, thejson={}) raise Exception("Unexpected URL {0}!".format(url)) diff --git a/onap-dcae-cbs-docker-client/tests/test_client.py b/onap-dcae-cbs-docker-client/tests/test_client.py index b1589c2..132ab33 100644 --- a/onap-dcae-cbs-docker-client/tests/test_client.py +++ b/onap-dcae-cbs-docker-client/tests/test_client.py @@ -18,13 +18,29 @@ from onap_dcae_cbs_docker_client.client import get_config, get_all from onap_dcae_cbs_docker_client.exceptions import CantGetConfig, CBSUnreachable, ENVsMissing -def test_config(monkeypatch, monkeyed_requests_get): +def test_http(monkeypatch, monkeyed_requests_get): monkeypatch.setattr("requests.get", monkeyed_requests_get) + assert get_config() == {"key_to_your_heart": 666} + assert get_all() == { + "config": {"key_to_your_heart": 666}, + "dti": {"some amazing": "dti stuff"}, + "policies": {"event": {"foo": "bar"}, "items": [{"foo2": "bar2"}]}, + "otherkey": {"foo3": "bar3"}, + } + + +def test_https_url(monkeypatch, monkeyed_requests_get_https): + """ + this doesn't really test https; because of all the cert stuff, + however it tests that the url gets formed correctly in the presence of this env variable + """ + monkeypatch.setattr("requests.get", monkeyed_requests_get_https) + monkeypatch.setenv("DCAE_CA_CERTPATH", "1") + + assert get_config() == {"key_to_your_heart": 666} -def test_all(monkeypatch, monkeyed_requests_get): - monkeypatch.setattr("requests.get", monkeyed_requests_get) assert get_all() == { "config": {"key_to_your_heart": 666}, "dti": {"some amazing": "dti stuff"}, diff --git a/onap-dcae-cbs-docker-client/tox.ini b/onap-dcae-cbs-docker-client/tox.ini index e5eeb43..fafebc6 100644 --- a/onap-dcae-cbs-docker-client/tox.ini +++ b/onap-dcae-cbs-docker-client/tox.ini @@ -8,8 +8,8 @@ deps= coverage pytest-cov setenv = - HOSTNAME = mybestfrienddotcom - CONFIG_BINDING_SERVICE = config_binding_service + HOSTNAME = testhostname + CONFIG_BINDING_SERVICE = config-binding-service PYTHONPATH={toxinidir} commands= |