예제 #1
0
    def do_deploy(self, args):
        """
        Usage:
          deploy [--dev] <path>

        Deploys a recipe.

        Arguments:
          <path>        A path to the local recipe or a git repo which contains a recipe.

        Options:
          --dev         Uses git clone instead of git archive to keep .git.
                        This should NOT be done on an assembly that are going to be released.
        """
        try:
            self._rpc.do_deploy_reset_check()
            path = args['path']
            if not giturlparse.validate(path):
                if not path.startswith("/"):
                    path = os.path.join(os.getcwd(), path)
                rpc_put_recipe(self._rpc, path, should_skip=get_filter(os.path.join(path, ".jscignore")))
            rec = self._rpc.do_deploy_read_new_recipe({"path": path})
            state = recipe.run(self._rpc, rec, args['--dev'])
            args.update({"state": state})
            self._rpc.do_deploy_finalize(args)
        except SshRpcCallError as e:
            log.white(str(e))
예제 #2
0
 def complete_deploy(self, text, line, begidx, endidx):
     try:
         argv = shlex.split(line)
         cwd = os.getcwd()
         if len(argv) == 1 or (len(argv) == 2 and argv[1] == '--dev'):
             ret = os.listdir(cwd)
         else:
             parsed = docopt(self.do_deploy.__doc__, argv[1:])
             path = parsed['<path>']
             ret = []
             if path == '.':
                 ret.append('.')
                 ret.append('..')
             elif path == '..':
                 ret.append('..')
             elif os.path.isdir(path):
                 os.chdir(path)
             elif os.path.isdir(os.path.dirname(path)):
                 os.chdir(os.path.dirname(path))
             resolved = glob.glob(os.path.basename(path)+'*')
             if len(resolved) == 1 and resolved[0] == path:
                 pass
             else:
                 ret += resolved
             os.chdir(cwd)
         return map(lambda d: d + "/" if os.path.isdir(d) else d, ret)
     except Exception as e:
         # The DocoptExit is thrown when the args do not match.
         # We print a message to the user and the usage block.
         log.white('Invalid Command!')
         log.white(e)
         return []
예제 #3
0
def print_status(assembly_id, status, env, verbose=False):
    email = env["ident"]["user"]["email"]
    name = env["ident"]["user"]["name"]
    if status['deploy_time'] is None:
        status['deploy_time'] = "<never>"
    log.white(
        u"\n".join([u"Jsc v{version} attached to assembly [{assembly_id}] by [{name} {email}]".format(version=__version__, assembly_id=assembly_id, name=name, email=email),
                   u"{dir}: {used} used of {total} ({percent_used} used)".format(**status['code_usage']),
                   u"    deployed recipe: {recipe_name}".format(**status),
                   u"        at {deploy_time}".format(**status),
                   u"    total backups: {total_backups}".format(**status),
                   u"{dir}: {used} used of {total} ({percent_used} used)".format(**status['state_usage'])]))
    if verbose:
        package_lines = []
        if "software" in status:
            if "package" in status["software"]:
                for pkg in status['software']["package"]:
                    pkg_kw = {"pkg": pkg,
                              "ver": status['software']["package"][pkg]["version"]}
                    package_lines.append("\t{pkg}: [{ver}]".format(**pkg_kw))
        gd_lines = []
        if "software" in status:
            if "gd" in status["software"]:
                for path in status['software']["gd"]:
                    gd_kw = {"ref": status['software']["gd"][path]["ref"],
                             "src": status['software']["gd"][path]["repo"],
                             "commit": status['software']["gd"][path]["commit"][0:8],
                             "path": path}
                    gd_lines.append("\t{path}: [{src}] [{ref}] [{commit}]".format(**gd_kw))
        all_lines = ["Deploiyed packages:"]
        all_lines += package_lines
        all_lines += ["Git deployed software:"]
        all_lines += gd_lines
        log.white("\n".join(all_lines))
예제 #4
0
def rpc_put_recipe(rpc, src, dst=NEW_RECIPE_SRC, chunk_size=2**16, should_skip=lambda x: False):
    def put_file(fn_path_src, fn_path_dst):
        f_stat = os.stat(fn_path_src)
        bytes_left = f_stat.st_size
        log.white("putting local:{src} -> remote:{dst}".format(src=fn_path_src, dst=dst))
        with open(fn_path_src, "rb") as fo:
            while True:
                b64_content = base64.standard_b64encode(fo.read(chunk_size))
                rpc.do_file_append({"path": fn_path_dst, "content": b64_content})
                bytes_left -= chunk_size
                if bytes_left <= 0:
                    break

    if os.path.isfile(src) or os.path.islink(src):
        put_file(src, dst + "/Jumpstart-Recipe")
    elif os.path.isdir(src):
        for fn in os.listdir(src):
            fn_path_src = os.path.join(src, fn)
            if should_skip(fn_path_src):
                continue
            fn_path_dst = dst + "/" + fn
            if os.path.islink(fn_path_src):
                link_target = os.readlink(fn_path_src)
                rpc.do_symlink({"path": fn_path_dst, "target": link_target})
            elif os.path.isfile(fn_path_src):
                put_file(fn_path_src, fn_path_dst)
            elif os.path.isdir(fn_path_src):
                rpc.do_mkdir({"path": fn_path_dst})
                rpc_put_recipe(rpc, fn_path_src, fn_path_dst, chunk_size, should_skip)
    else:
        log.white("could not find recipe dir or file")
예제 #5
0
파일: sshjsonrpcwin.py 프로젝트: dlq84/jsc
 def call(self, method, args):
     server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     for port in range(14000, 62000):
         try:
             server_socket.bind(("127.0.0.1", port))
             break
         except socket.error:
             continue
     server_socket.listen(5)
     ev = Event()
     input_thread = Process(target=input_reader, args=(port, ev))
     input_thread.start()
     (input_socket, _) = server_socket.accept()
     input_socket.setblocking(0)
     rpc_cmd = self.rpc(method, args)
     self._sendall(rpc_cmd)
     recv_buf = ""
     try:
         while True:
             rl, _, xl = select.select([self.ssh_channel, input_socket], [], [])
             if self.ssh_channel in rl:
                 if self.ssh_channel.recv_ready():
                     new_data = self.ssh_channel.recv(4096)
                     recv_buf += new_data
                     if "\n" in recv_buf:
                         lines = recv_buf.split("\n")
                         # Last line is either not complete or empty string.
                         # ("x\nnot compl".split("\n") => ['x', 'not compl'] or "x\n".split("\n") => ['x', ''])
                         # so we put it back in recv_buf for next iteration
                         recv_buf = lines.pop()
                         for line in lines:
                             resp = json.loads(line)
                             if "stdout" in resp:
                                 sys.stdout.write(resp["stdout"])
                                 sys.stdout.flush()
                             elif "stderr" in resp:
                                 log.white(resp["stderr"], f=sys.stderr)
                             elif "result" in resp:
                                 if resp['error'] is not None:
                                     raise SshRpcCallError(resp['error']['message'])
                                 #print("ending",method)
                                 return resp["result"]
                 if self.ssh_channel.recv_stderr_ready():
                     log.white("{}".format(self.ssh_channel.recv_stderr(4096)))
                 if self.ssh_channel.exit_status_ready():
                     raise SshRpcError()
             if input_socket in rl:
                 new_stdin_data = input_socket.recv(1024)
                 self._sendall(self.stdin(new_stdin_data))
     except (KeyboardInterrupt, SshRpcError):
         self.ssh_channel.shutdown(2)
         self.ssh_channel = None
         raise KeyboardInterrupt()
     finally:
         ev.set()
         input_thread.terminate()
         input_thread.join()
         del input_socket
         del server_socket
예제 #6
0
    def do_env(self, args):
        """
        Usage:
          env

        Dumps /app/env.json to console.
        """
        env_json = self._rpc.do_env()
        log.white(json.dumps(env_json, sort_keys=True, indent=4, separators=(',', ': ')))
예제 #7
0
    def do_sync(self, args):
        """
        Usage:
          sync

        Syncs software list so it becomes visable in the developer panel.
        """
        self._rpc.do_sync()
        log.white("sync done!")
예제 #8
0
 def _open_channel(self):
     try:
         self.ssh_channel = self.ssh_transport.open_session()
         self.ssh_channel.setblocking(0)
         self.ssh_channel.exec_command('/tmp/server')
         self.stdout_file = self.ssh_channel.makefile("r", 0)
     except paramiko.ssh_exception.SSHException:
         log.white("Connection lost, make sure the assembly is running, then reconnect.")
         os._exit(1)
