From 9cbe049d92690f94ca4e07e6a823b90340b922c1 Mon Sep 17 00:00:00 2001 From: Alex Shatov Date: Wed, 10 Jan 2018 11:27:44 -0500 Subject: variable collection of policies per component * new feature variable collection of policies per component in DCAE * Unit Test coverage 78% * moved module docstring below the license text Change-Id: Iefe6d4c31e2e125194781edc79e69af2c11e96ef Issue-ID: DCAEGEN2-249 Signed-off-by: Alex Shatov --- dcae-policy/tests/__init__.py | 18 ++++++ dcae-policy/tests/log_ctx.py | 12 ++-- dcae-policy/tests/mock_cloudify_ctx.py | 3 +- dcae-policy/tests/test_tasks.py | 106 ++++++++++++++++++++++++++------- 4 files changed, 111 insertions(+), 28 deletions(-) create mode 100644 dcae-policy/tests/__init__.py (limited to 'dcae-policy/tests') diff --git a/dcae-policy/tests/__init__.py b/dcae-policy/tests/__init__.py new file mode 100644 index 0000000..a3220c4 --- /dev/null +++ b/dcae-policy/tests/__init__.py @@ -0,0 +1,18 @@ +# 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. diff --git a/dcae-policy/tests/log_ctx.py b/dcae-policy/tests/log_ctx.py index 9f5464d..9e8ef26 100644 --- a/dcae-policy/tests/log_ctx.py +++ b/dcae-policy/tests/log_ctx.py @@ -1,5 +1,3 @@ -""":@CtxLogger.log_ctx: decorator for logging the cloudify ctx before and after operation""" - # org.onap.dcae # ================================================================================ # Copyright (c) 2017 AT&T Intellectual Property. All rights reserved. @@ -19,7 +17,10 @@ # # ECOMP is a trademark and service mark of AT&T Intellectual Property. +""":@CtxLogger.log_ctx: decorator for logging the cloudify ctx before and after operation""" + import json +import traceback from functools import wraps from cloudify import ctx @@ -102,7 +103,8 @@ class CtxLogger(object): ctx.logger.info("{0} context: {1}".format(\ func_name, json.dumps(CtxLogger.get_ctx_info()))) except Exception as ex: - ctx.logger.error("Failed to log the node context: {0}".format(str(ex))) + ctx.logger.error("Failed to log the node context: {0}: {1}" \ + .format(str(ex), traceback.format_exc())) @staticmethod def log_ctx(pre_log=True, after_log=False, exe_task=None): @@ -119,8 +121,8 @@ class CtxLogger(object): if ctx.type == NODE_INSTANCE and exe_task: ctx.instance.runtime_properties[exe_task] = func.__name__ except Exception as ex: - ctx.logger.error("Failed to set exe_task {0}: {1}".format(\ - exe_task, str(ex))) + ctx.logger.error("Failed to set exe_task {0}: {1}: {2}" \ + .format(exe_task, str(ex), traceback.format_exc())) if pre_log: CtxLogger.log_ctx_info('before ' + func.__name__) diff --git a/dcae-policy/tests/mock_cloudify_ctx.py b/dcae-policy/tests/mock_cloudify_ctx.py index 0c130c0..fe653d6 100644 --- a/dcae-policy/tests/mock_cloudify_ctx.py +++ b/dcae-policy/tests/mock_cloudify_ctx.py @@ -1,4 +1,3 @@ - # ============LICENSE_START======================================================= # org.onap.dcae # ================================================================================ @@ -19,6 +18,8 @@ # # ECOMP is a trademark and service mark of AT&T Intellectual Property. +"""mock cloudify context with relationships and type_hierarchy""" + from cloudify.mocks import MockCloudifyContext, MockNodeInstanceContext, MockNodeContext TARGET_NODE_ID = "target_node_id" diff --git a/dcae-policy/tests/test_tasks.py b/dcae-policy/tests/test_tasks.py index e2cc2e6..92d0611 100644 --- a/dcae-policy/tests/test_tasks.py +++ b/dcae-policy/tests/test_tasks.py @@ -18,28 +18,28 @@ # # ECOMP is a trademark and service mark of AT&T Intellectual Property. +"""unit tests for tasks in dcaepolicyplugin""" + import json import logging from datetime import datetime, timedelta import pytest - -from cloudify.state import current_ctx from cloudify.exceptions import NonRecoverableError - -from mock_cloudify_ctx import MockCloudifyContextFull, TARGET_NODE_ID, TARGET_NODE_NAME -from log_ctx import CtxLogger +from cloudify.state import current_ctx from dcaepolicyplugin import tasks +from tests.log_ctx import CtxLogger +from tests.mock_cloudify_ctx import (TARGET_NODE_ID, TARGET_NODE_NAME, + MockCloudifyContextFull) -DCAE_POLICY_TYPE = 'dcae.nodes.policy' POLICY_ID = 'policy_id' POLICY_VERSION = "policyVersion" POLICY_NAME = "policyName" POLICY_BODY = 'policy_body' POLICY_CONFIG = 'config' MONKEYED_POLICY_ID = 'monkeyed.Config_peach' -LOG_FILE = 'test_dcaepolicyplugin.log' +LOG_FILE = 'logs/test_dcaepolicyplugin.log' RUN_TS = datetime.utcnow() @@ -85,7 +85,7 @@ class MonkeyedPolicyBody(object): POLICY_VERSION: this_ver, POLICY_CONFIG: config, "matchingConditions": { - "ECOMPName": "DCAE", + "ONAPName": "DCAE", "ConfigName": "alex_config_name" }, "responseAttributes": {}, @@ -108,12 +108,15 @@ class MonkeyedPolicyBody(object): for key in policy_body_1.keys(): if key not in policy_body_2: return False - if isinstance(policy_body_1[key], dict): - return MonkeyedPolicyBody.is_the_same_dict( - policy_body_1[key], policy_body_2[key]) - if (policy_body_1[key] is None and policy_body_2[key] is not None) \ - or (policy_body_1[key] is not None and policy_body_2[key] is None) \ - or (policy_body_1[key] != policy_body_2[key]): + + val_1 = policy_body_1[key] + val_2 = policy_body_2[key] + if isinstance(val_1, dict) \ + and not MonkeyedPolicyBody.is_the_same_dict(val_1, val_2): + return False + if (val_1 is None and val_2 is not None) \ + or (val_1 is not None and val_2 is None) \ + or (val_1 != val_2): return False return True @@ -154,23 +157,34 @@ class MonkeyedNode(object): ) MonkeyedLogHandler.add_handler_to(self.ctx.logger) +def monkeyed_discovery_get_failure(full_path): + """monkeypatch for the GET to consul""" + return MonkeyedResponse(full_path, {}, None) + +def test_discovery_failure(monkeypatch): + """test finding policy-handler in consul""" + monkeypatch.setattr('requests.get', monkeyed_discovery_get_failure) + expected = None + tasks.PolicyHandler._lazy_init() + assert expected == tasks.PolicyHandler._url + def monkeyed_discovery_get(full_path): """monkeypatch for the GET to consul""" return MonkeyedResponse(full_path, {}, \ [{"ServiceAddress":"monkey-policy-handler-address", "ServicePort": "9999"}]) -def monkeyed_policy_handler_get(full_path, headers): - """monkeypatch for the GET to policy-engine""" - return MonkeyedResponse(full_path, headers, \ - MonkeyedPolicyBody.create_policy(MONKEYED_POLICY_ID)) - def test_discovery(monkeypatch): """test finding policy-handler in consul""" monkeypatch.setattr('requests.get', monkeyed_discovery_get) - expected = "http://monkey-policy-handler-address:9999/policy_latest" + expected = "http://monkey-policy-handler-address:9999" tasks.PolicyHandler._lazy_init() assert expected == tasks.PolicyHandler._url +def monkeyed_policy_handler_get(full_path, headers): + """monkeypatch for the GET to policy-engine""" + return MonkeyedResponse(full_path, headers, \ + MonkeyedPolicyBody.create_policy(MONKEYED_POLICY_ID)) + def test_policy_get(monkeypatch): """test policy_get operation on dcae.nodes.policy node""" monkeypatch.setattr('requests.get', monkeyed_policy_handler_get) @@ -178,7 +192,7 @@ def test_policy_get(monkeypatch): node_policy = MonkeyedNode( 'test_dcae_policy_node_id', 'test_dcae_policy_node_name', - DCAE_POLICY_TYPE, + tasks.DCAE_POLICY_TYPE, {POLICY_ID: MONKEYED_POLICY_ID} ) @@ -206,7 +220,55 @@ def test_policy_get(monkeypatch): with pytest.raises(NonRecoverableError) as excinfo: tasks.policy_get() CtxLogger.log_ctx_info("node_ms not policy type boom: {0}".format(str(excinfo.value))) - assert "can only invoke policy_get on node of type dcae.nodes.policy" in str(excinfo.value) + assert "unexpected node type " in str(excinfo.value) + + finally: + MockCloudifyContextFull.clear() + current_ctx.clear() + +def monkeyed_policy_handler_find(full_path, json, headers): + """monkeypatch for the GET to policy-engine""" + return MonkeyedResponse(full_path, headers, \ + {MONKEYED_POLICY_ID: MonkeyedPolicyBody.create_policy(MONKEYED_POLICY_ID)}) + +def test_policy_find(monkeypatch): + """test policy_get operation on dcae.nodes.policies node""" + monkeypatch.setattr('requests.post', monkeyed_policy_handler_find) + + node_policies = MonkeyedNode( + 'test_dcae_policies_node_id', + 'test_dcae_policies_node_name', + tasks.DCAE_POLICIES_TYPE, + {tasks.POLICY_FILTER: {POLICY_NAME: MONKEYED_POLICY_ID}} + ) + + try: + current_ctx.set(node_policies.ctx) + CtxLogger.log_ctx_info("before policy_get") + tasks.policy_get() + CtxLogger.log_ctx_info("after policy_get") + + expected = { + tasks.POLICIES_FILTERED: { + MONKEYED_POLICY_ID: MonkeyedPolicyBody.create_policy(MONKEYED_POLICY_ID)}} + + result = node_policies.ctx.instance.runtime_properties + node_policies.ctx.logger.info("expected runtime_properties: {0}".format( + json.dumps(expected))) + node_policies.ctx.logger.info("runtime_properties: {0}".format(json.dumps(result))) + assert MonkeyedPolicyBody.is_the_same_dict(result, expected) + assert MonkeyedPolicyBody.is_the_same_dict(expected, result) + + node_ms_multi = MonkeyedNode('test_ms_multi_id', 'test_ms_multi_name', "ms.nodes.type", \ + None, \ + [{TARGET_NODE_ID: node_policies.node_id, + TARGET_NODE_NAME: node_policies.node_name}]) + current_ctx.set(node_ms_multi.ctx) + CtxLogger.log_ctx_info("ctx of node_ms_multi not policy type") + with pytest.raises(NonRecoverableError) as excinfo: + tasks.policy_get() + CtxLogger.log_ctx_info("node_ms_multi not policy type boom: {0}".format(str(excinfo.value))) + assert "unexpected node type " in str(excinfo.value) finally: MockCloudifyContextFull.clear() -- cgit 1.2.3-korg