Exemple #1
0
def auth_cookie():
    config = utils.user_config()
    if keyring:
        log.debug("Use keyring module. Great!")
        cookie = keyring.get_password("cookie:api.pytheon.net", config.pytheon.username)
    else:
        config = utils.user_config()
        cookie = config.pytheon.auth_cookie or None
    if cookie is not None:
        return {"Cookie": "auth_tkt=%s" % cookie}
    return None
Exemple #2
0
def save_cookie(headers):
    config = utils.user_config()
    for k, v in headers:
        if k.lower() == "set-cookie":
            cookie = SimpleCookie(v)
            auth_cookie = cookie["auth_tkt"].value
            log.debug("Cookie: %s", auth_cookie)
            if keyring:
                keyring.set_password("cookie:api.pytheon.net", config.pytheon.username, auth_cookie)
            else:
                config.pytheon.auth_cookie = auth_cookie
                config.write()
Exemple #3
0
def auth_basic(retry=False):
    config = utils.user_config()
    username = config.pytheon.username or utils.get_input("Username")
    password = None
    if keyring:
        log.debug("Use keyring module. Great!")
        password = keyring.get_password("basic:api.pytheon.net", username)
    if password == None or retry:
        password = utils.get_input("Password", password=True)
    if keyring:
        keyring.set_password("basic:api.pytheon.net", username, password)
    auth = base64.encodestring("%s:%s" % (username, password))
    return {"Authorization": "Basic " + auth.strip()}
Exemple #4
0
def create(parser, options, args):
    """create your pytheon project"""
    binary = utils.vcs_binary()

    global_config = utils.user_config()
    if not os.path.isfile(global_config._filename):
        global_config.pytheon = dict(
                username=options.username or utils.get_input('Username'),
            )
        global_config.write()
    rc = global_config.pytheon

    config = utils.project_config(filename=options.buildout)
    if not os.path.isfile(config._filename):
        if not options.project_name:
            options.project_name = utils.get_input('Project name',
                           default=os.path.basename(os.getcwd()))
        config.deploy = dict(
                version='1',
                use='gunicorn',
                project_name=options.project_name,
            )
    if options.project_name:
        config.deploy.project_name = options.project_name
    config.write()

    kw = dict(username=rc.username, project_name=config.deploy.project_name)
    if binary == 'git':
        remote = os.environ.get('PYTHEON_REMOTE',
                        '[email protected]:%(project_name)s.git').rstrip('/')
        remote = remote % kw
        utils.call(binary, 'remote', 'add', 'pytheon', remote, silent=True)

    else:
        remote = os.environ.get('PYTHEON_REMOTE',
                        '[email protected]/%(project_name)s').rstrip('/')
        remote = remote % kw
        filename = '.hg/hgrc'
        config = Config.from_file(filename)
        config.paths.pytheon = remote
        config.write()

    commit(binary, config._filename)

    return http.request('/v1/applications', name=config.deploy.project_name)
Exemple #5
0
def register(parser, options, args):
    """register on pytheon"""
    if options.key and options.reset:
        parser.error("You can't reset a password with a confirmation key")

    config = utils.user_config()
    if options.username:
        config.pytheon.username = options.username
        config.write()

    if not config.pytheon.username:
        parser.error('Please specify a valid email')

    if options.key:
        return http.request('/v1/set_password/%s' % options.key.strip('/'),
                            auth=False,
                            password=utils.get_input('Password',
                            password=True))
    elif options.reset:
        return http.request('/v1/reset_password/', auth=False,
                            email=options.username)
    else:
        return http.request('/v1/register', auth=False, email=options.username)
Exemple #6
0
def request(path, method="GET", auth=True, host=None, json=False, **params):
    config = utils.user_config()
    headers = {}

    if params:
        method = "POST"
        params = urlencode(params)
        headers["Content-Type"] = "application/x-www-form-urlencoded"
    else:
        params = None

    if json:
        headers["Accept"] = "application/json"
    else:
        headers["Accept"] = "text/plain"

    if auth:
        cookie_auth = auth_cookie()
        if cookie_auth is not None:
            log.debug("Use cookie: %s" % cookie_auth)
            headers.update(cookie_auth)
        else:
            log.debug("Use auth basic")
            headers.update(auth_basic())

    def get_conn(host):
        host, port = host.split(":")
        port = int(port)
        if port == 443:
            ## This HTTPSConnection *REQUIRES* a file containing concatenated
            ## PEM certificates of the authorities you trust. This means you
            ## *HAVE TO* bundle certificates with your application
            ## (as firefox does).
            ##
            ## If you are running on a debian/ubuntu system,
            ## mozilla certificates are located in
            ## /usr/share/ca-certificates/mozilla/ .You can concatenate
            ## them with the command :
            ## for cert in /usr/share/ca-certificates/mozilla/*crt; \
            ##      do cat $cert >> mozcerts.pem; done
            ##
            ## You may want to bundle *only* your server certificate/your ca
            ## certificate with your application to make it more secure.
            conn = HTTPSConnection(host, ca_certs)
        else:
            conn = httplib.HTTPConnection(host, port)
        return conn

    host = host or config.pytheon.api_host or "api.pytheon.net:443"
    try:
        conn = get_conn(host)
        conn.request(method, path, params, headers)
        resp = conn.getresponse()
    except socket.error:
        raise
        raise OSError("Unable to contact %s" % host)

    if resp.status == 401 and cookie_auth is not None:
        log.info("Invalid password or session is expired")
        headers.update(auth_basic(retry=True))
        del headers["Cookie"]
        conn = get_conn(host)
        conn.request(method, path, params, headers)
        resp = conn.getresponse()

    data = resp.read()
    if resp.status != 200:
        log.error("%d - %s " % (resp.status, resp.reason))
        if resp.status == 500:
            sys.exit(1)

    save_cookie(resp.getheaders())
    if resp.getheader("Content-Type", "text/plain") == "application/json":
        return json.loads(data)
    return data
