Esempio n. 1
0
File: vc.py Progetto: wxtim/rose
def checkout():
    """CLI function: checkout."""
    opt_parser = RoseOptionParser(
        usage='rosie checkout [OPTIONS] ID ...',
        description='''
Checkout local copies of suites.

For each `ID` in the argument list, checkout a working copy of the suite
identified by `ID` to the standard location.
        ''',
    ).add_my_options("force_mode")
    opt_parser.modify_option(
        'force_mode',
        help=('If working copy for suite identified by `ID` already exists,'
              ' remove it. Continue to the next `ID` if checkout of a suite'
              ' fails.'),
    )
    opts, args = opt_parser.parse_args()
    verbosity = opts.verbosity - opts.quietness
    report = Reporter(verbosity)
    client = RosieVCClient(event_handler=report, force_mode=opts.force_mode)
    SuiteId.svn.event_handler = client.event_handler
    ret_code = 0
    for arg in args:
        try:
            client.checkout(arg)
        except (FileExistError, RosePopenError, SuiteIdPrefixError) as exc:
            ret_code = 1
            report(exc)
            if not opts.force_mode:
                sys.exit(1)
    if ret_code:
        sys.exit(ret_code)
Esempio n. 2
0
File: vc.py Progetto: wxtim/rose
def delete():
    """CLI function: delete."""
    opt_parser = RoseOptionParser(usage='rosie delete [OPTIONS] [--] [ID ...]',
                                  description='''
Delete suites.

Check the standard working copy location for a checked out suite
matching `ID` and remove it if there is no uncommitted change (or if
`--force` is specified).

Delete the suite directory structure from the HEAD of the central
repository matching the `ID`.

If no `ID` is specified and `$PWD` is a working copy of a suite, use the
`ID` of the suite in the working copy.
        ''').add_my_options("force_mode", "non_interactive", "local_only")
    opt_parser.modify_option(
        'force_mode',
        help=("Remove working copies even if there are uncommitted changes."
              "\nContinue with the next `ID` if delete of a suite fails."),
    )
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness)
    client = RosieVCClient(event_handler=report, force_mode=opts.force_mode)
    SuiteId.svn.event_handler = client.event_handler
    if not args:
        args.append(SuiteId(location=os.getcwd()))
    interactive_mode = not opts.non_interactive
    prompt = PROMPT_DELETE
    if opts.local_only:
        prompt = PROMPT_DELETE_LOCAL
    ret_code = 0
    for arg in args:
        if interactive_mode:
            try:
                response = input(prompt % arg)
            except EOFError:
                ret_code = 1
                continue
            if response == YES_TO_ALL:
                interactive_mode = False
            elif response != YES:
                ret_code = 1
                continue
        if opts.debug_mode:
            client.delete(arg, opts.local_only)
        else:
            try:
                client.delete(arg, opts.local_only)
            except (
                    LocalCopyStatusError,
                    RosePopenError,
                    SuiteIdPrefixError,
            ) as exc:
                client.event_handler(exc)
                ret_code = 1
                if not opts.force_mode:
                    sys.exit(1)
    if ret_code:
        sys.exit(ret_code)
Esempio n. 3
0
def main():
    """Implement "rose env-cat"."""
    opt_parser = RoseOptionParser(usage='rose env-cat [OPTIONS] [FILE ...]',
                                  description=r'''
Substitute environment variables in input files and print.

If no argument is specified, read from STDIN. One `FILE` argument may be
`-`, which means read from STDIN.

In `match-mode=default`, the command will look for `$NAME` or `${NAME}`
syntax and substitute them with the value of the environment variable
`NAME`. A backslash in front of the syntax, e.g. `\$NAME` or `\${NAME}`
will escape the substitution.

In `match-mode=brace`, the command will look for `${NAME}` syntax only.

EXAMPLES
    rose env-cat [OPTIONS] [FILE ...]
        ''')
    opt_parser.add_my_options("match_mode", "output_file", "unbound")
    opt_parser.modify_option(
        'output_file',
        help=("Specify an output file."
              "\nIf no output file is specified or if `FILE`"
              "is `-`, write output to STDOUT."),
    )
    opts, args = opt_parser.parse_args()
    rose_env_cat(args, opts)
