mirror of
https://github.com/frappe/bench.git
synced 2024-11-12 00:06:36 +00:00
Merge branch 'develop' into pull_specific_apps
This commit is contained in:
commit
06380d83d2
79
bench/cli.py
79
bench/cli.py
@ -1,13 +1,25 @@
|
||||
# imports - standard imports
|
||||
import atexit
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import pwd
|
||||
import sys
|
||||
|
||||
# imports - third party imports
|
||||
import click
|
||||
import os, sys, logging, json, pwd, subprocess
|
||||
from bench.utils import is_root, PatchError, drop_privileges, get_env_cmd, get_cmd_output, get_frappe, log, find_parent_bench
|
||||
|
||||
# imports - module imports
|
||||
from bench.app import get_apps
|
||||
from bench.config.common_site_config import get_config
|
||||
from bench.commands import bench_command
|
||||
from bench.config.common_site_config import get_config
|
||||
from bench.utils import PatchError, bench_cache_file, check_latest_version, drop_privileges, find_parent_bench, generate_command_cache, get_cmd_output, get_env_cmd, get_frappe, is_bench_directory, is_dist_editable, is_root, log
|
||||
|
||||
|
||||
logger = logging.getLogger('bench')
|
||||
from_command_line = False
|
||||
change_uid_msg = "You should not run this command as root"
|
||||
|
||||
|
||||
def cli():
|
||||
global from_command_line
|
||||
@ -18,42 +30,51 @@ def cli():
|
||||
change_dir()
|
||||
change_uid()
|
||||
|
||||
if is_dist_editable("bench") and len(sys.argv) > 1 and sys.argv[1] != "src":
|
||||
log("bench is installed in editable mode!\n\nThis is not the recommended mode of installation for production. Instead, install the package from PyPI with: `pip install frappe-bench`\n", level=3)
|
||||
|
||||
if not is_bench_directory() and not cmd_requires_root() and len(sys.argv) > 1 and sys.argv[1] not in ("init", "find", "src"):
|
||||
log("Command not being executed in bench directory", level=3)
|
||||
|
||||
if len(sys.argv) > 2 and sys.argv[1] == "frappe":
|
||||
return old_frappe_cli()
|
||||
|
||||
elif len(sys.argv) > 1 and sys.argv[1] in get_frappe_commands():
|
||||
elif len(sys.argv) > 1:
|
||||
if sys.argv[1] in get_frappe_commands() + ["--site", "--verbose", "--force", "--profile"]:
|
||||
return frappe_cmd()
|
||||
|
||||
elif len(sys.argv) > 1 and sys.argv[1] in ("--site", "--verbose", "--force", "--profile"):
|
||||
return frappe_cmd()
|
||||
|
||||
elif len(sys.argv) > 1 and sys.argv[1]=="--help":
|
||||
elif sys.argv[1] == "--help":
|
||||
print(click.Context(bench_command).get_help())
|
||||
print(get_frappe_help())
|
||||
return
|
||||
|
||||
elif len(sys.argv) > 1 and sys.argv[1] in get_apps():
|
||||
elif sys.argv[1] in get_apps():
|
||||
return app_cmd()
|
||||
|
||||
else:
|
||||
if not (len(sys.argv) > 1 and sys.argv[1] == "src"):
|
||||
atexit.register(check_latest_version)
|
||||
|
||||
try:
|
||||
# NOTE: this is the main bench command
|
||||
bench_command()
|
||||
except PatchError:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def check_uid():
|
||||
if cmd_requires_root() and not is_root():
|
||||
log('superuser privileges required for this command', level=3)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def cmd_requires_root():
|
||||
if len(sys.argv) > 2 and sys.argv[2] in ('production', 'sudoers', 'lets-encrypt', 'fonts',
|
||||
if len(sys.argv) > 2 and sys.argv[2] in ('production', 'sudoers', 'supervisor', 'lets-encrypt', 'fonts',
|
||||
'print', 'firewall', 'ssh-port', 'role', 'fail2ban', 'wildcard-ssl'):
|
||||
return True
|
||||
if len(sys.argv) >= 2 and sys.argv[1] in ('patch', 'renew-lets-encrypt', 'disable-production',
|
||||
'install'):
|
||||
if len(sys.argv) >= 2 and sys.argv[1] in ('patch', 'renew-lets-encrypt', 'disable-production'):
|
||||
return True
|
||||
if len(sys.argv) > 2 and sys.argv[1] in ('install'):
|
||||
return True
|
||||
|
||||
|
||||
def change_dir():
|
||||
if os.path.exists('config.json') or "init" in sys.argv:
|
||||
@ -65,6 +86,7 @@ def change_dir():
|
||||
if os.path.exists(dir_path):
|
||||
os.chdir(dir_path)
|
||||
|
||||
|
||||
def change_uid():
|
||||
if is_root() and not cmd_requires_root():
|
||||
frappe_user = get_config(".").get('frappe_user')
|
||||
@ -72,38 +94,40 @@ def change_uid():
|
||||
drop_privileges(uid_name=frappe_user, gid_name=frappe_user)
|
||||
os.environ['HOME'] = pwd.getpwnam(frappe_user).pw_dir
|
||||
else:
|
||||
log('You should not run this command as root', level=3)
|
||||
log(change_uid_msg, level=3)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
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_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_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_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):
|
||||
log("Command not being executed in bench directory", level=3)
|
||||
return []
|
||||
try:
|
||||
output = get_cmd_output("{python} -m frappe.utils.bench_helper get-frappe-commands".format(python=python), cwd=sites_path)
|
||||
return json.loads(output)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if hasattr(e, "stderr"):
|
||||
print(e.stderr.decode('utf-8'))
|
||||
|
||||
def get_frappe_commands():
|
||||
if not is_bench_directory():
|
||||
return []
|
||||
|
||||
if os.path.exists(bench_cache_file):
|
||||
command_dump = open(bench_cache_file, 'r').read() or '[]'
|
||||
return json.loads(command_dump)
|
||||
|
||||
else:
|
||||
return generate_command_cache()
|
||||
|
||||
|
||||
def get_frappe_help(bench_path='.'):
|
||||
python = get_env_cmd('python', bench_path=bench_path)
|
||||
sites_path = os.path.join(bench_path, 'sites')
|
||||
@ -113,6 +137,7 @@ def get_frappe_help(bench_path='.'):
|
||||
except:
|
||||
return ""
|
||||
|
||||
|
||||
def change_working_directory():
|
||||
"""Allows bench commands to be run from anywhere inside a bench directory"""
|
||||
cur_dir = os.path.abspath(".")
|
||||
|
@ -41,7 +41,8 @@ bench_command.add_command(switch_to_develop)
|
||||
|
||||
from bench.commands.utils import (start, restart, set_nginx_port, set_ssl_certificate, set_ssl_certificate_key, set_url_root,
|
||||
set_mariadb_host, set_default_site, download_translations, backup_site, backup_all_sites, release, renew_lets_encrypt,
|
||||
disable_production, bench_src, prepare_beta_release, set_redis_cache_host, set_redis_queue_host, set_redis_socketio_host, find_benches, migrate_env)
|
||||
disable_production, bench_src, prepare_beta_release, set_redis_cache_host, set_redis_queue_host, set_redis_socketio_host, find_benches, migrate_env,
|
||||
generate_command_cache, clear_command_cache)
|
||||
bench_command.add_command(start)
|
||||
bench_command.add_command(restart)
|
||||
bench_command.add_command(set_nginx_port)
|
||||
@ -63,7 +64,8 @@ bench_command.add_command(bench_src)
|
||||
bench_command.add_command(prepare_beta_release)
|
||||
bench_command.add_command(find_benches)
|
||||
bench_command.add_command(migrate_env)
|
||||
|
||||
bench_command.add_command(generate_command_cache)
|
||||
bench_command.add_command(clear_command_cache)
|
||||
|
||||
from bench.commands.setup import setup
|
||||
bench_command.add_command(setup)
|
||||
|
@ -2,12 +2,21 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
# imports - module imports
|
||||
from bench.utils import exec_cmd
|
||||
|
||||
# imports - third party imports
|
||||
from six import PY3
|
||||
import click
|
||||
from six import PY3
|
||||
|
||||
# imports - module imports
|
||||
import bench.config.lets_encrypt
|
||||
import bench.config.nginx
|
||||
import bench.config.procfile
|
||||
import bench.config.production_setup
|
||||
import bench.config.redis
|
||||
import bench.config.site_config
|
||||
import bench.config.supervisor
|
||||
|
||||
import bench.utils
|
||||
from bench.utils import exec_cmd, run_playbook
|
||||
|
||||
|
||||
@click.group(help="Setup command group for enabling setting up a Frappe environment")
|
||||
@ -18,80 +27,59 @@ def setup():
|
||||
@click.command("sudoers", help="Add commands to sudoers list for execution without password")
|
||||
@click.argument("user")
|
||||
def setup_sudoers(user):
|
||||
from bench.utils import setup_sudoers
|
||||
setup_sudoers(user)
|
||||
bench.utils.setup_sudoers(user)
|
||||
|
||||
|
||||
@click.command("nginx", help="Generate configuration files for NGINX")
|
||||
@click.option("--yes", help="Yes to regeneration of nginx config file", default=False, is_flag=True)
|
||||
def setup_nginx(yes=False):
|
||||
from bench.config.nginx import make_nginx_conf
|
||||
make_nginx_conf(bench_path=".", yes=yes)
|
||||
bench.config.nginx.make_nginx_conf(bench_path=".", yes=yes)
|
||||
|
||||
|
||||
@click.command("reload-nginx", help="Checks NGINX config file and reloads service")
|
||||
def reload_nginx():
|
||||
from bench.config.production_setup import reload_nginx
|
||||
reload_nginx()
|
||||
bench.config.production_setup.reload_nginx()
|
||||
|
||||
|
||||
@click.command("supervisor", help="Generate configuration for supervisor")
|
||||
@click.option("--user", help="optional user argument")
|
||||
@click.option("--yes", help="Yes to regeneration of supervisor config", is_flag=True, default=False)
|
||||
def setup_supervisor(user=None, yes=False):
|
||||
from bench.config.supervisor import generate_supervisor_config
|
||||
generate_supervisor_config(bench_path=".", user=user, yes=yes)
|
||||
bench.config.supervisor.generate_supervisor_config(bench_path=".", user=user, yes=yes)
|
||||
|
||||
|
||||
@click.command("redis", help="Generates configuration for Redis")
|
||||
def setup_redis():
|
||||
from bench.config.redis import generate_config
|
||||
generate_config(".")
|
||||
bench.config.redis.generate_config(".")
|
||||
|
||||
|
||||
@click.command("fonts", help="Add Frappe fonts to system")
|
||||
def setup_fonts():
|
||||
from bench.utils import setup_fonts
|
||||
setup_fonts()
|
||||
bench.utils.setup_fonts()
|
||||
|
||||
|
||||
@click.command("production", help="Setup Frappe production environment for specific user")
|
||||
@click.argument("user")
|
||||
@click.option("--yes", help="Yes to regeneration config", is_flag=True, default=False)
|
||||
def setup_production(user, yes=False):
|
||||
from bench.config.production_setup import setup_production
|
||||
# Install prereqs for production
|
||||
from distutils.spawn import find_executable
|
||||
if not find_executable("ansible"):
|
||||
exec_cmd("sudo -H {0} -m pip install ansible".format(sys.executable))
|
||||
if not find_executable("fail2ban-client"):
|
||||
exec_cmd("bench setup role fail2ban")
|
||||
if not find_executable("nginx"):
|
||||
exec_cmd("bench setup role nginx")
|
||||
if not find_executable("supervisord"):
|
||||
exec_cmd("bench setup role supervisor")
|
||||
setup_production(user=user, yes=yes)
|
||||
bench.config.production_setup.setup_production(user=user, yes=yes)
|
||||
|
||||
|
||||
@click.command("backups", help="Add cronjob for bench backups")
|
||||
def setup_backups():
|
||||
from bench.utils import setup_backups
|
||||
setup_backups()
|
||||
bench.utils.setup_backups()
|
||||
|
||||
|
||||
@click.command("env", help="Setup virtualenv for bench")
|
||||
@click.option("--python", type = str, default = "python3", help = "Path to Python Executable.")
|
||||
def setup_env(python="python3"):
|
||||
from bench.utils import setup_env
|
||||
setup_env(python=python)
|
||||
bench.utils.setup_env(python=python)
|
||||
|
||||
|
||||
@click.command("firewall", help="Setup firewall for system")
|
||||
@click.option("--ssh_port")
|
||||
@click.option("--force")
|
||||
def setup_firewall(ssh_port=None, force=False):
|
||||
from bench.utils import run_playbook
|
||||
|
||||
if not force:
|
||||
click.confirm("Setting up the firewall will block all ports except 80, 443 and {0}\nDo you want to continue?".format(ssh_port), abort=True)
|
||||
|
||||
@ -105,8 +93,6 @@ def setup_firewall(ssh_port=None, force=False):
|
||||
@click.argument("port")
|
||||
@click.option("--force")
|
||||
def set_ssh_port(port, force=False):
|
||||
from bench.utils import run_playbook
|
||||
|
||||
if not force:
|
||||
click.confirm("This will change your SSH Port to {}\nDo you want to continue?".format(port), abort=True)
|
||||
|
||||
@ -118,8 +104,7 @@ def set_ssh_port(port, force=False):
|
||||
@click.option("--custom-domain")
|
||||
@click.option('-n', '--non-interactive', default=False, is_flag=True, help="Run command non-interactively. This flag restarts nginx and runs certbot non interactively. Shouldn't be used on 1'st attempt")
|
||||
def setup_letsencrypt(site, custom_domain, non_interactive):
|
||||
from bench.config.lets_encrypt import setup_letsencrypt
|
||||
setup_letsencrypt(site, custom_domain, bench_path=".", interactive=not non_interactive)
|
||||
bench.config.lets_encrypt.setup_letsencrypt(site, custom_domain, bench_path=".", interactive=not non_interactive)
|
||||
|
||||
|
||||
@click.command("wildcard-ssl", help="Setup wildcard SSL certificate for multi-tenant bench")
|
||||
@ -127,20 +112,17 @@ def setup_letsencrypt(site, custom_domain, non_interactive):
|
||||
@click.option("--email")
|
||||
@click.option("--exclude-base-domain", default=False, is_flag=True, help="SSL Certificate not applicable for base domain")
|
||||
def setup_wildcard_ssl(domain, email, exclude_base_domain):
|
||||
from bench.config.lets_encrypt import setup_wildcard_ssl
|
||||
setup_wildcard_ssl(domain, email, bench_path=".", exclude_base_domain=exclude_base_domain)
|
||||
bench.config.lets_encrypt.setup_wildcard_ssl(domain, email, bench_path=".", exclude_base_domain=exclude_base_domain)
|
||||
|
||||
|
||||
@click.command("procfile", help="Generate Procfile for bench start")
|
||||
def setup_procfile():
|
||||
from bench.config.procfile import setup_procfile
|
||||
setup_procfile(".")
|
||||
bench.config.procfile.setup_procfile(".")
|
||||
|
||||
|
||||
@click.command("socketio", help="Setup node dependencies for socketio server")
|
||||
def setup_socketio():
|
||||
from bench.utils import setup_socketio
|
||||
setup_socketio()
|
||||
bench.utils.setup_socketio()
|
||||
|
||||
|
||||
@click.command("requirements", help="Setup Python and Node dependencies")
|
||||
@ -213,34 +195,28 @@ def setup_config():
|
||||
@click.option("--ssl-certificate-key", help="Absolute path to SSL Certificate Key")
|
||||
def add_domain(domain, site=None, ssl_certificate=None, ssl_certificate_key=None):
|
||||
"""Add custom domain to site"""
|
||||
from bench.config.site_config import add_domain
|
||||
|
||||
if not site:
|
||||
print("Please specify site")
|
||||
sys.exit(1)
|
||||
|
||||
add_domain(site, domain, ssl_certificate, ssl_certificate_key, bench_path=".")
|
||||
bench.config.site_config.add_domain(site, domain, ssl_certificate, ssl_certificate_key, bench_path=".")
|
||||
|
||||
|
||||
@click.command("remove-domain", help="Remove custom domain from a site")
|
||||
@click.argument("domain")
|
||||
@click.option("--site", prompt=True)
|
||||
def remove_domain(domain, site=None):
|
||||
from bench.config.site_config import remove_domain
|
||||
|
||||
if not site:
|
||||
print("Please specify site")
|
||||
sys.exit(1)
|
||||
|
||||
remove_domain(site, domain, bench_path=".")
|
||||
bench.config.site_config.remove_domain(site, domain, bench_path=".")
|
||||
|
||||
|
||||
@click.command("sync-domains", help="Check if there is a change in domains. If yes, updates the domains list.")
|
||||
@click.option("--domain", multiple=True)
|
||||
@click.option("--site", prompt=True)
|
||||
def sync_domains(domain=None, site=None):
|
||||
from bench.config.site_config import sync_domains
|
||||
|
||||
if not site:
|
||||
print("Please specify site")
|
||||
sys.exit(1)
|
||||
@ -251,7 +227,7 @@ def sync_domains(domain=None, site=None):
|
||||
print("Domains should be a json list of strings or dictionaries")
|
||||
sys.exit(1)
|
||||
|
||||
changed = sync_domains(site, domains, bench_path=".")
|
||||
changed = bench.config.site_config.sync_domains(site, domains, bench_path=".")
|
||||
|
||||
# if changed, success, else failure
|
||||
sys.exit(0 if changed else 1)
|
||||
@ -263,8 +239,6 @@ def sync_domains(domain=None, site=None):
|
||||
@click.option("--mysql_root_password")
|
||||
@click.option("--container", is_flag=True, default=False)
|
||||
def setup_roles(role, **kwargs):
|
||||
from bench.utils import run_playbook
|
||||
|
||||
extra_vars = {"production": True}
|
||||
extra_vars.update(kwargs)
|
||||
|
||||
@ -279,7 +253,6 @@ def setup_roles(role, **kwargs):
|
||||
@click.option("--bantime", default=600, help="The counter is set to zero if no match is found within 'findtime' seconds. Default is 600 seconds")
|
||||
@click.option("--findtime", default=600, help="Duration (in seconds) for IP to be banned for. Negative number for 'permanent' ban. Default is 600 seconds")
|
||||
def setup_nginx_proxy_jail(**kwargs):
|
||||
from bench.utils import run_playbook
|
||||
run_playbook("roles/fail2ban/tasks/configure_nginx_jail.yml", extra_vars=kwargs)
|
||||
|
||||
|
||||
|
@ -180,3 +180,15 @@ def find_benches(location):
|
||||
def migrate_env(python, backup=True):
|
||||
from bench.utils import migrate_env
|
||||
migrate_env(python=python, backup=backup)
|
||||
|
||||
|
||||
@click.command('generate-command-cache', help="Caches Frappe Framework commands")
|
||||
def generate_command_cache(bench_path='.'):
|
||||
from bench.utils import generate_command_cache
|
||||
return generate_command_cache(bench_path=bench_path)
|
||||
|
||||
|
||||
@click.command('clear-command-cache', help="Clears Frappe Framework cached commands")
|
||||
def clear_command_cache(bench_path='.'):
|
||||
from bench.utils import clear_command_cache
|
||||
return clear_command_cache(bench_path=bench_path)
|
||||
|
@ -1,11 +1,30 @@
|
||||
from bench.utils import get_program, exec_cmd, get_cmd_output, fix_prod_setup_perms, get_bench_name, find_executable, CommandFailedError
|
||||
# imports - standard imports
|
||||
import os
|
||||
import sys
|
||||
from distutils.spawn import find_executable
|
||||
|
||||
# imports - module imports
|
||||
from bench.config.common_site_config import get_config
|
||||
from bench.config.nginx import make_nginx_conf
|
||||
from bench.config.supervisor import generate_supervisor_config
|
||||
from bench.config.systemd import generate_systemd_config
|
||||
from bench.config.nginx import make_nginx_conf
|
||||
from bench.config.common_site_config import get_config
|
||||
import os, subprocess
|
||||
from bench.utils import CommandFailedError, exec_cmd, fix_prod_setup_perms, get_bench_name, get_cmd_output
|
||||
|
||||
|
||||
def setup_production_prerequisites():
|
||||
"""Installs ansible, fail2banc, NGINX and supervisor"""
|
||||
if not find_executable("ansible"):
|
||||
exec_cmd("sudo {0} -m pip install ansible".format(sys.executable))
|
||||
if not find_executable("fail2ban-client"):
|
||||
exec_cmd("bench setup role fail2ban")
|
||||
if not find_executable("nginx"):
|
||||
exec_cmd("bench setup role nginx")
|
||||
if not find_executable("supervisord"):
|
||||
exec_cmd("bench setup role supervisor")
|
||||
|
||||
|
||||
def setup_production(user, bench_path='.', yes=False):
|
||||
setup_production_prerequisites()
|
||||
if get_config(bench_path).get('restart_supervisor_on_update') and get_config(bench_path).get('restart_systemd_on_update'):
|
||||
raise Exception("You cannot use supervisor and systemd at the same time. Modify your common_site_config accordingly." )
|
||||
|
||||
@ -40,6 +59,7 @@ def setup_production(user, bench_path='.', yes=False):
|
||||
|
||||
reload_nginx()
|
||||
|
||||
|
||||
def disable_production(bench_path='.'):
|
||||
bench_name = get_bench_name(bench_path)
|
||||
|
||||
@ -62,28 +82,35 @@ def disable_production(bench_path='.'):
|
||||
|
||||
reload_nginx()
|
||||
|
||||
def service(service, option):
|
||||
if os.path.basename(get_program(['systemctl']) or '') == 'systemctl' and is_running_systemd():
|
||||
exec_cmd("sudo {service_manager} {option} {service}".format(service_manager='systemctl', option=option, service=service))
|
||||
elif os.path.basename(get_program(['service']) or '') == 'service':
|
||||
exec_cmd("sudo {service_manager} {service} {option} ".format(service_manager='service', service=service, option=option))
|
||||
|
||||
def service(service_name, service_option):
|
||||
if os.path.basename(find_executable('systemctl') or '') == 'systemctl' and is_running_systemd():
|
||||
systemctl_cmd = "sudo {service_manager} {service_option} {service_name}"
|
||||
exec_cmd(systemctl_cmd.format(service_manager='systemctl', service_option=service_option, service_name=service_name))
|
||||
|
||||
elif os.path.basename(find_executable('service') or '') == 'service':
|
||||
service_cmd = "sudo {service_manager} {service_name} {service_option}"
|
||||
exec_cmd(service_cmd.format(service_manager='service', service_name=service_name, service_option=service_option))
|
||||
|
||||
else:
|
||||
# look for 'service_manager' and 'service_manager_command' in environment
|
||||
service_manager = os.environ.get("BENCH_SERVICE_MANAGER")
|
||||
if service_manager:
|
||||
service_manager_command = (os.environ.get("BENCH_SERVICE_MANAGER_COMMAND")
|
||||
or "{service_manager} {option} {service}").format(service_manager=service_manager, service=service, option=option)
|
||||
or "{service_manager} {service_option} {service}").format(service_manager=service_manager, service=service, service_option=service_option)
|
||||
exec_cmd(service_manager_command)
|
||||
|
||||
else:
|
||||
raise Exception('No service manager found')
|
||||
|
||||
|
||||
def get_supervisor_confdir():
|
||||
possiblities = ('/etc/supervisor/conf.d', '/etc/supervisor.d/', '/etc/supervisord/conf.d', '/etc/supervisord.d')
|
||||
for possiblity in possiblities:
|
||||
if os.path.exists(possiblity):
|
||||
return possiblity
|
||||
|
||||
|
||||
def remove_default_nginx_configs():
|
||||
default_nginx_configs = ['/etc/nginx/conf.d/default.conf', '/etc/nginx/sites-enabled/default']
|
||||
|
||||
@ -95,6 +122,7 @@ def remove_default_nginx_configs():
|
||||
def is_centos7():
|
||||
return os.path.exists('/etc/redhat-release') and get_cmd_output("cat /etc/redhat-release | sed 's/Linux\ //g' | cut -d' ' -f3 | cut -d. -f1").strip() == '7'
|
||||
|
||||
|
||||
def is_running_systemd():
|
||||
with open('/proc/1/comm') as f:
|
||||
comm = f.read().strip()
|
||||
@ -104,20 +132,21 @@ def is_running_systemd():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def reload_supervisor():
|
||||
supervisorctl = find_executable('supervisorctl')
|
||||
|
||||
try:
|
||||
# first try reread/update
|
||||
exec_cmd('sudo {0} reread'.format(supervisorctl))
|
||||
exec_cmd('sudo {0} update'.format(supervisorctl))
|
||||
exec_cmd('{0} reread'.format(supervisorctl))
|
||||
exec_cmd('{0} update'.format(supervisorctl))
|
||||
return
|
||||
except CommandFailedError:
|
||||
pass
|
||||
|
||||
try:
|
||||
# something is wrong, so try reloading
|
||||
exec_cmd('sudo {0} reload'.format(supervisorctl))
|
||||
exec_cmd('{0} reload'.format(supervisorctl))
|
||||
return
|
||||
except CommandFailedError:
|
||||
pass
|
||||
@ -138,7 +167,7 @@ def reload_supervisor():
|
||||
|
||||
def reload_nginx():
|
||||
try:
|
||||
subprocess.check_output(['sudo', find_executable('nginx'), '-t'])
|
||||
exec_cmd('sudo {0} -t'.format(find_executable('nginx')))
|
||||
except:
|
||||
raise
|
||||
|
||||
|
@ -1,17 +1,27 @@
|
||||
import os, getpass, click
|
||||
import bench
|
||||
# imports - standard imports
|
||||
import getpass
|
||||
import os
|
||||
|
||||
def generate_supervisor_config(bench_path, user=None, yes=False):
|
||||
# imports - module imports
|
||||
import bench
|
||||
from bench.app import get_current_frappe_version, use_rq
|
||||
from bench.utils import get_bench_name, find_executable
|
||||
from bench.config.common_site_config import get_config, update_config, get_gunicorn_workers
|
||||
|
||||
template = bench.env.get_template('supervisor.conf')
|
||||
# imports - third party imports
|
||||
import click
|
||||
from six.moves import configparser
|
||||
|
||||
|
||||
def generate_supervisor_config(bench_path, user=None, yes=False):
|
||||
"""Generate supervisor config for respective bench path"""
|
||||
if not user:
|
||||
user = getpass.getuser()
|
||||
|
||||
config = get_config(bench_path=bench_path)
|
||||
update_supervisord_conf(user=user)
|
||||
|
||||
template = bench.env.get_template('supervisor.conf')
|
||||
config = get_config(bench_path=bench_path)
|
||||
bench_dir = os.path.abspath(bench_path)
|
||||
|
||||
config = template.render(**{
|
||||
@ -44,3 +54,37 @@ def generate_supervisor_config(bench_path, user=None, yes=False):
|
||||
update_config({'restart_supervisor_on_update': True}, bench_path=bench_path)
|
||||
update_config({'restart_systemd_on_update': False}, bench_path=bench_path)
|
||||
|
||||
|
||||
def get_supervisord_conf():
|
||||
"""Returns path of supervisord config from possible paths"""
|
||||
possibilities = ("supervisord.conf", "etc/supervisord.conf", "/etc/supervisord.conf", "/etc/supervisor/supervisord.conf", "/etc/supervisord.conf")
|
||||
|
||||
for possibility in possibilities:
|
||||
if os.path.exists(possibility):
|
||||
return possibility
|
||||
|
||||
|
||||
def update_supervisord_conf(user):
|
||||
"""From bench v5.0, we're moving to supervisor running as user"""
|
||||
from bench.config.production_setup import service
|
||||
|
||||
supervisord_conf = get_supervisord_conf()
|
||||
section = "unix_http_server"
|
||||
|
||||
if not supervisord_conf:
|
||||
return
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read(supervisord_conf)
|
||||
|
||||
if section not in config.sections():
|
||||
config.add_section(section)
|
||||
|
||||
config.set(section, "chmod", "0760")
|
||||
config.set(section, "chown", "{user}:{user}".format(user=user))
|
||||
|
||||
with open(supervisord_conf, "w") as f:
|
||||
config.write(f)
|
||||
|
||||
# restart supervisor to take new changes into effect
|
||||
service('supervisor', 'restart')
|
||||
|
@ -1,20 +1,20 @@
|
||||
# This file is auto-generated by frappe/bench
|
||||
# To re-generate this file, run "bench setup sudoers"
|
||||
|
||||
{% if service %}
|
||||
{{ user }} ALL = (root) {{ service }}
|
||||
{{ user }} ALL = (root) NOPASSWD: {{ service }} nginx *
|
||||
{{ user }} ALL = (root) NOPASSWD: {{ service }} supervisord *
|
||||
{% endif %}
|
||||
|
||||
{% if systemctl %}
|
||||
{{ user }} ALL = (root) {{ systemctl }}
|
||||
{{ user }} ALL = (root) NOPASSWD: {{ systemctl }} * nginx
|
||||
{{ user }} ALL = (root) NOPASSWD: {{ systemctl }} * supervisord
|
||||
{% endif %}
|
||||
{% if supervisorctl %}
|
||||
{{ user }} ALL = (root) NOPASSWD: {{ supervisorctl }}
|
||||
{% endif %}
|
||||
|
||||
{% if nginx %}
|
||||
{{ user }} ALL = (root) NOPASSWD: {{ nginx }}
|
||||
{% endif %}
|
||||
|
||||
{{ user }} ALL = (root) NOPASSWD: /opt/certbot-auto
|
||||
{{ user }} ALL = (root) NOPASSWD: {{ bench }}
|
||||
Defaults:{{ user }} !requiretty
|
||||
|
||||
|
@ -4,3 +4,4 @@ bench.patches.v3.redis_bind_ip
|
||||
bench.patches.v4.update_node
|
||||
bench.patches.v4.update_socketio
|
||||
bench.patches.v4.install_yarn #2
|
||||
bench.patches.v5.fix_user_permissions
|
||||
|
0
bench/patches/v5/__init__.py
Normal file
0
bench/patches/v5/__init__.py
Normal file
59
bench/patches/v5/fix_user_permissions.py
Normal file
59
bench/patches/v5/fix_user_permissions.py
Normal file
@ -0,0 +1,59 @@
|
||||
# imports - standard imports
|
||||
import getpass
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# imports - module imports
|
||||
from bench.cli import change_uid_msg
|
||||
from bench.config.production_setup import get_supervisor_confdir, is_centos7
|
||||
from bench.config.common_site_config import get_config
|
||||
from bench.utils import exec_cmd, get_bench_name, get_cmd_output
|
||||
|
||||
|
||||
def is_sudoers_set():
|
||||
"""Check if bench sudoers is set"""
|
||||
cmd = ["sudo", "-n", "bench"]
|
||||
|
||||
with open(os.devnull, "wb") as f:
|
||||
return_code_check = not subprocess.call(cmd, stdout=f)
|
||||
|
||||
if return_code_check:
|
||||
try:
|
||||
bench_warn = change_uid_msg in get_cmd_output(cmd, _raise=False)
|
||||
except subprocess.CalledProcessError:
|
||||
bench_warn = False
|
||||
finally:
|
||||
return_code_check = return_code_check and bench_warn
|
||||
|
||||
return return_code_check
|
||||
|
||||
|
||||
def is_production_set(bench_path):
|
||||
"""Check if production is set for current bench"""
|
||||
production_setup = False
|
||||
bench_name = get_bench_name(bench_path)
|
||||
|
||||
supervisor_conf_extn = "ini" if is_centos7() else "conf"
|
||||
supervisor_conf_file_name = '{bench_name}.{extn}'.format(bench_name=bench_name, extn=supervisor_conf_extn)
|
||||
supervisor_conf = os.path.join(get_supervisor_confdir(), supervisor_conf_file_name)
|
||||
|
||||
if os.path.exists(supervisor_conf):
|
||||
production_setup = production_setup or True
|
||||
|
||||
nginx_conf = '/etc/nginx/conf.d/{bench_name}.conf'.format(bench_name=bench_name)
|
||||
|
||||
if os.path.exists(nginx_conf):
|
||||
production_setup = production_setup or True
|
||||
|
||||
return production_setup
|
||||
|
||||
|
||||
def execute(bench_path):
|
||||
"""This patch checks if bench sudoers is set and regenerate supervisor and sudoers files"""
|
||||
user = get_config('.').get("frappe_user") or getpass.getuser()
|
||||
|
||||
if is_sudoers_set():
|
||||
exec_cmd("sudo bench setup sudoers {user}".format(user=user))
|
||||
|
||||
if is_production_set(bench_path):
|
||||
exec_cmd("sudo bench setup supervisor --yes --user {user}".format(user=user))
|
@ -61,6 +61,9 @@ class TestSetupProduction(TestBenchBase):
|
||||
|
||||
def assert_sudoers(self, user):
|
||||
sudoers_file = '/etc/sudoers.d/frappe'
|
||||
service = bench.utils.which("service")
|
||||
nginx = bench.utils.which("nginx")
|
||||
|
||||
self.assertTrue(self.file_exists(sudoers_file))
|
||||
|
||||
if os.environ.get("CI"):
|
||||
@ -69,9 +72,8 @@ class TestSetupProduction(TestBenchBase):
|
||||
with open(sudoers_file, 'r') as f:
|
||||
sudoers = f.read()
|
||||
|
||||
self.assertTrue('{user} ALL = (root) NOPASSWD: /usr/sbin/service nginx *'.format(user=user) in sudoers)
|
||||
self.assertTrue('{user} ALL = (root) NOPASSWD: /usr/bin/supervisorctl'.format(user=user) in sudoers)
|
||||
self.assertTrue('{user} ALL = (root) NOPASSWD: /usr/sbin/nginx'.format(user=user) in sudoers)
|
||||
self.assertTrue('{user} ALL = (root) NOPASSWD: {service} nginx *'.format(service=service, user=user) in sudoers)
|
||||
self.assertTrue('{user} ALL = (root) NOPASSWD: {nginx}'.format(nginx=nginx, user=user) in sudoers)
|
||||
|
||||
|
||||
def assert_supervisor_config(self, bench_name, use_rq=True):
|
||||
@ -126,12 +128,12 @@ class TestSetupProduction(TestBenchBase):
|
||||
|
||||
|
||||
def assert_supervisor_process(self, bench_name, use_rq=True, disable_production=False):
|
||||
out = bench.utils.get_cmd_output("sudo supervisorctl status")
|
||||
out = bench.utils.get_cmd_output("supervisorctl status")
|
||||
|
||||
while "STARTING" in out:
|
||||
print ("Waiting for all processes to start...")
|
||||
time.sleep(10)
|
||||
out = bench.utils.get_cmd_output("sudo supervisorctl status")
|
||||
out = bench.utils.get_cmd_output("supervisorctl status")
|
||||
|
||||
tests = [
|
||||
"{bench_name}-web:{bench_name}-frappe-web[\s]+RUNNING",
|
||||
|
176
bench/utils.py
176
bench/utils.py
@ -1,3 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# imports - standard imports
|
||||
import errno
|
||||
import glob
|
||||
@ -20,7 +23,9 @@ from distutils.spawn import find_executable
|
||||
|
||||
# imports - third party imports
|
||||
import click
|
||||
from crontab import CronTab
|
||||
import requests
|
||||
from semantic_version import Version
|
||||
from six import iteritems
|
||||
from six.moves.urllib.parse import urlparse
|
||||
|
||||
@ -35,8 +40,9 @@ class CommandFailedError(Exception):
|
||||
pass
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
bench_cache_file = '.bench.cmd'
|
||||
folders_in_bench = ('apps', 'sites', 'config', 'logs', 'config/pids')
|
||||
sudoers_file = '/etc/sudoers.d/frappe'
|
||||
|
||||
|
||||
class color:
|
||||
@ -60,15 +66,15 @@ def is_bench_directory(directory=os.path.curdir):
|
||||
|
||||
def log(message, level=0):
|
||||
levels = {
|
||||
0: color.blue + 'LOG', # normal
|
||||
0: color.blue + 'INFO', # normal
|
||||
1: color.green + 'SUCCESS', # success
|
||||
2: color.red + 'ERROR', # fail
|
||||
3: color.yellow + 'WARN' # warn/suggest
|
||||
}
|
||||
start = (levels.get(level) + ': ') if level in levels else ''
|
||||
end = '\033[0m'
|
||||
start_line = (levels.get(level) + ': ') if level in levels else ''
|
||||
end_line = '\033[0m'
|
||||
|
||||
print(start + message + end)
|
||||
print(start_line + message + end_line)
|
||||
|
||||
|
||||
def safe_decode(string, encoding = 'utf-8'):
|
||||
@ -79,6 +85,23 @@ def safe_decode(string, encoding = 'utf-8'):
|
||||
return string
|
||||
|
||||
|
||||
def check_latest_version():
|
||||
try:
|
||||
pypi_request = requests.get("https://pypi.org/pypi/frappe-bench/json")
|
||||
except Exception:
|
||||
# Exceptions thrown are defined in requests.exceptions
|
||||
# ignore checking on all Exceptions
|
||||
return
|
||||
|
||||
if pypi_request.status_code == 200:
|
||||
pypi_version_str = pypi_request.json().get('info').get('version')
|
||||
pypi_version = Version(pypi_version_str)
|
||||
local_version = Version(bench.__version__)
|
||||
|
||||
if pypi_version > local_version:
|
||||
log("A newer version of bench is available: {0} → {1}".format(local_version, pypi_version))
|
||||
|
||||
|
||||
def get_frappe(bench_path='.'):
|
||||
frappe = get_env_cmd('frappe', bench_path=bench_path)
|
||||
if not os.path.exists(frappe):
|
||||
@ -168,6 +191,8 @@ def update(pull=False, apps=apps, patch=False, build=False, requirements=False,
|
||||
if apps and not pull:
|
||||
apps = []
|
||||
|
||||
clear_command_cache(bench_path='.')
|
||||
|
||||
if conf.get('release_bench'):
|
||||
print('Release bench detected, cannot update!')
|
||||
sys.exit(1)
|
||||
@ -224,7 +249,7 @@ def update(pull=False, apps=apps, patch=False, build=False, requirements=False,
|
||||
conf.update({ "maintenance_mode": 0, "pause_scheduler": 0 })
|
||||
update_config(conf, bench_path=bench_path)
|
||||
|
||||
print("_" * 80 + "\nBench: Deployment tool for Frappe and Frappe Applications (https://frappe.io/bench).\nOpen source depends on your contributions, so please contribute bug reports, patches, fixes or cash and be a part of the community")
|
||||
print("_" * 80 + "\nBench: Deployment tool for Frappe and Frappe Applications (https://frappe.io/bench).\nOpen source depends on your contributions, so do give back by submitting bug reports, patches and fixes and be a part of the community :)")
|
||||
|
||||
|
||||
def copy_patches_txt(bench_path):
|
||||
@ -301,10 +326,12 @@ def get_venv_path():
|
||||
|
||||
def setup_env(bench_path='.', python='python3'):
|
||||
frappe = os.path.join(bench_path, "apps", "frappe")
|
||||
pip = os.path.join(".", "env", "bin", "pip")
|
||||
pip = os.path.join(bench_path, "env", "bin", "pip")
|
||||
virtualenv = get_venv_path()
|
||||
|
||||
exec_cmd('{} -q env -p {}'.format(virtualenv, python), cwd=bench_path)
|
||||
|
||||
if os.path.exists(frappe):
|
||||
exec_cmd('{} install -q -U -e {}'.format(pip, frappe), cwd=bench_path)
|
||||
|
||||
|
||||
@ -343,42 +370,27 @@ def get_sites(bench_path='.'):
|
||||
return sites
|
||||
|
||||
|
||||
def get_bench_dir(bench_path='.'):
|
||||
return os.path.abspath(bench_path)
|
||||
|
||||
|
||||
def setup_backups(bench_path='.'):
|
||||
from bench.config.common_site_config import get_config
|
||||
logger.info('setting up backups')
|
||||
bench_dir = get_bench_dir(bench_path=bench_path)
|
||||
|
||||
bench_dir = os.path.abspath(bench_path)
|
||||
user = get_config(bench_path=bench_dir).get('frappe_user')
|
||||
logfile = os.path.join(bench_dir, 'logs', 'backup.log')
|
||||
bench.set_frappe_version(bench_path=bench_path)
|
||||
system_crontab = CronTab(user=user)
|
||||
|
||||
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])
|
||||
backup_command = "cd {bench_dir} && {bench} --verbose --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_path=bench_path), 'logs', 'backup.log')))
|
||||
job_command = "{backup_command} >> {logfile} 2>&1".format(backup_command=backup_command, logfile=logfile)
|
||||
|
||||
|
||||
def add_to_crontab(line):
|
||||
current_crontab = read_crontab()
|
||||
line = str.encode(line)
|
||||
if not line in current_crontab:
|
||||
cmd = ["crontab"]
|
||||
if platform.system() == 'FreeBSD':
|
||||
cmd = ["crontab", "-"]
|
||||
s = subprocess.Popen(cmd, stdin=subprocess.PIPE)
|
||||
s.stdin.write(current_crontab)
|
||||
s.stdin.write(line + b'\n')
|
||||
s.stdin.close()
|
||||
|
||||
|
||||
def read_crontab():
|
||||
s = subprocess.Popen(["crontab", "-l"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
out = s.stdout.read()
|
||||
s.stdout.close()
|
||||
return out
|
||||
if job_command not in str(system_crontab):
|
||||
job = system_crontab.new(command=job_command, comment="bench auto backups set for every 6 hours")
|
||||
job.hour.every(6)
|
||||
system_crontab.write()
|
||||
|
||||
|
||||
def setup_sudoers(user):
|
||||
@ -397,16 +409,12 @@ def setup_sudoers(user):
|
||||
if set_permissions:
|
||||
os.chmod('/etc/sudoers', 0o440)
|
||||
|
||||
sudoers_file = '/etc/sudoers.d/frappe'
|
||||
|
||||
template = env.get_template('frappe_sudoers')
|
||||
frappe_sudoers = template.render(**{
|
||||
'user': user,
|
||||
'service': find_executable('service'),
|
||||
'systemctl': find_executable('systemctl'),
|
||||
'supervisorctl': find_executable('supervisorctl'),
|
||||
'nginx': find_executable('nginx'),
|
||||
'bench': find_executable('bench')
|
||||
})
|
||||
frappe_sudoers = safe_decode(frappe_sudoers)
|
||||
|
||||
@ -414,6 +422,7 @@ def setup_sudoers(user):
|
||||
f.write(frappe_sudoers)
|
||||
|
||||
os.chmod(sudoers_file, 0o440)
|
||||
log("Sudoers was set up for user {}".format(user), level=1)
|
||||
|
||||
|
||||
def setup_logging(bench_path='.'):
|
||||
@ -427,17 +436,11 @@ def setup_logging(bench_path='.'):
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
def get_program(programs):
|
||||
program = None
|
||||
for p in programs:
|
||||
program = find_executable(p)
|
||||
if program:
|
||||
break
|
||||
return program
|
||||
|
||||
|
||||
def get_process_manager():
|
||||
return get_program(['foreman', 'forego', 'honcho'])
|
||||
for proc_man in ['honcho', 'foreman', 'forego']:
|
||||
proc_man_path = find_executable(proc_man)
|
||||
if proc_man_path:
|
||||
return proc_man_path
|
||||
|
||||
|
||||
def start(no_dev=False, concurrency=None, procfile=None):
|
||||
@ -492,15 +495,16 @@ def check_git_for_shallow_clone():
|
||||
return True
|
||||
|
||||
|
||||
def get_cmd_output(cmd, cwd='.'):
|
||||
def get_cmd_output(cmd, cwd='.', _raise=True):
|
||||
output = ""
|
||||
try:
|
||||
output = subprocess.check_output(cmd, cwd=cwd, shell=True, stderr=subprocess.PIPE).strip()
|
||||
output = output.decode('utf-8')
|
||||
return output
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.output:
|
||||
print(e.output)
|
||||
output = e.output
|
||||
elif _raise:
|
||||
raise
|
||||
return safe_decode(output)
|
||||
|
||||
|
||||
def safe_encode(what, encoding = 'utf-8'):
|
||||
@ -522,7 +526,7 @@ def restart_supervisor_processes(bench_path='.', web_workers=False):
|
||||
exec_cmd(cmd, cwd=bench_path)
|
||||
|
||||
else:
|
||||
supervisor_status = subprocess.check_output(['sudo', 'supervisorctl', 'status'], cwd=bench_path)
|
||||
supervisor_status = get_cmd_output('supervisorctl status', cwd=bench_path)
|
||||
supervisor_status = safe_decode(supervisor_status)
|
||||
|
||||
if web_workers and '{bench_name}-web:'.format(bench_name=bench_name) in supervisor_status:
|
||||
@ -539,11 +543,10 @@ def restart_supervisor_processes(bench_path='.', web_workers=False):
|
||||
else:
|
||||
group = 'frappe:'
|
||||
|
||||
exec_cmd('sudo supervisorctl restart {group}'.format(group=group), cwd=bench_path)
|
||||
exec_cmd('supervisorctl restart {group}'.format(group=group), cwd=bench_path)
|
||||
|
||||
|
||||
def restart_systemd_processes(bench_path='.', web_workers=False):
|
||||
from .config.common_site_config import get_config
|
||||
bench_name = get_bench_name(bench_path)
|
||||
exec_cmd('sudo systemctl stop -- $(systemctl show -p Requires {bench_name}.target | cut -d= -f2)'.format(bench_name=bench_name))
|
||||
exec_cmd('sudo systemctl start -- $(systemctl show -p Requires {bench_name}.target | cut -d= -f2)'.format(bench_name=bench_name))
|
||||
@ -597,6 +600,7 @@ def update_yarn_packages(bench_path='.'):
|
||||
for app in os.listdir(apps_dir):
|
||||
app_path = os.path.join(apps_dir, app)
|
||||
if os.path.exists(os.path.join(app_path, 'package.json')):
|
||||
print('\n{0}Installing node dependencies for {1}{2}'.format(color.yellow, app, color.nc))
|
||||
exec_cmd('yarn install', cwd=app_path)
|
||||
|
||||
|
||||
@ -831,7 +835,7 @@ def update_translations_p(args):
|
||||
|
||||
|
||||
def download_translations_p():
|
||||
pool = multiprocessing.Pool(4)
|
||||
pool = multiprocessing.Pool(multiprocessing.cpu_count())
|
||||
|
||||
langs = get_langs()
|
||||
apps = ('frappe', 'erpnext')
|
||||
@ -1051,8 +1055,8 @@ def migrate_env(python, backup=False):
|
||||
from bench.config.common_site_config import get_config
|
||||
from bench.app import get_apps
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
log.setLevel(logging.DEBUG)
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
nvenv = 'env'
|
||||
path = os.getcwd()
|
||||
@ -1068,12 +1072,12 @@ def migrate_env(python, backup=False):
|
||||
|
||||
redis = '{redis} -p {port}'.format(redis=which('redis-cli'), port=rredis.port)
|
||||
|
||||
log.debug('Clearing Redis Cache...')
|
||||
logger.debug('Clearing Redis Cache...')
|
||||
exec_cmd('{redis} FLUSHALL'.format(redis = redis))
|
||||
log.debug('Clearing Redis DataBase...')
|
||||
logger.debug('Clearing Redis DataBase...')
|
||||
exec_cmd('{redis} FLUSHDB'.format(redis = redis))
|
||||
except:
|
||||
log.warn('Please ensure Redis Connections are running or Daemonized.')
|
||||
logger.warn('Please ensure Redis Connections are running or Daemonized.')
|
||||
|
||||
# Backup venv: restore using `virtualenv --relocatable` if needed
|
||||
if backup:
|
||||
@ -1084,7 +1088,7 @@ def migrate_env(python, backup=False):
|
||||
source = os.path.join(path, 'env')
|
||||
target = parch
|
||||
|
||||
log.debug('Backing up Virtual Environment')
|
||||
logger.debug('Backing up Virtual Environment')
|
||||
stamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
||||
dest = os.path.join(path, str(stamp))
|
||||
|
||||
@ -1093,18 +1097,27 @@ def migrate_env(python, backup=False):
|
||||
|
||||
# Create virtualenv using specified python
|
||||
try:
|
||||
log.debug('Setting up a New Virtual {} Environment'.format(python))
|
||||
logger.debug('Setting up a New Virtual {} Environment'.format(python))
|
||||
exec_cmd('{virtualenv} --python {python} {pvenv}'.format(virtualenv=virtualenv, python=python, pvenv=pvenv))
|
||||
|
||||
apps = ' '.join(["-e {}".format(os.path.join("apps", app)) for app in get_apps()])
|
||||
exec_cmd('{0} install -q -U {1}'.format(pip, apps))
|
||||
|
||||
log.debug('Migration Successful to {}'.format(python))
|
||||
logger.debug('Migration Successful to {}'.format(python))
|
||||
except:
|
||||
log.debug('Migration Error')
|
||||
logger.debug('Migration Error')
|
||||
raise
|
||||
|
||||
|
||||
def is_dist_editable(dist):
|
||||
"""Is distribution an editable install?"""
|
||||
for path_item in sys.path:
|
||||
egg_link = os.path.join(path_item, dist + '.egg-link')
|
||||
if os.path.isfile(egg_link):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def find_parent_bench(path):
|
||||
"""Checks if parent directories are benches"""
|
||||
if is_bench_directory(directory=path):
|
||||
@ -1117,3 +1130,36 @@ def find_parent_bench(path):
|
||||
# NOTE: the os.path.split assumes that given path is absolute
|
||||
parent_dir = os.path.split(path)[0]
|
||||
return find_parent_bench(parent_dir)
|
||||
|
||||
|
||||
def generate_command_cache(bench_path='.'):
|
||||
"""Caches all available commands (even custom apps) via Frappe
|
||||
Default caching behaviour: generated the first time any command (for a specific bench directory)
|
||||
"""
|
||||
|
||||
python = get_env_cmd('python', bench_path=bench_path)
|
||||
sites_path = os.path.join(bench_path, 'sites')
|
||||
|
||||
if os.path.exists(bench_cache_file):
|
||||
os.remove(bench_cache_file)
|
||||
|
||||
try:
|
||||
output = get_cmd_output("{0} -m frappe.utils.bench_helper get-frappe-commands".format(python), cwd=sites_path)
|
||||
with open(bench_cache_file, 'w') as f:
|
||||
json.dump(eval(output), f)
|
||||
return json.loads(output)
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
if hasattr(e, "stderr"):
|
||||
print(e.stderr.decode('utf-8'))
|
||||
|
||||
|
||||
def clear_command_cache(bench_path='.'):
|
||||
"""Clears commands cached
|
||||
Default invalidation behaviour: destroyed on each run of `bench update`
|
||||
"""
|
||||
|
||||
if os.path.exists(bench_cache_file):
|
||||
os.remove(bench_cache_file)
|
||||
else:
|
||||
print("Bench command cache doesn't exist in this folder!")
|
@ -72,7 +72,7 @@
|
||||
get_url:
|
||||
url: https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_{{ "amd64" if ansible_architecture == "x86_64" else "i386"}}.deb
|
||||
dest: /tmp/wkhtmltox.deb
|
||||
checksum: '{{ 1140b0ab02aa6e17346af2f14ed0de807376de475ba90e1db3975f112fbd20bb if ansible_architecture == "x86_64" else 5b2d15e738ac479e7a8ca6fd765f406c3684a48091813520f87878278d6dd22a }}'
|
||||
checksum: "sha256:{{ '1140b0ab02aa6e17346af2f14ed0de807376de475ba90e1db3975f112fbd20bb' if ansible_architecture == 'x86_64' else '5b2d15e738ac479e7a8ca6fd765f406c3684a48091813520f87878278d6dd22a' }}"
|
||||
when: ansible_distribution == 'Debian' and ansible_distribution_major_version == '9'
|
||||
|
||||
- name: download wkthmltox Debian 10
|
||||
|
Loading…
Reference in New Issue
Block a user