From 9c3c9f56e74c0569f307075a6850228fdcf07363 Mon Sep 17 00:00:00 2001 From: Kirill Makhonin Date: Wed, 21 Nov 2018 12:36:40 +0300 Subject: [PATCH] [#479] Redundant config map updates --- .../templates/legion-values.yaml.j2 | 2 + .../legion/templates/metrics/grafana.yaml | 2 + deploy/helms/legion/values.yaml | 1 + deploy/legionPipeline.groovy | 2 +- .../legion-ci-app.epm.kharlamov.biz.yml | 3 + .../legion-ci-infra.epm.kharlamov.biz.yml | 3 + .../profiles/legion-ci.epm.kharlamov.biz.yml | 3 + .../legion-demo.epm.kharlamov.biz.yml | 3 + .../profiles/legion-dev.epm.kharlamov.biz.yml | 3 + .../legion-test.epm.kharlamov.biz.yml | 3 + deploy/profiles/profiles_template.yaml | 4 + legion/.pylintrc | 5 +- legion/analyze_code.sh | 4 +- legion/legion/k8s/__init__.py | 1 - legion/legion/k8s/properties.py | 39 +++++-- legion/legion/k8s/utils.py | 1 + legion_test/legion_test/utils.py | 16 ++- tests/python/test_k8s_introspection.py | 5 +- tests/python/test_k8s_model_operations.py | 5 +- tests/python/test_k8s_properties_storages.py | 105 ++++++++++++------ tests/python/test_k8s_watching.py | 4 +- 21 files changed, 159 insertions(+), 55 deletions(-) diff --git a/deploy/ansible/roles/legion_enclave/templates/legion-values.yaml.j2 b/deploy/ansible/roles/legion_enclave/templates/legion-values.yaml.j2 index 7ec8060b5..49a6d4496 100644 --- a/deploy/ansible/roles/legion_enclave/templates/legion-values.yaml.j2 +++ b/deploy/ansible/roles/legion_enclave/templates/legion-values.yaml.j2 @@ -2,6 +2,8 @@ rootDomain: {{ root_domain }} enclaveName: "{{ enclave }}" namespace: default +log_level: {{ log_level }} + package: version: "{{ legion_version }}" repository: "{{ pypi_repo }}" diff --git a/deploy/helms/legion/templates/metrics/grafana.yaml b/deploy/helms/legion/templates/metrics/grafana.yaml index 7518ffff5..14052a3b5 100644 --- a/deploy/helms/legion/templates/metrics/grafana.yaml +++ b/deploy/helms/legion/templates/metrics/grafana.yaml @@ -35,6 +35,8 @@ spec: value: "true" - name: GF_INSTALL_PLUGINS value: "" + - name: GF_LOG_LEVEL + value: "{{ .Values.log_level }}" - name: GF_GRAPHITE_DATASOURCE {{- if .Values.grafana.graphite }} value: "{{ .Values.grafana.graphite }}" diff --git a/deploy/helms/legion/values.yaml b/deploy/helms/legion/values.yaml index 04540178a..ac68d1e6a 100644 --- a/deploy/helms/legion/values.yaml +++ b/deploy/helms/legion/values.yaml @@ -5,6 +5,7 @@ enclaveName: unknown localDomain: "cluster.local" addLocalDomain: false +log_level: info edi: enabled: true diff --git a/deploy/legionPipeline.groovy b/deploy/legionPipeline.groovy index 78841e2f3..9fd106d4f 100644 --- a/deploy/legionPipeline.groovy +++ b/deploy/legionPipeline.groovy @@ -204,7 +204,7 @@ def runRobotTests(tags="") { ansible-vault decrypt --vault-password-file=${vault} --output ${CREDENTIAL_SECRETS} ./${CLUSTER_NAME}_${Profile} PROFILE=$Profile PATH_TO_PROFILES_DIR=$PATH_TO_PROFILES_DIR LEGION_VERSION=$LegionVersion \ - ../../.venv/bin/nosetests $nose_tags --with-xunit || true + ../../.venv/bin/nosetests --logging-level DEBUG -v $nose_tags --with-xunit || true ''' step([ $class : 'RobotPublisher', diff --git a/deploy/profiles/legion-ci-app.epm.kharlamov.biz.yml b/deploy/profiles/legion-ci-app.epm.kharlamov.biz.yml index 287596891..59faae855 100644 --- a/deploy/profiles/legion-ci-app.epm.kharlamov.biz.yml +++ b/deploy/profiles/legion-ci-app.epm.kharlamov.biz.yml @@ -5,6 +5,9 @@ env_name: legion-ci-app base_domain: legion-ci-app.epm.kharlamov.biz route53_zone: epm.kharlamov.biz +# Logging +log_level: debug + # System vars tmp_dir: /tmp/ diff --git a/deploy/profiles/legion-ci-infra.epm.kharlamov.biz.yml b/deploy/profiles/legion-ci-infra.epm.kharlamov.biz.yml index c29575e24..10e5cea6b 100644 --- a/deploy/profiles/legion-ci-infra.epm.kharlamov.biz.yml +++ b/deploy/profiles/legion-ci-infra.epm.kharlamov.biz.yml @@ -5,6 +5,9 @@ env_name: legion-ci-infra base_domain: legion-ci-infra.epm.kharlamov.biz route53_zone: epm.kharlamov.biz +# Logging +log_level: debug + # System vars tmp_dir: /tmp/ diff --git a/deploy/profiles/legion-ci.epm.kharlamov.biz.yml b/deploy/profiles/legion-ci.epm.kharlamov.biz.yml index 8ac3b7542..a69d0254c 100644 --- a/deploy/profiles/legion-ci.epm.kharlamov.biz.yml +++ b/deploy/profiles/legion-ci.epm.kharlamov.biz.yml @@ -5,6 +5,9 @@ env_name: legion-ci base_domain: legion-ci.epm.kharlamov.biz route53_zone: epm.kharlamov.biz +# Logging +log_level: debug + # System vars tmp_dir: /tmp/ diff --git a/deploy/profiles/legion-demo.epm.kharlamov.biz.yml b/deploy/profiles/legion-demo.epm.kharlamov.biz.yml index a6384e0db..f27b613fd 100644 --- a/deploy/profiles/legion-demo.epm.kharlamov.biz.yml +++ b/deploy/profiles/legion-demo.epm.kharlamov.biz.yml @@ -5,6 +5,9 @@ env_name: legion-demo base_domain: legion-demo.epm.kharlamov.biz route53_zone: epm.kharlamov.biz +# Logging +log_level: debug + # System vars tmp_dir: /tmp/ diff --git a/deploy/profiles/legion-dev.epm.kharlamov.biz.yml b/deploy/profiles/legion-dev.epm.kharlamov.biz.yml index ee14b928d..ada035bbf 100644 --- a/deploy/profiles/legion-dev.epm.kharlamov.biz.yml +++ b/deploy/profiles/legion-dev.epm.kharlamov.biz.yml @@ -5,6 +5,9 @@ env_name: legion-dev base_domain: legion-dev.epm.kharlamov.biz route53_zone: epm.kharlamov.biz +# Logging +log_level: debug + # System vars tmp_dir: /tmp/ diff --git a/deploy/profiles/legion-test.epm.kharlamov.biz.yml b/deploy/profiles/legion-test.epm.kharlamov.biz.yml index 0138e278c..38b848bb4 100644 --- a/deploy/profiles/legion-test.epm.kharlamov.biz.yml +++ b/deploy/profiles/legion-test.epm.kharlamov.biz.yml @@ -5,6 +5,9 @@ env_name: legion-test base_domain: legion-test.epm.kharlamov.biz route53_zone: epm.kharlamov.biz +# Logging +log_level: debug + # System vars tmp_dir: /tmp/ diff --git a/deploy/profiles/profiles_template.yaml b/deploy/profiles/profiles_template.yaml index 87bd1daf4..221007c9c 100644 --- a/deploy/profiles/profiles_template.yaml +++ b/deploy/profiles/profiles_template.yaml @@ -9,6 +9,10 @@ env_type: ~ # name of env. type, will be added in resource tags env_name: ~ # short name of env, will be added in resource tags +# Logging +log_level: ~ # log level: debug / info / warning / error + + # Ansible variables tmp_dir: ~ # directory for storing temporary files (on host during deploy) git_key: ~ # SSH Git access key which will be copied to Jenkins in cluster diff --git a/legion/.pylintrc b/legion/.pylintrc index 953d564f5..2fdebc31c 100644 --- a/legion/.pylintrc +++ b/legion/.pylintrc @@ -2,4 +2,7 @@ max-line-length=120 [BASIC] -const-rgx=(([A-Z_][A-Za-z0-9_]*)|(__.*__))$ \ No newline at end of file +const-rgx=(([A-Z_][A-Za-z0-9_]*)|(__.*__))$ + +[MESSAGES CONTROL] +disable=W1202 \ No newline at end of file diff --git a/legion/analyze_code.sh b/legion/analyze_code.sh index 08267849f..65de3a188 100755 --- a/legion/analyze_code.sh +++ b/legion/analyze_code.sh @@ -1,6 +1,6 @@ #!/bin/bash -pycodestyle --show-source --show-pep8 legion -pycodestyle --show-source --show-pep8 tests --ignore E402,E126,W503,E731 +pycodestyle --show-source --show-pep8 legion --ignore W1202 +pycodestyle --show-source --show-pep8 tests --ignore E402,E126,W503,E731,W1202 pydocstyle --source legion pylint legion \ No newline at end of file diff --git a/legion/legion/k8s/__init__.py b/legion/legion/k8s/__init__.py index 607d450e2..6ceb35d62 100644 --- a/legion/legion/k8s/__init__.py +++ b/legion/legion/k8s/__init__.py @@ -22,7 +22,6 @@ from legion.k8s.definitions import STATUS_OK, STATUS_FAIL, STATUS_WARN from legion.k8s.definitions import EVENT_ADDED, EVENT_MODIFIED, EVENT_DELETED from legion.k8s.utils import build_client, get_current_namespace, load_config, load_secrets -from legion.k8s.utils import CONNECTION_CONTEXT from legion.k8s.watch import ResourceWatch from legion.k8s.properties import K8SPropertyStorage, K8SConfigMapStorage, K8SSecretStorage from legion.k8s.exceptions import UnknownDeploymentForModelService diff --git a/legion/legion/k8s/properties.py b/legion/legion/k8s/properties.py index 89f2d99c5..ecb05d4a0 100644 --- a/legion/legion/k8s/properties.py +++ b/legion/legion/k8s/properties.py @@ -34,9 +34,11 @@ import legion.config import legion.model import legion.k8s.watch +import legion.k8s.definitions import legion.k8s.utils import legion.k8s.services import legion.utils +from pandas.tests.extension.conftest import data LOGGER = logging.getLogger(__name__) @@ -290,9 +292,12 @@ def _read_data_from_dict(self, source_dict): :param source_dict: dict with readed values :type source_dict: dict[str, str] - :return: None + :return: bool -- is new data has been received """ - self._state = source_dict + data_has_been_changed = self._state != source_dict + if data_has_been_changed: + self._state = source_dict + return data_has_been_changed def _write_data_to_dict(self): """ @@ -333,8 +338,9 @@ def load(self): """ Load data from K8S - :return: None + :return: bool -- is new data has been received """ + data_has_been_changed = False try: LOGGER.debug('Reading {} {!r} in namespace {!r}'.format(self.__class__.__name__, self.k8s_name, @@ -342,12 +348,13 @@ def load(self): config_map_object = self._read_k8s_resource() - self._read_data_from_dict(config_map_object.data) + data_has_been_changed = self._read_data_from_dict(config_map_object.data) except Exception as load_exception: self._read_k8s_resource_exception_handler(load_exception) self._last_load_time = time.time() self._saved = True + return data_has_been_changed def _check_and_reload(self): """ @@ -446,9 +453,19 @@ def watch(self): LOGGER.info('Creating watch for object {!r}'.format(self)) watch = self._build_k8s_resource_watch() for (event_type, event_object) in watch.stream: - LOGGER.info('Watch got new event. Type = {}'.format(event_type)) - self.load() - yield (event_type, self.data) + LOGGER.info('Watch got new event. Type = {!r}'.format(event_type)) + if event_type != legion.k8s.definitions.EVENT_DELETED: + data_has_been_changed = self._read_data_from_dict(event_object.data) + if data_has_been_changed: + self._last_load_time = time.time() + self._saved = True + LOGGER.debug('Issuing properties change event {!r}'.format(event_type)) + yield (event_type, self.data) + else: + LOGGER.warning('Ignoring new properties change event {!r} without real data update' + .format(event_type)) + else: + LOGGER.error('Got DELETED event, ignoring...') def _call_callback(self): """ @@ -655,12 +672,16 @@ def _read_data_from_dict(self, source_dict): :param source_dict: dict with readed values :type source_dict: dict[str, str] - :return: None + :return: bool -- is new data has been received """ - self._state = { + new_data = { k: base64.b64decode(v.encode('ascii')).decode('utf-8') for k, v in source_dict.items() } + data_has_been_changed = self._state != new_data + if data_has_been_changed: + self._state = new_data + return data_has_been_changed def _write_data_to_dict(self): """ diff --git a/legion/legion/k8s/utils.py b/legion/legion/k8s/utils.py index e31ef155e..63f576b82 100644 --- a/legion/legion/k8s/utils.py +++ b/legion/legion/k8s/utils.py @@ -66,6 +66,7 @@ def build_client(): try: kubernetes.config.load_incluster_config() except kubernetes.config.config_exception.ConfigException: + LOGGER.debug('Connecting to cluster using context {!r}'.format(CONNECTION_CONTEXT)) kubernetes.config.load_kube_config(context=CONNECTION_CONTEXT) # Disable SSL warning for self-signed certificates diff --git a/legion_test/legion_test/utils.py b/legion_test/legion_test/utils.py index 49dfa7154..0e161603e 100644 --- a/legion_test/legion_test/utils.py +++ b/legion_test/legion_test/utils.py @@ -34,7 +34,8 @@ def wait_until(condition, iteration_duration=5, iterations=10): :return: True or False -- is condition result has been changed to True """ for _ in range(iterations): - if condition(): + result = condition() + if result: return True time.sleep(iteration_duration) @@ -68,6 +69,7 @@ class ContextThread(threading.Thread): """ Context manager thread """ + def __init__(self, threaded_function, name='ContextThread'): """ Construct context manager @@ -80,6 +82,16 @@ def __init__(self, threaded_function, name='ContextThread'): threading.Thread.__init__(self, name=name) self.daemon = True self._function = threaded_function + self._ready = False + + @property + def is_thread_ready(self): + """ + Check is thread ready + + :return: bool -- is thread ready or not + """ + return self._ready def run(self): """ @@ -88,6 +100,7 @@ def run(self): :return: None """ try: + self._ready = True self._function() finally: LOGGER.debug('ContextThread finished his work') @@ -121,4 +134,5 @@ def __exit__(self, exc_type, exc_val, exc_tb): :param exc_tb: exception traceback :return: None """ + self._ready = False self.stop() \ No newline at end of file diff --git a/tests/python/test_k8s_introspection.py b/tests/python/test_k8s_introspection.py index bf55b9307..214ff9213 100644 --- a/tests/python/test_k8s_introspection.py +++ b/tests/python/test_k8s_introspection.py @@ -21,6 +21,7 @@ import unittest2 import legion.k8s +import legion.k8s.utils import legion.config import legion.external import legion_test.profiler_loader @@ -42,8 +43,8 @@ def setUpClass(cls): """ logging.basicConfig(level=logging.DEBUG) - legion.k8s.CONNECTION_CONTEXT = VARIABLES['CLUSTER_NAME'] - LOGGER.info('K8S context has been set to {}'.format(legion.k8s.CONNECTION_CONTEXT)) + legion.k8s.utils.CONNECTION_CONTEXT = VARIABLES['CLUSTER_NAME'] + LOGGER.info('K8S context has been set to {}'.format(legion.k8s.utils.CONNECTION_CONTEXT)) def _get_test_enclave(self): """ diff --git a/tests/python/test_k8s_model_operations.py b/tests/python/test_k8s_model_operations.py index 78c015365..95f8b8eeb 100644 --- a/tests/python/test_k8s_model_operations.py +++ b/tests/python/test_k8s_model_operations.py @@ -25,6 +25,7 @@ import unittest2 import legion.k8s +import legion.k8s.utils import legion.config import legion.containers.docker import legion.external @@ -67,8 +68,8 @@ def setUpClass(cls): """ logging.basicConfig(level=logging.DEBUG) - legion.k8s.CONNECTION_CONTEXT = VARIABLES['CLUSTER_NAME'] - LOGGER.info('K8S context has been set to {}'.format(legion.k8s.CONNECTION_CONTEXT)) + legion.k8s.utils.CONNECTION_CONTEXT = VARIABLES['CLUSTER_NAME'] + LOGGER.info('K8S context has been set to {}'.format(legion.k8s.utils.CONNECTION_CONTEXT)) def _remove_model_if_exists(self, model_id, model_version=None): """ diff --git a/tests/python/test_k8s_properties_storages.py b/tests/python/test_k8s_properties_storages.py index 011564903..691485d93 100644 --- a/tests/python/test_k8s_properties_storages.py +++ b/tests/python/test_k8s_properties_storages.py @@ -44,6 +44,10 @@ LOGGER = logging.getLogger(__name__) +def check_modification_event_recieved(events, desired_data): + return len(events) > 0 and events[-1][1] == desired_data + + class TestK8SPropertiesStorage(unittest2.TestCase): @classmethod def setUpClass(cls): @@ -54,8 +58,8 @@ def setUpClass(cls): """ logging.basicConfig(level=logging.DEBUG) - legion.k8s.CONNECTION_CONTEXT = VARIABLES['CLUSTER_NAME'] - LOGGER.info('K8S context has been set to {}'.format(legion.k8s.CONNECTION_CONTEXT)) + legion.k8s.utils.CONNECTION_CONTEXT = VARIABLES['CLUSTER_NAME'] + LOGGER.info('K8S context has been set to {}'.format(legion.k8s.utils.CONNECTION_CONTEXT)) client = legion.k8s.utils.build_client() core_api = kubernetes.client.CoreV1Api(client) @@ -67,7 +71,8 @@ def check_cluster_is_active(): namespace_object = core_api.read_namespace(TEST_ENCLAVE_NAME) LOGGER.debug('Get namespace object: {!r}'.format(namespace_object)) LOGGER.info('Status of namespace object is {!r}'.format(namespace_object.status.phase)) - return namespace_object.status.phase.lower == 'active' + result = namespace_object.status.phase.lower == 'active' + return result try: new_namespace_metadata = kubernetes.client.models.v1_object_meta.V1ObjectMeta( @@ -79,6 +84,7 @@ def check_cluster_is_active(): LOGGER.info('Creating namespace {}'.format(TEST_ENCLAVE_NAME)) core_api.create_namespace(new_namespace) + LOGGER.info('Waiting until namespace will be active') legion_test.utils.wait_until(check_cluster_is_active) except Exception as exception: LOGGER.info('Cannot create namespace {} that should be built for testing: {}' @@ -115,28 +121,29 @@ def test_config_map_storage_watch(self): first_value = 'abc' second_value = 'abc-dgfa' + LOGGER.info('Constructing initial {!r} storage with start value {!r}' + .format(storage_name, first_value)) storage_to_write = legion.k8s.K8SConfigMapStorage(storage_name, TEST_ENCLAVE_NAME) storage_to_write[key] = first_value storage_to_write.save() + LOGGER.info('Retriving storage {!r}'.format(storage_name)) storage_to_read = legion.k8s.K8SConfigMapStorage.retrive(storage_name, TEST_ENCLAVE_NAME) def listener(): + LOGGER.info('Listener loop has been started') for event, new_data in storage_to_read.watch(): LOGGER.info('Got new event: type={}, new_data={}'.format(event, new_data)) events.append((event, new_data)) with legion_test.utils.ContextThread(listener): - LOGGER.debug('Waiting before updating') - - self.assertTrue(legion_test.utils.wait_until(lambda: len(events) > 0, 1, 5)) - self.assertTupleEqual(events[0], (legion.k8s.EVENT_ADDED, {key: first_value})) - + LOGGER.info('Updating inside listener loop') storage_to_write[key] = second_value storage_to_write.save() - self.assertTrue(legion_test.utils.wait_until(lambda: len(events) > 1, 1, 5)) - self.assertTupleEqual(events[1], (legion.k8s.EVENT_MODIFIED, {key: second_value})) + LOGGER.info('Checking update') + self.assertTrue(legion_test.utils.wait_until(lambda: check_modification_event_recieved(events, {key: second_value}), 1, 5), + 'Modification event has not been recieved for {!r}'.format(storage_name)) @attr('k8s', 'props', 'watch') def test_secret_storage_watch(self): @@ -151,28 +158,29 @@ def test_secret_storage_watch(self): first_value = 'abc' second_value = 'abc-dgfa' + LOGGER.info('Constructing initial {!r} storage with start value {!r}' + .format(storage_name, first_value)) storage_to_write = legion.k8s.K8SSecretStorage(storage_name, TEST_ENCLAVE_NAME) storage_to_write[key] = first_value storage_to_write.save() storage_to_read = legion.k8s.K8SSecretStorage.retrive(storage_name, TEST_ENCLAVE_NAME) + thread_ready = False def listener(): + LOGGER.info('Listener loop has been started') for event, new_data in storage_to_read.watch(): LOGGER.info('Got new event: type={}, new_data={}'.format(event, new_data)) events.append((event, new_data)) with legion_test.utils.ContextThread(listener): - LOGGER.debug('Waiting before updating') - - self.assertTrue(legion_test.utils.wait_until(lambda: len(events) > 0, 1, 5)) - self.assertTupleEqual(events[0], (legion.k8s.EVENT_ADDED, {key: first_value})) - + LOGGER.info('Updating inside listener loop') storage_to_write[key] = second_value storage_to_write.save() - self.assertTrue(legion_test.utils.wait_until(lambda: len(events) > 1, 1, 5)) - self.assertTupleEqual(events[1], (legion.k8s.EVENT_MODIFIED, {key: second_value})) + LOGGER.info('Checking update') + self.assertTrue(legion_test.utils.wait_until(lambda: check_modification_event_recieved(events, {key: second_value}), 1, 5), + 'Modification event has not been recieved for {!r}'.format(storage_name)) @attr('k8s', 'props', 'props_config_map') def test_read_config_map_with_update_on_timeout(self): @@ -192,11 +200,14 @@ def test_write_and_listing_config_map(self): """ storage_name = 'rw-storage-3' + LOGGER.info('Constructing empty {!r} storage'.format(storage_name)) storage_to_write = legion.k8s.K8SConfigMapStorage(storage_name, TEST_ENCLAVE_NAME) storage_to_write.save() - self.assertIn(storage_name, legion.k8s.K8SConfigMapStorage.list(TEST_ENCLAVE_NAME)) + self.assertIn(storage_name, legion.k8s.K8SConfigMapStorage.list(TEST_ENCLAVE_NAME), + 'Storage {!r} is not presented in list of storages'.format(storage_name)) + LOGGER.info('Destroying storage {!r}'.format(storage_name)) storage_to_write.destroy() @attr('k8s', 'props', 'props_config_map') @@ -208,13 +219,16 @@ def test_retrive_config_map(self): """ storage_name = 'rw-retrive-storage-4' + LOGGER.info('Constructing storage {!r}'.format(storage_name)) storage_to_write = legion.k8s.K8SConfigMapStorage(storage_name, TEST_ENCLAVE_NAME) storage_to_write['test_str'] = 'abc' storage_to_write.save() + LOGGER.info('Retriving storage {!r}'.format(storage_name)) storage_to_read = legion.k8s.K8SConfigMapStorage.retrive(storage_name, TEST_ENCLAVE_NAME) self.assertEqual(storage_to_read['test_str'], 'abc') + LOGGER.info('Destroying storage {!r}'.format(storage_name)) storage_to_read.destroy() @attr('k8s', 'props', 'props_config_map') @@ -226,23 +240,28 @@ def test_create_and_read_config_map_storage(self): """ storage_name = 'rw-map-storage-5' + LOGGER.info('Constructing storage {!r}'.format(storage_name)) storage_to_write = legion.k8s.K8SConfigMapStorage(storage_name, TEST_ENCLAVE_NAME) - storage_to_write['int_var'] = 1233 storage_to_write['float_var'] = 52.2354 storage_to_write['str_var'] = 'Test string' storage_to_write.save() + LOGGER.info('Listing storages') items = legion.k8s.K8SConfigMapStorage.list(TEST_ENCLAVE_NAME) self.assertIn(storage_name, items) + LOGGER.info('Loading storage {!r}'.format(storage_name)) storage_to_read = legion.k8s.K8SConfigMapStorage(storage_name, TEST_ENCLAVE_NAME) storage_to_read.load() - self.assertEqual(storage_to_read.get('int_var', cast=legion.model.int32), 1233) - self.assertAlmostEqual(storage_to_read.get('float_var', cast=legion.model.float32), 52.2354, 3) - self.assertEqual(storage_to_read.get('str_var', cast=legion.model.string), 'Test string') - self.assertEqual(storage_to_read['str_var'], 'Test string') + self.assertEqual(storage_to_read.get('int_var', cast=legion.model.int32), 1233, + 'Wrong casting to int') + self.assertAlmostEqual(storage_to_read.get('float_var', cast=legion.model.float32), 52.2354, 3, + 'Wrong casting to float') + self.assertEqual(storage_to_read.get('str_var', cast=legion.model.string), 'Test string', + 'Wrong casting to string') + self.assertEqual(storage_to_read['str_var'], 'Test string', 'Wrong calue w/o casting') @attr('k8s', 'props', 'props_secret') def test_create_and_read_secret_storage(self): @@ -253,28 +272,37 @@ def test_create_and_read_secret_storage(self): """ storage_name = 'rw-secret-storage-6' + LOGGER.info('Constructing storage {!r}'.format(storage_name)) storage_to_write = legion.k8s.K8SSecretStorage(storage_name, TEST_ENCLAVE_NAME) - storage_to_write['int_var'] = 1233 storage_to_write['float_var'] = 52.2354 storage_to_write['str_var'] = 'Test string' storage_to_write.save() + LOGGER.info('Listing storages') items = legion.k8s.K8SSecretStorage.list(TEST_ENCLAVE_NAME) - self.assertIn(storage_name, items) + self.assertIn(storage_name, items, 'Storage {!r} has not presented in list of storages' + .format(storage_name)) + LOGGER.info('Loading storage {!r}'.format(storage_name)) storage_to_read = legion.k8s.K8SSecretStorage(storage_name, TEST_ENCLAVE_NAME) storage_to_read.load() - self.assertEqual(storage_to_read.get('int_var', cast=legion.model.int32), 1233) - self.assertAlmostEqual(storage_to_read.get('float_var', cast=legion.model.float32), 52.2354, 3) - self.assertEqual(storage_to_read.get('str_var', cast=legion.model.string), 'Test string') - self.assertEqual(storage_to_read['str_var'], 'Test string') + self.assertEqual(storage_to_read.get('int_var', cast=legion.model.int32), 1233, + 'Wrong casting to int') + self.assertAlmostEqual(storage_to_read.get('float_var', cast=legion.model.float32), 52.2354, 3, + 'Wrong casting to float') + self.assertEqual(storage_to_read.get('str_var', cast=legion.model.string), 'Test string', + 'Wrong casting to str') + self.assertEqual(storage_to_read['str_var'], 'Test string', + 'Wrong value w/o casting') + LOGGER.info('Destroying storage {!r}'.format(storage_name)) storage_to_read.destroy() + LOGGER.info('Listing storages') items = legion.k8s.K8SConfigMapStorage.list(TEST_ENCLAVE_NAME) - self.assertNotIn(storage_name, items) + self.assertNotIn(storage_name, items, 'Storage {!r} has presented in list of strages after removing') @attr('k8s', 'props', 'props_config_map', 'props_ttl') def test_config_map_with_ttl(self): @@ -287,25 +315,30 @@ def test_config_map_with_ttl(self): ttl = 1 # Init storage + LOGGER.info('Constructing storage {!r}'.format(storage_name)) storage_to_write = legion.k8s.K8SConfigMapStorage(storage_name, TEST_ENCLAVE_NAME) storage_to_write['test_str'] = 'abc' storage_to_write.save() # Build storage object with ttl + LOGGER.info('Building reader for {!r} with TTL = {!r}'.format(storage_name, ttl)) storage_to_read = legion.k8s.K8SConfigMapStorage(storage_name, TEST_ENCLAVE_NAME, cache_ttl=ttl) storage_to_read.load() - self.assertEqual(storage_to_read['test_str'], 'abc') + self.assertEqual(storage_to_read['test_str'], 'abc', 'Wrong data has been recieved') # Update storage + LOGGER.info('Updating storage {!r}'.format(storage_name)) storage_to_write['test_str'] = 'def' storage_to_write.save() # Sleep TTL plus one seconds + LOGGER.info('Awaiting TTL + 1s = {}s for reader of storage {!r}'.format(ttl + 1, storage_name)) time.sleep(ttl + 1) # Check that data has been reloaded without forcing - self.assertEqual(storage_to_read['test_str'], 'def') + self.assertEqual(storage_to_read['test_str'], 'def', 'Data has not been changed after TTL timeout') + LOGGER.info('Destroying storage {!r}'.format(storage_name)) storage_to_read.destroy() @attr('k8s', 'props', 'props_config_map', 'props_ttl') @@ -318,22 +351,26 @@ def test_config_map_without_ttl(self): storage_name = 'config-map-without-ttl' # Init storage + LOGGER.info('Constructing storage {!r}'.format(storage_name)) storage_to_write = legion.k8s.K8SConfigMapStorage(storage_name, TEST_ENCLAVE_NAME) storage_to_write['test_str'] = 'abc' storage_to_write.save() # Build storage object without ttl + LOGGER.info('Building reader for {!r} without TTL'.format(storage_name)) storage_to_read = legion.k8s.K8SConfigMapStorage(storage_name, TEST_ENCLAVE_NAME) storage_to_read.load() - self.assertEqual(storage_to_read['test_str'], 'abc') + self.assertEqual(storage_to_read['test_str'], 'abc', 'Wrong data has been recieved') # Update storage + LOGGER.info('Updating storage {!r}'.format(storage_name)) storage_to_write['test_str'] = 'def' storage_to_write.save() # Check that data has not been reloaded without forcing - self.assertEqual(storage_to_read['test_str'], 'abc') + self.assertEqual(storage_to_read['test_str'], 'abc', 'Data has been updated') + LOGGER.info('Destroying storage {!r}'.format(storage_name)) storage_to_read.destroy() diff --git a/tests/python/test_k8s_watching.py b/tests/python/test_k8s_watching.py index 9c2f5789a..3f4f46886 100644 --- a/tests/python/test_k8s_watching.py +++ b/tests/python/test_k8s_watching.py @@ -53,8 +53,8 @@ def setUpClass(cls): """ logging.basicConfig(level=logging.DEBUG) - legion.k8s.CONNECTION_CONTEXT = VARIABLES['CLUSTER_NAME'] - LOGGER.info('K8S context has been set to {}'.format(legion.k8s.CONNECTION_CONTEXT)) + legion.k8s.utils.CONNECTION_CONTEXT = VARIABLES['CLUSTER_NAME'] + LOGGER.info('K8S context has been set to {}'.format(legion.k8s.utils.CONNECTION_CONTEXT)) try: legion.k8s.Enclave(TEST_ENCLAVE_NAME).delete()