def test_serialize_deserialize(self):
     self.assertEqual(
         {v
          for k, v in si.ID_TO_ITEM.items() if k != '/'} | {
              # These come the inline features added above.
              MakeDirsItem(
                  from_target='t1', into_dir='/a', path_to_make='b'),
              MakeDirsItem(
                  from_target='t2', into_dir='/c', path_to_make='d'),
          },
         self._items_for_features(),
     )
     # Fail if some target fails to resolve to a path
     with self.assertRaisesRegex(RuntimeError, f'{si.T_BASE}:[^ ]* not in'):
         self._items_for_features(target_to_path={})
示例#2
0
    def test_foreign_layer_assert(self):
        foreign1 = ForeignLayerItem(
            from_target='t1',
            cmd=['x'],
            user='******',
            serve_rpm_snapshots=(),
        )
        foreign2 = ForeignLayerItem(
            from_target='t2',
            cmd=['a'],
            user='******',
            serve_rpm_snapshots=(),
        )

        # Good path: one FOREIGN_LAYER & default MAKE_SUBVOL
        DependencyGraph([foreign1], 'layer_t')

        # Too many foreign layers
        with self.assertRaises(AssertionError):
            DependencyGraph([foreign1, foreign2], 'layer_t')

        # Cannot mix foreign layer & depedency-sortable item
        with self.assertRaises(AssertionError):
            DependencyGraph([
                foreign1,
                MakeDirsItem(from_target='', into_dir='a', path_to_make='b'),
            ], 'layer_t')

        # Cannot have other phase items
        with self.assertRaises(AssertionError):
            DependencyGraph([
                foreign1,
                RemovePathItem(from_target='', path='x', action='if_exists'),
            ], 'layer_t')
示例#3
0
 def test_duplicate_paths_provided(self):
     with self.assertRaisesRegex(
             RuntimeError,
             '^Both .* and .* from .* provide the same path$'):
         ValidatedReqsProvs([
             InstallFileItem(from_target='', source='x', dest='y/x'),
             MakeDirsItem(from_target='', into_dir='/', path_to_make='y/x'),
         ])
示例#4
0
    def test_cycle_detection(self):
        def requires_provides_directory_class(requires_dir, provides_dir):
            @dataclass(init=False, frozen=True)
            class RequiresProvidesDirectory(ImageItem):
                def requires(self):
                    yield require_directory(requires_dir)

                def provides(self):
                    yield ProvidesDirectory(path=provides_dir)

            return RequiresProvidesDirectory

        # `dg_ok`: dependency-sorting will work without a cycle
        first = FilesystemRootItem(from_target='')
        second = requires_provides_directory_class('/', 'a')(from_target='')
        third = MakeDirsItem(from_target='', into_dir='a', path_to_make='b/c')
        dg_ok = DependencyGraph([second, first, third], layer_target='t')
        self.assertEqual(_fs_root_phases(first), list(dg_ok.ordered_phases()))

        # `dg_bad`: changes `second` to get a cycle
        dg_bad = DependencyGraph([
            requires_provides_directory_class('a/b', 'a')(from_target=''),
            first,
            third,
        ],
                                 layer_target='t')
        self.assertEqual(_fs_root_phases(first), list(dg_bad.ordered_phases()))

        with TempSubvolumes(sys.argv[0]) as temp_subvolumes:
            subvol = temp_subvolumes.create('subvol')
            provides_root = PhasesProvideItem(from_target='t', subvol=subvol)
            self.assertEqual(
                [second, third],
                list(dg_ok.gen_dependency_order_items(provides_root)),
            )
            with self.assertRaisesRegex(AssertionError, '^Cycle in '):
                list(dg_bad.gen_dependency_order_items(provides_root))
示例#5
0
    def test_phase_order(self):
        class FakeRemovePaths:
            get_phase_builder = 'kittycat'

            def phase_order(self):
                return PhaseOrder.REMOVE_PATHS

        first = FilesystemRootItem(from_target='')
        second = FakeRemovePaths()
        third = MakeDirsItem(from_target='', into_dir='/', path_to_make='a/b')
        dg = DependencyGraph([second, first, third], layer_target='t')
        self.assertEqual(
            _fs_root_phases(first) + [
                (FakeRemovePaths.get_phase_builder, (second, )),
            ],
            list(dg.ordered_phases()),
        )
        with TempSubvolumes(sys.argv[0]) as temp_subvolumes:
            subvol = temp_subvolumes.create('subvol')
            self.assertEqual([third],
                             list(
                                 dg.gen_dependency_order_items(
                                     PhasesProvideItem(from_target='t',
                                                       subvol=subvol), )))
示例#6
0
def mangle(feature_target):
    return feature_target + (
        '_IF_YOU_REFER_TO_THIS_RULE_YOUR_DEPENDENCIES_WILL_BE_BROKEN_'
        'SO_DO_NOT_DO_THIS_EVER_PLEASE_KTHXBAI')


# This should be a faithful transcription of the `image_feature`
# specifications in `test/TARGETS`.  The IDs currently have no semantics,
# existing only to give names to specific items.
ID_TO_ITEM = {
    '/':
    FilesystemRootItem(from_target=None),

    # From `feature_dirs`:
    'foo/bar':
    MakeDirsItem(from_target=T_DIRS, into_dir='/', path_to_make='/foo/bar'),
    'foo/bar/baz':
    MakeDirsItem(from_target=T_DIRS, into_dir='/foo/bar', path_to_make='baz'),

    # From `feature_bad_dir`:
    'foo/borf/beep':
    MakeDirsItem(
        from_target=T_BAD_DIR,
        into_dir='/foo',
        path_to_make='borf/beep',
        user_group='uuu:ggg',
        mode='mmm',
    ),

    # From `feature_symlinks`:
    'foo/fighter':
示例#7
0
from fs_image.compiler.items.make_dirs import MakeDirsItem
from fs_image.compiler.items.make_subvol import FilesystemRootItem
from fs_image.compiler.items.phases_provide import PhasesProvideItem

from ..dep_graph import (
    DependencyGraph,
    ItemProv,
    ItemReq,
    ItemReqsProvs,
    ValidatedReqsProvs,
)
from ..provides import ProvidesDirectory, ProvidesDoNotAccess, ProvidesFile
from ..requires import require_directory

PATH_TO_ITEM = {
    '/a/b/c': MakeDirsItem(from_target='', into_dir='/', path_to_make='a/b/c'),
    '/a/d/e': MakeDirsItem(from_target='', into_dir='a', path_to_make='d/e'),
    '/a/b/c/F': InstallFileItem(
        from_target='',
        source='x',
        dest='a/b/c/F',
    ),
    '/a/d/e/G': InstallFileItem(
        from_target='',
        source='G',
        dest='a/d/e/G',
    ),
}


def _fs_root_phases(item):