Module harvester_e2e_tests.apis.test_support_bundle
Classes
class TestSupportBundle
-
Expand source code
@pytest.mark.p0 @pytest.mark.smoke @pytest.mark.support_bundle class TestSupportBundle: @pytest.mark.dependency(name="create support bundle") def test_create(self, api_client, unique_name, support_bundle_state): code, data = api_client.supportbundle.create(unique_name) assert 201 == code, (code, data) support_bundle_state.uid = data['metadata']['name'] @pytest.mark.dependency(name="get support bundle", depends=["create support bundle"]) def test_get(self, api_client, support_bundle_state): code, data = api_client.supportbundle.get(support_bundle_state.uid) assert 200 == code, (code, data) @pytest.mark.dependency(name="donwnload support bundle", depends=["get support bundle"]) def test_download(self, api_client, support_bundle_state, wait_timeout): endtime = datetime.now() + timedelta(seconds=wait_timeout) while endtime > datetime.now(): code, data = api_client.supportbundle.get(support_bundle_state.uid) if 100 == data.get('status', {}).get('progress', 0): break sleep(5) else: raise AssertionError( f"Failed to wait supportbundle ready with {wait_timeout} timed out\n" f"Still got {code} in {data}" ) code, ctx = api_client.supportbundle.download(support_bundle_state.uid) assert 200 == code, (code, ctx) with ZipFile(BytesIO(ctx), 'r') as zf: files = zf.namelist() assert 0 != len(files) support_bundle_state.files = files support_bundle_state.fio.write(ctx) support_bundle_state.fio.seek(0) @pytest.mark.dependency(depends=["donwnload support bundle"]) def test_logfile_exists(self, support_bundle_state): patterns = [r"^.*/logs/cattle-fleet-local-system/fleet-agent-.*/fleet-agent.log", r"^.*/logs/cattle-fleet-system/fleet-controller-.*/fleet-controller.log", r"^.*/logs/cattle-fleet-system/gitjob-.*/gitjob.log"] matches = [] for f in support_bundle_state.files: for pattern in patterns: matches.extend([f] if re.match(pattern, f) else []) assert len(matches) == len(patterns), ( f"Some file(s) not found, files: {matches}\npatterns: {patterns}" ) @pytest.mark.dependency(depends=["donwnload support bundle"]) def test_plan_secrets_exists(self, support_bundle_state): # ref: https://github.com/harvester/tests/issues/603 path = r"^.*/yamls/namespaced/fleet-local/v1/secrets.yaml" for fname in support_bundle_state.files: if re.match(path, fname): break else: raise AssertionError(f"{path} not existed") try: with ZipFile(support_bundle_state.fio, 'r') as zf: with zf.open(fname) as file: secrets = yaml.safe_load(file) assert all('rke.cattle.io/machine-plan' == o['type'] for o in secrets['items']), ( "secrets got unexpected type:\n" f"{[o['type'] for o in secrets['items']]}" ) finally: support_bundle_state.fio.seek(0) @pytest.mark.dependency(depends=["donwnload support bundle"]) def test_secret_file_exists(self, support_bundle_state): ''' ref: https://github.com/harvester/tests/issues/603 ''' pattern = r"^.*/yamls/namespaced/fleet-local/v1/secrets\.yaml" for fname in support_bundle_state.files: if re.match(pattern, fname): break else: raise AssertionError("secret file is not available in namespaced/fleet-local") with ZipFile(support_bundle_state.fio, 'r') as zf: ctx = zf.read(fname) support_bundle_state.fio.seek(0) secret = yaml.safe_load(ctx) assert secret.get('items') fails = [] for it in secret['items']: if it.get('type') != "rke.cattle.io/machine-plan" or not it.get('data'): fails.append(it) assert not fails, ( f"Got {len(fails)} incorrect item(s) from secret file," " expected type should be 'rke.cattle.io/machine-plan'" " and `data` field should not be empty but got:\n" f"{fails}" ) @pytest.mark.dependency(depends=["donwnload support bundle"]) def test_hardware_info_exists(self, support_bundle_state): ''' ref: https://github.com/harvester/tests/issues/569 ''' nodes, pattern = [], r"^.*/nodes/.*.zip" for fname in support_bundle_state.files: if re.match(pattern, fname): nodes.append(fname) assert nodes, "Host information is not generated" with ZipFile(support_bundle_state.fio, 'r') as zf: b_nodes = [zf.read(n) for n in nodes] support_bundle_state.fio.seek(0) fails, txz_pattern = [], r"^.*/scc_supportconfig.*.txz" for npath, node_byte in zip(nodes, b_nodes): node_name = npath.rsplit("/", 1)[-1] with ZipFile(BytesIO(node_byte), 'r') as zf: try: txz_file = next(i for i in zf.namelist() if re.match(txz_pattern, i)) txz_byte = zf.read(txz_file) except StopIteration: fails.append(f"`.txz` file is not available in {node_name}") continue try: with tarfile.open(mode="r:xz", fileobj=BytesIO(txz_byte)) as xz: txt_m = next(m for m in xz.getmembers() if m.name.endswith("hardware.txt")) hardware_ctx = xz.extractfile(txt_m).read().decode() except StopIteration: fails.append(f"`hardware.txt` file is not available in {node_name}") continue if "lsusb" not in hardware_ctx or "hwinfo" not in hardware_ctx: fails.append( f"Node {node_name}'s Hardware info not contains lsusb/hwinfo command ouput\n" f"got: {hardware_ctx}" ) assert not fails, ( f"Got {len(fails)} incorrect item(s):\n" "\n".join(fails) ) @pytest.mark.dependency(depends=["get support bundle"]) def test_delete(self, api_client, support_bundle_state): code, data = api_client.supportbundle.delete(support_bundle_state.uid) # ???: Downloaded support bundle will be deleted automatically assert 404 == code, (code, data)
Class variables
var pytestmark
Methods
def test_create(self, api_client, unique_name, support_bundle_state)
-
Expand source code
@pytest.mark.dependency(name="create support bundle") def test_create(self, api_client, unique_name, support_bundle_state): code, data = api_client.supportbundle.create(unique_name) assert 201 == code, (code, data) support_bundle_state.uid = data['metadata']['name']
def test_delete(self, api_client, support_bundle_state)
-
Expand source code
@pytest.mark.dependency(depends=["get support bundle"]) def test_delete(self, api_client, support_bundle_state): code, data = api_client.supportbundle.delete(support_bundle_state.uid) # ???: Downloaded support bundle will be deleted automatically assert 404 == code, (code, data)
def test_download(self, api_client, support_bundle_state, wait_timeout)
-
Expand source code
@pytest.mark.dependency(name="donwnload support bundle", depends=["get support bundle"]) def test_download(self, api_client, support_bundle_state, wait_timeout): endtime = datetime.now() + timedelta(seconds=wait_timeout) while endtime > datetime.now(): code, data = api_client.supportbundle.get(support_bundle_state.uid) if 100 == data.get('status', {}).get('progress', 0): break sleep(5) else: raise AssertionError( f"Failed to wait supportbundle ready with {wait_timeout} timed out\n" f"Still got {code} in {data}" ) code, ctx = api_client.supportbundle.download(support_bundle_state.uid) assert 200 == code, (code, ctx) with ZipFile(BytesIO(ctx), 'r') as zf: files = zf.namelist() assert 0 != len(files) support_bundle_state.files = files support_bundle_state.fio.write(ctx) support_bundle_state.fio.seek(0)
def test_get(self, api_client, support_bundle_state)
-
Expand source code
@pytest.mark.dependency(name="get support bundle", depends=["create support bundle"]) def test_get(self, api_client, support_bundle_state): code, data = api_client.supportbundle.get(support_bundle_state.uid) assert 200 == code, (code, data)
def test_hardware_info_exists(self, support_bundle_state)
-
Expand source code
@pytest.mark.dependency(depends=["donwnload support bundle"]) def test_hardware_info_exists(self, support_bundle_state): ''' ref: https://github.com/harvester/tests/issues/569 ''' nodes, pattern = [], r"^.*/nodes/.*.zip" for fname in support_bundle_state.files: if re.match(pattern, fname): nodes.append(fname) assert nodes, "Host information is not generated" with ZipFile(support_bundle_state.fio, 'r') as zf: b_nodes = [zf.read(n) for n in nodes] support_bundle_state.fio.seek(0) fails, txz_pattern = [], r"^.*/scc_supportconfig.*.txz" for npath, node_byte in zip(nodes, b_nodes): node_name = npath.rsplit("/", 1)[-1] with ZipFile(BytesIO(node_byte), 'r') as zf: try: txz_file = next(i for i in zf.namelist() if re.match(txz_pattern, i)) txz_byte = zf.read(txz_file) except StopIteration: fails.append(f"`.txz` file is not available in {node_name}") continue try: with tarfile.open(mode="r:xz", fileobj=BytesIO(txz_byte)) as xz: txt_m = next(m for m in xz.getmembers() if m.name.endswith("hardware.txt")) hardware_ctx = xz.extractfile(txt_m).read().decode() except StopIteration: fails.append(f"`hardware.txt` file is not available in {node_name}") continue if "lsusb" not in hardware_ctx or "hwinfo" not in hardware_ctx: fails.append( f"Node {node_name}'s Hardware info not contains lsusb/hwinfo command ouput\n" f"got: {hardware_ctx}" ) assert not fails, ( f"Got {len(fails)} incorrect item(s):\n" "\n".join(fails) )
def test_logfile_exists(self, support_bundle_state)
-
Expand source code
@pytest.mark.dependency(depends=["donwnload support bundle"]) def test_logfile_exists(self, support_bundle_state): patterns = [r"^.*/logs/cattle-fleet-local-system/fleet-agent-.*/fleet-agent.log", r"^.*/logs/cattle-fleet-system/fleet-controller-.*/fleet-controller.log", r"^.*/logs/cattle-fleet-system/gitjob-.*/gitjob.log"] matches = [] for f in support_bundle_state.files: for pattern in patterns: matches.extend([f] if re.match(pattern, f) else []) assert len(matches) == len(patterns), ( f"Some file(s) not found, files: {matches}\npatterns: {patterns}" )
def test_plan_secrets_exists(self, support_bundle_state)
-
Expand source code
@pytest.mark.dependency(depends=["donwnload support bundle"]) def test_plan_secrets_exists(self, support_bundle_state): # ref: https://github.com/harvester/tests/issues/603 path = r"^.*/yamls/namespaced/fleet-local/v1/secrets.yaml" for fname in support_bundle_state.files: if re.match(path, fname): break else: raise AssertionError(f"{path} not existed") try: with ZipFile(support_bundle_state.fio, 'r') as zf: with zf.open(fname) as file: secrets = yaml.safe_load(file) assert all('rke.cattle.io/machine-plan' == o['type'] for o in secrets['items']), ( "secrets got unexpected type:\n" f"{[o['type'] for o in secrets['items']]}" ) finally: support_bundle_state.fio.seek(0)
def test_secret_file_exists(self, support_bundle_state)
-
Expand source code
@pytest.mark.dependency(depends=["donwnload support bundle"]) def test_secret_file_exists(self, support_bundle_state): ''' ref: https://github.com/harvester/tests/issues/603 ''' pattern = r"^.*/yamls/namespaced/fleet-local/v1/secrets\.yaml" for fname in support_bundle_state.files: if re.match(pattern, fname): break else: raise AssertionError("secret file is not available in namespaced/fleet-local") with ZipFile(support_bundle_state.fio, 'r') as zf: ctx = zf.read(fname) support_bundle_state.fio.seek(0) secret = yaml.safe_load(ctx) assert secret.get('items') fails = [] for it in secret['items']: if it.get('type') != "rke.cattle.io/machine-plan" or not it.get('data'): fails.append(it) assert not fails, ( f"Got {len(fails)} incorrect item(s) from secret file," " expected type should be 'rke.cattle.io/machine-plan'" " and `data` field should not be empty but got:\n" f"{fails}" )
class TestSupportBundleNegative
-
Expand source code
@pytest.mark.p0 @pytest.mark.sanity @pytest.mark.negative @pytest.mark.support_bundle class TestSupportBundleNegative: def test_get_not_exist(self, api_client, unique_name): code, data = api_client.supportbundle.get(unique_name) assert 404 == code, (code, data) assert "NotFound" == data.get('reason'), (code, data) def test_delete_not_exist(self, api_client, unique_name): code, data = api_client.supportbundle.delete(unique_name) assert 404 == code, (code, data) assert "NotFound" == data.get('reason'), (code, data)
Class variables
var pytestmark
Methods
def test_delete_not_exist(self, api_client, unique_name)
-
Expand source code
def test_delete_not_exist(self, api_client, unique_name): code, data = api_client.supportbundle.delete(unique_name) assert 404 == code, (code, data) assert "NotFound" == data.get('reason'), (code, data)
def test_get_not_exist(self, api_client, unique_name)
-
Expand source code
def test_get_not_exist(self, api_client, unique_name): code, data = api_client.supportbundle.get(unique_name) assert 404 == code, (code, data) assert "NotFound" == data.get('reason'), (code, data)