示例#1
0
    def _inspect_query_attribute(self):
        console = Console(self.shell.pty)
        query = Inspector(self.node).get_query(self.attr_name).query

        def run():
            yield termcolor.colored('  Node:       ', 'cyan') + \
                  termcolor.colored(Inspector(self.node).get_full_name(), 'yellow')
            yield termcolor.colored('  Filename:   ', 'cyan') + \
                  termcolor.colored(query._filename, 'yellow')
            yield termcolor.colored('  Line:       ', 'cyan') + \
                  termcolor.colored(query._line, 'yellow')
            yield termcolor.colored('  Expression: ', 'cyan') + \
                  termcolor.colored(repr(query.query), 'yellow')
            yield ''

            # Execute query in sandboxed environment.
            yield 'Trace query:'
            try:
                insp = Inspector(self._get_env())
                result = insp.trace_query(self.attr_name)
            except Exception as e:
                yield 'Failed to execute query: %r' % e
                return

            # Print query and all subqueries with their results.
            for subquery in result.walk_through_subqueries():
                yield termcolor.colored(repr(subquery[0]), 'cyan')
                yield '    %s' % subquery[1]

        console.lesspipe(run())
示例#2
0
def pty_based_auth(auth_backend, pty):
    """
    Show a username/password login prompt.
    Return username when authentication succeeded.
    """
    tries = 0
    while True:
        # Password authentication required for this session?
        sys.stdout.write('\033[2J\033[0;0H')  # Clear screen
        sys.stdout.write(colored('Please authenticate\r\n\r\n', 'cyan'))

        if tries:
            sys.stdout.write(
                colored('  Authentication failed, try again\r\n', 'red'))

        try:
            console = Console(pty)
            username = console.input('Username', False)
            password = console.input('Password', True)
        except NoInput:
            raise NotAuthenticated

        if auth_backend.authenticate(username, password):
            sys.stdout.write(
                colored(' ' * 40 + 'Authentication successful\r\n\r\n',
                        'green'))
            return username
        else:
            tries += 1
            if tries == 3:
                raise NotAuthenticated
示例#3
0
 def fill_cache(self, pty):
     """ Fill cache for current directory. """
     console = Console(pty)
     with console.progress_bar('Reading directory...', clear_on_finish=True):
         cwd = self.getcwd()
         for s in self.listdir_stat():
             self._stat_cache[(cwd, s.filename)] = s
示例#4
0
            def read(rf, size=-1):
                if rf._is_open:
                    # Always read in chunks of 1024 bytes and show a progress bar.

                    # Create progress bar.
                    p = Console(self.pty).progress_bar('Downloading data',
                            expected=(size if size >= 0 else None))
                    result = StringIO()

                    with p:
                        while True:
                            if size == 0:
                                break
                            elif size < 0:
                                # If we have to read until EOF, keep reaeding
                                # in chunks of 1024
                                chunk = rf._file.read(1024)
                            else:
                                # If we have to read for a certain size, read
                                # until we reached that size.
                                read_size = min(1024, size)
                                chunk = rf._file.read(read_size)
                                size -= len(chunk)

                            if not chunk: break # EOF
                            result.write(chunk)
                            p.set_progress(result.len)

                    return result.getvalue()
                else:
                    raise IOError('Cannot read from closed remote file')
示例#5
0
    def _inspect_query_attribute(self):
        console = Console(self.shell.pty)
        query = Inspector(self.node).get_query(self.attr_name).query

        def run():
            yield termcolor.colored('  Node:       ', 'cyan') + \
                  termcolor.colored(Inspector(self.node).get_full_name(), 'yellow')
            yield termcolor.colored('  Filename:   ', 'cyan') + \
                  termcolor.colored(query._filename, 'yellow')
            yield termcolor.colored('  Line:       ', 'cyan') + \
                  termcolor.colored(query._line, 'yellow')
            yield termcolor.colored('  Expression: ', 'cyan') + \
                  termcolor.colored(repr(query.query), 'yellow')
            yield ''

            # Execute query in sandboxed environment.
            yield 'Trace query:'
            try:
                insp = Inspector(self._get_env())
                result = insp.trace_query(self.attr_name)
            except Exception as e:
                yield 'Failed to execute query: %r' % e
                return

            # Print query and all subqueries with their results.
            for subquery in result.walk_through_subqueries():
                yield termcolor.colored(repr(subquery[0]), 'cyan')
                yield '    %s' % subquery[1]

        console.lesspipe(run())
