From 860ec66aca308120dd999c6e067aef3d92602b90 Mon Sep 17 00:00:00 2001 From: Scott Hussey Date: Tue, 16 Oct 2018 12:27:01 -0500 Subject: [PATCH] (fix) Support node filter by rack name - Add unit tests for node filtering based on rack name, node tag and node label. - Code updates to get all unit tests passing. Change-Id: I79e7a8b35c5635364c37e22153b26687a684bfed --- .../drydock_provisioner/objects/__init__.py | 7 +- .../orchestrator/orchestrator.py | 32 ++++---- python/tests/unit/test_orch_node_filter.py | 75 ++++++++++++++++++- .../tests/yaml_samples/deckhand_fullsite.yaml | 2 + 4 files changed, 94 insertions(+), 22 deletions(-) diff --git a/python/drydock_provisioner/objects/__init__.py b/python/drydock_provisioner/objects/__init__.py index a38464d1..0555e56f 100644 --- a/python/drydock_provisioner/objects/__init__.py +++ b/python/drydock_provisioner/objects/__init__.py @@ -102,11 +102,12 @@ class Utils(object): try: # Probably should handle non-string values effective_list.extend( - filter(lambda x: not x.startswith("!"), child_list)) + [x for x in child_list if not x.startswith("!")]) effective_list.extend( - filter(lambda x: ("!" + x) not in child_list, - filter(lambda x: x not in effective_list, parent_list))) + [x for x in parent_list + if ("!" + x) not in child_list + and x not in effective_list]) except TypeError: raise TypeError("Error iterating list argument") diff --git a/python/drydock_provisioner/orchestrator/orchestrator.py b/python/drydock_provisioner/orchestrator/orchestrator.py index 44f23e55..f6d83431 100644 --- a/python/drydock_provisioner/orchestrator/orchestrator.py +++ b/python/drydock_provisioner/orchestrator/orchestrator.py @@ -472,25 +472,25 @@ class Orchestrator(object): target_nodes = dict() - if node_names and len(node_names) > 0: + if node_names: self.logger.debug("Filtering nodes based on node names.") target_nodes['node_names'] = [ x for x in node_set if x.get_name() in node_names ] - if node_tags and len(node_tags) > 0: + if node_tags: self.logger.debug("Filtering nodes based on node tags.") target_nodes['node_tags'] = [ x for x in node_set for t in node_tags if x.has_tag(t) ] - if rack_names and len(rack_names) > 0: + if rack_names: self.logger.debug("Filtering nodes based on rack names.") target_nodes['rack_names'] = [ x for x in node_set if x.get_rack() in rack_names ] - if node_labels and len(node_labels) > 0: + if node_labels: self.logger.debug("Filtering nodes based on node labels.") target_nodes['node_labels'] = [] for k, v in node_labels.items(): @@ -499,7 +499,7 @@ class Orchestrator(object): if getattr(x, 'owner_data', {}).get(k, None) == v ]) - if rack_labels and len(rack_labels) > 0: + if rack_labels: self.logger.info( "Rack label filtering not yet implemented, returning all nodes." ) @@ -531,21 +531,17 @@ class Orchestrator(object): """ if len(rest) > 1: result = self.list_intersection(rest[0], *rest[1:]) - if a is None: - return result - elif result is None: - return a - else: - return list(set(a).intersection(set(result))) - elif len(rest) == 1: - if a is None and rest[0] is None: - return None - elif rest is None or rest[0]: - return a - else: - return list(set(a).intersection(set(rest[0]))) + elif rest: + result = rest[0] else: + result = None + + if a is None: + return result + elif result is None: return a + else: + return list(set(a).intersection(set(result))) def list_union(self, *lists): """Return a unique-ified union of all the lists. diff --git a/python/tests/unit/test_orch_node_filter.py b/python/tests/unit/test_orch_node_filter.py index 932c31d4..7cc236a3 100644 --- a/python/tests/unit/test_orch_node_filter.py +++ b/python/tests/unit/test_orch_node_filter.py @@ -54,7 +54,80 @@ class TestClass(object): 'filter_set': [ { 'filter_type': 'intersection', - 'node_names': 'compute01', + 'node_names': ['compute01'], + }, + ], + } + + node_list = deckhand_orchestrator.process_node_filter(nfs, design_data) + + assert len(node_list) == 1 + + def test_node_filter_by_rackname(self, input_files, setup, deckhand_orchestrator, + deckhand_ingester): + input_file = input_files.join("deckhand_fullsite.yaml") + + design_state = DrydockState() + design_ref = "file://%s" % str(input_file) + + design_status, design_data = deckhand_ingester.ingest_data( + design_state=design_state, design_ref=design_ref) + + nfs = { + 'filter_set_type': + 'intersection', + 'filter_set': [ + { + 'filter_type': 'intersection', + 'rack_names': ['rack2', 'rack3'], + }, + ], + } + + node_list = deckhand_orchestrator.process_node_filter(nfs, design_data) + + assert len(node_list) == 2 + + def test_node_filter_by_nodetag(self, input_files, setup, deckhand_orchestrator, + deckhand_ingester): + input_file = input_files.join("deckhand_fullsite.yaml") + + design_ref = "file://%s" % str(input_file) + + design_status, design_data = deckhand_orchestrator.get_effective_site(design_ref) + + nfs = { + 'filter_set_type': + 'intersection', + 'filter_set': [ + { + 'filter_type': 'intersection', + 'node_tags': ['test'] + }, + ], + } + + node_list = deckhand_orchestrator.process_node_filter(nfs, design_data) + + assert len(node_list) == 3 + + def test_node_filter_by_nodelabel(self, input_files, setup, deckhand_orchestrator, + deckhand_ingester): + input_file = input_files.join("deckhand_fullsite.yaml") + + design_state = DrydockState() + design_ref = "file://%s" % str(input_file) + + design_status, design_data = deckhand_ingester.ingest_data( + design_state=design_state, design_ref=design_ref) + + nfs = { + 'filter_set_type': + 'intersection', + 'filter_set': [ + { + 'filter_type': 'intersection', + 'node_labels': {'foo': 'baz'}, }, ], } diff --git a/python/tests/yaml_samples/deckhand_fullsite.yaml b/python/tests/yaml_samples/deckhand_fullsite.yaml index a8f6b065..5a74a3c1 100644 --- a/python/tests/yaml_samples/deckhand_fullsite.yaml +++ b/python/tests/yaml_samples/deckhand_fullsite.yaml @@ -391,6 +391,8 @@ data: address: 172.16.100.23 metadata: rack: rack3 + owner_data: + foo: baz --- schema: 'drydock/HardwareProfile/v1' metadata: