Esempio n. 1
0
File: report.py Progetto: srand/jolt
class ReportHooks(TaskHook):
    def __init__(self):
        self.manifest = JoltManifest()

    def finalize_report(self, report, task, result):
        report.name = task.qualified_name
        report.duration = str(task.duration_running.seconds)
        report.goal = str(task.is_goal()).lower()
        report.identity = task.identity
        report.result = result
        if hasattr(task, "logstash"):
            report.logstash = task.logstash
        self.manifest.append(report)

    @contextmanager
    def task_run(self, task):
        try:
            yield
        except Exception as e:
            with task.task.report() as report:
                if not report.errors:
                    report.add_exception(e)
                self.finalize_report(report.manifest, task, "FAILED")
            raise e
        else:
            with task.task.report() as report:
                self.finalize_report(report.manifest, task, "SUCCESS")

    def write(self, filename):
        self.manifest.write(filename)

    @contextmanager
    def update(self):
        yield self.manifest
Esempio n. 2
0
File: cli.py Progetto: srand/jolt
def _autocomplete_tasks(ctx, args, incomplete):
    manifest = JoltManifest()
    utils.call_and_catch(manifest.parse)
    manifest.process_import()

    tasks = JoltLoader.get().load()
    tasks = [
        task.name for task in tasks if task.name.startswith(incomplete or '')
    ]
    return sorted(tasks)
Esempio n. 3
0
 def get_parameters(self, task):
     registry = TaskRegistry()
     registry.add_task_class(Jolt)
     acache = ArtifactCache.get()
     env = JoltEnvironment(cache=acache)
     gb = GraphBuilder(registry, JoltManifest())
     dag = gb.build(["jolt"])
     task = dag.select(lambda graph, task: True)
     assert len(task) == 1, "too many selfdeploy tasks found"
     task = task[0]
     if not acache.is_available_remotely(task):
         factory = LocalExecutorFactory()
         executor = LocalExecutor(factory, task, force_upload=True)
         executor.run(env)
     jolt_url = acache.location(task)
     raise_error_if(not jolt_url, "failed to deploy jolt to a remote cache")
     return {
         "jolt_url": jolt_url,
         "jolt_identity": task.identity[:8],
         "jolt_requires": config.get("selfdeploy", "requires", "")
     }
Esempio n. 4
0
    def _create_manifest(self):
        manifest = JoltManifest.export(self.task)
        build = manifest.create_build()

        tasks = [self.task.qualified_name]
        tasks += [t.qualified_name for t in self.task.extensions]

        for task in tasks:
            mt = build.create_task()
            mt.name = task

        registry = scheduler.ExecutorRegistry.get()
        for key, value in registry.get_network_parameters(self.task).items():
            param = manifest.create_parameter()
            param.key = key
            param.value = value

        routing_key = WorkerTaskConsumer.ROUTING_KEY_PREFIX
        routing_key += getattr(self.task.task, "routing_key", WorkerTaskConsumer.ROUTING_KEY_REQUEST)

        return manifest.format(), routing_key
Esempio n. 5
0
File: amqp.py Progetto: srand/jolt
            def selfdeploy(self):
                """ Installs the correct version of Jolt as specified in execution request. """

                tools = Tools()
                manifest = JoltManifest()
                try:
                    manifest.parse()
                    ident = manifest.get_parameter("jolt_identity")
                    url = manifest.get_parameter("jolt_url")
                    if not ident or not url:
                        return "jolt"

                    requires = manifest.get_parameter("jolt_requires")

                    log.info("Jolt version: {}", ident)

                    src = "build/selfdeploy/{}/src".format(ident)
                    env = "build/selfdeploy/{}/env".format(ident)

                    if not fs.path.exists(env):
                        try:
                            fs.makedirs(src)
                            tools.run("curl {} | tar zx -C {}", url, src)
                            tools.run("virtualenv {}", env)
                            tools.run(". {}/bin/activate && pip install -e {}",
                                      env, src)
                            if requires:
                                tools.run(
                                    ". {}/bin/activate && pip install {}", env,
                                    requires)
                        except Exception as e:
                            tools.rmtree("build/selfdeploy/{}",
                                         ident,
                                         ignore_errors=True)
                            raise e

                    return ". {}/bin/activate && jolt".format(env)
                except Exception as e:
                    log.exception()
                    raise e
