Пример #1
0
def test_incorrect_environment_variables_raise_error(
        mocked_dirs_to_symlink,
        mocked_make_symlink,
        mocked_get_workflow_run_dir, mocked_expandvars):
    mocked_dirs_to_symlink.return_value = {
        'run': '$doh/cylc-run/test_workflow'}
    mocked_get_workflow_run_dir.return_value = "rund"
    mocked_expandvars.return_value = "$doh"

    with pytest.raises(WorkflowFilesError, match=r"Unable to create symlink"
                       r" to \$doh. '\$doh/cylc-run/test_workflow' contains an"
                       " invalid environment variable. Please check "
                       "configuration."):
        make_localhost_symlinks('rund', 'test_workflow')
Пример #2
0
def test_make_localhost_symlinks_calls_make_symlink_for_each_key_value_dir(
        mocked_dirs_to_symlink,
        mocked_make_symlink,
        mocked_get_workflow_run_dir, mocked_expandvars):

    mocked_dirs_to_symlink.return_value = {
        'run': '$DOH/suite3',
        'log': '$DEE/suite3/log',
        'share': '$DEE/suite3/share'}
    mocked_get_workflow_run_dir.return_value = "rund"
    mocked_expandvars.return_value = "expanded"
    make_localhost_symlinks('rund', 'suite')
    mocked_make_symlink.assert_has_calls([
        call('expanded', 'rund'),
        call('expanded', 'rund/log'),
        call('expanded', 'rund/share')
    ])
Пример #3
0
def test_make_localhost_symlinks_calls_make_symlink_for_each_key_value_dir(
        mocked_dirs_to_symlink: Mock, mocked_get_workflow_run_dir: Mock,
        monkeypatch: pytest.MonkeyPatch, monkeymock: MonkeyMock) -> None:
    mocked_dirs_to_symlink.return_value = {
        'run': '$DOH/trinity',
        'log': '$DEE/trinity/log',
        'share': '$DEE/trinity/share'
    }
    mocked_get_workflow_run_dir.return_value = "rund"
    for v in ('DOH', 'DEE'):
        monkeypatch.setenv(v, 'expanded')
    mocked_make_symlink = monkeymock('cylc.flow.pathutil.make_symlink')

    make_localhost_symlinks('rund', 'workflow')
    mocked_make_symlink.assert_has_calls([
        call('rund', 'expanded/trinity'),
        call('rund/log', 'expanded/trinity/log'),
        call('rund/share', 'expanded/trinity/share')
    ])
Пример #4
0
def register(
    flow_name: Optional[str] = None, source: Optional[str] = None
) -> str:
    """Set up workflow.
    This completes some of the set up completed by cylc install.
    Called only if running workflow that has not been installed.

    Validates workflow name.
    Validates run directory structure.
    Symlinks flow.cylc -> suite.rc.
    Creates the .service directory.

    Args:
        flow_name: workflow name, default basename($PWD).
        source: directory location of flow.cylc file, default $PWD.

    Return:
        The installed suite name (which may be computed here).

    Raise:
        WorkflowFilesError:
           - No flow.cylc or suite.rc file found in source location.
           - Illegal name (can look like a relative path, but not absolute).
           - Nested workflow run directories.
    """
    if flow_name is None:
        flow_name = Path.cwd().stem
    validate_flow_name(flow_name)
    if source is not None:
        if os.path.basename(source) == SuiteFiles.FLOW_FILE:
            source = os.path.dirname(source)
    else:
        source = os.getcwd()
    # flow.cylc must exist so we can detect accidentally reversed args.
    source = os.path.abspath(source)
    check_flow_file(source, symlink_suiterc=True)
    symlinks_created = make_localhost_symlinks(
        get_workflow_run_dir(flow_name), flow_name)
    if bool(symlinks_created):
        for src, dst in symlinks_created.items():
            LOG.info(f"Symlink created from {src} to {dst}")
    # Create service dir if necessary.
    srv_d = get_suite_srv_dir(flow_name)
    os.makedirs(srv_d, exist_ok=True)
    return flow_name
