Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom repos #482

Merged
merged 13 commits into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packaging/leapp-repository.spec
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Requires: leapp-repository-dependencies = 5

# IMPORTANT: this is capability provided by the leapp framework rpm.
# Check that 'version' this instead of the real framework rpm version.
Requires: leapp-framework >= 1.1, leapp-framework < 2
Requires: leapp-framework >= 1.2, leapp-framework < 2
Requires: python2-leapp

# That's temporary to ensure the obsoleted subpackage is not installed
Expand Down
24 changes: 4 additions & 20 deletions repos/system_upgrade/el7toel8/actors/checkrhsmsku/actor.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from leapp.actors import Actor
from leapp.libraries.common import rhsm
from leapp.libraries.actor import library
from leapp.models import Report, RHSMInfo
from leapp.reporting import create_report
from leapp import reporting
from leapp.tags import IPUWorkflowTag, ChecksPhaseTag


Expand All @@ -11,7 +9,8 @@ class CheckRedHatSubscriptionManagerSKU(Actor):
Ensure the system is subscribed to the subscription manager

This actor verifies that the system is correctly subscribed to via the Red Hat Subscription Manager and
has attached SKUs. The actor will inhibit the upgrade if there are none.
has attached SKUs. The actor will inhibit the upgrade if there are none and RHSM is not supposed
to be skipped.
"""

name = 'check_rhsmsku'
Expand All @@ -20,19 +19,4 @@ class CheckRedHatSubscriptionManagerSKU(Actor):
tags = (IPUWorkflowTag, ChecksPhaseTag)

def process(self):
if not rhsm.skip_rhsm():
for info in self.consume(RHSMInfo):
if not info.attached_skus:
create_report([
reporting.Title('The system is not registered or subscribed.'),
reporting.Summary(
'The system has to be registered and subscribed to be able to proceed the upgrade.'
),
reporting.Severity(reporting.Severity.HIGH),
reporting.Tags([reporting.Tags.SANITY]),
reporting.Flags([reporting.Flags.INHIBITOR]),
reporting.Remediation(
hint='Register your system with the subscription-manager tool and attach it to proper SKUs'
' to be able to proceed the upgrade.'),
reporting.RelatedResource('package', 'subscription-manager')
])
library.process()
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from leapp import reporting
from leapp.libraries.common import rhsm
from leapp.libraries.stdlib import api
from leapp.models import RHSMInfo
from leapp.reporting import create_report


def process():
if not rhsm.skip_rhsm():
for info in api.consume(RHSMInfo):
if not info.attached_skus:
create_report([
reporting.Title('The system is not registered or subscribed.'),
reporting.Summary(
'The system has to be registered and subscribed to be able to proceed'
' with the upgrade, unless the --no-rhsm option is specified when'
' executing leapp.'
),
reporting.Severity(reporting.Severity.HIGH),
reporting.Tags([reporting.Tags.SANITY]),
reporting.Flags([reporting.Flags.INHIBITOR]),
reporting.Remediation(
hint='Register your system with the subscription-manager tool and attach'
' proper SKUs to be able to proceed the upgrade or use the --no-rhsm'
' leapp option if you want to provide target repositories by yourself.'),
reporting.RelatedResource('package', 'subscription-manager')
])
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@

from leapp import reporting
from leapp.libraries.actor import library
from leapp.libraries.common import rhsm
from leapp.models import Report, RHSMInfo
from leapp.libraries.common.testutils import create_report_mocked
from leapp.libraries.stdlib import api
from leapp.models import RHSMInfo


def test_sku_report_skipped(monkeypatch, current_actor_context):
with monkeypatch.context() as context:
context.setenv('LEAPP_DEVEL_SKIP_RHSM', '1')
current_actor_context.feed(RHSMInfo(attached_skus=[]))
current_actor_context.run()
assert not list(current_actor_context.consume(Report))
def test_sku_report_skipped(monkeypatch):
monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: True)
monkeypatch.setattr(api, 'consume', lambda x: (RHSMInfo(attached_skus=[]),))
monkeypatch.setattr(library, 'create_report', create_report_mocked())
library.process()
assert not library.create_report.called


def test_sku_report_has_skus(monkeypatch, current_actor_context):
with monkeypatch.context() as context:
context.setenv('LEAPP_DEVEL_SKIP_RHSM', '0')
current_actor_context.feed(RHSMInfo(attached_skus=['testing-sku']))
current_actor_context.run()
assert not list(current_actor_context.consume(Report))
def test_sku_report_has_skus(monkeypatch):
monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: False)
monkeypatch.setattr(api, 'consume', lambda x: (RHSMInfo(attached_skus=['testing-sku']),))
monkeypatch.setattr(library, 'create_report', create_report_mocked())
library.process()
assert not library.create_report.called


def test_sku_report_has_no_skus(monkeypatch, current_actor_context):
with monkeypatch.context() as context:
context.setenv('LEAPP_DEVEL_SKIP_RHSM', '0')
current_actor_context.feed(RHSMInfo(attached_skus=[]))
current_actor_context.run()
reports = list(current_actor_context.consume(Report))
assert reports and len(reports) == 1
report_fields = reports[0].report
assert report_fields['severity'] == 'high'
assert report_fields['title'] == 'The system is not registered or subscribed.'
def test_sku_report_has_no_skus(monkeypatch):
monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: False)
monkeypatch.setattr(api, 'consume', lambda x: (RHSMInfo(attached_skus=[]),))
monkeypatch.setattr(library, 'create_report', create_report_mocked())
library.process()
assert library.create_report.called == 1
assert library.create_report.report_fields['title'] == 'The system is not registered or subscribed.'
assert library.create_report.report_fields['severity'] == 'high'
assert 'inhibitor' in library.create_report.report_fields['flags']
44 changes: 44 additions & 0 deletions repos/system_upgrade/el7toel8/actors/checktargetrepos/actor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from leapp.actors import Actor
from leapp.libraries.actor import library
from leapp.models import CustomTargetRepositoryFile, Report, TargetRepositories
from leapp.tags import IPUWorkflowTag, ChecksPhaseTag


class Checktargetrepos(Actor):
"""
Check whether target yum repositories are specified.

