Ejemplo n.º 1
0
Archivo: cli.py Proyecto: pylover/hive
class DeleteUserSubCommand(SubCommand):
    __command__ = 'delete'
    __aliases__ = ['d']
    __help__ = 'Delete a user'
    __arguments__ = [
        Argument('name', help='Username')
    ]

    def __call__(self, args):
        user = DBSession.query(User).filter(User.id == args.name).one_or_none()
        if user is None:
            print(f'Invalid username: {args.name}', file=sys.stderr)
            return 1

        if input(
            f'Are you sure to delete the user: {user.id}? [N/y] '
        ).casefold() != 'y'.casefold():
            print(f'User: {args.name} is not deleted', file=sys.stderr)
            return 1

        DBSession.delete(user)
        DBSession.commit()
Ejemplo n.º 2
0
class SetupCommand(SubCommand):
    __command__ = 'setup'
    __arguments__ = [
        Argument('cidr',
                 nargs='?',
                 default=DEFAULT_CIDR,
                 help=f'The network/mask (aka CIDR), default: {DEFAULT_CIDR}')
    ]

    def __call__(self, args):

        settings.cidr = args.cidr
        with open(args.configurationfilename, 'w') as f:
            f.write(settings.dumps())

        ok(f'Settings are saved into {args.configurationfilename}')

        sshdfile = TextFile(SSHSERVER_CONFIGURATIONFILENAME)
        sshdfile.commentout('PermitTunnel (?!yes)')

        if not sshdfile.hasline('PermitTunnel yes'):
            sshdfile.append(SSHDSETTINGS)

            ok(
                f'The following lines are added into the ' \
                f'{SSHSERVER_CONFIGURATIONFILENAME}'
            )
            info(SSHDSETTINGS)
            warning('Do you want to restart the openssh-server?')
            if input('You may restart the SSH server manualy ' \
                'if you choose no[Y/n]:') in ('y', 'Y'):

                print('Restarting ssh server...')
        else:
            ok(f'PermitTunnel is already enabled in {sshdfile.filename}.')

        sshdfile.saveifneeded()
Ejemplo n.º 3
0
class MockupServer(SubCommand):
    __command__ = 'mockupserver'
    __help__ = 'Generates a mockup from YAML file.'
    __arguments__ = [
        Argument('story', metavar='YAML', help='A story file'),
    ]

    def __call__(self, args):
        from nanohttp import Controller, HTTPNotFound, context
        from ..authoring import Story
        with open(args.story) as story_file:
            story = Story.load(story_file)

        class RootMockupController(Controller):
            def __init__(self):
                self.stories = []

            def add_story(self, story):
                self.stories.append(story)

            def server(self, call):
                for k, v in call.response.headers:
                    context.response_headers.add_header(k, v)

                yield call.response.text.encode()

            def __call__(self, *remaining_paths):
                calls = [story.base_call] + story.calls
                for call in calls:
                    url = call.url.replace(':', '')
                    if set(url.strip('/').split('/')) == set(remaining_paths):
                        return self.server(call)

                raise HTTPNotFound()

        from nanohttp import quickstart
        quickstart(RootMockupController())
Ejemplo n.º 4
0
class Main(Root):
    __completion__ = True
    __arguments__ = [
        Argument(
            '-c', '--configuration-file',
            metavar="FILE",
            dest='configurationfile',
            help='Configuration file',
        ),
        Serve,
    ]

    def __init__(self, application):
        self.application = application
        self.__help__ = f'{sys.argv[0]} command line interface.'
        self.__arguments__.extend(self.application.cliarguments)
        super().__init__()

    def _execute_subcommand(self, args):
        args.application = self.application
        if args.configurationfile:
            self.application.settings.loadfile(args.configurationfile)

        super()._execute_subcommand(args)