Пример #5
0
def install_workflow(
    flow_name: Optional[str] = None,
    source: Optional[Union[Path, str]] = None,
    run_name: Optional[str] = None,
    no_run_name: bool = False,
    no_symlinks: bool = False
) -> Tuple[Path, Path, str]:
    """Install a workflow, or renew its installation.

    Install workflow into new run directory.
    Create symlink to suite source location, creating any symlinks for run,
    work, log, share, share/cycle directories.

    Args:
        flow_name: workflow name, default basename($PWD).
        source: directory location of flow.cylc file, default $PWD.
        run_name: name of the run, overrides run1, run2, run 3 etc...
            If specified, cylc install will not create runN symlink.
        rundir: for overriding the default cylc-run directory.
        no_run_name: Flag as True to install workflow into
            ~/cylc-run/<flow_name>
        no_symlinks: Flag as True to skip making localhost symlink dirs

    Return:
        source: The source directory.
        rundir: The directory the workflow has been installed into.
        flow_name: The installed suite name (which may be computed here).

    Raise:
        WorkflowFilesError:
            No flow.cylc file found in source location.
            Illegal name (can look like a relative path, but not absolute).
            Another suite already has this name (unless --redirect).
            Trying to install a workflow that is nested inside of another.
    """

    if not source:
        source = Path.cwd()
    elif Path(source).name == SuiteFiles.FLOW_FILE:
        source = Path(source).parent
    source = Path(expand_path(source))
    if not flow_name:
        flow_name = Path.cwd().stem
    validate_flow_name(flow_name)
    if run_name in SuiteFiles.RESERVED_NAMES:
        raise WorkflowFilesError(
            f'Run name cannot be "{run_name}".')
    validate_source_dir(source, flow_name)
    run_path_base = Path(get_workflow_run_dir(flow_name))
    relink, run_num, rundir = get_run_dir(run_path_base, run_name, no_run_name)
    if Path(rundir).exists():
        raise WorkflowFilesError(
            f"\"{rundir}\" exists."
            " Try using cylc reinstall. Alternatively, install with another"
            " name, using the --run-name option.")
    check_nested_run_dirs(rundir, flow_name)
    symlinks_created = {}
    if not no_symlinks:
        sub_dir = flow_name
        if run_num:
            sub_dir += '/' + f'run{run_num}'
        symlinks_created = make_localhost_symlinks(rundir, sub_dir)
    INSTALL_LOG = _get_logger(rundir, 'cylc-install')
    if not no_symlinks and bool(symlinks_created) is True:
        for src, dst in symlinks_created.items():
            INSTALL_LOG.info(f"Symlink created from {src} to {dst}")
    try:
        rundir.mkdir(exist_ok=True)
    except OSError as e:
        if e.strerror == "File exists":
            raise WorkflowFilesError(f"Run directory already exists : {e}")
    if relink:
        link_runN(rundir)
    create_workflow_srv_dir(rundir)
    rsync_cmd = get_rsync_rund_cmd(source, rundir)
    proc = Popen(rsync_cmd, stdout=PIPE, stderr=PIPE, text=True)
    stdout, stderr = proc.communicate()
    INSTALL_LOG.info(f"Copying files from {source} to {rundir}")
    INSTALL_LOG.info(f"{stdout}")
    if not proc.returncode == 0:
        INSTALL_LOG.warning(
            f"An error occurred when copying files from {source} to {rundir}")
        INSTALL_LOG.warning(f" Error: {stderr}")
    cylc_install = Path(rundir.parent, SuiteFiles.Install.DIRNAME)
    check_flow_file(rundir, symlink_suiterc=True, logger=INSTALL_LOG)
    if no_run_name:
        cylc_install = Path(rundir, SuiteFiles.Install.DIRNAME)
    source_link = cylc_install.joinpath(SuiteFiles.Install.SOURCE)
    cylc_install.mkdir(parents=True, exist_ok=True)
    if not source_link.exists():
        INSTALL_LOG.info(f"Creating symlink from {source_link}")
        source_link.symlink_to(source)
    elif source_link.exists() and (os.readlink(source_link) == str(source)):
        INSTALL_LOG.info(
            f"Symlink from \"{source_link}\" to \"{source}\" in place.")
    else:
        raise WorkflowFilesError(
            "Source directory between runs are not consistent.")
    # check source link matches the source symlink from workflow dir.
    INSTALL_LOG.info(f'INSTALLED {flow_name} from {source} -> {rundir}')
    print(f'INSTALLED {flow_name} from {source} -> {rundir}')
    _close_install_log(INSTALL_LOG)
    return source, rundir, flow_name