class GoApp:
  def __init__(self, root_path):
    self.root_path = root_path
    self.proc = None
    self.proc_start = 0
    self.goroot = os.path.join(

        up(__file__, 5),
        "goroot")
    if not os.path.isdir(self.goroot):
      raise Exception('no goroot found at ' + self.goroot)


    for bin in os.listdir(os.path.join(self.goroot, 'bin')):
      if len(bin) == 2 and bin[1] == 'g':
        self.arch = bin[0]
        break
    if not self.arch:
      raise Exception('bad goroot: no compiler found')

    atexit.register(self.cleanup)

  def cleanup(self):
    if self.proc:
      os.kill(self.proc.pid, signal.SIGTERM)

  def make_and_run(self, env):
    app_files = find_app_files(self.root_path)
    go_files, go_mtime = find_go_files_mtime(app_files)
    if not go_files:
      raise Exception('no .go files in %s', self.root_path)
    app_mtime = max(app_files.values())
    bin_name, bin_mtime = os.path.join(GAB_WORK_DIR, GO_APP_NAME), 0
    try:
      bin_mtime = os.stat(bin_name)[stat.ST_MTIME]
    except:
      pass




    rebuild, restart = False, False
    if go_mtime >= bin_mtime:
      rebuild, restart = True, True
    elif app_mtime > self.proc_start:
      restart = True

    if restart and self.proc:
      os.kill(self.proc.pid, signal.SIGTERM)
      self.proc.wait()
      self.proc = None
    if rebuild:
      self.build(go_files)


    if not self.proc or self.proc.poll() is not None:
      logging.info('running ' + GO_APP_NAME)

      limited_env = {
          'PWD': self.root_path,
          'TZ': 'UTC',
      }
      for k, v in env.items():
        if ENV_PASSTHROUGH.match(k):
          limited_env[k] = v
      self.proc_start = app_mtime
      self.proc = subprocess.Popen([bin_name,
          '-addr_http', 'unix:' + SOCKET_HTTP,
          '-addr_api', 'unix:' + SOCKET_API],
          stderr=subprocess.PIPE,
          cwd=self.root_path, env=limited_env)
      tee = Tee(self.proc.stderr, sys.stderr)
      tee.start()
      wait_until_go_app_ready(self.proc, tee)

  def build(self, go_files):
    logging.info('building ' + GO_APP_NAME)
    if not os.path.exists(GAB_WORK_DIR):
      os.makedirs(GAB_WORK_DIR)
    gab_argv = [
        os.path.join(self.goroot, 'bin', 'go-app-builder'),
        '-app_base', self.root_path,
        '-arch', self.arch,
        '-binary_name', GO_APP_NAME,
        '-dynamic',
        '-goroot', self.goroot,
        '-unsafe',
        '-work_dir', GAB_WORK_DIR] + go_files
    try:
      p = subprocess.Popen(gab_argv, stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE, env={})
      gab_retcode = p.wait()
    except Exception, e:
      raise Exception('cannot call go-app-builder', e)
    if gab_retcode != 0:
      raise dev_appserver.CompileError(p.stdout.read() + '\n' + p.stderr.read())
            raise dev_appserver.CompileError(p.stdout.read() + '\n' +
                                             p.stderr.read())

    def extras_hash(self, go_files):
        logging.info('checking extra files')
        gab_argv = self._gab_args() + ['-print_extras_hash'] + go_files
        try:
            p = subprocess.Popen(gab_argv,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 env={})
            gab_retcode = p.wait()
        except Exception, e:
            raise Exception('cannot call go-app-builder', e)
        if gab_retcode != 0:
            raise dev_appserver.CompileError(p.stderr.read())
        return p.stdout.read()


OldSigTermHandler = None


def SigTermHandler(signum, frame):
    if GO_APP:
        GO_APP.cleanup()
    if OldSigTermHandler:
        OldSigTermHandler(signum, frame)


def execute_go_cgi(root_path, config, handler_path, cgi_path, env, infile,
                   outfile):
