Exemple #1
0
    def test_basic(self):
        """Test basic usage."""
        with Pipeline('somename') as p:
            self.assertEqual(1, len(p.groups))
            with OpsGroup(group_type='exit_handler'):
                op1 = ContainerOp(name='op1', image='image')
                with OpsGroup(group_type='branch'):
                    op2 = ContainerOp(name='op2', image='image')
                    op3 = ContainerOp(name='op3', image='image')
                with OpsGroup(group_type='loop'):
                    op4 = ContainerOp(name='op4', image='image')

        self.assertEqual(1, len(p.groups))
        self.assertEqual(1, len(p.groups[0].groups))
        exit_handler_group = p.groups[0].groups[0]
        self.assertEqual('exit_handler', exit_handler_group.type)
        self.assertEqual(2, len(exit_handler_group.groups))
        self.assertEqual(1, len(exit_handler_group.ops))
        self.assertEqual('op1', exit_handler_group.ops[0].name)

        branch_group = exit_handler_group.groups[0]
        self.assertFalse(branch_group.groups)
        self.assertCountEqual([x.name for x in branch_group.ops],
                              ['op2', 'op3'])

        loop_group = exit_handler_group.groups[1]
        self.assertFalse(loop_group.groups)
        self.assertCountEqual([x.name for x in loop_group.ops], ['op4'])
Exemple #2
0
 def test_invalid_exit_op(self):
     with self.assertRaises(ValueError):
         with Pipeline('somename') as p:
             op1 = ContainerOp(name='op1', image='image')
             exit_op = ContainerOp(name='exit', image='image')
             exit_op.after(op1)
             with ExitHandler(exit_op=exit_op):
                 pass
Exemple #3
0
    def test_basic(self):
        """Test basic usage."""
        with Pipeline('somename') as p:
            self.assertTrue(Pipeline.get_default_pipeline() is not None)
            op1 = ContainerOp(name='op1', image='image')
            op2 = ContainerOp(name='op2', image='image')

        self.assertTrue(Pipeline.get_default_pipeline() is None)
        self.assertEqual(p.ops['op1'].name, 'op1')
        self.assertEqual(p.ops['op2'].name, 'op2')
Exemple #4
0
    def test_basic(self):
        """Test basic usage."""
        with Pipeline('somename') as p:
            exit_op = ContainerOp(name='exit', image='image')
            with ExitHandler(exit_op=exit_op):
                op1 = ContainerOp(name='op1', image='image')

        exit_handler = p.groups[0].groups[0]
        self.assertEqual('exit_handler', exit_handler.type)
        self.assertEqual('exit', exit_handler.exit_op.name)
        self.assertEqual(1, len(exit_handler.ops))
        self.assertEqual('op1', exit_handler.ops[0].name)
 def test_use_set_volume_use_secret(self):
     op1 = ContainerOp(name="op1", image="image")
     secret_name = "my-secret"
     secret_path = "/here/are/my/secret"
     op1 = op1.apply(
         use_secret(secret_name=secret_name,
                    secret_volume_mount_path=secret_path))
     self.assertEqual(type(op1.container.env), type(None))
     container_dict = op1.container.to_dict()
     volume_mounts = container_dict["volume_mounts"][0]
     self.assertEqual(type(volume_mounts), dict)
     self.assertEqual(volume_mounts["mount_path"], secret_path)
Exemple #6
0
    def test_use_aws_secret(self):
        op1 = ContainerOp(name='op1', image='image')
        op1 = op1.apply(use_aws_secret('myaws-secret', 'key_id', 'access_key'))
        assert len(op1.container.env) == 2

        index = 0
        for expected_name, expected_key in [('AWS_ACCESS_KEY_ID', 'key_id'),
                                            ('AWS_SECRET_ACCESS_KEY',
                                             'access_key')]:
            assert op1.container.env[index].name == expected_name
            assert op1.container.env[
                index].value_from.secret_key_ref.name == 'myaws-secret'
            assert op1.container.env[
                index].value_from.secret_key_ref.key == expected_key
            index += 1
