Source code for flux_restful.library.env
"""
The environment given to jobs and launchers.
The server's own environment must not be copied into jobs: it holds the
server's configuration and secrets (FLUX_TOKEN, FLUX_SECRET_KEY,
FLUX_TOKEN_SIGNING_KEY, ...) and in multi-user mode the job runs as someone
else. A job only needs a small set of variables to run and to talk to Flux;
the job shell provides FLUX_URI and the FLUX_JOB_* variables itself.
Operators can pass more with FLUX_JOB_ENV_PASSTHROUGH (comma separated
names or fnmatch patterns).
"""
import fnmatch
import os
from typing import Dict, Iterable, Optional
# Always passed through from the server environment, when set.
JOB_ENV_ALLOWLIST = [
"PATH",
"HOME",
"USER",
"LOGNAME",
"SHELL",
"LANG",
"LANGUAGE",
"LC_*",
"TERM",
"TZ",
"TMPDIR",
# Needed for flux python / modules when Flux is not on the default paths
"PYTHONPATH",
"LD_LIBRARY_PATH",
"MANPATH",
"LUA_PATH",
"LUA_CPATH",
# Flux runtime paths exported by flux start (never FLUX_URI: the job
# shell sets that, and never the server's FLUX_* configuration)
"FLUX_EXEC_PATH",
"FLUX_MODULE_PATH",
"FLUX_CONNECTOR_PATH",
"FLUX_PMI_LIBRARY_PATH",
]
[docs]def passthrough_patterns() -> list:
"""
Extra names or patterns from FLUX_JOB_ENV_PASSTHROUGH.
"""
value = os.environ.get("FLUX_JOB_ENV_PASSTHROUGH") or ""
return [item.strip() for item in value.split(",") if item.strip()]
[docs]def is_allowed(name: str, patterns: Iterable[str]) -> bool:
return any(fnmatch.fnmatchcase(name, pattern) for pattern in patterns)
[docs]def build_job_environment(
extra: Optional[Dict[str, str]] = None, source: Optional[Dict[str, str]] = None
) -> Dict[str, str]:
"""
The environment for a job: allowlisted server variables plus user extras.
User provided variables (from the submit request) take precedence.
"""
source = os.environ if source is None else source
patterns = JOB_ENV_ALLOWLIST + passthrough_patterns()
environment = {
name: value for name, value in source.items() if is_allowed(name, patterns)
}
for name, value in (extra or {}).items():
environment[str(name)] = str(value)
return environment
[docs]def build_helper_environment(extra: Optional[Dict[str, str]] = None) -> Dict[str, str]:
"""
The environment for processes that run on the server (not inside a job)
and must reach this Flux instance: the multi-user submit script, and
launchers such as nextflow or snakemake that submit their own jobs.
The job environment plus FLUX_URI, which the job shell would otherwise
provide.
"""
environment = build_job_environment(extra)
if "FLUX_URI" in os.environ:
environment["FLUX_URI"] = os.environ["FLUX_URI"]
return environment