Esempio n. 1
0
def exec_while(condition, inner_while):
    """
    Generate the Argo recursive logic. For example
    https://github.com/argoproj/argo/blob/master/examples/README.md#recursion.
    """
    # _while_lock means 'exec_while' operation begins to work
    # _while_steps stores logic steps inside the recursion logic
    states._while_lock = True

    # Enforce inner function of the while-loop to run
    if callable(inner_while):
        branch = inner_while()
        if branch is None:
            raise SyntaxError("require function return value")
    else:
        raise TypeError("condition to run would be a function")

    branch_dict = output.extract_step_return(branch)
    recursive_name = "exec-while-" + branch_dict["name"]
    recursive_id = "exec-while-" + branch_dict["id"]
    if states.workflow.get_template(recursive_name) is None:
        template = Steps(name=recursive_name)
    else:
        raise SyntaxError("Recursive function can not be called twice ")

    # Generate leaving point for recursive
    step_out_name = "%s-%s" % (recursive_name, "exit")
    pre = condition["pre"]
    pre_dict = output.extract_step_return(pre)
    condition_suffix = condition["condition"]

    # Generate the recursive go to step
    when_prefix = "{{steps.%s.%s}} %s %s" % (
        branch_dict["id"],
        branch_dict["output"],
        condition_suffix,
        pre_dict["value"],
    )
    step_out_template = OrderedDict({
        "name": step_out_name,
        "template": recursive_name,
        "when": when_prefix,
    })
    step_out_id = utils.invocation_name(step_out_name, recursive_id)
    states._while_steps[step_out_id] = [step_out_template]

    # Add steps inside the recursive logic to recursive template
    template.steps = list(states._while_steps.values())

    # Add this recursive logic to the templates
    states.workflow.add_template(template)

    # Add recursive logic to global _steps
    recursive_out_step = Step(name=recursive_id, template=recursive_name)
    states.workflow.add_step(name=recursive_id, step=recursive_out_step)

    states._while_lock = False
    states._while_steps = OrderedDict()
Esempio n. 2
0
def when(condition, function):
    """Generates an Argo conditional step.
    For example, the coinflip example in
    https://github.com/argoproj/argo/blob/master/examples/coinflip.yaml.
    """
    pre = condition["pre"]
    post = condition["post"]
    if pre is None or post is None:
        raise SyntaxError("Output of function can not be null")

    condition_suffix = condition["condition"]

    pre_dict = output.extract_step_return(pre)
    post_dict = output.extract_step_return(post)

    if "name" in pre_dict:
        left_function_id = pre_dict["id"]
        if states.workflow.get_step(left_function_id) is None:
            states.workflow.add_step(
                name=left_function_id,
                step=Step(name=left_function_id, template=pre_dict["name"]),
            )
    else:
        # TODO: fixed if left branch is a variable rather than function
        pre_dict["value"]

    post_value = post_dict["value"]

    if states._upstream_dag_task is not None:
        step_type = "tasks"
        states._when_task = pre_dict["id"]
    else:
        step_type = "steps"
    states._when_prefix = "{{%s.%s.%s}} %s %s" % (
        step_type,
        pre_dict["id"],
        pre_dict["output"],
        condition_suffix,
        post_value,
    )
    states._condition_id = "%s.%s" % (pre_dict["id"], pre_dict["output"])

    # Enforce the function to run and lock to add into step
    if callable(function):
        function()
    else:
        raise TypeError("condition to run would be a function")

    states._when_prefix = None
    states._condition_id = None
