Skip to content

Commit 54b82e5

Browse files
authored
Re-translate LaunchPlan fixed inputs with remote context on registration (#3403)
* fix: re-translate LaunchPlan fixed inputs with remote context on registration * NamedTemporaryFile(delete=False) to avoid file lock error
1 parent e0c3e23 commit 54b82e5

3 files changed

Lines changed: 73 additions & 0 deletions

File tree

flytekit/core/launch_plan.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ def create(
177177
# we don't have to reverse it back every time.
178178
default_inputs.update(fixed_inputs)
179179
lp._saved_inputs = default_inputs
180+
lp._raw_fixed_inputs = fixed_inputs
180181

181182
if name in cls.CACHE:
182183
raise AssertionError(f"Launch plan named {name} was already created! Make sure your names are unique.")
@@ -347,6 +348,7 @@ def __init__(
347348
self._fixed_inputs = fixed_inputs
348349
# See create() for additional information
349350
self._saved_inputs: Dict[str, Any] = {}
351+
self._raw_fixed_inputs: Dict[str, Any] = {}
350352

351353
self._schedule = schedule
352354
self._notifications = notifications or []
@@ -423,6 +425,10 @@ def fixed_inputs(self) -> _literal_models.LiteralMap:
423425
def workflow(self) -> _annotated_workflow.WorkflowBase:
424426
return self._workflow
425427

428+
@property
429+
def raw_fixed_inputs(self) -> Dict[str, Any]:
430+
return self._raw_fixed_inputs.copy()
431+
426432
@property
427433
def saved_inputs(self) -> Dict[str, Any]:
428434
# See note in create()

flytekit/remote/remote.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
from flytekit.core.data_persistence import FileAccessProvider
4949
from flytekit.core.launch_plan import LaunchPlan, ReferenceLaunchPlan
5050
from flytekit.core.node import Node as CoreNode
51+
from flytekit.core.promise import translate_inputs_to_literals
5152
from flytekit.core.python_auto_container import (
5253
PICKLE_FILE_PATH,
5354
PickledEntity,
@@ -1537,6 +1538,15 @@ def register_launch_plan(
15371538
entity.workflow, serialization_settings, version, default_launch_plan=False, options=options
15381539
)
15391540

1541+
if entity.raw_fixed_inputs:
1542+
fixed_literals = translate_inputs_to_literals(
1543+
self.context,
1544+
incoming_values=entity.raw_fixed_inputs,
1545+
flyte_interface_types=entity.workflow.interface.inputs,
1546+
native_types=entity.workflow.python_interface.inputs,
1547+
)
1548+
entity._fixed_inputs = literal_models.LiteralMap(literals=fixed_literals)
1549+
15401550
# Underlying workflow, exists, only register the launch plan itself
15411551
launch_plan_model = get_serializable(
15421552
OrderedDict(), settings=serialization_settings, entity=entity, options=options

tests/flytekit/unit/remote/test_remote.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,3 +911,60 @@ def hello_world_wf() -> str:
911911
assert remote_lp is mock_remote_lp
912912
assert not mock_serialize_and_register.called
913913
assert mock_raw_register.called
914+
915+
916+
@mock.patch("flytekit.remote.remote.translate_inputs_to_literals")
917+
@mock.patch("flytekit.remote.remote.get_serializable")
918+
@mock.patch("flytekit.remote.remote.FlyteRemote.fetch_launch_plan")
919+
@mock.patch("flytekit.remote.remote.FlyteRemote.raw_register")
920+
@mock.patch("flytekit.remote.remote.FlyteRemote._serialize_and_register")
921+
def test_register_launch_plan_retranslates_fixed_inputs_with_remote_context(
922+
mock_serialize_and_register, mock_raw_register, mock_fetch_launch_plan,
923+
mock_get_serializable, mock_translate, mock_flyte_remote_client
924+
):
925+
from flytekit.types.file import FlyteFile
926+
927+
@task
928+
def t_with_file(f: FlyteFile) -> str:
929+
return str(f)
930+
931+
@workflow
932+
def wf_with_file(f: FlyteFile) -> str:
933+
return t_with_file(f=f)
934+
935+
tmp = tempfile.NamedTemporaryFile(delete=False)
936+
try:
937+
ff = FlyteFile(path=tmp.name)
938+
lp = LaunchPlan.get_or_create(
939+
workflow=wf_with_file,
940+
name="lp_with_flytefile_fixed",
941+
fixed_inputs={"f": ff},
942+
)
943+
finally:
944+
tmp.close()
945+
946+
try:
947+
assert lp.raw_fixed_inputs == {"f": ff}
948+
949+
rr = FlyteRemote(
950+
Config.for_sandbox(),
951+
default_project="flytesnacks",
952+
default_domain="development",
953+
)
954+
955+
mock_translate.return_value = {"f": MagicMock()}
956+
mock_get_serializable.return_value = MagicMock()
957+
mock_flyte_remote_client.get_workflow.return_value = MagicMock()
958+
mock_fetch_launch_plan.return_value = MagicMock()
959+
960+
ss = SerializationSettings(image_config=ImageConfig.auto_default_image(), version="v1")
961+
rr.register_launch_plan(lp, version="v1", serialization_settings=ss)
962+
963+
mock_translate.assert_called_once_with(
964+
rr.context,
965+
incoming_values={"f": ff},
966+
flyte_interface_types=wf_with_file.interface.inputs,
967+
native_types=wf_with_file.python_interface.inputs,
968+
)
969+
finally:
970+
os.unlink(tmp.name)

0 commit comments

Comments
 (0)