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 (comma separated string => list) for key in ['hosts', 'roles']: 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) # 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: 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 commands.update(load_fabfile(fabfile)) # Abort if no commands found if not 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: print("Using fabfile '%s'" % fabfile) # Handle list-commands option (now that commands are loaded) if options.list_commands: list_commands() # 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 tup[0] not in commands: 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>' commands[r] = lambda: api.run(remainder_command) commands_to_run.append((r, [], {}, [], [])) # At this point all commands must exist, so execute them in order. for name, args, kwargs, cli_hosts, cli_roles in commands_to_run: # Get callable by itself command = commands[name] # Set current command name (used for some error messages) state.env.command = name # Set host list (also copy to env) state.env.all_hosts = hosts = get_hosts( command, cli_hosts, cli_roles) # If hosts found, execute the function on each host in turn for host in hosts: username, hostname, port = normalize(host) state.env.host_string = host state.env.host = hostname # Preserve user prev_user = state.env.user state.env.user = username state.env.port = port # Log to stdout if state.output.running: print("[%s] Executing task '%s'" % (host, name)) # Actually run command commands[name](*args, **kwargs) # Put old user back state.env.user = prev_user # If no hosts found, assume local-only and run once if not hosts: commands[name](*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: # Explicitly disconnect from all servers for key in connections.keys(): if state.output.status: print "Disconnecting from %s..." % denormalize(key), connections[key].close() if state.output.status: print "done." sys.exit(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: env[option.dest] = getattr(options, option.dest) # Handle --hosts, --roles (comma separated string => list) for key in ['hosts', 'roles']: if key in env and isinstance(env[key], str): env[key] = 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" % env.version) sys.exit(0) # Load settings from user settings file, into shared env dict. env.update(load_settings(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 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, callables = load_fabfile(fabfile) commands.update(callables) # Autocompletion support autocomplete_items = [cmd.replace('_', '-') for cmd in commands] if 'autocomplete' in env: autocomplete_items += env.autocomplete autocomplete(parser, ListCompleter(autocomplete_items)) # Handle hooks related options _disable_hooks = options.disable_hooks _enable_hooks = options.enable_hooks if _disable_hooks: for _hook in _disable_hooks.strip().split(): DISABLED_HOOKS.append(_hook.strip()) if _enable_hooks: for _hook in _enable_hooks.strip().split(): ENABLED_HOOKS.append(_hook.strip()) # Handle the non-execution flow if not arguments and not remainder_arguments: # Non-verbose command list if options.shortlist: shortlist() # Handle show (command-specific help) option if options.display: display_command(options.display) # Else, show the list of commands and exit list_commands(docstring) # Now that we're settled on a fabfile, inform user. if output.debug: if fabfile: print("Using fabfile '%s'" % fabfile) else: print("No fabfile loaded -- remainder command only") # Parse arguments into commands to run (plus args/kwargs/hosts) commands_to_run, env_update = parse_arguments(arguments) env.update(env_update) # 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 tup[0] not in commands: 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>' commands[r] = lambda: api.run(remainder_command) commands_to_run.append((r, [], {}, [], [])) if output.debug: names = ", ".join(x[0] for x in commands_to_run) print("Commands to run: %s" % names) call_hooks('commands.before', commands, commands_to_run) # Initialse context runner env() # Initialise the default stage if none are given as the first command. if 'stages' in env: if commands_to_run[0][0] not in env.stages: execute_command( (env.stages[0], (), {}, None, None, None), commands ) else: execute_command(commands_to_run.pop(0), commands) if env.config_file: config_path = realpath(expanduser(env.config_file)) config_path = join(dirname(fabfile), config_path) config_file = open(config_path, 'rb') config = load_yaml(config_file.read()) if not config: env.config = AttributeDict() elif not isinstance(config, dict): abort("Invalid config file found at %s" % config_path) else: env.config = AttributeDict(config) config_file.close() call_hooks('config.loaded') first_time_env_call = 1 # At this point all commands must exist, so execute them in order. for spec in commands_to_run: execute_command(spec, commands) # If we got here, no errors occurred, so print a final note. if output.status: msg = "\nDone." if env.colors: msg = env.color_settings['finish'](msg) print(msg) except SystemExit: # a number of internal functions might raise this one. raise except KeyboardInterrupt: if output.status: msg = "\nStopped." if env.colors: msg = env.color_settings['finish'](msg) print >> sys.stderr, msg sys.exit(1) except: sys.excepthook(*sys.exc_info()) # we might leave stale threads if we don't explicitly exit() sys.exit(1) finally: call_hooks('commands.after') disconnect_all() sys.exit(0)
:type config_params: dict """ try: if isinstance(name, ModuleType): m = name name = m.__name__ else: m = import_module("{0}.{1}".format(NAME_LIB, name)) except Exception, e: abort("Can't import recipe {0}: {1}".format(name, e)) docstring, new_style, classic, default = load_tasks_from_module(m) tasks = new_style if env.new_style_tasks else classic _configure_module_config(m, _namespace_from(m), config_params) commands.update(_make_recipe_dict(tasks, _namespace_from(namespace))) puts("{0} recipe configured".format(name)) return True def _recipe_repr(recipe): """Configure recipe :param recipe: recipe item (list, string) :type param: string, tuple, list """ if isinstance(recipe, (str, unicode)): return recipe elif isinstance(recipe, ModuleType): return recipe.__name__ elif isinstance(recipe, (tuple, list)):
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 (comma separated string => list) for key in ['hosts', 'roles']: 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, callables = load_fabfile(fabfile) commands.update(callables) # Abort if no commands found if not 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") # Non-verbose command list if options.shortlist: shortlist() # Handle list-commands option (now that commands are loaded) if options.list_commands: list_commands(docstring) # 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 tup[0] not in commands: 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>' 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 in commands_to_run: # Get callable by itself command = commands[name] # Set current command name (used for some error messages) state.env.command = name # Set host list (also copy to env) state.env.all_hosts = hosts = get_hosts(command, cli_hosts, cli_roles) # 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 commands[name](*args, **kwargs) # If interpret_host_string modified the user, restore it if state.env.user == username: state.env.user = prev_user # If no hosts found, assume local-only and run once if not hosts: commands[name](*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)