Ejemplo n.º 5
0
Archivo: cli.py Proyecto: yhttp/yhttp
class Main(Root):
    __completion__ = True
    __arguments__ = [
        Argument(
            '-c', '--configuration-file',
            metavar="FILE",
            dest='configurationfile',
            help='Configuration file',
        ),
        Serve,
    ]

    def __init__(self, application):
        if application.version:
            self.__arguments__.append(
                Argument('--version', action='store_true')
            )

        self.application = application
        self.__help__ = f'{sys.argv[0]} command line interface.'
        self.__arguments__.extend(self.application.cliarguments)
        super().__init__()

    def _execute_subcommand(self, args):
        args.application = self.application
        if args.configurationfile:
            self.application.settings.loadfile(args.configurationfile)

        return super()._execute_subcommand(args)

    def __call__(self, args):
        if self.application.version and args.version:
            print(self.application.version)
            return

        self._parser.print_help()
Ejemplo n.º 6
0
class DocumentaryLauncher(SubCommand):
    __command__ = 'document'
    __help__ = 'Generates REST API Documentation from standard input to ' \
        'standard output.'
    __arguments__ = [
        Argument('-f',
                 '--format',
                 default='markdown',
                 help='The output format. One of markdown, html. Default is '
                 'markdown.'),
    ]

    formatters = {
        'markdown': MarkdownFormatter,
        # 'html': HtmlFormatter,
    }

    def __call__(self, args):
        self.convert_file(sys.stdin, sys.stdout, args.format)

    def convert_file(self, source, destination, format):
        from ..authoring import Story
        story = Story.load(source)
        story.document(destination, formatter_factory=self.formatters[format])
Ejemplo n.º 7
0
class PasswdSubCommand(SubCommand):
    __command__ = 'passwd'
    __help__ = 'change a user\'s password'
    __arguments__ = [
        Argument(
            'name',
            help='Username',
        ),
    ]

    def __call__(self, args):
        user = DBSession.query(User).filter(User.id == args.name).one_or_none()
        if user is None:
            print(f'Invalid username: {args.name}', file=sys.stderr)
            return 1

        password=getpass('New Password:'******'Again:')
        if password != confirm:
            print(f'Passwords are mismatch.', file=sys.stderr)
            return 1

        user.password=password
        DBSession.commit()
Ejemplo n.º 8
0
class WebsocketStartSubSubCommand(SubCommand):  # pragma: no cover
    __help__ = 'Starts the websocket server.'
    __command__ = 'start'
    __arguments__ = [
        Argument(
            '-b',
            '--bind',
            default=DEFAULT_ADDRESS,
            metavar='{HOST:}PORT',
            help='Bind Address. default: %s' % DEFAULT_ADDRESS,
        ),
    ]

    def __call__(self, args):
        host, port = args.bind.split(':')\
            if ':' in args.bind else ('', args.bind)
        kw = {}
        if port:
            kw['port'] = port

        if host:
            kw['host'] = host

        web.run_app(app, **kw)
Ejemplo n.º 9
0
class StartSubSubCommand(SubCommand):
    __command__ = 'start'
    __help__ = 'Starts the background worker.'
    __arguments__ = [
        Argument(
            '-g',
            '--gap',
            type=int,
            default=None,
            help='Gap between run next task.',
        ),
        Argument(
            '-s',
            '--status',
            default=[],
            action='append',
            help='Task status to process',
        ),
        Argument(
            '-n',
            '--number-of-threads',
            type=int,
            default=None,
            help='Number of working threads',
        ),
    ]

    def __call__(self, args):
        from restfulpy.taskqueue import worker

        signal.signal(signal.SIGINT, self.kill_signal_handler)
        signal.signal(signal.SIGTERM, self.kill_signal_handler)

        if not args.status:
            args.status = {'new'}

        if args.gap is not None:
            settings.worker.merge({'gap': args.gap})

        print(f'The following task types would be processed with gap of '
              f'{settings.worker.gap}s:')
        print('Tracking task status(es): %s' % ','.join(args.status))

        number_of_threads = \
            args.number_of_threads or settings.worker.number_of_threads
        for i in range(number_of_threads):
            t = threading.Thread(target=worker,
                                 name='restfulpy-worker-thread-%s' % i,
                                 daemon=True,
                                 kwargs=dict(statuses=args.status,
                                             filters=args.filter))
            t.start()

        print('Worker started with %d threads' % number_of_threads)
        print('Press Ctrl+C to terminate worker')
        signal.pause()

    @staticmethod
    def kill_signal_handler(signal_number, frame):

        if signal_number == signal.SIGINT:
            print('You pressed Ctrl+C!')

        elif signal_number in (signal.SIGTERM, signal.SIGKILL):
            print('OS Killed Me!')

        sys.stdin.close()
        sys.stderr.close()
        sys.stdout.close()
        sys.exit(1)