RHSM | ER | CTR | CTRF || result
-----+----+-----+------++-------
Yes | -- | --- | ---- || -
-----+----+-----+------++-------
No | -- | No | No || inhibit
-----+----+-----+------++-------
No | -- | No | Yes || inhibit
-----+----+-----+------++-------
No | No | Yes | No || warn/report info
-----+----+-----+------++-------
No | No | Yes | Yes || -
-----+----+-----+------++-------
No | Yes| Yes | No || -
-----+----+-----+------++-------
No | Yes| Yes | Yes || -

ER - config.get_env('LEAPP_ENABLE_REPOS') is non-empty
CTR - CustomTargetRepositories found
CTRF - the expected CustomTargetRepositoryFile found
RHSM - RHSM is used (it is not skipped)

This is not 100 % reliable check. This cover just the most obvious cases
that are expected to fail. Reporting of such issues in this way, here,
will be probably much more clear, without additional errors that could
be raised.
"""

name = 'checktargetrepos'
consumes = (CustomTargetRepositoryFile, TargetRepositories)
produces = (Report)
tags = (IPUWorkflowTag, ChecksPhaseTag)

def process(self):
library.process()
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
from leapp.models import CustomTargetRepositoryFile, TargetRepositories
from leapp.libraries.stdlib import api
from leapp import reporting
from leapp.libraries.common import config, rhsm


_IPU_DOC_URL = ('https://access.redhat.com/documentation/en-us/'
'red_hat_enterprise_linux/8/html-single/upgrading_to_rhel_8/index')
# TODO: we need to provide this path in a shared library
CUSTOM_REPO_PATH = '/etc/leapp/files/leapp_upgrade_repositories.repo'


def _any_custom_repo_defined():
for tr in api.consume(TargetRepositories):
if tr.custom_repos:
return True
return False


def _the_custom_repofile_defined():
for ctrf in api.consume(CustomTargetRepositoryFile):
if ctrf and ctrf.file == CUSTOM_REPO_PATH:
return True
return False


def _the_enablerepo_option_used():
return config.get_env('LEAPP_ENABLE_REPOS', None) is not None


def process():
if not rhsm.skip_rhsm():
# getting RH repositories through RHSM; resolved by seatbelts
# implemented in other actors
return

# rhsm skipped; take your seatbelts please
is_ctr = _any_custom_repo_defined()
is_ctrf = _the_custom_repofile_defined()
is_re = _the_enablerepo_option_used()
if not is_ctr:
# no rhsm, no custom repositories.. this will really not work :)
# TODO: add link to the RH article about use of custom repositories!!
# NOTE: we can put here now the link to the main document, as this
# will be described there or at least the link to the right document
# will be delivered here.
if is_ctrf:
summary_ctrf = '\n\nThe custom repository file has been detected. Maybe it is empty?'
else:
summary_ctrf = ''
reporting.create_report([
reporting.Title('Using RHSM has been skipped but no custom repositories have been delivered.'),
reporting.Summary(
'Leapp is run in the mode when the Red Hat Subscription Manager'
' is not used (the --no-rhsm option or the LEAPP_NO_RHSM=1'
' environment variable has been set) so leapp is not able to'
' obtain YUM/DNF repositories with the content for the target'
' system in the standard way. The content has to be delivered'
' by the user manually.'
),
reporting.Remediation(hint=(
'Create the repository file according to instructions in the'
' referred document on the following path with all'
' repositories that should be used during the upgrade: "{}".'
'\n\n{}'
.format(CUSTOM_REPO_PATH, summary_ctrf)
)),
reporting.Severity(reporting.Severity.HIGH),
reporting.Tags([reporting.Tags.SANITY]),
reporting.Flags([reporting.Flags.INHIBITOR]),
reporting.ExternalLink(url=_IPU_DOC_URL, title='UPGRADING TO RHEL 8'),
reporting.RelatedResource('file', CUSTOM_REPO_PATH),
])
elif not (is_ctrf or is_re):
# Some custom repositories have been discovered, but the custom repo
# file not - neither the --enablerepo option is used. Inform about
# the official recommended way.
reporting.create_report([
reporting.Title('Detected "CustomTargetRepositories" without using new provided mechanisms used.'),
reporting.Summary(
'Red Hat now provides an official way for using custom'
' repositories during the in-place upgrade through'
' the referred custom repository file or through the'
' --enablerepo option for leapp. The CustomTargetRepositories'
' have been produced from custom (own) actors?'
),
reporting.Remediation(hint=(
'Follow the new simple way to enable custom repositories'
' during the upgrade (see the referred document) or create'
' the empty custom repository file to acknowledge this report'
' message.'
)),
reporting.Severity(reporting.Severity.INFO),
reporting.ExternalLink(url=_IPU_DOC_URL, title='UPGRADING TO RHEL 8'),
reporting.RelatedResource('file', CUSTOM_REPO_PATH),
])
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
from collections import namedtuple

import pytest

from leapp.models import (CustomTargetRepository, CustomTargetRepositoryFile, EnvVar, Report,
RepositoryData, RHELTargetRepository, TargetRepositories)
from leapp.libraries.actor import library
from leapp import reporting
from leapp.libraries.stdlib import api
from leapp.libraries.common import rhsm
from leapp.libraries.common.testutils import create_report_mocked


class MockedConsume(object):
def __init__(self, *args):
self._msgs = []
for arg in args:
if not arg:
continue
if isinstance(arg, list):
self._msgs.extend(arg)
else:
self._msgs.append(arg)

def __call__(self, model):
return iter([msg for msg in self._msgs if isinstance(msg, model)])


class CurrentActorMocked(object):
def __init__(self, envars=None):
if envars:
envarsList = [EnvVar(name=key, value=value) for key, value in envars.items()]
else:
envarsList = []
self.configuration = namedtuple('configuration', ['leapp_env_vars'])(envarsList)

def __call__(self):
return self


_RHEL_REPOS = [
RHELTargetRepository(repoid='repo1'),
RHELTargetRepository(repoid='repo2'),
RHELTargetRepository(repoid='repo3'),
RHELTargetRepository(repoid='repo4'),
]

_CUSTOM_REPOS = [
CustomTargetRepository(repoid='repo1', name='repo1name', baseurl='repo1url', enabled=True),
CustomTargetRepository(repoid='repo2', name='repo2name', baseurl='repo2url', enabled=False),
CustomTargetRepository(repoid='repo3', name='repo3name', baseurl=None, enabled=True),
CustomTargetRepository(repoid='repo4', name='repo4name', baseurl=None, enabled=True),
]

_TARGET_REPOS_CUSTOM = TargetRepositories(rhel_repos=_RHEL_REPOS, custom_repos=_CUSTOM_REPOS)
_TARGET_REPOS_NO_CUSTOM = TargetRepositories(rhel_repos=_RHEL_REPOS)
_CUSTOM_TARGET_REPOFILE = CustomTargetRepositoryFile(file='/etc/leapp/files/leapp_upgrade_repositories.repo')


def test_checktargetrepos_rhsm(monkeypatch):
monkeypatch.setattr(reporting, 'create_report', create_report_mocked())
monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: False)
monkeypatch.setattr(api, 'consume', MockedConsume())
library.process()
assert reporting.create_report.called == 0


@pytest.mark.parametrize('enable_repos', [True, False])
@pytest.mark.parametrize('custom_target_repos', [True, False])
@pytest.mark.parametrize('custom_target_repofile', [True, False])
def test_checktargetrepos_no_rhsm(monkeypatch, enable_repos, custom_target_repos, custom_target_repofile):
mocked_consume = MockedConsume(_TARGET_REPOS_CUSTOM if custom_target_repos else _TARGET_REPOS_NO_CUSTOM)
if custom_target_repofile:
mocked_consume._msgs.append(_CUSTOM_TARGET_REPOFILE)
envvars = {'LEAPP_ENABLE_REPOS': 'hill,spencer'} if enable_repos else {}
monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(envvars))

monkeypatch.setattr(reporting, 'create_report', create_report_mocked())
monkeypatch.setattr(rhsm, 'skip_rhsm', lambda: True)
monkeypatch.setattr(api, 'consume', mocked_consume)

library.process()

if not custom_target_repos:
assert reporting.create_report.called == 1
assert 'inhibitor' in reporting.create_report.report_fields.get('flags', [])
elif not enable_repos and custom_target_repos and not custom_target_repofile:
assert reporting.create_report.called == 1
assert 'inhibitor' not in reporting.create_report.report_fields.get('flags', [])
else:
assert reporting.create_report.called == 0
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
def set_rhsm_release():
"""Set the RHSM release to the target RHEL 8 minor version."""
if rhsm.skip_rhsm():
api.current_logger().debug('Skipping setting the RHSM release due to the use of LEAPP_DEVEL_SKIP_RHSM.')
api.current_logger().debug('Skipping setting the RHSM release due to --no-rhsm or environment variables.')
return

if config.get_product_type('target') != 'ga':
Expand All @@ -29,8 +29,8 @@ def enable_rhsm_repos():
the known repositories.
"""
if rhsm.skip_rhsm():
api.current_logger().debug('Skipping enabling repositories through subscription-manager due to the use of'
' LEAPP_DEVEL_SKIP_RHSM.')
api.current_logger().debug('Skipping enabling repositories through subscription-manager due to --no-rhsm'
' or environment variables.')
return
try:
run(get_submgr_cmd(get_repos_to_enable()))
Expand Down
Loading