示例#6
0
            def read(rf, size=-1):
                if rf._is_open:
                    # Always read in chunks of 1024 bytes and show a progress bar.

                    # Create progress bar.
                    p = Console(self.pty).progress_bar(
                        'Downloading data',
                        expected=(size if size >= 0 else None))
                    result = StringIO()

                    with p:
                        while True:
                            if size == 0:
                                break
                            elif size < 0:
                                # If we have to read until EOF, keep reaeding
                                # in chunks of 1024
                                chunk = rf._file.read(1024)
                            else:
                                # If we have to read for a certain size, read
                                # until we reached that size.
                                read_size = min(1024, size)
                                chunk = rf._file.read(read_size)
                                size -= len(chunk)

                            if not chunk: break  # EOF
                            result.write(chunk)
                            p.set_progress(result.len)

                    return result.getvalue()
                else:
                    raise IOError('Cannot read from closed remote file')
示例#7
0
    def __call__(self):
        w = self.shell.stdout.write
        console = Console(self.shell.pty)

        def run():
            # Print nodes
            if Inspector(self.node).get_childnodes():
                yield 'Child nodes:'

                def column_iterator():
                    for c in Inspector(self.node).get_childnodes():
                        name = Inspector(c).get_name()
                        yield termcolor.colored(
                            name,
                            type_of_node(c).color), len(name)

                for line in console.in_columns(column_iterator()):
                    yield line

            # Print actions
            if Inspector(self.node).get_actions():
                yield 'Actions:'

                def column_iterator():
                    for a in Inspector(self.node).get_actions():
                        yield termcolor.colored(a.name,
                                                type_of_action(a).color), len(
                                                    a.name)

                for line in console.in_columns(column_iterator()):
                    yield line

        console.lesspipe(run())
示例#8
0
    def __call__(self):
        options = []

        for m in self.node.__class__.__mro__:
            if m.__module__ != 'deployer.node' and m != object:
                options.append(
                    ('%s.%s' % (termcolor.colored(m.__module__, 'red'),
                                termcolor.colored(m.__name__, 'yellow')), m))

        if len(options) > 1:
            try:
                node_class = Console(self.shell.pty).choice(
                    'Choose node definition', options)
            except NoInput:
                return
        else:
            node_class = options[0][1]

        def run():
            try:
                # Retrieve source
                source = inspect.getsource(node_class)

                # Highlight code
                source = highlight(source, PythonLexer(), TerminalFormatter())

                for l in source.split('\n'):
                    yield l.rstrip('\n')
            except IOError:
                yield 'Could not retrieve source code.'

        Console(self.shell.pty).lesspipe(run())
示例#9
0
def pty_based_auth(auth_backend, pty):
    """
    Show a username/password login prompt.
    Return username when authentication succeeded.
    """
    tries = 0
    while True:
        # Password authentication required for this session?
        sys.stdout.write('\033[2J\033[0;0H') # Clear screen
        sys.stdout.write(colored('Please authenticate\r\n\r\n', 'cyan'))

        if tries:
            sys.stdout.write(colored('  Authentication failed, try again\r\n', 'red'))

        try:
            console = Console(pty)
            username = console.input('Username', False)
            password = console.input('Password', True)
        except NoInput:
            raise NotAuthenticated

        if auth_backend.authenticate(username, password):
            sys.stdout.write(colored(' ' * 40 + 'Authentication successful\r\n\r\n', 'green'))
            return username
        else:
            tries += 1
            if tries == 3:
                raise NotAuthenticated