Ejemplo n.º 10
0
class ScaffoldSubCommand(SubCommand):
    __command__ = 'scaffold'
    __help__ = 'Creates an empty boilerplate'
    __arguments__ = [
        Argument(
            'name',
            help='The snake_case project\'s name'
        ),
        Argument(
            'author',
            help='The project\'s author'
        ),
        Argument(
            'email',
            help='The projects author\'s email'
        ),
        Argument(
            '-t',
            '--template',
            default='full',
            help= \
                f'The project\'s template, one of {", ".join(TEMPLATES)}. '
                f'default: full.'
        ),
        Argument(
            '-o',
            '--overwrite',
            default=False,
            action='store_true',
            help= \
                'Continue and overwrite files when the target '
                'directory(-d/--directory) is not empty.'
        ),
        Argument(
            '-d',
            '--directory',
            default='.',
            help= \
                'Change to this directory before generating new files. It '
                'will make it if does not exists. default: "."'
        ),
    ]

    def __call__(self, args):
        template_path = path.join(TEMPLATES_PATH, args.template)
        target_path = path.abspath(args.directory)
        title_snakecase = args.name.lower()

        if not path.exists(template_path):
            print(f'Invalid template: {template_path}', file=sys.stderr)
            return 1

        if not path.exists(target_path):
            os.makedirs(target_path)

        for top, subdirectories, subfiles in os.walk(template_path):
            current_directory = path.relpath(top, template_path) \
                .replace('__project__', title_snakecase)
            for filename in subfiles:
                if not filename.endswith('.template'):
                    continue

                source = path.abspath(path.join(top, filename))
                target = path.abspath(
                    path.join(
                        target_path, current_directory,
                        filename[:-9].replace('__project__', title_snakecase)))
                if not args.overwrite and path.exists(target):
                    print(f'Target file exists: {target}, use -o to overwrite',
                          file=sys.stderr)
                    return 1

                os.makedirs(path.dirname(target), exist_ok=True)
                self.install_file(source, target, args)
                if args.template == 'singlefile':
                    os.chmod(target, 0o774)

    def install_file(self, source, target, args):
        print(f'Installing  {target}')
        title_snakecase = args.name.lower()
        title_camelcase = to_pascal_case(title_snakecase)

        with open(source) as s, open(target, 'w') as t:
            content = s.read()
            content = content.replace('${project_snakecase}', title_snakecase)
            content = content.replace('${project_author}', args.author)
            content = content.replace('${project_author_email}', args.email)
            content = content.replace('${project_camelcase}', title_camelcase)
            content = content.replace('${restfulpy_version}',
                                      restfulpy.__version__)
            t.write(content)