Esempio n. 4
0
def main():
    """Implement "rose env-cat"."""
    opt_parser = RoseOptionParser(usage='rose env-cat [OPTIONS] [FILE ...]',
                                  description=r'''
Substitute environment variables in input files and print.

If no argument is specified, read from STDIN. One `FILE` argument may be
`-`, which means read from STDIN.

In `match-mode=default`, the command will look for `$NAME` or `${NAME}`
syntax and substitute them with the value of the environment variable
`NAME`. A backslash in front of the syntax, e.g. `\$NAME` or `\${NAME}`
will escape the substitution.

In `match-mode=brace`, the command will look for `${NAME}` syntax only.

EXAMPLES
    rose env-cat [OPTIONS] [FILE ...]
        ''')
    opt_parser.add_my_options("match_mode", "output_file", "unbound")
    opt_parser.modify_option(
        'output_file',
        help=("Specify an output file."
              "\nIf no output file is specified or if `FILE`"
              "is `-`, write output to STDOUT."),
    )
    opts, args = opt_parser.parse_args()
    if not args:
        args = ["-"]
    if not opts.output_file or opts.output_file == "-":
        out_handle = sys.stdout
    else:
        out_handle = open(opts.output_file, "wb")
    for arg in args:
        if arg == "-":
            in_handle = sys.stdin
        else:
            in_handle = open(arg)
        line_num = 0
        while True:
            line_num += 1
            line = in_handle.readline()
            if not line:
                break
            try:
                out_handle.write(
                    env_var_process(line, opts.unbound, opts.match_mode))
            except UnboundEnvironmentVariableError as exc:
                name = arg
                if arg == "-":
                    name = "<STDIN>"
                sys.exit("%s:%s: %s" % (name, line_num, str(exc)))
        in_handle.close()
    out_handle.close()
Esempio n. 5
0
def list_local_suites():
    """CLI command to list all the locally checked out suites"""
    opt_parser = RoseOptionParser(description='''
List the local suites.

Search for locally checked out suites and print their details.

The default format includes a local working copy status field (`%local`)
in the first column.
A blank field means there is no related suite checked out.

* `=` means that the suite is checked out at this branch and revision.
* `<` means that the suite is checked out but at an older revision.
* `>` means that the suite is checked out but at a newer revision.
* `S` means that the suite is checked out but on a different branch.
* `M` means that the suite is checked out and modified.
* `X` means that the suite is checked out but is corrupted.
        ''', ).add_my_options("no_headers", "prefixes", "print_format",
                              "reverse", "sort", "user")
    opt_parser.modify_option(
        'verbosity',
        help=('Display full info for each returned suite.'),
    )
    opts = opt_parser.parse_args()[0]
    report = Reporter(opts.verbosity - opts.quietness)

    if opts.user:
        alternative_roses_dir = SuiteId.get_local_copy_root(opts.user)
        report(UserSpecificRoses(alternative_roses_dir), prefix=None)

    ws_client = RosieWSClient(prefixes=opts.prefixes, event_handler=report)
    if ws_client.unreachable_prefixes:
        bad_prefix_string = " ".join(ws_client.unreachable_prefixes)
        report(
            RosieWSClientError(
                ERR_PREFIX_UNREACHABLE.format(bad_prefix_string)))
    _display_maps(opts, ws_client, ws_client.query_local_copies(opts.user))
