Skip to content

Commit

Permalink
Initial work to demonstrate an actor config framework.
Browse files Browse the repository at this point in the history
* Modify the upgrade workflow to load the actor configuration to be available to the actors
  [_] Note: The same sort of code needs to be added to other workflows that need actor config.  For
      instance, the pre-upgrade workflow.
* Define potential config schemas for RHUI and for listing rpm packages to be treated specially
  during transations.
* Add config schemas to the rpmtransactionconfigtaskscollector as a sample of using it.

Depends-On: 870
  • Loading branch information
abadger committed Sep 13, 2024
1 parent 41e32e3 commit 4e4ad3a
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 6 deletions.
12 changes: 12 additions & 0 deletions commands/upgrade/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import sys
import uuid

from leapp.actor import config as actor_config
from leapp.cli.commands import command_utils
from leapp.cli.commands.config import get_config
from leapp.cli.commands.upgrade import breadcrumbs, util
Expand Down Expand Up @@ -90,6 +91,17 @@ def upgrade(args, breadcrumbs):
except LeappError as exc:
raise CommandError(exc.message)
workflow = repositories.lookup_workflow('IPUWorkflow')(auto_reboot=args.reboot)

# Read the Actor Config and validate it against the schemas saved in the
# configuration.
actor_config_schemas = tuple(actor.config_schemas for actor in repositories.actors)
actor_config_schemas = actor_config.normalize_schemas(actor_config_schemas)
actor_config_path = cfg.get('actor_config', 'path')
# Note: actor_config.load() stores the loaded actor config into a global
# variable which can then be accessed by functions in that file. Is this
# the right way to store that information?
actor_config.load(actor_config_path, actor_config_schemas)

util.process_whitelist_experimental(repositories, workflow, configuration, logger)
util.warn_if_unsupported(configuration)
with beautify_actor_exception():
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from leapp.actors import Actor
from leapp.configs import Transaction_ToInstall, Transaction_ToKeep, Transaction_ToRemove
from leapp.libraries.actor.rpmtransactionconfigtaskscollector import load_tasks
from leapp.models import DistributionSignedRPM, RpmTransactionTasks
from leapp.tags import FactsPhaseTag, IPUWorkflowTag


CONFIGURATION_BASE_PATH = '/etc/leapp/transaction'


Expand All @@ -13,11 +15,11 @@ class RpmTransactionConfigTasksCollector(Actor):
After collecting task data from /etc/leapp/transaction directory, a message with relevant data
will be produced.
"""

config_schemas = (Transaction_ToInstall, Transaction_ToKeep, Transaction_ToRemove)
name = 'rpm_transaction_config_tasks_collector'
consumes = (DistributionSignedRPM,)
produces = (RpmTransactionTasks,)
tags = (FactsPhaseTag, IPUWorkflowTag)

def process(self):
self.produce(load_tasks(CONFIGURATION_BASE_PATH, self.log))
self.produce(load_tasks(self.config, self.log))
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ def load_tasks_file(path, logger):
return []


def load_tasks(base_dir, logger):
def load_tasks(config, logger):
# Loads configuration files to_install, to_keep, and to_remove from the given base directory
rpms = next(api.consume(DistributionSignedRPM))
rpm_names = [rpm.name for rpm in rpms.items]
to_install = load_tasks_file(os.path.join(base_dir, 'to_install'), logger)
to_install = config['transaction']['to_install']
# we do not want to put into rpm transaction what is already installed (it will go to "to_upgrade" bucket)
to_install_filtered = [pkg for pkg in to_install if pkg not in rpm_names]

Expand All @@ -34,5 +34,5 @@ def load_tasks(base_dir, logger):

return RpmTransactionTasks(
to_install=to_install_filtered,
to_keep=load_tasks_file(os.path.join(base_dir, 'to_keep'), logger),
to_remove=load_tasks_file(os.path.join(base_dir, 'to_remove'), logger))
to_keep=config['transaction']['to_keep'],
to_remove=config['transaction']['to_remove'])
Empty file.
81 changes: 81 additions & 0 deletions repos/system_upgrade/common/configs/rhui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""
Configuration keys for RHUI.
In case of RHUI in private regions it usual that publicly known RHUI data
is not valid. In such cases it's possible to provide the correct expected
RHUI data to correct the in-place upgrade process.
"""