示例#10
0
    def __call__(self):
        w = self.shell.stdout.write
        console = Console(self.shell.pty)

        def run():
            # Print nodes
            if Inspector(self.node).get_childnodes():
                yield 'Child nodes:'

                def column_iterator():
                    for c in Inspector(self.node).get_childnodes():
                        name = Inspector(c).get_name()
                        yield termcolor.colored(name, type_of_node(c).color), len(name)
                for line in console.in_columns(column_iterator()):
                    yield line

            # Print actions
            if Inspector(self.node).get_actions():
                yield 'Actions:'

                def column_iterator():
                    for a in Inspector(self.node).get_actions():
                        yield termcolor.colored(a.name, type_of_action(a).color), len(a.name)
                for line in console.in_columns(column_iterator()):
                    yield line

        console.lesspipe(run())
示例#11
0
 def fill_cache(self, pty):
     """ Fill cache for current directory. """
     console = Console(pty)
     with console.progress_bar('Reading directory...',
                               clear_on_finish=True):
         cwd = self.getcwd()
         for s in self.listdir_stat():
             self._stat_cache[(cwd, s.filename)] = s
示例#12
0
 def _create_connect_progress_bar(self, host):
     from deployer.console import ProgressBarSteps
     console = Console(host.pty)
     return console.progress_bar_with_steps('Connecting %s (%s)' % (host.address, host.slug),
             steps=ProgressBarSteps({
                 1: "Resolving DNS",
                 2: "Creating socket",
                 3: "Creating transport",
                 4: "Exchanging keys",
                 5: "Authenticating" }),
             format_str="%(message)s: %(counter)s/%(expected)s %(status)s")
示例#13
0
    def _inspect_action(self):
        console = Console(self.shell.pty)
        action = Inspector(self.node).get_action(self.attr_name)

        def run():
            yield termcolor.colored('  Action name:   ', 'cyan') + \
                  termcolor.colored(self.attr_name, 'yellow')
            yield termcolor.colored('  __repr__:      ', 'cyan') + \
                  termcolor.colored(repr(action._func), 'yellow')
            yield termcolor.colored('  Node:          ', 'cyan') + \
                  termcolor.colored(repr(self.node), 'yellow')
        console.lesspipe(run())
示例#14
0
        def __call__(self):
            host = get_host_func(self.shell)
            files = host.listdir()

            def iterator():
                for f in files:
                    if host.stat(f).is_dir:
                        yield colored(f, DirectoryType.color), len(f)
                    else:
                        yield f, len(f)

            console = Console(self.shell.pty)
            console.lesspipe(console.in_columns(iterator()))
示例#15
0
        def __call__(self):
            host = get_host_func(self.shell)
            files = host.listdir()

            def iterator():
                for f in files:
                    if host.stat(f).is_dir:
                        yield colored(f, DirectoryType.color), len(f)
                    else:
                        yield f, len(f)

            console = Console(self.shell.pty)
            console.lesspipe(console.in_columns(iterator()))
示例#16
0
    def _inspect_action(self):
        console = Console(self.shell.pty)
        action = Inspector(self.node).get_action(self.attr_name)

        def run():
            yield termcolor.colored('  Action name:   ', 'cyan') + \
                  termcolor.colored(self.attr_name, 'yellow')
            yield termcolor.colored('  __repr__:      ', 'cyan') + \
                  termcolor.colored(repr(action._func), 'yellow')
            yield termcolor.colored('  Node:          ', 'cyan') + \
                  termcolor.colored(repr(self.node), 'yellow')

        console.lesspipe(run())
示例#17
0
def lview(shell, path):
    """ View local file. """
    console = Console(shell.pty)

    with shell.localhost.open(path, 'r') as f:
        def reader():
            while True:
                line = f.readline()
                if line:
                    yield line.rstrip('\n')
                else:
                    return # EOF

        console.lesspipe(reader())
示例#18
0
def lview(shell, path):
    """ View local file. """
    console = Console(shell.pty)

    with shell.localhost.open(path, 'r') as f:

        def reader():
            while True:
                line = f.readline()
                if line:
                    yield line.rstrip('\n')
                else:
                    return  # EOF

        console.lesspipe(reader())
