From c698e66797bad69b4c77b26b487bf8322989beb0 Mon Sep 17 00:00:00 2001 From: Michael Hwang Date: Tue, 12 Nov 2019 16:04:20 -0500 Subject: Copy dcae-cli->onboardingapi, copy component specs Issue-ID: DCAEGEN2-1860 Change-Id: I4805398c76479fad51cbdb74470ccc8f706ce9dc Signed-off-by: Michael Hwang --- .../dcae_cli/util/tests/test_cdap_util.py | 93 +++++ .../dcae_cli/util/tests/test_config.py | 137 +++++++ .../dcae_cli/util/tests/test_discovery.py | 447 +++++++++++++++++++++ .../dcae_cli/util/tests/test_dmaap.py | 259 ++++++++++++ .../dcae_cli/util/tests/test_docker_util.py | 62 +++ .../dcae_cli/util/tests/test_inputs.py | 37 ++ .../dcae_cli/util/tests/test_profiles.py | 162 ++++++++ .../dcae_cli/util/tests/test_remove.py | 24 ++ .../dcae_cli/util/tests/test_undeploy.py | 62 +++ 9 files changed, 1283 insertions(+) create mode 100644 mod/onboardingapi/dcae_cli/util/tests/test_cdap_util.py create mode 100644 mod/onboardingapi/dcae_cli/util/tests/test_config.py create mode 100644 mod/onboardingapi/dcae_cli/util/tests/test_discovery.py create mode 100644 mod/onboardingapi/dcae_cli/util/tests/test_dmaap.py create mode 100644 mod/onboardingapi/dcae_cli/util/tests/test_docker_util.py create mode 100644 mod/onboardingapi/dcae_cli/util/tests/test_inputs.py create mode 100644 mod/onboardingapi/dcae_cli/util/tests/test_profiles.py create mode 100644 mod/onboardingapi/dcae_cli/util/tests/test_remove.py create mode 100644 mod/onboardingapi/dcae_cli/util/tests/test_undeploy.py (limited to 'mod/onboardingapi/dcae_cli/util/tests') diff --git a/mod/onboardingapi/dcae_cli/util/tests/test_cdap_util.py b/mod/onboardingapi/dcae_cli/util/tests/test_cdap_util.py new file mode 100644 index 0000000..9282691 --- /dev/null +++ b/mod/onboardingapi/dcae_cli/util/tests/test_cdap_util.py @@ -0,0 +1,93 @@ +# ============LICENSE_START======================================================= +# 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. + +from dcae_cli.util.cdap_util import _merge_spec_config_into_broker_put, normalize_cdap_params + + +def test_normalize_cdap_params(): + spec = {"parameters" : {}} + normalized = normalize_cdap_params(spec) + assert normalized == {"app_preferences" : {}, + "app_config" : {}, + "program_preferences" : []} + +def test_cdap_util(): + """ + Tests both _merge_spec_config_into_broker_put and normalize_cdap_params + """ + jar = "bahphomet.com/nexus/doomsday.jar" + config = { + "artifact_name" : "testname", + "artifact_version" : "6.6.6", + "streamname" : "stream", + "programs" : [{"program_type" : "flows", "program_id" : "flow_id"}], + "namespace" : "underworld" + } + spec = { + "self": { + "version": "6.6.6", + "description": "description", + "component_type": "cdap", + "name": "name" + }, + "parameters" : { + "app_preferences" : [{"name" : "he", "description" : "", "value" : "shall rise"}], + "program_preferences" : [{"program_type" : "flows", "program_id" : "flow_id", "program_pref" : [{"name": "foo", "description" : "", "value" : "bar"}]}] + }, + + "streams": { + "publishes": [], + "subscribes" : [] + }, + "services": { + "calls" : [], + 'provides': [ + {"request": {"format" : 'std.format_one', "version" : "1.0.0"}, + "response" : {"format" : "std.format_two", "version" : "1.5.0"}, + "service_name" : "baphomet", + "service_endpoint" : "rises", + "verb" : "GET"} + ] + }, + } + parsed_parameters = normalize_cdap_params(spec) + templated_conf = {"streams_publishes":{}, "streams_subscribes": {}, + "services_calls": {}} #TODO: Incorporate a test templated_conf + broker_put = _merge_spec_config_into_broker_put(jar, config, spec, parsed_parameters, templated_conf) + + expected = { + "app_config": {"services_calls" : {}, + "streams_publishes" : {}, + "streams_subscribes": {} + }, + "app_preferences": {"he" : "shall rise"}, + "artifact_name" : "testname", + "artifact_version" : "6.6.6", + "jar_url": "bahphomet.com/nexus/doomsday.jar", + "namespace": "underworld", + "program_preferences" : [{"program_type" : "flows", "program_id" : "flow_id", "program_pref" : {"foo" : "bar"}}], + "programs" : [{"program_type" : "flows", "program_id" : "flow_id"}], + "service_component_type": "cdap", + "services": [{"service_name" : "baphomet", "service_endpoint" : "rises", "endpoint_method" : "GET"}], + "streamname": "stream", + "cdap_application_type" : "program-flowlet" + } + + assert broker_put == expected diff --git a/mod/onboardingapi/dcae_cli/util/tests/test_config.py b/mod/onboardingapi/dcae_cli/util/tests/test_config.py new file mode 100644 index 0000000..3b4cd6e --- /dev/null +++ b/mod/onboardingapi/dcae_cli/util/tests/test_config.py @@ -0,0 +1,137 @@ +# ============LICENSE_START======================================================= +# 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. + +# -*- coding: utf-8 -*- +""" +Tests the config functionality +""" +import os, json +from functools import partial +from mock import patch + +import pytest +import click + +import dcae_cli +from dcae_cli.util import config, write_pref +from dcae_cli.util.config import get_app_dir, get_config, get_config_path + + +def test_no_config(monkeypatch, tmpdir): + '''Tests the creation and initialization of a config on a clean install''' + monkeypatch.setattr(click, "get_app_dir", lambda app: str(tmpdir.realpath())) + + mock_config = {'user': 'mock-user'} + + config_file = tmpdir.join("config.json") + config_file.write(json.dumps(mock_config)) + + assert get_config() == mock_config + + +def test_init_config_user(monkeypatch): + good_case = "abc123" + values = [ good_case, "d-e-f", "g*h*i", "j k l" ] + + def fake_input(values, message, type="red"): + return values.pop() + + monkeypatch.setattr(click, 'prompt', partial(fake_input, values)) + assert config._init_config_user() == good_case + + +def test_init_config(monkeypatch): + monkeypatch.setattr(config, '_init_config_user', lambda: "bigmama") + monkeypatch.setattr(config, '_init_config_server_url', + lambda: "http://some-nexus-in-the-sky.com") + monkeypatch.setattr(dcae_cli.util, 'fetch_file_from_web', + lambda server_url, path: { "db_url": "conn" }) + monkeypatch.setattr("dcae_cli._version.__version__", "2.X.X") + + expected = {'cli_version': '2.X.X', 'user': 'bigmama', 'db_url': 'conn', + 'server_url': 'http://some-nexus-in-the-sky.com', + 'active_profile': 'default' } + assert expected == config._init_config() + + # Test using of db fallback + + monkeypatch.setattr(dcae_cli.util, 'fetch_file_from_web', + lambda server_url, path: { "db_url": "" }) + + db_url = "postgresql://king:of@mountain:5432/dcae_onboarding_db" + + def fake_init_config_db_url(): + return db_url + + monkeypatch.setattr(config, "_init_config_db_url", + fake_init_config_db_url) + + assert db_url == config._init_config()["db_url"] + + monkeypatch.setattr(dcae_cli.util, 'fetch_file_from_web', + lambda server_url, path: {}) + + assert db_url == config._init_config()["db_url"] + + # Simulate error trying to fetch + + def fetch_simulate_error(server_url, path): + raise RuntimeError("Simulated error") + + monkeypatch.setattr(dcae_cli.util, 'fetch_file_from_web', + fetch_simulate_error) + # Case when user opts out of manually setting up + monkeypatch.setattr(click, "confirm", lambda msg: False) + + with pytest.raises(config.ConfigurationInitError): + config._init_config() + + +def test_should_force_reinit(): + bad_config = {} + assert config.should_force_reinit(bad_config) == True + + old_config = { "cli_version": "1.0.0" } + assert config.should_force_reinit(old_config) == True + + uptodate_config = { "cli_version": "2.0.0" } + assert config.should_force_reinit(uptodate_config) == False + + +def test_reinit_config(monkeypatch, tmpdir): + monkeypatch.setattr(click, "get_app_dir", lambda app: str(tmpdir.realpath())) + + new_config = { "user": "ninny", "db_url": "some-db" } + + def init(): + return new_config + + assert config._reinit_config(init) == new_config + + old_config = { "user": "super", "db_url": "other-db", "hidden": "yo" } + write_pref(old_config, get_config_path()) + + new_config["hidden"] = "yo" + assert config._reinit_config(init) == new_config + + +if __name__ == '__main__': + '''Test area''' + pytest.main([__file__, ]) diff --git a/mod/onboardingapi/dcae_cli/util/tests/test_discovery.py b/mod/onboardingapi/dcae_cli/util/tests/test_discovery.py new file mode 100644 index 0000000..2148ea3 --- /dev/null +++ b/mod/onboardingapi/dcae_cli/util/tests/test_discovery.py @@ -0,0 +1,447 @@ +# ============LICENSE_START======================================================= +# org.onap.dcae +# ================================================================================ +# 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. + +# -*- coding: utf-8 -*- +''' +Provides tests for the discovery module +''' +import json +from functools import partial +from copy import deepcopy + +import pytest + +from dcae_cli.util import discovery as dis +from dcae_cli.util.discovery import create_config, Consul, config_context, DiscoveryNoDownstreamComponentError + + +user = 'bob' +cname = 'asimov.test_comp' +cver = '0.0.0' +inst_pref = 'abc123' +params = {'param0': 12345} + + +def test_create_config(): + ''' + Test explanation: + 1. param1 in the component spec has 2 compatible component types, comp1 and comp2. however infrastructure + support only allows for 1. thus comp2 shouldn't make it to the rels. + 2. comp1 has two instances, so both should make it to the rels + 3. param2 is compatible with comp3, but there are no comp3 instances. thus it's missing from rels. + ''' + expected_ckey = 'bob.abc123.0-0-0.asimov-test_comp' + expected_conf = {'param1': '{{1-1-1.foo-bar-comp1}}', 'param0': 12345, 'param2': '{{3-3-3.foo-bar-comp3}}'} + expected_rkey = 'bob.abc123.0-0-0.asimov-test_comp:rel' + expected_rels = ['bob.aaa111.1-1-1.foo-bar-comp1.suffix', + 'bob.bbb222.1-1-1.foo-bar-comp1.suffix', + 'bob.ddd444.3-3-3.foo-bar-comp3.suffix'] + expected_dmaap_key = 'bob.abc123.0-0-0.asimov-test_comp:dmaap' + expected_dmaap_map = {} + + interface_map = {'param1': [('foo.bar.comp1', '1.1.1'), + ('foo.bar.comp2', '2.2.2')], + 'param2': [('foo.bar.comp3', '3.3.3')] + } + instance_map = {('foo.bar.comp1', '1.1.1'): ['bob.aaa111.1-1-1.foo-bar-comp1.suffix', + 'bob.bbb222.1-1-1.foo-bar-comp1.suffix'], + ('foo.bar.comp2', '2.2.2'): ['bob.ccc333.2-2-2.foo-bar-comp2.suffix'], + ('foo.bar.comp3', '3.3.3'): ['bob.ddd444.3-3-3.foo-bar-comp3.suffix']} + + ckey, conf, rkey, rels, dmaap_key, dmaap_map = create_config(user, cname, cver, + params, interface_map, instance_map, expected_dmaap_map, inst_pref) + + assert ckey == expected_ckey + assert conf == expected_conf + assert rkey == expected_rkey + assert sorted(rels) == sorted(expected_rels) + assert dmaap_key == expected_dmaap_key + assert dmaap_map == expected_dmaap_map + + # + # Fail cases: When a downstream dependency does not exist + # + + # (1) Case when there's no actual instance + instance_map_missing_3 = deepcopy(instance_map) + instance_map_missing_3[('foo.bar.comp3', '3.3.3')] = [] + + with pytest.raises(DiscoveryNoDownstreamComponentError): + create_config(user, cname, cver, params, interface_map, instance_map_missing_3, + expected_dmaap_map, inst_pref) + + # (2) Case when there's no existence in instance_map + interface_map_extra = deepcopy(interface_map) + interface_map_extra["param_not_exist"] = [] + + with pytest.raises(DiscoveryNoDownstreamComponentError): + create_config(user, cname, cver, params, interface_map_extra, instance_map, + expected_dmaap_map, inst_pref) + + # + # Force the fail cases to succeed + # + + # (1) + ckey, conf, rkey, rels, dmaap_key, dmaap_map = create_config(user, cname, cver, + params, interface_map, instance_map_missing_3, expected_dmaap_map, inst_pref, + force=True) + + assert ckey == expected_ckey + assert conf == expected_conf + assert rkey == expected_rkey + # Remove the foo.bar.comp3:3.3.3 instance because we are simulating when that + # instance does not exist + assert sorted(rels) == sorted(expected_rels[:2]) + assert dmaap_key == expected_dmaap_key + assert dmaap_map == expected_dmaap_map + + # (2) + ckey, conf, rkey, rels, dmaap_key, dmaap_map = create_config(user, cname, cver, + params, interface_map_extra, instance_map, expected_dmaap_map, inst_pref, + force=True) + + expected_conf["param_not_exist"] = "{{}}" + + assert ckey == expected_ckey + assert conf == expected_conf + assert rkey == expected_rkey + assert sorted(rels) == sorted(expected_rels) + assert dmaap_key == expected_dmaap_key + assert dmaap_map == expected_dmaap_map + + # + # Test differnt dashes scenario + # + + # Component has been added with dashes but the instance comes back with dots + # because the discovery layer always brings back instances with dots + interface_map_dashes = {'param1': [('foo-bar-comp1', '1.1.1')]} + instance_map_dashes = {('foo.bar.comp1', '1.1.1'): + ['bob.aaa111.1-1-1.foo-bar-comp1.suffix']} + + with pytest.raises(DiscoveryNoDownstreamComponentError): + create_config(user, cname, cver, params, interface_map_dashes, instance_map_dashes, + expected_dmaap_map, inst_pref) + + # The fix in v2.3.2 was to have the caller to send in instances with dots and + # with dashes + instance_map_dashes = { + ('foo.bar.comp1', '1.1.1'): ['bob.aaa111.1-1-1.foo-bar-comp1.suffix'], + ('foo-bar-comp1', '1.1.1'): ['bob.aaa111.1-1-1.foo-bar-comp1.suffix'] } + + ckey, conf, rkey, rels, dmaap_key, dmaap_map = create_config(user, cname, cver, + params, interface_map_dashes, instance_map_dashes, expected_dmaap_map, inst_pref) + + # The expecteds have changed because the inputs have been narrowed to just + # one + assert ckey == expected_ckey + assert conf == {'param1': '{{1-1-1.foo-bar-comp1}}', 'param0': 12345} + assert rkey == expected_rkey + assert sorted(rels) == sorted(['bob.aaa111.1-1-1.foo-bar-comp1.suffix']) + assert dmaap_key == expected_dmaap_key + assert dmaap_map == expected_dmaap_map + + # Pass in a non-empty dmaap map + dmaap_map_input = { "some-config-key": { "type": "message_router", + "dmaap_info": {"topic_url": "http://some-topic-url.com/abc"} } } + del expected_conf["param_not_exist"] + expected_conf["some-config-key"] = { "type": "message_router", + "dmaap_info": "<>" } + + ckey, conf, rkey, rels, dmaap_key, dmaap_map = create_config(user, cname, cver, + params, interface_map, instance_map, dmaap_map_input, inst_pref) + + assert ckey == expected_ckey + assert conf == expected_conf + assert rkey == expected_rkey + assert sorted(rels) == sorted(expected_rels) + assert dmaap_key == expected_dmaap_key + assert dmaap_map == {'some-config-key': {'topic_url': 'http://some-topic-url.com/abc'}} + + +@pytest.mark.skip(reason="Not a pure unit test") +def test_config_context(mock_cli_config): + interface_map = {'param1': [('foo.bar.comp1', '1.1.1'), + ('foo.bar.comp2', '2.2.2')], + 'param2': [('foo.bar.comp3', '3.3.3')] + } + instance_map = {('foo.bar.comp1', '1.1.1'): ['bob.aaa111.1-1-1.foo-bar-comp1.suffix', + 'bob.bbb222.1-1-1.foo-bar-comp1.suffix'], + ('foo.bar.comp2', '2.2.2'): ['bob.ccc333.2-2-2.foo-bar-comp2.suffix'], + ('foo.bar.comp3', '3.3.3'): ['bob.ddd444.3-3-3.foo-bar-comp3.suffix']} + + config_key_map = {"param1": {"group": "streams_publishes", "type": "http"}, + "param2": {"group": "services_calls", "type": "http"}} + + ckey = 'bob.abc123.0-0-0.asimov-test_comp' + rkey = 'bob.abc123.0-0-0.asimov-test_comp:rel' + expected_conf = {"streams_publishes": {'param1': '{{1-1-1.foo-bar-comp1}}'}, + 'param0': 12345, "streams_subscribes": {}, + "services_calls": {'param2': '{{3-3-3.foo-bar-comp3}}'}} + expected_rels = ['bob.aaa111.1-1-1.foo-bar-comp1.suffix', + 'bob.bbb222.1-1-1.foo-bar-comp1.suffix', + 'bob.ddd444.3-3-3.foo-bar-comp3.suffix'] + + c = Consul(dis.default_consul_host()) + with config_context(user, cname, cver, params, interface_map, instance_map, + config_key_map, instance_prefix=inst_pref) as (instance,_): + assert json.loads(c.kv.get(ckey)[1]['Value'].decode('utf-8')) == expected_conf + assert sorted(json.loads(c.kv.get(rkey)[1]['Value'].decode('utf-8'))) \ + == sorted(expected_rels) + assert instance == ckey + + assert c.kv.get(ckey)[1] is None + assert c.kv.get(rkey)[1] is None + + # Fail case: When a downstream dependency does not exist + interface_map_extra = deepcopy(interface_map) + interface_map_extra["param_not_exist"] = [] + + with pytest.raises(DiscoveryNoDownstreamComponentError): + with config_context(user, cname, cver, params, interface_map_extra, + instance_map, config_key_map, instance_prefix=inst_pref) as (instance,_): + pass + + # Force fail case to succeed + expected_conf["param_not_exist"] = "{{}}" + + with config_context(user, cname, cver, params, interface_map_extra, + instance_map, config_key_map, instance_prefix=inst_pref, + force_config=True) as (instance,_): + assert json.loads(c.kv.get(ckey)[1]['Value'].decode('utf-8')) == expected_conf + assert sorted(json.loads(c.kv.get(rkey)[1]['Value'].decode('utf-8'))) \ + == sorted(expected_rels) + assert instance == ckey + + +def test_inst_regex(): + ckey = 'bob.abc123.0-0-0.asimov-test_comp' + match = dis._inst_re.match(ckey) + assert match != None + + # Big version case + + ckey = 'bob.abc123.100-100-100.asimov-test_comp' + match = dis._inst_re.match(ckey) + assert match != None + + +def test_is_healthy_pure(): + component = { 'CreateIndex': 204546, 'Flags': 0, + 'Key': 'mike.21fbcabd-fac1-4b9b-9d18-2f624bfa44a5.0-4-0.sandbox-platform-dummy_subscriber', 'LockIndex': 0, 'ModifyIndex': 204546, + 'Value': b'{}' } + + component_health_good = ('262892', + [{'Checks': [{'CheckID': 'serfHealth', + 'CreateIndex': 3, + 'ModifyIndex': 3, + 'Name': 'Serf Health Status', + 'Node': 'agent-one', + 'Notes': '', + 'Output': 'Agent alive and reachable', + 'ServiceID': '', + 'ServiceName': '', + 'Status': 'passing'}, + {'CheckID': 'service:rework-central-swarm-master:mike.21fbcabd-fac1-4b9b-9d18-2f624bfa44a5.0-4-0.sandbox-platform-dummy_subscriber:8080', + 'CreateIndex': 204550, + 'ModifyIndex': 204551, + 'Name': 'Service ' + "'mike.21fbcabd-fac1-4b9b-9d18-2f624bfa44a5.0-4-0.sandbox-platform-dummy_subscriber' " + 'check', + 'Node': 'agent-one', + 'Notes': '', + 'Output': '', + 'ServiceID': 'rework-central-swarm-master:mike.21fbcabd-fac1-4b9b-9d18-2f624bfa44a5.0-4-0.sandbox-platform-dummy_subscriber:8080', + 'ServiceName': 'mike.21fbcabd-fac1-4b9b-9d18-2f624bfa44a5.0-4-0.sandbox-platform-dummy_subscriber', + 'Status': 'passing'}], + 'Node': {'Address': '10.170.2.17', + 'CreateIndex': 3, + 'ModifyIndex': 262877, + 'Node': 'agent-one', + 'TaggedAddresses': {'wan': '10.170.2.17'}}, + 'Service': {'Address': '196.207.170.175', + 'CreateIndex': 204550, + 'EnableTagOverride': False, + 'ID': 'rework-central-swarm-master:mike.21fbcabd-fac1-4b9b-9d18-2f624bfa44a5.0-4-0.sandbox-platform-dummy_subscriber:8080', + 'ModifyIndex': 204551, + 'Port': 33064, + 'Service': 'mike.21fbcabd-fac1-4b9b-9d18-2f624bfa44a5.0-4-0.sandbox-platform-dummy_subscriber', + 'Tags': None}}]) + + assert True == dis._is_healthy_pure(lambda name: component_health_good, component) + + # Case: Check is failing + + component_health_bad = deepcopy(component_health_good) + # NOTE: The failed status here. Not sure if this is what Consul actually sends + # but at least its not "passing" + component_health_bad[1][0]["Checks"][0]["Status"] = "failing" + + assert False == dis._is_healthy_pure(lambda name: component_health_bad, component) + + # Case: No health for a component + + component_health_nothing = ('262892', []) + assert False == dis._is_healthy_pure(lambda name: component_health_nothing, component) + + +def test_get_instances_from_kv(): + + def get_from_kv_fake(result, user, recurse=True): + return "don't care about first arg", result + + user = "jane" + kvs_nothing = [] + + assert dis._get_instances_from_kv(partial(get_from_kv_fake, kvs_nothing), user) == [] + + kvs_success = [ { "Value": "some value", "Key": "jane.1344a03a-06a8-4b92-bfac-d8f89df0c0cd.1-0-0.dcae-controller-ves-collector:rel" + }, + { "Value": "some value", "Key": "jane.1344a03a-06a8-4b92-bfac-d8f89df0c0cd.1-0-0.dcae-controller-ves-collector" } ] + + assert dis._get_instances_from_kv(partial(get_from_kv_fake, kvs_success), user) == ["jane.1344a03a-06a8-4b92-bfac-d8f89df0c0cd.1-0-0.dcae-controller-ves-collector"] + + kvs_partial = [ { "Value": "some value", "Key": "jane.1344a03a-06a8-4b92-bfac-d8f89df0c0cd.1-0-0.dcae-controller-ves-collector:rel" + } ] + + assert dis._get_instances_from_kv(partial(get_from_kv_fake, kvs_partial), user) == ["jane.1344a03a-06a8-4b92-bfac-d8f89df0c0cd.1-0-0.dcae-controller-ves-collector"] + + +def test_get_instances_from_catalog(): + + def get_from_catalog_fake(result): + return ("some Consul index", result) + + user = "jane" + services_nothing = {} + + assert dis._get_instances_from_catalog( + partial(get_from_catalog_fake, services_nothing), user) == [] + + services_no_matching = { '4f09bb72-8578-4e82-a6a4-9b7d679bd711.cdap_app_hello_world.hello-world-cloudify-test': [], + '666.fake_testing_service.rework-central.com': [], + 'Platform_Dockerhost_Solutioning_Test': [], + 'jack.2271ec6b-9224-4f42-b0b0-bfa91b41218f.1-0-1.cdap-event-proc-map-app': [], + 'jack.bca28c8c-a352-41f1-81bc-63ff46db2582.1-0-1.cdap-event-proc-supplement-app': + [] } + + assert dis._get_instances_from_catalog( + partial(get_from_catalog_fake, services_no_matching), user) == [] + + services_success = { '4f09bb72-8578-4e82-a6a4-9b7d679bd711.cdap_app_hello_world.hello-world-cloudify-test': [], + '666.fake_testing_service.rework-central.com': [], + 'Platform_Dockerhost_Solutioning_Test': [], + 'jack.2271ec6b-9224-4f42-b0b0-bfa91b41218f.1-0-1.cdap-event-proc-map-app': [], + 'jane.bca28c8c-a352-41f1-81bc-63ff46db2582.1-0-1.cdap-event-proc-supplement-app': + [] } + + assert dis._get_instances_from_catalog( + partial(get_from_catalog_fake, services_success), user) == ['jane.bca28c8c-a352-41f1-81bc-63ff46db2582.1-0-1.cdap-event-proc-supplement-app'] + + +def test_merge_instances(): + user = "somebody" + group_one = [ "123", "456" ] + group_two = [ "123", "abc" ] + group_three = [] + + assert sorted(dis._merge_instances(user, lambda user: group_one, lambda user: group_two, + lambda user: group_three)) == sorted([ "123", "456", "abc" ]) + + +def test_make_instance_map(): + instances_latest_format = ["mike.112e4faa-2ac8-4b13-93e9-8924150538d5.0-5-0.sandbox-platform-laika"] + + instances_map = dis._make_instances_map(instances_latest_format) + assert instances_map.get(("sandbox.platform.laika", "0.5.0")) == set(instances_latest_format) + + +def test_get_component_instances(monkeypatch): + instances = [ + 'jane.b493b48b-5fdf-4c1d-bd2a-8ce747b918ba.1-0-0.dcae-controller-ves-collector', + 'jane.2455ec5c-67e6-4d4d-8581-79037c7b5f8e.1-0-0.dcae-controller-ves-collector.rework-central.dcae.com', + 'jane.bfbb1356-d703-4007-8799-759a9e1fc8c2.1-0-0.dcae-controller-ves-collector.rework-central.dcae.com', + 'jane.89d82ff6-1482-4c01-8758-db9325aad085.1-0-0.dcae-controller-ves-collector' + ] + + instances_map = { ('dcae.controller.ves.collector', '1.0.0'): set(instances) } + + def get_user_instances_mock(user, consul_host=None, filter_instances_func=None): + return instances_map + + monkeypatch.setattr(dis, 'get_user_instances', get_user_instances_mock) + + def always_true_filter(consul_host, instance): + return True + + # Test base case + + user = "jane" + cname = "dcae.controller.ves.collector" + cver = "1.0.0" + consul_host = "bogus" + + assert sorted(dis._get_component_instances(always_true_filter, user, cname, cver, + consul_host)) == sorted(instances) + + # Test for dashes + + cname = "dcae-controller-ves-collector" + + assert sorted(dis._get_component_instances(always_true_filter, user, cname, cver, + consul_host)) == sorted(instances) + + +def test_group_config(): + config_key_map = {'call1': {'group': 'services_calls'}, 'pub1': {'type': 'http', 'group': 'streams_publishes'}, 'sub2': {'type': 'message_router', 'group': 'streams_subscribes'}, 'pub2': {'type': 'message_router', 'group': 'streams_publishes'}} + + config = { "call1": "{{yo}}", "pub1": "{{target}}", "some-param": 123, + "sub2": { "dmaap_info": "<>" }, "pub2": { "dmaap_info": "<>" } } + + gc = dis._group_config(config, config_key_map) + expected = {'services_calls': {'call1': '{{yo}}'}, 'streams_publishes': {'pub2': {'dmaap_info': '<>'}, 'pub1': '{{target}}'}, 'some-param': 123, 'streams_subscribes': {'sub2': {'dmaap_info': '<>'}}} + + assert gc == expected + + +def test_parse_instance_lookup(): + results = [{"ServiceAddress": "192.168.1.100", "ServicePort": "8080"}, + {"ServiceAddress": "10.100.1.100", "ServicePort": "8081"}] + assert dis.parse_instance_lookup(results) == "192.168.1.100:8080" + + +def test_apply_inputs(): + updated_config = dis._apply_inputs({"foo": "bar"}, {"foo": "baz"}) + assert updated_config == {"foo": "baz"} + + +def test_choose_consul_host(monkeypatch): + def fake_default_consul_host(): + return "default-consul-host" + + monkeypatch.setattr(dis, "default_consul_host", fake_default_consul_host) + assert "default-consul-host" == dis._choose_consul_host(None) + assert "provided-consul-host" == dis._choose_consul_host("provided-consul-host") + + +if __name__ == '__main__': + '''Test area''' + pytest.main([__file__, ]) diff --git a/mod/onboardingapi/dcae_cli/util/tests/test_dmaap.py b/mod/onboardingapi/dcae_cli/util/tests/test_dmaap.py new file mode 100644 index 0000000..dabc737 --- /dev/null +++ b/mod/onboardingapi/dcae_cli/util/tests/test_dmaap.py @@ -0,0 +1,259 @@ +# ============LICENSE_START======================================================= +# 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. + +""" +Tests for dmaap module +""" +import pytest +from dcae_cli.util import dmaap +from dcae_cli.util.exc import DcaeException + + +def test_validate_dmaap_map_schema_message_router(): + def pack_her_up(entry): + return { "some-config-key": entry } + + good = { + "type": "message_router", + "aaf_username": "foo3", + "aaf_password": "bar3", + "dmaap_info": { + "client_role":"com.dcae.member", + "client_id":"1500462518108", + "location":"mtc5", + "topic_url":"https://dcae-msrt-ftl2.com:3905/events/com.dcae.dmaap.FTL2.TommyTestTopic2" + } + } + dmaap.validate_dmaap_map_schema(pack_her_up(good)) + + good_minimal = { + "type": "message_router", + "dmaap_info": { + "topic_url":"https://dcae-msrt-ftl2.com:3905/events/com.dcae.dmaap.FTL2.TommyTestTopic2" + } + } + dmaap.validate_dmaap_map_schema(pack_her_up(good_minimal)) + + bad_extra = { + "type": "message_router", + "aaf_username": "foo3", + "aaf_password": "bar3", + "something_else": "boo", + "dmaap_info": { + "client_role":"com.dcae.member", + "client_id":"1500462518108", + "location":"mtc5", + "topic_url":"https://dcae-msrt-ftl2.com:3905/events/com.dcae.dmaap.FTL2.TommyTestTopic2" + } + } + dm = { "some-config-key": bad_extra } + + + with pytest.raises(DcaeException): + dmaap.validate_dmaap_map_schema(dm) + + bad_missing = { + "type": "message_router", + "aaf_username": "foo3", + "aaf_password": "bar3", + "dmaap_info": { + "client_role":"com.dcae.member", + "client_id":"1500462518108", + "location":"mtc5" + } + } + dm = { "some-config-key": bad_missing } + + with pytest.raises(DcaeException): + dmaap.validate_dmaap_map_schema(dm) + + +def test_validate_dmaap_map_schema_data_router(): + def pack_her_up(entry): + return { "some-config-key": entry } + + # Publishers + good = { + "type": "data_router", + "dmaap_info": { + "location": "mtc5", + "publish_url": "http://some-publish-url/123", + "log_url": "http://some-log-url/456", + "username": "jane", + "password": "abc" + } + } + dmaap.validate_dmaap_map_schema(pack_her_up(good)) + + good_minimal = { + "type": "data_router", + "dmaap_info": { + "publish_url": "http://some-publish-url/123" + } + } + dmaap.validate_dmaap_map_schema(pack_her_up(good_minimal)) + + bad_extra = { + "type": "data_router", + "dmaap_info": { + "publish_url": "http://some-publish-url/123", + "unknown_key": "value" + } + } + with pytest.raises(DcaeException): + dmaap.validate_dmaap_map_schema(pack_her_up(bad_extra)) + + # Subscribers + good = { + "type": "data_router", + "dmaap_info": { + "username": "drdeliver", + "password": "1loveDataR0uter", + "location": "loc00", + "delivery_url": "https://example.com/whatever", + "subscriber_id": "1550" + } + } + dmaap.validate_dmaap_map_schema(pack_her_up(good)) + + good_minimal = { + "type": "data_router", + "dmaap_info": { + "delivery_url": "https://example.com/whatever" + } + } + dmaap.validate_dmaap_map_schema(pack_her_up(good_minimal)) + + bad_extra = { + "type": "data_router", + "dmaap_info": { + "delivery_url": "https://example.com/whatever", + "unknown_key": "value" + } + } + with pytest.raises(DcaeException): + dmaap.validate_dmaap_map_schema(pack_her_up(bad_extra)) + + +def test_validate_dmaap_map_entries(): + + # Success + + dmaap_map = { "mr_pub_fun": { "foo": "bar" }, "mr_sub_fun": { "baz": "duh"} } + mr_config_keys = [ "mr_pub_fun", "mr_sub_fun" ] + dr_config_keys = [] + + assert dmaap.validate_dmaap_map_entries(dmaap_map, mr_config_keys, dr_config_keys) == True + + # Not supposed to be empty + + dmaap_map = {} + + assert dmaap.validate_dmaap_map_entries(dmaap_map, mr_config_keys, dr_config_keys) == False + + # Too many in dmaap map + + # NOTE: This scenario has been changed to be a success case per Tommy who + # believes that having extra keys in the dmaap_map is harmless. People would + # want to have a master dmaap_map that has a superset of connections used + # across many components. + + dmaap_map = { "mr_pub_fun": { "foo": "bar" }, "mr_sub_fun": { "baz": "duh"} } + mr_config_keys = [ "mr_pub_fun" ] + dr_config_keys = [] + + assert dmaap.validate_dmaap_map_entries(dmaap_map, mr_config_keys, dr_config_keys) == True + + # Too little in dmaap map + + dmaap_map = { "mr_pub_fun": { "foo": "bar" }, "mr_sub_fun": { "baz": "duh"} } + mr_config_keys = [ "mr_pub_fun", "mr_sub_fun", "mr_xxx" ] + dr_config_keys = [] + + assert dmaap.validate_dmaap_map_entries(dmaap_map, mr_config_keys, dr_config_keys) == False + + +def test_apply_defaults_dmaap_map(): + good = { + "type": "message_router", + "aaf_username": "foo3", + "aaf_password": "bar3", + "dmaap_info": { + "client_role":"com.dcae.member", + "client_id":"1500462518108", + "location":"mtc5", + "topic_url":"https://dcae-msrt-ftl2.com:3905/events/com.dcae.dmaap.FTL2.TommyTestTopic2" + } + } + dm = { "some-config-key": good } + + assert dmaap.apply_defaults_dmaap_map(dm) == dm + + minimal = { + "type": "message_router", + "dmaap_info": { + "topic_url":"https://dcae-msrt-ftl2.com:3905/events/com.dcae.dmaap.FTL2.TommyTestTopic2" + } + } + dm = { "some-config-key": minimal } + + result = dmaap.apply_defaults_dmaap_map(dm) + assert result == {'some-config-key': {'aaf_username': None, + 'aaf_password': None, 'dmaap_info': {'client_role': None, + 'topic_url': 'https://dcae-msrt-ftl2.com:3905/events/com.dcae.dmaap.FTL2.TommyTestTopic2', 'client_id': None, 'location': None}, + 'type': 'message_router'}} + + +def test_update_delivery_urls(): + def get_route_with_slash(config_key): + return "/eden" + + dmaap_map = {"spade-key": {"type": "data_router", "dmaap_info": {"delivery_url": "bleh","username": "dolittle"}}, + "clover-key": {"type": "data_router", "dmaap_info": {"publish_url": "manyfoos", + "username": "chickenlittle"}}} + + dmaap_map = dmaap.update_delivery_urls(get_route_with_slash, "http://some-host.io", dmaap_map) + + expected = {'spade-key': {"type": "data_router", 'dmaap_info': {'delivery_url': 'http://some-host.io/eden', + 'username': 'dolittle'}}, 'clover-key': {"type": "data_router", 'dmaap_info': {'publish_url': 'manyfoos', + 'username': 'chickenlittle'}}} + assert expected == dmaap_map + + def get_route_no_slash(config_key): + return "eden" + + dmaap_map = dmaap.update_delivery_urls(get_route_no_slash, "http://some-host.io", dmaap_map) + assert expected == dmaap_map + + # Case when there is nothing to update + dmaap_map = {"clover-key": {"type": "data_router", "dmaap_info": {"publish_url": "manyfoos", + "username": "chickenlittle"}}} + + assert dmaap_map == dmaap.update_delivery_urls(get_route_no_slash, "http://some-host.io", + dmaap_map) + + +def test_list_delivery_urls(): + dmaap_map = {"spade-key": {"type": "data_router", "dmaap_info": {"delivery_url": "bleh","username": "dolittle"}}, + "clover-key": {"type": "data_router", "dmaap_info": {"publish_url": "manyfoos", + "username": "chickenlittle"}}} + + result = dmaap.list_delivery_urls(dmaap_map) + assert result == [('spade-key', 'bleh')] diff --git a/mod/onboardingapi/dcae_cli/util/tests/test_docker_util.py b/mod/onboardingapi/dcae_cli/util/tests/test_docker_util.py new file mode 100644 index 0000000..1860357 --- /dev/null +++ b/mod/onboardingapi/dcae_cli/util/tests/test_docker_util.py @@ -0,0 +1,62 @@ +# ============LICENSE_START======================================================= +# 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. + +# -*- coding: utf-8 -*- +''' +Provides tests for the docker_util module +''' +import pytest +from dcae_cli.util.profiles import Profile, CONSUL_HOST, CONFIG_BINDING_SERVICE, CDAP_BROKER, DOCKER_HOST +from dcae_cli.util import docker_util as du + + +# TODO: formalize tests +''' +from dcae_cli.util.logger import set_verbose +set_verbose() + +client = _get_docker_client() + +params = dict() +interface_map = dict() +instance_map = dict() +# TODO: make-me-valid? +external_ip ='196.207.143.209' + +# TODO: Need to replace the use of asimov +_run_component('asimov-anomaly-viz:0.0.0', + 'bob', 'asimov.anomaly.viz', '1.0.0', params, interface_map, instance_map, + external_ip) +''' + +def test_convert_profile_to_docker_envs(): + expected = { CONSUL_HOST.upper(): "some.consul.somewhere", + CONFIG_BINDING_SERVICE.upper(): "some.config_binding.somewhere", + CDAP_BROKER.upper(): "broker", + DOCKER_HOST.upper(): "some-docker-host" + } + profile = Profile(**{ CONSUL_HOST: expected[CONSUL_HOST.upper()], + CONFIG_BINDING_SERVICE: expected[CONFIG_BINDING_SERVICE.upper()], + CDAP_BROKER: expected[CDAP_BROKER.upper()], + DOCKER_HOST: expected[DOCKER_HOST.upper()] + }) + actual = du._convert_profile_to_docker_envs(profile) + + assert actual == expected diff --git a/mod/onboardingapi/dcae_cli/util/tests/test_inputs.py b/mod/onboardingapi/dcae_cli/util/tests/test_inputs.py new file mode 100644 index 0000000..5271705 --- /dev/null +++ b/mod/onboardingapi/dcae_cli/util/tests/test_inputs.py @@ -0,0 +1,37 @@ +# ============LICENSE_START======================================================= +# 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. + +""" +Tests for inputs module +""" +import pytest +from dcae_cli.util import inputs + + +def test_filter_entries(): + spec = { "parameters": [{"name": "foo"}, {"name": "bar", + "sourced_at_deployment": False}, {"name": "baz", "sourced_at_deployment": True}] } + + with pytest.raises(inputs.InputsValidationError): + inputs.filter_entries({}, spec) + + inputs_map = { "foo": "do not copy", "baz": "hello world", "extra": "do not copy" } + + assert len(inputs.filter_entries(inputs_map, spec)) == 1 diff --git a/mod/onboardingapi/dcae_cli/util/tests/test_profiles.py b/mod/onboardingapi/dcae_cli/util/tests/test_profiles.py new file mode 100644 index 0000000..969697a --- /dev/null +++ b/mod/onboardingapi/dcae_cli/util/tests/test_profiles.py @@ -0,0 +1,162 @@ +# ============LICENSE_START======================================================= +# 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. + +# -*- coding: utf-8 -*- +""" +Tests the profiles module +""" +import os, json, copy +from functools import partial + +import click +import pytest + +from dcae_cli import util +from dcae_cli.util.exc import DcaeException +from dcae_cli.util import profiles +from dcae_cli.util.profiles import (get_active_name, get_profile, get_profiles, get_profiles_path, + create_profile, delete_profile, update_profile, ACTIVE, + activate_profile, CONSUL_HOST) +from dcae_cli.util import config + + +def test_profiles(monkeypatch, tmpdir): + '''Tests the creation and initialization of profiles on a clean install''' + # Setup config + config_dict = { "active_profile": "fake-solutioning", "db_url": "some-db" } + config_file = tmpdir.join("config.json") + config_file.write(json.dumps(config_dict)) + + # Setup profile + profile_dict = { "fake-solutioning": { "cdap_broker": "cdap_broker", + "config_binding_service": "config_binding_service", + "consul_host": "realsolcnsl00.dcae.solutioning.com", + "docker_host": "realsoldokr00.dcae.solutioning.com:2376" }} + profile_file = tmpdir.join("profiles.json") + profile_file.write(json.dumps(profile_dict)) + + monkeypatch.setattr(click, "get_app_dir", lambda app: str(tmpdir.realpath())) + + assert get_active_name() == config_dict["active_profile"] + assert get_profile() == profiles.Profile(**profile_dict["fake-solutioning"]) + + # Failures looking for unknown profile + + with pytest.raises(DcaeException): + get_profile('foo') + + with pytest.raises(DcaeException): + delete_profile('foo') + + with pytest.raises(DcaeException): + update_profile('foo', **{}) # doesn't exist + + # Cannot delete active profile + + assert delete_profile(get_active_name()) == False + + # Do different get_profiles queries + + assert get_profiles(user_only=True) == profile_dict + all_profiles = copy.deepcopy(profile_dict) + all_profiles[ACTIVE] = profile_dict["fake-solutioning"] + assert get_profiles(user_only=False) == all_profiles + + # Create and activate new profile + + create_profile('foo') + activate_profile('foo') + assert get_active_name() == 'foo' + + # Update new profile + + update_profile('foo', **{CONSUL_HOST:'bar'}) + assert get_profiles()['foo'][CONSUL_HOST] == 'bar' + assert get_profile()._asdict()[CONSUL_HOST] == 'bar' + + activate_profile("fake-solutioning") + assert delete_profile('foo') == True + + +def test_reinit_via_get_profiles(monkeypatch, tmpdir): + monkeypatch.setattr(click, "get_app_dir", lambda app: str(tmpdir.realpath())) + + def fake_reinit_failure(): + raise profiles.ProfilesInitError("Faked failure") + + monkeypatch.setattr(profiles, "reinit_profiles", fake_reinit_failure) + + with pytest.raises(DcaeException): + get_profiles() + + +def test_reinit_profiles(monkeypatch, tmpdir): + monkeypatch.setattr(click, "get_app_dir", lambda app: str(tmpdir.realpath())) + + # Setup config (need this because the "active_profile" is needed) + config_dict = { "active_profile": "fake-solutioning", "db_url": "some-db" } + config_file = tmpdir.join("config.json") + config_file.write(json.dumps(config_dict)) + + # Start with empty profiles + + profile_dict = { "fake-solutioning": { "cdap_broker": "cdap_broker", + "config_binding_service": "config_binding_service", + "consul_host": "realsolcnsl00.dcae.solutioning.com", + "docker_host": "realsoldokr00.dcae.solutioning.com:2376" }} + + def fetch_profile(target_profile, server_url, path): + return target_profile + + monkeypatch.setattr(util, "fetch_file_from_web", partial(fetch_profile, + profile_dict)) + profiles.reinit_profiles() + assert profiles.get_profiles(include_active=False) == profile_dict + + # Test update + + profile_dict = { "fake-5g": { "cdap_broker": "cdap_broker", + "config_binding_service": "config_binding_service", + "consul_host": "realsolcnsl00.dcae.solutioning.com", + "docker_host": "realsoldokr00.dcae.solutioning.com:2376" }} + + monkeypatch.setattr(util, "fetch_file_from_web", partial(fetch_profile, + profile_dict)) + profiles.reinit_profiles() + all_profiles = profiles.get_profiles(include_active=False) + assert "fake-5g" in all_profiles + assert "fake-solutioning" in all_profiles + + # Test fetch failure + + def fetch_failure(server_url, path): + raise RuntimeError("Mysterious error") + + monkeypatch.setattr(util, "fetch_file_from_web", fetch_failure) + # Case when user opts out of manually setting up + monkeypatch.setattr(click, "confirm", lambda msg: False) + + with pytest.raises(profiles.ProfilesInitError): + profiles.reinit_profiles() + + +if __name__ == '__main__': + '''Test area''' + pytest.main([__file__, ]) diff --git a/mod/onboardingapi/dcae_cli/util/tests/test_remove.py b/mod/onboardingapi/dcae_cli/util/tests/test_remove.py new file mode 100644 index 0000000..92b8ce9 --- /dev/null +++ b/mod/onboardingapi/dcae_cli/util/tests/test_remove.py @@ -0,0 +1,24 @@ +# ============LICENSE_START======================================================= +# 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. + +# -*- coding: utf-8 -*- +''' +TODO: Test removing components +''' diff --git a/mod/onboardingapi/dcae_cli/util/tests/test_undeploy.py b/mod/onboardingapi/dcae_cli/util/tests/test_undeploy.py new file mode 100644 index 0000000..664c69c --- /dev/null +++ b/mod/onboardingapi/dcae_cli/util/tests/test_undeploy.py @@ -0,0 +1,62 @@ +# ============LICENSE_START======================================================= +# 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. + +# -*- coding: utf-8 -*- +''' +Provides tests for the undeploy module +''' +from dcae_cli.util.undeploy import _handler, _handler_report + +def test_handler(): + instances = set(["some-instance-name", "another-instance-name"]) + + def fake_remove_config(config_key): + return True + + def undeploy_success(config_key): + return True + + failures, results = _handler([undeploy_success, fake_remove_config], instances) + + assert len(results) == 2 + assert len(failures) == 0 + + def undeploy_failure(config_key): + return False + + failures, results = _handler([undeploy_failure, fake_remove_config], instances) + + assert len(results) == 2 + assert len(failures) == 2 + + def undeploy_failure_sometimes(config_key): + if "some-instance-name" == config_key: + return False + return True + + failures, results = _handler([undeploy_failure_sometimes, fake_remove_config], instances) + + assert len(results) == 2 + assert len(failures) == 1 + + failures, results = _handler([undeploy_success, fake_remove_config], []) + + assert len(results) == 0 + assert len(failures) == 0 -- cgit 1.2.3-korg