Esempio n. 3
0
def map(function, input_list):
    """
    map operation of Couler
    """
    # Enforce the function to run and lock to add into step
    if callable(function):
        states._update_steps_lock = False
        # TODO (terrytangyuan): Support functions with multiple arguments.
        para = input_list[0]
        inner = function(para)
        if inner is None:
            raise SyntaxError("require function return value")
        states._update_steps_lock = True
    else:
        raise TypeError("require loop over a function to run")

    inner_dict = output.extract_step_return(inner)
    template_name = inner_dict["name"]
    inner_step = Step(name=inner_dict["id"], template=template_name)

    parameters = []
    items_param_name = "%s-para-name" % template_name
    items_param_dict = {"name": items_param_name}
    function_template = states.workflow.get_template(template_name)
    function_template_dict = function_template.to_dict()

    if "resource" in function_template_dict:
        # Update the template with the new dynamic `metadata.name`.
        manifest_dict = yaml.safe_load(
            function_template_dict["resource"]["manifest"]
        )
        manifest_dict["metadata"]["name"] = (
            "'{{inputs.parameters.%s}}'" % items_param_name
        )
        function_template = states.workflow.get_template(template_name)
        function_template.manifest = pyaml.dump(manifest_dict)
        # Append this items parameter to input parameters in the template
        function_template.args.append(items_param_dict)
        states.workflow.add_template(function_template)
        input_parameters = [items_param_dict]
    else:
        input_parameters = function_template_dict["inputs"]["parameters"]

    for para_name in input_parameters:
        parameters.append(
            {
                "name": para_name["name"],
                "value": '"{{item.%s}}"' % para_name["name"],
            }
        )

    inner_step.arguments = {"parameters": parameters}

    with_items = []
    for para_values in input_list:
        item = {}
        if not isinstance(para_values, list):
            para_values = [para_values]

        for j in range(len(input_parameters)):
            para_name = input_parameters[j]["name"]
            item[para_name] = para_values[j]

        with_items.append(item)

    inner_step.with_items = with_items
    states.workflow.add_step(inner_dict["id"], inner_step)

    return inner_step
Esempio n. 4
0
def map(function, *arguments):
    """
    map operation of Couler
    """

    # Enforce the function to run and lock to add into step
    # Checks the correct syntax
    if callable(function):
        states._update_steps_lock = False

        para = []
        x = 0

        while x < len(arguments):
            para.append(arguments[x][0])
            x += 1

        inner = function(*para)

        if inner is None:
            raise SyntaxError("require function return value")
        states._update_steps_lock = True

    else:
        raise TypeError("require loop over a function to run")

    inner_dict = output.extract_step_return(inner)
    template_name = inner_dict["name"]
    inner_step = Step(name=inner_dict["id"], template=template_name)

    parameters = []
    items_param_name = "%s-para-name" % template_name
    items_param_dict = {"name": items_param_name}
    function_template = states.workflow.get_template(template_name)
    function_template_dict = function_template.to_dict()

    if "resource" in function_template_dict:
        # Update the template with the new dynamic `metadata.name`.
        manifest_dict = yaml.safe_load(
            function_template_dict["resource"]["manifest"])
        manifest_dict["metadata"]["name"] = ("'{{inputs.parameters.%s}}'" %
                                             items_param_name)
        function_template = states.workflow.get_template(template_name)
        function_template.manifest = pyaml.dump(manifest_dict)
        # Append this items parameter to input parameters in the template
        function_template.args.append(items_param_dict)
        states.workflow.add_template(function_template)
        input_parameters = [items_param_dict]
    else:
        input_parameters = function_template_dict["inputs"]["parameters"]

    for para_name in input_parameters:
        parameters.append({
            "name": para_name["name"],
            "value": '"{{item.%s}}"' % para_name["name"],
        })

    inner_step.arguments = {"parameters": parameters}

    # the following part of the code
    # Adds values to parameters (with items) while it goes
    # through the *arguments-variable with two loops.
    # inner loop:
    # arguments[ind_of_func_param][0], arguments[ind_of_func_param][0]...
    # Outer loop:
    # arguments[0][ind_of_func_call], arguments[0][ind_of_func_call]...
    # With two lists in *arguments
    # result would be:
    #  1. pair of items for the function:
    # arguments[0][0], arguments[1][0]
    # 2. pair of items for the function:
    #  arguments[0][1], arguments[1][1]
    # and so on...
    with_items = []
    ind_of_func_call = 0
    # the number of calls to be made to function
    while ind_of_func_call < len(arguments[0]):
        ind_of_func_param = 0
        item = {}
        # the number of parameters function takes.
        while ind_of_func_param < len(arguments):

            # checks if arguments[ind_of_func_param] is a list if not makes it
            if not isinstance(arguments[ind_of_func_param], list):
                arguments[ind_of_func_param] = [arguments[ind_of_func_param]]

            # items are created for the with items part in .yaml
            para_name = input_parameters[ind_of_func_param]["name"]
            item[para_name] = arguments[ind_of_func_param][ind_of_func_call]

            ind_of_func_param += 1
        with_items.append(item)
        ind_of_func_call += 1

    # all the created items are added to the step and
    # then the step is added to  .yaml
    inner_step.with_items = with_items
    states.workflow.add_step(inner_dict["id"], inner_step)

    return inner_step