示例#19
0
    def print_all_completions(self, all_completions):
        self.stdout.write('\r\n')

        # Create an iterator which yields all the comments (in their color),
        # and pass it through in_columns/lesspipe
        def column_items():
            for w in all_completions:
                handler_type = w[1].handler_type
                text = '%s%s' % (
                    termcolor.colored(w[0], handler_type.color),
                    termcolor.colored(handler_type.postfix, handler_type.postfix_color))
                length = len(w[0]) + len(handler_type.postfix)
                yield text, length

        c = Console(self.pty)
        c.lesspipe(c.in_columns(column_items()))
示例#20
0
    def print_all_completions(self, all_completions):
        self.stdout.write('\r\n')

        # Create an iterator which yields all the comments (in their color),
        # and pass it through in_columns/lesspipe
        def column_items():
            for w in all_completions:
                handler_type = w[1].handler_type
                text = '%s%s' % (termcolor.colored(w[0], handler_type.color),
                                 termcolor.colored(handler_type.postfix,
                                                   handler_type.postfix_color))
                length = len(w[0]) + len(handler_type.postfix)
                yield text, length

        c = Console(self.pty)
        c.lesspipe(c.in_columns(column_items()))
示例#21
0
 def console(self):
     """
     Interface for user input. Returns a :class:`deployer.console.Console`
     instance.
     """
     if not self._pty:
         raise AttributeError(
             'Console is not available in Env when no pty was given.')
     return Console(self._pty)
示例#22
0
    def test_input(self):
        # Test normal input
        p = DummyPty(input_data='my-input\n')
        result = Console(p).input('input question')
        output = p.get_output()

        self.assertEqual(result, 'my-input')
        self.assertIn('input question', output)

        # Test default input
        p = DummyPty(input_data='\n')
        result = Console(p).input('input question', default='default-value')
        self.assertEqual(result, 'default-value')

        p = DummyPty(input_data='my-input\n')
        p.interactive = True  # We have to set interactive=True, otherwise
        # Console will take the default value anyway.
        result = Console(p).input('input question', default='default-value')
        self.assertEqual(result, 'my-input')
示例#23
0
 def _get_env(self):
     """
     Created a sandboxed environment for evaluation of attributes.
     (attributes shouldn't have side effects on servers, so sandboxing is fine.)
     Returns an ``Env`` object.
     """
     env = Env(self.node,
               self.shell.pty,
               self.shell.logger_interface,
               is_sandbox=True)
     return Console(self.shell.pty).select_node_isolation(env)
示例#24
0
    def test_confirm(self):
        question = 'this is my question'

        # Test various inputs
        for inp, result in [
                ('yes', True),
                ('y', True),
                ('no', False),
                ('n', False) ]:

            p = DummyPty(input_data='%s\n' % inp)
            c = Console(p)
            returnvalue = c.confirm(question)

            self.assertEqual(returnvalue, result)
            self.assertIn(question, p.get_output())

        # Test default
        p = DummyPty(input_data='\n')
        c = Console(p)
        self.assertEqual(c.confirm('', default=True), True)
        self.assertEqual(c.confirm('', default=False), False)
示例#25
0
            def write(rf, data):
                if rf._is_open:
                    # On some hosts, Paramiko blocks when writing more than
                    # 1180 bytes at once. Not sure about the reason or the
                    # exact limit, but using chunks of 1024 seems to work
                    # well. (and that way we can visualise our progress bar.)

                    # Create progress bar.
                    size=len(data)
                    p = Console(self.pty).progress_bar('Uploading data', expected=size)

                    with p:
                        if len(data) > 1024:
                            while data:
                                p.set_progress(size - len(data), rewrite=False) # Auto rewrite
                                rf._file.write(data[:1024])
                                data = data[1024:]
                        else:
                            rf._file.write(data)
                        p.set_progress(size, rewrite=True)
                else:
                    raise IOError('Cannot write to closed remote file')
