Example #1
0
    def config(self):
        """return a valid deploy section extracted from project's ini files"""
        deploy = join(self.etc_dir, 'deploy.ini')
        current = Config.from_file(deploy)

        http_host = os.environ.get('IP', '127.0.0.1')
        if 'PORT' in os.environ:
            http_port = os.environ('PORT')
        else:
            filename = join(self.etc_dir, 'http_port.txt')
            if os.path.isfile(filename):
                http_port = open(filename).read().strip()
            else:
                http_port = current['server:pytheon'].port or \
                            utils.get_free_port()
                f = open(join(self.etc_dir, 'http_port.txt'), 'w')
                f.write(str(http_port))
                f.close()

        self.options['bind'] = '%s:%s' % (http_host, http_port)

        filename = join(self.curdir,
                        'deploy-%s.ini' % self.options['project_name'])
        if not os.path.isfile(filename):
            filename = join(self.curdir, 'deploy.ini')
        config = Config.from_file(filename, here=self.curdir, __file__=deploy)
        config['server:pytheon'] = dict(use='egg:Paste#http',
                                        host=http_host, port=http_port)

        if self.is_django:
            config['app:main'] = {
                    'paste.app_factory':
                            'pytheon.deploy.django_utils:make_django',
                  }

        fd = StringIO()
        config.write(fd)
        fd.seek(0)
        data = fd.read()
        data = data.replace('%(here)s', self.curdir)

        fd = open(deploy, 'w')
        fd.write(data)
        fd.close()

        return deploy
