2
0
mirror of https://github.com/frappe/bench.git synced 2024-11-12 00:06:36 +00:00

[cleanup] bench path

This commit is contained in:
Anand Doshi 2016-06-16 11:18:51 +05:30
parent 47662c4d90
commit 8ff5519959
14 changed files with 280 additions and 264 deletions

View File

@ -3,3 +3,11 @@ from jinja2 import Environment, PackageLoader
__version__ = "4.0.0-beta"
env = Environment(loader=PackageLoader('bench.config'), trim_blocks=True)
FRAPPE_VERSION = None
def set_frappe_version(bench_path='.'):
from .app import get_current_frappe_version
global FRAPPE_VERSION
if not FRAPPE_VERSION:
FRAPPE_VERSION = get_current_frappe_version(bench_path=bench_path)

View File

@ -9,6 +9,7 @@ import semantic_version
import json
import re
import subprocess
import bench
logging.basicConfig(level="DEBUG")
logger = logging.getLogger(__name__)
@ -22,30 +23,30 @@ class MajorVersionUpgradeException(Exception):
self.upstream_version = upstream_version
self.local_version = local_version
def get_apps(bench='.'):
def get_apps(bench_path='.'):
try:
with open(os.path.join(bench, 'sites', 'apps.txt')) as f:
with open(os.path.join(bench_path, 'sites', 'apps.txt')) as f:
return f.read().strip().split('\n')
except IOError:
return []
def add_to_appstxt(app, bench='.'):
apps = get_apps(bench=bench)
def add_to_appstxt(app, bench_path='.'):
apps = get_apps(bench_path=bench_path)
if app not in apps:
apps.append(app)
return write_appstxt(apps, bench=bench)
return write_appstxt(apps, bench_path=bench_path)
def remove_from_appstxt(app, bench='.'):
apps = get_apps(bench=bench)
def remove_from_appstxt(app, bench_path='.'):
apps = get_apps(bench_path=bench_path)
if app in apps:
apps.remove(app)
return write_appstxt(apps, bench=bench)
return write_appstxt(apps, bench_path=bench_path)
def write_appstxt(apps, bench='.'):
with open(os.path.join(bench, 'sites', 'apps.txt'), 'w') as f:
def write_appstxt(apps, bench_path='.'):
with open(os.path.join(bench_path, 'sites', 'apps.txt'), 'w') as f:
return f.write('\n'.join(apps))
def get_app(git_url, branch=None, bench='.', build_asset_files=True, verbose=False):
def get_app(git_url, branch=None, bench_path='.', build_asset_files=True, verbose=False):
#Gets repo name from URL
repo_name = git_url.rsplit('/', 1)[1].rsplit('.', 1)[0]
logger.info('getting app {}'.format(repo_name))
@ -56,52 +57,55 @@ def get_app(git_url, branch=None, bench='.', build_asset_files=True, verbose=Fal
git_url=git_url,
shallow_clone=shallow_clone,
branch=branch),
cwd=os.path.join(bench, 'apps'))
cwd=os.path.join(bench_path, 'apps'))
#Retrieves app name from setup.py
app_path = os.path.join(bench, 'apps', repo_name, 'setup.py')
app_path = os.path.join(bench_path, 'apps', repo_name, 'setup.py')
with open(app_path, 'rb') as f:
app_name = re.search(r'name\s*=\s*[\'"](.*)[\'"]', f.read().decode('utf-8')).group(1)
if repo_name != app_name:
apps_path = os.path.join(os.path.abspath(bench), 'apps')
apps_path = os.path.join(os.path.abspath(bench_path), 'apps')
os.rename(os.path.join(apps_path, repo_name), os.path.join(apps_path, app_name))
print 'installing', app_name
install_app(app=app_name, bench=bench, verbose=verbose)
if build_asset_files:
build_assets(bench=bench)
conf = get_config(bench=bench)
if conf.get('restart_supervisor_on_update'):
restart_supervisor_processes(bench=bench)
install_app(app=app_name, bench_path=bench_path, verbose=verbose)
def new_app(app, bench='.'):
if build_asset_files:
build_assets(bench_path=bench_path)
conf = get_config(bench_path=bench_path)
if conf.get('restart_supervisor_on_update'):
restart_supervisor_processes(bench_path=bench_path)
def new_app(app, bench_path='.'):
# For backwards compatibility
app = app.lower().replace(" ", "_").replace("-", "_")
logger.info('creating new app {}'.format(app))
apps = os.path.abspath(os.path.join(bench, 'apps'))
if FRAPPE_VERSION == 4:
exec_cmd("{frappe} --make_app {apps} {app}".format(frappe=get_frappe(bench=bench),
apps = os.path.abspath(os.path.join(bench_path, 'apps'))
bench.set_frappe_version(bench_path=bench_path)
if bench.FRAPPE_VERSION == 4:
exec_cmd("{frappe} --make_app {apps} {app}".format(frappe=get_frappe(bench_path=bench_path),
apps=apps, app=app))
else:
run_frappe_cmd('make-app', apps, app, bench=bench)
install_app(app, bench=bench)
run_frappe_cmd('make-app', apps, app, bench_path=bench_path)
install_app(app, bench_path=bench_path)
def install_app(app, bench='.', verbose=False):
def install_app(app, bench_path='.', verbose=False):
logger.info('installing {}'.format(app))
# find_links = '--find-links={}'.format(conf.get('wheel_cache_dir')) if conf.get('wheel_cache_dir') else ''
find_links = ''
exec_cmd("{pip} install {quiet} {find_links} -e {app}".format(
pip=os.path.join(bench, 'env', 'bin', 'pip'),
pip=os.path.join(bench_path, 'env', 'bin', 'pip'),
quiet="-q" if not verbose else "",
app=os.path.join(bench, 'apps', app),
app=os.path.join(bench_path, 'apps', app),
find_links=find_links))
add_to_appstxt(app, bench=bench)
add_to_appstxt(app, bench_path=bench_path)
def pull_all_apps(bench='.'):
rebase = '--rebase' if get_config(bench).get('rebase_on_pull') else ''
def pull_all_apps(bench_path='.'):
rebase = '--rebase' if get_config(bench_path).get('rebase_on_pull') else ''
for app in get_apps(bench=bench):
app_dir = get_repo_dir(app, bench=bench)
for app in get_apps(bench_path=bench_path):
app_dir = get_repo_dir(app, bench_path=bench_path)
if os.path.exists(os.path.join(app_dir, '.git')):
contents = subprocess.check_output(['git', 'remote', '-v'], cwd=app_dir,
stderr=subprocess.STDOUT)
@ -114,22 +118,22 @@ def pull_all_apps(bench='.'):
logger.info('pulling {0}'.format(app))
exec_cmd("git pull {rebase} {remote} {branch}".format(rebase=rebase,
remote=remote, branch=get_current_branch(app, bench=bench)), cwd=app_dir)
remote=remote, branch=get_current_branch(app, bench_path=bench_path)), cwd=app_dir)
exec_cmd('find . -name "*.pyc" -delete', cwd=app_dir)
def is_version_upgrade(app='frappe', bench='.', branch=None):
def is_version_upgrade(app='frappe', bench_path='.', branch=None):
try:
fetch_upstream(app, bench=bench)
fetch_upstream(app, bench_path=bench_path)
except CommandFailedError:
raise InvalidRemoteException("No remote named upstream for {0}".format(app))
upstream_version = get_upstream_version(app=app, branch=branch, bench=bench)
upstream_version = get_upstream_version(app=app, branch=branch, bench_path=bench_path)
if not upstream_version:
raise InvalidBranchException("Specified branch of app {0} is not in upstream".format(app))
local_version = get_major_version(get_current_version(app, bench=bench))
local_version = get_major_version(get_current_version(app, bench_path=bench_path))
upstream_version = get_major_version(upstream_version)
if upstream_version - local_version > 0:
@ -137,14 +141,14 @@ def is_version_upgrade(app='frappe', bench='.', branch=None):
return (False, local_version, upstream_version)
def get_current_frappe_version(bench='.'):
def get_current_frappe_version(bench_path='.'):
try:
return get_major_version(get_current_version('frappe', bench=bench))
return get_major_version(get_current_version('frappe', bench_path=bench_path))
except IOError:
return 0
def get_current_branch(app, bench='.'):
repo_dir = get_repo_dir(app, bench=bench)
def get_current_branch(app, bench_path='.'):
repo_dir = get_repo_dir(app, bench_path=bench_path)
return get_cmd_output("basename $(git symbolic-ref -q HEAD)", cwd=repo_dir)
def use_rq(bench_path):
@ -152,12 +156,12 @@ def use_rq(bench_path):
celery_app = os.path.join(bench_path, 'apps', 'frappe', 'frappe', 'celery_app.py')
return not os.path.exists(celery_app)
def fetch_upstream(app, bench='.'):
repo_dir = get_repo_dir(app, bench=bench)
def fetch_upstream(app, bench_path='.'):
repo_dir = get_repo_dir(app, bench_path=bench_path)
return subprocess.call(["git", "fetch", "upstream"], cwd=repo_dir)
def get_current_version(app, bench='.'):
repo_dir = get_repo_dir(app, bench=bench)
def get_current_version(app, bench_path='.'):
repo_dir = get_repo_dir(app, bench_path=bench_path)
try:
with open(os.path.join(repo_dir, os.path.basename(repo_dir), '__init__.py')) as f:
return get_version_from_string(f.read())
@ -167,10 +171,10 @@ def get_current_version(app, bench='.'):
with open(os.path.join(repo_dir, 'setup.py')) as f:
return get_version_from_string(f.read(), field='version')
def get_upstream_version(app, branch=None, bench='.'):
repo_dir = get_repo_dir(app, bench=bench)
def get_upstream_version(app, branch=None, bench_path='.'):
repo_dir = get_repo_dir(app, bench_path=bench_path)
if not branch:
branch = get_current_branch(app, bench=bench)
branch = get_current_branch(app, bench_path=bench_path)
try:
contents = subprocess.check_output(['git', 'show', 'upstream/{branch}:{app}/__init__.py'.format(branch=branch, app=app)], cwd=repo_dir, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError, e:
@ -180,17 +184,17 @@ def get_upstream_version(app, branch=None, bench='.'):
raise
return get_version_from_string(contents)
def get_upstream_url(app, bench='.'):
repo_dir = get_repo_dir(app, bench=bench)
def get_upstream_url(app, bench_path='.'):
repo_dir = get_repo_dir(app, bench_path=bench_path)
return subprocess.check_output(['git', 'config', '--get', 'remote.upstream.url'], cwd=repo_dir).strip()
def get_repo_dir(app, bench='.'):
return os.path.join(bench, 'apps', app)
def get_repo_dir(app, bench_path='.'):
return os.path.join(bench_path, 'apps', app)
def switch_branch(branch, apps=None, bench='.', upgrade=False, check_upgrade=True):
def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrade=True):
from .utils import update_requirements, backup_all_sites, patch_sites, build_assets, pre_upgrade, post_upgrade
import utils
apps_dir = os.path.join(bench, 'apps')
apps_dir = os.path.join(bench_path, 'apps')
version_upgrade = (False,)
switched_apps = []
@ -205,7 +209,7 @@ def switch_branch(branch, apps=None, bench='.', upgrade=False, check_upgrade=Tru
if os.path.exists(app_dir):
try:
if check_upgrade:
version_upgrade = is_version_upgrade(app=app, bench=bench, branch=branch)
version_upgrade = is_version_upgrade(app=app, bench_path=bench_path, branch=branch)
if version_upgrade[0] and not upgrade:
raise MajorVersionUpgradeException("Switching to {0} will cause upgrade from {1} to {2}. Pass --upgrade to confirm".format(branch, version_upgrade[1], version_upgrade[2]), version_upgrade[1], version_upgrade[2])
print "Switching for "+app
@ -235,20 +239,20 @@ def switch_branch(branch, apps=None, bench='.', upgrade=False, check_upgrade=Tru
build_assets()
post_upgrade(version_upgrade[1], version_upgrade[2])
def switch_to_branch(branch=None, apps=None, bench='.', upgrade=False):
switch_branch(branch, apps=apps, bench=bench, upgrade=upgrade)
def switch_to_branch(branch=None, apps=None, bench_path='.', upgrade=False):
switch_branch(branch, apps=apps, bench_path=bench_path, upgrade=upgrade)
def switch_to_master(apps=None, bench='.', upgrade=False):
switch_branch('master', apps=apps, bench=bench, upgrade=upgrade)
def switch_to_master(apps=None, bench_path='.', upgrade=False):
switch_branch('master', apps=apps, bench_path=bench_path, upgrade=upgrade)
def switch_to_develop(apps=None, bench='.', upgrade=False):
switch_branch('develop', apps=apps, bench=bench, upgrade=upgrade)
def switch_to_develop(apps=None, bench_path='.', upgrade=False):
switch_branch('develop', apps=apps, bench_path=bench_path, upgrade=upgrade)
def switch_to_v4(apps=None, bench='.', upgrade=False):
switch_branch('v4.x.x', apps=apps, bench=bench, upgrade=upgrade)
def switch_to_v4(apps=None, bench_path='.', upgrade=False):
switch_branch('v4.x.x', apps=apps, bench_path=bench_path, upgrade=upgrade)
def switch_to_v5(apps=None, bench='.', upgrade=False):
switch_branch('v5.x.x', apps=apps, bench=bench, upgrade=upgrade)
def switch_to_v5(apps=None, bench_path='.', upgrade=False):
switch_branch('v5.x.x', apps=apps, bench_path=bench_path, upgrade=upgrade)
def get_version_from_string(contents, field='__version__'):
match = re.search(r"^(\s*%s\s*=\s*['\\\"])(.+?)(['\"])(?sm)" % field,
@ -258,10 +262,10 @@ def get_version_from_string(contents, field='__version__'):
def get_major_version(version):
return semantic_version.Version(version).major
def install_apps_from_path(path, bench='.'):
def install_apps_from_path(path, bench_path='.'):
apps = get_apps_json(path)
for app in apps:
get_app(app['url'], branch=app.get('branch'), bench=bench, build_asset_files=False)
get_app(app['url'], branch=app.get('branch'), bench_path=bench_path, build_asset_files=False)
def get_apps_json(path):
if path.startswith('http'):
@ -270,5 +274,3 @@ def get_apps_json(path):
else:
with open(path) as f:
return json.load(f)
FRAPPE_VERSION = get_current_frappe_version()

View File

@ -73,24 +73,24 @@ def change_uid():
print 'You should not run this command as root'
sys.exit(1)
def old_frappe_cli(bench='.'):
f = get_frappe(bench=bench)
os.chdir(os.path.join(bench, 'sites'))
def old_frappe_cli(bench_path='.'):
f = get_frappe(bench_path=bench_path)
os.chdir(os.path.join(bench_path, 'sites'))
os.execv(f, [f] + sys.argv[2:])
def app_cmd(bench='.'):
f = get_env_cmd('python', bench=bench)
os.chdir(os.path.join(bench, 'sites'))
def app_cmd(bench_path='.'):
f = get_env_cmd('python', bench_path=bench_path)
os.chdir(os.path.join(bench_path, 'sites'))
os.execv(f, [f] + ['-m', 'frappe.utils.bench_helper'] + sys.argv[1:])
def frappe_cmd(bench='.'):
f = get_env_cmd('python', bench=bench)
os.chdir(os.path.join(bench, 'sites'))
def frappe_cmd(bench_path='.'):
f = get_env_cmd('python', bench_path=bench_path)
os.chdir(os.path.join(bench_path, 'sites'))
os.execv(f, [f] + ['-m', 'frappe.utils.bench_helper', 'frappe'] + sys.argv[1:])
def get_frappe_commands(bench='.'):
python = get_env_cmd('python', bench=bench)
sites_path = os.path.join(bench, 'sites')
def get_frappe_commands(bench_path='.'):
python = get_env_cmd('python', bench_path=bench_path)
sites_path = os.path.join(bench_path, 'sites')
if not os.path.exists(sites_path):
return []
try:
@ -98,9 +98,9 @@ def get_frappe_commands(bench='.'):
except subprocess.CalledProcessError:
return []
def get_frappe_help(bench='.'):
python = get_env_cmd('python', bench=bench)
sites_path = os.path.join(bench, 'sites')
def get_frappe_help(bench_path='.'):
python = get_env_cmd('python', bench_path=bench_path)
sites_path = os.path.join(bench_path, 'sites')
if not os.path.exists(sites_path):
return []
try:

View File

@ -1,16 +1,14 @@
import click
global FRAPPE_VERSION
@click.group()
def bench_command(bench='.'):
def bench_command(bench_path='.'):
"Bench manager for Frappe"
import bench
from bench.app import get_current_frappe_version
from bench.utils import setup_logging
# TODO add bench path context
global FRAPPE_VERSION
FRAPPE_VERSION = get_current_frappe_version()
setup_logging(bench=bench)
bench.set_frappe_version(bench_path=bench_path)
setup_logging(bench_path=bench_path)
from bench.commands.make import init, get_app, new_app, new_site

View File

@ -23,12 +23,12 @@ def setup_nginx(force=None):
@click.command('supervisor')
@click.option('--user')
@click.option('--force', help='Force regeneration of supervisor config', is_flag=True, default=False)
def setup_supervisor(force=None):
"generate config for supervisor"
def setup_supervisor(user=None, force=None):
"generate config for supervisor with an optional user argument"
from bench.config.supervisor import generate_supervisor_config
generate_supervisor_config(bench_path=".", force=force)
generate_supervisor_config(bench_path=".", user=user, force=force)
@click.command('redis')
def setup_redis():

View File

@ -61,39 +61,39 @@ def update(pull=False, patch=False, build=False, bench=False, auto=False, restar
def _update(pull=False, patch=False, build=False, update_bench=False, auto=False, restart_supervisor=False, requirements=False, no_backup=False, upgrade=False, bench_path='.', force=False):
conf = get_config(bench=bench_path)
version_upgrade = is_version_upgrade(bench=bench_path)
conf = get_config(bench_path=bench_path)
version_upgrade = is_version_upgrade(bench_path=bench_path)
if version_upgrade[0] and not upgrade:
raise Exception("Major Version Upgrade")
if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)):
validate_upgrade(version_upgrade[1], version_upgrade[2], bench=bench_path)
validate_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path)
before_update(bench=bench_path, requirements=requirements)
before_update(bench_path=bench_path, requirements=requirements)
if pull:
pull_all_apps(bench=bench_path)
pull_all_apps(bench_path=bench_path)
if requirements:
update_requirements(bench=bench_path)
update_requirements(bench_path=bench_path)
if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)):
pre_upgrade(version_upgrade[1], version_upgrade[2], bench=bench_path)
pre_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path)
import bench.utils, bench.app
reload(bench.utils)
reload(bench.app)
if patch:
if not no_backup:
backup_all_sites(bench=bench_path)
patch_sites(bench=bench_path)
backup_all_sites(bench_path=bench_path)
patch_sites(bench_path=bench_path)
if build:
build_assets(bench=bench_path)
build_assets(bench_path=bench_path)
if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)):
post_upgrade(version_upgrade[1], version_upgrade[2], bench=bench_path)
post_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path)
if restart_supervisor or conf.get('restart_supervisor_on_update'):
restart_supervisor_processes(bench=bench_path)
restart_supervisor_processes(bench_path=bench_path)
print "_"*80
print "Bench: Open source installer + admin for Frappe and ERPNext (https://erpnext.com)"