Ejemplo n.º 11
0
class ConnectCommand(SubCommand):
    __command__ = 'connect'
    __aliases__ = ['c']
    __arguments__ = [
        Argument('-v', '--verbose', action='store_true', help='Verbose'),
        Argument('-r',
                 '--retrymax',
                 type=int,
                 default=0,
                 help='Maximum retry, default is: 0, infinite!'),
    ]

    def getdefaultgateway(self):
        """Returns the current default gateway from `/proc`
        """
        with open('/proc/net/route') as fh:
            for line in fh:
                fields = line.strip().split()
                if fields[1] != '00000000' or not int(fields[3], 16) & 2:
                    continue
                return socket.inet_ntoa(struct.pack("<L", int(fields[2], 16)))

    def connect(self, gateway, hostaddr, hostname, args):
        index = settings.index
        hostname = settings.hostname
        remoteuser = settings.remoteuser
        localuser = settings.localuser
        serveraddr = settings.addresses.server
        terminating = False
        c = args.retrymax
        infinite = c == 0
        sshargs = []

        if args.verbose:
            sshargs.append('-v')

        sshargs.append(f'-o"ServerAliveInterval 10"')
        sshargs.append(f'-o"ServerAliveCountMax 1"')
        sshargs.append(f'-o"ConnectTimeout 10"')
        sshargs.append(f'-o"ConnectionAttempts 20"')

        def term(sig, frame):
            nonlocal terminating
            terminating = True
            os.killpg(os.getpgid(sshprocess.pid), signal.SIGTERM)

        signal.signal(signal.SIGTERM, term)
        signal.signal(signal.SIGINT, term)

        while infinite or (c > 0):
            try:
                shell(f'ip route replace {hostaddr} via {gateway}')
                shell(f'ip route replace default via {serveraddr}')
                sshprocess = Popen(
                    f'sudo -u {localuser} ssh {remoteuser}@{hostname} ' \
                    f'-Nw {index}:{index} {" ".join(sshargs)}',
                    shell=True,
                    preexec_fn=os.setsid,
                )
                sshprocess.wait()

                if terminating or sshprocess.returncode <= 0:
                    break

            finally:
                shell(f'ip route del {hostaddr} via {gateway}', check=False)
                shell(f'ip route replace default via {gateway}', check=False)

            time.sleep(1)
            c -= 1

    def __call__(self, args):
        if USER != 'root':
            error('Please run this command as root.')
            return 1

        hostname = settings.hostname
        remoteuser = settings.remoteuser
        localuser = settings.localuser
        index = settings.index
        ifname = f'tun{index}'
        clientaddr = settings.addresses.client
        serveraddr = settings.addresses.server
        netmask = settings.netmask
        hostaddr = socket.gethostbyname(hostname)

        gateway = self.getdefaultgateway()
        if gateway is None:
            error(f'Invalid default gateway: {gateway}')

        try:
            shell(
                f'ip tuntap add mode tun dev {ifname} user {localuser} group {localuser}'
            )
            shell(
                f'ip address add dev {ifname} {clientaddr}/{netmask} ' \
                f'peer {serveraddr}/{netmask}'
            )
            shell(f'ip link set up dev {ifname}')
            self.connect(gateway, hostaddr, hostname, args)
        finally:
            info('Terminating...')
            shell(f'ip tuntap delete mode tun dev {ifname}', check=False)
