Example #1
0
    def test_invalid_spec(self):
        """Ensure that loading an invalid spec result in a SandboxError."""
        spec_repo = AnodSpecRepository(self.spec_dir)
        with pytest.raises(SandBoxError) as err:
            spec_repo.load('invalid_spec')

        assert 'invalid spec code' in str(err.value)
Example #2
0
    def test_spec_loader1(self):
        spec_dir = os.path.join(
            os.path.dirname(__file__),
            'data')

        spec_repo = AnodSpecRepository(spec_dir)
        s = spec_repo.load('loader1')
        assert s.name == 'loader1'
Example #3
0
 def test_load_config_api_1_5(self):
     sync_tree(self.spec_dir, "new_spec_dir")
     Run(["e3-sandbox", "migrate", "1.5", "new_spec_dir"], output=None)
     spec_repo = AnodSpecRepository("new_spec_dir")
     spec_repo.api_version = "1.5"
     anod_class = spec_repo.load("withconfig")
     anod_instance = anod_class("", "build")
     assert anod_instance.test1() == 9
     assert anod_instance.test_suffix() == 42
Example #4
0
    def test_spec_loader_prolog(self):
        spec_repo = AnodSpecRepository(self.spec_dir, spec_config=True)
        anod_class = spec_repo.load('prolog_test')

        # We should be able to load a spec twice
        anod_class = spec_repo.load('prolog_test')

        anod_instance = anod_class('prolog_test', '', 'build')
        assert anod_instance.prolog_test, 'prolog not executed properly'
Example #5
0
    def test_spec_loader_prolog(self):
        spec_repo = AnodSpecRepository(self.spec_dir)
        anod_class = spec_repo.load("prolog_test")

        # We should be able to load a spec twice
        anod_class = spec_repo.load("prolog_test")

        anod_instance = anod_class("prolog_test", "", "build")
        assert anod_instance.prolog_test, "prolog not executed properly"
Example #6
0
 def test_load_config_api_1_5(self):
     sync_tree(self.spec_dir, 'new_spec_dir')
     Run(['e3-sandbox', 'migrate', '1.5', 'new_spec_dir'], output=None)
     spec_repo = AnodSpecRepository('new_spec_dir')
     spec_repo.api_version = '1.5'
     anod_class = spec_repo.load('withconfig')
     anod_instance = anod_class('', 'build')
     assert anod_instance.test1() == 9
     assert anod_instance.test_suffix() == 42
Example #7
0
 def create_context(self):
     # Create a context for a x86-linux machine
     asr = AnodSpecRepository(self.spec_dir)
     asr.repos['spec1-git'] = 'spec1-git'
     asr.repos['spec8-git'] = 'spec8-git'
     asr.repos['spec2-git'] = 'spec2-git'
     env = BaseEnv()
     env.set_build('x86-linux', 'rhes6', 'mylinux')
     ac = AnodContext(asr, default_env=env)
     return ac
Example #8
0
    def test_spec_loader2(self):
        spec_dir = os.path.join(
            os.path.dirname(__file__),
            'data')

        spec_repo = AnodSpecRepository(spec_dir)

        with pytest.raises(SandBoxError) as err:
            spec_repo.load('loader2')
        assert str(err.value).startswith(
            'load: cannot find Anod subclass in')
Example #9
0
    def test_load_config(self):
        spec_repo = AnodSpecRepository(self.spec_dir)
        anod_class = spec_repo.load('withconfig')
        anod_instance = anod_class('', 'build')

        # See comments in tests/tests_e3/anod/data/withconfig.anod

        assert anod_instance.test1() == 9
        with pytest.raises(KeyError) as err:
            anod_instance.test2()
        assert 'foo' in str(err.value)

        assert list(anod_instance.test3()) == ['case_foo']
Example #10
0
    def test_load_config(self):
        spec_repo = AnodSpecRepository(self.spec_dir)
        spec_repo.api_version = "1.4"
        anod_class = spec_repo.load("withconfig")
        anod_instance = anod_class("", "build")

        # See comments in tests/tests_e3/anod/data/withconfig.anod

        assert anod_instance.test1() == 9
        with pytest.raises(KeyError) as err:
            anod_instance.test2()
        assert "foo" in str(err.value)

        assert list(anod_instance.test3()) == ["case_foo"]
Example #11
0
    def test_force_download_after_install(self):
        """Test two deps on the same spec with installation and download.

        Here we have two specs having an "installation" and a "download"
        depdendency on the same spec (spec_build). When the two are set
        together the scheduler find the proper solution: download.
        """
        env = BaseEnv()
        env.set_build("x86_64-linux", "rhes8", "mylinux")
        asr = AnodSpecRepository(self.spec_dir)
        ac = AnodContext(asr, default_env=env)
        ac.add_anod_action("spec_install_dep",
                           env=ac.default_env,
                           primitive="build")
        with pytest.raises(SchedulingError) as err:
            ac.schedule(ac.always_create_source_resolver)
        assert "This plan resolver cannot decide" in str(err)

        ac.add_anod_action("spec_download_dep",
                           env=ac.default_env,
                           primitive="build")
        result = ac.schedule(ac.always_create_source_resolver)

        assert set(result.vertex_data.keys()) == {
            "root",
            "mylinux.x86_64-linux.spec_install_dep.build",
            "mylinux.x86_64-linux.spec_download_dep.build",
            "mylinux.x86_64-linux.spec_build.install",
            "mylinux.x86_64-linux.spec_build.download_bin",
        }
Example #12
0
    def test_force_download_before_install(self):
        """Test two deps on the same spec with installation and download.

        Same as test_force_download_after_install but in a different
        order. The end result should be the same.
        """
        env = BaseEnv()
        env.set_build("x86_64-linux", "rhes8", "mylinux")
        asr = AnodSpecRepository(self.spec_dir)
        ac = AnodContext(asr, default_env=env)
        ac.add_anod_action("spec_download_dep",
                           env=ac.default_env,
                           primitive="build")
        result = ac.schedule(ac.always_create_source_resolver)

        assert set(result.vertex_data.keys()) == {
            "root",
            "mylinux.x86_64-linux.spec_download_dep.build",
            "mylinux.x86_64-linux.spec_build.install",
            "mylinux.x86_64-linux.spec_build.download_bin",
        }
        ac.add_anod_action("spec_install_dep",
                           env=ac.default_env,
                           primitive="build")
        ac.schedule(ac.always_create_source_resolver)
        result = ac.schedule(ac.always_create_source_resolver)

        assert set(result.vertex_data.keys()) == {
            "root",
            "mylinux.x86_64-linux.spec_install_dep.build",
            "mylinux.x86_64-linux.spec_download_dep.build",
            "mylinux.x86_64-linux.spec_build.install",
            "mylinux.x86_64-linux.spec_build.download_bin",
        }
Example #13
0
    def test_force_download_after_build(self):
        """Test two deps on the same spec with build and download.

        Here we have two specs having an "build_tree" and a "download"
        depdendency on the same spec (spec_build). When the two are set
        together the scheduler cannot find a solution.
        """
        env = BaseEnv()
        env.set_build("x86_64-linux", "rhes8", "mylinux")
        asr = AnodSpecRepository(self.spec_dir)
        ac = AnodContext(asr, default_env=env)
        ac.add_anod_action("spec_build_dep",
                           env=ac.default_env,
                           primitive="build")

        # Verify that, when scheduling this plan, the scheduler ask for
        # having an explicit build
        with pytest.raises(SchedulingError) as err:
            ac.schedule(ac.always_create_source_resolver)
        assert "A spec in the plan has a build_tree dependency on spec_build" in str(
            err)

        # Verify that after adding a download dep, the scheduler now
        # warns that he cannot resolve the plan
        ac.add_anod_action("spec_download_dep",
                           env=ac.default_env,
                           primitive="build")
        with pytest.raises(SchedulingError) as err:
            ac.schedule(ac.always_create_source_resolver)
        assert "explicit DownloadBinary decision made" in str(err)
Example #14
0
    def test_load_all(self):
        spec_repo = AnodSpecRepository(self.spec_dir)
        with pytest.raises(SandBoxError):
            spec_repo.load_all()

        spec_repo = AnodSpecRepository(self.spec2_dir)
        spec_repo.load_all()
        assert 'parent' in spec_repo
        assert 'child' in spec_repo
        assert 'unknown' not in spec_repo
