Beispiel #1
0
    def __init__(self,
                 hosts=[],
                 envSettings={},
                 alias=None,
                 aliases=None,
                 default=False,
                 name=None,
                 *args,
                 **kwargs):
        if type(hosts) is str:
            hosts = [hosts]

        from ccapi import Configurer
        Configurer.patch(self)
        print self.fabricLogStateOutput

        env.hosts = hosts
        env.warn_only = False
        env.exceptions = ['everything']
        env.abort_exception = Exception
        for key, value in self.fabricLogStateOutput.items():
            fabric.state.output[key] = bool(value)

        for key, value in envSettings.items():
            if hasattr(env, key):
                setattr(env, key, value)

        Task.__init__(self, alias, aliases, default, name, *args, **kwargs)
 def __init__(self, name, desc='', tasks=None):
     self.name = name
     Task.__init__(self)
     self.todo = []
     if tasks is not None:
         for t in tasks:
             self.add_task(t)
     if desc:
         desc += " "
     self.__doc__ = desc
     if self.todo:
         self.__doc__ += "(%s)" % ", ".join([self.get_name(t) for t in self.todo])
Beispiel #3
0
def load_fabfile(path, importer=None):
    """
    Import given fabfile path and return (docstring, callables).

    Specifically, the fabfile's ``__doc__`` attribute (a string) and a
    dictionary of ``{'name': callable}`` containing all callables which pass
    the "is a Fabric task" test.
    """
    classic_tasks = None
    if importer is None:
        importer = __import__
    # Get directory and fabfile name
    directory, fabfile = os.path.split(path)
    # If the directory isn't in the PYTHONPATH, add it so our import will work
    added_to_path = False
    index = None
    if directory not in sys.path:
        sys.path.insert(0, directory)
        added_to_path = True
    # If the directory IS in the PYTHONPATH, move it to the front temporarily,
    # otherwise other fabfiles -- like Fabric's own -- may scoop the intended
    # one.
    else:
        i = sys.path.index(directory)
        if i != 0:
            # Store index for later restoration
            index = i
            # Add to front, then remove from original position
            sys.path.insert(0, directory)
            del sys.path[i + 1]
    # Perform the import (trimming off the .py)
    imported = importer(os.path.splitext(fabfile)[0])
    # Remove directory from path if we added it ourselves (just to be neat)
    if added_to_path:
        del sys.path[0]
    # Put back in original index if we moved it
    if index is not None:
        sys.path.insert(index + 1, directory)
        del sys.path[0]

    # Try to load classic-style tasks if no new-style tasks were auto-registered.
    if not Task.all():
        _, classic_tasks = load_tasks_from_module(imported)
        # Clean up after ourselves
        _seen.clear()

    return imported.__doc__, classic_tasks
Beispiel #4
0
def name_to_task(name):
    t = Task()
    t.name = name
    return t
Beispiel #5
0
def test_base_task_raises_exception_on_call_to_run():
    task = Task()
    task.run()
Beispiel #6
0
def test_base_task_provides_undefined_name():
    task = Task()
    eq_("undefined", task.name)
Beispiel #7
0
 def test_aliases_are_None_by_default(self):
     task = Task()
     self.assertTrue(task.aliases is None)
Beispiel #8
0
 def test_aliases_are_set_based_on_provided_aliases(self):
     aliases = ["a_%d" % i for i in range(random.randint(1, 10))]
     task = Task(aliases=aliases)
     self.assertTrue(all([a in task.aliases for a in aliases]))
Beispiel #9
0
 def test_takes_an_alias_kwarg_and_wraps_it_in_aliases_list(self):
     random_alias = "alias_%d" % random.randint(100, 200)
     task = Task(alias=random_alias)
     self.assertTrue(random_alias in task.aliases)
Beispiel #10
0
def name_to_task(name):
    t = Task()
    t.name = name
    return t
