From b8fde8337a5248fe4487ab72229a099438c7fc8a Mon Sep 17 00:00:00 2001 From: eabdullin Date: Thu, 27 Feb 2025 16:14:12 +0000 Subject: [PATCH] Import from CS git --- .gitignore | 2 +- .leapp.metadata | 2 +- ...eferences-from-master-branch-to-main.patch | 525 ------ ...-Update-docs-engine-and-dependencies.patch | 509 ------ ...mplement-actor-configuration-support.patch | 1575 ----------------- ...ore-too-many-params-lines-yield-from.patch | 43 - ...ckaging-bump-leapp-framework-version.patch | 37 - ...uce-etc-leapp-actor_conf.d-directory.patch | 35 - SPECS/leapp.spec | 24 +- 9 files changed, 12 insertions(+), 2740 deletions(-) delete mode 100644 SOURCES/0001-Update-references-from-master-branch-to-main.patch delete mode 100644 SOURCES/0002-docs-Update-docs-engine-and-dependencies.patch delete mode 100644 SOURCES/0003-configs-implement-actor-configuration-support.patch delete mode 100644 SOURCES/0004-pylint-ignore-too-many-params-lines-yield-from.patch delete mode 100644 SOURCES/0005-packaging-bump-leapp-framework-version.patch delete mode 100644 SOURCES/0006-spec-Introduce-etc-leapp-actor_conf.d-directory.patch diff --git a/.gitignore b/.gitignore index cf5b3c2..fdc601b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/leapp-0.18.0.tar.gz +SOURCES/leapp-0.19.0.tar.gz diff --git a/.leapp.metadata b/.leapp.metadata index b0717aa..e7b1dd2 100644 --- a/.leapp.metadata +++ b/.leapp.metadata @@ -1 +1 @@ -6f78400cf9fac51624d105c5be94945bd68e79cf SOURCES/leapp-0.18.0.tar.gz +03632cf33458ec52b7fea2b8c7a5da68d953d4eb SOURCES/leapp-0.19.0.tar.gz diff --git a/SOURCES/0001-Update-references-from-master-branch-to-main.patch b/SOURCES/0001-Update-references-from-master-branch-to-main.patch deleted file mode 100644 index 45e8c7f..0000000 --- a/SOURCES/0001-Update-references-from-master-branch-to-main.patch +++ /dev/null @@ -1,525 +0,0 @@ -From 97871166d037fce1029428d369541ec2d6eeeef7 Mon Sep 17 00:00:00 2001 -From: Vojtech Sokol -Date: Mon, 2 Sep 2024 17:22:11 +0200 -Subject: [PATCH 1/6] Update references from master branch to main - -Focus was on making the CI and GitHub actions work after the default -branch was switched from master to main. - -See: OAMG-4907 ---- - .github/workflows/pr-welcome-msg.yml | 4 ++-- - .github/workflows/reuse-copr-build.yml | 4 ++-- - .github/workflows/unit-tests.yml | 10 +++++----- - .packit.yaml | 6 +++--- - Makefile | 8 ++++---- - docs/source/best-practices.md | 20 +++++++++---------- - docs/source/build-schema.md | 4 ++-- - .../compatibility-with-leapp-repository.md | 2 +- - docs/source/contributing.md | 6 +++--- - docs/source/dependencies-leapp-repository.md | 8 ++++---- - docs/source/dependencies.md | 2 +- - docs/source/deprecation.md | 2 +- - docs/source/devenv-install.md | 4 ++-- - docs/source/el7toel8/actor-rhel7-to-rhel8.md | 12 +++++------ - .../source/el7toel8/inhibit-rhel7-to-rhel8.md | 4 ++-- - docs/source/test-actors.md | 4 ++-- - docs/source/unit-testing.md | 8 ++++---- - packaging/leapp.spec | 4 ++-- - 18 files changed, 56 insertions(+), 56 deletions(-) - -diff --git a/.github/workflows/pr-welcome-msg.yml b/.github/workflows/pr-welcome-msg.yml -index af5d543..66d001e 100644 ---- a/.github/workflows/pr-welcome-msg.yml -+++ b/.github/workflows/pr-welcome-msg.yml -@@ -25,9 +25,9 @@ jobs: - - **/packit copr-build** to submit a public copr build using packit - - To launch regression testing public members of oamg organization can leave the following comment: -- - **/rerun** to schedule basic regression tests using this pr build and leapp-repository\*master\* as artifacts -+ - **/rerun** to schedule basic regression tests using this pr build and leapp-repository\*main\* as artifacts - - **/rerun 42** to schedule basic regression tests using this pr build and leapp-repository\*PR42\* as artifacts -- - **/rerun-sst** to schedule sst tests using this pr build and leapp-repository\*master\* as artifacts -+ - **/rerun-sst** to schedule sst tests using this pr build and leapp-repository\*main\* as artifacts - - **/rerun-sst 42** to schedule sst tests using this pr build and leapp-repository\*PR42\* as artifacts - - Please [open ticket](https://url.corp.redhat.com/oamg-ci-issue) in case you experience technical problem with the CI. (RH internal only) -diff --git a/.github/workflows/reuse-copr-build.yml b/.github/workflows/reuse-copr-build.yml -index a935c7e..b0079a1 100644 ---- a/.github/workflows/reuse-copr-build.yml -+++ b/.github/workflows/reuse-copr-build.yml -@@ -59,7 +59,7 @@ jobs: - echo "::set-output name=sha::$(git rev-parse --short HEAD)" - echo "::set-output name=ref::refs/pull/${{ steps.pr_nr.outputs.pr_nr }}/head" - -- - name: Get latest leapp-repository master copr build id -+ - name: Get latest leapp-repository main copr build id - id: get_latest_lpr_copr_build_id - if: ${{ steps.leapp_repository_pr_regex_match.outputs.match == '' }} - run: | -@@ -73,7 +73,7 @@ jobs: - EOF - - pip install copr-cli -- REGEX='leapp-repository.*master.*' COPR_REPO='@oamg/leapp' _COPR_CONFIG=copr_fedora.conf python ${{ github.workspace }}/utils/get_latest_copr_build > latest_lpr -+ REGEX='leapp-repository.*main.*' COPR_REPO='@oamg/leapp' _COPR_CONFIG=copr_fedora.conf python ${{ github.workspace }}/utils/get_latest_copr_build > latest_lpr - COPR_ID=$(cat latest_lpr) - echo "::set-output name=copr_id::${COPR_ID##*/}" - -diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml -index e67264b..a0a3942 100644 ---- a/.github/workflows/unit-tests.yml -+++ b/.github/workflows/unit-tests.yml -@@ -2,10 +2,10 @@ name: Unit Tests - on: - push: - branches: -- - master -+ - main - pull_request: - branches: -- - master -+ - main - - jobs: - test: -@@ -33,9 +33,9 @@ jobs: - uses: actions/checkout@v4 - with: - fetch-depth: '0' -- - name: Set master to origin/master -- if: github.ref != 'refs/heads/master' -+ - name: Set main to origin/main -+ if: github.ref != 'refs/heads/main' - run: | -- git branch -f master origin/master -+ git branch -f main origin/main - - name: ${{matrix.scenarios.name}} - run: script -e -c /bin/bash -c 'TERM=xterm podman build --security-opt=seccomp=unconfined -t leapp-tests -f res/container-tests/Containerfile.${{matrix.scenarios.container}} res/container-tests && PYTHON_VENV=${{matrix.scenarios.python}} REPOSITORIES=${{matrix.scenarios.repos}} podman run --security-opt=seccomp=unconfined --rm -ti -v ${PWD}:/payload --env=PYTHON_VENV --env=REPOSITORIES leapp-tests' -diff --git a/.packit.yaml b/.packit.yaml -index 2aead86..36a6e16 100644 ---- a/.packit.yaml -+++ b/.packit.yaml -@@ -19,7 +19,7 @@ jobs: - - fedora-all-x86_64 - actions: - post-upstream-clone: -- # builds from PRs should have lower NVR than those from master branch -+ # builds from PRs should have lower NVR than those from main branch - - sed -i "s/1%{?dist}/0%{?dist}/g" packaging/leapp.spec - get-current-version: - # get version from spec file instead from git tag -@@ -27,7 +27,7 @@ jobs: - - job: copr_build - trigger: commit - metadata: -- branch: master -+ branch: main - owner: "@oamg" - project: leapp - targets: -@@ -38,7 +38,7 @@ jobs: - - fedora-all-x86_64 - actions: - post-upstream-clone: -- # builds from master branch should have the highest NVR -+ # builds from main branch should have the highest NVR - - sed -i "s/1%{?dist}/100%{?dist}/g" packaging/leapp.spec - get-current-version: - # get version from spec file instead from git tag -diff --git a/Makefile b/Makefile -index 677c748..0c1b805 100644 ---- a/Makefile -+++ b/Makefile -@@ -23,7 +23,7 @@ _TEST_CONTAINER=$${TEST_CONTAINER:-rhel8} - - # just to reduce number of unwanted builds mark as the upstream one when - # someone will call copr_build without additional parameters --MASTER_BRANCH=master -+MASTER_BRANCH=main - - # In case the PR or MR is defined or in case build is not coming from the - # MATER_BRANCH branch, N_REL=0; (so build is not update of the approved -@@ -44,14 +44,14 @@ REQUEST=`if test -n "$$PR"; then echo ".PR$${PR}"; elif test -n "$$MR"; then ech - # Examples: - # 0.201810080027Z.4078402.packaging.PR2 - # 0.201810080027Z.4078402.packaging --# 0.201810080027Z.4078402.master.MR2 --# 1.201810080027Z.4078402.master -+# 0.201810080027Z.4078402.main.MR2 -+# 1.201810080027Z.4078402.main - RELEASE="$(N_REL).$(TIMESTAMP).$(SHORT_SHA).$(BRANCH)$(REQUEST)$(_SUFFIX)" - - ifneq ($(shell id -u),0) - ENTER_VENV := . $(VENVNAME)/bin/activate; - else -- ENTER_VENV := -+ ENTER_VENV := - endif - - all: help -diff --git a/docs/source/best-practices.md b/docs/source/best-practices.md -index f3387e2..46aedbc 100644 ---- a/docs/source/best-practices.md -+++ b/docs/source/best-practices.md -@@ -43,17 +43,17 @@ to a shared library function. You can introduce it in one of these two places: - writing your actor for, e.g. for an OS in-place upgrade workflow, should go to the `/libraries` - folder. In this case, we welcome your proposals under the - [leapp-repository on GitHub](https://github.com/oamg/leapp-repository). -- -+ - Please note that the name of the library module in this case should be unique and contain - the actor name. For example: - `repos/system_upgrade/el7toel8/actors/vimmigrate/libraries/vimmigrate.py` -- -+ - - ## Discover standard library functions - - Before implementing functionality for your actor, browse through the available functionality provided by: - --- the [Leapp Standard Library](https://github.com/oamg/leapp/tree/master/leapp/libraries/stdlib/), -+- the [Leapp Standard Library](https://github.com/oamg/leapp/tree/main/leapp/libraries/stdlib/), - - the shared library of your Leapp repository (`/libraries` folder). - - These libraries contain functions that may satisfy your needs. Using them can save you time, lower code complexity and -@@ -63,7 +63,7 @@ help avoiding duplicate code. Improvement proposals for the library functions ar - - Sources of external functionality to be used in your actor in order of preference: - --1. the [Leapp Standard Library](https://github.com/oamg/leapp/tree/master/leapp/libraries/stdlib/) -+1. the [Leapp Standard Library](https://github.com/oamg/leapp/tree/main/leapp/libraries/stdlib/) - 2. the [Python Standard Library](https://docs.python.org/3/library/index.html) - 3. shell commands - -@@ -81,13 +81,13 @@ As with the Leapp Standard Library mentioned above, it may be beneficial for you - place in the [leapp-repository](https://github.com/oamg/leapp-repository). You might be interested in the messages they - produce, for example: - --- [SystemFactsActor](https://github.com/oamg/leapp-repository/blob/master/repos/system_upgrade/el7toel8/actors/systemfacts/actor.py) - -+- [SystemFactsActor](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/el7toel8/actors/systemfacts/actor.py) - - information about kernel modules, yum repos, sysctl variables, users, firewall, SELinux, etc. --- [OSReleaseCollector](https://github.com/oamg/leapp-repository/blob/master/repos/system_upgrade/el7toel8/actors/osreleasecollector/actor.py) - -+- [OSReleaseCollector](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/el7toel8/actors/osreleasecollector/actor.py) - - system release information --- [RpmScanner](https://github.com/oamg/leapp-repository/blob/master/repos/system_upgrade/el7toel8/actors/rpmscanner/actor.py) - -+- [RpmScanner](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/el7toel8/actors/rpmscanner/actor.py) - - list of installed packages --- [StorageScanner](https://github.com/oamg/leapp-repository/blob/master/repos/system_upgrade/el7toel8/actors/storagescanner/actor.py) - -+- [StorageScanner](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/el7toel8/actors/storagescanner/actor.py) - - storage information - - In case you find any message of the existing actors to be incorrect, incomplete or misleading, we encourage you to -@@ -123,8 +123,8 @@ For more about unit testing, see the [tutorial](unit-testing). - ## Do not introduce new dependencies - - Ideally, actors shouldn't require any additional dependency on top of the dependencies already in the --[leapp](https://github.com/oamg/leapp/blob/master/packaging/leapp.spec) and --[leapp-repository](https://github.com/oamg/leapp-repository/blob/master/packaging/leapp-repository.spec) spec files, -+[leapp](https://github.com/oamg/leapp/blob/main/packaging/leapp.spec) and -+[leapp-repository](https://github.com/oamg/leapp-repository/blob/main/packaging/leapp-repository.spec) spec files, - which are, as of December 2018, just these: - - - dnf -diff --git a/docs/source/build-schema.md b/docs/source/build-schema.md -index 053ff0c..7919964 100644 ---- a/docs/source/build-schema.md -+++ b/docs/source/build-schema.md -@@ -4,7 +4,7 @@ All projects under the OAMG should use the same schema for names of RPM builds, - to be able to simply and fast find specific builds. The schema itself looks - like that (NVR without %{dist}): - --- for builds made from the master branch: -+- for builds made from the main branch: - ``` - --100... - ``` -@@ -25,4 +25,4 @@ Where: - of a (S)RPM file; so it is suggested (not required) to to avoid dashes - in names of branches - - **number** is number of a pull-request (alternatively merge-request) to which -- builds are related -\ No newline at end of file -+ builds are related -diff --git a/docs/source/compatibility-with-leapp-repository.md b/docs/source/compatibility-with-leapp-repository.md -index 40441ed..13c6123 100644 ---- a/docs/source/compatibility-with-leapp-repository.md -+++ b/docs/source/compatibility-with-leapp-repository.md -@@ -9,7 +9,7 @@ We rather prefer releasing new versions with changelogs and everything - when we agree it's worthwhile. - - But we need a mechanism to be able to synchronize with other projects, when we --provide new functionality in the upstream (master) branch without the need -+provide new functionality in the upstream (main) branch without the need - of immediate release of the new version of leapp. For these purposes the - `leapp-framework` capability is provided in the framework (python[23]-leapp) rpms. - -diff --git a/docs/source/contributing.md b/docs/source/contributing.md -index f0422ee..65f94a5 100644 ---- a/docs/source/contributing.md -+++ b/docs/source/contributing.md -@@ -29,7 +29,7 @@ Before you submit your pull request, consider the following guidelines: - * Fork the repository and clone your fork. - * Make your changes in a new git branch: - -- ``git checkout -b bug/my-fix-branch master`` -+ ``git checkout -b bug/my-fix-branch main`` - - * Include documentation that either describe a change to a behavior or the changed capability to an end user. - * Commit your changes with message conforming to the [Git Commit Messages](#git-commit-messages) guidelines. -@@ -39,7 +39,7 @@ Before you submit your pull request, consider the following guidelines: - - ``git push --set-upstream origin bug/my-fix-branch`` - --* When opening a pull request, select the `master` branch as a base. -+* When opening a pull request, select the `main` branch as a base. - * Mark your pull request with **[WIP]** (Work In Progress) to get feedback, but prevent merging (for example, - [WIP] Update CONTRIBUTING.rst). - * If you are fixing a GitHub issue, include the issue number you are fixing, e.g. 'Closes issue #xyz'. -@@ -51,7 +51,7 @@ Before you submit your pull request, consider the following guidelines: - * Push changes to git (this will update your pull request). For that you can add a new commit or rebase your branch - and force push to your GitHub repository like this: :: - -- git rebase -i master -+ git rebase -i main - git push -f origin bug/my-fix-branch - - ### Merge Rules -diff --git a/docs/source/dependencies-leapp-repository.md b/docs/source/dependencies-leapp-repository.md -index dc0ed61..cbefca0 100644 ---- a/docs/source/dependencies-leapp-repository.md -+++ b/docs/source/dependencies-leapp-repository.md -@@ -14,11 +14,11 @@ this document focuses on the leapp-repository specifics only. - Currently there are two SPEC files for leapp-repository: - - - The --[leapp-repository.spec](https://github.com/oamg/leapp-repository/blob/master/packaging/leapp-repository.spec) -+[leapp-repository.spec](https://github.com/oamg/leapp-repository/blob/main/packaging/leapp-repository.spec) - file is used to build leapp-repository packages and their dependency - metapackage _leapp-repository-deps_ **for RHEL 7**. - - The --[leapp-el7toel8-deps.spec](https://github.com/oamg/leapp-repository/blob/master/packaging/leapp-el7toel8-deps.spec) -+[leapp-el7toel8-deps.spec](https://github.com/oamg/leapp-repository/blob/main/packaging/leapp-el7toel8-deps.spec) - file is used to build dependency metapackages _leapp-deps-el8_ and - _leapp-repository-deps-el8_ **for RHEL 8** whose purpose is to replace the - RHEL 7 dependency metapackages _leapp-deps_ and _leapp-repository-deps_ during -@@ -27,10 +27,10 @@ the upgrade. - ## What to do in leapp-repository when dependencies of leapp change? - - Go to the section below the line `%package -n %{ldname}` in the --[leapp-el7toel8-deps.spec](https://github.com/oamg/leapp-repository/blob/master/packaging/leapp-el7toel8-deps.spec). -+[leapp-el7toel8-deps.spec](https://github.com/oamg/leapp-repository/blob/main/packaging/leapp-el7toel8-deps.spec). - This section creates the RHEL 8 _leapp-deps-el8_ metapackage that replaces the - RHEL7 _leapp-deps_ metapackage. So when the leapp package dependencies change --in the [leapp.spec](https://github.com/oamg/leapp/blob/master/packaging/leapp.spec) -+in the [leapp.spec](https://github.com/oamg/leapp/blob/main/packaging/leapp.spec) - together with incrementing version of the **leapp-framework-dependencies** - capability, it's necessary to: - -diff --git a/docs/source/dependencies.md b/docs/source/dependencies.md -index a94beab..9d0fdca 100644 ---- a/docs/source/dependencies.md -+++ b/docs/source/dependencies.md -@@ -40,7 +40,7 @@ As a solution, we are using the metapackage that contains those dependencies. - ## What to do when dependencies needs to be changed - - It's easy to change *outer dependencies* for Leapp. Open the --[packaging/leapp.spec](https://github.com/oamg/leapp/blob/master/packaging/leapp.spec) file and change the dependencies as needed under -+[packaging/leapp.spec](https://github.com/oamg/leapp/blob/main/packaging/leapp.spec) file and change the dependencies as needed under - `%package deps`. The right place is pretty highlighted (you cannot miss it): - - ```spec -diff --git a/docs/source/deprecation.md b/docs/source/deprecation.md -index b583758..65cc18a 100644 ---- a/docs/source/deprecation.md -+++ b/docs/source/deprecation.md -@@ -10,7 +10,7 @@ impact on your code, we introduce the deprecation process described below. - - The following lists cover deprecated functionality in the leapp utility, snactor, - the leapp standard library, etc. But don't cover deprecated functionalities --from particular leapp repositories (e.g. the [elt7toel8](https://github.com/oamg/leapp-repository/tree/master/repos/system_upgrade/el7toel8) leapp repository). For -+from particular leapp repositories (e.g. the [elt7toel8](https://github.com/oamg/leapp-repository/tree/main/repos/system_upgrade/el7toel8) leapp repository). For - such information, see [Deprecated functionality in the el7toel8 repository](el7toel8/deprecation.html#deprecated-functionality-in-the-el7toel8-repository). - - ## current upstream development (till the next release + 6months) -diff --git a/docs/source/devenv-install.md b/docs/source/devenv-install.md -index 72f2590..84a5bab 100644 ---- a/docs/source/devenv-install.md -+++ b/docs/source/devenv-install.md -@@ -4,7 +4,7 @@ - - If you do not want to modify the framework itself, install it from - the RPM packages provided by the [Copr](https://copr.fedorainfracloud.org/coprs/g/oamg/leapp/) --build system, which automatically builds packages with every commit merged into master. -+build system, which automatically builds packages with every commit merged into main. - Packages are built for EPEL and Fedora. - - * On CentOS/RHEL: -@@ -65,7 +65,7 @@ Optional arguments: - --debug Enables debug mode - - Main commands: -- -+ - new-tag Create a new tag - new-model Creates a new model - run Execute the given actor -diff --git a/docs/source/el7toel8/actor-rhel7-to-rhel8.md b/docs/source/el7toel8/actor-rhel7-to-rhel8.md -index 06bdfae..2cc72f3 100644 ---- a/docs/source/el7toel8/actor-rhel7-to-rhel8.md -+++ b/docs/source/el7toel8/actor-rhel7-to-rhel8.md -@@ -21,7 +21,7 @@ The leapp framework provides the libraries required to be imported by any actor - - Separate tool provided by Leapp to help the process of creating and executing an actor. - --You can see _snactor_ source code [here](https://github.com/oamg/leapp/tree/master/leapp/snactor). -+You can see _snactor_ source code [here](https://github.com/oamg/leapp/tree/main/leapp/snactor). - - ## Creating an actor - -@@ -62,7 +62,7 @@ For further information about how create an actor read this [document](../first- - - Until now, you have created boilerplate of a new actor and made it visible to Leapp. But, Leapp needs some more information about what to do with the actor. Specifically, in which **“workflow”** and in which **“phase”** the actor should be executed. A workflow is a sequence of phases. The only workflow available now is the one solving the upgrade of RHEL 7 to RHEL 8. Each phase is a set of actors that will be executed one after another before the next phase starts. To find out in which workflow and phase should the actor be executed, Leapp looks for **“tags”**. To be part of RHEL 7 to RHEL 8 upgrade workflow, an actor needs to be tagged with **IPUWorkflowTag**. - --The phases of the IPUWorkflow (in order) are: **Facts Collection, Checks, Report, Download, Upgrade RamDisk Preparation, Upgrade RamDisk Start, Late Tests, Preparation, RPM Upgrade, Application Upgrade, Third Party Applications, Finalization** and **First Boot**. Each phase has a specific tag that marks an actor as being part of that phase. You can find descriptions of all the phases and their tags [here](https://github.com/oamg/leapp-repository/blob/master/repos/system_upgrade/common/workflows/inplace_upgrade.py) and workflow diagram [here](../inplace-upgrade-workflow). -+The phases of the IPUWorkflow (in order) are: **Facts Collection, Checks, Report, Download, Upgrade RamDisk Preparation, Upgrade RamDisk Start, Late Tests, Preparation, RPM Upgrade, Application Upgrade, Third Party Applications, Finalization** and **First Boot**. Each phase has a specific tag that marks an actor as being part of that phase. You can find descriptions of all the phases and their tags [here](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/common/workflows/inplace_upgrade.py) and workflow diagram [here](../inplace-upgrade-workflow). - - For example, if an actor is to be executed within the Checks phase, it needs to be tagged both with IPUWorkflowTag and ChecksPhaseTag. The result after updating the boilerplate would be: - -@@ -90,7 +90,7 @@ All communication between actors in Leapp is carried out using **“messages”* - - For further information about messaging see [document](../messaging). - --One of the existing models in Leapp is [ActiveKernelModulesFacts](https://github.com/oamg/leapp-repository/blob/master/repos/system_upgrade/el7toel8/models/activekernelmodulesfacts.py). Messages from this model contain data about the system on which Leapp has been started. For example, it contains installed kernel modules. If an actor wants to perform some action based on existing kernel modules on the system, the actor can get list of these modules by consuming the _ActiveKernelModulesFacts_ messages. By extending the boilerplate, the code could look like this: -+One of the existing models in Leapp is [ActiveKernelModulesFacts](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/el7toel8/models/activekernelmodulesfacts.py). Messages from this model contain data about the system on which Leapp has been started. For example, it contains installed kernel modules. If an actor wants to perform some action based on existing kernel modules on the system, the actor can get list of these modules by consuming the _ActiveKernelModulesFacts_ messages. By extending the boilerplate, the code could look like this: - - ```python - from leapp.actors import Actor -@@ -280,7 +280,7 @@ During development of your new actor, it is expected that you will test your wor - - ### Executing a single actor - --You should use snactor tool to run a single actor and verify its output. Assuming that there are no errors, the actor was placed inside a valid leapp repository and snactor tool is aware of such repository, you can call snactor run to execute it. Below we are executing the existing [OSReleaseCollector](https://github.com/oamg/leapp-repository/tree/master/repos/system_upgrade/el7toel8/actors/osreleasecollector) actor that provides information about operating system release from target system. For the `snactor run` command you can use either the actor’s folder name (osreleasecollector), the actor’s class name (OSReleaseCollector) or the value of the name attribute of the actor’s class (os_release_collector). -+You should use snactor tool to run a single actor and verify its output. Assuming that there are no errors, the actor was placed inside a valid leapp repository and snactor tool is aware of such repository, you can call snactor run to execute it. Below we are executing the existing [OSReleaseCollector](https://github.com/oamg/leapp-repository/tree/main/repos/system_upgrade/el7toel8/actors/osreleasecollector) actor that provides information about operating system release from target system. For the `snactor run` command you can use either the actor’s folder name (osreleasecollector), the actor’s class name (OSReleaseCollector) or the value of the name attribute of the actor’s class (os_release_collector). - - ```shell - # pwd -@@ -350,7 +350,7 @@ Finally, you can make your actor part of the “leapp upgrade” process and che - - ### Verifying correct communication between actors - --Leapp provides another actor, named [CheckOSRelease](https://github.com/oamg/leapp-repository/tree/master/repos/system_upgrade/el7toel8/actors/checkosrelease), that consumes messages from model _OSReleaseFacts_ and produces an error message in case system OS Release is not supported by Leapp upgrade process. In order to consume such message, _OSReleaseCollector_ actor needs to be executed before _CheckOSRelease_ and its message needs to be stored inside Leapp database. This process is controlled by the framework during the execution of “leapp upgrade” command. -+Leapp provides another actor, named [CheckOSRelease](https://github.com/oamg/leapp-repository/tree/main/repos/system_upgrade/el7toel8/actors/checkosrelease), that consumes messages from model _OSReleaseFacts_ and produces an error message in case system OS Release is not supported by Leapp upgrade process. In order to consume such message, _OSReleaseCollector_ actor needs to be executed before _CheckOSRelease_ and its message needs to be stored inside Leapp database. This process is controlled by the framework during the execution of “leapp upgrade” command. - - But, if you want to execute it manually, for test purposes, you can also use snactor for it. First we need to make sure that all messages that will be consumed are generated and stored. For this example, this means running _OSReleaseCollector_ actor with the _--save-output_ option of snactor: - -@@ -412,7 +412,7 @@ This [pull request](https://github.com/oamg/leapp-repository/pull/186) gives a g - - ### In which existing workflow phase should I place my new actor? - --You can decide that based on the description of the phases this information is available in the [code](https://github.com/oamg/leapp-repository/blob/master/repos/system_upgrade/el7toel8/workflows/inplace_upgrade.py) and diagram [here](../inplace-upgrade-workflow). Please note that if your actor depends on some message generated by another actor, it cannot be executed in a phase before the phase of such actor. In a similar way, if your actor produces data, it needs to be executed before the actor consuming the data. -+You can decide that based on the description of the phases this information is available in the [code](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/el7toel8/workflows/inplace_upgrade.py) and diagram [here](../inplace-upgrade-workflow). Please note that if your actor depends on some message generated by another actor, it cannot be executed in a phase before the phase of such actor. In a similar way, if your actor produces data, it needs to be executed before the actor consuming the data. - - ### How to stop the upgrade in case my actor finds a problem with the system setup? - -diff --git a/docs/source/el7toel8/inhibit-rhel7-to-rhel8.md b/docs/source/el7toel8/inhibit-rhel7-to-rhel8.md -index 5e97c78..a31208f 100644 ---- a/docs/source/el7toel8/inhibit-rhel7-to-rhel8.md -+++ b/docs/source/el7toel8/inhibit-rhel7-to-rhel8.md -@@ -56,7 +56,7 @@ $ snactor run CheckSystemArch --verbose - If, instead of only adding a message to the log, the actor writer wants to make - sure that the upgrade process will be stopped in case of unsupported arch, the - actor needs to produce a [Report](/pydoc/leapp.reporting.html#leapp.reporting.Report) --message using one of the `report_*` functions from the [reporting](https://github.com/oamg/leapp-repository/blob/master/repos/system_upgrade/el7toel8/libraries/reporting.py) -+message using one of the `report_*` functions from the [reporting](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/el7toel8/libraries/reporting.py) - shared library with the `'inhibitor'` group. - - ```python -@@ -131,7 +131,7 @@ This is all that an actor needs to do in order to verify if some condition is - present on the system and inhibit the upgrade process based on that check. - - After all the system checks are executed by different actors, an existing actor --named [VerifyCheckResults](https://github.com/oamg/leapp-repository/tree/master/repos/system_upgrade/el7toel8/actors/verifycheckresults) -+named [VerifyCheckResults](https://github.com/oamg/leapp-repository/tree/main/repos/system_upgrade/el7toel8/actors/verifycheckresults) - is scheduled to run in the Leapp upgrade workflow. If some [Report](/pydoc/leapp.reporting.html#leapp.reporting.Report) - message with the `'inhibitor'` group was generated by some previous execution of - another actor in any previous phase of the workflow, like the sample one we just -diff --git a/docs/source/test-actors.md b/docs/source/test-actors.md -index 322fe77..967c2ad 100644 ---- a/docs/source/test-actors.md -+++ b/docs/source/test-actors.md -@@ -21,13 +21,13 @@ Test module names should match the following regex: - - These tests deal with individual actor's functions/methods. - - It's not possible to unit test any method/function within the *actor.py*. You can write unit tests only for functions/methods within the actor's libraries. - - Thus, to be able to write unit tests for an actor, ideally the only thing in the _actor.py_'s _process()_ method is calling the entry-point function of the actor's library python module. --- [Example of unit tests](https://github.com/oamg/leapp-repository/blob/master/repos/system_upgrade/el7toel8/actors/checkbootavailspace/tests/unit_test_checkbootavailspace.py) -+- [Example of unit tests](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/el7toel8/actors/checkbootavailspace/tests/unit_test_checkbootavailspace.py) - - ### Component tests - - - These tests provide fabricated input messages for the actor, check the outputs stated in the actor's description. - - These tests should not be written based on the actor's code but rather based on the behavior stated in the actor's description. They could be written by somebody who didn't write the code. --- [Example of component tests](https://github.com/oamg/leapp-repository/blob/master/repos/system_upgrade/el7toel8/actors/checknfs/tests/test_checknfs.py) -+- [Example of component tests](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/el7toel8/actors/checknfs/tests/test_checknfs.py) - - ## End to end (e2e) tests - -diff --git a/docs/source/unit-testing.md b/docs/source/unit-testing.md -index d4feec9..52310e1 100644 ---- a/docs/source/unit-testing.md -+++ b/docs/source/unit-testing.md -@@ -11,7 +11,7 @@ Tests are considered being part of the actor and we do not only encourage but - basically require you to write tests if you want the actors to be accepted into - the git repository. To read more about what we ask from you when submitting - your work for our review, see --[Contributing guidelines for writing actors](https://github.com/oamg/leapp-repository/blob/master/CONTRIBUTING.md). -+[Contributing guidelines for writing actors](https://github.com/oamg/leapp-repository/blob/main/CONTRIBUTING.md). - - Tests for an actor are to be placed within the actor's directory, in a - subdirectory called `tests`. The layout for an actor `MyActor` in the -@@ -111,7 +111,7 @@ supposed to be unit tested is necessary to move into the actor's private - library. Modules from the private library can then be imported not only from - the `actor.py` but also from the test modules. - --Let's assume your actor has a private library module called -+Let's assume your actor has a private library module called - `private_{actor_name}.py`. - - ``` -@@ -173,7 +173,7 @@ install-deps: - Note: Dependencies defined the way mentioned above is for test execution only. - If your actor requires any package when executed as part of a workflow, it - needs to be specified in a --[leapp-repository specfile](https://github.com/oamg/leapp-repository/blob/master/packaging/leapp-repository.spec). -+[leapp-repository specfile](https://github.com/oamg/leapp-repository/blob/main/packaging/leapp-repository.spec). - - ## Running the tests - -@@ -209,7 +209,7 @@ It is also possible to run only selected tests based on their name: - pytest -k "vim" # to run all tests contains vim in name - pytest -k "not vim" # to run all tests, which not contains vim in name - ``` --More examples could be found in the -+More examples could be found in the - [pytest documentation](https://docs.pytest.org/en/latest/example/markers.html#using-k-expr-to-select-tests-based-on-their-name) - - ### Shared libraries' tests -diff --git a/packaging/leapp.spec b/packaging/leapp.spec -index 2352bf0..ab38d20 100644 ---- a/packaging/leapp.spec -+++ b/packaging/leapp.spec -@@ -1,9 +1,9 @@ - # IMPORTANT: - # Please read the documentation on how to deal with dependencies before adding a new one. --# https://github.com/oamg/leapp/blob/master/docs/source/dependencies.md -+# https://github.com/oamg/leapp/blob/main/docs/source/dependencies.md - - %global debug_package %{nil} --%global gittag master -+%global gittag main - - # IMPORTANT: this is for the leapp-framework capability (it's not the real - # version of the leapp). The capability reflects changes in api and whatever --- -2.47.0 - diff --git a/SOURCES/0002-docs-Update-docs-engine-and-dependencies.patch b/SOURCES/0002-docs-Update-docs-engine-and-dependencies.patch deleted file mode 100644 index 3a3b85d..0000000 --- a/SOURCES/0002-docs-Update-docs-engine-and-dependencies.patch +++ /dev/null @@ -1,509 +0,0 @@ -From 7565b5c8cd5a098522565ff0ed5278eb2b04b7a8 Mon Sep 17 00:00:00 2001 -From: Matej Matuska -Date: Mon, 4 Mar 2024 13:49:18 +0100 -Subject: [PATCH 2/6] docs: Update docs engine and dependencies - -Changes with version 3.5.4: -- The biggest change is the replacement of recommonmark with MyST for markdown -parsing. The recommonmark library is no longer maintained and is also deprecated -in sphinx. The recommended replacement is MyST library. In our case it seems -like a drop-in replacement with only errors being "non-consecutive header level -increment", which shouldn't be a problem and the docs build successfully. - -Changes with version 4.5.0 -- No major changes, just some deprecated APIs are replaced. - -Changes with version 5.3.0 -- Instead of linking to autodoc generated HTML files (in the pydoc dir), use cross -references. Also fix some of the ambiguous references and repair some of -the broken ones. - -Changes with version 6.2.1 -- No breaking changes. -- This version requires Python 3.10 for deps to correctly install, -otherwise the version of sphinx-autobuild and sphinxcontrib-* packages -would have to pinned. - -Changes with version 7.2.6 -- No breaking changes. -- Works properly on Python >= 3.10. On Python 3.12 requires manual upgrade -of the six package until the version is bumped in requirements.txt. ---- - .readthedocs.yaml | 2 +- - docs/Makefile | 5 ++-- - docs/source/best-practices.md | 18 +++++------ - docs/source/conf.py | 30 +++++++++---------- - docs/source/debugging.md | 2 +- - docs/source/deprecation.md | 7 ++--- - docs/source/devenv-install.md | 2 +- - docs/source/dialogs.md | 4 +-- - docs/source/el7toel8/actor-rhel7-to-rhel8.md | 2 +- - docs/source/el7toel8/deprecation.md | 2 +- - docs/source/el7toel8/envars.md | 2 +- - .../source/el7toel8/inhibit-rhel7-to-rhel8.md | 8 +++-- - docs/source/faq.md | 16 +++++----- - docs/source/messaging.md | 2 +- - docs/source/terminology.md | 2 +- - docs/source/unit-testing.md | 4 +-- - leapp/libraries/actor/__init__.py | 2 +- - leapp/libraries/common/__init__.py | 2 +- - leapp/utils/__init__.py | 4 +-- - requirements-docs.txt | 10 ++++--- - 20 files changed, 64 insertions(+), 62 deletions(-) - -diff --git a/.readthedocs.yaml b/.readthedocs.yaml -index 5b892d8..f78af83 100644 ---- a/.readthedocs.yaml -+++ b/.readthedocs.yaml -@@ -8,7 +8,7 @@ version: 2 - build: - os: ubuntu-22.04 - tools: -- python: "2.7" -+ python: "3.10" - # You can also specify other tool versions: - # nodejs: "20" - # rust: "1.70" -diff --git a/docs/Makefile b/docs/Makefile -index 8750d07..709c35b 100644 ---- a/docs/Makefile -+++ b/docs/Makefile -@@ -15,12 +15,11 @@ BUILDDIR = build - help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - livehtml: -- @$(SPHINXAUTOBUILD) -z ../leapp "$(SOURCEDIR)" "$(BUILDDIR)/html" $(SPHINXOPTS) $(0) -- --.PHONY: help Makefile -+ @$(SPHINXAUTOBUILD) --watch ../leapp "$(SOURCEDIR)" "$(BUILDDIR)/html" $(SPHINXOPTS) $(0) - - # Catch-all target: route all unknown targets to Sphinx using the new - # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). - %: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -+.PHONY: all help Makefile -diff --git a/docs/source/best-practices.md b/docs/source/best-practices.md -index 46aedbc..7951290 100644 ---- a/docs/source/best-practices.md -+++ b/docs/source/best-practices.md -@@ -30,10 +30,10 @@ See the [tutorial on basic usage of snactor](first-actor). - Part of your actor's functionality might end up being rather generic or abstract. In that case, consider converting it - to a shared library function. You can introduce it in one of these two places: - --- The [Leapp Standard Library](pydoc/leapp.libraries.stdlib) -+- The [Leapp Standard Library](leapp.libraries.stdlib) - - The most generic functionality which actors of any workflow can use, e.g. function for exectuting a shell command, -- should go to the [Leapp Standard Library](pydoc/leapp.libraries.stdlib). -+ should go to the [Leapp Standard Library](leapp.libraries.stdlib). - For that, please submit proposals through issues or pull requests under the - [leapp GitHub repository](https://github.com/oamg/leapp/). - -@@ -146,16 +146,16 @@ For more details about dependencies and how to modify them, see the [How to deal - - If you encounter unexpected input or any other error during execution of an actor and want to stop it, use these exceptions: - --- [StopActorExecution](pydoc/leapp.html#leapp.exceptions.StopActorExecution) - raising this exception is a convenient to stop actor's execution with no side effect - it has the same effect as returning `None` from the main `process()` method in the `actor.py` --- [StopActorExecutionError](pydoc/leapp.html#leapp.exceptions.StopActorExecutionError) - raising this exception will stop actor's execution and notify the framework that an error has occurred and can influence the result of the workflow execution. -+- [StopActorExecution](leapp.exceptions.StopActorExecution) - raising this exception is a convenient to stop actor's execution with no side effect - it has the same effect as returning `None` from the main `process()` method in the `actor.py` -+- [StopActorExecutionError](leapp.exceptions.StopActorExecutionError) - raising this exception will stop actor's execution and notify the framework that an error has occurred and can influence the result of the workflow execution. - --In case of [StopActorExecutionError](pydoc/leapp.html#leapp.exceptions.StopActorExecutionError) the execution of the workflow will stop or not according to the [policy](pydoc/leapp.workflows.html?highlight=FailPhase#module-leapp.workflows.policies) defined in the workflow, there are three possibilities: -+In case of [StopActorExecutionError](leapp.exceptions.StopActorExecutionError) the execution of the workflow will stop or not according to the [policy](leapp.workflows.policies) defined in the workflow, there are three possibilities: - --- [FailImmediately](pydoc/leapp.workflows.html?highlight=FailPhase#leapp.workflows.policies.Policies.Errors.FailImmediately) - end the workflow execution right away --- [FailPhase](pydoc/leapp.workflows.html?highlight=FailPhase#leapp.workflows.policies.Policies.Errors.FailPhase) - end the workflow execution after finishing the current phase --- [ReportOnly](pydoc/leapp.workflows.html?highlight=FailPhase#leapp.workflows.policies.Policies.Errors.ReportOnly) - do not end the workflow execution at all and continue with logging the issue only -+- [FailImmediately](leapp.workflows.policies.Policies.Errors.FailImmediately) - end the workflow execution right away -+- [FailPhase](leapp.workflows.policies.Policies.Errors.FailPhase) - end the workflow execution after finishing the current phase -+- [ReportOnly](leapp.workflows.policies.Policies.Errors.ReportOnly) - do not end the workflow execution at all and continue with logging the issue only - --You can also use the [StopActorExecution](pydoc/leapp.html#leapp.exceptions.StopActorExecution) and [StopActorExecutionError](pydoc/leapp.html#leapp.exceptions.StopActorExecutionError) exceptions inside a private or shared library. -+You can also use the [StopActorExecution](leapp.exceptions.StopActorExecution) and [StopActorExecutionError](leapp.exceptions.StopActorExecutionError) exceptions inside a private or shared library. - - ## Use the LEAPP and LEAPP\_DEVEL prefixes for new envars - -diff --git a/docs/source/conf.py b/docs/source/conf.py -index 4b1b4bc..d8551f4 100644 ---- a/docs/source/conf.py -+++ b/docs/source/conf.py -@@ -25,8 +25,6 @@ sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(os.path.dirna - - import sphinx_rtd_theme # noqa - import leapp # noqa --from recommonmark.parser import CommonMarkParser # noqa --from recommonmark.transform import AutoStructify # noqa - - # -- General configuration ------------------------------------------------ - -@@ -37,9 +35,12 @@ from recommonmark.transform import AutoStructify # noqa - # Add any Sphinx extension module names here, as strings. They can be - # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom - # ones. --extensions = ['sphinx.ext.autodoc', -- 'sphinx.ext.githubpages', -- 'autosectionlabelext'] -+extensions = [ -+ 'sphinx.ext.autodoc', -+ 'sphinx.ext.githubpages', -+ 'autosectionlabelext', -+ 'myst_parser', -+] - - # Add any paths that contain templates here, relative to this directory. - templates_path = ['_templates'] -@@ -50,6 +51,9 @@ templates_path = ['_templates'] - source_suffix = ['.md', '.rst'] - # source_suffix = '.rst' - -+# how many level of headings in markdown should linkable anchors be generated for -+myst_heading_anchors = 3 -+ - # The master toctree document. - master_doc = 'index' - -@@ -72,7 +76,8 @@ release = leapp.FULL_VERSION - # - # This is also used if you do content translation via gettext catalogs. - # Usually you set "language" from the command line for these cases. --language = None -+language = 'en' -+# highlight_language = "python" - - # List of patterns, relative to source directory, that match files and - # directories to ignore when looking for source files. -@@ -165,11 +170,6 @@ texinfo_documents = [ - 'Miscellaneous'), - ] - -- --source_parsers = { -- '.md': CommonMarkParser, --} -- - autoclass_content = 'both' - autodoc_default_flags = ['members', 'undoc-members', 'inherited-members', 'show-inheritance'] - -@@ -185,9 +185,7 @@ def filter_unwanted_leapp_types(app, what, name, obj, skip, options): - - - def setup(app): -- app.add_config_value('recommonmark_config', {}, True) -- app.add_transform(AutoStructify) - app.connect('autodoc-skip-member', filter_unwanted_leapp_types) -- app.add_stylesheet('css/asciinema-player.css') -- app.add_stylesheet('css/custom.css') -- app.add_javascript('js/asciinema-player.js') -+ app.add_css_file('css/asciinema-player.css') -+ app.add_css_file('css/custom.css') -+ app.add_js_file('js/asciinema-player.js') -diff --git a/docs/source/debugging.md b/docs/source/debugging.md -index b01d156..b1e222e 100644 ---- a/docs/source/debugging.md -+++ b/docs/source/debugging.md -@@ -4,7 +4,7 @@ - - The snactor tool is used to debug your actors. You can execute actors - and save their output, so that it can be consumed by other actors. --See [Storing messages in the repository data for reuse](messaging.html#storing-messages-in-the-repository-data-for-reuse). -+See [Storing messages in the repository data for reuse](messaging.md#storing-messages-in-the-repository-data-for-reuse). - - Snactor checks for the `LEAPP_DEBUG` environment variable and has also - the --debug parameter which sets the environment variable to '1' when it is -diff --git a/docs/source/deprecation.md b/docs/source/deprecation.md -index 65cc18a..142d884 100644 ---- a/docs/source/deprecation.md -+++ b/docs/source/deprecation.md -@@ -11,7 +11,7 @@ impact on your code, we introduce the deprecation process described below. - The following lists cover deprecated functionality in the leapp utility, snactor, - the leapp standard library, etc. But don't cover deprecated functionalities - from particular leapp repositories (e.g. the [elt7toel8](https://github.com/oamg/leapp-repository/tree/main/repos/system_upgrade/el7toel8) leapp repository). For --such information, see [Deprecated functionality in the el7toel8 repository](el7toel8/deprecation.html#deprecated-functionality-in-the-el7toel8-repository). -+such information, see [Deprecated functionality in the el7toel8 repository](el7toel8/deprecation.md#deprecated-functionality-in-the-el7toel8-repository). - - ## current upstream development (till the next release + 6months) - -@@ -106,7 +106,7 @@ the deprecation of derived classes.* - In case of a class deprecation, all derived classes are considered to be deprecated - as well. However, the current reporting could be a little bit confusing. To - improve that, the `stack_level_offset` option can be specified. --See [examples of the use of the @deprecated decorator for classes](deprecation.html#classes). -+See [examples of the use of the @deprecated decorator for classes](deprecation.md#classes). - - When you mark any entity as deprecated and this entity is then used - in the code, users will be notified about that via a terminal and report -@@ -290,9 +290,8 @@ before the definition of the `produce_answer` function. But if we do the same - for the test function, we will get an error (see that we have now just one - deprecation warning now): - --```python -+``` - | 21:59:57 | conftest | INFO | conftest.py | Actor 'foo_producer' context teardown complete -- - repos/system_upgrade/el7toel8/actors/fooproducer/tests/test_unit_fooproducer.py::test_process FAILED - - ====================================================== FAILURES ====================================================== -diff --git a/docs/source/devenv-install.md b/docs/source/devenv-install.md -index 84a5bab..210e48f 100644 ---- a/docs/source/devenv-install.md -+++ b/docs/source/devenv-install.md -@@ -49,7 +49,7 @@ $ pip install git+https://github.com/oamg/leapp - ``` - - Once the framework is installed, you can use the snactor tool. --```shell -+``` - $ snactor --help - usage: snactor [-h] [--version] [--logger-config LOGGER_CONFIG] - [--config CONFIG] [--verbose] [--debug] -diff --git a/docs/source/dialogs.md b/docs/source/dialogs.md -index 391b37f..d863fab 100644 ---- a/docs/source/dialogs.md -+++ b/docs/source/dialogs.md -@@ -4,9 +4,9 @@ Leapp framework uses dialogs to ask user for any additional information an actor - automatically. - Dialogs contain Components which represent individual questions. - Complete list of component types can be found in --[documentation](pydoc/leapp.dialogs.html#module-leapp.dialogs.components). -+[documentation](leapp.dialogs.components). - --As an example we will change [IpResolver](messaging.html#creating-a-message-consuming-actor) actor in a way that user -+As an example we will change [IpResolver](messaging.md#creating-a-message-consuming-actor) actor in a way that user - will decide which hostnames will be resolved. - - -diff --git a/docs/source/el7toel8/actor-rhel7-to-rhel8.md b/docs/source/el7toel8/actor-rhel7-to-rhel8.md -index 2cc72f3..32b371f 100644 ---- a/docs/source/el7toel8/actor-rhel7-to-rhel8.md -+++ b/docs/source/el7toel8/actor-rhel7-to-rhel8.md -@@ -420,7 +420,7 @@ The process of inhibiting the upgrade is done by the VerifyCheckResult actor, ex - - ### How to stop execution of my actor in case of an unexpected error? - --It’s good practice to code defensively so the code is robust. The actor should detect unexpected input or result of some operation and exit gracefully instead of tracebacking. In case you detect an unexpected behavior, let the framework know about it by raising [StopActorExecutionError](pydoc/leapp.html#leapp.exceptions.StopActorExecutionError). Framework will act based on the [setting of the upgrade workflow](pydoc/leapp.workflows.html?highlight=FailPhase#module-leapp.workflows.policies) in one of the following three ways: -+It’s good practice to code defensively so the code is robust. The actor should detect unexpected input or result of some operation and exit gracefully instead of tracebacking. In case you detect an unexpected behavior, let the framework know about it by raising [StopActorExecutionError](leapp.exceptions.StopActorExecutionError). Framework will act based on the [setting of the upgrade workflow](leapp.workflows.policies) in one of the following three ways: - - - end the upgrade process right away, or - - end the upgrade process after finishing the current phase, or -diff --git a/docs/source/el7toel8/deprecation.md b/docs/source/el7toel8/deprecation.md -index 37bef8f..243972f 100644 ---- a/docs/source/el7toel8/deprecation.md -+++ b/docs/source/el7toel8/deprecation.md -@@ -8,7 +8,7 @@ after which the related functionality can be removed at any time. - - *Note* The lists cover just the functionality provided inside the el7toel8 - repository only. For the functionality deprecated in the leapp --framework, see [List of deprecated functionality in leapp](../deprecation.html#list-of-deprecated-functionality-in-leapp) -+framework, see [List of deprecated functionality in leapp](../deprecation.md#list-of-the-deprecated-functionality-in-leapp) - - ## current upstream development (till the next release + 6months) - -diff --git a/docs/source/el7toel8/envars.md b/docs/source/el7toel8/envars.md -index 86190ad..6eeb81f 100644 ---- a/docs/source/el7toel8/envars.md -+++ b/docs/source/el7toel8/envars.md -@@ -2,7 +2,7 @@ - - Actors in the el7toel8 repository use environment variables specified below. - All these envars use the suggested prefixes specified in --[the best practices document](../best-practices#use-the-leapp-and-leapp-devel-prefixes-for-new-envars) -+[the best practices document](../best-practices.md#use-the-leapp-and-leapp_devel-prefixes-for-new-envars) - for the leapp project to distinguish their purpose: _production_ or _devel_ use. - - If the argument for envars below is not specified, it is expected to set `0` -diff --git a/docs/source/el7toel8/inhibit-rhel7-to-rhel8.md b/docs/source/el7toel8/inhibit-rhel7-to-rhel8.md -index a31208f..c2c592f 100644 ---- a/docs/source/el7toel8/inhibit-rhel7-to-rhel8.md -+++ b/docs/source/el7toel8/inhibit-rhel7-to-rhel8.md -@@ -5,7 +5,7 @@ - With latest changes on Leapp and with new actors added to the el7toel8 Leapp - repository, any actor can inhibit the upgrade process by producing a specific - message when a problem is found. The message model to use in this case is --[Report](pydoc/leapp.reporting.html#leapp.reporting.Report). -+[Report](leapp.reporting.Report). - If there is at least one Report message with the `'inhibitor'` group produced before - the Report phase, the upgrade will be stopped in the Reports phase, in which the - messages are being collected. It means that any Report message produced -@@ -55,7 +55,7 @@ $ snactor run CheckSystemArch --verbose - - If, instead of only adding a message to the log, the actor writer wants to make - sure that the upgrade process will be stopped in case of unsupported arch, the --actor needs to produce a [Report](/pydoc/leapp.reporting.html#leapp.reporting.Report) -+actor needs to produce a [Report](leapp.reporting.Report) - message using one of the `report_*` functions from the [reporting](https://github.com/oamg/leapp-repository/blob/main/repos/system_upgrade/el7toel8/libraries/reporting.py) - shared library with the `'inhibitor'` group. - -@@ -131,8 +131,10 @@ This is all that an actor needs to do in order to verify if some condition is - present on the system and inhibit the upgrade process based on that check. - - After all the system checks are executed by different actors, an existing actor --named [VerifyCheckResults](https://github.com/oamg/leapp-repository/tree/main/repos/system_upgrade/el7toel8/actors/verifycheckresults) -+==== BASE ==== -+named [VerifyCheckResults](https://github.com/oamg/leapp-repository/tree/master/repos/system_upgrade/el7toel8/actors/verifycheckresults) - is scheduled to run in the Leapp upgrade workflow. If some [Report](/pydoc/leapp.reporting.html#leapp.reporting.Report) -+==== BASE ==== - message with the `'inhibitor'` group was generated by some previous execution of - another actor in any previous phase of the workflow, like the sample one we just - wrote, the following output will be displayed to the user: -diff --git a/docs/source/faq.md b/docs/source/faq.md -index 66de4e0..4e00583 100644 ---- a/docs/source/faq.md -+++ b/docs/source/faq.md -@@ -8,12 +8,12 @@ - - [What do I have to do in order to execute actor I just wrote?](#what-do-i-have-to-do-in-order-to-execute-actor-i-just-wrote) - - [What should I do if I need to execute multiple actors? Can I somehow ensure the dependencies between them?](#what-should-i-do-if-i-need-to-execute-multiple-actors-can-i-somehow-ensure-the-dependencies-between-them) - - [How can I specify what run time dependencies will my actor have?](#how-can-i-specify-what-run-time-dependencies-will-my-actor-have) --- [How can I distinguish between actors that I depend on directly (I need to consume their output) and indirectly (I just need them to be executed as part of the upgrade as I don’t handle the upgrade of that specific piece; think PHP vs. Apache - upgrade of Apache is independent of the upgrade of PHP but it needs to be done to enable its upgrade)?](#how-can-i-distinguish-between-actors-that-i-depend-on-directly-i-need-to-consume-their-output-and-indirectly-i-just-need-them-to-be-executed-as-part-of-the-upgrade-as-i-don-t-handle-the-upgrade-of-that-specific-piece-think-php-vs-apache-upgrade-of-apache-is-independent-of-the-upgrade-of-php-but-it-needs-to-be-done-to-enable-its-upgrade) -+- [How can I distinguish between actors that I depend on directly (I need to consume their output) and indirectly (I just need them to be executed as part of the upgrade as I don’t handle the upgrade of that specific piece; think PHP vs. Apache - upgrade of Apache is independent of the upgrade of PHP but it needs to be done to enable its upgrade)?](#how-can-i-distinguish-between-actors-that-i-depend-on-directly-i-need-to-consume-their-output-and-indirectly-i-just-need-them-to-be-executed-as-part-of-the-upgrade-as-i-dont-handle-the-upgrade-of-that-specific-piece) - - [Once I write an actor that consumes data from some other actors, how can I be sure that the format will not change on the producing side in the future?](#once-i-write-an-actor-that-consumes-data-from-some-other-actors-how-can-i-be-sure-that-the-format-will-not-change-on-the-producing-side-in-the-future) - - [What are the best practices for writing actors?](#what-are-the-best-practices-for-writing-actors) - - [What are the requirements for actors to be accepted by upstream?](#what-are-the-requirements-for-actors-to-be-accepted-by-upstream) - - [How can I debug my actor? Is there a standard/supported way how to log and get logs from actors/channels?](#what-are-the-requirements-for-actors-to-be-accepted-by-upstream) --- [Are there some technical limitations for an actor? E.g. maximum time execution, size of the input/output, libraries I can use… In case there are, is it possible to specify that the actor needs e.g. longer time for execution?](#are-there-some-technical-limitations-for-an-actor-e-g-maximum-time-execution-size-of-the-input-output-libraries-i-can-use-in-case-there-are-is-it-possible-to-specify-that-the-actor-needs-e-g-longer-time-for-execution) -+- [Are there some technical limitations for an actor? E.g. maximum time execution, size of the input/output, libraries I can use… In case there are, is it possible to specify that the actor needs e.g. longer time for execution?](#are-there-some-technical-limitations-for-an-actor-eg-maximum-time-execution-size-of-the-inputoutput-libraries-i-can-use-in-case-there-are-is-it-possible-to-specify-that-the-actor-needs-eg-longer-time-for-execution) - - [Are there some actions that are either forbidden or not recommended to be done in actors?](#are-there-some-actions-that-are-either-forbidden-or-not-recommended-to-be-done-in-actors) - - [I got an error about PES data/ Repositories mapping where I find such files?](#i-got-an-error-about-pes-data-repositories-mapping-where-i-find-such-files) - -@@ -49,19 +49,21 @@ Source: [How to create a Leapp actor for RHEL 7 to 8 upgrade](el7toel8/actor-rhe - ## What should I do if I need to execute multiple actors? Can I somehow ensure the dependencies between them? - - To be sure that your ActorA runs before your ActorB, produce a specific message in ActorA and let ActorB consume it. By doing this you create a dependency of ActorB on ActorA. --To run just your actors during development, use snactor run --save-output ActorA to save the message of ActorA to the Leapp repository database and then snactor run ActorB. This way, the ActorB will be able to consume the ActorA's saved message. Read more about that in the [tutorial about messaging](messaging). -+To run just your actors during development, use snactor run --save-output ActorA to save the message of ActorA to the Leapp repository database and then snactor run ActorB. This way, the ActorB will be able to consume the ActorA's saved message. Read more about that in the [tutorial about messaging](messaging.md). - - ## How can I specify what run time dependencies will my actor have? - --See the section about dependencies in the [Best practices document](best-practices.html#do-not-introduce-new-dependencies) -+See the section about dependencies in the [Best practices document](best-practices.md#do-not-introduce-new-dependencies) - --## How can I distinguish between actors that I depend on directly (I need to consume their output) and indirectly (I just need them to be executed as part of the upgrade as I don't handle the upgrade of that specific piece; think PHP vs. Apache - upgrade of Apache is independent of the upgrade of PHP but it needs to be done to enable its upgrade)? -+## How can I distinguish between actors that I depend on directly (I need to consume their output) and indirectly (I just need them to be executed as part of the upgrade as I don't handle the upgrade of that specific piece)? -+ -+An example of this is PHP vs. Apache - upgrade of Apache is independent of the upgrade of PHP but it needs to be done to enable its upgrade. - - In the case of actors you depend on directly because you consume their message, you don't need to do anything extra, the Leapp framework will make sure that the actors that produce the messages you consume are executed before your actor. - In case of the actors you depend on indirectly you may approach it in various ways: - - - Talk to the developers of the actors you depend on indirectly and agree on sending a message between their actors and your actor. This will cause a direct dependency described above. --- Talk to the [Engineering Lead](contributing.html#contact) of the OS and Application Modernization group and tell them to coordinate development, testing and release of your actor and the actors you depend on indirectly, targeting the same milestone. -+- Talk to the [Engineering Lead](contributing.md#contact) of the OS and Application Modernization group and tell them to coordinate development, testing and release of your actor and the actors you depend on indirectly, targeting the same milestone. - - ## Once I write an actor that consumes data from some other actors, how can I be sure that the format will not change on the producing side in the future? - -@@ -85,7 +87,7 @@ Source: [How to create a Leapp actor for RHEL 7 to 8 upgrade](el7toel8/actor-rhe - There are no technical limitations but rather conceptual: - - - Libraries to use: -- - See the section about actor dependencies in the [Best practices document](best-practices.html#do-not-introduce-new-dependencies) -+ - See the section about actor dependencies in the [Best practices document](best-practices.md#do-not-introduce-new-dependencies) - - Execution time: - -diff --git a/docs/source/messaging.md b/docs/source/messaging.md -index 73b76c1..f1f5636 100644 ---- a/docs/source/messaging.md -+++ b/docs/source/messaging.md -@@ -1,7 +1,7 @@ - ## Using messaging to send data between actors - - The Leapp framework uses messages to send data to other actors that are executed afterward. --Messages are defined through the models declared [earlier](first-actor.html#creating-a-model). Actors can consume these messages and produce data based on their input. -+Messages are defined through the models declared [earlier](first-actor.md#creating-a-model). Actors can consume these messages and produce data based on their input. - - As an example, the actors consume Hostname messages, resolve IPs for those - hostnames, and create the ResolvedHostname model to send a new type of message. -diff --git a/docs/source/terminology.md b/docs/source/terminology.md -index 42a823f..b1754dc 100644 ---- a/docs/source/terminology.md -+++ b/docs/source/terminology.md -@@ -1,4 +1,4 @@ --## Terminology -+# Terminology - - ### Actor - -diff --git a/docs/source/unit-testing.md b/docs/source/unit-testing.md -index 52310e1..f721d55 100644 ---- a/docs/source/unit-testing.md -+++ b/docs/source/unit-testing.md -@@ -49,7 +49,7 @@ def test_actor_execution(current_actor_context): - current_actor_context.run() - ``` - --This example makes use of the [current_actor_context](pydoc/leapp.html#leapp.snactor.fixture.current_actor_context) -+This example makes use of the [current_actor_context](#leapp.snactor.fixture.current_actor_context) - fixture and will execute the `MyActor` actor. - - Now if you would want to check that it produced an imaginary model called -@@ -92,7 +92,7 @@ The unit testing support was first implemented with the help of - [pytest fixtures](https://docs.pytest.org/en/latest/fixture.html). - Nowadays, we encourage you to use only the `current_actor_context` fixture - mentioned above. However the other fixtures have been preserved and are --still possible to use - see their [documentation](pydoc/leapp.html#module-leapp.snactor.fixture). -+still possible to use - see their [documentation](#leapp.snactor.fixture). - - #### Testing actors that modify the OS - -diff --git a/leapp/libraries/actor/__init__.py b/leapp/libraries/actor/__init__.py -index a0662c5..e63b5e1 100644 ---- a/leapp/libraries/actor/__init__.py -+++ b/leapp/libraries/actor/__init__.py -@@ -5,7 +5,7 @@ are placed in the actor's libraries folder. - - Example: - If you actor has a libraries folder with a module.py python module, import it -- from the actor like this:: -+ from the actor like this: - - from leapp.libraries.actor import module - -diff --git a/leapp/libraries/common/__init__.py b/leapp/libraries/common/__init__.py -index d14c19e..a983cfa 100644 ---- a/leapp/libraries/common/__init__.py -+++ b/leapp/libraries/common/__init__.py -@@ -4,7 +4,7 @@ are placed in the repository's libraries folder. - - Example: - If any of the repositories has a libraries folder with a module.py python module, import it -- from the actor like this:: -+ from the actor like this: - - from leapp.libraries.common import module - -diff --git a/leapp/utils/__init__.py b/leapp/utils/__init__.py -index 68a5f38..1f5dde1 100644 ---- a/leapp/utils/__init__.py -+++ b/leapp/utils/__init__.py -@@ -13,8 +13,8 @@ def get_api_models(actor, what): - - :param what: A string which either is 'consumes' or 'produces' - :type what: str -- :param actor: Actor type/instance or ActorDefinition instance to retrieve the information from -- :type actor: Actor or ActorDefinition -+ :param actor: type/instance or ActorDefinition instance to retrieve the information from -+ :type actor: leapp.actors.Actor or ActorDefinition - :return: Tuple of all produced or consumed models as specified by actor and APIs used by the actor. - """ - -diff --git a/requirements-docs.txt b/requirements-docs.txt -index 54d5ba1..93096c4 100644 ---- a/requirements-docs.txt -+++ b/requirements-docs.txt -@@ -1,7 +1,9 @@ - -r requirements-tests.txt - --CommonMark==0.7.5 --sphinx>=1.5,<1.6 --sphinx_rtd_theme==0.4.3 -+sphinx==7.2.6 -+sphinx_rtd_theme -+sphinxcontrib-jquery -+docutils -+CommonMark -+myst-parser - sphinx-autobuild --git+https://github.com/leapp-to/recommonmark.git@master --- -2.47.0 - diff --git a/SOURCES/0003-configs-implement-actor-configuration-support.patch b/SOURCES/0003-configs-implement-actor-configuration-support.patch deleted file mode 100644 index 806a8c1..0000000 --- a/SOURCES/0003-configs-implement-actor-configuration-support.patch +++ /dev/null @@ -1,1575 +0,0 @@ -From b1539e2dba07f5c0a0d6b76d53bc344890200965 Mon Sep 17 00:00:00 2001 -From: Toshio Kuratomi -Date: Thu, 12 Sep 2024 13:25:55 -0700 -Subject: [PATCH 3/6] configs: implement actor configuration support - -This commit introduces multiple improvements and fixes for actor -configuration management in LEAPP, including configuration schema -support, API updates, validation improvements, and compatibility fixes. - -- Actor Configuration: - - Add actor configuration support - - Introduce configuration schema attributes for LEAPP actors. - - Create an API to load and validate actor configs against the schemas - stored in actors. - - Provide a function to retrieve actor-specified configurations. - - Enable config directories at both repository-wide and actor-wide - levels. - - Add configs to `leapp.db`. - -- Configuration Schema Support: - - Add `_is_config_sequence()` to validate sequences (lists, tuples) of - configuration fields. - - Add support for `StringMap` field types in `config_schemas`. - -- Testing and Linting: - - Separate linting and unittests for better CI control. - -- Dependency Management: - - Add `pyyaml` to requirements in `requirements.txt`, `setup.py`, and - spec files. - -Some unit tests were also updated as they rely on `os.chdir` which -is problematic as the patch tries to correctly reverse any os.chdir -that is executed. Therefore, we mock `os.chdir` in the appropriate -unit tests. - -JIRA: OAMG-8803 ---- - .github/workflows/unit-tests.yml | 12 + - etc/leapp/leapp.conf | 2 + - leapp/actors/__init__.py | 78 +++-- - leapp/actors/config.py | 318 ++++++++++++++++++ - leapp/configs/__init__.py | 0 - leapp/configs/actor/__init__.py | 13 + - leapp/configs/common/__init__.py | 4 + - leapp/libraries/stdlib/api.py | 7 + - leapp/models/fields/__init__.py | 78 ++++- - leapp/repository/__init__.py | 22 +- - leapp/repository/actor_definition.py | 41 ++- - leapp/repository/definition.py | 5 +- - leapp/repository/scan.py | 16 + - leapp/utils/audit/__init__.py | 65 +++- - leapp/workflows/__init__.py | 1 + - packaging/leapp.spec | 2 + - requirements.txt | 1 + - res/container-tests/Containerfile.ubi10 | 13 - - res/container-tests/Containerfile.ubi10-lint | 35 ++ - res/container-tests/Containerfile.ubi7 | 13 - - res/container-tests/Containerfile.ubi7-lint | 28 ++ - res/container-tests/Containerfile.ubi8 | 13 - - res/container-tests/Containerfile.ubi8-lint | 31 ++ - res/container-tests/Containerfile.ubi9 | 13 - - res/container-tests/Containerfile.ubi9-lint | 30 ++ - res/schema/audit-layout.sql | 13 +- - .../0003-add-actor-configuration.sql | 16 + - setup.py | 2 +- - tests/scripts/test_actor_config_db.py | 90 +++++ - tests/scripts/test_metadata.py | 5 +- - .../test_repository_actor_definition.py | 6 +- - 31 files changed, 876 insertions(+), 97 deletions(-) - create mode 100644 leapp/actors/config.py - create mode 100644 leapp/configs/__init__.py - create mode 100644 leapp/configs/actor/__init__.py - create mode 100644 leapp/configs/common/__init__.py - create mode 100644 res/container-tests/Containerfile.ubi10-lint - create mode 100644 res/container-tests/Containerfile.ubi7-lint - create mode 100644 res/container-tests/Containerfile.ubi8-lint - create mode 100644 res/container-tests/Containerfile.ubi9-lint - create mode 100644 res/schema/migrations/0003-add-actor-configuration.sql - create mode 100644 tests/scripts/test_actor_config_db.py - -diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml -index a0a3942..d994b27 100644 ---- a/.github/workflows/unit-tests.yml -+++ b/.github/workflows/unit-tests.yml -@@ -18,15 +18,27 @@ jobs: - - name: Run unit tests with python3.12 on el9 - python: python3.12 - container: ubi10 -+ - name: Run python linters with python3.12 on el9 -+ python: python3.12 -+ container: ubi10-lint - - name: Run unit tests with python3.9 on el9 - python: python3.9 - container: ubi9 -+ - name: Run python linters with python3.9 on el9 -+ python: python3.9 -+ container: ubi9-lint - - name: Run unit tests with python 3.6 on el8 - python: python3.6 - container: ubi8 -+ - name: Run python linters with python 3.6 on el8 -+ python: python3.6 -+ container: ubi8-lint - - name: Run unit tests with python2.7 on el7 - python: python2.7 - container: ubi7 -+ - name: Run python linters with python2.7 on el7 -+ python: python2.7 -+ container: ubi7-lint - - steps: - - name: Checkout code -diff --git a/etc/leapp/leapp.conf b/etc/leapp/leapp.conf -index d641b30..a96dcce 100644 ---- a/etc/leapp/leapp.conf -+++ b/etc/leapp/leapp.conf -@@ -4,3 +4,5 @@ repo_path=/etc/leapp/repos.d/ - [database] - path=/var/lib/leapp/leapp.db - -+[actor_config] -+path=/etc/leapp/actor_conf.d/ -diff --git a/leapp/actors/__init__.py b/leapp/actors/__init__.py -index 9d83bf1..5970bdb 100644 ---- a/leapp/actors/__init__.py -+++ b/leapp/actors/__init__.py -@@ -1,7 +1,16 @@ -+import functools - import logging - import os - import sys - -+try: -+ # Python 3.3+ -+ from collections.abc import Sequence -+except ImportError: -+ # Python 2.6 through 3.2 -+ from collections import Sequence -+ -+from leapp.actors.config import Config, retrieve_config - from leapp.compat import string_types - from leapp.dialogs import Dialog - from leapp.exceptions import (MissingActorAttributeError, RequestStopAfterPhase, StopActorExecution, -@@ -41,6 +50,11 @@ class Actor(object): - Write the actor's description as a docstring. - """ - -+ config_schemas = () -+ """ -+ Defines the structure of the configuration that the actor uses. -+ """ -+ - consumes = () - """ - Tuple of :py:class:`leapp.models.Model` derived classes defined in the :ref:`repositories ` -@@ -86,6 +100,7 @@ class Actor(object): - 'path': os.path.dirname(sys.modules[type(self).__module__].__file__), - 'class_name': type(self).__name__, - 'description': self.description or type(self).__doc__, -+ 'config_schemas': [c.__name__ for c in self.config_schemas], - 'consumes': [c.__name__ for c in self.consumes], - 'produces': [p.__name__ for p in self.produces], - 'tags': [t.__name__ for t in self.tags], -@@ -100,6 +115,7 @@ class Actor(object): - This depends on the definition of such a configuration model being defined by the workflow - and an actor that provides such a message. - """ -+ - Actor.current_instance = self - install_translation_for_actor(type(self)) - self._messaging = messaging -@@ -107,8 +123,12 @@ class Actor(object): - self.skip_dialogs = skip_dialogs - """ A configured logger instance for the current actor. """ - -+ # self._configuration is the workflow configuration. -+ # self.config_schemas is the actor defined configuration. -+ # self.config is the actual actor configuration - if config_model: - self._configuration = next(self.consume(config_model), None) -+ self.config = retrieve_config(self.config_schemas) - - self._path = path - -@@ -359,6 +379,15 @@ class Actor(object): - actor=self, - details=details) - -+ def retrieve_config(self): -+ """ -+ Retrieve the configuration described by self.config_schema. -+ -+ :return: Dictionary containing requested configuration. -+ :rtype: dict -+ """ -+ return retrieve_config(self.config_schema) -+ - - def _is_type(value_type): - def validate(actor, name, value): -@@ -390,17 +419,23 @@ def _lint_warn(actor, name, type_name): - logging.getLogger("leapp.linter").warning("Actor %s field %s should be a tuple of %s", actor, name, type_name) - - --def _is_model_tuple(actor, name, value): -- if isinstance(value, type) and issubclass(value, Model): -- _lint_warn(actor, name, "Models") -+def _is_foo_sequence(cls, cls_name, actor, name, value): -+ if isinstance(value, type) and issubclass(value, cls): -+ _lint_warn(actor, name, cls_name) - value = (value,) -- _is_type(tuple)(actor, name, value) -- if not all([True] + [isinstance(item, type) and issubclass(item, Model) for item in value]): -+ _is_type(Sequence)(actor, name, value) -+ if not all(isinstance(item, type) and issubclass(item, cls) for item in value): - raise WrongAttributeTypeError( -- 'Actor {} attribute {} should contain only Models'.format(actor, name)) -+ 'Actor {} attribute {} should contain only {}'.format(actor, name, cls_name)) - return value - - -+_is_config_sequence = functools.partial(_is_foo_sequence, Config, "Configs") -+_is_model_sequence = functools.partial(_is_foo_sequence, Model, "Models") -+_is_tag_sequence = functools.partial(_is_foo_sequence, Tag, "Tags") -+_is_api_sequence = functools.partial(_is_foo_sequence, WorkflowAPI, "WorkflowAPIs") -+ -+ - def _is_dialog_tuple(actor, name, value): - if isinstance(value, Dialog): - _lint_warn(actor, name, "Dialogs") -@@ -412,28 +447,6 @@ def _is_dialog_tuple(actor, name, value): - return value - - --def _is_tag_tuple(actor, name, value): -- if isinstance(value, type) and issubclass(value, Tag): -- _lint_warn(actor, name, "Tags") -- value = (value,) -- _is_type(tuple)(actor, name, value) -- if not all([True] + [isinstance(item, type) and issubclass(item, Tag) for item in value]): -- raise WrongAttributeTypeError( -- 'Actor {} attribute {} should contain only Tags'.format(actor, name)) -- return value -- -- --def _is_api_tuple(actor, name, value): -- if isinstance(value, type) and issubclass(value, WorkflowAPI): -- _lint_warn(actor, name, "Apis") -- value = (value,) -- _is_type(tuple)(actor, name, value) -- if not all([True] + [isinstance(item, type) and issubclass(item, WorkflowAPI) for item in value]): -- raise WrongAttributeTypeError( -- 'Actor {} attribute {} should contain only WorkflowAPIs'.format(actor, name)) -- return value -- -- - def _get_attribute(actor, name, validator, required=False, default_value=None, additional_info='', resolve=None): - if resolve: - value = resolve(actor, name) -@@ -464,13 +477,14 @@ def get_actor_metadata(actor): - # # if path is not transformed into the realpath. - ('path', os.path.dirname(os.path.realpath(sys.modules[actor.__module__].__file__))), - _get_attribute(actor, 'name', _is_type(string_types), required=True), -- _get_attribute(actor, 'tags', _is_tag_tuple, required=True, additional_info=additional_tag_info), -- _get_attribute(actor, 'consumes', _is_model_tuple, required=False, default_value=(), resolve=get_api_models), -- _get_attribute(actor, 'produces', _is_model_tuple, required=False, default_value=(), resolve=get_api_models), -+ _get_attribute(actor, 'tags', _is_tag_sequence, required=True, additional_info=additional_tag_info), -+ _get_attribute(actor, 'consumes', _is_model_sequence, required=False, default_value=(), resolve=get_api_models), -+ _get_attribute(actor, 'produces', _is_model_sequence, required=False, default_value=(), resolve=get_api_models), - _get_attribute(actor, 'dialogs', _is_dialog_tuple, required=False, default_value=()), - _get_attribute(actor, 'description', _is_type(string_types), required=False, - default_value=actor.__doc__ or 'There has been no description provided for this actor.'), -- _get_attribute(actor, 'apis', _is_api_tuple, required=False, default_value=()) -+ _get_attribute(actor, 'config_schemas', _is_config_sequence, required=False, default_value=()), -+ _get_attribute(actor, 'apis', _is_api_sequence, required=False, default_value=()) - ]) - - -diff --git a/leapp/actors/config.py b/leapp/actors/config.py -new file mode 100644 -index 0000000..160c159 ---- /dev/null -+++ b/leapp/actors/config.py -@@ -0,0 +1,318 @@ -+""" -+Config file format: -+ yaml file like this: -+ -+--- -+# Note: have to add a fields.Map type before we can use yaml mappings. -+section_name: -+ field1_name: value -+ field2_name: -+ - listitem1 -+ - listitem2 -+section2_name: -+ field3_name: value -+ -+Config files are any yaml files in /etc/leapp/actor_config.d/ -+(This is settable in /etc/leapp/leapp.conf) -+ -+""" -+__metaclass__ = type -+ -+import abc -+import glob -+import logging -+import os.path -+from collections import defaultdict -+ -+import six -+import yaml -+ -+from leapp.models.fields import ModelViolationError -+ -+ -+try: -+ # Compiled versions if available, for speed -+ from yaml import CSafeLoader as SafeLoader -+except ImportError: -+ from yaml import SafeLoader -+ -+ -+_ACTOR_CONFIG = None -+ -+log = logging.getLogger('leapp.actors.config') -+ -+ -+class SchemaError(Exception): -+ """ -+ Raised when actors use conflicting schemas. -+ -+ For example, one schema wants `section.field` to be an integer and other schema wants -+ `section.field` to be a string. -+ """ -+ -+ -+class ValidationError(Exception): -+ """ -+ Raised when a config file fails to validate against any of the available schemas. -+ """ -+ -+ -+# pylint: disable=deprecated-decorator -+# @abc.abstractproperty is deprecated in newer Python3 versions but it's -+# necessary for Python <= 3.3 (including 2.7) -+@six.add_metaclass(abc.ABCMeta) -+class Config: -+ """ -+ An Actor config schema looks like this. -+ -+ :: -+ class RHUIConfig(Config): -+ section = "rhui" -+ name = "file_map" -+ type_ = fields.Map(fields.String()) -+ description = 'Description here' -+ default = {"repo": "url"} -+ """ -+ @abc.abstractproperty -+ def section(self): -+ pass -+ -+ @abc.abstractproperty -+ def name(self): -+ pass -+ -+ @abc.abstractproperty -+ def type_(self): -+ pass -+ -+ @abc.abstractproperty -+ def description(self): -+ pass -+ -+ @abc.abstractproperty -+ def default(self): -+ pass -+ -+ @classmethod -+ def to_dict(cls): -+ """ -+ Return a dictionary representation of the config item that would be suitable for putting -+ into a config file. -+ """ -+ representation = { -+ cls.section: { -+ '{0}_description__'.format(cls.name): cls.description -+ } -+ } -+ # TODO: Retrieve the default values from the type field. -+ # Something like this maybe: -+ # representation[cls.section][cls.name] = cls.type_.get_default() -+ -+ return representation -+ -+ @classmethod -+ def serialize(cls): -+ """ -+ :return: Serialized information for the config -+ """ -+ return { -+ 'class_name': cls.__name__, -+ 'section': cls.section, -+ 'name': cls.name, -+ 'type': cls.type_.serialize(), -+ 'description': cls.description, -+ 'default': cls.default, -+ } -+# pylint: enable=deprecated-decorator -+ -+ -+def _merge_config(configuration, new_config): -+ """ -+ Merge two dictionaries representing configuration. fields in new_config overwrite -+ any existing fields of the same name in the same section in configuration. -+ """ -+ for section_name, section in new_config.items(): -+ if section_name not in configuration: -+ configuration[section_name] = section -+ else: -+ for field_name, field in section: -+ configuration[section_name][field_name] = field -+ -+ -+def _get_config(config_dir='/etc/leapp/actor_conf.d'): -+ """ -+ Read all configuration files from the config_dir and return a dict with their values. -+ """ -+ # We do not do a recursive walk to maintain Python2 compatibility, but we do -+ # not expect rich config hierarchies, so no harm done. -+ config_files = glob.glob(os.path.join(config_dir, '*')) -+ config_files = [f for f in config_files if f.endswith('.yml') or f.endswith('.yaml')] -+ config_files.sort() -+ -+ configuration = {} -+ for config_file in config_files: -+ with open(config_file) as f: -+ raw_cfg = f.read() -+ -+ try: -+ parsed_config = yaml.load(raw_cfg, SafeLoader) -+ except Exception as e: -+ log.warning("Warning: unparsable yaml file %s in the config directory." -+ " Error: %s", config_file, str(e)) -+ raise -+ -+ _merge_config(configuration, parsed_config) -+ -+ return configuration -+ -+ -+def normalize_schemas(schemas): -+ """ -+ Merge all schemas into a single dictionary and validate them for errors we can detect. -+ """ -+ added_fields = set() -+ normalized_schema = defaultdict(dict) -+ for schema in schemas: -+ for field in schema: -+ unique_name = (field.section, field.name) -+ -+ # Error if the field has been added by another schema -+ if unique_name in added_fields and added_fields[unique_name] != field: -+ # TODO: Also include information on what Actor contains the -+ # conflicting fields but that information isn't passed into -+ # this function right now. -+ message = ('Two actors added incompatible configuration items' -+ ' with the same name for Section: {section},' -+ ' Field: {field}'.format(section=field.section, -+ field=field.name)) -+ log.error(message) -+ raise SchemaError(message) -+ -+ # TODO: More validation here. -+ -+ # Store the fields from the schema in a way that we can easily look -+ # up while validating -+ added_fields.add(unique_name) -+ normalized_schema[field.section][field.name] = field -+ -+ return normalized_schema -+ -+ -+def _validate_field_type(field_type, field_value, field_path): -+ """ -+ Return False if the field is not of the proper type. -+ -+ :param str field_path: Path in the config where the field is placed. -+ Example: A field 'target_clients' in a section 'rhui' would have a path 'rhui.target_clients' -+ """ -+ try: -+ # the name= parameter is displayed in error messages to let the user know what precisely is wrong -+ field_type._validate_model_value(field_value, name=field_path) -+ except ModelViolationError as e: -+ # Any problems mean that the field did not validate. -+ log.info("Configuration value failed to validate with: %s", e) -+ return False -+ return True -+ -+ -+def _normalize_config(actor_config, schema): -+ # Go through the config and log warnings about unexpected sections/fields. -+ for section_name, section in actor_config.items(): -+ if section_name not in schema: -+ # TODO: Also have information about which config file contains the unknown field. -+ message = "A config file contained an unknown section: {section}".format(section=section_name) -+ log.warning(message) -+ continue -+ -+ for field_name in actor_config: -+ # Any field names which end in "__" are reserved for LEAPP to use -+ # for its purposes. In particular, it places documentation of -+ # a field's value into these reserved field names. -+ if field_name.endswith("__"): -+ continue -+ -+ if field_name not in schema[section_name]: -+ # TODO: Also have information about which config file contains the unknown field. -+ message = ("A config file contained an unknown field: (Section:" -+ " {section}, Field: {field})".format( -+ section=section_name, field=field_name) -+ ) -+ log.warning(message) -+ -+ # Do several things: -+ # * Validate that the config values are of the proper types. -+ # * Add default values where no config value was provided. -+ normalized_actor_config = {} -+ for section_name, section in schema.items(): -+ for field_name, field in section.items(): -+ # TODO: We might be able to do this using the default piece of -+ # model.fields.Field(). Something using -+ # schema[section_name, field_name].type_ with the value from -+ # actor_config[section_name][field_name]. But looking at the Model -+ # code, I wasn't quite sure how this should be done so I think this -+ # will work for now. -+ -+ # For every item in the schema, either retrieve the value from the -+ # config files or set it to the default. -+ try: -+ value = actor_config[section_name][field_name] -+ except KeyError: -+ # Either section_name or field_name doesn't exist -+ section = actor_config[section_name] = actor_config.get(section_name, {}) -+ # May need to deepcopy default if these values are modified. -+ # However, it's probably an error if they are modified and we -+ # should possibly look into disallowing that. -+ value = field.default -+ section[field_name] = value -+ -+ field_path = '{0}.{1}'.format(section_name, field_name) -+ if not _validate_field_type(field.type_, value, field_path): -+ raise ValidationError("Config value for (Section: {section}," -+ " Field: {field}) is not of the correct" -+ " type".format(section=section_name, -+ field=field_name) -+ ) -+ -+ normalized_section = normalized_actor_config.get(section_name, {}) -+ normalized_section[field_name] = value -+ # If the section already exists, this is a no-op. Otherwise, it -+ # sets it to the newly created dict. -+ normalized_actor_config[section_name] = normalized_section -+ -+ return normalized_actor_config -+ -+ -+def load(config_dir, schemas): -+ """ -+ Return Actor Configuration. -+ -+ :returns: a dict representing the configuration. -+ :raises ValueError: if the actor configuration does not match the schema. -+ -+ This function reads the config, validates it, and adds any default values. -+ """ -+ global _ACTOR_CONFIG -+ if _ACTOR_CONFIG: -+ return _ACTOR_CONFIG -+ -+ config = _get_config(config_dir) -+ config = _normalize_config(config, schemas) -+ -+ _ACTOR_CONFIG = config -+ return _ACTOR_CONFIG -+ -+ -+def retrieve_config(schema): -+ """Called by the actor to retrieve the actor configuration specific to this actor.""" -+ # TODO: The use of _ACTOR_CONFIG isn't good API. Since this function is -+ # called by the Actors, we *know* that this is okay to do (as the -+ # configuration will have already been loaded.) However, there's nothing in -+ # the API that ensures that this is the case. Need to redesign this. -+ # Can't think of how it should look right now because loading requires -+ # information that the Actor doesn't know. -+ -+ configuration = defaultdict(dict) -+ for field in schema: -+ configuration[field.section][field.name] = _ACTOR_CONFIG[field.section][field.name] -+ -+ return dict(configuration) -diff --git a/leapp/configs/__init__.py b/leapp/configs/__init__.py -new file mode 100644 -index 0000000..e69de29 -diff --git a/leapp/configs/actor/__init__.py b/leapp/configs/actor/__init__.py -new file mode 100644 -index 0000000..37a0c80 ---- /dev/null -+++ b/leapp/configs/actor/__init__.py -@@ -0,0 +1,13 @@ -+""" -+:py:mod:`leapp.configs.actor` represents the import location for private actor config schema that -+are placed in the actor's configs folder. -+ -+ -+Example: -+ If your actor has a configs folder with a schemas.py python module, import it -+ from the actor like this:: -+ -+ from leapp.configs.actor import schemas -+ -+This directory is intended for the definitions of actor configuration fields. -+""" -diff --git a/leapp/configs/common/__init__.py b/leapp/configs/common/__init__.py -new file mode 100644 -index 0000000..d41c86c ---- /dev/null -+++ b/leapp/configs/common/__init__.py -@@ -0,0 +1,4 @@ -+""" -+:py:mod:`leapp.configs.common` represents an import location for shared libraries that -+are placed in the repository's configs folder. -+""" -diff --git a/leapp/libraries/stdlib/api.py b/leapp/libraries/stdlib/api.py -index c49a03d..267468b 100644 ---- a/leapp/libraries/stdlib/api.py -+++ b/leapp/libraries/stdlib/api.py -@@ -228,3 +228,10 @@ def get_actor_tool_path(name): - :rtype: str or None - """ - return current_actor().get_actor_tool_path(name) -+ -+ -+def retrieve_config(): -+ """ -+ Retrieve the configuration specific to the specified schema. -+ """ -+ return current_actor().retrieve_config() -diff --git a/leapp/models/fields/__init__.py b/leapp/models/fields/__init__.py -index 5e24be4..e5052c6 100644 ---- a/leapp/models/fields/__init__.py -+++ b/leapp/models/fields/__init__.py -@@ -2,6 +2,12 @@ import base64 - import copy - import datetime - import json -+try: -+ # Python 3 -+ from collections.abc import Sequence -+except ImportError: -+ # Python 2.7 -+ from collections import Sequence - - import six - -@@ -147,7 +153,7 @@ class Field(object): - - def serialize(self): - """ -- :return: Serialized form of the workflow -+ :return: Serialized form of the field - """ - return { - 'nullable': self._nullable, -@@ -185,11 +191,13 @@ class BuiltinField(Field): - self._validate(value=value, name=name, expected_type=self._builtin_type) - - def _validate(self, value, name, expected_type): -- if not isinstance(expected_type, tuple): -+ if not isinstance(expected_type, Sequence): - expected_type = (expected_type,) -+ - if value is None and self._nullable: - return -- if not any(isinstance(value, t) for t in expected_type): -+ -+ if not isinstance(value, expected_type): - names = ', '.join(['{}'.format(t.__name__) for t in expected_type]) - raise ModelViolationError("Fields {} is of type: {} expected: {}".format(name, type(value).__name__, - names)) -@@ -457,6 +465,70 @@ class List(Field): - return result - - -+class StringMap(Field): -+ """ -+ Map from strings to instances of a given value type. -+ """ -+ def __init__(self, value_type, **kwargs): -+ super(StringMap, self).__init__(**kwargs) -+ -+ if self._default is not None: -+ self._default = copy.copy(self._default) -+ -+ if not isinstance(value_type, Field): -+ raise ModelMisuseError("value_type must be an instance of a type derived from Field") -+ -+ self._value_type = value_type -+ -+ def _validate_model_value_using_validator(self, new_map, name, validation_method): -+ list_validator_fn = getattr(super(StringMap, self), validation_method) -+ list_validator_fn(new_map, name) -+ -+ if isinstance(new_map, dict): -+ for key in new_map: -+ # Check that the key is trully a string -+ if not isinstance(key, str): -+ err = 'Expected a key of type `str`, but got a key `{}` of type `{}`' -+ raise ModelViolationError(err.format(key, type(key).__name__)) -+ -+ value = new_map[key] # avoid using .items(), as it creates a list of all items (slow) in py2 -+ -+ # _value_type's validation will check whether the value has a correct type -+ value_validator_fn = getattr(self._value_type, validation_method) -+ value_validator_fn(value, name='{}[{}]'.format(name, key)) -+ elif value is not None: -+ raise ModelViolationError('Expected a dict but got {} for the {} field'.format(type(value).__name__, name)) -+ -+ def _validate_model_value(self, value, name): -+ self._validate_model_value_using_validator(value, name, '_validate_model_value') -+ -+ def _validate_builtin_value(self, value, name): -+ self._validate_model_value_using_validator(value, name, '_validate_builtin_value') -+ -+ def _convert_to_model(self, value, name): -+ self._validate_builtin_value(value=value, name=name) -+ -+ if value is None: -+ return value -+ -+ converter = self._value_type._convert_to_model -+ return {key: converter(value[key], name='{0}["{1}"]'.format(name, key)) for key in value} -+ -+ def _convert_from_model(self, value, name): -+ self._validate_model_value(value=value, name=name) -+ -+ if value is None: -+ return value -+ -+ converter = self._value_type._convert_from_model -+ return {key: converter(value[key], name='{0}["{1}"]'.format(name, key)) for key in value} -+ -+ def serialize(self): -+ result = super(StringMap, self).serialize() -+ result['value_type'] = self._value_type.serialize() -+ return result -+ -+ - class Model(Field): - """ - Model is used to use other Models as fields -diff --git a/leapp/repository/__init__.py b/leapp/repository/__init__.py -index 58b6d16..8b7aac4 100644 ---- a/leapp/repository/__init__.py -+++ b/leapp/repository/__init__.py -@@ -7,6 +7,7 @@ from leapp.compat import load_module - from leapp.exceptions import RepoItemPathDoesNotExistError, UnsupportedDefinitionKindError - from leapp.models import get_models, resolve_model_references - import leapp.libraries.common # noqa # pylint: disable=unused-import -+import leapp.configs.common # noqa # pylint: disable=unused-import - from leapp.repository.actor_definition import ActorDefinition - from leapp.repository.definition import DefinitionKind - from leapp.tags import get_tags -@@ -144,8 +145,10 @@ class Repository(object): - self.log.debug("Extending LEAPP_COMMON_FILES for common file paths") - self._extend_environ_paths('LEAPP_COMMON_FILES', self.files) - self.log.debug("Installing repository provided common libraries loader hook") -+ - sys.meta_path.append(LeappLibrariesFinder(module_prefix='leapp.libraries.common', paths=self.libraries)) - sys.meta_path.append(LeappLibrariesFinder(module_prefix='leapp.workflows.api', paths=self.apis)) -+ sys.meta_path.append(LeappLibrariesFinder(module_prefix='leapp.configs.common', paths=self.configs)) - - if not skip_actors_discovery: - if not stage or stage is _LoadStage.ACTORS: -@@ -189,6 +192,15 @@ class Repository(object): - }) - return data - -+ # Note: `configs` are not present here because we are not yet making -+ # them globally accessible. This is to force people to copy the config -+ # schema to their Actors instead of importing them from other Actors. -+ # That copy, in turn, is a good idea so the framework can return an -+ # error if two Actors share the same config but they have different -+ # schemafor it (for instance, if Actor Foo and Bar were sharing the -+ # same config entry but Actor Foo updated the entry in a later version. -+ # We need to error so Actor Bar can either be ported to the new -+ # definition or use a different config entry for it's needs.) - return { - 'repo_dir': self._repo_dir, - 'actors': [mapped_actor_data(a.serialize()) for a in self.actors], -@@ -199,7 +211,8 @@ class Repository(object): - 'workflows': filtered_serialization(get_workflows, self.workflows), - 'tools': [dict([('path', path)]) for path in self.relative_paths(self.tools)], - 'files': [dict([('path', path)]) for path in self.relative_paths(self.files)], -- 'libraries': [dict([('path', path)]) for path in self.relative_paths(self.libraries)] -+ 'libraries': [dict([('path', path)]) for path in self.relative_paths(self.libraries)], -+ 'configs': [dict([('path', path)]) for path in self.relative_paths(self.configs)], - } - - def _extend_environ_paths(self, name, paths): -@@ -268,6 +281,13 @@ class Repository(object): - """ - return tuple(self._definitions.get(DefinitionKind.LIBRARIES, ())) - -+ @property -+ def configs(self): -+ """ -+ :return: Tuple of configs in the repository -+ """ -+ return tuple(self._definitions.get(DefinitionKind.CONFIGS, ())) -+ - @property - def files(self): - """ -diff --git a/leapp/repository/actor_definition.py b/leapp/repository/actor_definition.py -index 0e9cc0a..454d7ad 100644 ---- a/leapp/repository/actor_definition.py -+++ b/leapp/repository/actor_definition.py -@@ -175,6 +175,7 @@ class ActorDefinition(object): - 'class_name': self.class_name, - 'description': self.description, - 'tags': self.tags, -+ 'config_schemas': self.config_schemas, - 'consumes': self.consumes, - 'produces': self.produces, - 'apis': self.apis, -@@ -182,6 +183,7 @@ class ActorDefinition(object): - 'tools': self.tools, - 'files': self.files, - 'libraries': self.libraries, -+ 'configs': self.configs, - 'tests': self.tests - } - -@@ -212,7 +214,21 @@ class ActorDefinition(object): - if p.exitcode != 0: - self.log.error("Process inspecting actor in %s failed with %d", self.directory, p.exitcode) - raise ActorInspectionFailedError('Inspection of actor in {path} failed'.format(path=self.directory)) -- result = q.get() -+ -+ # Note (dkubek): The use of injected_context() here is necessary -+ # when retrieving the discovered actor. This is because -+ # configuration schemas are defined within the actor's scope, and -+ # how Leapp manages imports. Configuration schemas, being scoped -+ # within each actor, are accessible internally by the actor itself. -+ # However, attempting to return a configuration schema outside this -+ # scope results in an error. This occurs because the schema class -+ # definition is no longer accessible in the path, making it -+ # unavailable for importint. The injected_context() here ensures -+ # the path to the actor level code remains in scope while accessing -+ # it. -+ with self.injected_context(): -+ result = q.get() -+ - if not result: - self.log.error("Process inspecting actor in %s returned no result", self.directory) - raise ActorInspectionFailedError( -@@ -279,6 +295,13 @@ class ActorDefinition(object): - """ - return self.discover()['description'] - -+ @property -+ def config_schemas(self): -+ """ -+ :return: Actor config_schemas -+ """ -+ return self.discover()['config_schemas'] -+ - @contextlib.contextmanager - def injected_context(self): - """ -@@ -301,11 +324,18 @@ class ActorDefinition(object): - if self.tools: - os.environ['LEAPP_TOOLS'] = os.path.join(self._repo_dir, self._directory, self.tools[0]) - -+ meta_path_backup = sys.meta_path[:] -+ - sys.meta_path.append( - LeappLibrariesFinder( - module_prefix='leapp.libraries.actor', - paths=[os.path.join(self._repo_dir, self.directory, x) for x in self.libraries])) - -+ sys.meta_path.append( -+ LeappLibrariesFinder( -+ module_prefix='leapp.configs.actor', -+ paths=[os.path.join(self._repo_dir, self.directory, x) for x in self.configs])) -+ - previous_path = os.getcwd() - os.chdir(os.path.join(self._repo_dir, self._directory)) - try: -@@ -326,6 +356,8 @@ class ActorDefinition(object): - else: - os.environ.pop('LEAPP_TOOLS', None) - -+ sys.meta_path = meta_path_backup -+ - @property - def apis(self): - """ -@@ -361,6 +393,13 @@ class ActorDefinition(object): - """ - return tuple(self._definitions.get(DefinitionKind.FILES, ())) - -+ @property -+ def configs(self): -+ """ -+ :return: Tuple with path to the configs folder of the actor, empty tuple if none -+ """ -+ return tuple(self._definitions.get(DefinitionKind.CONFIGS, ())) -+ - @property - def tests(self): - """ -diff --git a/leapp/repository/definition.py b/leapp/repository/definition.py -index e853a6a..344ec77 100644 ---- a/leapp/repository/definition.py -+++ b/leapp/repository/definition.py -@@ -14,8 +14,9 @@ class DefinitionKind(object): - LIBRARIES = _Kind('libraries') - TOOLS = _Kind('tools') - FILES = _Kind('files') -+ CONFIGS = _Kind('configs') - TESTS = _Kind('tests') - API = _Kind('api') - -- REPO_WHITELIST = (ACTOR, API, MODEL, TOPIC, TAG, WORKFLOW, TOOLS, LIBRARIES, FILES) -- ACTOR_WHITELIST = (TOOLS, LIBRARIES, FILES, TESTS) -+ REPO_WHITELIST = (ACTOR, API, MODEL, TOPIC, TAG, WORKFLOW, TOOLS, LIBRARIES, FILES, CONFIGS) -+ ACTOR_WHITELIST = (TOOLS, LIBRARIES, FILES, CONFIGS, TESTS) -diff --git a/leapp/repository/scan.py b/leapp/repository/scan.py -index 378940a..94e0512 100644 ---- a/leapp/repository/scan.py -+++ b/leapp/repository/scan.py -@@ -89,6 +89,7 @@ def scan(repository, path): - ('workflows', scan_workflows), - ('files', scan_files), - ('libraries', scan_libraries), -+ ('configs', scan_configs), - ('tests', scan_tests), - ('tools', scan_tools), - ('apis', scan_apis)) -@@ -224,6 +225,21 @@ def scan_libraries(repo, path, repo_path): - repo.add(DefinitionKind.LIBRARIES, os.path.relpath(path, repo_path)) - - -+def scan_configs(repo, path, repo_path): -+ """ -+ Scans configs and adds them to the repository. -+ -+ :param repo: Instance of the repository -+ :type repo: :py:class:`leapp.repository.Repository` -+ :param path: path to the configs -+ :type path: str -+ :param repo_path: path to the repository -+ :type repo_path: str -+ """ -+ if os.listdir(path): -+ repo.add(DefinitionKind.CONFIGS, os.path.relpath(path, repo_path)) -+ -+ - def scan_tools(repo, path, repo_path): - """ - Scans tools and adds them to the repository. -diff --git a/leapp/utils/audit/__init__.py b/leapp/utils/audit/__init__.py -index 16db107..8511179 100644 ---- a/leapp/utils/audit/__init__.py -+++ b/leapp/utils/audit/__init__.py -@@ -222,6 +222,67 @@ class DataSource(Host): - self._data_source_id = cursor.fetchone()[0] - - -+class ActorConfigData(Storable): -+ """ -+ Actor configuration data -+ """ -+ -+ def __init__(self, config=None, hash_id=None): -+ """ -+ :param config: Actor configuration -+ :type config: str -+ :param hash_id: SHA256 hash in hexadecimal representation of config -+ :type hash_id: str -+ """ -+ super(ActorConfigData, self).__init__() -+ self.config = config -+ self.hash_id = hash_id -+ -+ def do_store(self, connection): -+ super(ActorConfigData, self).do_store(connection) -+ connection.execute( -+ 'INSERT OR IGNORE INTO actor_config_data (hash, config) VALUES(?, ?)', -+ (self.hash_id, self.config) -+ ) -+ -+ -+class ActorConfig(Storable): -+ """ -+ Actor configuration -+ """ -+ -+ def __init__(self, context=None, config=None): -+ """ -+ :param context: The execution context -+ :type context: str -+ :param config: Actor configuration -+ :type config: :py:class:`leapp.utils.audit.ActorConfigData` -+ """ -+ super(ActorConfig, self).__init__() -+ self.context = context -+ self.config = config -+ self._actor_config_id = None -+ -+ @property -+ def actor_config_id(self): -+ """ -+ Returns the id of the entry, which is only set when already stored. -+ :return: Integer id or None -+ """ -+ return self._actor_config_id -+ -+ def do_store(self, connection): -+ super(ActorConfig, self).do_store(connection) -+ self.config.do_store(connection) -+ connection.execute( -+ 'INSERT OR IGNORE INTO actor_config (context, actor_config_hash) VALUES(?, ?)', -+ (self.context, self.config.hash_id)) -+ cursor = connection.execute( -+ 'SELECT id FROM actor_config WHERE context = ? AND actor_config_hash = ?', -+ (self.context, self.config.hash_id)) -+ self._actor_config_id = cursor.fetchone()[0] -+ -+ - class Metadata(Storable): - """ - Metadata of an Entity -@@ -651,10 +712,12 @@ def store_actor_metadata(actor_definition, phase): - 'consumes': sorted(model.__name__ for model in _metadata.get('consumes', ())), - 'produces': sorted(model.__name__ for model in _metadata.get('produces', ())), - 'tags': sorted(tag.__name__ for tag in _metadata.get('tags', ())), -+ 'config_schemas': [field.serialize() for field in _metadata.get('config_schemas', ())], - }) - _metadata['phase'] = phase - -- actor_metadata_fields = ('class_name', 'name', 'description', 'phase', 'tags', 'consumes', 'produces', 'path') -+ actor_metadata_fields = ('class_name', 'name', 'description', 'phase', -+ 'tags', 'consumes', 'produces', 'config_schemas', 'path') - metadata = json.dumps({field: _metadata[field] for field in actor_metadata_fields}, sort_keys=True) - metadata_hash_id = hashlib.sha256(metadata.encode('utf-8')).hexdigest() - -diff --git a/leapp/workflows/__init__.py b/leapp/workflows/__init__.py -index 1b6fc98..b6168ee 100644 ---- a/leapp/workflows/__init__.py -+++ b/leapp/workflows/__init__.py -@@ -4,6 +4,7 @@ import socket - import sys - import uuid - -+from leapp.actors.config import retrieve_config - from leapp.dialogs import RawMessageDialog - from leapp.exceptions import CommandError, MultipleConfigActorsError, WorkflowConfigNotAvailable - from leapp.messaging.answerstore import AnswerStore -diff --git a/packaging/leapp.spec b/packaging/leapp.spec -index ab38d20..29ece53 100644 ---- a/packaging/leapp.spec -+++ b/packaging/leapp.spec -@@ -134,6 +134,7 @@ Provides: leapp-framework-dependencies = %{framework_dependencies} - Requires: python-six - Requires: python-setuptools - Requires: python-requests -+Requires: PyYAML - %else # <> rhel 7 - # for Fedora & RHEL 8+ deliver just python3 stuff - # NOTE: requirement on python3 refers to the general version of Python -@@ -144,6 +145,7 @@ Requires: python3 - Requires: python3-six - Requires: python3-setuptools - Requires: python3-requests -+Requires: python3-PyYAML - %endif - Requires: findutils - ################################################## -diff --git a/requirements.txt b/requirements.txt -index ec831ad..2951f23 100644 ---- a/requirements.txt -+++ b/requirements.txt -@@ -1,2 +1,3 @@ - six==1.12 - requests -+PyYAML -diff --git a/res/container-tests/Containerfile.ubi10 b/res/container-tests/Containerfile.ubi10 -index 6d6507c..1d15d29 100644 ---- a/res/container-tests/Containerfile.ubi10 -+++ b/res/container-tests/Containerfile.ubi10 -@@ -20,19 +20,6 @@ ENTRYPOINT virtualenv testenv -p "/usr/bin/$PYTHON_VENV" && \ - pip install -U pytest && \ - pip install -U six && \ - pip install -U . && \ -- export LINTABLES=$(find . -name '*.py' | grep -E -e '^\./leapp\/' -e '^\./tests/scripts/' | sort -u ) && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo '=============== Running pylint ===============' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo $LINTABLES | xargs pylint && echo '===> pylint PASSED' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo '=============== Running flake8 ===============' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- flake8 $LINTABLES && echo '===> flake8 PASSED' && \ - echo '==================================================' && \ - echo '==================================================' && \ - echo '=============== Running tests ===============' && \ -diff --git a/res/container-tests/Containerfile.ubi10-lint b/res/container-tests/Containerfile.ubi10-lint -new file mode 100644 -index 0000000..a32e440 ---- /dev/null -+++ b/res/container-tests/Containerfile.ubi10-lint -@@ -0,0 +1,35 @@ -+FROM registry.access.redhat.com/ubi9/ubi:latest -+ -+VOLUME /payload -+ -+RUN dnf update -y && \ -+ dnf install python3 python312 python3-pip make -y && \ -+ python3 -m pip install --upgrade pip==20.3.4 -+ -+RUN pip install virtualenv -+ -+WORKDIR /payload -+ENTRYPOINT virtualenv testenv -p "/usr/bin/$PYTHON_VENV" && \ -+ source testenv/bin/activate && \ -+ pip install -U setuptools && \ -+ pip install -U funcsigs && \ -+ pip install -U -r requirements-tests.txt && \ -+ # NOTE(mmatuska): The pytest ver defined in requirements-tests is too old \ -+ # for Python 3.12 (missing imp module), there do an update here until we \ -+ # bump that. Similarly for six. \ -+ pip install -U pytest && \ -+ pip install -U six && \ -+ pip install -U . && \ -+ export LINTABLES=$(find . -name '*.py' | grep -E -e '^\./leapp\/' -e '^\./tests/scripts/' | sort -u ) && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo '=============== Running pylint ===============' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo $LINTABLES | xargs pylint && echo '===> pylint PASSED' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo '=============== Running flake8 ===============' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ flake8 $LINTABLES && echo '===> flake8 PASSED' -diff --git a/res/container-tests/Containerfile.ubi7 b/res/container-tests/Containerfile.ubi7 -index 9e36280..fd5b965 100644 ---- a/res/container-tests/Containerfile.ubi7 -+++ b/res/container-tests/Containerfile.ubi7 -@@ -13,19 +13,6 @@ ENTRYPOINT virtualenv testenv && \ - pip install -U funcsigs && \ - pip install -U -r requirements-tests.txt && \ - pip install -U . && \ -- export LINTABLES=$(find . -name '*.py' | grep -E -e '^\./leapp\/' -e '^\./tests/scripts/' | sort -u ) && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo '=============== Running pylint ===============' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo $LINTABLES | xargs pylint --py3k && echo '===> pylint PASSED' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo '=============== Running flake8 ===============' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- flake8 $LINTABLES && echo '===> flake8 PASSED' && \ - echo '==================================================' && \ - echo '==================================================' && \ - echo '=============== Running tests ===============' && \ -diff --git a/res/container-tests/Containerfile.ubi7-lint b/res/container-tests/Containerfile.ubi7-lint -new file mode 100644 -index 0000000..2e1de4a ---- /dev/null -+++ b/res/container-tests/Containerfile.ubi7-lint -@@ -0,0 +1,28 @@ -+FROM registry.access.redhat.com/ubi7/ubi:7.9 -+ -+VOLUME /payload -+ -+RUN yum -y install python27-python-pip && \ -+ scl enable python27 -- pip install -U --target /usr/lib/python2.7/site-packages/ pip==20.3.0 && \ -+ python -m pip install --ignore-installed pip==20.3.4 virtualenv -+ -+WORKDIR /payload -+ENTRYPOINT virtualenv testenv && \ -+ source testenv/bin/activate && \ -+ pip install -U setuptools && \ -+ pip install -U funcsigs && \ -+ pip install -U -r requirements-tests.txt && \ -+ pip install -U . && \ -+ export LINTABLES=$(find . -name '*.py' | grep -E -e '^\./leapp\/' -e '^\./tests/scripts/' | sort -u ) && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo '=============== Running pylint ===============' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo $LINTABLES | xargs pylint --py3k && echo '===> pylint PASSED' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo '=============== Running flake8 ===============' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ flake8 $LINTABLES && echo '===> flake8 PASSED' -diff --git a/res/container-tests/Containerfile.ubi8 b/res/container-tests/Containerfile.ubi8 -index 03d499d..960f4b0 100644 ---- a/res/container-tests/Containerfile.ubi8 -+++ b/res/container-tests/Containerfile.ubi8 -@@ -16,19 +16,6 @@ ENTRYPOINT virtualenv testenv -p "/usr/bin/$PYTHON_VENV" && \ - pip install -U funcsigs && \ - pip install -U -r requirements-tests.txt && \ - pip install -U . && \ -- export LINTABLES=$(find . -name '*.py' | grep -E -e '^\./leapp\/' -e '^\./tests/scripts/' | sort -u ) && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo '=============== Running pylint ===============' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo $LINTABLES | xargs pylint && echo '===> pylint PASSED' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo '=============== Running flake8 ===============' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- flake8 $LINTABLES && echo '===> flake8 PASSED' && \ - echo '==================================================' && \ - echo '==================================================' && \ - echo '=============== Running tests ===============' && \ -diff --git a/res/container-tests/Containerfile.ubi8-lint b/res/container-tests/Containerfile.ubi8-lint -new file mode 100644 -index 0000000..75143d9 ---- /dev/null -+++ b/res/container-tests/Containerfile.ubi8-lint -@@ -0,0 +1,31 @@ -+FROM registry.access.redhat.com/ubi8/ubi:latest -+ -+VOLUME /payload -+ -+ENV PYTHON_VENV "python3.6" -+ -+RUN yum update -y && \ -+ yum install python3 python39 python3-virtualenv make -y && \ -+ yum -y install python3-pip && \ -+ python3 -m pip install --upgrade pip==20.3.4 -+ -+WORKDIR /payload -+ENTRYPOINT virtualenv testenv -p "/usr/bin/$PYTHON_VENV" && \ -+ source testenv/bin/activate && \ -+ pip install -U setuptools && \ -+ pip install -U funcsigs && \ -+ pip install -U -r requirements-tests.txt && \ -+ pip install -U . && \ -+ export LINTABLES=$(find . -name '*.py' | grep -E -e '^\./leapp\/' -e '^\./tests/scripts/' | sort -u ) && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo '=============== Running pylint ===============' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo $LINTABLES | xargs pylint && echo '===> pylint PASSED' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo '=============== Running flake8 ===============' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ flake8 $LINTABLES && echo '===> flake8 PASSED' -diff --git a/res/container-tests/Containerfile.ubi9 b/res/container-tests/Containerfile.ubi9 -index b1b5b71..755e874 100644 ---- a/res/container-tests/Containerfile.ubi9 -+++ b/res/container-tests/Containerfile.ubi9 -@@ -15,19 +15,6 @@ ENTRYPOINT virtualenv testenv -p "/usr/bin/$PYTHON_VENV" && \ - pip install -U funcsigs && \ - pip install -U -r requirements-tests.txt && \ - pip install -U . && \ -- export LINTABLES=$(find . -name '*.py' | grep -E -e '^\./leapp\/' -e '^\./tests/scripts/' | sort -u ) && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo '=============== Running pylint ===============' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo $LINTABLES | xargs pylint && echo '===> pylint PASSED' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- echo '=============== Running flake8 ===============' && \ -- echo '==================================================' && \ -- echo '==================================================' && \ -- flake8 $LINTABLES && echo '===> flake8 PASSED' && \ - echo '==================================================' && \ - echo '==================================================' && \ - echo '=============== Running tests ===============' && \ -diff --git a/res/container-tests/Containerfile.ubi9-lint b/res/container-tests/Containerfile.ubi9-lint -new file mode 100644 -index 0000000..9a1d186 ---- /dev/null -+++ b/res/container-tests/Containerfile.ubi9-lint -@@ -0,0 +1,30 @@ -+FROM registry.access.redhat.com/ubi9/ubi:latest -+ -+VOLUME /payload -+ -+RUN dnf update -y && \ -+ dnf install python3 python39 make python3-pip -y && \ -+ python3 -m pip install --upgrade pip==20.3.4 -+ -+RUN pip install virtualenv -+ -+WORKDIR /payload -+ENTRYPOINT virtualenv testenv -p "/usr/bin/$PYTHON_VENV" && \ -+ source testenv/bin/activate && \ -+ pip install -U setuptools && \ -+ pip install -U funcsigs && \ -+ pip install -U -r requirements-tests.txt && \ -+ pip install -U . && \ -+ export LINTABLES=$(find . -name '*.py' | grep -E -e '^\./leapp\/' -e '^\./tests/scripts/' | sort -u ) && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo '=============== Running pylint ===============' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo $LINTABLES | xargs pylint && echo '===> pylint PASSED' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ echo '=============== Running flake8 ===============' && \ -+ echo '==================================================' && \ -+ echo '==================================================' && \ -+ flake8 $LINTABLES && echo '===> flake8 PASSED' -diff --git a/res/schema/audit-layout.sql b/res/schema/audit-layout.sql -index d567ce4..93a92f1 100644 ---- a/res/schema/audit-layout.sql -+++ b/res/schema/audit-layout.sql -@@ -1,6 +1,6 @@ - BEGIN; - --PRAGMA user_version = 3; -+PRAGMA user_version = 4; - - CREATE TABLE IF NOT EXISTS execution ( - id INTEGER PRIMARY KEY NOT NULL, -@@ -47,6 +47,17 @@ CREATE TABLE IF NOT EXISTS metadata ( - metadata TEXT - ); - -+CREATE TABLE IF NOT EXISTS actor_config ( -+ id INTEGER PRIMARY KEY NOT NULL, -+ context VARCHAR(36) NOT NULL REFERENCES execution (context), -+ actor_config_hash VARCHAR(64) NOT NULL REFERENCES actor_config_data (hash) -+); -+ -+CREATE TABLE IF NOT EXISTS actor_config_data ( -+ hash VARCHAR(64) PRIMARY KEY NOT NULL, -+ config TEXT -+); -+ - CREATE TABLE IF NOT EXISTS entity ( - id INTEGER PRIMARY KEY NOT NULL, - context VARCHAR(36) NOT NULL REFERENCES execution (context), -diff --git a/res/schema/migrations/0003-add-actor-configuration.sql b/res/schema/migrations/0003-add-actor-configuration.sql -new file mode 100644 -index 0000000..11131c8 ---- /dev/null -+++ b/res/schema/migrations/0003-add-actor-configuration.sql -@@ -0,0 +1,16 @@ -+BEGIN; -+ -+CREATE TABLE IF NOT EXISTS actor_config ( -+ id INTEGER PRIMARY KEY NOT NULL, -+ context VARCHAR(36) NOT NULL REFERENCES execution (context), -+ actor_config_hash VARCHAR(64) NOT NULL REFERENCES actor_config_data (hash) -+); -+ -+CREATE TABLE IF NOT EXISTS actor_config_data ( -+ hash VARCHAR(64) PRIMARY KEY NOT NULL, -+ config TEXT -+); -+ -+PRAGMA user_version = 4; -+ -+COMMIT; -diff --git a/setup.py b/setup.py -index 40e7656..3ebe8b2 100644 ---- a/setup.py -+++ b/setup.py -@@ -23,7 +23,7 @@ setup( - name='leapp', - version=main_ns['VERSION'], - packages=find_packages(exclude=EXCLUSION), -- install_requires=['six', 'requests'], -+ install_requires=['six', 'requests', 'PyYAML'], - entry_points=''' - [console_scripts] - snactor=leapp.snactor:main -diff --git a/tests/scripts/test_actor_config_db.py b/tests/scripts/test_actor_config_db.py -new file mode 100644 -index 0000000..75d6676 ---- /dev/null -+++ b/tests/scripts/test_actor_config_db.py -@@ -0,0 +1,90 @@ -+import os -+import hashlib -+import json -+ -+from leapp.utils.audit import (get_connection, dict_factory, ActorConfigData, ActorConfig) -+from leapp.config import get_config -+ -+_CONTEXT_NAME = 'test-context-name-actor-config-db' -+_TEST_ACTOR_CONFIG = {} -+ -+ -+def setup_module(): -+ get_config().set('database', 'path', '/tmp/leapp-test.db') -+ -+ -+def setup(): -+ path = get_config().get('database', 'path') -+ if os.path.isfile(path): -+ os.unlink(path) -+ -+ -+def test_save_empty_actor_config_data(): -+ hash_id = hashlib.sha256('test-empty-actor-config'.encode('utf-8')).hexdigest() -+ cfg = ActorConfigData(hash_id=hash_id, config='') -+ cfg.store() -+ -+ entry = None -+ with get_connection(None) as conn: -+ cursor = conn.execute('SELECT * FROM actor_config_data WHERE hash = ?;', (hash_id,)) -+ cursor.row_factory = dict_factory -+ entry = cursor.fetchone() -+ -+ assert entry is not None -+ assert entry['config'] == '' -+ -+ -+def test_save_empty_actor_config(): -+ hash_id = hashlib.sha256('test-empty-actor-config'.encode('utf-8')).hexdigest() -+ acd = ActorConfigData(hash_id=hash_id, config='') -+ ac = ActorConfig( -+ context=_CONTEXT_NAME, -+ config=acd, -+ ) -+ ac.store() -+ -+ assert ac.actor_config_id -+ -+ entry = None -+ with get_connection(None) as conn: -+ cursor = conn.execute('SELECT * FROM actor_config WHERE id = ?;', (ac.actor_config_id,)) -+ cursor.row_factory = dict_factory -+ entry = cursor.fetchone() -+ -+ assert entry is not None -+ assert entry['context'] == _CONTEXT_NAME -+ assert entry['actor_config_hash'] == hash_id -+ -+ -+def test_store_actor_config(): -+ hash_id = hashlib.sha256('test-actor-config'.encode('utf-8')).hexdigest() -+ config_str = json.dumps(_TEST_ACTOR_CONFIG, sort_keys=True) -+ acd = ActorConfigData(hash_id=hash_id, config=config_str) -+ ac = ActorConfig( -+ context=_CONTEXT_NAME, -+ config=acd, -+ ) -+ ac.store() -+ -+ assert ac.actor_config_id -+ -+ entry = None -+ with get_connection(None) as conn: -+ cursor = conn.execute( -+ 'SELECT * FROM actor_config WHERE id = ?;', (ac.actor_config_id,)) -+ cursor = conn.execute( -+ 'SELECT * ' -+ 'FROM actor_config ' -+ 'JOIN actor_config_data ' -+ 'ON actor_config.actor_config_hash = actor_config_data.hash ' -+ 'WHERE actor_config.id = ?;', -+ (ac.actor_config_id,) -+ ) -+ cursor.row_factory = dict_factory -+ entry = cursor.fetchone() -+ -+ assert entry is not None -+ assert entry['context'] == _CONTEXT_NAME -+ assert entry['actor_config_hash'] == hash_id -+ ans_config = json.loads(entry['config']) -+ assert ans_config == {} -diff --git a/tests/scripts/test_metadata.py b/tests/scripts/test_metadata.py -index 9b5c07f..6631c49 100644 ---- a/tests/scripts/test_metadata.py -+++ b/tests/scripts/test_metadata.py -@@ -20,7 +20,8 @@ _PHASE_NAME = 'test-phase-name' - _DIALOG_SCOPE = 'test-dialog' - - _WORKFLOW_METADATA_FIELDS = ('description', 'name', 'phases', 'short_name', 'tag') --_ACTOR_METADATA_FIELDS = ('class_name', 'name', 'description', 'phase', 'tags', 'consumes', 'produces', 'path') -+_ACTOR_METADATA_FIELDS = ('class_name', 'config_schemas', 'name', 'description', -+ 'phase', 'tags', 'consumes', 'produces', 'path') - - _TEST_WORKFLOW_METADATA = { - 'description': 'No description has been provided for the UnitTest workflow.', -@@ -144,7 +145,7 @@ def test_store_actor_metadata(monkeypatch, repository_dir): - # --- - with repository_dir.as_cwd(): - logger = logging.getLogger('leapp.actor.test') -- with mock.patch.object(logger, 'log') as log_mock: -+ with mock.patch.object(logger, 'log') as log_mock, mock.patch('os.chdir'): - definition = ActorDefinition('actors/test', '.', log=log_mock) - with mock.patch('leapp.repository.actor_definition.get_actor_metadata', return_value=_TEST_ACTOR_METADATA): - with mock.patch('leapp.repository.actor_definition.get_actors', return_value=[True]): -diff --git a/tests/scripts/test_repository_actor_definition.py b/tests/scripts/test_repository_actor_definition.py -index 3fcf757..954928f 100644 ---- a/tests/scripts/test_repository_actor_definition.py -+++ b/tests/scripts/test_repository_actor_definition.py -@@ -13,6 +13,7 @@ _FAKE_META_DATA = { - 'name': 'fake-actor', - 'path': 'actors/test', - 'tags': (), -+ 'config_schemas': (), - 'consumes': (), - 'produces': (), - 'dialogs': (), -@@ -21,7 +22,7 @@ _FAKE_META_DATA = { - - - def test_actor_definition(repository_dir): -- with repository_dir.as_cwd(): -+ with repository_dir.as_cwd(), mock.patch('os.chdir', return_value=None): - logger = logging.getLogger('leapp.actor.test') - with mock.patch.object(logger, 'log') as log_mock: - definition = ActorDefinition('actors/test', '.', log=log_mock) -@@ -40,6 +41,7 @@ def test_actor_definition(repository_dir): - assert definition.consumes == _FAKE_META_DATA['consumes'] - assert definition.produces == _FAKE_META_DATA['produces'] - assert definition.tags == _FAKE_META_DATA['tags'] -+ assert definition.config_schemas == _FAKE_META_DATA['config_schemas'] - assert definition.class_name == _FAKE_META_DATA['class_name'] - assert definition.dialogs == _FAKE_META_DATA['dialogs'] - assert definition.name == _FAKE_META_DATA['name'] -@@ -52,11 +54,13 @@ def test_actor_definition(repository_dir): - assert dumped.pop('produces') == definition.produces - assert dumped.pop('apis') == definition.apis - assert dumped.pop('tags') == definition.tags -+ assert dumped.pop('config_schemas') == definition.config_schemas - assert dumped.pop('dialogs') == [dialog.serialize() for dialog in definition.dialogs] - assert dumped.pop('path') == _FAKE_META_DATA['path'] - assert dumped.pop('name') == definition.name - assert dumped.pop('files') == ('.',) - assert dumped.pop('libraries') == ('.',) -+ assert dumped.pop('configs') == ('.',) - assert dumped.pop('tests') == ('.',) - assert dumped.pop('tools') == ('.',) - # Assert to ensure we covered all keys --- -2.47.0 - diff --git a/SOURCES/0004-pylint-ignore-too-many-params-lines-yield-from.patch b/SOURCES/0004-pylint-ignore-too-many-params-lines-yield-from.patch deleted file mode 100644 index 0071d2e..0000000 --- a/SOURCES/0004-pylint-ignore-too-many-params-lines-yield-from.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 45c1b35fb5cc5ec43288a4318c904bc5ae997638 Mon Sep 17 00:00:00 2001 -From: Michal Hecko -Date: Tue, 29 Oct 2024 22:16:09 +0100 -Subject: [PATCH 4/6] pylint: ignore too many params/lines, yield from - -Ignore pylint's options: -* too-many-lines -* too-many-positional-arguments -* use-yield-from - -Some of these options cannot be used (python2.7 compat) or configured. -See: https://github.com/oamg/leapp-repository/pull/1299 ---- - .pylintrc | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/.pylintrc b/.pylintrc -index fd73083..459933a 100644 ---- a/.pylintrc -+++ b/.pylintrc -@@ -28,7 +28,9 @@ disable= - too-few-public-methods, - too-many-ancestors, - too-many-branches, -+ too-many-lines, - too-many-locals, -+ too-many-positional-arguments, - too-many-public-methods, - too-many-statements, - print-statement, -@@ -42,7 +44,8 @@ disable= - no-absolute-import, # XXX FIXME nice to have one day - unspecified-encoding, # XXX FIXME May be a good thing to have one day though - deprecated-class, # We still have < 3.9 to support -- use-dict-literal -+ use-dict-literal, -+ use-yield-from - - [FORMAT] - # Maximum number of characters on a single line. --- -2.47.0 - diff --git a/SOURCES/0005-packaging-bump-leapp-framework-version.patch b/SOURCES/0005-packaging-bump-leapp-framework-version.patch deleted file mode 100644 index a4abee3..0000000 --- a/SOURCES/0005-packaging-bump-leapp-framework-version.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 607be4cd18dd24695e8fad827e7484bed36f7dce Mon Sep 17 00:00:00 2001 -From: Michal Hecko -Date: Mon, 4 Nov 2024 11:29:00 +0100 -Subject: [PATCH 5/6] packaging: bump leapp-framework version - -Increase the provided leapp-framework version to 6.0 (from 5.0). -Similarly, framework_dependencies are bumped to 6.0. These changes -are done as introducing actor configuration presents a major feature, -and, therefore, any codebases using the framework might want to -require leapp with config support. Bumping the version number, thus, -allows to distinguish between leapp-framework versions that provide -configs and those that do not. ---- - packaging/leapp.spec | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/packaging/leapp.spec b/packaging/leapp.spec -index 29ece53..7efe596 100644 ---- a/packaging/leapp.spec -+++ b/packaging/leapp.spec -@@ -13,11 +13,11 @@ - # This is kind of help for more flexible development of leapp repository, - # so people do not have to wait for new official release of leapp to ensure - # it is installed/used the compatible one. --%global framework_version 5.0 -+%global framework_version 6.0 - - # IMPORTANT: everytime the requirements are changed, increment number by one - # - same for Provides in deps subpackage --%global framework_dependencies 5 -+%global framework_dependencies 6 - - # Do not build bindings for python3 for RHEL == 7 - # # Currently Py2 is dead on Fedora and we don't have to support it. As well, --- -2.47.0 - diff --git a/SOURCES/0006-spec-Introduce-etc-leapp-actor_conf.d-directory.patch b/SOURCES/0006-spec-Introduce-etc-leapp-actor_conf.d-directory.patch deleted file mode 100644 index ea22a07..0000000 --- a/SOURCES/0006-spec-Introduce-etc-leapp-actor_conf.d-directory.patch +++ /dev/null @@ -1,35 +0,0 @@ -From ee6bf5aa0608723528caaf9e6fd2edd67258dcc8 Mon Sep 17 00:00:00 2001 -From: Petr Stodulka -Date: Thu, 14 Nov 2024 16:28:57 +0100 -Subject: [PATCH 6/6] spec: Introduce /etc/leapp/actor_conf.d/ directory - -The directory should be owned by the leapp rpm so leapp actors -could already use it - or existing leapp repositories packages could -install some config files inside already. ---- - packaging/leapp.spec | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/packaging/leapp.spec b/packaging/leapp.spec -index 7efe596..8bb4102 100644 ---- a/packaging/leapp.spec -+++ b/packaging/leapp.spec -@@ -184,6 +184,7 @@ install -m 0755 -d %{buildroot}%{_datadir}/leapp/report_schema - install -m 0644 -p report-schema-v110.json %{buildroot}%{_datadir}/leapp/report_schema/report-schema.json - install -m 0700 -d %{buildroot}%{_sharedstatedir}/leapp - install -m 0755 -d %{buildroot}%{_sysconfdir}/leapp -+install -m 0755 -d %{buildroot}%{_sysconfdir}/leapp/actor_conf.d/ - install -m 0755 -d %{buildroot}%{_sysconfdir}/leapp/repos.d - install -m 0600 -d %{buildroot}%{_sysconfdir}/leapp/answers - # standard directory should have permission set to 0755, however this directory -@@ -209,6 +210,7 @@ install -m 0644 -p man/leapp.1 %{buildroot}%{_mandir}/man1/ - %config(noreplace) %{_sysconfdir}/leapp/leapp.conf - %config(noreplace) %{_sysconfdir}/leapp/logger.conf - %dir %{_sysconfdir}/leapp -+%dir %{_sysconfdir}/leapp/actor_conf.d - %dir %{_sysconfdir}/leapp/answers - %dir %{_sysconfdir}/leapp/repos.d - %{_bindir}/leapp --- -2.47.0 - diff --git a/SPECS/leapp.spec b/SPECS/leapp.spec index 6303c62..5864e62 100644 --- a/SPECS/leapp.spec +++ b/SPECS/leapp.spec @@ -36,8 +36,8 @@ %endif Name: leapp -Version: 0.18.0 -Release: 2%{?dist} +Version: 0.19.0 +Release: 1%{?dist} Summary: OS & Application modernization framework License: ASL 2.0 @@ -65,12 +65,6 @@ Requires: leapp-repository # PATCHES HERE # Patch0001: filename.patch -Patch0001: 0001-Update-references-from-master-branch-to-main.patch -Patch0002: 0002-docs-Update-docs-engine-and-dependencies.patch -Patch0003: 0003-configs-implement-actor-configuration-support.patch -Patch0004: 0004-pylint-ignore-too-many-params-lines-yield-from.patch -Patch0005: 0005-packaging-bump-leapp-framework-version.patch -Patch0006: 0006-spec-Introduce-etc-leapp-actor_conf.d-directory.patch %description Leapp utility provides the possibility to use the Leapp framework via CLI. @@ -166,12 +160,7 @@ Requires: findutils # APPLY REGISTERED PATCHES HERE -%patch -P 0001 -p1 -%patch -P 0002 -p1 -%patch -P 0003 -p1 -%patch -P 0004 -p1 -%patch -P 0005 -p1 -%patch -P 0006 -p1 +# %%patch -P 0001 -p1 ################################################## @@ -257,6 +246,13 @@ install -m 0644 -p man/leapp.1 %{buildroot}%{_mandir}/man1/ # no files here %changelog +* Fri Feb 14 2025 Petr Stodulka - 0.19.0-1 +- Rebase to new upstream version 0.19.0 +- Add possibility to use a specified execution context for snactor run in an existing leapp.db +- Increase limits on the number of opened file descriptors and maximum size + of manipulated files when running leapp +- Resolves: RHEL-67622, RHEL-79411 + * Mon Nov 18 2024 Petr Stodulka - 0.18.0-2 - Bump leapp-framework to 6.0 - Bump leapp-framework-dependencies to 6