示例#26
0
    def _inspect_property_attribute(self):
        console = Console(self.shell.pty)
        action = Inspector(self.node).get_property(self.attr_name)

        def run():
            yield termcolor.colored('  Property name:   ', 'cyan') + \
                  termcolor.colored(self.attr_name, 'yellow')
            yield termcolor.colored('  __repr__:      ', 'cyan') + \
                  termcolor.colored(repr(action._func), 'yellow')
            yield termcolor.colored('  Node:          ', 'cyan') + \
                  termcolor.colored(repr(self.node), 'yellow')

            # Value
            try:
                value = getattr(self._get_env(), self.attr_name)

                yield termcolor.colored('  Value:          ', 'cyan') + \
                      termcolor.colored(repr(value), 'yellow')
            except Exception as e:
                yield termcolor.colored('  Value:          ', 'cyan') + \
                      termcolor.colored('Failed to evaluate value...', 'yellow')
        console.lesspipe(run())
示例#27
0
    def _inspect_property_attribute(self):
        console = Console(self.shell.pty)
        action = Inspector(self.node).get_property(self.attr_name)

        def run():
            yield termcolor.colored('  Property name:   ', 'cyan') + \
                  termcolor.colored(self.attr_name, 'yellow')
            yield termcolor.colored('  __repr__:      ', 'cyan') + \
                  termcolor.colored(repr(action._func), 'yellow')
            yield termcolor.colored('  Node:          ', 'cyan') + \
                  termcolor.colored(repr(self.node), 'yellow')

            # Value
            try:
                value = getattr(self._get_env(), self.attr_name)

                yield termcolor.colored('  Value:          ', 'cyan') + \
                      termcolor.colored(repr(value), 'yellow')
            except Exception as e:
                yield termcolor.colored('  Value:          ', 'cyan') + \
                      termcolor.colored('Failed to evaluate value...', 'yellow')

        console.lesspipe(run())
示例#28
0
    def _run_on_node(self, isolation, *a, **kw):
        """
        Run the action on one isolation. (On a normal Node, or on a ParallelNode cell.)
        """
        with isolation._logger.group(self._action._func.__name__, *a, **kw):
            while True:
                try:
                    return self._action._func(isolation, *a, **kw)
                except ActionException as e:
                    raise
                except ExecCommandFailed as e:
                    isolation._logger.log_exception(e)

                    if self._env._pty.interactive:
                        # If the console is interactive, ask what to do, otherwise, just abort
                        # without showing this question.
                        choice = Console(self._env._pty).choice(
                            'Continue?',
                            [('Retry', 'retry'),
                             ('Skip (This will not always work.)', 'skip'),
                             ('Abort', 'abort')],
                            default='abort')
                    else:
                        choice = 'abort'

                    if choice == 'retry':
                        continue
                    elif choice == 'skip':

                        class SkippedTaskResult(object):
                            def __init__(self, node, action):
                                self._node = node
                                self._action = action

                            def __getattribute__(self, name):
                                raise Exception(
                                    'SkippedTask(%r.%r) does not have an attribute %r'
                                    % (object.__getattr__(self, '_node'),
                                       object.__getattr__(self,
                                                          '_action'), name))

                        return SkippedTaskResult(self._env._node, self._action)
                    elif choice == 'abort':
                        # TODO: send exception to logger -> and print it
                        raise ActionException(e, traceback.format_exc())
                except Exception as e:
                    e2 = ActionException(e, traceback.format_exc())
                    isolation._logger.log_exception(e2)
                    raise e2
示例#29
0
    def _ensure_password_is_known(self):
        # Make sure that we know the localhost password, before running sudo.
        global _localhost_password
        tries = 0

        while _localhost_password is None:
            _localhost_password = Console(self.pty).input(
                '[sudo] password for %s at %s' % (self.username, self.slug),
                is_password=True)

            # Check password
            try:
                Host._run_silent_sudo(self, 'ls > /dev/null')
            except ExecCommandFailed:
                print 'Incorrect password'
                self._backend.password = None

                tries += 1
                if tries >= 3:
                    raise Exception('Incorrect password')