Example #15
0
    def create_context(self, reject_duplicates=True):
        """Create a spec repository and anod context.

        :param reject_duplicates: whether to reject duplicates in plan
        :type reject_duplicates: bool

        :rtype: AnodContext
        """
        # Create a context for a x86-linux machine
        asr = AnodSpecRepository(self.spec_dir)
        asr.repos['spec1-git'] = 'spec1-git'
        asr.repos['spec8-git'] = 'spec8-git'
        asr.repos['spec2-git'] = 'spec2-git'
        env = BaseEnv()
        env.set_build('x86-linux', 'rhes6', 'mylinux')
        ac = AnodContext(asr,
                         default_env=env,
                         reject_duplicates=reject_duplicates)
        return ac
Example #16
0
 def test_context_init(self):
     # Create a context using:
     # 1. the local default configuration
     # 2. forcing a x86-linux configuration
     asr = AnodSpecRepository(self.spec_dir)
     ac = AnodContext(asr)
     assert ac.default_env.build == BaseEnv().build
     assert ac.default_env.host == BaseEnv().host
     assert ac.default_env.target == BaseEnv().target
     self.create_context()
Example #17
0
 def get_source_closure(self,
                        name,
                        expand_packages=True,
                        other_builds=None):
     asr = AnodSpecRepository(self.spec_dir)
     ac = AnodContext(asr)
     anod_instance = ac.add_anod_action(name, primitive="build").data
     anod_instance = get_build_node(anod_instance, ac, anod_instance)
     if other_builds is not None:
         for b in other_builds:
             ac.add_anod_action(b, primitive="build")
     return SourceClosure(anod_instance=anod_instance,
                          context=ac,
                          expand_packages=expand_packages)
Example #18
0
    def activate(self, sandbox: SandBox, spec_repository: AnodSpecRepository) -> None:
        self.anod_instance.bind_to_sandbox(sandbox)

        self.anod_instance.log = e3.log.getLogger("spec." + self.anod_instance.uid)

        for e in getattr(self.anod_instance, "%s_deps" % self.anod_instance.kind, ()):
            if isinstance(e, self.anod_instance.Dependency):
                dep_class = spec_repository.load(e.name)
                dep_instance = dep_class(
                    qualifier=e.qualifier,
                    kind=e.kind,
                    env=e.env(self.anod_instance, BaseEnv.from_env()),
                )
                self.anod_instance.deps[e.local_name] = dep_instance
        e3.log.debug("activating spec %s", self.anod_instance.uid)
Example #19
0
 def test_multiple_spec_repository(self):
     """Ensure that spec function is context dependent."""
     spec_repo = AnodSpecRepository(self.spec_dir)
     spec2_repo = AnodSpecRepository(self.spec2_dir)
     anod_class = spec_repo.load('child')
     anod_instance = anod_class('load', '', 'build')
     assert anod_instance.parent_info == 'from_parent'
     anod_class2 = spec2_repo.load('child')
     anod_instance2 = anod_class2('load', '', 'build')
     assert anod_instance2.parent_info == 'from_parent2'
Example #20
0
 def test_multiple_spec_repository(self):
     """Ensure that spec function is context dependent."""
     spec_repo = AnodSpecRepository(self.spec_dir)
     spec2_repo = AnodSpecRepository(self.spec2_dir)
     anod_class = spec_repo.load("child")
     anod_instance = anod_class("load", "", "build")
     assert anod_instance.parent_info == "from_parent"
     anod_class2 = spec2_repo.load("child")
     anod_instance2 = anod_class2("load", "", "build")
     assert anod_instance2.parent_info == "from_parent2"
Example #21
0
    def test_force_download_before_build(self):
        """Test two deps on the same spec with build and download.

        Same as test_force_download_after_build but in a different order.
        The expected result is the same: an error should be raised.
        """
        env = BaseEnv()
        env.set_build("x86_64-linux", "rhes8", "mylinux")
        asr = AnodSpecRepository(self.spec_dir)
        ac = AnodContext(asr, default_env=env)
        ac.add_anod_action("spec_download_dep",
                           env=ac.default_env,
                           primitive="build")
        ac.add_anod_action("spec_build_dep",
                           env=ac.default_env,
                           primitive="build")
        with pytest.raises(SchedulingError) as err:
            ac.schedule(ac.always_create_source_resolver)
        assert "explicit DownloadBinary decision made" in str(err)
