Skip to content

Commit d6a0d17

Browse files
committed
Avoid changing the task runtime config object at all.
1 parent 98d6b92 commit d6a0d17

File tree

5 files changed

+106
-21
lines changed

5 files changed

+106
-21
lines changed

cylc/flow/platforms.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ def get_platform(
108108
def get_platform(
109109
task_conf: Union[str, dict, 'OrderedDictWithDefaults', None] = None,
110110
task_name: str = UNKNOWN_TASK,
111-
bad_hosts: Optional[Set[str]] = None
111+
bad_hosts: Optional[Set[str]] = None,
112+
evaluated_host: Optional[str] = None,
112113
) -> Optional[Dict[str, Any]]:
113114
"""Get a platform.
114115
@@ -121,6 +122,7 @@ def get_platform(
121122
task_name: Help produce more helpful error messages.
122123
bad_hosts: A set of hosts known to be unreachable (had an ssh 255
123124
error)
125+
evaluated_host: Host name evaluated from platform subshell.
124126
125127
Returns:
126128
platform: A platform definition dictionary. Uses either
@@ -169,7 +171,8 @@ def get_platform(
169171
platform_name_from_job_info(
170172
glbl_cfg().get(['platforms']),
171173
task_job_section,
172-
task_remote_section
174+
task_remote_section,
175+
evaluated_host
173176
),
174177
bad_hosts=bad_hosts
175178
)
@@ -331,7 +334,8 @@ def get_platform_from_group(
331334
def platform_name_from_job_info(
332335
platforms: Union[dict, 'OrderedDictWithDefaults'],
333336
job: Dict[str, Any],
334-
remote: Dict[str, Any]
337+
remote: Dict[str, Any],
338+
evaluated_host: Optional[str] = None,
335339
) -> str:
336340
"""
337341
Find out which job platform to use given a list of possible platforms
@@ -386,6 +390,7 @@ def platform_name_from_job_info(
386390
job: Workflow config [runtime][TASK][job] section.
387391
remote: Workflow config [runtime][TASK][remote] section.
388392
platforms: Dictionary containing platform definitions.
393+
evaluated_host: Host is the result of evaluating a subshell.
389394
390395
Returns:
391396
platform: string representing a platform from the global config.
@@ -423,7 +428,9 @@ def platform_name_from_job_info(
423428

424429
# NOTE: Do NOT use .get() on OrderedDictWithDefaults -
425430
# https://github.com/cylc/cylc-flow/pull/4975
426-
if 'host' in remote and remote['host']:
431+
if evaluated_host:
432+
task_host = evaluated_host
433+
elif 'host' in remote and remote['host']:
427434
task_host = remote['host']
428435
else:
429436
task_host = 'localhost'

cylc/flow/task_job_mgr.py

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,10 +1236,10 @@ def _prep_submit_task_job(
12361236
f"\"{itask.identity}\" the following are not compatible:\n"
12371237
)
12381238

1239-
host_n, platform_name, orig_platform_name, orig_host_name = [None] * 4
1239+
host_name, platform_name = [None] * 2
12401240
try:
12411241
if rtconfig['remote']['host'] is not None:
1242-
host_n = self.task_remote_mgr.eval_host(
1242+
host_name = self.task_remote_mgr.eval_host(
12431243
rtconfig['remote']['host']
12441244
)
12451245
else:
@@ -1258,33 +1258,34 @@ def _prep_submit_task_job(
12581258
return False
12591259
else:
12601260
# host/platform select not ready
1261-
if host_n is None and platform_name is None:
1261+
if host_name is None and platform_name is None:
12621262
return None
12631263
elif (
1264-
host_n is None
1264+
host_name is None
12651265
and rtconfig['platform']
12661266
and rtconfig['platform'] != platform_name
12671267
):
12681268
LOG.debug(
12691269
f"for task {itask.identity}: platform = "
12701270
f"{rtconfig['platform']} evaluated as {platform_name}"
12711271
)
1272-
orig_platform_name = rtconfig['platform']
1273-
rtconfig['platform'] = platform_name
1272+
# orig_platform_name = rtconfig['platform']
1273+
# rtconfig['platform'] = platform_name
12741274
elif (
12751275
platform_name is None
1276-
and rtconfig['remote']['host'] != host_n
1276+
and rtconfig['remote']['host'] != host_name
12771277
):
12781278
LOG.debug(
12791279
f"[{itask}] host = "
1280-
f"{rtconfig['remote']['host']} evaluated as {host_n}"
1280+
f"{rtconfig['remote']['host']} evaluated as {host_name}"
12811281
)
1282-
orig_host_name = host_n
1283-
rtconfig['remote']['host'] = host_n
12841282

12851283
try:
12861284
platform = get_platform(
1287-
rtconfig, itask.tdef.name, bad_hosts=self.bad_hosts
1285+
platform_name or rtconfig,
1286+
itask.tdef.name,
1287+
bad_hosts=self.bad_hosts,
1288+
evaluated_host=host_name,
12881289
)
12891290
except PlatformLookupError as exc:
12901291
itask.waiting_on_job_prep = False
@@ -1308,12 +1309,6 @@ def _prep_submit_task_job(
13081309
# Retry delays, needed for the try_num
13091310
self._set_retry_timers(itask, rtconfig)
13101311

1311-
# Put the original platform and host names back into the
1312-
# rtconfig. Prevents storing first evaluation of shell expression.
1313-
if orig_platform_name:
1314-
rtconfig['platform'] = orig_platform_name
1315-
if orig_host_name:
1316-
rtconfig['remote']['host'] = orig_host_name
13171312

13181313
try:
13191314
job_conf = self._prep_submit_task_job_impl(
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env bash
2+
# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE.
3+
# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
4+
#
5+
# This program is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
#-----------------------------------------------------------------------------
18+
19+
# If a task has a platform set using a subshell this should be evaluated
20+
# every time the task is run.
21+
# https://github.com/cylc/cylc-flow/issues/6808
22+
export REQUIRE_PLATFORM='loc:remote'
23+
24+
. "$(dirname "$0")/test_header"
25+
26+
set_test_number 3
27+
28+
install_workflow "${TEST_NAME_BASE}" "${TEST_NAME_BASE}"
29+
30+
workflow_run_ok "${TEST_NAME_BASE}-run" \
31+
cylc play "${WORKFLOW_NAME}" --debug --no-detach
32+
33+
named_grep_ok "1/remote_task submits to ${CYLC_TEST_PLATFORM}" \
34+
"\[1/remote_task/01:preparing\] submitted to ${CYLC_TEST_PLATFORM}" \
35+
"${WORKFLOW_RUN_DIR}/log/scheduler/log"
36+
37+
named_grep_ok "2/remote_task submits to localhost" \
38+
"\[2/remote_task/01:preparing\] submitted to localhost" \
39+
"${WORKFLOW_RUN_DIR}/log/scheduler/log"
40+
41+
purge
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!jinja2
2+
[scheduler]
3+
[[events]]
4+
stall timeout = PT0S
5+
6+
[scheduling]
7+
cycling mode = integer
8+
final cycle point = 2
9+
[[graph]]
10+
P1 = remote_task[-P1] => toggler => remote_task
11+
12+
[runtime]
13+
[[remote_task]]
14+
[[[remote]]]
15+
host = $(cat ${CYLC_WORKFLOW_RUN_DIR}/pretend-hall-info)
16+
17+
[[toggler]]
18+
script = """
19+
# Toggle the platform between localhost and the remote host
20+
# using the content of a file, ${CYLC_WORKFLOW_RUN_DIR}/pretend-hall-info.
21+
# between localhost and the remote.
22+
23+
if (( $CYLC_TASK_CYCLE_POINT % 2 == 1 )); then
24+
echo ${REMOTE_PLATFORM} > ${CYLC_WORKFLOW_RUN_DIR}/pretend-hall-info
25+
cylc message -- "changing platform to ${REMOTE_PLATFORM}"
26+
else
27+
echo "localhost" > ${CYLC_WORKFLOW_RUN_DIR}/pretend-hall-info
28+
cylc message -- "changing platform to localhost"
29+
fi
30+
"""
31+
[[[environment]]]
32+
REMOTE_PLATFORM = {{ CYLC_TEST_PLATFORM }}

tests/unit/test_platforms.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,16 @@ def test_platform_name_from_job_info_basic(job, remote, returns):
273273
assert platform_name_from_job_info(PLATFORMS, job, remote) == returns
274274

275275

276+
def test_platform_name_from_job_info_evaluated_hostname():
277+
result = platform_name_from_job_info(
278+
PLATFORMS,
279+
{'batch system': 'background'},
280+
{'host': '$(cat tiddles)'},
281+
evaluated_host='hpc2',
282+
)
283+
assert result == 'hpc2-bg'
284+
285+
276286
def test_platform_name_from_job_info_ordered_dict_comparison():
277287
"""Check that we are only comparing set items in OrderedDictWithDefaults.
278288
"""

0 commit comments

Comments
 (0)