Skip to content

Commit

Permalink
Add test case to verify artifacts repair at the Capsule side (Satelli…
Browse files Browse the repository at this point in the history
…teQE#14884)

* Add test case to verify artifacts repair at Capsule

* Merge yum/file and docker/AC into one test case
  • Loading branch information
vsedmik authored and jyejare committed Oct 19, 2024
1 parent 6a492e5 commit d0f47b8
Show file tree
Hide file tree
Showing 8 changed files with 301 additions and 27 deletions.
8 changes: 8 additions & 0 deletions robottelo/cli/capsule.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ def content_update_counts(cls, options):

return cls.execute(cls._construct_command(options), output_format='json')

@classmethod
def content_verify_checksum(cls, options):
"""Trigger verify checksum task."""

cls.command_sub = 'content verify-checksum'

return cls.execute(cls._construct_command(options), output_format='json')

@classmethod
def import_classes(cls, options):
"""Import puppet classes from puppet Capsule."""
Expand Down
2 changes: 1 addition & 1 deletion robottelo/constants/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,6 @@
CUSTOM_LOCAL_FILE = '/var/lib/pulp/imports/myrepo/test.txt'
CUSTOM_FILE_REPO_FILES_COUNT = 3
CUSTOM_RPM_SHA_512_FEED_COUNT = {'rpm': 35, 'errata': 4}
CUSTOM_REPODATA_PATH = '/var/lib/pulp/published/yum/https/repos'
CERT_PATH = "/etc/pki/ca-trust/source/anchors/"
CERT_DATA = {
'capsule_hostname': 'capsule.example.com',
Expand Down Expand Up @@ -859,6 +858,7 @@
}
CUSTOM_PUPPET_MODULE_REPOS_VERSION = '-0.2.0.tar.gz'

PULP_ARTIFACT_DIR = '/var/lib/pulp/media/artifact/'
PULP_EXPORT_DIR = '/var/lib/pulp/exports/'
PULP_IMPORT_DIR = '/var/lib/pulp/imports/'
EXPORT_LIBRARY_NAME = 'Export-Library'
Expand Down
42 changes: 41 additions & 1 deletion robottelo/host_helpers/capsule_mixins.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from datetime import datetime, timedelta
import time

from box import Box
from dateutil.parser import parse

from robottelo.constants import PUPPET_CAPSULE_INSTALLER, PUPPET_COMMON_INSTALLER_OPTS
from robottelo.constants import (
PULP_ARTIFACT_DIR,
PUPPET_CAPSULE_INSTALLER,
PUPPET_COMMON_INSTALLER_OPTS,
)
from robottelo.logging import logger
from robottelo.utils.installer import InstallerCommand

Expand Down Expand Up @@ -149,3 +154,38 @@ def get_published_repo_url(self, org, prod, repo, lce=None, cv=None):
if lce and cv:
return f'{self.url}/pulp/content/{org}/{lce}/{cv}/custom/{prod}/{repo}/'
return f'{self.url}/pulp/content/{org}/Library/custom/{prod}/{repo}/'

def get_artifacts(self, since=None, tz='UTC'):
"""Get paths of pulp artifact.
:param str since: Creation time of artifact we are looking for.
:param str tz: Time zone for `since` param.
:return: A list of artifacts paths.
"""
query = f'find {PULP_ARTIFACT_DIR} -type f'
if since:
query = f'{query} -newermt "{since} {tz}"'
return self.execute(query).stdout.splitlines()

def get_artifact_info(self, checksum=None, path=None):
"""Returns information about pulp artifact if found on FS,
throws FileNotFoundError otherwise.
:param checksum: Checksum of the artifact to look for.
:param path: Path to the artifact.
:return: A Box with artifact path, size, latest sum and info.
"""
if not (checksum or path):
raise ValueError('Either checksum or path must be specified')

if not path:
path = f'{PULP_ARTIFACT_DIR}{checksum[0:2]}/{checksum[2:]}'

res = self.execute(f'stat --format %s {path}')
if res.status:
raise FileNotFoundError(f'Artifact not found: {path}')
size = int(res.stdout)
real_sum = self.execute(f'sha256sum {path}').stdout.split()[0]
info = self.execute(f'file {path}').stdout.strip().split(': ')[1]

return Box(path=path, size=size, sum=real_sum, info=info)
12 changes: 7 additions & 5 deletions robottelo/host_helpers/satellite_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,15 @@ def get_repomd_revision(self, repo_url):

return match.group(0)

def md5_by_url(self, url):
"""Returns md5 checksum of a file, accessible via URL. Useful when you want
def checksum_by_url(self, url, sum_type='md5sum'):
"""Returns desired checksum of a file, accessible via URL. Useful when you want
to calculate checksum but don't want to deal with storing a file and
removing it afterwards.
:param str url: URL of a file.
:return str: string containing md5 checksum.
:param str sum_type: Checksum type like md5sum, sha256sum, sha512sum, etc.
Defaults to md5sum.
:return str: string containing the checksum.
:raises: AssertionError: If non-zero return code received (file couldn't be
reached or calculation was not successful).
"""
Expand All @@ -131,8 +133,8 @@ def md5_by_url(self, url):
if result.status != 0:
raise AssertionError(f'Failed to get `{filename}` from `{url}`.')
return self.execute(
f'wget -qO - {url} | tee {filename} | md5sum | awk \'{{print $1}}\''
).stdout
f'wget -qO - {url} | tee {filename} | {sum_type} | awk \'{{print $1}}\''
).stdout.strip()

def upload_manifest(self, org_id, manifest=None, interface='API', timeout=None):
"""Upload a manifest using the requested interface.
Expand Down
23 changes: 11 additions & 12 deletions tests/foreman/api/test_capsulecontent.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
FAKE_FILE_NEW_NAME,
KICKSTART_CONTENT,
PRDS,
PULP_ARTIFACT_DIR,
REPOS,
REPOSET,
RH_CONTAINER_REGISTRY_HUB,
Expand Down Expand Up @@ -635,9 +636,9 @@ def test_positive_on_demand_sync(
assert len(caps_files) == packages_count

# Download a package from the Capsule and get its md5 checksum
published_package_md5 = target_sat.md5_by_url(f'{caps_repo_url}/{package}')
published_package_md5 = target_sat.checksum_by_url(f'{caps_repo_url}/{package}')
# Get md5 checksum of source package
package_md5 = target_sat.md5_by_url(f'{repo_url}/{package}')
package_md5 = target_sat.checksum_by_url(f'{repo_url}/{package}')
# Assert checksums are matching
assert package_md5 == published_package_md5

Expand Down Expand Up @@ -847,8 +848,10 @@ def test_positive_sync_kickstart_repo(

# Check kickstart specific files
for file in KICKSTART_CONTENT:
sat_file = target_sat.md5_by_url(f'{target_sat.url}/{url_base}/{file}')
caps_file = target_sat.md5_by_url(f'{module_capsule_configured.url}/{url_base}/{file}')
sat_file = target_sat.checksum_by_url(f'{target_sat.url}/{url_base}/{file}')
caps_file = target_sat.checksum_by_url(
f'{module_capsule_configured.url}/{url_base}/{file}'
)
assert sat_file == caps_file

# Check packages
Expand Down Expand Up @@ -1162,8 +1165,8 @@ def test_positive_sync_file_repo(
assert sat_files == caps_files

for file in sat_files:
sat_file = target_sat.md5_by_url(f'{sat_repo_url}{file}')
caps_file = target_sat.md5_by_url(f'{caps_repo_url}{file}')
sat_file = target_sat.checksum_by_url(f'{sat_repo_url}{file}')
caps_file = target_sat.checksum_by_url(f'{caps_repo_url}{file}')
assert sat_file == caps_file

@pytest.mark.tier4
Expand Down Expand Up @@ -1370,9 +1373,7 @@ def test_positive_remove_capsule_orphans(
assert sync_status['result'] == 'success', 'Capsule sync task failed.'

# Ensure the RPM artifacts were created.
result = capsule_configured.execute(
'ls /var/lib/pulp/media/artifact/*/* | xargs file | grep RPM'
)
result = capsule_configured.execute(f'ls {PULP_ARTIFACT_DIR}*/* | xargs file | grep RPM')
assert not result.status, 'RPM artifacts are missing after capsule sync.'

# Remove the Library LCE from the capsule and resync it.
Expand Down Expand Up @@ -1401,9 +1402,7 @@ def test_positive_remove_capsule_orphans(
)

# Ensure the artifacts were removed.
result = capsule_configured.execute(
'ls /var/lib/pulp/media/artifact/*/* | xargs file | grep RPM'
)
result = capsule_configured.execute(f'ls {PULP_ARTIFACT_DIR}*/* | xargs file | grep RPM')
assert result.status, 'RPM artifacts are still present. They should be gone.'

@pytest.mark.skip_if_not_set('capsule')
Expand Down
4 changes: 2 additions & 2 deletions tests/foreman/api/test_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -1250,12 +1250,12 @@ def test_positive_sync_with_treeinfo_ignore(
repo = repo.update(['mirroring_policy', 'ignorable_content'])
repo.sync()
with pytest.raises(AssertionError):
target_sat.md5_by_url(f'{repo.full_path}.treeinfo')
target_sat.checksum_by_url(f'{repo.full_path}.treeinfo')

repo.ignorable_content = []
repo = repo.update(['ignorable_content'])
repo.sync()
assert target_sat.md5_by_url(
assert target_sat.checksum_by_url(
f'{repo.full_path}.treeinfo'
), 'The treeinfo file is missing in the KS repo but it should be there.'

Expand Down
Loading

0 comments on commit d0f47b8

Please sign in to comment.