예제 #9
0
 def put_file(fn_path_src, fn_path_dst):
     f_stat = os.stat(fn_path_src)
     bytes_left = f_stat.st_size
     log.white("putting local:{src} -> remote:{dst}".format(src=fn_path_src, dst=dst))
     with open(fn_path_src, "rb") as fo:
         while True:
             b64_content = base64.standard_b64encode(fo.read(chunk_size))
             rpc.do_file_append({"path": fn_path_dst, "content": b64_content})
             bytes_left -= chunk_size
             if bytes_left <= 0:
                 break
예제 #10
0
    def do_revert(self, args):
        """
        Usage:
          revert <id>

        Reverts a backup. This will destroy any changes you've made since backup.

        Arguments:
          <id>        Id of the backup to restore.
        """
        self._rpc.do_revert(args)
        log.white("revert of backup done!")
예제 #11
0
 def fn(self, arg):
     try:
         opt = docopt(fn.__doc__, shlex.split(arg))
     except DocoptExit as e:
         # The DocoptExit is thrown when the args do not match.
         # We print a message to the user and the usage block.
         log.white('Invalid Command!')
         log.white(e)
         return
     except SystemExit:
         # The SystemExit exception prints the usage for --help
         # We do not need to do the print here.
         return
     return func(self, {k.lstrip("<").rstrip(">"): opt[k] for k in opt})
예제 #12
0
    def do_ssh(self, args):
        """
        Usage:
          ssh

        Opens a new terminal and starts an SSH shell to this assembly.
        """
        if sys.platform.startswith("linux"):
            cmd_open = "xdg-open"
        elif sys.platform.startswith("darwin"):
            cmd_open = "open"
        else:
            log.white("Cannot start ssh shell since your platform [{platform}] is not supported.".format(platform=platform))
            return
        try:
            subprocess.check_call([cmd_open, "ssh://{uri}".format(uri=self._ssh_conn_str)])
        except subprocess.CalledProcessError:
            pass
예제 #13
0
    def do_backup(self, args):
        """
        Usage:
          backup [ls]
          backup new
          backup du
          backup rm <id>

        Managing backups.

        Arguments:
          ls        List backups.
          new       Create a new backup.
          du        Like ls, but also shows size and disk space usage.
          rm        Removes backup with supplied id.
        """
        resp = self._rpc.do_backup(args)
        if resp is not None:
            for line in resp:
                log.white(line)
예제 #14
0
 def call(self, method, args):
     rpc_cmd = self.rpc(method, args)
     self._sendall(rpc_cmd)
     recv_buf = ""
     stdin_fd = os.dup(sys.stdin.fileno())
     flags = fcntl.fcntl(stdin_fd, fcntl.F_GETFL, 0)
     flags |= os.O_NONBLOCK
     fcntl.fcntl(stdin_fd, fcntl.F_SETFL, flags)
     tty = os.fdopen(stdin_fd, "r", 0)
     try:
         # Some code stolen from getpass.py
         # getpass Authors: Piers Lauder (original)
         #                  Guido van Rossum (Windows support and cleanup)
         #                  Gregory P. Smith (tty support & GetPassWarning)b
         old = termios.tcgetattr(stdin_fd)     # a copy to save
         new = termios.tcgetattr(stdin_fd)
         new[3] &= ~termios.ECHO  # 3 == 'lflags'
         new[3] &= ~termios.ICANON  # 3 == 'lflags'
         tcsetattr_flags = termios.TCSADRAIN
         termios.tcsetattr(stdin_fd, tcsetattr_flags, new)
         while True:
             rl, _, xl = select.select([self.ssh_channel, stdin_fd], [], [])
             if self.ssh_channel in rl:
                 if self.ssh_channel.recv_ready():
                     new_data = self.ssh_channel.recv(4096)
                     recv_buf += new_data
                     if "\n" in recv_buf:
                         lines = recv_buf.split("\n")
                         # Last line is either not complete or empty string.
                         # ("x\nnot compl".split("\n") => ['x', 'not compl'] or "x\n".split("\n") => ['x', ''])
                         # so we put it back in recv_buf for next iteration
                         recv_buf = lines.pop()
                         for line in lines:
                             resp = json.loads(line)
                             if "stdout" in resp:
                                 log.white(resp["stdout"], f=sys.stdout)
                             elif "stderr" in resp:
                                 log.white(resp["stderr"], f=sys.stderr)
                             elif "result" in resp:
                                 if resp['error'] is not None:
                                     raise SshRpcCallError(resp['error']['message'])
                                 return resp["result"]
                 if self.ssh_channel.recv_stderr_ready():
                     log.white("{}".format(self.ssh_channel.recv_stderr(4096)))
                 if self.ssh_channel.exit_status_ready():
                     raise SshRpcError()
             if stdin_fd in rl:
                 new_stdin_data = tty.read()
                 self._sendall(self.stdin(new_stdin_data))
     except (KeyboardInterrupt, SshRpcError):
         # stdin_g.kill()
         self.ssh_channel.shutdown(2)
         self.ssh_channel = None
         raise KeyboardInterrupt()
     finally:
         termios.tcsetattr(stdin_fd, tcsetattr_flags, old)
         tty.flush()  # issue7208
         flags &= ~os.O_NONBLOCK
         fcntl.fcntl(stdin_fd, fcntl.F_SETFL, flags)
