forked from oamg/leapp-repository
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add the ScanFilesForTargetUserspace actor.
This actor allows us to specify what files should be copied to the target userspace container upon its creation. Produces a `TargetUserSpacePreupgradeTasks` containing the files to be copied. The functionality provided by this actor is already employed to copy the `/etc/hosts/` file into the target userspace, as the original implementation relying on the usage of bind mounting would crash if the file did not exist. The copy of this file is performed conditionally, that means it is copyied only when the file exists. The original functionality that enables us to always bind mount a certain file has been kept and it is still available for use.
- Loading branch information
Showing
4 changed files
with
137 additions
and
1 deletion.
There are no files selected for viewing
18 changes: 18 additions & 0 deletions
18
repos/system_upgrade/common/actors/scanfilesfortargetuserspace/actor.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
from leapp.actors import Actor | ||
from leapp.libraries.actor.scanfilesfortargetuserspace import scan_files_to_copy | ||
from leapp.models import TargetUserSpacePreupgradeTasks | ||
from leapp.tags import FactsPhaseTag, IPUWorkflowTag | ||
|
||
|
||
class ScanFilesForTargetUserspace(Actor): | ||
""" | ||
Scan the source system and identify files that will be copied into the target userspace when it is created. | ||
""" | ||
|
||
name = 'scan_files_for_target_userspace' | ||
consumes = () | ||
produces = (TargetUserSpacePreupgradeTasks,) | ||
tags = (FactsPhaseTag, IPUWorkflowTag) | ||
|
||
def process(self): | ||
scan_files_to_copy() |
26 changes: 26 additions & 0 deletions
26
...pgrade/common/actors/scanfilesfortargetuserspace/libraries/scanfilesfortargetuserspace.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import os | ||
|
||
from leapp.libraries.stdlib import api | ||
from leapp.models import CopyFile, TargetUserSpacePreupgradeTasks | ||
|
||
# Maps src location in the source system to the destination within the target system | ||
FILES_TO_COPY_IF_PRESENT = { | ||
'/etc/hosts': '/etc/hosts' | ||
} | ||
|
||
|
||
def scan_files_to_copy(): | ||
""" | ||
Scans the source system and identifies files that should be copied into target userspace. | ||
When an item to be copied is identified a message :class:`CopyFile` is produced. | ||
""" | ||
files_to_copy = [] | ||
for src_path in FILES_TO_COPY_IF_PRESENT: | ||
if os.path.isfile(src_path): | ||
dst_path = FILES_TO_COPY_IF_PRESENT[src_path] | ||
files_to_copy.append(CopyFile(src=src_path, dst=dst_path)) | ||
|
||
preupgrade_task = TargetUserSpacePreupgradeTasks(copy_files=files_to_copy) | ||
|
||
api.produce(preupgrade_task) |
89 changes: 89 additions & 0 deletions
89
...grade/common/actors/scanfilesfortargetuserspace/tests/test_scanfilesfortargetuserspace.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import os | ||
|
||
import pytest | ||
|
||
from leapp.libraries.actor.scanfilesfortargetuserspace import scan_files_to_copy | ||
from leapp.libraries.common.testutils import produce_mocked | ||
from leapp.libraries.stdlib import api | ||
|
||
|
||
@pytest.fixture | ||
def isfile_default_config(): | ||
config = { | ||
'/etc/hosts': True | ||
} | ||
return config | ||
|
||
|
||
def do_files_to_copy_contain_entry_with_src(files_to_copy, src): | ||
"""Searches the files to be copied for an entry with src field that matches the given src.""" | ||
is_present = False | ||
for file_to_copy in files_to_copy: | ||
if file_to_copy.src == src: | ||
is_present = True | ||
break | ||
return is_present | ||
|
||
|
||
def make_mocked_isfile(configuration): | ||
""" | ||
Creates mocked isfile function that returns values according the given configuration. | ||
The created function raises :class:`ValueError` should the unit under test try to "isfile" | ||
a path that is not present in the configuration. | ||
One global mocked function with configuration is error prone as individual test would | ||
have to return the configuration into the original state after execution. | ||
""" | ||
|
||
def mocked_isfile(path): | ||
if path in configuration: | ||
return configuration[path] | ||
error_msg = 'The actor tried to isfile a path that it should not. (path `{0}`)' | ||
raise ValueError(error_msg.format(path)) | ||
return mocked_isfile | ||
|
||
|
||
def test_etc_hosts_present(monkeypatch, isfile_default_config): | ||
"""Tests whether /etc/hosts is identified as "to be copied" into target userspace when it is present.""" | ||
mocked_isfile = make_mocked_isfile(isfile_default_config) | ||
actor_produces = produce_mocked() | ||
monkeypatch.setattr(os.path, 'isfile', mocked_isfile) | ||
monkeypatch.setattr(api, 'produce', actor_produces) | ||
|
||
scan_files_to_copy() | ||
|
||
fail_msg = 'Produced unexpected number of messages.' | ||
assert len(actor_produces.model_instances) == 1, fail_msg | ||
|
||
preupgrade_task_msg = actor_produces.model_instances[0] | ||
|
||
fail_msg = 'Didn\'t indentify any files to copy into target userspace (at least /etc/hosts shoud be).' | ||
assert preupgrade_task_msg.copy_files, fail_msg | ||
|
||
should_copy_hostsfile = do_files_to_copy_contain_entry_with_src(preupgrade_task_msg.copy_files, '/etc/hosts') | ||
assert should_copy_hostsfile, 'Failed to identify /etc/hosts as a file to be copied into target userspace.' | ||
|
||
fail_msg = 'Produced message contains rpms to be installed, however only copy files field should be populated.' | ||
assert not preupgrade_task_msg.install_rpms, fail_msg | ||
|
||
|
||
def test_etc_hosts_missing(monkeypatch, isfile_default_config): | ||
"""Tests whether /etc/hosts is not identified as "to be copied" into target userspace when it is missing.""" | ||
isfile_default_config['/etc/hosts'] = False # The file is not present or is a directory (-> shoud not be copied) | ||
mocked_isfile = make_mocked_isfile(isfile_default_config) | ||
actor_produces = produce_mocked() | ||
|
||
monkeypatch.setattr(os.path, 'isfile', mocked_isfile) | ||
monkeypatch.setattr(api, 'produce', actor_produces) | ||
|
||
scan_files_to_copy() | ||
|
||
assert len(actor_produces.model_instances) == 1, 'Produced unexpected number of messages.' | ||
|
||
preupgrade_task_msg = actor_produces.model_instances[0] | ||
should_copy_hostsfile = do_files_to_copy_contain_entry_with_src(preupgrade_task_msg.copy_files, '/etc/hosts') | ||
assert not should_copy_hostsfile, 'Identified /etc/hosts as a file to be copied even if it doesn\'t exists' | ||
|
||
fail_msg = 'Produced message contains rpms to be installed, however only copy files field should be populated.' | ||
assert not preupgrade_task_msg.install_rpms, fail_msg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters