Пример #1
0
def parse_template(
        template: WorkflowTemplate,
        arguments: Dict) -> Tuple[List[ContainerStep], Dict, List[str]]:
    """Parse a serial workflow template to extract workflow steps and output
    files.

    Expands template parameter references in the workflow argument specification
    and returns the modified argument list as part of the result.

    Parameters
    ----------
    template: flowserv.model.template.base.WorkflowTemplate
        Template for a serial workflow.

    Returns
    -------
    tuple of list of flowsert.controller.serial.workflow.step.ContainerStep, dict and list of string
    """
    # Get the commands from the workflow specification.
    workflow_spec = template.workflow_spec
    steps = list()
    for step in workflow_spec.get('workflow', {}).get('specification',
                                                      {}).get('steps', []):
        # Workflow steps may either be parameter references or dictionaries
        # with `image` and `commands` elements.
        script = None
        if tp.is_parameter(step):
            para = template.parameters[tp.get_name(step)]
            if para.name in arguments:
                script = para.cast(arguments[para.name])
        else:
            script = ContainerStep(image=step.get('environment'))
            for cmd in step.get('commands', []):
                script.add(cmd)
        if script:
            steps.append(script)
    # Get the workflow arguments that are defined in the workflow template.
    # Expand template parameter references using the given argument set.
    run_args = workflow_spec.get('inputs', {}).get('parameters', {})
    for key in run_args.keys():
        run_args[key] = tp.expand_value(value=str(run_args[key]),
                                        arguments=arguments,
                                        parameters=template.parameters)
    # Get the list of output files from the workflow specification. At this
    # point we do not support references to template arguments or parameters.
    output_files = workflow_spec.get('outputs', {}).get('files', {})
    # Return tuple of workflow steps and output file list.
    return steps, run_args, output_files
Пример #2
0
    def exec(self, step: ContainerStep, context: Dict,
             store: FileSystemStorage) -> ExecResult:
        """Execute a given list of commands that are represented by template
        strings.

        Substitutes parameter and template placeholder occurrences first. Then
        calls the implementation-specific run method to execute the individual
        commands.

        Note that the container worker expects a file system storage volume.

        Parameters
        ----------
        step: flowserv.controller.serial.workflow.ContainerStep
            Step in a serial workflow.
        context: dict
            Dictionary of argument values for parameters in the template.
        store: flowserv.volume.fs.FileSystemStorage
            Storage volume that contains the workflow run files.

        Returns
        -------
        flowserv.controller.serial.workflow.result.ExecResult
        """
        # Create a modified container step where all commands are expended so
        # that they do not contain references to variables and template parameters
        # any more.
        expanded_step = ContainerStep(identifier=step.identifier,
                                      image=step.image,
                                      env=step.env)
        for cmd in step.commands:
            # Generate mapping for template substitution. Include a mapping of
            # placeholder names to themselves.
            args = {p: p for p in tp.placeholders(cmd)}
            args.update(context)
            # Update arguments with fixed variables.
            args.update(self.variables)
            expanded_step.add(Template(cmd).substitute(args).strip())
        # Create mapping for environment variables.
        environment = dict(self.env)
        environment.update(step.env)
        environment = environment if environment else None
        return self.run(step=expanded_step,
                        env=environment,
                        rundir=store.basedir)