-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(sdk): supporting bring your own container for arbitrary input an…
…d outputs (#8066) * support container_component decorator for function with no inputs * resolve review comments * add sample tests for milestone 1 * modify compiler test data * resolve reviews * resolve reviews * WIP * implementation of function of no inputs * fixed sample test * re-fix sample test * fix rebase merge conflict * resolve formatting * resolve isort error for test data * resolve comments * fix nit * resolve nit * add implementation for placeholders i/o, sample and compiler tests * resolve comments and merge logic for constructing container component * resolve comments * resolve comments * fix assertion messages * add error handling for accessing artifact by itself * add test for raising error for accessing artifact by itself
- Loading branch information
1 parent
e8abec2
commit 04c827f
Showing
25 changed files
with
1,109 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Copyright 2022 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 os | ||
|
||
from kfp import compiler | ||
from kfp import dsl | ||
|
||
|
||
@dsl.container_component | ||
def container_no_input(): | ||
return dsl.ContainerSpec( | ||
image='python:3.7', | ||
command=['echo', 'hello world'], | ||
args=[], | ||
) | ||
|
||
|
||
@dsl.pipeline(name='v2-container-component-no-input') | ||
def pipeline_container_no_input(): | ||
container_no_input() | ||
|
||
|
||
if __name__ == '__main__': | ||
# execute only if run as a script | ||
compiler.Compiler().compile( | ||
pipeline_func=pipeline_container_no_input, | ||
package_path='pipeline_container_no_input.yaml') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# Copyright 2022 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. | ||
"""Pipeline container no input v2 engine pipeline.""" | ||
|
||
from __future__ import annotations | ||
|
||
import unittest | ||
|
||
import kfp.deprecated as kfp | ||
import kfp_server_api | ||
from ml_metadata.proto import Execution | ||
|
||
from kfp.samples.test.utils import KfpTask, TaskInputs, TaskOutputs, TestCase, run_pipeline_func | ||
from .pipeline_container_no_input import pipeline_container_no_input | ||
|
||
|
||
def verify(t: unittest.TestCase, run: kfp_server_api.ApiRun, | ||
tasks: dict[str, KfpTask], **kwargs): | ||
t.assertEqual(run.status, 'Succeeded') | ||
t.assertEqual( | ||
{ | ||
'container-no-input': | ||
KfpTask( | ||
name='container-no-input', | ||
type='system.ContainerExecution', | ||
state=Execution.State.COMPLETE, | ||
inputs=TaskInputs(parameters={}, artifacts=[]), | ||
outputs=TaskOutputs(parameters={}, artifacts=[])) | ||
}, | ||
tasks, | ||
) | ||
|
||
|
||
if __name__ == '__main__': | ||
run_pipeline_func([ | ||
TestCase( | ||
pipeline_func=pipeline_container_no_input, | ||
verify_func=verify, | ||
mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, | ||
), | ||
]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Copyright 2022 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. | ||
"""Two step pipeline using dsl.container_component decorator.""" | ||
import os | ||
|
||
from kfp import compiler | ||
from kfp.dsl import container_component | ||
from kfp.dsl import ContainerSpec | ||
from kfp.dsl import Dataset | ||
from kfp.dsl import Input | ||
from kfp.dsl import Output | ||
from kfp.dsl import pipeline | ||
|
||
|
||
@container_component | ||
def component1(text: str, output_gcs: Output[Dataset]): | ||
return ContainerSpec( | ||
image='google/cloud-sdk:slim', | ||
command=[ | ||
'sh -c | set -e -x', 'echo', text, '| gsutil cp -', output_gcs.uri | ||
]) | ||
|
||
|
||
@container_component | ||
def component2(input_gcs: Input[Dataset]): | ||
return ContainerSpec( | ||
image='google/cloud-sdk:slim', | ||
command=['sh', '-c', '|', 'set -e -x gsutil cat'], | ||
args=[input_gcs.path]) | ||
|
||
|
||
@pipeline(name='two-step-pipeline-containerized') | ||
def two_step_pipeline_containerized(): | ||
component_1 = component1(text='hi').set_display_name('Producer') | ||
component_2 = component2(input_gcs=component_1.outputs['output_gcs']) | ||
component_2.set_display_name('Consumer') | ||
|
||
|
||
if __name__ == '__main__': | ||
# execute only if run as a script | ||
|
||
compiler.Compiler().compile( | ||
pipeline_func=two_step_pipeline_containerized, | ||
package_path='two_step_pipeline_containerized.yaml') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Copyright 2022 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. | ||
"""Pipeline container no input v2 engine pipeline.""" | ||
|
||
from __future__ import annotations | ||
|
||
import unittest | ||
|
||
import kfp.deprecated as kfp | ||
from kfp.samples.test.utils import KfpTask | ||
from kfp.samples.test.utils import run_pipeline_func | ||
from kfp.samples.test.utils import TaskInputs | ||
from kfp.samples.test.utils import TaskOutputs | ||
from kfp.samples.test.utils import TestCase | ||
import kfp_server_api | ||
from ml_metadata.proto import Execution | ||
|
||
from .two_step_pipeline_containerized import two_step_pipeline_containerized | ||
|
||
|
||
def verify(t: unittest.TestCase, run: kfp_server_api.ApiRun, | ||
tasks: dict[str, KfpTask], **kwargs): | ||
t.assertEqual(run.status, 'Succeeded') | ||
component1_dict = tasks['component1'].get_dict() | ||
component2_dict = tasks['component2'].get_dict() | ||
for artifact in component1_dict.get('outputs').get('artifacts'): | ||
# pop metadata here because the artifact which got re-imported may have metadata with uncertain data | ||
if artifact.get('metadata') is not None: | ||
artifact.pop('metadata') | ||
for artifact in component2_dict.get('inputs').get('artifacts'): | ||
# pop metadata here because the artifact which got re-imported may have metadata with uncertain data | ||
if artifact.get('metadata') is not None: | ||
artifact.pop('metadata') | ||
|
||
t.assertEqual( | ||
{ | ||
'name': 'component1', | ||
'inputs': { | ||
'parameters': { | ||
'text': 'hi' | ||
} | ||
}, | ||
'outputs': { | ||
'artifacts': [{ | ||
'name': 'output_gcs', | ||
'type': 'system.Dataset' | ||
}], | ||
}, | ||
'type': 'system.ContainerExecution', | ||
'state': Execution.State.COMPLETE, | ||
}, component1_dict) | ||
|
||
t.assertEqual( | ||
{ | ||
'name': 'component2', | ||
'inputs': { | ||
'artifacts': [{ | ||
'name': 'input_gcs', | ||
'type': 'system.Dataset' | ||
}], | ||
}, | ||
'outputs': {}, | ||
'type': 'system.ContainerExecution', | ||
'state': Execution.State.COMPLETE, | ||
}, component2_dict) | ||
|
||
|
||
if __name__ == '__main__': | ||
run_pipeline_func([ | ||
TestCase( | ||
pipeline_func=two_step_pipeline_containerized, | ||
verify_func=verify, | ||
mode=kfp.dsl.PipelineExecutionMode.V2_ENGINE, | ||
), | ||
]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.