Example #2
0
def admin():

    root = os.path.join(os.getcwd(), 'root')

    parser.add_option("-i", "--interpreter", dest="interpreter",
                      action="store", default=sys.executable,
                      help='Default to: ' + sys.executable)
    parser.add_option("-d", "--deploy", dest="source",
                      action="store", metavar='SOURCE',
                      default=os.environ.get('SOURCE', None),
                      help='Default to $SOURCE if exist.')
    parser.add_option("-b", "--branch", dest="branch",
                      action="store",
                      default=os.environ.get('BRANCH', None),
                      help='Default to $BRANCH if exist')
    parser.add_option("-a", "--app-name", dest="app_name",
                      action="store", default=None)
    parser.add_option("--destroy", dest="destroy",
                      action="store")
    parser.add_option("--host", dest="host",
                      action="append",
                      default=os.environ.get('HOSTS', '').split(';'))
    parser.add_option("-r", "--root", dest="root",
                      action="store", default=root,
                      help='Default to %s' % root)
    parser.add_option("-e", "--eggs", dest="eggs",
                      action="store", default=os.path.expanduser('~/eggs'),
                      help='Default to: ' + os.path.expanduser('~/eggs'))
    parser.add_option("--develop", dest="develop",
                      action="append", default=[], help="Testing only")
    parser.add_option("--develop-dir", dest="develop_dir",
                      default=os.environ.get('DEVELOP_DIR', None),
                      help=("Used for buildout:develop-dir. "
                            "Default to $DEVELOP_DIR if exist"))

    (options, args) = parser.parse_args()

    if 'GIT_DIR' in os.environ:
        del os.environ['GIT_DIR']

    if not options.root:
        parser.error('Invalid root option')

    root = utils.realpath(options.root)

    if not os.path.isdir(options.root):
        parser.error('Invalid root option')

    os.chdir(root)

    def guess_app():
        for ext in ('.hg', '.git'):
            app_dirs = glob(join(root, '*', ext))
            if len(app_dirs) == 1:
                app_dir = os.path.dirname(app_dirs[0])
                return app_dir

    app_dir = guess_app()

    if options.destroy:
        if not app_dir:
            parser.error('No application in %s' % options.root)
        supervisor = join(app_dir, 'bin', 'supervisorctl')
        if os.path.isfile(supervisor):
            utils.call(supervisor, 'shutdown', silent=True)
            time.sleep(0.5)
        shutil.rmtree(options.root)
        sys.exit(0)

    if options.source:
        if app_dir and os.path.isdir(app_dir):
            shutil.rmtree(app_dir)
        if not options.source:
            parser.error('No source option')
        log.info(options.source)
        # .git url or local path are git repositories
        if options.source.endswith('.git') or options.source.startswith('/'):
            if options.app_name:
                utils.call('git', 'clone', '-q', options.source,
                                                 options.app_name)
            else:
                utils.call('git', 'clone', '-q', options.source)
            app_dir = guess_app()
            log.info(app_dir)
            os.chdir(app_dir)
            if not options.branch:
                options.branch = 'master'
            utils.call('git', 'checkout', options.branch)
        else:
            if options.app_name:
                utils.call('hg', 'clone', '-q', options.source,
                                                options.app_name)
            else:
                utils.call('hg', 'clone', '-q', options.source)
            app_dir = guess_app()
            log.info(app_dir)
            os.chdir(app_dir)
            if options.branch and options.branch != 'master':
                # dont take care of hg branch for now
                pass
    elif app_dir is None:
        parser.error('You must have an existing repository or a deploy url')

    os.chdir(app_dir)
    app_name = os.path.basename(app_dir)

    if os.path.isfile('setup.py'):
        options.develop.insert(0, '.')

    for setup in glob(join(app_dir, '*', 'setup.py')):
        options.develop.append(os.path.dirname(setup))

    for setup in glob(join(app_dir, 'src', '*', 'setup.py')):
        options.develop.append(os.path.dirname(setup))

    var = utils.realpath(root, 'var', 'buildout')

    config = Config.from_template('pytheon.cfg')
    config.buildout['dump-picked-versions-file'] = join(root, 'etc',
                                                              'versions.cfg')
    config.buildout['eggs-directory'] = options.eggs or join(var, 'eggs')
    config.buildout['parts-directory'] = join(var, 'parts')
    config.buildout['develop-eggs-directory'] = join(var, 'develop-eggs')
    config.buildout.develop = options.develop
    config.deploy.recipe = 'pytheon.deploy'
    config.deploy['deploy-dir'] = root
    if options.develop_dir:
        config.buildout['develop-dir'] = options.develop_dir
    if options.host:
        config.deploy.host = options.host
    config.deploy.environ = ['PYTHEON=1', 'PRODUCTION=1'] + list(args)

    if os.path.isfile('requirements.txt'):
        config.buildout.requirements = 'requirements.txt'

    extends = []
    for filename in ('buildout.cfg', 'versions.cfg',
                     'deploy-%s.ini' % app_name, 'deploy.ini'):
        filename = utils.realpath(os.getcwd(), filename)
        if os.path.isfile(filename):
            extends.append(filename)
    config.buildout.extends = extends

    buildout = 'pytheon.cfg'
    config.write(buildout)

    env = os.environ
    env.update(dict([v.split('=', 1) for v in args if '=' in v]))

    utils.buildout(options.interpreter, buildout,
                   eggs=CONFIG.pytheon.eggs_dir, env=env)

    if os.path.isfile('post_install.sh'):
        lib_dir = join(root, 'lib')
        if os.path.isfile(os.path.join(lib_dir, 'environ.py')):
            execfile(os.path.join(lib_dir, 'environ.py'))
        utils.call('/bin/bash', 'post_install.sh', env=os.environ)