Ejemplo n.º 12
0
class CP(Root):
    __help__ = 'easycli example'
    __command__ = 'cp'
    __completion__ = False
    __arguments__ = [
        Argument(
            'files',
            nargs='*',
            metavar='N',
            type=str,
            help='source path'
        ),
        Argument(
            '-r', '--recursive',
            action='store_true',
            help='copy directories recursively'
        ),
        Argument(
            '-v', '--verbose',
            help='explain what is being done',
            action='store_true',
        ),
    ]

    def _split_source_destination(self, args):
        if len(args.files) < 2:
            print('Source or destination is not entered')
            sys.exit()
        sources = args.files[:-1]
        destination = args.files[-1]
        return sources, destination

    def __call__(self, args):
        sources, destination = self._split_source_destination(args)
        current_dir = os.getcwd()
        for source_file in sources:

            if '/' in source_file[:-1]:
                source_path = source_file
                os.chdir(source_file[:source_file.rindex('/')])
                file_name = source_file[source_file.rindex('/')+1:]

            else:
                source_path = current_dir + '/' + source_file
                file_name = source_file

            if not (
                os.path.exists(source_path) or os.path.isfile(source_path)
            ):
                print(
                    f"cp: cannot stat '{source_path}':"\
                    "No such file or directory"
                )

            if os.path.isdir(source_path):

                if not args.recursive:
                    destination = os.path.abspath(destination)
                    destination = destination.split('/')[-1]
                    print(
                        f"cp: -r not specified;"\
                        "omitting directory {destination!r}"
                    )
                    sys.exit()

                else:
                    source = os.path.abspath(source_path)
                    destination = os.path.abspath(destination)

                    if '/' not in source[-1] or '/' not in source:
                        top = destination + '/' + source[source.rindex('/')+1:]

                    else:
                        top = destination + '/' + source

                    if not os.path.isdir(destination):
                        os.mkdir(destination)

                    if source == top:

                        if '/' in destination:
                            print(
                                f"cp: '{source_path}' and ./'{destination}'"
                                "are the same file"
                            )

                        else:
                            print(
                                f"cp: '{source_path}' and '{destination}'"
                                "are the same file"
                            )
                        sys.exit()
                    if os.path.exists(top):

                        for root, dirs, files in os.walk(top, topdown=False):

                            for name in files:
                                os.remove(os.path.join(root, name))

                            for name in dirs:
                                os.rmdir(os.path.join(root, name))
                        os.rmdir(top)

                    recursive_copy(source, destination, args.verbose)

            elif os.path.isfile(source_path):
                source = source_path
                destination = destination

                if not(os.path.exists(source)):
                    print(
                        f"cp: cannot stat '{source_path}':"
                        "No such file or directory"
                    )

                if not os.path.isdir(destination):
                    os.mkdir(destination)

                if destination == "":
                    print(
                        f"cp: missing destination file operand after "
                        "'{destination}'"
                    )

                if os.path.isdir(source):
                    print(
                        f"cp: -r not specified;"\
                        "omitting directory '{source_path}'"
                    )
                copyfile(source, destination, args.verbose)
Ejemplo n.º 13
0
class ConnectCommand(SubCommand):
    __command__ = 'connect'
    __aliases__ = ['c']
    __arguments__ = [
        Argument('-v', '--verbose', action='store_true', help='Verbose'),
        Argument(
            '-i', '--aliveinterval',
            type=int,
            default=2,
            help=\
                'ssh ServerAliveInterval option, see man ssh_config. ' \
                'default is: 2'
        ),
        Argument(
            '-m', '--alivecountmax',
            type=int,
            default=1,
            help=\
                'ssh ServerAliveCountMax option, see man ssh_config. ' \
                'default is: 1'
        ),
        Argument(
            '-r', '--retrymax',
            type=int,
            default=0,
            help='Maximum retry, default is: 0, infinite!'
        ),
        Argument(
            '--connecttimeout',
            type=int,
            default=2,
            help='ssh ConnectTimeout option, default is: 2.'
        ),
        Argument(
            '--connectionattempts',
            type=int,
            default=2,
            help='ssh ConnectionAttempts option, default is: 2.'
        )
    ]

    def getdefaultgateway(self):
        """Returns the current default gateway from `/proc`
        """
        with open('/proc/net/route') as fh:
            for line in fh:
                fields = line.strip().split()
                if fields[1] != '00000000' or not int(fields[3], 16) & 2:
                    continue
                return socket.inet_ntoa(struct.pack("<L", int(fields[2], 16)))

    def connect(self, gateway, hostaddr, hostname, args):
        index = settings.index
        hostname = settings.hostname
        remoteuser = settings.remoteuser
        localuser = settings.localuser
        serveraddr = settings.addresses.server
        c = args.retrymax
        infinite = c == 0
        sshargs = []

        if args.verbose:
            sshargs.append('-v')

        sshargs.append(f'-o"ServerAliveInterval {args.aliveinterval}"')
        sshargs.append(f'-o"ServerAliveCountMax {args.alivecountmax}"')
        sshargs.append(f'-o"ConnectTimeout {args.connecttimeout}"')
        sshargs.append(f'-o"ConnectionAttempts {args.connectionattempts}"')

        while infinite or (c > 0):
            try:
                shell(f'ip route replace {hostaddr} via {gateway}')
                shell(f'ip route replace default via {serveraddr}')
                shell(
                    f'sudo -u {localuser} ssh {remoteuser}@{hostname} ' \
                    f'-Nw {index}:{index} {" ".join(sshargs)}'
                )
            except CalledProcessError as ex:
                if ex.returncode < 0:
                    break

            except:
                traceback.print_exc()
                time.sleep(3)

            finally:
                shell(f'ip route del {hostaddr} via {gateway}', check=False)
                shell(f'ip route replace default via {gateway}', check=False)

            time.sleep(1)
            c -= 1

    def __call__(self, args):
        if USER != 'root':
            error('Please run this command as root.')
            return 1

        hostname = settings.hostname
        remoteuser = settings.remoteuser
        localuser = settings.localuser
        index = settings.index
        ifname = f'tun{index}'
        clientaddr = settings.addresses.client
        serveraddr = settings.addresses.server
        netmask = settings.netmask
        hostaddr = socket.gethostbyname(hostname)

        gateway = self.getdefaultgateway()
        if gateway is None:
            error(f'Invalid default gateway: {gateway}')

        try:
            shell(
                f'ip tuntap add mode tun dev {ifname} user {localuser} group {localuser}'
            )
            shell(
                f'ip address add dev {ifname} {clientaddr}/{netmask} ' \
                f'peer {serveraddr}/{netmask}'
            )
            shell(f'ip link set up dev {ifname}')
            self.connect(gateway, hostaddr, hostname, args)
        finally:
            info('Terminating...')
            shell(f'ip tuntap delete mode tun dev {ifname}', check=False)