from leapp.models import fields
from leapp.actors.configs import Config


class RhuiSrcPkg(Config):
section = "rhui"
name = "src_pkg"
type_ = fields.String(default="rhui")
default = "rhui"
description = """
The name of the source RHUI client RPM (installed on the system).
Default: rhui.
"""


class RhuiTargetPkg(Config):
section = "rhui"
name = "target_pkg"
type_ = fields.String(default="rhui")
default = "rhui"
description = """
The name of the target RHUI client RPM (to be installed on the system).
Default: rhui
"""


class RhuiLeappRhuiPkg(Config):
section = "rhui"
name = "leapp_rhui_pkg"
type_ = fields.String(default="leapp-rhui")
default = "leapp-rhui"
description = """
The name of the leapp-rhui RPM. Default: leapp-rhui
"""


class RhuiLeappRhuiPkgRepo(Config):
section = "rhui"
name = "leapp_rhui_pkg_repo"
type_ = fields.String(default="rhel-base")
default = "rhel-base"
description = """
The repository ID containing the specified leapp-rhui RPM.
Default: rhel-base
"""


all_rhui_cfg = (RhuiSrcPkg, RhuiTargetPkg, RhuiLeappRhuiPkg, RhuiLeappRhuiPkg)
# Usage: from configs import rhui
# class MyActor:
# [...]
# configs = all_rhui_cfg + (MyConfig,)

# TODO: We need to implement fields.Map before this can be enabled
'''
class RhuiFileMap(Config):
section = "rhui"
name = "file_map"
type_ = fields.Map(fields.String())
description = """
Define directories to which paritcular files provided by the leapp-rhui
RPM should be installed. The files in 'files_map' are provided by
special Leapp rpms (per cloud) and are supposed to be delivered into the
repos/system_upgrade/common/files/rhui/<PROVIDER> directory.
These files are usually needed to get access to the target system repositories
using RHUI. Typically these are certificates, keys, and repofiles with the
target RHUI repositories.
The key is the name of the file, the value is the expected directory
where the file should be installed on the upgraded system.
"""
'''
64 changes: 64 additions & 0 deletions repos/system_upgrade/common/configs/rpm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""
Configuration keys for dnf transactions.
"""

from leapp.models import fields
from leapp.actors.configs import Config


# * Nested containers?
# * Duplication of default value in type_ and Config. If we eliminate that, we need to extract
# default from the type_ for the documentation.
# * We probably want to allow dicts in Config. But IIRC, dicts were
# specifically excluded for model fields. Do we need something that restricts
# where fields are valid?
# * Test that type validation is strict. For instance, giving an integer like 644 to
# a field.String() is an error.
class Transaction_ToInstall(Config):
section = "transaction"
name = "to_install"
type_ = fields.List(fields.String(), default=[])
default = []
description = """
List of packages to be added to the upgrade transaction.
Signed packages which are already installed will be skipped.
"""


class Transaction_ToKeep(Config):
section = "transaction"
name = "to_keep"
type_ = fields.List(fields.String(), default=[
"leapp",
"python2-leapp",
"python3-leapp",
"leapp-repository",
"snactor",
])
default = [
"leapp",
"python2-leapp",
"python3-leapp",
"leapp-repository",
"snactor",
]
description = """
List of packages to be kept in the upgrade transaction. The default is
leapp, python2-leapp, python3-leapp, leapp-repository, snactor. If you
override this, remember to include the default values if applicable.
"""


class Transaction_ToRemove(Config):
section = "transaction"
name = "to_remove"
type_ = fields.List(fields.String(), default=[
"initial-setup",
])
default = ["initial-setup"]
description = """
List of packages to be removed from the upgrade transaction. The default
is initial-setup which should be removed to avoid it asking for EULA
acceptance during upgrade. If you override this, remember to include the
default values if applicable.
"""

0 comments on commit 4e4ad3a

Please sign in to comment.