Esempio n. 6
0
File: cli.py Progetto: srand/jolt
def cli(ctx, verbose, extra_verbose, config_file, debugger, profile, force,
        salt, debug, network, local, keep_going, jobs):
    """
    A task execution tool.

    When invoked without any commands and arguments, Jolt by default tries
    to execute and build the artifact of a task called `default`. To build
    artifacts of other tasks use the build subcommand.

    The Jolt command line interface is hierarchical. One set of options
    can be passed to the top-level command and a different set of options
    to the subcommands, simultaneously. For example, verbose output is
    a top-level option while forced rebuild is a build command option.
    They may combined like this:

      $ jolt --verbose build --force taskname

    Most build command options are available also at the top-level when
    build is invoked implicitly for the default task.

    """

    global debug_enabled
    debug_enabled = debugger

    log.verbose("Jolt command: {}",
                " ".join([fs.path.basename(sys.argv[0])] + sys.argv[1:]))
    log.verbose("Jolt host: {}", environ.get("HOSTNAME", "localhost"))
    log.verbose("Jolt install path: {}", fs.path.dirname(__file__))

    if ctx.invoked_subcommand in ["config"]:
        # Don't attempt to load any task recipes as they might require
        # plugins that are not yet configured.
        return

    if ctx.invoked_subcommand is None:
        build = ctx.command.get_command(ctx, "build")

    manifest = JoltManifest()
    utils.call_and_catch(manifest.parse)
    manifest.process_import()
    ctx.obj["manifest"] = manifest

    if manifest.version:
        from jolt.version_utils import requirement, version
        req = requirement(manifest.version)
        ver = version(__version__)
        raise_error_if(not req.satisfied(ver),
                       "this project requires Jolt version {} (running {})",
                       req, __version__)

    loader = JoltLoader.get()
    tasks = loader.load()
    for cls in tasks:
        TaskRegistry.get().add_task_class(cls)

    if ctx.invoked_subcommand in ["build", "clean"] and loader.joltdir:
        ctx.obj["workspace_lock"] = utils.LockFile(
            fs.path.join(loader.joltdir, "build"), log.info,
            "Workspace is locked by another process, please wait...")
        atexit.register(ctx.obj["workspace_lock"].close)

    # If no command is given, we default to building the default task.
    # If the default task doesn't exist, help is printed inside build().
    if ctx.invoked_subcommand is None:
        task = config.get("jolt", "default", "default")
        taskname, _ = utils.parse_task_name(task)
        if TaskRegistry.get().get_task_class(taskname) is not None:
            ctx.invoke(build,
                       task=[task],
                       force=force,
                       salt=salt,
                       debug=debug,
                       network=network,
                       local=local,
                       keep_going=keep_going,
                       jobs=jobs)
        else:
            print(cli.get_help(ctx))
            sys.exit(1)
Esempio n. 7
0
File: amqp.py Progetto: srand/jolt
    def _run(self, env):
        timeout = int(config.getint("amqp", "timeout", 300))
        manifest, routing_key = self._create_manifest()

        self.connect()
        self.publish_request(manifest, routing_key)

        log.debug("[AMQP] Queued {0}", self.task.short_qualified_name)

        self.task.running()
        for extension in self.task.extensions:
            extension.running()

        while self.response is None:
            try:
                self.connection.process_data_events(time_limit=timeout)
                if self.response is None:
                    self.task.info(
                        "Remote execution still in progress after {}",
                        self.task.duration_queued)
            except (ConnectionError, AMQPConnectionError):
                log.warning("[AMQP] Lost server connection")
                self.connect()

        log.debug("[AMQP] Finished {0}", self.task.short_qualified_name)

        manifest = JoltManifest()
        with raise_task_error_on_exception(
                self.task, "failed to parse build result manifest"):
            manifest.parsestring(self.response)

        self.task.running(utils.duration() - float(manifest.duration))

        if manifest.result != "SUCCESS":
            output = []
            if manifest.stdout:
                output.extend(manifest.stdout.split("\n"))
            if manifest.stderr:
                output.extend(manifest.stderr.split("\n"))
            for line in output:
                log.transfer(line, self.task.identity[:8])
            for task in [self.task] + self.task.extensions:
                with task.task.report() as report:
                    remote_report = manifest.find_task(task.qualified_name)
                    if remote_report:
                        for error in remote_report.errors:
                            report.manifest.append(error)
            raise_error("[AMQP] remote build failed with status: {0}".format(
                manifest.result))

        raise_task_error_if(
            not env.cache.is_available_remotely(self.task), self.task,
            "no task artifact available in any cache, check configuration")

        raise_task_error_if(
            not env.cache.download(self.task) and env.cache.download_enabled(),
            self.task, "failed to download task artifact")

        for extension in self.task.extensions:
            raise_task_error_if(
                not env.cache.download(extension)
                and env.cache.download_enabled(), self.task,
                "failed to download task artifact")

        return self.task
Esempio n. 8
0
File: amqp.py Progetto: srand/jolt
            def run(self):
                with open("default.joltxmanifest", "wb") as f:
                    f.write(self.body)

                log.info("Manifest written")

                tools = Tools()
                for recipe in tools.glob("*.jolt"):
                    tools.unlink(recipe)

                try:
                    jolt = self.selfdeploy()
                    config_file = config.get("amqp", "config", "")
                    if config_file:
                        config_file = "-c " + config_file

                    log.info("Running jolt")
                    tools.run(
                        "{} -vv {} build --worker --result result.joltxmanifest",
                        jolt,
                        config_file,
                        output_stdio=True)
                except JoltCommandError as e:
                    self.response = ""
                    try:
                        manifest = JoltManifest()
                        try:
                            manifest.parse("result.joltxmanifest")
                        except Exception:
                            manifest.duration = "0"
                        manifest.result = "FAILED"
                        manifest.stdout = "\n".join(e.stdout)
                        manifest.stderr = "\n".join(e.stderr)
                        self.response = manifest.format()
                    except Exception:
                        log.exception()
                    log.error("Task failed")
                except Exception:
                    log.exception()
                    self.response = ""
                    try:
                        manifest = JoltManifest()
                        try:
                            manifest.parse("result.joltxmanifest")
                        except Exception:
                            manifest.duration = "0"
                        manifest.result = "FAILED"
                        self.response = manifest.format()
                    except Exception:
                        log.exception()
                    log.error("Task failed")
                else:
                    self.response = ""
                    try:
                        manifest = JoltManifest()
                        try:
                            manifest.parse("result.joltxmanifest")
                        except Exception:
                            manifest.duration = "0"
                        manifest.result = "SUCCESS"
                        self.response = manifest.format()
                    except Exception:
                        log.exception()
                    log.info("Task succeeded")

                utils.call_and_catch(tools.unlink, "result.joltxmanifest")
                self.consumer.add_on_job_completed_callback(self)
Esempio n. 9
0
File: report.py Progetto: srand/jolt
 def __init__(self):
     self.manifest = JoltManifest()