Example #3
0
def build_eggs(args=None):

    parser.add_option("-i", "--interpreter", dest="interpreters",
                      action="append", default=[])

    if args is not None:
        (options, args) = parser.parse_args(args)
    else:
        (options, args) = parser.parse_args()

    interpreters = options.interpreters or \
                   ['.'.join([str(i) for i in sys.version_info[:2]])]

    bin_dir = os.path.dirname(os.path.abspath(sys.argv[0]))

    if 'PYTHEON_EGGS_DIR' in os.environ:
        eggs_dir = os.environ['PYTHEON_EGGS_DIR']
    else:
        eggs_dir = os.path.join(os.getcwd(), 'eggs')

    if 'PYTHEON_PREFIX' in os.environ:
        pwd = os.path.join(os.environ['PYTHEON_PREFIX'], 'lib', 'pytheon')
    else:
        pwd = os.path.dirname(eggs_dir)

    env = os.environ
    env.update(
        PYTHEON_PREFIX=env.get('PYTHEON_PREFIX', pwd),
        PYTHEON_EGGS_DIR=env.get('PYTHEON_EGGS_DIR', eggs_dir))

    os.chdir(pwd)

    for i, interpreter in enumerate(interpreters):
        build_dir = os.path.join(pwd, 'build', interpreter)
        if not os.path.isdir(build_dir):
            os.makedirs(build_dir)
        os.chdir(build_dir)
        if os.path.isfile('.installed.cfg'):
            os.unlink('.installed.cfg')
        buildout = os.path.join(build_dir, 'buildout-%s.cfg' % interpreter)
        config = Config.from_template('build_eggs.cfg')
        config.buildout['bin-directory'] = bin_dir
        config.buildout['eggs-directory'] = eggs_dir
        config.buildout['dump-picked-versions-file'] = os.path.join(
                               eggs_dir, 'python%s-versions.cfg' % interpreter)
        config.buildout.extends = CONFIG.build_eggs.extends
        config.buildout['find-links'] = [
            'https://github.com/pytheon/pytheon/tarball/master#egg=pytheon',
            ('https://github.com/pytheon/pytheon.deploy/tarball/master'
             '#egg=pytheon.deploy'),
          ]
        config.versions = {'none': '0.0'}
        eggs = CONFIG.build_eggs.eggs.as_list()
        for egg in ['pytheon.deploy', 'zc.buildout']:
            if egg not in eggs:
                eggs.insert(0, egg)
        config.deploy.eggs = eggs + ['${buildout:eggs}']
        scripts = CONFIG.build_eggs.scripts.as_list()
        for script in ['buildout', 'pytheon-admin']:
            if script not in scripts:
                scripts.append(script)
        scripts = ['%s=%s-%s' % (s, s, interpreter) for s in scripts]
        config.deploy.scripts = scripts
        config.deploy.initialization = [
            "import os",
            "os.environ['PYTHEON_PREFIX'] = %(PYTHEON_PREFIX)r" % env,
            ("os.environ['PYTHEON_EGGS_DIR'] ="
             "os.environ['PYTHON_EGGS'] = %(PYTHEON_EGGS_DIR)r") % env,
          ]
        config.write(buildout)
        utils.buildout('python%s' % interpreter, buildout=buildout,
                                                 eggs=eggs_dir)