class GoApp:
    def __init__(self, root_path):
        self.root_path = root_path
        self.proc = None
        self.proc_start = 0
        self.last_extras_hash = None
        self.goroot = os.path.join(up(__file__, 5), 'goroot')
        if not os.path.isdir(self.goroot):
            raise Exception('no goroot found at ' + self.goroot)

        self.arch = None
        arch_map = {
            'arm': '5',
            'amd64': '6',
            '386': '8',
        }
        for p in os.listdir(os.path.join(self.goroot, 'pkg', 'tool')):

            if '_' not in p:
                continue
            arch = p.split('_', 1)[1]
            if arch in arch_map:
                self.arch = arch_map[arch]
                break
        if not self.arch:
            raise Exception('bad goroot: no compiler found')

        atexit.register(self.cleanup)

    def cleanup(self):
        if self.proc:
            quiet_kill(self.proc.pid)
            self.proc = None

    def make_and_run(self, env):
        app_files = find_app_files(self.root_path)
        go_files, go_mtime = find_go_files_mtime(app_files)
        if not go_files:
            raise Exception('no .go files in %s', self.root_path)
        app_mtime = max(app_files.values())
        bin_name, bin_mtime = os.path.join(GAB_WORK_DIR, GO_APP_NAME), 0
        try:
            bin_mtime = os.stat(bin_name)[stat.ST_MTIME]
        except:
            pass

        rebuild, restart = False, False
        if go_mtime >= bin_mtime:
            rebuild, restart = True, True
        elif app_mtime > self.proc_start:
            restart = True
        if not rebuild:

            h = self.extras_hash(go_files)
            if h != self.last_extras_hash:
                logging.info('extra-app files hash changed to %s; rebuilding',
                             h)
                self.last_extras_hash = h
                rebuild, restart = True, True

        if restart and self.proc:
            quiet_kill(self.proc.pid)
            self.proc.wait()
            self.proc = None
        if rebuild:
            self.build(go_files)

        if not self.proc or self.proc.poll() is not None:
            logging.info('running %s, HTTP port = %d, API port = %d',
                         GO_APP_NAME, GO_HTTP_PORT, GO_API_PORT)

            limited_env = {
                'GOROOT': self.goroot,
                'PWD': self.root_path,
                'TZ': 'UTC',
            }
            for k, v in env.items():
                if ENV_PASSTHROUGH.match(k):
                    limited_env[k] = v
            for e in OS_ENV_PASSTHROUGH:
                if e in os.environ:
                    limited_env[e] = os.environ[e]
            self.proc_start = app_mtime
            self.proc = subprocess.Popen([
                bin_name, '-addr_http',
                'tcp:127.0.0.1:%d' % GO_HTTP_PORT, '-addr_api',
                'tcp:127.0.0.1:%d' % GO_API_PORT
            ],
                                         stderr=subprocess.PIPE,
                                         cwd=self.root_path,
                                         env=limited_env)
            tee = Tee(self.proc.stderr, sys.stderr)
            tee.start()
            wait_until_go_app_ready(self.proc, tee)

    def _gab_args(self):
        argv = [
            os.path.join(self.goroot, 'bin', 'go-app-builder'),
            '-app_base',
            self.root_path,
            '-arch',
            self.arch,
            '-binary_name',
            GO_APP_NAME,
            '-dynamic',
            '-goroot',
            os.environ['GOROOT'],
            '-unsafe',
            '-work_dir',
            GAB_WORK_DIR,
        ]
        if 'GOPATH' in os.environ:
            argv.extend(['-gopath', os.environ['GOPATH']])
        return argv

    def build(self, go_files):
        logging.info('building ' + GO_APP_NAME)
        if not os.path.exists(GAB_WORK_DIR):
            os.makedirs(GAB_WORK_DIR)
        gab_argv = self._gab_args() + go_files
        try:
            p = subprocess.Popen(gab_argv,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 env={})
            gab_retcode = p.wait()
        except Exception, e:
            raise Exception('cannot call go-app-builder', e)
        if gab_retcode != 0:
            raise dev_appserver.CompileError(p.stdout.read() + '\n' +
                                             p.stderr.read())
Exemple #4
0
class GoApp:
    def __init__(self, root_path):
        self.root_path = root_path
        self.proc = None
        self.goroot = os.path.join(up(__file__, 5), "goroot")
        if not os.path.isdir(self.goroot):
            raise Exception('no goroot found at ' + self.goroot)

        for bin in os.listdir(os.path.join(self.goroot, 'bin')):
            if len(bin) == 2 and bin[1] == 'g':
                self.arch = bin[0]
                break
        if not self.arch:
            raise Exception('bad goroot: no compiler found')

    def make_and_run(self):
        go_files, go_mtime = find_go_files_mtime(self.root_path)
        if not go_files:
            raise Exception('no .go files in %s', self.root_path)
        app_name, app_mtime = os.path.join(GAB_WORK_DIR, GO_APP_NAME), 0
        try:
            app_mtime = os.stat(app_name)[stat.ST_MTIME]
        except:
            pass

        if go_mtime >= app_mtime:
            if self.proc:
                os.kill(self.proc.pid, signal.SIGTERM)
                self.proc.wait()
                self.proc = None
            self.build(go_files, app_name)

        if not self.proc or self.proc.poll() is not None:
            logging.info('running ' + GO_APP_NAME)
            self.proc = subprocess.Popen([
                app_name, '-addr_http', 'unix:' + SOCKET_HTTP, '-addr_api',
                'unix:' + SOCKET_API
            ],
                                         cwd=self.root_path)
            wait_until_go_app_ready()

    def build(self, go_files, app_name):
        logging.info('building ' + GO_APP_NAME)
        if not os.path.exists(GAB_WORK_DIR):
            os.makedirs(GAB_WORK_DIR)
        gab_argv = [
            os.path.join(self.goroot, 'bin',
                         'go-app-builder'), '-app_base', self.root_path,
            '-arch', self.arch, '-binary_name', GO_APP_NAME, '-dynamic',
            '-goroot', self.goroot, '-unsafe', '-work_dir', GAB_WORK_DIR
        ] + go_files
        try:
            p = subprocess.Popen(gab_argv,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
            gab_retcode = p.wait()
        except Exception, e:
            raise Exception('cannot call go-app-builder', e)
        if gab_retcode != 0:
            raise dev_appserver.CompileError(p.stdout.read() + '\n' +
                                             p.stderr.read())