diff --git a/manager/integration/tests/node.py b/manager/integration/tests/node.py new file mode 100644 index 0000000000..d10f81449a --- /dev/null +++ b/manager/integration/tests/node.py @@ -0,0 +1,57 @@ +import pytest + +from kubernetes import client as k8sclient + +from common import get_self_host_id + + +@pytest.fixture( + params=[("foo/bar", "test", "NoSchedule"), + ("foo", "", "NoSchedule")] +) +def taint_nodes_exclude_self(request): + taint = k8sclient.V1Taint( + key = request.param[0], + value = request.param[1], + effect = request.param[2], + ) + + self_host_id = get_self_host_id() + + api = k8sclient.CoreV1Api() + node_items = api.list_node().items + saved_nodes = [] + for node in node_items: + if node.metadata.name == self_host_id: + continue + + saved_nodes.append(node) + + if node.spec.taints == None: + taints = [taint] + else: + taints = node.spec.taints + [taint] + payload = { + "spec": { + "taints": taints + } + } + api.patch_node(node.metadata.name, body=payload) + + yield saved_nodes + + for node in saved_nodes: + if node.metadata.name == self_host_id: + continue + + if node.spec.taints == None: + taints = [] + else: + taints = [node.spec.taints] + payload = { + "spec": { + "taints": taints + } + } + api.patch_node(node.metadata.name, body=payload) + diff --git a/manager/integration/tests/test_support_bundle.py b/manager/integration/tests/test_support_bundle.py index c5de9d9482..fb76a7c751 100644 --- a/manager/integration/tests/test_support_bundle.py +++ b/manager/integration/tests/test_support_bundle.py @@ -1,10 +1,11 @@ import pytest -import time import os import zipfile from tempfile import TemporaryDirectory +from node import taint_nodes_exclude_self # NOQA + from common import apps_api # NOQA from common import client # NOQA from common import core_api # NOQA @@ -21,6 +22,7 @@ from common import SETTING_NODE_SELECTOR from common import SETTING_SUPPORT_BUNDLE_FAILED_LIMIT +from common import SETTING_TAINT_TOLERATION @pytest.mark.support_bundle # NOQA @@ -216,3 +218,46 @@ def check_bundled_nodes_matches(node_names, zip, temp_dir): f'Nodes zipped in bundle do not match. \n' \ f'Expect = {expect_node_zips}\n' \ f'Got = {node_zips}\n' + + +@pytest.mark.support_bundle # NOQA +def test_support_bundle_agent_with_taint_toleration(client, taint_nodes_exclude_self): # NOQA + """ + Scenario: support bundle agent should respect taint toleration + + Issue: https://github.com/longhorn/longhorn/issues/5614 + + Given there are some tainted nodes in the cluster + And Longhorn tolerates the tainted nodes with setting "taint-toleration" + + When a support bundle is generated + + Then should be able to download the support bundle successfully + And support bundle should include all tainted nodes in node collection + + """ + # The taint-toleration is set up to match the "taint_nodes_exclude_self" + # fixture. + update_setting(client, SETTING_TAINT_TOLERATION, + "foo/bar=test:NoSchedule; foo:NoSchedule") + + resp = create_support_bundle(client) + node_id = resp['id'] + name = resp['name'] + + wait_for_support_bundle_state("ReadyForDownload", node_id, name, client) + + # The temporary directory will be automatically deleted outside of the + # "with" context manager. + with TemporaryDirectory(prefix="supportbundle-") as temp_dir: + download_path = f'{temp_dir}/{0}.zip'.format(name) + download_support_bundle(node_id, name, client, + target_path=download_path) + + with zipfile.ZipFile(download_path, 'r') as zip: + node_list = client.list_node() + node_names = [f"{node.name}" for node in node_list] + check_bundled_nodes_matches(node_names, zip, temp_dir) + + wait_for_support_bundle_cleanup(client) + check_all_support_bundle_managers_deleted()