Beispiel #11
0
def main():
    """
    Main command-line execution loop.
    """
    try:
        # Parse command line options
        parser, options, arguments = parse_options()

        # Handle regular args vs -- args
        arguments = parser.largs
        remainder_arguments = parser.rargs

        # Update env with any overridden option values
        # NOTE: This needs to remain the first thing that occurs
        # post-parsing, since so many things hinge on the values in env.
        for option in env_options:
            state.env[option.dest] = getattr(options, option.dest)

        # Handle --hosts, --roles, --exclude-hosts (comma separated string => list)
        for key in ['hosts', 'roles', 'exclude_hosts']:
            if key in state.env and isinstance(state.env[key], str):
                state.env[key] = state.env[key].split(',')

        # Handle output control level show/hide
        update_output_levels(show=options.show, hide=options.hide)

        # Handle version number option
        if options.show_version:
            print("Fabric %s" % state.env.version)
            sys.exit(0)

        # Handle case where we were called bare, i.e. just "fab", and print
        # a help message.
        actions = (options.list_commands, options.shortlist, options.display,
            arguments, remainder_arguments)
        if not any(actions):
            parser.print_help()
            sys.exit(1)

        # Load settings from user settings file, into shared env dict.
        state.env.update(load_settings(state.env.rcfile))

        # Find local fabfile path or abort
        fabfile = find_fabfile()
        if not fabfile and not remainder_arguments:
            abort("Couldn't find any fabfiles!")

        # Store absolute path to fabfile in case anyone needs it
        state.env.real_fabfile = fabfile

        # Load fabfile (which calls its module-level code, including
        # tweaks to env values) and put its commands in the shared commands
        # dict
        if fabfile:
            docstring, classic_tasks = load_fabfile(fabfile)
            if classic_tasks:
                state.commands.update(classic_tasks)
            else:
                state.commands.update(Task.all())

        # Abort if no commands found
        if not state.commands and not remainder_arguments:
            abort("Fabfile didn't contain any commands!")

        # Now that we're settled on a fabfile, inform user.
        if state.output.debug:
            if fabfile:
                print("Using fabfile '%s'" % fabfile)
            else:
                print("No fabfile loaded -- remainder command only")

        # Shortlist is now just an alias for the "short" list format;
        # it overrides use of --list-format if somebody were to specify both
        if options.shortlist:
            options.list_format = 'short'

        # List available commands
        if options.list_commands:
            print("\n".join(list_commands(docstring, options.list_format)))
            sys.exit(0)

        # Handle show (command-specific help) option
        if options.display:
            display_command(options.display)

        # If user didn't specify any commands to run, show help
        if not (arguments or remainder_arguments):
            parser.print_help()
            sys.exit(0)  # Or should it exit with error (1)?

        # Parse arguments into commands to run (plus args/kwargs/hosts)
        commands_to_run = parse_arguments(arguments)

        # Parse remainders into a faux "command" to execute
        remainder_command = parse_remainder(remainder_arguments)

        # Figure out if any specified task names are invalid
        unknown_commands = []
        for tup in commands_to_run:
            if crawl(tup[0], state.commands) is None:
                unknown_commands.append(tup[0])

        # Abort if any unknown commands were specified
        if unknown_commands:
            abort("Command(s) not found:\n%s" \
                % indent(unknown_commands))

        # Generate remainder command and insert into commands, commands_to_run
        if remainder_command:
            r = '<remainder>'
            state.commands[r] = lambda: api.run(remainder_command)
            commands_to_run.append((r, [], {}, [], [], []))

        if state.output.debug:
            names = ", ".join(x[0] for x in commands_to_run)
            print("Commands to run: %s" % names)

        # At this point all commands must exist, so execute them in order.
        for name, args, kwargs, cli_hosts, cli_roles, cli_exclude_hosts in commands_to_run:
            # Get callable by itself
            task = crawl(name, state.commands)
            # Set current task name (used for some error messages)
            state.env.command = name
            # Set host list (also copy to env)
            state.env.all_hosts = hosts = get_hosts(
                task, cli_hosts, cli_roles, cli_exclude_hosts)
            # If hosts found, execute the function on each host in turn
            for host in hosts:
                # Preserve user
                prev_user = state.env.user
                # Split host string and apply to env dict
                username, hostname, port = interpret_host_string(host)
                # Log to stdout
                if state.output.running:
                    print("[%s] Executing task '%s'" % (host, name))
                # Actually run command
                _run_task(task, args, kwargs)
                # Put old user back
                state.env.user = prev_user
            # If no hosts found, assume local-only and run once
            if not hosts:
                _run_task(task, args, kwargs)
        # If we got here, no errors occurred, so print a final note.
        if state.output.status:
            print("\nDone.")
    except SystemExit:
        # a number of internal functions might raise this one.
        raise
    except KeyboardInterrupt:
        if state.output.status:
            print >> sys.stderr, "\nStopped."
        sys.exit(1)
    except:
        sys.excepthook(*sys.exc_info())
        # we might leave stale threads if we don't explicitly exit()
        sys.exit(1)
    finally:
        disconnect_all()
    sys.exit(0)
Beispiel #12
0
def test_base_task_raises_exception_on_call_to_run():
    task = Task()
    task.run()