示例#30
0
    def __call__(self):
        def _list_nested_nodes(node, prefix):
            for a in Inspector(node).get_actions():
                yield '%s %s' % (prefix,
                                 termcolor.colored(
                                     a.name,
                                     Inspector(a.node).get_group().color))

            for c in Inspector(node).get_childnodes():
                # Check the parent, to avoid loops.
                if c.parent == node:
                    name = Inspector(c).get_name()
                    for i in _list_nested_nodes(
                            c, '%s %s' %
                        (prefix,
                         termcolor.colored(name,
                                           Inspector(c).get_group().color))):
                        yield i

        Console(self.shell.pty).lesspipe(_list_nested_nodes(self.node, ''))
示例#31
0
    def __call__(self):
        # Choose host.
        hosts = self.node.hosts.get_hosts()
        if len(hosts) == 0:
            print 'No hosts found'
            return
        elif len(hosts) == 1:
            host = hosts.copy().pop()
        else:
            # Choose a host.
            options = [(h.slug, h) for h in hosts]
            try:
                host = Console(self.shell.pty).choice('Choose a host',
                                                      options,
                                                      allow_random=True)
            except NoInput:
                return

        # Start scp shell
        from deployer.scp_shell import Shell
        Shell(self.shell.pty, host, self.shell.logger_interface).cmdloop()
示例#32
0
    def test_confirm(self):
        question = 'this is my question'

        # Test various inputs
        for inp, result in [('yes', True), ('y', True), ('no', False),
                            ('n', False)]:

            p = DummyPty(input_data='%s\n' % inp)
            c = Console(p)
            returnvalue = c.confirm(question)

            self.assertEqual(returnvalue, result)
            self.assertIn(question, p.get_output())

        # Test default
        p = DummyPty(input_data='\n')
        c = Console(p)
        self.assertEqual(c.confirm('', default=True), True)
        self.assertEqual(c.confirm('', default=False), False)
示例#33
0
            def write(rf, data):
                if rf._is_open:
                    # On some hosts, Paramiko blocks when writing more than
                    # 1180 bytes at once. Not sure about the reason or the
                    # exact limit, but using chunks of 1024 seems to work
                    # well. (and that way we can visualise our progress bar.)

                    # Create progress bar.
                    size = len(data)
                    p = Console(self.pty).progress_bar('Uploading data',
                                                       expected=size)

                    with p:
                        if len(data) > 1024:
                            while data:
                                p.set_progress(size - len(data),
                                               rewrite=False)  # Auto rewrite
                                rf._file.write(data[:1024])
                                data = data[1024:]
                        else:
                            rf._file.write(data)
                        p.set_progress(size, rewrite=True)
                else:
                    raise IOError('Cannot write to closed remote file')
示例#34
0
 def get_command(self):
     try:
         text = '[SUDO] Enter command' if self.use_sudo else 'Enter command'
         return Console(self.shell.pty).input(text)
     except NoInput:
         return
