1 | # -*- coding: utf-8 -*-
|
---|
2 | import base64
|
---|
3 | import os
|
---|
4 | import re
|
---|
5 | import gzip
|
---|
6 | import tarfile
|
---|
7 | from gluon.contrib.simplejsonrpc import ServerProxy
|
---|
8 | from gluon._compat import StringIO, ProtocolError, urlencode, urllib2
|
---|
9 |
|
---|
10 | def deploy():
|
---|
11 | response.title = T('Deploy to pythonanywhere')
|
---|
12 | return {}
|
---|
13 |
|
---|
14 |
|
---|
15 | def create_account():
|
---|
16 | """ Create a PythonAnywhere account """
|
---|
17 | if not request.vars:
|
---|
18 | raise HTTP(400)
|
---|
19 |
|
---|
20 | if request.vars.username and request.vars.web2py_admin_password:
|
---|
21 | # Check if web2py is already there otherwise we get an error 500 too.
|
---|
22 | client = ServerProxy('https://%(username)s:%(web2py_admin_password)s@%(username)s.pythonanywhere.com/admin/webservices/call/jsonrpc' % request.vars)
|
---|
23 | try:
|
---|
24 | if client.login() is True:
|
---|
25 | return response.json({'status': 'ok'})
|
---|
26 | except ProtocolError as error:
|
---|
27 | pass
|
---|
28 |
|
---|
29 | url = 'https://www.pythonanywhere.com/api/web2py/create_account'
|
---|
30 | data = urlencode(request.vars)
|
---|
31 | req = urllib2.Request(url, data)
|
---|
32 |
|
---|
33 | try:
|
---|
34 | reply = urllib2.urlopen(req)
|
---|
35 | except urllib2.HTTPError as error:
|
---|
36 | if error.code == 400:
|
---|
37 | reply = error
|
---|
38 | elif error.code == 500:
|
---|
39 | return response.json({'status':'error', 'errors':{'username': ['An App other than web2py is installed in the domain %(username)s.pythonanywhere.com' % request.vars]}})
|
---|
40 | else:
|
---|
41 | raise
|
---|
42 | response.headers['Content-Type'] = 'application/json'
|
---|
43 | return reply.read()
|
---|
44 |
|
---|
45 |
|
---|
46 | def list_apps():
|
---|
47 | """ Get a list of apps both remote and local """
|
---|
48 | if not request.vars.username or not request.vars.password:
|
---|
49 | raise HTTP(400)
|
---|
50 | client = ServerProxy('https://%(username)s:%(password)s@%(username)s.pythonanywhere.com/admin/webservices/call/jsonrpc' % request.vars)
|
---|
51 | regex = re.compile('^\w+$')
|
---|
52 | local = [f for f in os.listdir(apath(r=request)) if regex.match(f)]
|
---|
53 | try:
|
---|
54 | pythonanywhere = client.list_apps()
|
---|
55 | except ProtocolError as error:
|
---|
56 | raise HTTP(error.errcode)
|
---|
57 | return response.json({'local': local, 'pythonanywhere': pythonanywhere})
|
---|
58 |
|
---|
59 |
|
---|
60 | def bulk_install():
|
---|
61 | """ Install a list of apps """
|
---|
62 |
|
---|
63 | def b64pack(app):
|
---|
64 | """
|
---|
65 | Given an app's name, return the base64 representation of its packed version.
|
---|
66 | """
|
---|
67 | folder = apath(app, r=request)
|
---|
68 | tmpfile = StringIO()
|
---|
69 | tar = tarfile.TarFile(fileobj=tmpfile, mode='w')
|
---|
70 | try:
|
---|
71 | filenames = listdir(folder, '^[\w\.\-]+$', add_dirs=True,
|
---|
72 | exclude_content_from=['cache', 'sessions', 'errors'])
|
---|
73 | for fname in filenames:
|
---|
74 | tar.add(os.path.join(folder, fname), fname, False)
|
---|
75 | finally:
|
---|
76 | tar.close()
|
---|
77 | tmpfile.seek(0)
|
---|
78 | gzfile = StringIO()
|
---|
79 | w2pfp = gzip.GzipFile(fileobj=gzfile, mode='wb')
|
---|
80 | w2pfp.write(tmpfile.read())
|
---|
81 | w2pfp.close()
|
---|
82 | gzfile.seek(0)
|
---|
83 | return base64.b64encode(gzfile.read())
|
---|
84 |
|
---|
85 | request.vars.apps = request.vars['apps[]']
|
---|
86 | if not request.vars.apps or not request.vars.username or not request.vars.password:
|
---|
87 | raise HTTP(400)
|
---|
88 | if not isinstance(request.vars.apps, list):
|
---|
89 | request.vars.apps = [request.vars.apps] # Only one app selected
|
---|
90 |
|
---|
91 | client = ServerProxy('https://%(username)s:%(password)s@%(username)s.pythonanywhere.com/admin/webservices/call/jsonrpc' % request.vars)
|
---|
92 |
|
---|
93 | for app in request.vars.apps:
|
---|
94 | try:
|
---|
95 | client.install(app, app+'.w2p', b64pack(app))
|
---|
96 | except ProtocolError as error:
|
---|
97 | raise HTTP(error.errcode)
|
---|
98 |
|
---|
99 | return response.json({'status': 'ok'})
|
---|