from kfp.samples.test.utils import run_pipeline_func, TestCase def EXPECTED_OOM(run_id, run, **kwargs): """confirms a sample test case is failing, because of OOM.""" assert run.status == 'Failed' run_pipeline_func([ TestCase( pipeline_func=my_pipeline_v2, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, ), TestCase( pipeline_func=my_pipeline_v2, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, arguments={'n': 21234567}, verify_func=EXPECTED_OOM, ), TestCase( pipeline_func=my_pipeline, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), TestCase( pipeline_func=my_pipeline, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, arguments={'n': 21234567}, verify_func=EXPECTED_OOM, ), ])
# Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp.deprecated as kfp from kfp.samples.test.utils import TestCase, relative_path, run_pipeline_func run_pipeline_func([ TestCase( pipeline_file=relative_path(__file__, 'imagepullsecrets.py'), mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), ])
# Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp.deprecated as kfp from kfp.samples.test.utils import TestCase, relative_path, run_pipeline_func run_pipeline_func([ TestCase( pipeline_file=relative_path(__file__, 'parallelism_sub_dag.py'), mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), TestCase( pipeline_file=relative_path(__file__, 'parallelism_sub_dag_with_op_output.py'), mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), ])
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import json import kfp from kfp.samples.test.utils import TestCase, relative_path, run_pipeline_func bucket = 'kfp-ci' run_pipeline_func([ TestCase( pipeline_file=relative_path(__file__, 'parameterized_tfx_oss.py'), pipeline_file_compile_path=relative_path( __file__, 'parameterized_tfx_oss.py.yaml'), arguments={ 'pipeline-root': f'gs://{bucket}/tfx_taxi_simple', 'push_destination': json.dumps({ "filesystem": { "base_directory": f"gs://{bucket}/tfx_taxi_simple/serving_model" } }) }, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, timeout_mins=40, ), ])
# Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp.deprecated as kfp from kfp.samples.test.utils import TestCase, relative_path, run_pipeline_func run_pipeline_func([ TestCase( pipeline_file=relative_path(__file__, 'execution_order.py'), mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), ])
from .roc import roc_curve_pipeline from kfp.samples.test.utils import KfpMlmdClient, run_pipeline_func, TestCase import kfp.deprecated as kfp def verify(run: kfp_server_api.ApiRun, mlmd_connection_config, **kwargs): t = unittest.TestCase() t.maxDiff = None # we always want to see full diff t.assertEqual(run.status, 'Succeeded') client = KfpMlmdClient(mlmd_connection_config=mlmd_connection_config) tasks = client.get_tasks(run_id=run.id) pprint(tasks) roc_visualization = tasks['roc-visualization'] output = [ a for a in roc_visualization.outputs.artifacts if a.name == 'mlpipeline_ui_metadata' ][0] pprint(output) t.assertEqual( roc_visualization.get_dict()['outputs']['artifacts'][0]['name'], 'mlpipeline_ui_metadata') run_pipeline_func([ TestCase(pipeline_func=roc_curve_pipeline, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY) ])
tasks['for-loop-1'].children['for-loop-1-#0'].get_dict(), ) t.assertEqual( { 'name': 'print-op', 'type': 'system.ContainerExecution', 'state': Execution.State.COMPLETE, 'inputs': { 'parameters': { 's': '1.1', } }, 'outputs': {}, }, tasks['for-loop-1'].children['for-loop-1-#0'].children['print-op']. get_dict(), ) run_pipeline_func([ TestCase( pipeline_func=my_pipeline_v2, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, verify_func=verify, ), TestCase( pipeline_func=my_pipeline, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), ])
"A": 1.0, "B": 2.0, }, 'input_list': ["a", "b", "c"], 'message': 'message' } }, 'name': 'train', 'outputs': { 'artifacts': [{ 'metadata': { 'display_name': 'model', 'accuracy': 0.9, }, 'name': 'model', 'type': 'system.Model' }], }, 'type': 'system.ContainerExecution', 'state': Execution.State.COMPLETE, }, train.get_dict(), ) run_pipeline_func([ TestCase(pipeline_func=pipeline, verify_func=verify, mode=dsl.PipelineExecutionMode.V2_ENGINE), ])
# Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp.deprecated as kfp from .xgboost_sample import xgboost_pipeline from kfp.samples.test.utils import run_pipeline_func, TestCase run_pipeline_func([ TestCase( pipeline_func=xgboost_pipeline, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), ])
# Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp from kfp.samples.test.utils import TestCase, relative_path, run_pipeline_func run_pipeline_func([ TestCase( pipeline_file=relative_path(__file__, 'volume_snapshot_ops.py'), mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, run_pipeline=False, ), ])
# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp from .parameter_with_format import my_pipeline from kfp.samples.test.utils import run_pipeline_func, TestCase def verify(run, run_id: str, **kwargs): assert run.status == 'Succeeded' # TODO(Bobgy): verify output run_pipeline_func([ # Cannot test V2_ENGINE and V1_LEGACY using the same code. # V2_ENGINE requires importing everything from v2 namespace. # TestCase( # pipeline_func=my_pipeline, # verify_func=verify, # mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, # ), TestCase( pipeline_func=my_pipeline, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), ])
tasks = client.get_tasks(run_id=run.id) verify_tasks(t, tasks, state, uri, some_int) if __name__ == '__main__': letters = string.ascii_lowercase random_uri = 'http://v2' + ''.join(random.choice(letters) for i in range(5)) random_int = random.randint(0, 10000) run_pipeline_func([ TestCase( pipeline_func=two_step_pipeline, arguments={ 'uri': f'{random_uri}', 'some_int': f'{random_int}' }, verify_func=functools.partial( verify, uri=random_uri, some_int=random_int, state=Execution.State.COMPLETE, ), mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, enable_caching=True), ]), run_pipeline_func([ TestCase( pipeline_func=two_step_pipeline, arguments={ 'uri': f'{random_uri}', 'some_int': f'{random_int}' }, verify_func=functools.partial(
#!/usr/bin/env python3 # Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp from .legacy_exit_handler import download_and_print from kfp.samples.test.utils import run_pipeline_func, TestCase run_pipeline_func([ # This sample is expected to not work on v2 compatible mode. TestCase(pipeline_func=download_and_print, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY) ])
type='system.ContainerExecution', state=Execution.State.COMPLETE, inputs=TaskInputs(parameters={ 'input_value': 'Hello world, this is an output parameter\n' }, artifacts=[]), outputs=TaskOutputs(parameters={}, artifacts=[])), 'producer': KfpTask(name='producer', type='system.ContainerExecution', state=Execution.State.COMPLETE, inputs=TaskInputs(parameters={'input_text': 'Hello world'}, artifacts=[]), outputs=TaskOutputs(parameters={ 'output_value': 'Hello world, this is an output parameter\n' }, artifacts=[])) }, tasks) if __name__ == '__main__': run_pipeline_func([ TestCase( pipeline_func=producer_consumer_param_pipeline, verify_func=verify, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, ), ])
# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp.deprecated as kfp from .placeholder_if import pipeline_both, pipeline_none # from .placeholder_if_v2 import pipeline_both as pipeline_both_v2, pipeline_none as pipeline_none_v2 from kfp.samples.test.utils import run_pipeline_func, TestCase run_pipeline_func([ # TODO(chesu): fix compile failure, https://github.com/kubeflow/pipelines/issues/6966 # TestCase( # pipeline_func=pipeline_none_v2, # mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE), # TestCase( # pipeline_func=pipeline_both_v2, # mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE), TestCase(pipeline_func=pipeline_none, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY), TestCase(pipeline_func=pipeline_both, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY), ])
# Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp from kfp.samples.test.utils import TestCase, relative_path, run_pipeline_func run_pipeline_func([ TestCase( pipeline_file=relative_path(__file__, 'multiple_outputs.ipynb'), mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), ])
'type': 'system.HTML' }], }, 'state': Execution.State.COMPLETE, 'type': 'system.ContainerExecution' }, html_visualization.get_dict()) t.assertEqual( { 'name': 'markdown-visualization', 'inputs': {}, 'outputs': { 'artifacts': [{ 'metadata': { 'display_name': 'markdown_artifact' }, 'name': 'markdown_artifact', 'type': 'system.Markdown' }], }, 'state': Execution.State.COMPLETE, 'type': 'system.ContainerExecution' }, markdown_visualization.get_dict()) run_pipeline_func([ TestCase(pipeline_func=metrics_visualization_pipeline, verify_func=verify, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE), ])
t = unittest.TestCase() t.maxDiff = None # we always want to see full diff t.assertEqual(run.status, 'Succeeded') # Verify MLMD state client = KfpMlmdClient(mlmd_connection_config=mlmd_connection_config) tasks = client.get_tasks(run_id=run.id) task_names = [*tasks.keys()] t.assertEqual(task_names, ['echo-msg', 'print-file', 'download-from-gcs']) for task in task_names: pprint(f'======= {task} =======') pprint(tasks.get(task).get_dict()) t.assertEqual( tasks.get('echo-msg').inputs.parameters.get('msg'), 'exit!', ) # %% if __name__ == '__main__': run_pipeline_func([ TestCase( pipeline_func=pipeline_exit_handler, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), ])
#!/usr/bin/env python3 # Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp.deprecated as kfp from .use_run_id import pipeline_use_run_id from kfp.samples.test.utils import run_pipeline_func, TestCase run_pipeline_func([ TestCase( pipeline_func=pipeline_use_run_id, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), ])
from kfp.samples.test.utils import KfpTask, TaskInputs, TaskOutputs, TestCase, run_pipeline_func from .hello_world import pipeline_hello_world def verify(t: unittest.TestCase, run: kfp_server_api.ApiRun, tasks: dict[str, KfpTask], **kwargs): t.assertEqual(run.status, 'Succeeded') t.assertEqual( { 'hello-world': KfpTask(name='hello-world', type='system.ContainerExecution', state=Execution.State.COMPLETE, inputs=TaskInputs(parameters={'text': 'hi there'}, artifacts=[]), outputs=TaskOutputs(parameters={'Output': 'hi there'}, artifacts=[])) }, tasks, ) if __name__ == '__main__': run_pipeline_func([ TestCase( pipeline_func=pipeline_hello_world, verify_func=verify, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, ), ])
from .legacy_data_passing import data_passing_pipeline from kfp.samples.test.utils import run_pipeline_func, TestCase from kfp.dsl import PipelineExecutionMode run_pipeline_func([ TestCase( pipeline_func=data_passing_pipeline, mode=PipelineExecutionMode.V1_LEGACY, ) ])
# Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp.deprecated as kfp from kfp.samples.test.utils import TestCase, relative_path, run_pipeline_func run_pipeline_func([ TestCase( pipeline_file=relative_path(__file__, 'caching.ipynb'), mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, run_pipeline=False, ), ])
# Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp from kfp.samples.test.utils import TestCase, relative_path, run_pipeline_func run_pipeline_func([ TestCase( pipeline_file=relative_path(__file__, 'dataflow.ipynb'), arguments={ 'project_id': 'kfp-ci', 'staging_dir': 'gs://kfp-ci/samples/dataflow', 'region': 'us-central1', }, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, timeout_mins=40, ), ])
'metadata': { 'display_name': 'artifact' }, 'name': 'artifact', 'type': 'system.Artifact', }], }, 'outputs': {}, 'type': 'system.ContainerExecution', 'state': Execution.State.COMPLETE, }, read_task.get_dict()) def verify(run: kfp_server_api.ApiRun, mlmd_connection_config, **kwargs): t = unittest.TestCase() t.maxDiff = None # we always want to see full diff t.assertEqual(run.status, 'Succeeded') client = KfpMlmdClient(mlmd_connection_config=mlmd_connection_config) tasks = client.get_tasks(run_id=run.id) verify_tasks(t, tasks) if __name__ == '__main__': run_pipeline_func([ TestCase( pipeline_func=two_step_with_uri_placeholder, verify_func=verify, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, ), ])
# Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp from kfp.samples.test.utils import TestCase, relative_path, run_pipeline_func run_pipeline_func([ TestCase( pipeline_file=relative_path(__file__, 'pipeline_transformers.py'), mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, ), ])
t.assertCountEqual(['print-msg', 'condition-1', 'flip-coin'], tasks.keys()) t.assertIsNone(tasks['condition-1'].children) # MLMD canceled state means NotTriggered state for KFP. t.assertEqual(Execution.State.CANCELED, tasks['condition-1'].state) run_pipeline_func([ TestCase( pipeline_func=condition_v2, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, arguments={"force_flip_result": "heads"}, verify_func=verify_heads, ), TestCase( pipeline_func=condition_v2, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, arguments={"force_flip_result": "tails"}, verify_func=verify_tails, ), TestCase( pipeline_func=condition, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, arguments={"force_flip_result": "heads"}, ), TestCase( pipeline_func=condition, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY, arguments={"force_flip_result": "tails"}, ), ])
# Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp.deprecated as kfp from .after import my_pipeline from kfp.samples.test.utils import run_pipeline_func, TestCase run_pipeline_func([ TestCase(pipeline_func=my_pipeline, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE), ])
assert run.status == 'Failed' def verify_v2(t: unittest.TestCase, run: kfp_server_api.ApiRun, tasks: dict[str, KfpTask], **kwargs): t.assertEqual(run.status, 'Failed') t.assertEqual( { 'fail': KfpTask( name='fail', type='system.ContainerExecution', # TODO(Bobgy): fix v2 engine to properly publish FAILED state. state=Execution.State.RUNNING, inputs=TaskInputs(parameters={}, artifacts=[]), outputs=TaskOutputs(parameters={}, artifacts=[]), ) }, tasks, ) run_pipeline_func([ TestCase(pipeline_func=fail_v2_pipeline, verify_func=verify_v2, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE), TestCase(pipeline_func=fail_pipeline, verify_func=verify, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY), ])
# Copyright 2021 The Kubeflow Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from .markdown import markdown_pipeline from kfp.samples.test.utils import run_pipeline_func, TestCase import kfp run_pipeline_func([ TestCase(pipeline_func=markdown_pipeline, mode=kfp.dsl.PipelineExecutionMode.V1_LEGACY) ])
# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import kfp from .placeholder_concat import pipeline_with_concat_placeholder from kfp.samples.test.utils import run_pipeline_func, TestCase def verify(run, run_id: str, **kwargs): assert run.status == 'Succeeded' # TODO(Bobgy): verify echo output # TODO(v2-compatible): support IR placeholder like {{$.inputs.parameters['input_prefix']}} run_pipeline_func([ TestCase( pipeline_func=pipeline_with_concat_placeholder, verify_func=verify, mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, ), ])