示例#35
0
    def _inspect_node(self):
        console = Console(self.shell.pty)

        def inspect():
            # Print full name
            yield termcolor.colored('  Node:    ', 'cyan') + \
                  termcolor.colored(Inspector(self.node).get_full_name(), 'yellow')

            # Print mro
            yield termcolor.colored('  Mro:', 'cyan')
            i = 1
            for m in self.node.__class__.__mro__:
                if m.__module__ != 'deployer.node' and m != object:
                    yield termcolor.colored('              %i ' % i, 'cyan') + \
                          termcolor.colored('%s.' % m.__module__, 'red') + \
                          termcolor.colored('%s' % m.__name__, 'yellow')
                    i += 1

            # File names
            yield termcolor.colored('  Files:', 'cyan')
            i = 1
            for m in self.node.__class__.__mro__:
                if m.__module__ != 'deployer.node' and m != object:
                    yield termcolor.colored('              %i ' % i, 'cyan') + \
                          termcolor.colored(getfile(m), 'red')
                    i += 1

            # Print host mappings
            yield termcolor.colored('  Hosts:', 'cyan')

            for role in sorted(self.node.hosts._hosts.keys()):
                items = self.node.hosts._hosts[role]
                yield termcolor.colored('         "%s"' % role, 'yellow')
                i = 1
                for host in sorted(items, key=lambda h:h.slug):
                    yield termcolor.colored('            %3i ' % i, 'cyan') + \
                          termcolor.colored('%-25s (%s)' % (host.slug, getattr(host, 'address', '')), 'red')
                    i += 1

            # Print the first docstring (look to the parents)
            for m in self.node.__class__.__mro__:
                if m.__module__ != 'deployer.node' and m != object and m.__doc__:
                    yield termcolor.colored('  Docstring:\n', 'cyan') + \
                          termcolor.colored(m.__doc__ or '<None>', 'red')
                    break

            # Actions
            yield termcolor.colored('  Actions:', 'cyan')

            def item_iterator():
                for a in Inspector(self.node).get_actions():
                    yield termcolor.colored(a.name, 'red'), len(a.name)

            for line in console.in_columns(item_iterator(), margin_left=13):
                yield line

            # Nodes
            yield termcolor.colored('  Sub nodes:', 'cyan')

                # Group by node group
            grouper = lambda c:Inspector(c).get_group()
            for group, nodes in groupby(sorted(Inspector(self.node).get_childnodes(), key=grouper), grouper):
                yield termcolor.colored('         "%s"' % group.name, 'yellow')

                # Create iterator for all the items in this group
                def item_iterator():
                    for n in nodes:
                        name = Inspector(n).get_name()

                        if n.parent == self.node:
                            text = termcolor.colored(name, type_of_node(n).color)
                            length = len(name)
                        else:
                            full_name = Inspector(n).get_full_name()
                            text = termcolor.colored('%s -> %s' % (name, full_name), type_of_node(n).color)
                            length = len('%s -> %s' % (name, full_name))
                        yield text, length

                # Show in columns
                for line in console.in_columns(item_iterator(), margin_left=13):
                    yield line

        console.lesspipe(inspect())
示例#36
0
    def __call__(self, *a, **kw):
        # In case of a not_isolated ParallelNode, return a
        # ParallelActionResult, otherwise, just return the actual result.
        if isinstance(self._env, ParallelNode) and not self._env._node_is_isolated and \
                            not getattr(self._action._func, 'dont_isolate_yet', False):

            # Get isolations of the env.
            isolations = list(self._env)

            # No hosts in ParallelNode. Nothing to do.
            if len(isolations) == 0:
                self._env._logger.log_msg('Nothing to do. No hosts in %r' %
                                          self._action)
                return ParallelActionResult([])

            # Exactly one host.
            elif len(isolations) == 1:
                return ParallelActionResult([
                    (isolations[0], self._run_on_node(isolations[0], *a, **kw))
                ])

            # Multiple hosts, but isolate_one_only flag set.
            elif getattr(self._action._func, 'isolate_one_only', False):
                # Ask the end-user which one to use.
                # TODO: this is not necessarily okay. we can have several levels of isolation.
                options = [('%s    [%s]' % (i.host.slug, i.host.address), i)
                           for i in isolations]
                i = Console(self._env._pty).choice('Choose a host',
                                                   options,
                                                   allow_random=True)
                return self._run_on_node(i, *a, **kw)

            # Multiple hosts. Fork for each isolation.
            else:
                errors = []

                # Create a callable for each host.
                def closure(isolation):
                    def call(pty):
                        # Isolation should be an env, but
                        i2 = Env(isolation._node, pty, isolation._logger,
                                 isolation._is_sandbox)

                        # Fork logger
                        logger_fork = self._env._logger.log_fork('On: %r' %
                                                                 i2._node)
                        # TODO: maybe we shouldn't log fork(). Consider it an abstraction.

                        try:
                            # Run this action on the new service.
                            result = self._run_on_node(i2, *a, **kw)

                            # Succeed
                            logger_fork.set_succeeded()
                            return (isolation, result)
                        except Exception as e:
                            # TODO: handle exception in thread
                            logger_fork.set_failed(e)
                            errors.append(e)

                    return call

                # For every isolation, create a callable.
                callables = [closure(i) for i in isolations]
                logging.info('Forking %r (%i pseudo terminals)' %
                             (self._action, len(callables)))

                fork_result = self._env._pty.run_in_auxiliary_ptys(callables)
                fork_result.join()

                if errors:
                    # When an error occcured in one fork, raise this error
                    # again in current thread.
                    raise errors[0]
                else:
                    # This returns a list of results.
                    return ParallelActionResult(fork_result.result)
        else:
            return self._run_on_node(self._env, *a, **kw)