Exemple #7
0
    def test_use_azure_secret(self):
        op1 = ContainerOp(name='op1', image='image')
        op1 = op1.apply(use_azure_secret('foo'))
        assert len(op1.container.env) == 4

        index = 0
        for expected in [
                'AZ_SUBSCRIPTION_ID', 'AZ_TENANT_ID', 'AZ_CLIENT_ID',
                'AZ_CLIENT_SECRET'
        ]:
            assert op1.container.env[index].name == expected
            assert op1.container.env[
                index].value_from.secret_key_ref.name == 'foo'
            assert op1.container.env[
                index].value_from.secret_key_ref.key == expected
            index += 1
 def test_use_set_env_use_secret(self):
     op1 = ContainerOp(name="op1", image="image")
     secret_name = "my-secret"
     secret_path = "/here/are/my/secret/"
     env_variable = "MY_SECRET"
     secret_file_path_in_volume = "secret.json"
     op1 = op1.apply(
         use_secret(secret_name=secret_name,
                    secret_volume_mount_path=secret_path,
                    env_variable=env_variable,
                    secret_file_path_in_volume=secret_file_path_in_volume))
     self.assertEqual(len(op1.container.env), 1)
     container_dict = op1.container.to_dict()
     volume_mounts = container_dict["volume_mounts"][0]
     self.assertEqual(type(volume_mounts), dict)
     self.assertEqual(volume_mounts["mount_path"], secret_path)
     env_dict = op1.container.env[0].to_dict()
     self.assertEqual(env_dict["name"], env_variable)
     self.assertEqual(env_dict["value"],
                      secret_path + secret_file_path_in_volume)