Esempio n. 6
0
def main():
    """Implement the "rose host-select" command."""
    opt_parser = RoseOptionParser(
        usage='rose host-select [OPTIONS] [GROUP/HOST ...]',
        description='''
Select a host from a set of groups or names by load, by free memory
or by random.

Print the selected host name.
        ''',
        epilog='''
RANKING METHODS IN DETAIL (--rank-method):
    `load`
        Rank by average load as reported by `uptime` divided by
        number of virtual processors.

        If `METHOD-ARG` is specified, it must be `1`, `5` or `15`.
        The default is to use the 15 minute load.
    `fs`
        Rank by % usage of a file system as reported by `df`.

        `METHOD-ARG` must be a valid file system in all the given
        hosts and host groups. The default is to use the `~`
        directory.
    `mem`
        Rank by largest amount of free memory. Uses `free -m` to
        return memory in Mb
    `random`
        No ranking is used.

CONFIGURATION
    The command reads its settings from the `[rose-host-select]` section in
    the Rose configuration. All settings are optional. Type
    `rose config rose-host-select` to print settings.

    Valid settings are:

    default = GROUP/HOST ...
       The default arguments to use for this command.
    group{NAME} = GROUP/HOST ...
       Declare a named group of hosts.
    method{NAME} = METHOD[:METHOD-ARG]
       Declare the default ranking method for a group of hosts.
    thresholds{NAME} = [METHOD[:METHOD-ARG]:]VALUE ...
       Declare the default threshold(s) for a group of hosts.
    timeout = FLOAT
       Set the timeout in seconds of SSH commands to hosts.
       (default=10.0)
        '''
    )
    opt_parser.add_my_options("choice", "rank_method", "thresholds", "timeout")
    opt_parser.modify_option(
        'timeout',
        help='Set the timeout in seconds of SSH commands to hosts.',
    )
    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness)
    popen = RosePopener(event_handler=report)
    select = HostSelector(event_handler=report, popen=popen)
    try:
        host_score_list = select(
            names=args,
            rank_method=opts.rank_method,
            thresholds=opts.thresholds,
            ssh_cmd_timeout=opts.timeout,
        )
    except (NoHostError, NoHostSelectError) as exc:
        report(exc)
        if opts.debug_mode:
            traceback.print_exc()
        sys.exit(1)
    opts.choice = int(opts.choice)
    report(choice(host_score_list[0 : opts.choice])[0] + "\n", level=0)
