Example #1
0
    def test_run_container_with_workflow_volume(self):
        pvc = VolumeClaimTemplate("workdir")
        volume_mount = VolumeMount("workdir", "/mnt/vol")
        couler.create_workflow_volume(pvc)
        couler.run_container(
            image="docker/whalesay:latest",
            args=["echo -n hello world"],
            command=["bash", "-c"],
            step_name="A",
            volume_mounts=[volume_mount],
        )
        volume_mount = VolumeMount("workdir", "/mnt/vol")
        couler.run_container(
            image="docker/whalesay:latest",
            args=["echo -n hello world"],
            command=["bash", "-c"],
            step_name="A",
            volume_mounts=[volume_mount],
        )

        wf = couler.workflow_yaml()
        self.assertEqual(len(wf["spec"]["volumeClaimTemplates"]), 1)
        self.assertEqual(wf["spec"]["volumeClaimTemplates"][0], pvc.to_dict())
        self.assertEqual(
            wf["spec"]["templates"][1]["container"]["volumeMounts"][0],
            volume_mount.to_dict(),
        )
        couler._cleanup()
Example #2
0
    def test_run_container_with_volume(self):
        volume = Volume("workdir", "my-existing-volume")
        volume_mount = VolumeMount("workdir", "/mnt/vol")
        couler.add_volume(volume)
        couler.run_container(
            image="docker/whalesay:latest",
            args=["echo -n hello world"],
            command=["bash", "-c"],
            step_name="A",
            volume_mounts=[volume_mount],
        )

        wf = couler.workflow_yaml()
        self.assertEqual(wf["spec"]["volumes"][0], volume.to_dict())
        self.assertEqual(
            wf["spec"]["templates"][1]["container"]["volumeMounts"][0],
            volume_mount.to_dict(),
        )
        couler._cleanup()
Example #3
0
def run_container(
    image,
    command=None,
    args=None,
    output=None,
    input=None,
    env=None,
    secret=None,
    resources=None,
    timeout=None,
    retry=None,
    step_name=None,
    image_pull_policy=None,
    pool=None,
    enable_ulogfs=True,
    daemon=False,
    volume_mounts=None,
    working_dir=None,
    node_selector=None,
):
    """
    Generate an Argo container template.  For example, the template whalesay
    in https://github.com/argoproj/argo/tree/master/examples#hello-world.
    :param image:
    :param command:
    :param args:
    :param output: output artifact for container output
    :param input: input artifact for container input
    :param env: environmental variable
    :param secret:
    :param resources: CPU or memory resource config dict
    :param timeout: in seconds
    :param retry: retry policy
    :param step_name: used for annotating step .
    :param image_pull_policy:
    :param pool:
    :param enable_ulogfs:
    :param daemon:
    :return:
    """
    func_name, caller_line = utils.invocation_location()
    func_name = (utils.argo_safe_name(step_name)
                 if step_name is not None else func_name)

    if states.workflow.get_template(func_name) is None:
        # Generate the inputs parameter for the template
        if input is None:
            input = []

        if args is None and states._outputs_tmp is not None:
            args = []

        if args is not None:
            if not isinstance(args, list):
                args = [args]

            # Handle case where args is a list of list type
            # For example, [[Output, ]]
            if (isinstance(args, list) and len(args) > 0
                    and isinstance(args[0], list) and len(args[0]) > 0
                    and isinstance(args[0][0], Output)):
                args = args[0]

            if states._outputs_tmp is not None:
                args.extend(states._outputs_tmp)

            # In case, the args include output artifact
            # Place output artifact into the input
            for arg in args:
                if isinstance(arg, (OutputArtifact, OutputJob)):
                    input.append(arg)

        # Automatically append emptyDir volume and volume mount to work with
        # Argo k8sapi executor.
        # More info: https://argoproj.github.io/argo/empty-dir/
        if output is not None:
            if not isinstance(output, list):
                output = [output]
            if volume_mounts is None:
                volume_mounts = []
            mounted_path = []
            for i, out in enumerate(output):
                if "/tmp" in out.path:
                    raise ValueError("Mounting to /tmp is not supported")
                path_to_mount = os.path.dirname(out.path)
                # Avoid duplicate mount paths
                if path_to_mount not in mounted_path:
                    volume_mounts.append(
                        VolumeMount("couler-out-dir-%s" % i, path_to_mount))
                    mounted_path.append(path_to_mount)

        # Generate container and template
        template = Container(
            name=func_name,
            image=image,
            command=command,
            args=args,
            env=env,
            secret=states.get_secret(secret),
            resources=resources,
            image_pull_policy=image_pull_policy,
            retry=retry,
            timeout=timeout,
            output=output,
            input=input,
            pool=pool,
            enable_ulogfs=enable_ulogfs,
            daemon=daemon,
            volume_mounts=volume_mounts,
            working_dir=working_dir,
            node_selector=node_selector,
        )
        states.workflow.add_template(template)

    step_name = step_update_utils.update_step(func_name, args, step_name,
                                              caller_line)

    # TODO: need to switch to use field `output` directly
    step_templ = states.workflow.get_template(func_name)
    _output = step_templ.to_dict().get("outputs", None)
    _input = step_templ.to_dict().get("inputs", None)

    rets = _container_output(step_name, func_name, _output)
    states._steps_outputs[step_name] = rets

    pb_step = proto_repr.step_repr(  # noqa: F841
        step_name=step_name,
        tmpl_name=func_name,
        image=image,
        command=command,
        source=None,
        script_output=None,
        args=args,
        input=_input,
        output=_output,
    )

    return rets
Example #4
0
    _SUBMITTER_IMPL_ENV_VAR_KEY,
    ArgoSubmitter,
    _SubmitterImplTypes,
)
from couler.core.templates.volume import VolumeMount

if __name__ == "__main__":
    for impl_type in [_SubmitterImplTypes.PYTHON]:
        os.environ[_SUBMITTER_IMPL_ENV_VAR_KEY] = impl_type
        print("Submitting volume example workflow via %s implementation" %
              impl_type)
        couler.config_workflow(
            name="volume-%s" % impl_type.lower(),
            timeout=3600,
            time_to_clean=3600 * 1.5,
        )
        # 2) Add a container to the workflow.
        couler.run_container(
            image="debian:latest",
            command=["/bin/bash", "-c"],
            args=[
                ' vol_found=`mount | grep /tmp` && \
            if [[ -n $vol_found ]]; \
            then echo "Volume mounted and found"; \
            else exit -1; fi '
            ],
            volume_mounts=[VolumeMount("apppath", "/tmp")],
        )
        submitter = ArgoSubmitter(namespace="argo")
        couler.run(submitter=submitter)