def test_argument_parsing(): for args, output in [ # Basic ('abc', ('abc', [], {}, [], [], [])), # Arg ('ab:c', ('ab', ['c'], {}, [], [], [])), # Kwarg ('a:b=c', ('a', [], {'b':'c'}, [], [], [])), # Arg and kwarg ('a:b=c,d', ('a', ['d'], {'b':'c'}, [], [], [])), # Multiple kwargs ('a:b=c,d=e', ('a', [], {'b':'c','d':'e'}, [], [], [])), # Host ('abc:host=foo', ('abc', [], {}, ['foo'], [], [])), # Hosts with single host ('abc:hosts=foo', ('abc', [], {}, ['foo'], [], [])), # Hosts with multiple hosts # Note: in a real shell, one would need to quote or escape "foo;bar". # But in pure-Python that would get interpreted literally, so we don't. ('abc:hosts=foo;bar', ('abc', [], {}, ['foo', 'bar'], [], [])), # Exclude hosts ('abc:hosts=foo;bar,exclude_hosts=foo', ('abc', [], {}, ['foo', 'bar'], [], ['foo'])), ('abc:hosts=foo;bar,exclude_hosts=foo;bar', ('abc', [], {}, ['foo', 'bar'], [], ['foo','bar'])), # Empty string args ("task:x=y,z=", ('task', [], {'x': 'y', 'z': ''}, [], [], [])), ("task:foo,,x=y", ('task', ['foo', ''], {'x': 'y'}, [], [], [])), ]: yield eq_, parse_arguments([args]), [output]
def test_argument_parsing(): for args, output in [ # Basic ("abc", ("abc", [], {}, [], [], [])), # Arg ("ab:c", ("ab", ["c"], {}, [], [], [])), # Kwarg ("a:b=c", ("a", [], {"b": "c"}, [], [], [])), # Arg and kwarg ("a:b=c,d", ("a", ["d"], {"b": "c"}, [], [], [])), # Multiple kwargs ("a:b=c,d=e", ("a", [], {"b": "c", "d": "e"}, [], [], [])), # Host ("abc:host=foo", ("abc", [], {}, ["foo"], [], [])), # Hosts with single host ("abc:hosts=foo", ("abc", [], {}, ["foo"], [], [])), # Hosts with multiple hosts # Note: in a real shell, one would need to quote or escape "foo;bar". # But in pure-Python that would get interpreted literally, so we don't. ("abc:hosts=foo;bar", ("abc", [], {}, ["foo", "bar"], [], [])), # Exclude hosts ("abc:hosts=foo;bar,exclude_hosts=foo", ("abc", [], {}, ["foo", "bar"], [], ["foo"])), ("abc:hosts=foo;bar,exclude_hosts=foo;bar", ("abc", [], {}, ["foo", "bar"], [], ["foo", "bar"])), # Empty string args ("task:x=y,z=", ("task", [], {"x": "y", "z": ""}, [], [], [])), ("task:foo,,x=y", ("task", ["foo", ""], {"x": "y"}, [], [], [])), ]: yield eq_, parse_arguments([args]), [output]
def test_argument_parsing(): for args, output in [ # Basic ('abc', ('abc', [], {}, [], [])), # Arg ('ab:c', ('ab', ['c'], {}, [], [])), # Kwarg ('a:b=c', ('a', [], {'b':'c'}, [], [])), # Arg and kwarg ('a:b=c,d', ('a', ['d'], {'b':'c'}, [], [])), # Multiple kwargs ('a:b=c,d=e', ('a', [], {'b':'c','d':'e'}, [], [])), # Host ('abc:host=foo', ('abc', [], {}, ['foo'], [])), # Hosts with single host ('abc:hosts=foo', ('abc', [], {}, ['foo'], [])), # Hosts with multiple hosts # Note: in a real shell, one would need to quote or escape "foo;bar". # But in pure-Python that would get interpreted literally, so we don't. ('abc:hosts=foo;bar', ('abc', [], {}, ['foo', 'bar'], [])), # Empty string args ("task:x=y,z=", ('task', [], {'x': 'y', 'z': ''}, [], [])), ("task:foo,,x=y", ('task', ['foo', ''], {'x': 'y'}, [], [])), ]: yield eq_, parse_arguments([args]), [output]
def get_commands(): """ Attempts to figure out what commands the user wants to run, returning a list of tuples of: (cmd_name, args, kwargs, hosts, roles, exclude_hosts) """ # Note: Most of this is lifted from fabric.main from fabric import state, api from fabric.main import parse_options, parse_arguments, parse_remainder # Parse command line options parser, options, arguments = parse_options() # Handle regular args vs -- args arguments = parser.largs remainder_arguments = parser.rargs # 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) # Generate remainder command and insert into commands, commands_to_run if remainder_command: commands_to_run.append(('<shell>', [remainder_command], {}, [], [], [])) return commands_to_run
def ec2_fab(service, args): """ Run Fabric commands against EC2 instances """ instance_ids = args.instances instances = service.list(elb=args.elb, instance_ids=instance_ids) hosts = service.resolve_hosts(instances) fab.env.hosts = hosts fab.env.key_filename = settings.get('SSH', 'KEY_FILE') fab.env.user = settings.get('SSH', 'USER', getpass.getuser()) fab.env.parallel = True fabfile = find_fabfile(args.file) if not fabfile: print 'Couldn\'t find any fabfiles!' return fab.env.real_fabile = fabfile docstring, callables, default = load_fabfile(fabfile) fab_state.commands.update(callables) commands_to_run = parse_arguments(args.methods) for name, args, kwargs, arg_hosts, arg_roles, arg_exclude_hosts in commands_to_run: fab.execute(name, hosts=arg_hosts, roles=arg_roles, exclude_hosts=arg_exclude_hosts, *args, **kwargs)
def test_escaped_task_kwarg_split(): """ Allow backslashes to escape the = in x=y task kwargs """ argstr = r"cmd:arg,escaped\,arg,nota\=kwarg,regular=kwarg,escaped=regular\=kwarg" args = ["arg", "escaped,arg", "nota=kwarg"] kwargs = {"regular": "kwarg", "escaped": "regular=kwarg"} eq_(parse_arguments([argstr])[0], ("cmd", args, kwargs, [], [], []))
def test_escaped_task_kwarg_split(): """ Allow backslashes to escape the = in x=y task kwargs """ argstr = r"cmd:arg,escaped\,arg,nota\=kwarg,regular=kwarg,escaped=regular\=kwarg" args = ['arg', 'escaped,arg', 'nota=kwarg'] kwargs = {'regular': 'kwarg', 'escaped': 'regular=kwarg'} eq_( parse_arguments([argstr])[0], ('cmd', args, kwargs, [], [], []), )
def gentleman(): args_dict = docopt(__doc__, version=__version__) arguments = args_dict['COMMAND'] if not os.path.exists(os.path.join(os.getcwd(), '.gentle.yaml')): if arguments != ['init']: print(red('This is not a gentle directory, Make sure this is the correct' # noqa 'directory, and use `gt init` Initialization')) return sys.exit(1) else: init() arguments = args_dict['COMMAND'] try: # state.env.update(load_settings(state.env.rcfile)) fabfile = os.path.join(here, 'gt') state.env.real_fabfile = fabfile default = None if fabfile: docstring, callables, default = load_fabfile(fabfile) state.commands.update(callables) commands_to_run = parse_arguments(arguments) unknown_commands = [] for tup in commands_to_run: if crawl(tup[0], state.commands) is None: unknown_commands.append(tup[0]) if args_dict['--list']: show_commands(docstring, 'normal', 1) for type in ['show', 'hide']: t = args_dict['--' + type] if t is not None: hide = True if type == 'hide' else False set_output(t, hide=hide, only=args_dict['--only']) # Abort if any unknown commands were specified if unknown_commands: warn("Command(s) not found:\n%s" % indent(unknown_commands)) show_commands(None, 'normal', 1) for name, args, kwargs, arg_hosts, arg_roles, arg_exclude_hosts in \ commands_to_run: execute( name, hosts=arg_hosts, roles=arg_roles, exclude_hosts=arg_exclude_hosts, *args, **kwargs) if state.output.status: print("\nDone.") except SystemExit: raise except KeyboardInterrupt: if state.output.status: sys.stderr.write("\nStopped.\n") sys.exit(1) except: sys.excepthook(*sys.exc_info()) sys.exit(1) finally: disconnect_all() sys.exit(0)
def run(): try: # Parse command line options parser, options, arguments = parse_options() # Handle regular args vs -- args arguments = parser.largs if len(arguments) > 1: abort("You can call only one command!") if arguments: tmp_parts = arguments[0].split(':') parts = tmp_parts[0].split('.') if not command_exists(parts): print print 'Warning: command not found!' print return fabfile_locations = ['%s.py' % os.path.join(satellite.commands.__path__[0], *parts[:-1])] arguments[0] = parts[-1] + ''.join(":%s" % i for i in tmp_parts[1:]) else: print "Command tree:" print_tree_commands() return # 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] = option.default # 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], basestring): state.env[key] = state.env[key].split(',') # Load settings from user settings file, into shared env dict. settings.update(load_settings(options.configfile)) state.env.update(settings.fabric) # Find local fabfile path or abort fabfile = find_fabfile(fabfile_locations) if not fabfile: abort("""Couldn't find any fabfiles! Use -h for help.""") # 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 default = None if fabfile: docstring, callables, default = load_fabfile(fabfile) state.commands.update(callables) # Abort if no commands found if not state.commands: 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") # Parse arguments into commands to run (plus args/kwargs/hosts) commands_to_run = parse_arguments(arguments) 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, arg_hosts, arg_roles, arg_exclude_hosts in commands_to_run: execute( name, hosts=arg_hosts, roles=arg_roles, exclude_hosts=arg_exclude_hosts, *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: sys.stderr.write("\nStopped.\n") 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)