Esempio n. 7
0
def main():
    """Implement the "rose config" command."""
    opt_parser = RoseOptionParser(description='''
Parse and print rose configuration files.

With no option and no argument, print the rose site + user configuration.

EXAMPLES
    # Print the value of OPTION in SECTION.
    rose config SECTION OPTION

    # Print the value of OPTION in SECTION in FILE.
    rose config --file=FILE SECTION OPTION

    # Print the value of OPTION in SECTION if exists, or VALUE otherwise.
    rose config --default=VALUE SECTION OPTION

    # Print the OPTION=VALUE pairs in SECTION.
    rose config SECTION

    # Print the value of a top level OPTION.
    rose config OPTION

    # Print the OPTION keys in SECTION.
    rose config --keys SECTION

    # Print the SECTION keys.
    rose config --keys

    # Exit with 0 if OPTION exists in SECTION, or 1 otherwise.
    rose config -q SECTION OPTION

    # Exit with 0 if SECTION exists, or 1 otherwise.
    rose config -q SECTION

    # Combine the configurations in FILE1 and FILE2, and dump the result.
    rose config --file=FILE1 --file=FILE2

    # Print the value of OPTION in SECTION of the metadata associated with
    # the specified config FILE
    rose config --file=FILE --meta SECTION OPTION

    # Print the value of a specified metadata KEY
    rose config --meta-key=KEY
        ''',
                                  epilog='''
ENVIRONMENT VARIABLES
    optional ROSE_META_PATH
        Prepend `$ROSE_META_PATH` to the metadata search path.
        ''')
    opt_parser.add_my_options(
        "default",
        "env_var_process_mode",
        "files",
        "keys",
        "meta",
        "meta_key",
        "no_ignore",
        "no_opts",
        "print_conf_mode",
    )
    # the quietness argument is non-standard for this command
    opt_parser.modify_option(
        'quietness',
        help=("Exit with 0 if the specified `SECTION` and/or `OPTION` exist in"
              " the configuration, or 1 otherwise."),
    )

    opts, args = opt_parser.parse_args()
    report = Reporter(opts.verbosity - opts.quietness)
    metomi.rose.macro.add_meta_paths()

    if opts.meta_key:
        opts.meta = True

    if opts.files and opts.meta_key:
        report(Exception("Cannot specify both a file and meta key."))
        sys.exit(1)

    config_loader = ConfigLoader()
    sources = []
    if opts.files:
        root_node = ConfigNode()
        for fname in opts.files:
            if fname == "-":
                sources.append(sys.stdin)
            else:
                if opts.meta:
                    try:
                        root_node = config_loader.load(fname)
                    except ConfigSyntaxError as exc:
                        report(exc)
                        sys.exit(1)
                    rel_path = os.sep.join(fname.split(os.sep)[:-1])
                    fpath = get_meta_path(root_node, rel_path)
                    if fpath is None:
                        report(MetadataNotFoundEvent(fname))
                    else:
                        sources.append(fpath)
                else:
                    sources.append(fname)
    elif opts.meta:
        root_node = ConfigNode()
        if opts.meta_key:
            root_node.set(["meta"], opts.meta_key)
        else:
            fname = os.path.join(os.getcwd(), metomi.rose.SUB_CONFIG_NAME)
            try:
                root_node = config_loader.load(fname)
            except ConfigSyntaxError as exc:
                report(exc)
                sys.exit(1)
        fpath = get_meta_path(root_node, meta_key=opts.meta_key)
        root_node.unset(["meta"])
        if fpath is None:
            report(Exception("Metadata not found"))
            sys.exit(1)
        else:
            sources.append(fpath)
    else:
        root_node = ResourceLocator.default().get_conf()

    for source in sources:
        try:
            if opts.meta or opts.no_opts:
                config_loader.load(source, root_node)
            else:
                config_loader.load_with_opts(source, root_node)
        except (ConfigSyntaxError, IOError) as exc:
            report(exc)
            sys.exit(1)
        if source is sys.stdin:
            source.close()

    if opts.quietness:
        sys.exit(root_node.get(args, opts.no_ignore) is None)

    if opts.keys_mode:
        try:
            keys = list(root_node.get(args, opts.no_ignore).value)
        except AttributeError:
            sys.exit(1)
        keys.sort()
        for key in keys:
            print(key)
        sys.exit()

    conf_dump = ConfigDumper()
    if len(args) == 0:
        conf_dump(root_node, concat_mode=opts.print_conf_mode)
        sys.exit()

    node = root_node.get(args, opts.no_ignore)

    if node is not None and isinstance(node.value, dict):
        if opts.print_conf_mode:
            conf_dump(ConfigNode().set(args, node.value), concat_mode=True)
            sys.exit()

        keys = list(node.value)
        keys.sort()
        for key in keys:
            node_of_key = node.get([key], opts.no_ignore)
            if node_of_key:
                value = node_of_key.value
                state = node_of_key.state
                string = "%s%s=%s" % (state, key, value)
                lines = string.splitlines()
                print(lines[0])
                i_equal = len(state + key) + 1
                for line in lines[1:]:
                    print(" " * i_equal + line)
        sys.exit()

    if node is None:
        if opts.default is None:
            sys.exit(1)
        value = opts.default
    elif opts.env_var_process_mode:
        value = env_var_process(node.value)
    else:
        value = node.value
    if opts.print_conf_mode:
        conf_dump(ConfigNode().set(args, value), concat_mode=True)
    else:
        print(value)
    sys.exit()