Example #4
0
    def install_wsgi(self):
        """Install a wsgi application and scripts. Take care of django"""
        eggs = Scripts(self.buildout, self.options['recipe'], self.options)
        reqs, ws = eggs.working_set()

        filename = self.buildout['buildout'].get('dump-picked-versions-file')
        if filename:
            config = Config()
            config.versions = dict(
                            [(pkg.project_name, pkg.version) for pkg in ws])
            config.write(filename)

        extra_paths = self.options.get('extra-paths', '')
        extra_paths = extra_paths.split()
        if self.is_django:
            extra_paths.append(os.path.dirname(self.django_setttings))

        self.install_script(name='scripts', extra_paths=extra_paths)

        # now we can switch in offline mode
        self.buildout['buildout']['offline'] = 'true'

        config = self.config
        addons_requires = self.addons_requires
        self.install_script(
                name='wsgi',
                bin_directory=self.lib_dir,
                entry_points='pytheon_wsgi.py=logging:warn',
                scripts='pytheon_wsgi.py=pytheon_wsgi.py',
                arguments='"%s run as a main module", __file__',
                extra_paths=extra_paths,
                eggs=self.options['eggs'] +
                     '\npytheon.deploy\nPasteDeploy\nsqlalchemy' +
                     addons_requires,
                script_initialization=WSGI_SCRIPT % config,
                )
        wsgi_script = os.path.join(self.lib_dir, 'pytheon_wsgi.py')

        # bin/touch script
        self.install_script(
                name='touch',
                scripts='touch-wsgi=touch-wsgi',
                extra_paths='', eggs='',
                entry_points='touch-wsgi=os:utime',
                arguments='%r, (t, t)' % wsgi_script,
                script_initialization='import time; t = time.time()')

        # bin/backup-db
        backup_db = os.path.join(
                os.path.dirname(os.path.abspath(sys.argv[0])),
                'backup-db')
        if os.path.isfile(backup_db):
            self.install_script(
                name='backup',
                scripts='backup-db=backup-db',
                extra_paths='', eggs='',
                entry_points='backup-db=subprocess:call',
                arguments='[%r]' % backup_db)

        if utils.PY3:
            # add lib dir to extra_paths so cherrypy can find the wsgi script
            dirname = os.path.dirname(wsgi_script)
            self.install_script(
                    name='cherrypy',
                    scripts='pytheon-serve\nceleryd=celeryd',
                    extra_paths=[dirname] + extra_paths,
                    entry_points=('pytheon-serve='
                                  'pytheon.deploy.scripts:cherrypy_serve'),
                    eggs=self.options['eggs'] +
                         '\npytheon.deploy\nPasteDeploy\nsqlalchemy' +
                         addons_requires,
                    script_initialization=SERVE % ([config,
                                                    self.options['bind']],)
                    )
        elif self.options.get('use', 'gunicorn') == 'gunicorn':
            self.options['bind'] = 'unix:%s' % join(self.run_dir,
                                                    'gunicorn.sock')
            gu_config = self.install_config('gunicorn_config.py')
            # add lib dir to extra_paths so gunicorn can find the wsgi script
            dirname = os.path.dirname(wsgi_script)
            self.install_script(
                    name='gunicorn',
                    scripts='gunicorn=pytheon-serve\nceleryd=celeryd',
                    extra_paths=[dirname] + extra_paths,
                    eggs=self.options['eggs'] +
                         '\npytheon.deploy\ngunicorn\nsqlalchemy' +
                         addons_requires,
                    script_initialization=SERVE % (
                                                ["-c", gu_config,
                                                 "pytheon_wsgi:application"],))
        else:
            self.install_script(
                    name='pastescript',
                    scripts='paster=pytheon-serve\nceleryd=celeryd',
                    extra_paths=extra_paths,
                    eggs=self.options['eggs'] +
                         '\npytheon.deploy\nPasteScript\nsqlalchemy' +
                         addons_requires,
                    script_initialization=SERVE % (
                                                ["serve",
                                                 "--server-name=pytheon",
                                                 config],))

        if self.is_django:
            self.install_script(
                    name='django',
                    scripts='manage',
                    eggs=self.options['eggs'] +
                         '\npytheon.deploy\nsqlalchemy' + addons_requires,
                    entry_points='manage=pytheon.deploy.django_utils:manage',
                    extra_paths=extra_paths,
                    arguments='%r' % config)

        if 'CELERY_URL' in os.environ:
            celeryconfig = join(self.lib_dir, 'celeryconfig.py')
            if not os.path.isfile(celeryconfig):
                self.install_config('celeryconfig.py', output=celeryconfig)

        if not os.path.isfile(join(self.bin_dir, 'pytheon-update')):
            self.install_script(
                    name='buildout',
                    scripts='buildout=pytheon-update',
                    eggs='pytheon.deploy\nzc.buildout',
                    script_initialization=BUILDOUT % self.curdir,
                    )

        return tuple()