| # org.onap.dcae |
| # ================================================================================ |
| # Copyright (c) 2017 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 six, json, logging |
| # http://stackoverflow.com/questions/9623114/check-if-two-unordered-lists-are-equal |
| from collections import Counter |
| from functools import partial |
| import pytest |
| import requests |
| from discovery_client import discovery as dis |
| |
| |
| def test_get_connection_types(): |
| config = { "x": "say something", "y": 123, "z": "{{some-analytics}}" } |
| expected = [(("z", ), "some-analytics"), ] |
| actual = dis._get_connection_types(config) |
| assert Counter(expected) == Counter(actual) |
| |
| # Whitespaces ok |
| config = { "x": "say something", "y": 123, "z": "{{ some-analytics }}" } |
| expected = [(("z", ), "some-analytics"), ] |
| actual = dis._get_connection_types(config) |
| assert Counter(expected) == Counter(actual) |
| |
| # Paul wanted the ability to include version so match on more than just one |
| # subfield |
| config = { "x": "say something", "y": 123, "z": "{{1-0-0.some-analytics}}" } |
| expected = [(("z", ), "1-0-0.some-analytics"), ] |
| actual = dis._get_connection_types(config) |
| assert Counter(expected) == Counter(actual) |
| |
| # Need double parantheses |
| config = { "x": "say something", "y": 123, "z": "{some-analytics}" } |
| actual = dis._get_connection_types(config) |
| assert Counter([]) == Counter(actual) |
| |
| # Nested in dict dict |
| config = { "x": "say something", "y": 123, |
| "z": { "aa": { "bbb": "{{some-analytics}}" } } } |
| expected = [(("z", "aa", "bbb"), "some-analytics"), ] |
| actual = dis._get_connection_types(config) |
| assert Counter(expected) == Counter(actual) |
| |
| # Nested in list dict |
| config = { "x": "say something", "y": 123, |
| "z": [ "no-op", { "bbb": "{{some-analytics}}" } ] } |
| expected = [(("z", 1, "bbb"), "some-analytics"), ] |
| actual = dis._get_connection_types(config) |
| assert Counter(expected) == Counter(actual) |
| |
| # Force strings to be unicode, test for Python2 compatibility |
| config = { "x": six.u("say something"), "y": 123, |
| "z": six.u("{{some-analytics}}") } |
| expected = [(("z", ), "some-analytics"), ] |
| actual = dis._get_connection_types(config) |
| assert Counter(expected) == Counter(actual) |
| |
| |
| def test_resolve_connection_types(): |
| upstream = "b243b0b8-8a24-4f88-add7-9b530c578149.laika.foobar.rework-central.dcae.ecomp.com" |
| downstream = "839b0b31-f13d-4bfc-9adf-450d34071304.laika.foobar.rework-central.dcae.ecomp.com" |
| |
| connection_types = [("downstream-laika", "laika"),] |
| relationships = [downstream] |
| expected = [("downstream-laika", [downstream])] |
| actual = dis._resolve_connection_types(upstream, connection_types, relationships) |
| assert sorted(actual) == sorted(expected) |
| |
| # NOTE: Removed test that tested the scenario where the name stems don't |
| # match up. This name stem matching was causing grief to others so lifted the |
| # constraint. |
| |
| |
| def test_resolve_name_for_platform(): |
| def fake_lookup(fixture, service_name): |
| if service_name == fixture["ServiceName"]: |
| return [fixture] |
| |
| # Good case. Grabbed from Consul call |
| fixture = { 'Node': 'agent-one', 'ModifyIndex': 2892, 'Address': '127.0.0.1', |
| 'ServiceName': 'e9526e08-f9b8-42c4-99a3-443cd4deeac1.platform-laika.foobar.rework-central.dcae.ecomp.com', |
| 'ServicePort': 12708, 'CreateIndex': 2825, 'ServiceAddress': '196.207.143.67', |
| 'ServiceTags': [], 'ServiceEnableTagOverride': False, |
| 'ServiceID': 'e9526e08-f9b8-42c4-99a3-443cd4deeac1.platform-laika.foobar.rework-central.dcae.ecomp.com'} |
| |
| expected = ["{0}:{1}".format(fixture["ServiceAddress"], |
| fixture["ServicePort"])] |
| assert dis._resolve_name(partial(fake_lookup, fixture), fixture["ServiceName"]) == expected |
| |
| # Fail case. When Registrator is misconfigured and ServiceAddress is not set |
| fixture = { 'Node': 'agent-one', 'ModifyIndex': 2892, 'Address': '127.0.0.1', |
| 'ServiceName': 'e9526e08-f9b8-42c4-99a3-443cd4deeac1.platform-laika.foobar.rework-central.dcae.ecomp.com', |
| 'ServicePort': 12708, 'CreateIndex': 2825, 'ServiceAddress': '', |
| 'ServiceTags': [], 'ServiceEnableTagOverride': False, |
| 'ServiceID': 'e9526e08-f9b8-42c4-99a3-443cd4deeac1.platform-laika.foobar.rework-central.dcae.ecomp.com'} |
| |
| with pytest.raises(dis.DiscoveryResolvingNameError): |
| dis._resolve_name(partial(fake_lookup, fixture), fixture["ServiceName"]) |
| |
| # Fail case. When lookup just blows up for some reason |
| def fake_lookup_blows(service_name): |
| raise RuntimeError("Thar she blows") |
| |
| with pytest.raises(dis.DiscoveryResolvingNameError): |
| dis._resolve_name(fake_lookup_blows, fixture["ServiceName"]) |
| |
| |
| def test_resolve_name_for_docker(): |
| def fake_lookup(fixture, service_name): |
| if service_name == fixture["ServiceName"]: |
| return [fixture] |
| |
| # Good case. Grabbed from Consul call |
| fixture = { 'Node': 'agent-one', 'ModifyIndex': 2892, 'Address': '127.0.0.1', |
| 'ServiceName': 'e9526e08-f9b8-42c4-99a3-443cd4deeac1.laika.foobar.rework-central.dcae.ecomp.com', |
| 'ServicePort': 12708, 'CreateIndex': 2825, 'ServiceAddress': '196.207.143.67', |
| 'ServiceTags': [], 'ServiceEnableTagOverride': False, |
| 'ServiceID': 'e9526e08-f9b8-42c4-99a3-443cd4deeac1.laika.foobar.rework-central.dcae.ecomp.com'} |
| |
| expected = ["{0}:{1}".format(fixture["ServiceAddress"], |
| fixture["ServicePort"])] |
| assert dis._resolve_name(partial(fake_lookup, fixture), fixture["ServiceName"]) == expected |
| |
| # Fail case. When Registrator is misconfigured and ServiceAddress is not set |
| fixture = { 'Node': 'agent-one', 'ModifyIndex': 2892, 'Address': '127.0.0.1', |
| 'ServiceName': 'e9526e08-f9b8-42c4-99a3-443cd4deeac1.laika.foobar.rework-central.dcae.ecomp.com', |
| 'ServicePort': 12708, 'CreateIndex': 2825, 'ServiceAddress': '', |
| 'ServiceTags': [], 'ServiceEnableTagOverride': False, |
| 'ServiceID': 'e9526e08-f9b8-42c4-99a3-443cd4deeac1.laika.foobar.rework-central.dcae.ecomp.com'} |
| |
| with pytest.raises(dis.DiscoveryResolvingNameError): |
| dis._resolve_name(partial(fake_lookup, fixture), fixture["ServiceName"]) |
| |
| # Fail case. When lookup just blows up for some reason |
| def fake_lookup_blows(service_name): |
| raise RuntimeError("Thar she blows") |
| |
| with pytest.raises(dis.DiscoveryResolvingNameError): |
| dis._resolve_name(fake_lookup_blows, fixture["ServiceName"]) |
| |
| |
| def test_resolve_name_for_cdap(monkeypatch): |
| def fake_lookup(fixture, service_name): |
| if service_name == fixture["ServiceName"]: |
| return [fixture] |
| |
| # Good case. Handle CDAP apps |
| fixture = { |
| "Node":"agent-one", "Address":"10.170.2.17", |
| "ServiceID": "00b6210b71e445cdaadf76e620ebffcfhelloworldcdapappfoobardcaereworkdcaeecompcom", |
| "ServiceName": "00b6210b71e445cdaadf76e620ebffcfhelloworldcdapappfoobardcaereworkdcaeecompcom", |
| "ServiceTags":[], |
| "ServiceAddress": "196.207.143.116", |
| "ServicePort": 7777, "ServiceEnableTagOverride": False, "CreateIndex": 144733, "ModifyIndex":145169 } |
| |
| class FakeRequestsResponse(object): |
| def __init__(self, url, broker_json): |
| self.url = url |
| self.broker_json = broker_json |
| |
| def raise_for_status(self): |
| expected_broker_url = "http://{0}:{1}/application/{2}".format( |
| fixture["ServiceAddress"], fixture["ServicePort"], |
| fixture["ServiceName"]) |
| if self.url == expected_broker_url: |
| return True |
| else: |
| raise RuntimeError("Mismatching address") |
| |
| def json(self): |
| return self.broker_json |
| |
| # Simulate the call to the CDAP broker |
| broker_json = { |
| "appname":"00b6210b71e445cdaadf76e620ebffcfhelloworldcdapappfoobardcaereworkdcaeecompcom", |
| "healthcheckurl":"http://196.207.143.116:7777/application/00b6210b71e445cdaadf76e620ebffcfhelloworldcdapappfoobardcaereworkdcaeecompcom/healthcheck", |
| "metricsurl":"http://196.207.143.116:7777/application/00b6210b71e445cdaadf76e620ebffcfhelloworldcdapappfoobardcaereworkdcaeecompcom/metrics", |
| "url":"http://196.207.143.116:7777/application/00b6210b71e445cdaadf76e620ebffcfhelloworldcdapappfoobardcaereworkdcaeecompcom", |
| "connectionurl":"http://196.207.160.159:10000/v3/namespaces/default/streams/foo", |
| "serviceendpoints": "something" } |
| |
| monkeypatch.setattr(requests, "get", lambda url: FakeRequestsResponse(url, broker_json)) |
| |
| expected = [{ key: broker_json[key] |
| for key in ["connectionurl", "serviceendpoints"] }] |
| assert dis._resolve_name(partial(fake_lookup, fixture), fixture["ServiceName"]) == expected |
| |
| |
| def test_resolve_configuration_dict(monkeypatch): |
| service_name = "123.current-node-type.some-service.some-location.com" |
| target_service_name = "456.target-node-type.some-service.some-location.com" |
| |
| # Fake the Consul calls |
| |
| def fake_get_relationship(ch, service_name): |
| return [ target_service_name ] |
| |
| monkeypatch.setattr(dis, "_get_relationships_from_consul", |
| fake_get_relationship) |
| |
| fixture = [{ 'Node': 'agent-one', 'ModifyIndex': 2892, 'Address': '127.0.0.1', |
| 'ServiceName': target_service_name, |
| 'ServicePort': 12708, 'CreateIndex': 2825, 'ServiceAddress': '196.207.143.67', |
| 'ServiceTags': [], 'ServiceEnableTagOverride': False, |
| 'ServiceID': target_service_name }] |
| |
| def fake_lookup(ch, service_name): |
| return fixture |
| |
| monkeypatch.setattr(dis, "_lookup_with_consul", fake_lookup) |
| |
| # Simple config case |
| test_config = { "target-node": "{{ target-node-type }}", "other-param": 123 } |
| |
| expected = dict(test_config) |
| expected["target-node"] = ["196.207.143.67:12708"] |
| actual = dis._resolve_configuration_dict(None, service_name, test_config) |
| assert Counter(actual) == Counter(expected) |
| |
| # Nested config case |
| test_config = { "output_formats": { "target-node": "{{ target-node-type }}" }, |
| "other-param": 123 } |
| |
| expected = dict(test_config) |
| expected["output_formats"]["target-node"] = "196.207.143.67:12708" |
| actual = dis._resolve_configuration_dict(None, service_name, test_config) |
| assert Counter(actual) == Counter(expected) |
| |
| |
| def test_get_consul_host(monkeypatch): |
| with pytest.raises(dis.DiscoveryInitError): |
| dis.get_consul_hostname() |
| |
| monkeypatch.setenv("CONSUL_HOST", "i-am-consul-host") |
| assert "i-am-consul-host" == dis.get_consul_hostname() |
| |
| assert "no-i-am" == dis.get_consul_hostname("no-i-am") |