示例#37
0
 def __call__(self):
     files = self.shell.localhost.listdir()
     console = Console(self.shell.pty)
     console.lesspipe(console.in_columns(files))
示例#38
0
    def _inspect_node(self):
        console = Console(self.shell.pty)

        def inspect():
            # Print full name
            yield termcolor.colored('  Node:    ', 'cyan') + \
                  termcolor.colored(Inspector(self.node).get_full_name(), 'yellow')

            # Print mro
            yield termcolor.colored('  Mro:', 'cyan')
            i = 1
            for m in self.node.__class__.__mro__:
                if m.__module__ != 'deployer.node' and m != object:
                    yield termcolor.colored('              %i ' % i, 'cyan') + \
                          termcolor.colored('%s.' % m.__module__, 'red') + \
                          termcolor.colored('%s' % m.__name__, 'yellow')
                    i += 1

            # File names
            yield termcolor.colored('  Files:', 'cyan')
            i = 1
            for m in self.node.__class__.__mro__:
                if m.__module__ != 'deployer.node' and m != object:
                    yield termcolor.colored('              %i ' % i, 'cyan') + \
                          termcolor.colored(getfile(m), 'red')
                    i += 1

            # Print host mappings
            yield termcolor.colored('  Hosts:', 'cyan')

            for role in sorted(self.node.hosts._hosts.keys()):
                items = self.node.hosts._hosts[role]
                yield termcolor.colored('         "%s"' % role, 'yellow')
                i = 1
                for host in sorted(items, key=lambda h: h.slug):
                    yield termcolor.colored('            %3i ' % i, 'cyan') + \
                          termcolor.colored('%-25s (%s)' % (host.slug, getattr(host, 'address', '')), 'red')
                    i += 1

            # Print the first docstring (look to the parents)
            for m in self.node.__class__.__mro__:
                if m.__module__ != 'deployer.node' and m != object and m.__doc__:
                    yield termcolor.colored('  Docstring:\n', 'cyan') + \
                          termcolor.colored(m.__doc__ or '<None>', 'red')
                    break

            # Actions
            yield termcolor.colored('  Actions:', 'cyan')

            def item_iterator():
                for a in Inspector(self.node).get_actions():
                    yield termcolor.colored(a.name, 'red'), len(a.name)

            for line in console.in_columns(item_iterator(), margin_left=13):
                yield line

            # Nodes
            yield termcolor.colored('  Sub nodes:', 'cyan')

            # Group by node group
            grouper = lambda c: Inspector(c).get_group()
            for group, nodes in groupby(
                    sorted(Inspector(self.node).get_childnodes(), key=grouper),
                    grouper):
                yield termcolor.colored('         "%s"' % group.name, 'yellow')

                # Create iterator for all the items in this group
                def item_iterator():
                    for n in nodes:
                        name = Inspector(n).get_name()

                        if n.parent == self.node:
                            text = termcolor.colored(name,
                                                     type_of_node(n).color)
                            length = len(name)
                        else:
                            full_name = Inspector(n).get_full_name()
                            text = termcolor.colored(
                                '%s -> %s' % (name, full_name),
                                type_of_node(n).color)
                            length = len('%s -> %s' % (name, full_name))
                        yield text, length

                # Show in columns
                for line in console.in_columns(item_iterator(),
                                               margin_left=13):
                    yield line

        console.lesspipe(inspect())
示例#39
0
 def test_print_warning(self):
     p = DummyPty()
     c = Console(p)
     c.warning('this is a warning')
     self.assertIn('this is a warning', p.get_output())
示例#40
0
 def test_print_warning(self):
     p = DummyPty()
     c = Console(p)
     c.warning('this is a warning')
     self.assertIn('this is a warning', p.get_output())
示例#41
0
 def __call__(self):
     files = self.shell.localhost.listdir()
     console = Console(self.shell.pty)
     console.lesspipe(console.in_columns(files))