예제 #15
0
 def _server_update(self):
     try:
         channel = self.ssh_transport.open_session()
         channel.setblocking(0)
         # TODO: call server binary
         src = (repr(inspect.getsource(server_updater))+"\n").encode()
         channel.exec_command("env JSC_CLIENT_VERSION={version} python2 -c \"import sys;exec(eval(sys.stdin.readline()))\"".format(version=__version__))
         channel.sendall(src)
         while True:
             if channel.exit_status_ready():
                 break
             rl, wl, xl = select.select([channel], [], [])
             for _ in rl:
                 while channel.recv_stderr_ready():
                     log.white(channel.recv_stderr(4096).decode())
                 while channel.recv_ready():
                     log.white(channel.recv(4096).decode())
     except paramiko.ssh_exception.SSHException:
         log.white("Connection lost, make sure the assembly is running, then reconnect.")
         os._exit(1)
예제 #16
0
def update_self():
    # TODO: implement
    state_dir = os.path.expanduser("~/.jsc")
    touch_dir(state_dir)
    last_update_file = os.path.join(state_dir, "last_update")
    last_update_time = 0
    if os.path.exists(last_update_file):
        with open(last_update_file) as f:
            last_update_time = int(f.read().strip())
    epoch_time = int(time.time())
    if (epoch_time - last_update_time) > MIN_TIME_BETWEEN_UPDATES:
        log.white("Checking for updates of jsc")
        try:
            response = url.urlopen(PYPI_JSON)
            package_json = json.loads(response.read().decode())
            if dist_version.StrictVersion(package_json['info']['version']) > dist_version.StrictVersion(__version__):
                stop("There's a new version available, update with '# pip install -U jsc'")
            else:
                log.white("You're running the latest version of jsc")
            with open(last_update_file, "w") as f:
                f.truncate(0)
                f.write(str(epoch_time))
        except (url.URLError, ValueError):
            log.white("Could not check for updates, try '# pip install -U jsc'")
예제 #17
0
 def call(self, method, args):
     rpc_cmd = self.rpc(method, args)
     self._sendall(rpc_cmd)
     recv_buf = ""
     stdin_fd = os.dup(sys.stdin.fileno())
     flags = fcntl.fcntl(stdin_fd, fcntl.F_GETFL, 0)
     flags |= os.O_NONBLOCK
     fcntl.fcntl(stdin_fd, fcntl.F_SETFL, flags)
     tty = os.fdopen(stdin_fd, "r", 0)
     try:
         # Some code stolen from getpass.py
         # getpass Authors: Piers Lauder (original)
         #                  Guido van Rossum (Windows support and cleanup)
         #                  Gregory P. Smith (tty support & GetPassWarning)b
         old = termios.tcgetattr(stdin_fd)  # a copy to save
         new = termios.tcgetattr(stdin_fd)
         new[3] &= ~termios.ECHO  # 3 == 'lflags'
         new[3] &= ~termios.ICANON  # 3 == 'lflags'
         tcsetattr_flags = termios.TCSADRAIN
         termios.tcsetattr(stdin_fd, tcsetattr_flags, new)
         while True:
             rl, _, xl = select.select([self.ssh_channel, stdin_fd], [], [])
             if self.ssh_channel in rl:
                 if self.ssh_channel.recv_ready():
                     new_data = self.ssh_channel.recv(4096)
                     recv_buf += new_data
                     if "\n" in recv_buf:
                         lines = recv_buf.split("\n")
                         # Last line is either not complete or empty string.
                         # ("x\nnot compl".split("\n") => ['x', 'not compl'] or "x\n".split("\n") => ['x', ''])
                         # so we put it back in recv_buf for next iteration
                         recv_buf = lines.pop()
                         for line in lines:
                             resp = json.loads(line)
                             if "stdout" in resp:
                                 log.white(resp["stdout"], f=sys.stdout)
                             elif "stderr" in resp:
                                 log.white(resp["stderr"], f=sys.stderr)
                             elif "result" in resp:
                                 if resp['error'] is not None:
                                     raise SshRpcCallError(
                                         resp['error']['message'])
                                 return resp["result"]
                 if self.ssh_channel.recv_stderr_ready():
                     log.white("{}".format(
                         self.ssh_channel.recv_stderr(4096)))
                 if self.ssh_channel.exit_status_ready():
                     raise SshRpcError()
             if stdin_fd in rl:
                 new_stdin_data = tty.read()
                 self._sendall(self.stdin(new_stdin_data))
     except (KeyboardInterrupt, SshRpcError):
         # stdin_g.kill()
         self.ssh_channel.shutdown(2)
         self.ssh_channel = None
         raise KeyboardInterrupt()
     finally:
         termios.tcsetattr(stdin_fd, tcsetattr_flags, old)
         tty.flush()  # issue7208
         flags &= ~os.O_NONBLOCK
         fcntl.fcntl(stdin_fd, fcntl.F_SETFL, flags)