Example #22
0
    def test_force_download_without_require_condition(self):
        """Test that the force download can be done thanks to require=xxx.

        A require condition can be added to the build primitive to disable the
        build primitive for some qualifiers.
        """
        env = BaseEnv()
        env.set_build("x86_64-linux", "rhes8", "mylinux")
        asr = AnodSpecRepository(self.spec_dir)

        # We start with a dependency on spec_nobuild where build primitive
        # require condition is True
        ac = AnodContext(asr, default_env=env)
        ac.add_anod_action(
            "spec_nobuild_dep",
            env=ac.default_env,
            primitive="build",
        )

        # If both build and install are allowed the resolver will
        # complain and ask for an explicit choice
        with pytest.raises(SchedulingError) as err:
            ac.schedule(ac.always_create_source_resolver)
        assert "what to do for resolving" in str(err)

        # Now with a dependency making require return False, and so
        # disable the build primitive, the resolver will not have any
        # conflict: the only allowed action will be download.
        ac2 = AnodContext(asr, default_env=env)
        ac2.add_anod_action(
            "spec_nobuild_stable_dep",
            env=ac.default_env,
            primitive="build",
        )
        result = ac2.schedule(ac.always_create_source_resolver)

        assert set(result.vertex_data.keys()) == {
            "root",
            "mylinux.x86_64-linux.spec_nobuild.download_bin",
            "mylinux.x86_64-linux.spec_nobuild_stable_dep.build",
            "mylinux.x86_64-linux.spec_nobuild.install",
        }
Example #23
0
    def test_force_download_without_download_primitive(self):
        """Test that the force download do not require the download primitive.

        Having a download() primitive or not should not impact this feature.
        """
        env = BaseEnv()
        env.set_build("x86_64-linux", "rhes8", "mylinux")
        asr = AnodSpecRepository(self.spec_dir)
        ac = AnodContext(asr, default_env=env)
        ac.add_anod_action(
            "spec_download_dep_for_nodownloadprimitive",
            env=ac.default_env,
            primitive="build",
        )
        result = ac.schedule(ac.always_create_source_resolver)

        assert set(result.vertex_data.keys()) == {
            "root",
            "mylinux.x86_64-linux.spec_download_dep_for_nodownloadprimitive.build",
            "mylinux.x86_64-linux.spec_nodownloadprimitive.install",
            "mylinux.x86_64-linux.spec_nodownloadprimitive.download_bin",
        }
Example #24
0
    def create_context(self, reject_duplicates: bool = True) -> AnodContext:
        """Create a spec repository and anod context.

        :param reject_duplicates: whether to reject duplicates in plan
        """

        def repo_conf(name: str) -> dict[str, str]:
            return {"vcs": "git", "url": name, "branch": "master"}

        # Create a context for a x86-linux machine
        asr = AnodSpecRepository(self.spec_dir)
        asr.repos["spec1-git"] = repo_conf("spec1")
        asr.repos["spec8-git"] = repo_conf("spec8")
        asr.repos["spec2-git"] = repo_conf("spec2")
        asr.repos["a-git"] = repo_conf("a")
        env = BaseEnv()
        env.set_build("x86-linux", "rhes6", "mylinux")
        ac = AnodContext(asr, default_env=env, reject_duplicates=reject_duplicates)
        return ac
Example #25
0
    def test_spec_loader_prolog_with_repos(self):
        sync_tree(self.spec_dir, "specs_dir")
        repositories_yaml = os.path.join("specs_dir", "config",
                                         "repositories.yaml")
        cp(repositories_yaml + ".tmpl", repositories_yaml)

        spec_repo = AnodSpecRepository("specs_dir")
        anod_class = spec_repo.load("prolog_test")
        assert anod_class.e3_version == "20.1"
        assert anod_class.has_foo is False
        assert anod_class.e3_extra_version is None

        override_conf = {
            "e3-core": {
                "revision": 21.0
            },
            "e3-extra": {
                "vcs": "git",
                "url": "unknown",
                "revision": "master"
            },
        }

        spec_config = SpecConfig()
        spec_config.foo = 2

        spec_repo2 = AnodSpecRepository(
            "specs_dir",
            spec_config=spec_config,
            extra_repositories_config=override_conf,
        )
        anod_class2 = spec_repo2.load("prolog_test")
        assert anod_class2.e3_version == "21.0"
        assert anod_class2.e3_extra_version == "master"

        assert anod_class2.has_foo is True