Exemple #9
0
def update_op(op: dsl.ContainerOp,
              pipeline_name: dsl.PipelineParam,
              pipeline_root: dsl.PipelineParam,
              launcher_image: Optional[str] = None) -> None:
    """Updates the passed in Op for running in v2-compatible mode.

    Args:
      op: The Op to update.
      pipeline_spec: The PipelineSpec for the pipeline under which `op`
        runs.
      pipeline_root: The root output directory for pipeline artifacts.
      launcher_image: An optional launcher image. Useful for tests.
    """
    op.is_v2 = True
    # Inject the launcher binary and overwrite the entrypoint.
    image_name = launcher_image or _DEFAULT_LAUNCHER_IMAGE
    launcher_container = dsl.UserContainer(
        name="kfp-launcher",
        image=image_name,
        command=["launcher", "--copy", "/kfp-launcher/launch"],
        mirror_volume_mounts=True)

    op.add_init_container(launcher_container)
    op.add_volume(k8s_client.V1Volume(name='kfp-launcher'))
    op.add_volume_mount(
        k8s_client.V1VolumeMount(name='kfp-launcher',
                                 mount_path='/kfp-launcher'))

    # op.command + op.args will have the following sections:
    # 1. args passed to kfp-launcher
    # 2. a separator "--"
    # 3. parameters in format "key1=value1", "key2=value2", ...
    # 4. a separator "--" as end of arguments passed to launcher
    # 5. (start of op.args) arguments of the original user program command + args
    #
    # example:
    # - command:
    # - /kfp-launcher/launch
    # - '--mlmd_server_address'
    # - $(METADATA_GRPC_SERVICE_HOST)
    # - '--mlmd_server_port'
    # - $(METADATA_GRPC_SERVICE_PORT)
    # - ... # more launcher params
    # - '--pipeline_task_id'
    # - $(KFP_POD_NAME)
    # - '--pipeline_root'
    # - ''
    # - '--' # start of parameter values
    # - first=first
    # - second=second
    # - '--' # start of user command and args
    # args:
    # - sh
    # - '-ec'
    # - |
    #     program_path=$(mktemp)
    #     printf "%s" "$0" > "$program_path"
    #     python3 -u "$program_path" "$@"
    # - >
    #     import json
    #     import xxx
    #     ...
    op.command = [
        "/kfp-launcher/launch",
        "--mlmd_server_address",
        "$(METADATA_GRPC_SERVICE_HOST)",
        "--mlmd_server_port",
        "$(METADATA_GRPC_SERVICE_PORT)",
        "--runtime_info_json",
        "$(KFP_V2_RUNTIME_INFO)",
        "--container_image",
        "$(KFP_V2_IMAGE)",
        "--task_name",
        op.name,
        "--pipeline_name",
        pipeline_name,
        "--run_id",
        "$(KFP_RUN_ID)",
        "--run_resource",
        "workflows.argoproj.io/$(WORKFLOW_ID)",
        "--namespace",
        "$(KFP_NAMESPACE)",
        "--pod_name",
        "$(KFP_POD_NAME)",
        "--pod_uid",
        "$(KFP_POD_UID)",
        "--pipeline_root",
        pipeline_root,
        "--enable_caching",
        "$(ENABLE_CACHING)",
    ]

    # Mount necessary environment variables.
    op.apply(_default_transformers.add_kfp_pod_env)
    op.container.add_env_variable(
        k8s_client.V1EnvVar(name="KFP_V2_IMAGE", value=op.container.image))

    config_map_ref = k8s_client.V1ConfigMapEnvSource(
        name='metadata-grpc-configmap', optional=True)
    op.container.add_env_from(
        k8s_client.V1EnvFromSource(config_map_ref=config_map_ref))

    op.arguments = list(op.container_spec.command) + list(
        op.container_spec.args)

    runtime_info = {
        "inputParameters": collections.OrderedDict(),
        "inputArtifacts": collections.OrderedDict(),
        "outputParameters": collections.OrderedDict(),
        "outputArtifacts": collections.OrderedDict(),
    }

    op.command += ["--"]
    component_spec = op.component_spec
    for parameter, spec in sorted(
            component_spec.input_definitions.parameters.items()):
        parameter_type = pipeline_spec_pb2.ParameterType.ParameterTypeEnum.Name(
            spec.parameter_type)
        parameter_info = {"type": parameter_type}

        parameter_value = op._parameter_arguments[parameter]
        op.command += [f"{parameter}={parameter_value}"]

        runtime_info["inputParameters"][parameter] = parameter_info
    op.command += ["--"]

    for artifact_name, spec in sorted(
            component_spec.input_definitions.artifacts.items()):
        artifact_info = {
            "metadataPath": op.input_artifact_paths[artifact_name],
            "schemaTitle": spec.artifact_type.schema_title,
            "instanceSchema": spec.artifact_type.instance_schema,
            "schemaVersion": spec.artifact_type.schema_version,
        }
        runtime_info["inputArtifacts"][artifact_name] = artifact_info

    for parameter, spec in sorted(
            component_spec.output_definitions.parameters.items()):
        parameter_info = {
            "type":
            pipeline_spec_pb2.ParameterType.ParameterTypeEnum.Name(
                spec.parameter_type),
            "path":
            op.file_outputs[parameter],
        }
        runtime_info["outputParameters"][parameter] = parameter_info

    for artifact_name, spec in sorted(
            component_spec.output_definitions.artifacts.items()):
        # TODO: Assert instance_schema.
        artifact_info = {
            # Type used to register output artifacts.
            "schemaTitle": spec.artifact_type.schema_title,
            "instanceSchema": spec.artifact_type.instance_schema,
            "schemaVersion": spec.artifact_type.schema_version,
            # File used to write out the registered artifact ID.
            "metadataPath": op.file_outputs[artifact_name],
        }
        runtime_info["outputArtifacts"][artifact_name] = artifact_info

    op.container.add_env_variable(
        k8s_client.V1EnvVar(name="KFP_V2_RUNTIME_INFO",
                            value=json.dumps(runtime_info)))

    op.pod_annotations['pipelines.kubeflow.org/v2_component'] = "true"
    op.pod_labels['pipelines.kubeflow.org/v2_component'] = "true"
 def _add_common_labels(op: dsl.ContainerOp) -> dsl.ContainerOp:
     return op.add_pod_label('param', param)