예제 #18
0
 def call(self, method, args):
     server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     for port in range(14000, 62000):
         try:
             server_socket.bind(("127.0.0.1", port))
             break
         except socket.error:
             continue
     server_socket.listen(5)
     ev = Event()
     input_thread = Process(target=input_reader, args=(port, ev))
     input_thread.start()
     (input_socket, _) = server_socket.accept()
     input_socket.setblocking(0)
     rpc_cmd = self.rpc(method, args)
     self._sendall(rpc_cmd)
     recv_buf = ""
     try:
         while True:
             rl, _, xl = select.select([self.ssh_channel, input_socket], [],
                                       [])
             if self.ssh_channel in rl:
                 if self.ssh_channel.recv_ready():
                     new_data = self.ssh_channel.recv(4096)
                     recv_buf += new_data
                     if "\n" in recv_buf:
                         lines = recv_buf.split("\n")
                         # Last line is either not complete or empty string.
                         # ("x\nnot compl".split("\n") => ['x', 'not compl'] or "x\n".split("\n") => ['x', ''])
                         # so we put it back in recv_buf for next iteration
                         recv_buf = lines.pop()
                         for line in lines:
                             resp = json.loads(line)
                             if "stdout" in resp:
                                 sys.stdout.write(resp["stdout"])
                                 sys.stdout.flush()
                             elif "stderr" in resp:
                                 log.white(resp["stderr"], f=sys.stderr)
                             elif "result" in resp:
                                 if resp['error'] is not None:
                                     raise SshRpcCallError(
                                         resp['error']['message'])
                                 #print("ending",method)
                                 return resp["result"]
                 if self.ssh_channel.recv_stderr_ready():
                     log.white("{}".format(
                         self.ssh_channel.recv_stderr(4096)))
                 if self.ssh_channel.exit_status_ready():
                     raise SshRpcError()
             if input_socket in rl:
                 new_stdin_data = input_socket.recv(1024)
                 self._sendall(self.stdin(new_stdin_data))
     except (KeyboardInterrupt, SshRpcError):
         self.ssh_channel.shutdown(2)
         self.ssh_channel = None
         raise KeyboardInterrupt()
     finally:
         ev.set()
         input_thread.terminate()
         input_thread.join()
         del input_socket
         del server_socket
예제 #19
0
def fail(message):
    log.white(message)
    os._exit(1)
예제 #20
0
def stop(message):
    log.white(message)
    os._exit(0)
예제 #21
0
 def default(self, line):
     """Called on an input line when the command prefix is not recognized.
        In that case we execute the line as Python code.
     """
     log.white("unknown command: [{line}]".format(line=line))
예제 #22
0
 def postloop(self):
     """Take care of any unfinished business.
        Despite the claims in the Cmd documentaion, Cmd.postloop() is not a stub.
     """
     cmd.Cmd.postloop(self)   # Clean up command completion
     log.white("Goodbye!")
예제 #23
0
 def do_hist(self, args):
     """Print a list of commands that have been entered"""
     log.white(self._hist)