Exemple #7
0
    def test_cli(self):
        out = run('register', '-e', self.email)
        self.assertIn('check', out.lower())

        u = self.get_user().fetchone()
        out = run('register', '-e', self.email)
        self.assertIn(' is already used', out.lower())

        # avoid prompt
        os.environ['TEST_PASSWORD'] = '******'

        key = '%s/%s' % (u.id, u.register_key)
        out = run('register', '-e', self.email, '-k', key)
        self.assertIn('password set', out.lower())

        # init git server
        gitolite = join(self.home, '.gitolite')
        os.makedirs(gitolite)
        self.writeFile('''
[git]
url = %(repos)s
        ''' % dict(repos=join(self.home, 'repos')),
        gitolite, 'pytheon.ini')

        repo = join(self.home, 'repos', 'test-project.git')
        os.makedirs(repo)
        self.runCommand(['git', 'init', '--bare', repo])
        self.writeFile('''#!/bin/sh
%s --app-name=www --git-url=%s --testing
            ''' % (post_receive, repo),
            repo, 'hooks', 'post-receive')
        self.runCommand(['chmod', '+x', join(repo, 'hooks', 'post-receive')])

        os.environ['PYTHEON_REMOTE'] = join(self.home, 'repos', '%(project_name)s.git')

        # init git config and project repo
        self.runCommand(['git', 'init'])
        self.runCommand(['git', 'config', 'user.name', '"Your Name"'])
        self.runCommand(['git', 'config', 'user.email', '*****@*****.**'])
        self.writeFile('''DATABASES = {}; URLS='urls.py''', 'settings.py')
        self.runCommand(['git', 'add', '-A'])
        self.runCommand(['git', 'commit', '-m', 'changes'])

        # create project on pytheon with invalid name
        #out = run('create', '-n', 'test_project')
        #self.assertIn('Applications names must be composed of only letters, '
        #               'digits and hyphens and cannot start with a hyphen', out)

        # create project on pytheon
        out = run('create', '-n', 'test-project')
        self.assertIn('Application test-project created', out)

        # now we can use the cookie
        config = utils.user_config()
        self.assertIn('auth_cookie', config.pytheon)
        del os.environ['TEST_PASSWORD']

        # deploy
        self.runCommand(['git', 'status'])
        run('deploy')

        # api calls
        out = run('apps', '-l')
        self.assertIn('- test-project', out)

        out = run('addons', '--all')
        self.assertIn('- mysql', out)

        out = run('addons', '-l')
        self.assertIn('- No addons', out)

        out = run('addons', '--add', 'mysql:premium')
        self.assertIn('You cannot access this resource', out)

        resp = self.wsgi_app.get('/update_model', dict(model='User', field='email',
                                                       value=self.email, payment_ok='true'))
        out = run('addons', '--add', 'mysql:basic')
        self.assertIn('Addon added', out)

        out = run('addons', '--upgrade', 'mysql:premium')
        self.assertIn('Addon plan changed', out)

        out = run('addons', '--delete', 'mysql')
        self.assertIn('Addon removed', out)

        out = run('addons', '--add', 'mysql:premium')
        self.assertIn('Addon added', out)

        out = run('addons', '-l')
        self.assertIn('- mysql', out)

        out = run('apps', '--delete', 'test-project')
        self.assertIn('Application deleted', out)

        out = run('apps', '-l')
        self.assertIn('- No application', out)

        ## Test ssh keys
        key_file = self.writeFile("ssh-rsa sdfsdfsdf\n",
                                  self.wd, "pytheon-key1")
        key_file2 = self.writeFile("ssh-rsa 2sdfsdfsdf\n",
                                   self.wd, "pytheon-key2")
        key_file3 = self.writeFile("ssh-rsa 3sdfsdfsdf\n",
                                   self.wd, "pytheon-key3")
        key_file4 = self.writeFile("ssh-rsa 4sdfsdfsdf\n",
                                   self.wd, "pytheon-key4")
        fake_key = self.writeFile("fake file\n",
                                   self.wd, "pytheon-fake-key")

        out = run('add_key', fake_key)
        #self.assertIn('File %s does not seems to be a public key.', out)

        out = run('add_key', key_file)
        self.assertIn('Key added', out)
        out = run('add_key', key_file2)
        self.assertIn('Key added', out)
        out = run('add_key', key_file)
        self.assertIn('Key added', out)

        out = run('add_key', '-n',
            '*****@*****.**',
            key_file3)
        self.assertIn('Key added', out)
        out = run('add_key', '-n',
            '*****@*****.**',
            key_file4)
        self.assertIn('A key with this name already exists', out)
Exemple #8
0
from __future__ import with_statement
import os
import os.path
import sys
import logging as log
import functools
from pytheon import http
from pytheon import utils
from pytheon.utils import Config
from optparse import OptionParser
# totot
commands = []
project_commands = []

filename = os.path.expanduser('~/.pytheonrc')
global_config = utils.user_config()


def with_project(func):
    @functools.wraps(func)
    def wrapped(parser, options, args):
        config = utils.project_config()
        if not os.path.isfile(config._filename):
            parser.error('It look like you are not in a valid pytheon project')
        elif not config.deploy.project_name:
            parser.error('It look like you are not in a valid pytheon project')
        return func(parser, options, args, config)
    wrapped.project_command = True
    return wrapped