Ejemplo n.º 14
0
class CP(Root):
    __help__ = 'easycli example'
    __command__ = 'cp'
    __completion__ = True
    __arguments__ = [
        #        Argument(
        #            '-V', '--version',
        #            action='version',
        #            version='CP 1.0',
        #        ),
        Argument('-r',
                 '--recursive',
                 action='store_true',
                 help='copy directories recursively'),
        Argument(
            '-v',
            '--verbose',
            help='asdf',
            action='store_true',
        ),
        Argument('source', help='source path'),
        Argument('destination', help='destination path'),
    ]

    def __call__(self, args):
        if not (os.path.exists(args.source) or os.path.isfile(args.source)):
            print(
                f"cp: cannot stat '{args.source}': No such file or directory")

        if os.path.isdir(args.source):
            if not args.recursive:
                destination = os.path.abspath(args.destination)
                destination = destination.split('/')[-1]
                print(
                    f"cp: -r not specified; omitting directory {destination!r}"
                )
                sys.exit()
            else:
                source = os.path.abspath(args.source)
                destination = os.path.abspath(args.destination)
                if '/' not in source[-1] or '/' not in source:
                    top = destination + '/' + source[source.rindex('/') + 1:]

                else:
                    top = destination + '/' + source

                if not os.path.isdir(args.destination):
                    os.mkdir(args.destination)

                if source == top:
                    if '/' in destination:
                        print(f"cp: '{args.source}' and ./'{destination}'"
                              "are the same file")
                    else:
                        print(f"cp: '{args.source}' and '{args.destination}'"
                              "are the same file")
                    sys.exit()
                if os.path.exists(top):
                    for root, dirs, files in os.walk(top, topdown=False):
                        for name in files:
                            os.remove(os.path.join(root, name))
                        for name in dirs:
                            os.rmdir(os.path.join(root, name))
                    os.rmdir(top)
                recursive_copy(source, destination, args.verbose)

        elif os.path.isfile(args.source):
            source = args.source
            destination = args.destination
            if not (os.path.exists(source)):
                print(f"cp: cannot stat '{args.source}':"
                      "No such file or directory")
            if not os.path.isdir(args.destination):
                os.mkdir(args.destination)
            if destination == "":
                print(f"cp: missing destination file operand after "
                      "'{args.destination}'")
            if os.path.isdir(source):
                print(
                    f"cp: -r not specified; omitting directory '{args.source}'"
                )

            copyfile(source, destination, args.verbose)