Example #26
0
 def test_spec_inheritance(self):
     """Load a spec that inherit from another spec."""
     spec_repo = AnodSpecRepository(self.spec_dir)
     anod_class = spec_repo.load("child")
     anod_instance = anod_class("load", "", "build")
     assert anod_instance.parent_info == "from_parent"
Example #27
0
    def test_spec_does_not_exist(self):
        with pytest.raises(SandBoxError) as err:
            AnodSpecRepository('/foo/bar')

        assert str(
            err.value).startswith('spec directory /foo/bar does not exist')
Example #28
0
    def run(self, args):
        sandbox = SandBox()
        sandbox.root_dir = args.sandbox

        if args.specs_dir:
            sandbox.specs_dir = args.specs_dir

        if args.create_sandbox:
            sandbox.create_dirs()

        if args.create_sandbox and args.spec_git_url:
            mkdir(sandbox.specs_dir)
            g = GitRepository(sandbox.specs_dir)
            if e3.log.default_output_stream is not None:
                g.log_stream = e3.log.default_output_stream
            g.init()
            g.update(args.spec_git_url, args.spec_git_branch, force=True)

        sandbox.dump_configuration()
        sandbox.write_scripts()

        asr = AnodSpecRepository(sandbox.specs_dir)
        check_api_version(asr.api_version)

        # Load plan content if needed
        if args.plan:
            if not os.path.isfile(args.plan):
                raise SandBoxError("plan file %s does not exist" % args.plan,
                                   origin="SandBoxExec.run")
            with open(args.plan, "r") as plan_fd:
                plan_content = ["def main_entry_point():"]
                plan_content += [
                    "    %s" % line for line in plan_fd.read().splitlines()
                ]
                plan_content = "\n".join(plan_content)

            env = BaseEnv()
            cm = PlanContext(server=env)
            store = None
            resolver = getattr(
                AnodContext,
                str(args.resolver),
                AnodContext.always_create_source_resolver,
            )
            logger.debug("Using resolver %s", resolver.__name__)

            # Declare available actions and their signature
            def anod_action(module,
                            build=None,
                            host=None,
                            target=None,
                            qualifier=None):
                pass  # all: no cover

            for a in ("anod_install", "anod_build", "anod_test"):
                cm.register_action(a, anod_action)

            # Load the plan and execute
            plan = Plan(data={})
            plan.load_chunk(plan_content)
            actions = cm.execute(plan, "main_entry_point")

            ac = AnodContext(asr, default_env=env)
            for action in actions:
                ac.add_anod_action(
                    action.module,
                    action,
                    action.action.replace("anod_", "", 1),
                    action.qualifier,
                )

            # Check if machine plan is locally schedulable
            action_list = ac.schedule(resolver)
            e = ElectrolytJobFactory(sandbox, asr, store, dry_run=args.dry_run)
            e.run(action_list)
Example #29
0
 def test_spec_inheritance(self):
     """Load a spec that inherit from another spec."""
     spec_repo = AnodSpecRepository(self.spec_dir)
     anod_class = spec_repo.load('child')
     anod_instance = anod_class('load', '', 'build')
     assert anod_instance.parent_info == 'from_parent'
Example #30
0
 def test_getitem_without_buildspace(self):
     """Without a build space PKG_DIR returns 'unknown'."""
     spec_repo = AnodSpecRepository(self.spec_dir)
     anod_class = spec_repo.load('parent')
     anod_instance = anod_class('', 'build')
     assert anod_instance['PKG_DIR'] == 'unknown'
Example #31
0
 def test_spec_loader1(self):
     spec_repo = AnodSpecRepository(self.spec_dir)
     s = spec_repo.load('loader1')
     assert s.name == 'loader1'
Example #32
0
    def test_spec_loader2(self):
        spec_repo = AnodSpecRepository(self.spec_dir)

        with pytest.raises(SandBoxError) as err:
            spec_repo.load('loader2')
        assert str(err.value).startswith('load: cannot find Anod subclass in')