From 549f0c115810d46b196bacc48bad331d00fad872 Mon Sep 17 00:00:00 2001 From: Davi Mello Date: Wed, 27 Jan 2021 14:47:08 +0000 Subject: [PATCH] STABLE Version. : Alpha v1.0 --- README.md | 3 +- magi/__main__.py | 14 ++++++ magi/execution.py | 14 ++++++ magi/nodesolver.py | 25 +++++++++-- magi/rest_engine.py | 10 +++++ magi/sys_env.py | 17 +++++++ requirements-dev.txt | 3 +- requirements.txt | 3 +- test/mock/alpha/mock_test_1.yaml | 4 +- test/mock/bitbucket/mock_test_nexus copy.yaml | 10 +++++ test/mock/bitbucket/mock_test_nexus.yaml | 22 ++++++++++ test/test_nodesolver.py | 23 ++++++---- test/test_rest_engine.py | 44 +++++++++++++++++++ test/test_sys_env.py | 31 +++++++++++++ 14 files changed, 207 insertions(+), 16 deletions(-) create mode 100644 magi/execution.py create mode 100644 magi/rest_engine.py create mode 100644 magi/sys_env.py create mode 100644 test/mock/bitbucket/mock_test_nexus copy.yaml create mode 100644 test/mock/bitbucket/mock_test_nexus.yaml create mode 100644 test/test_rest_engine.py create mode 100644 test/test_sys_env.py diff --git a/README.md b/README.md index 136d063..b598ca3 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ - \ No newline at end of file +export MAGI_YAML_AUTH_BASIC_USER=admin +export MAGI_YAML_AUTH_BASIC_PASS=admin \ No newline at end of file diff --git a/magi/__main__.py b/magi/__main__.py index e69de29..7762cdf 100644 --- a/magi/__main__.py +++ b/magi/__main__.py @@ -0,0 +1,14 @@ +import click +from magi.execution import run + + + +@click.command() +@click.option('-d', '--dir', 'directory', required=True, help='The directory of yaml file to do deploy.') +# @click.option('-f', '--file', 'file', required=False, help='The yaml file name (file.: input.yaml || use .: input ) to do deploy.') +def command(directory: str = ""): + run(folder_path=directory) + + +if __name__ == '__main__': + command() diff --git a/magi/execution.py b/magi/execution.py new file mode 100644 index 0000000..8c0df96 --- /dev/null +++ b/magi/execution.py @@ -0,0 +1,14 @@ +import os +from magi.nodesolver import nodesolver +from magi.readfiles import read_yaml_files +from magi.rest_engine import rest_call + +def run(folder_path:str=None)->None: + + YAMLS_ON_FOLDER : dict = read_yaml_files(folder_path) + + for yaml in YAMLS_ON_FOLDER: + request_list : list = nodesolver(YAMLS_ON_FOLDER[yaml]) + for rest_request in request_list: + rest_call(**rest_request) + diff --git a/magi/nodesolver.py b/magi/nodesolver.py index 5d13e80..439999f 100644 --- a/magi/nodesolver.py +++ b/magi/nodesolver.py @@ -1,9 +1,13 @@ import logging +from magi.sys_env import replace_by_sys_variables -def __get_basic_info__(raw_input:dict) -> dict: - return raw_input.get("metadata") +def __get_basic_info__(raw_input:dict, sys_env_replacer:bool=True) -> dict: + metadata : dict = raw_input.get("metadata") + if sys_env_replacer: + replace_by_sys_variables(metadata) + return metadata def __metadata_auth__(raw_metadata_auth_input:dict) -> dict: @@ -51,12 +55,13 @@ def __url__(url_base: str, url_endpoint: str) -> str: return f"{base}/{endpoint}" def __inject_basic_info__(metadata_input:dict, raw_request_input:dict) -> dict: - metadata: dict = metadata_input.copy() + result : dict = {} for node_name in raw_request_input: request_list : list = [] for request_item in raw_request_input[node_name]: + metadata: dict = metadata_input.copy() request_item_copy: dict = request_item.copy() request : dict = {} if metadata.get("url") and request_item_copy.get("url"): @@ -76,4 +81,16 @@ def __inject_basic_info__(metadata_input:dict, raw_request_input:dict) -> dict: # TODO: Implements the method sort -def __sort_requests__(raw_input:dict) -> dict : ... +def __sort_requests__(raw_input:dict) -> list : + result : list = [] + for node in raw_input: + for request in raw_input[node]: + result.append(request) + return result + + +def nodesolver(input_data: dict) -> list: + metadata: dict = __metadata__(input_data) + request_dict :dict = __inject_basic_info__(metadata_input=metadata, raw_request_input=__get_requests__(input_data)) + + return __sort_requests__(request_dict) \ No newline at end of file diff --git a/magi/rest_engine.py b/magi/rest_engine.py new file mode 100644 index 0000000..58812ea --- /dev/null +++ b/magi/rest_engine.py @@ -0,0 +1,10 @@ +import requests +import logging + + +def rest_call(rest_engine = requests.request, **kwargs) -> int: + call : requests.Response = rest_engine(**kwargs) + logging.info(msg=f"REST_CALL: {kwargs['url']} -> method : {kwargs['method']} -> status_code : {call.status_code}") + logging.debug(msg=f"JSON : {kwargs['url']}") + print(f"REST_CALL: {kwargs['url']} -> method : {kwargs['method']} -> status_code : {call.status_code}") + return call.status_code \ No newline at end of file diff --git a/magi/sys_env.py b/magi/sys_env.py new file mode 100644 index 0000000..5491ed0 --- /dev/null +++ b/magi/sys_env.py @@ -0,0 +1,17 @@ +import os + +def replace_by_sys_variables(metadata_raw:dict, sys_var_prefix:str="MAGI_YAML") -> None: + """ + This method change the input object in memory. + """ + + metadata: dict = metadata_raw + + for key in metadata: + sys_var: str = f"{sys_var_prefix}_{str(key).upper()}" + if isinstance(metadata[key], dict): + replace_by_sys_variables(metadata_raw=metadata[key], sys_var_prefix=sys_var) + + elif os.getenv(sys_var): + metadata[key] = os.getenv(sys_var) + diff --git a/requirements-dev.txt b/requirements-dev.txt index b0bf855..64f1974 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -3,4 +3,5 @@ pytest==6.2.1 coverage==5.3.1 setuptools==51.3.3 wheel==0.36.2 -twine==3.3.0 \ No newline at end of file +twine==3.3.0 +responses==0.12.1 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 07f1710..7f2b7f3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ requests==2.25.1 -pyaml==20.4.0 \ No newline at end of file +pyaml==20.4.0 +click==7.1.2 \ No newline at end of file diff --git a/test/mock/alpha/mock_test_1.yaml b/test/mock/alpha/mock_test_1.yaml index ff01005..b4ab133 100644 --- a/test/mock/alpha/mock_test_1.yaml +++ b/test/mock/alpha/mock_test_1.yaml @@ -3,7 +3,9 @@ metadata: #basic_info basic: user: "mock_user" password: "mock_pass" - url: "mock.site.localhost" + url: "http://mock.site.localhost" requests: test_default: #By default the "magi" will do a get - url: "/dummy" + - url: "/dummy_2" + diff --git a/test/mock/bitbucket/mock_test_nexus copy.yaml b/test/mock/bitbucket/mock_test_nexus copy.yaml new file mode 100644 index 0000000..54f86da --- /dev/null +++ b/test/mock/bitbucket/mock_test_nexus copy.yaml @@ -0,0 +1,10 @@ +metadata: #basic_info + auth: + basic: + user: "admin" + password: "admin" + url: "http://127.0.0.1:8081" +requests: + test_default: #By default the "magi" will do a get + - url: "/service/rest/v1/repositories/docker/hosted" + - url: "/service/rest/v1/repositories" diff --git a/test/mock/bitbucket/mock_test_nexus.yaml b/test/mock/bitbucket/mock_test_nexus.yaml new file mode 100644 index 0000000..172b6b8 --- /dev/null +++ b/test/mock/bitbucket/mock_test_nexus.yaml @@ -0,0 +1,22 @@ +metadata: #basic_info + auth: + basic: + user: "admin" + password: "admin" + url: "http://127.0.0.1:8081" +requests: + test_default: #By default the "magi" will do a get + - url: "/service/rest/v1/repositories" + - url: "/service/rest/v1/repositories/helm/hosted" + method: 'post' + json: + name: internal_2 + online: true + storage: + blobStoreName: default + strictContentTypeValidation: true + writePolicy: allow_once + cleanup: + policyNames: + - string + diff --git a/test/test_nodesolver.py b/test/test_nodesolver.py index 3f20384..74165be 100644 --- a/test/test_nodesolver.py +++ b/test/test_nodesolver.py @@ -16,11 +16,11 @@ def test__get_basic_info__(self): 'auth': {'basic': {'password': 'mock_pass', 'user': 'mock_user'}}, - 'url':'mock.site.localhost'} + 'url':'http://mock.site.localhost'} self.assertIsInstance(YAML, dict, "The Yaml must be a 'dict' instance") - self.assertIsInstance(__get_basic_info__(YAML), dict, "The method must return 'dict' instance") - self.assertEqual(__get_basic_info__(YAML), result, "The method must return the espect content.") + self.assertIsInstance(__get_basic_info__(raw_input=YAML.copy(), sys_env_replacer=False), dict, "The method must return 'dict' instance") + self.assertEqual(__get_basic_info__(raw_input=YAML.copy(), sys_env_replacer=False), result, "The method must return the espect content.") def test__metadata_auth__(self): @@ -38,7 +38,7 @@ def test__get_requests__(self): YAML: dict = CASE1.get("mock_test_1") result: dict = { - "test_default": [ {"url": "/dummy"} ] + "test_default": [ {"url": "/dummy"},{"url": "/dummy_2"}] } self.assertIsInstance(YAML, dict, "The Yaml must be a 'dict' instance") @@ -50,7 +50,7 @@ def test__metadata__(self): YAML: dict = CASE1.get("mock_test_1") result: dict = { - "url": "mock.site.localhost", + "url": "http://mock.site.localhost", "auth": ("mock_user", "mock_pass") } @@ -63,11 +63,18 @@ def test__inject_basic_info__(self): result: dict = { "test_default": [ { - "url": "mock.site.localhost/dummy", + "url": "http://mock.site.localhost/dummy", "auth": ("mock_user", "mock_pass"), "method": "GET" - } ] + }, + { + "url": "http://mock.site.localhost/dummy_2", + "auth": ("mock_user", "mock_pass"), + "method": "GET" + }] } self.assertIsInstance(__inject_basic_info__(__metadata__(YAML), __get_requests__(YAML)), dict, "The method must return 'dict' instance") - self.assertEqual(__inject_basic_info__(__metadata__(YAML), __get_requests__(YAML)), result, "The method must return the espect content.") \ No newline at end of file + self.assertEqual(__inject_basic_info__(__metadata__(YAML), __get_requests__(YAML)), result, "The method must return the espect content.") + + diff --git a/test/test_rest_engine.py b/test/test_rest_engine.py new file mode 100644 index 0000000..0bde43d --- /dev/null +++ b/test/test_rest_engine.py @@ -0,0 +1,44 @@ +import unittest +import responses +import requests +import os +from magi.rest_engine import rest_call + +# Project Magi dependencies +from magi.nodesolver import nodesolver +from magi.readfiles import read_yaml_files +from magi.rest_engine import rest_call + + + +FOLDER: str = f"{os.path.dirname(__file__)}/mock" +CASE1: str = read_yaml_files(f"{FOLDER}/alpha") +YAML: str = CASE1["mock_test_1"] +request_list : list = nodesolver(YAML) + + +TEST_CASE_1_1 = { + "method": "GET", + "url": "http://mock.site.localhost/dummy", + "status": 200 +} + +TEST_CASE_1_2 = { + "method": "GET", + "url": "http://mock.site.localhost/dummy_2", + "status": 200 +} + +class Test_rest_engine(unittest.TestCase): + + @responses.activate + def test_rest_call(self): + status_code: int = 200 + # Using request Lib + responses.add(**TEST_CASE_1_1) + responses.add(**TEST_CASE_1_2) + + for rest_request in request_list: + print(rest_request["url"]) + self.assertEqual(status_code, rest_call(**rest_request)) + \ No newline at end of file diff --git a/test/test_sys_env.py b/test/test_sys_env.py new file mode 100644 index 0000000..082b6f0 --- /dev/null +++ b/test/test_sys_env.py @@ -0,0 +1,31 @@ +import os +import unittest +from magi.sys_env import replace_by_sys_variables + + +class Test_sys_env(unittest.TestCase): + + def test_replace_by_sys_variables(self): + CASE : dict = { + "test": { + "user": "hello", + "pass": "pass" + } + } + + CASE_out : dict = { + "test": { + "user": "test", + "pass": "test_Pass0rd" + } + } + + os.environ["MAGI_YAML_TEST_USER"] = CASE_out["test"]["user"] + os.environ["MAGI_YAML_TEST_PASS"] = CASE_out["test"]["pass"] + + + self.assertIsNone(replace_by_sys_variables(CASE.copy())) + + replace_by_sys_variables(CASE.copy()) + self.assertIsInstance(CASE, dict) + self.assertEqual(CASE, CASE_out)