From f53725e53e48e73ae944fa600183e99a5cbaa11b Mon Sep 17 00:00:00 2001 From: Thomas Duval Date: Mon, 18 Dec 2017 15:21:46 +0100 Subject: Add unit tests in moon_orchestrator Change-Id: I1b5b4a263098ef6f8bbd0bf59a661c5b76237ea6 --- .../moon_orchestrator/__main__.py | 3 +- .../moon_orchestrator/api/configuration.py | 63 ---- .../moon_orchestrator/api/containers.py | 123 ------- .../moon_orchestrator/api/slaves.py | 78 ---- .../moon_orchestrator/moon_orchestrator/drivers.py | 2 - .../moon_orchestrator/http_server.py | 3 +- .../moon_orchestrator/moon_orchestrator/server.py | 5 +- .../tests/unit_python/conftest.py | 18 + .../tests/unit_python/mock_pods.py | 404 +++++++++++++++++++++ .../tests/unit_python/requirements.txt | 5 + .../tests/unit_python/test_pods.py | 43 +++ .../tests/unit_python/utilities.py | 173 +++++++++ 12 files changed, 649 insertions(+), 271 deletions(-) delete mode 100644 moonv4/moon_orchestrator/moon_orchestrator/api/configuration.py delete mode 100644 moonv4/moon_orchestrator/moon_orchestrator/api/containers.py delete mode 100644 moonv4/moon_orchestrator/moon_orchestrator/api/slaves.py create mode 100644 moonv4/moon_orchestrator/tests/unit_python/conftest.py create mode 100644 moonv4/moon_orchestrator/tests/unit_python/mock_pods.py create mode 100644 moonv4/moon_orchestrator/tests/unit_python/requirements.txt create mode 100644 moonv4/moon_orchestrator/tests/unit_python/test_pods.py create mode 100644 moonv4/moon_orchestrator/tests/unit_python/utilities.py diff --git a/moonv4/moon_orchestrator/moon_orchestrator/__main__.py b/moonv4/moon_orchestrator/moon_orchestrator/__main__.py index b1feff49..9ebc3a7f 100644 --- a/moonv4/moon_orchestrator/moon_orchestrator/__main__.py +++ b/moonv4/moon_orchestrator/moon_orchestrator/__main__.py @@ -1,3 +1,4 @@ from moon_orchestrator.server import main -main() +server = main() +server.run() diff --git a/moonv4/moon_orchestrator/moon_orchestrator/api/configuration.py b/moonv4/moon_orchestrator/moon_orchestrator/api/configuration.py deleted file mode 100644 index 887a989b..00000000 --- a/moonv4/moon_orchestrator/moon_orchestrator/api/configuration.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors -# This software is distributed under the terms and conditions of the 'Apache-2.0' -# license which can be found in the file 'LICENSE' in this package distribution -# or at 'http://www.apache.org/licenses/LICENSE-2.0'. - -import json -from oslo_config import cfg -from oslo_log import log as logging -# from moon_db.core import IntraExtensionRootManager -from moon_db.core import ConfigurationManager - -LOG = logging.getLogger("moon.orchestrator.api.configuration") -CONF = cfg.CONF - - -class Configuration(object): - """ - Retrieve the global configuration. - """ - - __version__ = "0.1.0" - - def get_policy_templates(self, ctx, args): - """List all policy templates - - :param ctx: {"id": "intra_extension_id"} - :param args: {} - :return: { - "template_id": { - "name": "name of the template", - "description": "description of the template", - } - """ - templates = ConfigurationManager.get_policy_templates_dict(ctx["user_id"]) - return {"policy_templates": templates} - - def get_aggregation_algorithms(self, ctx, args): - """List all aggregation algorithms - - :param ctx: {"id": "intra_extension_id"} - :param args: {} - :return: { - "algorithm_id": { - "name": "name of the algorithm", - "description": "description of the algorithm", - } - } - """ - return {'aggregation_algorithms': ConfigurationManager.get_aggregation_algorithms_dict(ctx["user_id"])} - - def get_sub_meta_rule_algorithms(self, ctx, args): - """List all sub meta rule algorithms - - :param ctx: {"id": "intra_extension_id"} - :param args: {} - :return: { - "algorithm_id": { - "name": "name of the algorithm", - "description": "description of the algorithm", - } - } - """ - return {'sub_meta_rule_algorithms': ConfigurationManager.get_sub_meta_rule_algorithms_dict(ctx["user_id"])} diff --git a/moonv4/moon_orchestrator/moon_orchestrator/api/containers.py b/moonv4/moon_orchestrator/moon_orchestrator/api/containers.py deleted file mode 100644 index cb365414..00000000 --- a/moonv4/moon_orchestrator/moon_orchestrator/api/containers.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors -# This software is distributed under the terms and conditions of the 'Apache-2.0' -# license which can be found in the file 'LICENSE' in this package distribution -# or at 'http://www.apache.org/licenses/LICENSE-2.0'. - -import hashlib -from oslo_config import cfg -from oslo_log import log as logging -# from moon_db.core import IntraExtensionRootManager -# from moon_db.core import ConfigurationManager -# from moon_utilities.security_functions import call - -LOG = logging.getLogger("moon.orchestrator.api.containers") -CONF = cfg.CONF - - -class Containers(object): - """ - Manage containers. - """ - - __version__ = "0.1.0" - - def __init__(self, docker_manager): - self.docker_manager = docker_manager - self.components = dict() - # for pdp_key, pdp_value in call("moon_manager", method="get_pdp", - # ctx={"user_id": "admin", "id": None})["pdps"].items(): - # self.add_container(ctx={"id": pdp_key, "pipeline": pdp_value["security_pipeline"]}) - - def get_container(self, ctx, args=None): - """Get containers linked to an intra-extension - - :param ctx: { - "id": "intra_extension_uuid", - "keystone_project_id": "Keystone Project UUID" - } - :param args: {} - :return: { - "containers": {...}, - } - """ - uuid = ctx.get("id") - keystone_project_id = ctx.get("keystone_project_id") - # _containers = self.docker_manager.get_component(uuid=uuid) - # LOG.info("containers={}".format(_containers)) - if uuid: - return self.components[uuid] - elif keystone_project_id: - for container_id, container_value in self.components.items(): - if container_value['keystone_project_id'] == keystone_project_id: - return {container_id: container_value} - else: - return {} - return {"containers": self.components} - - def add_container(self, ctx, args=None): - """Add containers - - :param ctx: {"id": "intra_extension_uuid"} - :param args: {} - :return: { - "container_id1": {"status": True}, - "container_id2": {"status": True}, - } - """ - LOG.info("add_container {}".format(ctx)) - pdp = call("moon_manager", method="get_pdp", - ctx={"user_id": "admin", "id": ctx["id"]}, - args={})["pdps"] - pdp_id = list(pdp.keys())[0] - if not pdp[pdp_id]["keystone_project_id"]: - return {"result": "False", "message": "Cannot find keystone_project_id in pdp"} - keystone_project_id = pdp[pdp_id]["keystone_project_id"] - self.components[ctx["id"]] = [] - for policy_key, policy_value in call("moon_manager", method="get_policies", - ctx={"user_id": "admin", "id": None}, - args={})["policies"].items(): - if policy_key in ctx["pipeline"]: - models = call("moon_manager", method="get_models", - ctx={"user_id": "admin", "id": None}, - args={})["models"] - for meta_rule in models[policy_value['model_id']]['meta_rules']: - genre = policy_value['genre'] - pre_container_id = "pdp:{}_metarule:{}_project:{}".format(ctx["id"], meta_rule, keystone_project_id) - container_data = {"pdp": ctx["id"], "metarule": meta_rule, "project": keystone_project_id} - policy_component = self.docker_manager.load(component=genre, - uuid=pre_container_id, - container_data=container_data) - self.components[ctx["id"]].append({ - "meta_rule_id": meta_rule, - "genre": policy_value['genre'], - "keystone_project_id": keystone_project_id, - "container_id": policy_value['genre']+"_"+hashlib.sha224(pre_container_id.encode("utf-8")).hexdigest() - }) - return {"containers": self.components[ctx["id"]]} - - def delete_container(self, ctx, args=None): - """Delete a container - - :param ctx: {"id": "intra_extension_uuid"} - :param args: {} - :return: {} - """ - try: - self.docker_manager.kill(component_id="moon_secpolicy_"+ctx["id"]) - try: - # FIXME (asteroide): need to select other security_function here - self.docker_manager.kill(component_id="moon_secfunction_authz_"+ctx["id"]) - except Exception as e: - LOG.error(e, exc_info=True) - return {"result": True, - "error": {'code': 200, 'title': 'Moon Warning', 'description': str(e)}, - "intra_extension_id": ctx["id"], - "ctx": ctx, "args": args} - except Exception as e: - LOG.error(e, exc_info=True) - return {"result": False, - "error": {'code': 500, 'title': 'Moon Error', 'description': str(e)}, - "intra_extension_id": ctx["id"], - "ctx": ctx, "args": args} - return {"result": True} - diff --git a/moonv4/moon_orchestrator/moon_orchestrator/api/slaves.py b/moonv4/moon_orchestrator/moon_orchestrator/api/slaves.py deleted file mode 100644 index 3a16fea1..00000000 --- a/moonv4/moon_orchestrator/moon_orchestrator/api/slaves.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors -# This software is distributed under the terms and conditions of the 'Apache-2.0' -# license which can be found in the file 'LICENSE' in this package distribution -# or at 'http://www.apache.org/licenses/LICENSE-2.0'. - -from oslo_config import cfg -from oslo_log import log as logging -from uuid import uuid4 - -LOG = logging.getLogger("moon.orchestrator.api.slaves") -CONF = cfg.CONF - - -class Slaves(object): - """ - Manage containers. - """ - - __version__ = "0.1.0" - - def __init__(self, slaves): - self.slaves = slaves - - def add_slave(self, ctx, args=None): - """Add a new slave in the global list - - :param ctx: { - "name": "name of the slave", - "description": "description" - } - :param args: {} - :return: { - "uuid_of_the_slave": { - "name": "name of the slave", - "description": "description" - } - } - """ - if "name" in ctx: - for _id, _dict in self.slaves.items(): - if _dict['name'] == ctx['name']: - LOG.warning("A slave named {} already exists!".format(ctx['name'])) - return {"slaves": {_id: _dict}} - uuid = uuid4().hex - ctx.pop("method") - ctx.pop("call_master") - self.slaves[uuid] = ctx - LOG.info("New slave added: {}".format(ctx['name'])) - return {"slaves": {uuid: ctx}} - LOG.warning("No name given for the new slave.") - - def get_slaves(self, ctx, args=None): - """Get all the known slaves - - :param ctx: {} - :param args: {} - :return: { - "uuid_of_the_slave": { - "name": "name of the slave", - "description": "description" - } - } - """ - return {"slaves": self.slaves} - - def delete_slave(self, ctx, args=None): - """Delete a previous slave in the global list - - :param ctx: { - "id": "ID of the slave" - } - :param args: {} - :return: None - """ - if "id" in ctx: - if ctx['id'] in self.slaves: - self.slaves.pop(ctx['id']) - return {"slaves": self.slaves} diff --git a/moonv4/moon_orchestrator/moon_orchestrator/drivers.py b/moonv4/moon_orchestrator/moon_orchestrator/drivers.py index 63ca8f3c..95000840 100644 --- a/moonv4/moon_orchestrator/moon_orchestrator/drivers.py +++ b/moonv4/moon_orchestrator/moon_orchestrator/drivers.py @@ -152,8 +152,6 @@ class K8S(Driver): pod = self.__create_pod(client=ext_client, data=data) service = self.__create_service(client=_client, data=data[0], expose=expose) - # logger.info("load_pod data={}".format(data)) - # logger.info("pod.metadata.uid={}".format(pod.metadata.uid)) self.cache[pod.metadata.uid] = data def delete_pod(self, uuid=None, name=None): diff --git a/moonv4/moon_orchestrator/moon_orchestrator/http_server.py b/moonv4/moon_orchestrator/moon_orchestrator/http_server.py index c9816f5b..7aed18a6 100644 --- a/moonv4/moon_orchestrator/moon_orchestrator/http_server.py +++ b/moonv4/moon_orchestrator/moon_orchestrator/http_server.py @@ -206,12 +206,11 @@ class HTTPServer(Server): security function in all context (ie, in all slaves) :return: None """ - # LOG.info(self.driver.get_pods()) for key, value in self.driver.get_pods().items(): for _pod in value: if _pod.get('keystone_project_id') == keystone_project_id: LOG.warning("A pod for this Keystone project {} " - "already exists.".format(keystone_project_id)) + "already exists.".format(keystone_project_id)) return plugins = configuration.get_plugins() diff --git a/moonv4/moon_orchestrator/moon_orchestrator/server.py b/moonv4/moon_orchestrator/moon_orchestrator/server.py index d8e312d0..5e16bfcd 100644 --- a/moonv4/moon_orchestrator/moon_orchestrator/server.py +++ b/moonv4/moon_orchestrator/moon_orchestrator/server.py @@ -28,8 +28,9 @@ def main(): configuration.add_component(uuid="orchestrator", name=hostname, port=port, bind=bind) LOG.info("Starting server with IP {} on port {} bind to {}".format(hostname, port, bind)) server = HTTPServer(host=bind, port=port) - server.run() + return server if __name__ == '__main__': - main() + server = main() + server.run() diff --git a/moonv4/moon_orchestrator/tests/unit_python/conftest.py b/moonv4/moon_orchestrator/tests/unit_python/conftest.py new file mode 100644 index 00000000..044489e6 --- /dev/null +++ b/moonv4/moon_orchestrator/tests/unit_python/conftest.py @@ -0,0 +1,18 @@ +import pytest +import requests_mock +import mock_pods +from utilities import CONTEXT + + +@pytest.fixture +def context(): + return CONTEXT + + +@pytest.fixture(autouse=True) +def no_requests(monkeypatch): + """ Modify the response from Requests module + """ + with requests_mock.Mocker(real_http=True) as m: + mock_pods.register_pods(m) + yield m \ No newline at end of file diff --git a/moonv4/moon_orchestrator/tests/unit_python/mock_pods.py b/moonv4/moon_orchestrator/tests/unit_python/mock_pods.py new file mode 100644 index 00000000..c5633152 --- /dev/null +++ b/moonv4/moon_orchestrator/tests/unit_python/mock_pods.py @@ -0,0 +1,404 @@ +from kubernetes import client, config +from utilities import CONF, get_b64_conf, COMPONENTS + +pdp_mock = { + "pdp_id1": { + "name": "...", + "security_pipeline": ["policy_id_1", "policy_id_2"], + "keystone_project_id": "keystone_project_id1", + "description": "...", + }, + "pdp_id12": { + "name": "...", + "security_pipeline": ["policy_id_1", "policy_id_2"], + "keystone_project_id": "keystone_project_id1", + "description": "...", + } +} + +meta_rules_mock = { + "meta_rule_id1": { + "name": "meta_rule1", + "algorithm": "name of the meta rule algorithm", + "subject_categories": ["subject_category_id1", + "subject_category_id2"], + "object_categories": ["object_category_id1"], + "action_categories": ["action_category_id1"] + }, + "meta_rule_id2": { + "name": "name of the meta rules2", + "algorithm": "name of the meta rule algorithm", + "subject_categories": ["subject_category_id1", + "subject_category_id2"], + "object_categories": ["object_category_id1"], + "action_categories": ["action_category_id1"] + } +} + +policies_mock = { + "policy_id_1": { + "name": "test_policy1", + "model_id": "model_id_1", + "genre": "authz", + "description": "test", + }, + "policy_id_2": { + "name": "test_policy2", + "model_id": "model_id_2", + "genre": "authz", + "description": "test", + } +} + +subject_mock = { + "policy_id_1": { + "subject_id": { + "name": "subject_name", + "keystone_id": "keystone_project_id1", + "description": "a description" + } + }, + "policy_id_2": { + "subject_id": { + "name": "subject_name", + "keystone_id": "keystone_project_id1", + "description": "a description" + } + } +} + +subject_assignment_mock = { + "subject_id": { + "policy_id": "ID of the policy", + "subject_id": "ID of the subject", + "category_id": "ID of the category", + "assignments": [], + } +} + +object_mock = { + "policy_id_1": { + "object_id": { + "name": "object_name", + "description": "a description" + } + }, + "policy_id_2": { + "object_id": { + "name": "object_name", + "description": "a description" + } + } +} + +object_assignment_mock = { + "object_id": { + "policy_id": "ID of the policy", + "object_id": "ID of the object", + "category_id": "ID of the category", + "assignments": [], + } +} + +action_mock = { + "policy_id_1": { + "action_id": { + "name": "action_name", + "description": "a description" + } + }, + "policy_id_2": { + "action_id": { + "name": "action_name", + "description": "a description" + } + } +} + +action_assignment_mock = { + "action_id": { + "policy_id": "ID of the policy", + "action_id": "ID of the action", + "category_id": "ID of the category", + "assignments": [], + } +} + +models_mock = { + "model_id_1": { + "name": "test_model", + "description": "test", + "meta_rules": ["meta_rule_id1"] + }, + "model_id_2": { + "name": "test_model", + "description": "test", + "meta_rules": ["meta_rule_id2"] + }, +} + +rules_mock = { + "rules": { + "meta_rule_id": "meta_rule_id1", + "rule_id1": { + "rule": ["subject_data_id1", + "object_data_id1", + "action_data_id1"], + "instructions": ( + {"decision": "grant"}, + # "grant" to immediately exit, + # "continue" to wait for the result of next policy + # "deny" to deny the request + ) + }, + "rule_id2": { + "rule": ["subject_data_id2", + "object_data_id2", + "action_data_id2"], + "instructions": ( + { + "update": { + "operation": "add", + # operations may be "add" or "delete" + "target": "rbac:role:admin" + # add the role admin to the current user + } + }, + {"chain": {"name": "rbac"}} + # chain with the policy named rbac + ) + } + } +} + + +def patch_k8s(monkeypatch): + def _load_kube_config_mockreturn(*args, **kwargs): + return + monkeypatch.setattr(config, 'load_kube_config', + _load_kube_config_mockreturn) + + def list_kube_config_contexts_mockreturn(*args, **kwargs): + return [{"name": "active_context"}], {"name": "active_context"} + monkeypatch.setattr(config, 'list_kube_config_contexts', + list_kube_config_contexts_mockreturn) + + def new_client_from_config_mockreturn(*args, **kwargs): + return {"client": True} + monkeypatch.setattr(config, 'new_client_from_config', + new_client_from_config_mockreturn) + + def list_pod_for_all_namespaces_mockreturn(*args, **kwargs): + class pods: + items = [] + return pods + monkeypatch.setattr(client.CoreV1Api, 'list_pod_for_all_namespaces', + list_pod_for_all_namespaces_mockreturn) + + def create_namespaced_deployment_mockreturn(*args, **kwargs): + + class metadata: + uid = "123456789" + + class pod: + def __init__(self): + self.metadata = metadata() + return pod() + monkeypatch.setattr(client.ExtensionsV1beta1Api, + 'create_namespaced_deployment', + create_namespaced_deployment_mockreturn) + + def create_namespaced_service_mockreturn(*args, **kwargs): + return {} + monkeypatch.setattr(client.CoreV1Api, + 'create_namespaced_service', + create_namespaced_service_mockreturn) + + +def register_pods(m): + """ Modify the response from Requests module + """ + register_consul(m) + register_pdp(m) + # register_meta_rules(m) + register_policies(m) + register_models(m) + # register_policy_subject(m, "policy_id_1") + # register_policy_subject(m, "policy_id_2") + # register_policy_object(m, "policy_id_1") + # register_policy_object(m, "policy_id_2") + # register_policy_action(m, "policy_id_1") + # register_policy_action(m, "policy_id_2") + # register_policy_subject_assignment(m, "policy_id_1", "subject_id") + # register_policy_subject_assignment_list(m1, "policy_id_1") + # register_policy_subject_assignment(m, "policy_id_2", "subject_id") + # register_policy_subject_assignment_list(m1, "policy_id_2") + # register_policy_object_assignment(m, "policy_id_1", "object_id") + # register_policy_object_assignment_list(m1, "policy_id_1") + # register_policy_object_assignment(m, "policy_id_2", "object_id") + # register_policy_object_assignment_list(m1, "policy_id_2") + # register_policy_action_assignment(m, "policy_id_1", "action_id") + # register_policy_action_assignment_list(m1, "policy_id_1") + # register_policy_action_assignment(m, "policy_id_2", "action_id") + # register_policy_action_assignment_list(m1, "policy_id_2") + # register_rules(m, "policy_id1") + + +def register_consul(m): + for component in COMPONENTS: + m.register_uri( + 'GET', 'http://consul:8500/v1/kv/{}'.format(component), + json=[{'Key': component, 'Value': get_b64_conf(component)}] + ) + m.register_uri( + 'GET', 'http://consul:8500/v1/kv/components_port_start', + json=[ + { + "LockIndex": 0, + "Key": "components_port_start", + "Flags": 0, + "Value": "MzEwMDE=", + "CreateIndex": 9, + "ModifyIndex": 9 + } + ], + ) + m.register_uri( + 'PUT', 'http://consul:8500/v1/kv/components_port_start', + json=[], + ) + m.register_uri( + 'GET', 'http://consul:8500/v1/kv/plugins?recurse=true', + json=[ + { + "LockIndex": 0, + "Key": "plugins/authz", + "Flags": 0, + "Value": "eyJjb250YWluZXIiOiAid3Vrb25nc3VuL21vb25fYXV0aHo6djQuMyIsICJwb3J0IjogODA4MX0=", + "CreateIndex": 14, + "ModifyIndex": 656 + } + ], + ) + + +def register_pdp(m): + m.register_uri( + 'GET', 'http://{}:{}/{}'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'pdp'), + json={'pdps': pdp_mock} + ) + + +def register_meta_rules(m): + m.register_uri( + 'GET', 'http://{}:{}/{}'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'meta_rules'), + json={'meta_rules': meta_rules_mock} + ) + + +def register_policies(m): + m.register_uri( + 'GET', 'http://{}:{}/{}'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'policies'), + json={'policies': policies_mock} + ) + + +def register_models(m): + m.register_uri( + 'GET', 'http://{}:{}/{}'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'models'), + json={'models': models_mock} + ) + + +def register_policy_subject(m, policy_id): + m.register_uri( + 'GET', 'http://{}:{}/{}/{}/subjects'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'policies', policy_id), + json={'subjects': subject_mock[policy_id]} + ) + + +def register_policy_object(m, policy_id): + m.register_uri( + 'GET', 'http://{}:{}/{}/{}/objects'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'policies', policy_id), + json={'objects': object_mock[policy_id]} + ) + + +def register_policy_action(m, policy_id): + m.register_uri( + 'GET', 'http://{}:{}/{}/{}/actions'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'policies', policy_id), + json={'actions': action_mock[policy_id]} + ) + + +def register_policy_subject_assignment(m, policy_id, subj_id): + m.register_uri( + 'GET', 'http://{}:{}/{}/{}/subject_assignments/{}'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'policies', + policy_id, + subj_id), + json={'subject_assignments': subject_assignment_mock} + ) + + +def register_policy_subject_assignment_list(m, policy_id): + m.register_uri( + 'GET', 'http://{}:{}/{}/{}/subject_assignments'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'policies', + policy_id), + json={'subject_assignments': subject_assignment_mock} + ) + + +def register_policy_object_assignment(m, policy_id, obj_id): + m.register_uri( + 'GET', 'http://{}:{}/{}/{}/object_assignments/{}'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'policies', + policy_id, + obj_id), + json={'object_assignments': object_assignment_mock} + ) + + +def register_policy_object_assignment_list(m, policy_id): + m.register_uri( + 'GET', 'http://{}:{}/{}/{}/object_assignments'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'policies', + policy_id), + json={'object_assignments': object_assignment_mock} + ) + + +def register_policy_action_assignment(m, policy_id, action_id): + m.register_uri( + 'GET', 'http://{}:{}/{}/{}/action_assignments/{}'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'policies', + policy_id, + action_id), + json={'action_assignments': action_assignment_mock} + ) + + +def register_policy_action_assignment_list(m, policy_id): + m.register_uri( + 'GET', 'http://{}:{}/{}/{}/action_assignments'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'policies', + policy_id), + json={'action_assignments': action_assignment_mock} + ) + + +def register_rules(m, policy_id): + m.register_uri( + 'GET', 'http://{}:{}/{}/{}/{}'.format(CONF['components']['manager']['hostname'], + CONF['components']['manager']['port'], 'policies', + policy_id, 'rules'), + json={'rules': rules_mock} + ) \ No newline at end of file diff --git a/moonv4/moon_orchestrator/tests/unit_python/requirements.txt b/moonv4/moon_orchestrator/tests/unit_python/requirements.txt new file mode 100644 index 00000000..8bd8449f --- /dev/null +++ b/moonv4/moon_orchestrator/tests/unit_python/requirements.txt @@ -0,0 +1,5 @@ +flask +flask_cors +flask_restful +moon_db +moon_utilities \ No newline at end of file diff --git a/moonv4/moon_orchestrator/tests/unit_python/test_pods.py b/moonv4/moon_orchestrator/tests/unit_python/test_pods.py new file mode 100644 index 00000000..42c8404b --- /dev/null +++ b/moonv4/moon_orchestrator/tests/unit_python/test_pods.py @@ -0,0 +1,43 @@ +import json +from mock_pods import patch_k8s +from utilities import get_json + + +def test_get_pods(context, monkeypatch): + patch_k8s(monkeypatch) + + import moon_orchestrator.server + server = moon_orchestrator.server.main() + _client = server.app.test_client() + req = _client.get("/pods") + assert req.status_code == 200 + assert req.data + data = get_json(req.data) + assert isinstance(data, dict) + assert "pods" in data + + +def test_add_pods(context, monkeypatch): + patch_k8s(monkeypatch) + + import moon_orchestrator.server + server = moon_orchestrator.server.main() + _client = server.app.test_client() + data = { + "keystone_project_id": context.get('project_id'), + "pdp_id": context.get('pdp_id'), + "security_pipeline": context.get('security_pipeline'), + } + req = _client.post("/pods", data=json.dumps(data), + headers={'Content-Type': 'application/json'}) + assert req.status_code == 200 + assert req.data + data = get_json(req.data) + assert isinstance(data, dict) + assert "pods" in data + assert data["pods"] + + +def test_delete_pods(context, monkeypatch): + # TODO + pass diff --git a/moonv4/moon_orchestrator/tests/unit_python/utilities.py b/moonv4/moon_orchestrator/tests/unit_python/utilities.py new file mode 100644 index 00000000..aec03d9d --- /dev/null +++ b/moonv4/moon_orchestrator/tests/unit_python/utilities.py @@ -0,0 +1,173 @@ +import base64 +import json +import pytest +from uuid import uuid4 + + +CONF = { + "openstack": { + "keystone": { + "url": "http://keystone:5000/v3", + "user": "admin", + "check_token": False, + "password": "p4ssw0rd", + "domain": "default", + "certificate": False, + "project": "admin" + } + }, + "components": { + "wrapper": { + "bind": "0.0.0.0", + "port": 8080, + "container": "wukongsun/moon_wrapper:v4.3", + "timeout": 5, + "hostname": "wrapper" + }, + "manager": { + "bind": "0.0.0.0", + "port": 8082, + "container": "wukongsun/moon_manager:v4.3", + "hostname": "manager" + }, + "port_start": 31001, + "orchestrator": { + "bind": "0.0.0.0", + "port": 8083, + "container": "wukongsun/moon_orchestrator:v4.3", + "hostname": "interface" + }, + "interface": { + "bind": "0.0.0.0", + "port": 8080, + "container": "wukongsun/moon_interface:v4.3", + "hostname": "interface" + } + }, + "plugins": { + "session": { + "port": 8082, + "container": "asteroide/session:latest" + }, + "authz": { + "port": 8081, + "container": "wukongsun/moon_authz:v4.3" + } + }, + "logging": { + "handlers": { + "file": { + "filename": "/tmp/moon.log", + "class": "logging.handlers.RotatingFileHandler", + "level": "DEBUG", + "formatter": "custom", + "backupCount": 3, + "maxBytes": 1048576 + }, + "console": { + "class": "logging.StreamHandler", + "formatter": "brief", + "level": "INFO", + "stream": "ext://sys.stdout" + } + }, + "formatters": { + "brief": { + "format": "%(levelname)s %(name)s %(message)-30s" + }, + "custom": { + "format": "%(asctime)-15s %(levelname)s %(name)s %(message)s" + } + }, + "root": { + "handlers": [ + "console" + ], + "level": "ERROR" + }, + "version": 1, + "loggers": { + "moon": { + "handlers": [ + "console", + "file" + ], + "propagate": False, + "level": "DEBUG" + } + } + }, + "slave": { + "name": None, + "master": { + "url": None, + "login": None, + "password": None + } + }, + "docker": { + "url": "tcp://172.88.88.1:2376", + "network": "moon" + }, + "database": { + "url": "sqlite:///database.db", + # "url": "mysql+pymysql://moon:p4sswOrd1@db/moon", + "driver": "sql" + }, + "messenger": { + "url": "rabbit://moon:p4sswOrd1@messenger:5672/moon" + } +} + + +CONTEXT = { + "project_id": "a64beb1cc224474fb4badd43173e7101", + "subject_name": "testuser", + "object_name": "vm1", + "action_name": "boot", + "request_id": uuid4().hex, + "interface_name": "interface", + "manager_url": "http://{}:{}".format( + CONF["components"]["manager"]["hostname"], + CONF["components"]["manager"]["port"] + ), + "cookie": uuid4().hex, + "pdp_id": "b3d3e18abf3340e8b635fd49e6634ccd", + "security_pipeline": ["f8f49a779ceb47b3ac810f01ef71b4e0"] + } + + +COMPONENTS = ( + "logging", + "openstack/keystone", + "database", + "slave", + "components/manager", + "components/orchestrator", + "components/interface", + "components/wrapper", +) + + +def get_b64_conf(component=None): + if component == "components": + return base64.b64encode( + json.dumps(CONF["components"]).encode('utf-8')+b"\n").decode('utf-8') + elif component in CONF: + return base64.b64encode( + json.dumps( + CONF[component]).encode('utf-8')+b"\n").decode('utf-8') + elif not component: + return base64.b64encode( + json.dumps(CONF).encode('utf-8')+b"\n").decode('utf-8') + elif "/" in component: + key1, _, key2 = component.partition("/") + return base64.b64encode( + json.dumps( + CONF[key1][key2]).encode('utf-8')+b"\n").decode('utf-8') + + +def get_json(data): + return json.loads(data.decode("utf-8")) + + -- cgit 1.2.3-korg