View File

@ -83,7 +83,7 @@ def renew_lets_encrypt():
renew_certs()
@click.command()
def shell(bench='.'):
def shell(bench_path='.'):
if not os.environ.get('SHELL'):
print "Cannot get shell"
sys.exit(1)
@ -102,17 +102,17 @@ def shell(bench='.'):
def backup_site(site):
"backup site"
from bench.utils import get_sites, backup_site
if not site in get_sites(bench='.'):
if not site in get_sites(bench_path='.'):
print 'site not found'
sys.exit(1)
backup_site(site, bench='.')
backup_site(site, bench_path='.')
@click.command('backup-all-sites')
def backup_all_sites():
"backup all sites"
from bench.utils import backup_all_sites
backup_all_sites(bench='.')
backup_all_sites(bench_path='.')
@click.command('release')

View File

@ -20,8 +20,8 @@ def make_config(bench_path):
put_config(bench_config, bench_path)
def get_config(bench):
return get_common_site_config(bench)
def get_config(bench_path):
return get_common_site_config(bench_path)
def get_common_site_config(bench_path):
config_path = get_config_path(bench_path)
@ -30,18 +30,18 @@ def get_common_site_config(bench_path):
with open(config_path, 'r') as f:
return json.load(f)
def put_config(config, bench='.'):
config_path = get_config_path(bench)
def put_config(config, bench_path='.'):
config_path = get_config_path(bench_path)
with open(config_path, 'w') as f:
return json.dump(config, f, indent=1, sort_keys=True)
def update_config(new_config, bench='.'):
config = get_config(bench=bench)
def update_config(new_config, bench_path='.'):
config = get_config(bench_path=bench_path)
config.update(new_config)
put_config(config, bench=bench)
put_config(config, bench_path=bench_path)
def get_config_path(bench):
return os.path.join(bench, 'sites', 'common_site_config.json')
def get_config_path(bench_path):
return os.path.join(bench_path, 'sites', 'common_site_config.json')
def get_gunicorn_workers():
'''This function will return the maximum workers that can be started depending upon
@ -78,9 +78,9 @@ def make_ports(bench_path):
# collect all existing ports
existing_ports = {}
for folder in os.listdir(benches_path):
bench = os.path.join(benches_path, folder)
if os.path.isdir(bench):
bench_config = get_config(bench)
bench_path = os.path.join(benches_path, folder)
if os.path.isdir(bench_path):
bench_config = get_config(bench_path)
for key in default_ports.keys():
value = bench_config.get(key)

View File

@ -61,7 +61,7 @@ def prepare_sites(config, bench_path):
return sites
def get_sites_with_config(bench_path):
sites = get_sites(bench=bench_path)
sites = get_sites(bench_path=bench_path)
ret = []
for site in sites:
site_config = get_site_config(site, bench_path=bench_path)

View File

@ -4,7 +4,7 @@ from bench.app import use_rq
from bench.config.common_site_config import get_config
def setup_procfile(bench_path, force=False):
config = get_config(bench=bench_path)
config = get_config(bench_path=bench_path)
procfile_path = os.path.join(bench_path, 'Procfile')
if not force and os.path.exists(procfile_path):
click.confirm('A Procfile already exists and this will overwrite it. Do you want to continue?',

View File

@ -3,13 +3,13 @@ from bench.config.supervisor import generate_supervisor_config
from bench.config.nginx import make_nginx_conf
import os
def setup_production(user, bench='.'):
generate_supervisor_config(bench_path=bench, user=user)
make_nginx_conf(bench_path=bench)
fix_prod_setup_perms(bench, frappe_user=user)
def setup_production(user, bench_path='.'):
generate_supervisor_config(bench_path=bench_path, user=user)
make_nginx_conf(bench_path=bench_path)
fix_prod_setup_perms(bench_path, frappe_user=user)
remove_default_nginx_configs()
bench_name = get_bench_name(bench)
bench_name = get_bench_name(bench_path)
nginx_conf = '/etc/nginx/conf.d/{bench_name}.conf'.format(bench_name=bench_name)
supervisor_conf_extn = "ini" if is_centos7() else "conf"
@ -18,10 +18,10 @@ def setup_production(user, bench='.'):
# Check if symlink exists, If not then create it.
if not os.path.islink(supervisor_conf):
os.symlink(os.path.abspath(os.path.join(bench, 'config', 'supervisor.conf')), supervisor_conf)
os.symlink(os.path.abspath(os.path.join(bench_path, 'config', 'supervisor.conf')), supervisor_conf)
if not os.path.islink(nginx_conf):
os.symlink(os.path.abspath(os.path.join(bench, 'config', 'nginx.conf')), nginx_conf)
os.symlink(os.path.abspath(os.path.join(bench_path, 'config', 'nginx.conf')), nginx_conf)
exec_cmd('supervisorctl reload')
if os.environ.get('NO_SERVICE_RESTART'):

View File

@ -10,7 +10,7 @@ def generate_supervisor_config(bench_path, user=None, force=False):
if not user:
user = getpass.getuser()
config = get_config(bench=bench_path)
config = get_config(bench_path=bench_path)
bench_dir = os.path.abspath(bench_path)
@ -41,5 +41,5 @@ def generate_supervisor_config(bench_path, user=None, force=False):
with open(conf_path, 'w') as f:
f.write(config)
update_config({'restart_supervisor_on_update': True}, bench=bench_path)
update_config({'restart_supervisor_on_update': True}, bench_path=bench_path)

View File

@ -103,12 +103,12 @@ class TestBenchInit(unittest.TestCase):
bench_path = os.path.join(self.benches_path, "test-bench")
# get app
bench.app.get_app("https://github.com/frappe/erpnext", "develop", bench=bench_path)
bench.app.get_app("https://github.com/frappe/erpnext", "develop", bench_path=bench_path)
self.assertTrue(os.path.exists(os.path.join(bench_path, "apps", "erpnext")))
# install app
bench.app.install_app("erpnext", bench=bench_path)
bench.app.install_app("erpnext", bench_path=bench_path)
# install it to site
subprocess.check_output(["bench", "--site", site_name, "install-app", "erpnext"], cwd=bench_path)

View File

@ -10,6 +10,7 @@ import select
import multiprocessing
from distutils.spawn import find_executable
import pwd, grp
import bench
from bench import env
class PatchError(Exception):
@ -24,15 +25,15 @@ logger = logging.getLogger(__name__)
folders_in_bench = ('apps', 'sites', 'config', 'logs', 'config/pids')
def get_frappe(bench='.'):
frappe = get_env_cmd('frappe', bench=bench)
def get_frappe(bench_path='.'):
frappe = get_env_cmd('frappe', bench_path=bench_path)
if not os.path.exists(frappe):
print 'frappe app is not installed. Run the following command to install frappe'
print 'bench get-app https://github.com/frappe/frappe.git'
return frappe
def get_env_cmd(cmd, bench='.'):
return os.path.abspath(os.path.join(bench, 'env', 'bin', cmd))
def get_env_cmd(cmd, bench_path='.'):
return os.path.abspath(os.path.join(bench_path, 'env', 'bin', cmd))
def init(path, apps_path=None, no_procfile=False, no_backups=False,
no_auto_update=False, frappe_path=None, frappe_branch=None, wheel_cache_dir=None,
@ -41,7 +42,6 @@ def init(path, apps_path=None, no_procfile=False, no_backups=False,
from .config.common_site_config import make_config
from .config import redis
from .config.procfile import setup_procfile
global FRAPPE_VERSION
if os.path.exists(path):
print 'Directory {} already exists!'.format(path)
@ -54,30 +54,31 @@ def init(path, apps_path=None, no_procfile=False, no_backups=False,
setup_logging()
setup_env(bench=path)
setup_env(bench_path=path)
make_config(path)
if not frappe_path:
frappe_path = 'https://github.com/frappe/frappe.git'
get_app(frappe_path, branch=frappe_branch, bench=path, build_asset_files=False, verbose=verbose)
get_app(frappe_path, branch=frappe_branch, bench_path=path, build_asset_files=False, verbose=verbose)
if apps_path:
install_apps_from_path(apps_path, bench=path)
install_apps_from_path(apps_path, bench_path=path)
FRAPPE_VERSION = get_current_frappe_version(bench=path)
if FRAPPE_VERSION > 5:
setup_socketio(bench=path)
bench.set_frappe_version(bench_path=path)
if bench.FRAPPE_VERSION > 5:
setup_socketio(bench_path=path)
build_assets(bench=path)
build_assets(bench_path=path)
redis.generate_config(path)
if not no_procfile:
setup_procfile(path)
if not no_backups:
setup_backups(bench=path)
setup_backups(bench_path=path)
if not no_auto_update:
setup_auto_update(bench=path)
setup_auto_update(bench_path=path)
def exec_cmd(cmd, cwd='.'):
@ -98,74 +99,80 @@ def exec_cmd(cmd, cwd='.'):
if return_code > 0:
raise CommandFailedError(cmd)
def setup_env(bench='.'):
exec_cmd('virtualenv -q {} -p {}'.format('env', sys.executable), cwd=bench)
exec_cmd('./env/bin/pip -q install --upgrade pip', cwd=bench)
exec_cmd('./env/bin/pip -q install wheel', cwd=bench)
# exec_cmd('./env/bin/pip -q install https://github.com/frappe/MySQLdb1/archive/MySQLdb-1.2.5-patched.tar.gz', cwd=bench)
exec_cmd('./env/bin/pip -q install -e git+https://github.com/frappe/python-pdfkit.git#egg=pdfkit', cwd=bench)
def setup_env(bench_path='.'):
exec_cmd('virtualenv -q {} -p {}'.format('env', sys.executable), cwd=bench_path)
exec_cmd('./env/bin/pip -q install --upgrade pip', cwd=bench_path)
exec_cmd('./env/bin/pip -q install wheel', cwd=bench_path)
# exec_cmd('./env/bin/pip -q install https://github.com/frappe/MySQLdb1/archive/MySQLdb-1.2.5-patched.tar.gz', cwd=bench_path)
exec_cmd('./env/bin/pip -q install -e git+https://github.com/frappe/python-pdfkit.git#egg=pdfkit', cwd=bench_path)
def setup_socketio(bench='.'):
exec_cmd("npm install socket.io redis express superagent cookie", cwd=bench)
def setup_socketio(bench_path='.'):
exec_cmd("npm install socket.io redis express superagent cookie", cwd=bench_path)
def new_site(site, mariadb_root_password=None, admin_password=None, bench='.'):
def new_site(site, mariadb_root_password=None, admin_password=None, bench_path='.'):
import hashlib
logger.info('creating new site {}'.format(site))
mariadb_root_password_fragment = '--root_password {}'.format(mariadb_root_password) if mariadb_root_password else ''
admin_password_fragment = '--admin_password {}'.format(admin_password) if admin_password else ''
exec_cmd("{frappe} {site} --install {db_name} {mariadb_root_password_fragment} {admin_password_fragment}".format(
frappe=get_frappe(bench=bench),
frappe=get_frappe(bench_path=bench_path),
site=site,
db_name = hashlib.sha1(site).hexdigest()[:10],
mariadb_root_password_fragment=mariadb_root_password_fragment,
admin_password_fragment=admin_password_fragment
), cwd=os.path.join(bench, 'sites'))
if len(get_sites(bench=bench)) == 1:
exec_cmd("{frappe} --use {site}".format(frappe=get_frappe(bench=bench), site=site), cwd=os.path.join(bench, 'sites'))
), cwd=os.path.join(bench_path, 'sites'))
if len(get_sites(bench_path=bench_path)) == 1:
exec_cmd("{frappe} --use {site}".format(frappe=get_frappe(bench_path=bench_path), site=site), cwd=os.path.join(bench_path, 'sites'))
def patch_sites(bench_path='.'):
bench.set_frappe_version(bench_path=bench_path)
def patch_sites(bench='.'):
try:
if FRAPPE_VERSION == 4:
exec_cmd("{frappe} --latest all".format(frappe=get_frappe(bench=bench)), cwd=os.path.join(bench, 'sites'))
if bench.FRAPPE_VERSION == 4:
exec_cmd("{frappe} --latest all".format(frappe=get_frappe(bench_path=bench_path)), cwd=os.path.join(bench_path, 'sites'))
else:
run_frappe_cmd('--site', 'all', 'migrate', bench=bench)
run_frappe_cmd('--site', 'all', 'migrate', bench_path=bench_path)
except subprocess.CalledProcessError:
raise PatchError
def build_assets(bench='.'):
if FRAPPE_VERSION == 4:
exec_cmd("{frappe} --build".format(frappe=get_frappe(bench=bench)), cwd=os.path.join(bench, 'sites'))
else:
run_frappe_cmd('build', bench=bench)
def build_assets(bench_path='.'):
bench.set_frappe_version(bench_path=bench_path)
def get_sites(bench='.'):
sites_dir = os.path.join(bench, "sites")
if bench.FRAPPE_VERSION == 4:
exec_cmd("{frappe} --build".format(frappe=get_frappe(bench_path=bench_path)), cwd=os.path.join(bench_path, 'sites'))
else:
run_frappe_cmd('build', bench_path=bench_path)
def get_sites(bench_path='.'):
sites_dir = os.path.join(bench_path, "sites")
sites = [site for site in os.listdir(sites_dir)
if os.path.isdir(os.path.join(sites_dir, site)) and site not in ('assets',)]
return sites
def get_sites_dir(bench='.'):
return os.path.abspath(os.path.join(bench, 'sites'))
def get_sites_dir(bench_path='.'):
return os.path.abspath(os.path.join(bench_path, 'sites'))
def get_bench_dir(bench='.'):
return os.path.abspath(bench)
def get_bench_dir(bench_path='.'):
return os.path.abspath(bench_path)
def setup_auto_update(bench='.'):
def setup_auto_update(bench_path='.'):
logger.info('setting up auto update')
add_to_crontab('0 10 * * * cd {bench_dir} && {bench} update --auto >> {logfile} 2>&1'.format(bench_dir=get_bench_dir(bench=bench),
bench=os.path.join(get_bench_dir(bench=bench), 'env', 'bin', 'bench'),
logfile=os.path.join(get_bench_dir(bench=bench), 'logs', 'auto_update_log.log')))
add_to_crontab('0 10 * * * cd {bench_dir} && {bench} update --auto >> {logfile} 2>&1'.format(bench_dir=get_bench_dir(bench_path=bench_path),
bench=os.path.join(get_bench_dir(bench_path=bench_path), 'env', 'bin', 'bench'),
logfile=os.path.join(get_bench_dir(bench_path=bench_path), 'logs', 'auto_update_log.log')))
def setup_backups(bench='.'):
def setup_backups(bench_path='.'):
logger.info('setting up backups')
bench_dir = get_bench_dir(bench=bench)
if FRAPPE_VERSION == 4:
backup_command = "cd {sites_dir} && {frappe} --backup all".format(frappe=get_frappe(bench=bench),)
bench_dir = get_bench_dir(bench_path=bench_path)
bench.set_frappe_version(bench_path=bench_path)
if bench.FRAPPE_VERSION == 4:
backup_command = "cd {sites_dir} && {frappe} --backup all".format(frappe=get_frappe(bench_path=bench_path),)
else:
backup_command = "cd {bench_dir} && {bench} --site all backup".format(bench_dir=bench_dir, bench=sys.argv[0])
add_to_crontab('0 */6 * * * {backup_command} >> {logfile} 2>&1'.format(backup_command=backup_command,
logfile=os.path.join(get_bench_dir(bench=bench), 'logs', 'backup.log')))
logfile=os.path.join(get_bench_dir(bench_path=bench_path), 'logs', 'backup.log')))
def add_to_crontab(line):
current_crontab = read_crontab()
@ -223,10 +230,10 @@ def setup_sudoers(user):
os.chmod(sudoers_file, 0440)
def setup_logging(bench='.'):
if os.path.exists(os.path.join(bench, 'logs')):
def setup_logging(bench_path='.'):
if os.path.exists(os.path.join(bench_path, 'logs')):
logger = logging.getLogger('bench')
log_file = os.path.join(bench, 'logs', 'bench.log')
log_file = os.path.join(bench_path, 'logs', 'bench.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr = logging.FileHandler(log_file)
hdlr.setFormatter(formatter)
@ -290,17 +297,17 @@ def get_cmd_output(cmd, cwd='.'):
print e.output
raise
def restart_supervisor_processes(bench='.'):
def restart_supervisor_processes(bench_path='.'):
from .config.common_site_config import get_config
conf = get_config(bench=bench)
bench_name = get_bench_name(bench)
conf = get_config(bench_path=bench_path)
bench_name = get_bench_name(bench_path)
cmd = conf.get('supervisor_restart_cmd')
if cmd:
exec_cmd(cmd, cwd=bench)
exec_cmd(cmd, cwd=bench_path)
else:
supervisor_status = subprocess.check_output(['sudo', 'supervisorctl', 'status'], cwd=bench)
supervisor_status = subprocess.check_output(['sudo', 'supervisorctl', 'status'], cwd=bench_path)
if '{bench_name}-workers:'.format(bench_name=bench_name) in supervisor_status:
group = '{bench_name}-workers: {bench_name}-web:'.format(bench_name=bench_name)
@ -313,84 +320,86 @@ def restart_supervisor_processes(bench='.'):
else:
group = 'frappe:'
exec_cmd('sudo supervisorctl restart {group}'.format(group=group), cwd=bench)
exec_cmd('sudo supervisorctl restart {group}'.format(group=group), cwd=bench_path)
def get_site_config(site, bench='.'):
config_path = os.path.join(bench, 'sites', site, 'site_config.json')
def get_site_config(site, bench_path='.'):
config_path = os.path.join(bench_path, 'sites', site, 'site_config.json')
if not os.path.exists(config_path):
return {}
with open(config_path) as f:
return json.load(f)
def put_site_config(site, config, bench='.'):
config_path = os.path.join(bench, 'sites', site, 'site_config.json')
def put_site_config(site, config, bench_path='.'):
config_path = os.path.join(bench_path, 'sites', site, 'site_config.json')
with open(config_path, 'w') as f:
return json.dump(config, f, indent=1)
def update_site_config(site, new_config, bench='.'):
config = get_site_config(site, bench=bench)
def update_site_config(site, new_config, bench_path='.'):
config = get_site_config(site, bench_path=bench_path)
config.update(new_config)
put_site_config(site, config, bench=bench)
put_site_config(site, config, bench_path=bench_path)
def set_nginx_port(site, port, bench='.', gen_config=True):
set_site_config_nginx_property(site, {"nginx_port": port}, bench=bench, gen_config=gen_config)
def set_nginx_port(site, port, bench_path='.', gen_config=True):
set_site_config_nginx_property(site, {"nginx_port": port}, bench_path=bench_path, gen_config=gen_config)
def set_ssl_certificate(site, ssl_certificate, bench='.', gen_config=True):
set_site_config_nginx_property(site, {"ssl_certificate": ssl_certificate}, bench=bench, gen_config=gen_config)
def set_ssl_certificate(site, ssl_certificate, bench_path='.', gen_config=True):
set_site_config_nginx_property(site, {"ssl_certificate": ssl_certificate}, bench_path=bench_path, gen_config=gen_config)
def set_ssl_certificate_key(site, ssl_certificate_key, bench='.', gen_config=True):
set_site_config_nginx_property(site, {"ssl_certificate_key": ssl_certificate_key}, bench=bench, gen_config=gen_config)
def set_ssl_certificate_key(site, ssl_certificate_key, bench_path='.', gen_config=True):
set_site_config_nginx_property(site, {"ssl_certificate_key": ssl_certificate_key}, bench_path=bench_path, gen_config=gen_config)
def set_site_config_nginx_property(site, config, bench='.', gen_config=True):
def set_site_config_nginx_property(site, config, bench_path='.', gen_config=True):
from .config.nginx import make_nginx_conf
if site not in get_sites(bench=bench):
if site not in get_sites(bench_path=bench_path):
raise Exception("No such site")
update_site_config(site, config, bench=bench)
update_site_config(site, config, bench_path=bench_path)
if gen_config:
make_nginx_conf(bench_path=bench)
make_nginx_conf(bench_path=bench_path)
def set_url_root(site, url_root, bench='.'):
update_site_config(site, {"host_name": url_root}, bench=bench)
def set_url_root(site, url_root, bench_path='.'):
update_site_config(site, {"host_name": url_root}, bench_path=bench_path)
def set_default_site(site, bench='.'):
if not site in get_sites(bench=bench):
def set_default_site(site, bench_path='.'):
if not site in get_sites(bench_path=bench_path):
raise Exception("Site not in bench")
exec_cmd("{frappe} --use {site}".format(frappe=get_frappe(bench=bench), site=site),
cwd=os.path.join(bench, 'sites'))
exec_cmd("{frappe} --use {site}".format(frappe=get_frappe(bench_path=bench_path), site=site),
cwd=os.path.join(bench_path, 'sites'))
def update_requirements(bench='.'):
pip = os.path.join(bench, 'env', 'bin', 'pip')
def update_requirements(bench_path='.'):
pip = os.path.join(bench_path, 'env', 'bin', 'pip')
# upgrade pip to latest
exec_cmd("{pip} install --upgrade pip".format(pip=pip))
apps_dir = os.path.join(bench, 'apps')
apps_dir = os.path.join(bench_path, 'apps')
for app in os.listdir(apps_dir):
req_file = os.path.join(apps_dir, app, 'requirements.txt')
if os.path.exists(req_file):
exec_cmd("{pip} install -q -r {req_file}".format(pip=pip, req_file=req_file))
def backup_site(site, bench='.'):
if FRAPPE_VERSION == 4:
exec_cmd("{frappe} --backup {site}".format(frappe=get_frappe(bench=bench), site=site),
cwd=os.path.join(bench, 'sites'))
else:
run_frappe_cmd('--site', site, 'backup', bench=bench)
def backup_site(site, bench_path='.'):
bench.set_frappe_version(bench_path=bench_path)
def backup_all_sites(bench='.'):
for site in get_sites(bench=bench):
backup_site(site, bench=bench)
if bench.FRAPPE_VERSION == 4:
exec_cmd("{frappe} --backup {site}".format(frappe=get_frappe(bench_path=bench_path), site=site),
cwd=os.path.join(bench_path, 'sites'))
else:
run_frappe_cmd('--site', site, 'backup', bench_path=bench_path)
def backup_all_sites(bench_path='.'):
for site in get_sites(bench_path=bench_path):
backup_site(site, bench_path=bench_path)
def is_root():
if os.getuid() == 0:
return True
return False
def set_mariadb_host(host, bench='.'):
update_common_site_config({'db_host': host}, bench=bench)
def set_mariadb_host(host, bench_path='.'):
update_common_site_config({'db_host': host}, bench_path=bench_path)
def update_common_site_config(ddict, bench='.'):
update_json_file(os.path.join(bench, 'sites', 'common_site_config.json'), ddict)
def update_common_site_config(ddict, bench_path='.'):
update_json_file(os.path.join(bench_path, 'sites', 'common_site_config.json'), ddict)
def update_json_file(filename, ddict):
if os.path.exists(filename):
@ -424,7 +433,7 @@ def drop_privileges(uid_name='nobody', gid_name='nogroup'):
# Ensure a very conservative umask
os.umask(022)
def fix_prod_setup_perms(bench='.', frappe_user=None):
def fix_prod_setup_perms(bench_path='.', frappe_user=None):
from .config.common_site_config import get_config
files = [
"logs/web.error.log",
@ -438,7 +447,7 @@ def fix_prod_setup_perms(bench='.', frappe_user=None):
]
if not frappe_user:
frappe_user = get_config(bench).get('frappe_user')
frappe_user = get_config(bench_path).get('frappe_user')
if not frappe_user:
print "frappe user not set"
@ -462,16 +471,16 @@ def fix_file_perms():
if not _file.startswith('activate'):
os.chmod(os.path.join(bin_dir, _file), 0755)
def get_current_frappe_version(bench='.'):
def get_current_frappe_version(bench_path='.'):
from .app import get_current_frappe_version as fv
return fv(bench=bench)
return fv(bench_path=bench_path)
def run_frappe_cmd(*args, **kwargs):
from .cli import from_command_line
bench = kwargs.get('bench', '.')
f = get_env_cmd('python', bench=bench)
sites_dir = os.path.join(bench, 'sites')
bench_path = kwargs.get('bench_path', '.')
f = get_env_cmd('python', bench_path=bench_path)
sites_dir = os.path.join(bench_path, 'sites')
async = False if from_command_line else True
if async:
@ -491,48 +500,49 @@ def run_frappe_cmd(*args, **kwargs):
raise CommandFailedError(args)
def get_frappe_cmd_output(*args, **kwargs):
bench = kwargs.get('bench', '.')
f = get_env_cmd('python', bench=bench)
sites_dir = os.path.join(bench, 'sites')
bench_path = kwargs.get('bench_path', '.')
f = get_env_cmd('python', bench_path=bench_path)
sites_dir = os.path.join(bench_path, 'sites')
return subprocess.check_output((f, '-m', 'frappe.utils.bench_helper', 'frappe') + args, cwd=sites_dir)
def validate_upgrade(from_ver, to_ver, bench='.'):
def validate_upgrade(from_ver, to_ver, bench_path='.'):
if to_ver >= 6:
if not find_executable('npm') and not (find_executable('node') or find_executable('nodejs')):
raise Exception("Please install nodejs and npm")
def pre_upgrade(from_ver, to_ver, bench='.'):
pip = os.path.join(bench, 'env', 'bin', 'pip')
def pre_upgrade(from_ver, to_ver, bench_path='.'):
pip = os.path.join(bench_path, 'env', 'bin', 'pip')
if from_ver <= 4 and to_ver >= 5:
from .migrate_to_v5 import remove_shopping_cart
apps = ('frappe', 'erpnext')
remove_shopping_cart(bench=bench)
remove_shopping_cart(bench_path=bench_path)
for app in apps:
cwd = os.path.abspath(os.path.join(bench, 'apps', app))
cwd = os.path.abspath(os.path.join(bench_path, 'apps', app))
if os.path.exists(cwd):
exec_cmd("git clean -dxf", cwd=cwd)
exec_cmd("{pip} install --upgrade -e {app}".format(pip=pip, app=cwd))
def post_upgrade(from_ver, to_ver, bench='.'):
def post_upgrade(from_ver, to_ver, bench_path='.'):
from .config.common_site_config import get_config
from .config import redis
from .config.supervisor import generate_supervisor_config
from .config.nginx import make_nginx_conf
conf = get_config(bench=bench)
conf = get_config(bench_path=bench_path)
print "-"*80
print "Your bench was upgraded to version {0}".format(to_ver)
if conf.get('restart_supervisor_on_update'):
redis.generate_config(bench_path=bench)
generate_supervisor_config(bench_path=bench)
make_nginx_conf(bench_path=bench)
redis.generate_config(bench_path=bench_path)
generate_supervisor_config(bench_path=bench_path)
make_nginx_conf(bench_path=bench_path)
if from_ver == 4 and to_ver == 5:
setup_backups(bench=bench)
setup_backups(bench_path=bench_path)
if from_ver <= 5 and to_ver == 6:
setup_socketio(bench=bench)
setup_socketio(bench_path=bench_path)
print "As you have setup your bench for production, you will have to reload configuration for nginx and supervisor"
print "To complete the migration, please run the following commands"
@ -618,17 +628,15 @@ def get_output(*cmd):
s.stdout.close()
return out
FRAPPE_VERSION = get_current_frappe_version()
def before_update(bench_path, requirements):
validate_pillow_dependencies(bench_path, requirements)
def before_update(bench, requirements):
validate_pillow_dependencies(bench, requirements)
def validate_pillow_dependencies(bench, requirements):
def validate_pillow_dependencies(bench_path, requirements):
if not requirements:
return
try:
pip = os.path.join(bench, 'env', 'bin', 'pip')
pip = os.path.join(bench_path, 'env', 'bin', 'pip')
exec_cmd("{pip} install Pillow".format(pip=pip))
except CommandFailedError: