mirror of
https://github.com/frappe/bench.git
synced 2025-01-10 09:02:10 +00:00
Merge branch 'develop' into setup-supervisor-skip-redis
This commit is contained in:
commit
f109c3eaad
22
bench/app.py
22
bench/app.py
@ -6,20 +6,14 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# imports - third party imports
|
# imports - third party imports
|
||||||
import click
|
import click
|
||||||
import git
|
|
||||||
import requests
|
|
||||||
import semantic_version
|
|
||||||
from six.moves import reload_module
|
|
||||||
|
|
||||||
# imports - module imports
|
# imports - module imports
|
||||||
import bench
|
import bench
|
||||||
from bench.config.common_site_config import get_config
|
|
||||||
from bench.utils import color, CommandFailedError, build_assets, check_git_for_shallow_clone, exec_cmd, get_cmd_output, get_frappe, restart_supervisor_processes, restart_systemd_processes, run_frappe_cmd
|
from bench.utils import color, CommandFailedError, build_assets, check_git_for_shallow_clone, exec_cmd, get_cmd_output, get_frappe, restart_supervisor_processes, restart_systemd_processes, run_frappe_cmd
|
||||||
|
|
||||||
|
|
||||||
@ -91,6 +85,9 @@ def remove_from_excluded_apps_txt(app, bench_path='.'):
|
|||||||
return write_excluded_apps_txt(apps, bench_path=bench_path)
|
return write_excluded_apps_txt(apps, bench_path=bench_path)
|
||||||
|
|
||||||
def get_app(git_url, branch=None, bench_path='.', skip_assets=False, verbose=False, restart_bench=True, overwrite=False):
|
def get_app(git_url, branch=None, bench_path='.', skip_assets=False, verbose=False, restart_bench=True, overwrite=False):
|
||||||
|
import requests
|
||||||
|
import shutil
|
||||||
|
|
||||||
if not os.path.exists(git_url):
|
if not os.path.exists(git_url):
|
||||||
if not is_git_url(git_url):
|
if not is_git_url(git_url):
|
||||||
orgs = ['frappe', 'erpnext']
|
orgs = ['frappe', 'erpnext']
|
||||||
@ -166,6 +163,8 @@ def new_app(app, bench_path='.'):
|
|||||||
|
|
||||||
|
|
||||||
def install_app(app, bench_path=".", verbose=False, no_cache=False, restart_bench=True, skip_assets=False):
|
def install_app(app, bench_path=".", verbose=False, no_cache=False, restart_bench=True, skip_assets=False):
|
||||||
|
from bench.config.common_site_config import get_config
|
||||||
|
|
||||||
print('\n{0}Installing {1}{2}'.format(color.yellow, app, color.nc))
|
print('\n{0}Installing {1}{2}'.format(color.yellow, app, color.nc))
|
||||||
logger.log("installing {}".format(app))
|
logger.log("installing {}".format(app))
|
||||||
|
|
||||||
@ -194,6 +193,9 @@ def install_app(app, bench_path=".", verbose=False, no_cache=False, restart_benc
|
|||||||
|
|
||||||
|
|
||||||
def remove_app(app, bench_path='.'):
|
def remove_app(app, bench_path='.'):
|
||||||
|
import shutil
|
||||||
|
from bench.config.common_site_config import get_config
|
||||||
|
|
||||||
if app not in get_apps(bench_path):
|
if app not in get_apps(bench_path):
|
||||||
print("No app named {0}".format(app))
|
print("No app named {0}".format(app))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -221,6 +223,8 @@ def remove_app(app, bench_path='.'):
|
|||||||
|
|
||||||
def pull_apps(apps=None, bench_path='.', reset=False):
|
def pull_apps(apps=None, bench_path='.', reset=False):
|
||||||
'''Check all apps if there no local changes, pull'''
|
'''Check all apps if there no local changes, pull'''
|
||||||
|
from bench.config.common_site_config import get_config
|
||||||
|
|
||||||
rebase = '--rebase' if get_config(bench_path).get('rebase_on_pull') else ''
|
rebase = '--rebase' if get_config(bench_path).get('rebase_on_pull') else ''
|
||||||
|
|
||||||
apps = apps or get_apps(bench_path=bench_path)
|
apps = apps or get_apps(bench_path=bench_path)
|
||||||
@ -358,6 +362,8 @@ def get_repo_dir(app, bench_path='.'):
|
|||||||
return os.path.join(bench_path, 'apps', app)
|
return os.path.join(bench_path, 'apps', app)
|
||||||
|
|
||||||
def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrade=True):
|
def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrade=True):
|
||||||
|
import git
|
||||||
|
from six.moves import reload_module
|
||||||
from bench.utils import update_requirements, update_node_packages, backup_all_sites, patch_sites, build_assets, post_upgrade
|
from bench.utils import update_requirements, update_node_packages, backup_all_sites, patch_sites, build_assets, post_upgrade
|
||||||
apps_dir = os.path.join(bench_path, 'apps')
|
apps_dir = os.path.join(bench_path, 'apps')
|
||||||
version_upgrade = (False,)
|
version_upgrade = (False,)
|
||||||
@ -425,6 +431,8 @@ def get_version_from_string(contents, field='__version__'):
|
|||||||
return match.group(2)
|
return match.group(2)
|
||||||
|
|
||||||
def get_major_version(version):
|
def get_major_version(version):
|
||||||
|
import semantic_version
|
||||||
|
|
||||||
return semantic_version.Version(version).major
|
return semantic_version.Version(version).major
|
||||||
|
|
||||||
def install_apps_from_path(path, bench_path='.'):
|
def install_apps_from_path(path, bench_path='.'):
|
||||||
@ -433,6 +441,8 @@ def install_apps_from_path(path, bench_path='.'):
|
|||||||
get_app(app['url'], branch=app.get('branch'), bench_path=bench_path, skip_assets=True)
|
get_app(app['url'], branch=app.get('branch'), bench_path=bench_path, skip_assets=True)
|
||||||
|
|
||||||
def get_apps_json(path):
|
def get_apps_json(path):
|
||||||
|
import requests
|
||||||
|
|
||||||
if path.startswith('http'):
|
if path.startswith('http'):
|
||||||
r = requests.get(path)
|
r = requests.get(path)
|
||||||
return r.json()
|
return r.json()
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
# imports - standard imports
|
|
||||||
import ast
|
|
||||||
|
|
||||||
# imports - module imports
|
# imports - module imports
|
||||||
from bench.config.common_site_config import update_config, get_config, put_config
|
from bench.config.common_site_config import update_config, get_config, put_config
|
||||||
|
|
||||||
@ -52,6 +49,8 @@ def config_http_timeout(seconds):
|
|||||||
@click.command('set-common-config', help='Set value in common config')
|
@click.command('set-common-config', help='Set value in common config')
|
||||||
@click.option('configs', '-c', '--config', multiple=True, type=(str, str))
|
@click.option('configs', '-c', '--config', multiple=True, type=(str, str))
|
||||||
def set_common_config(configs):
|
def set_common_config(configs):
|
||||||
|
import ast
|
||||||
|
|
||||||
common_site_config = {}
|
common_site_config = {}
|
||||||
for key, value in configs:
|
for key, value in configs:
|
||||||
if value in ('true', 'false'):
|
if value in ('true', 'false'):
|
||||||
|
@ -6,10 +6,7 @@ import sys
|
|||||||
import click
|
import click
|
||||||
|
|
||||||
# imports - module imports
|
# imports - module imports
|
||||||
import bench.config.lets_encrypt
|
|
||||||
import bench.config.nginx
|
|
||||||
import bench.config.procfile
|
import bench.config.procfile
|
||||||
import bench.config.production_setup
|
|
||||||
import bench.config.redis
|
import bench.config.redis
|
||||||
import bench.config.site_config
|
import bench.config.site_config
|
||||||
import bench.config.supervisor
|
import bench.config.supervisor
|
||||||
@ -31,11 +28,15 @@ def setup_sudoers(user):
|
|||||||
@click.command("nginx", help="Generate configuration files for NGINX")
|
@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)
|
@click.option("--yes", help="Yes to regeneration of nginx config file", default=False, is_flag=True)
|
||||||
def setup_nginx(yes=False):
|
def setup_nginx(yes=False):
|
||||||
|
import bench.config.nginx
|
||||||
|
|
||||||
bench.config.nginx.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")
|
@click.command("reload-nginx", help="Checks NGINX config file and reloads service")
|
||||||
def reload_nginx():
|
def reload_nginx():
|
||||||
|
import bench.config.production_setup
|
||||||
|
|
||||||
bench.config.production_setup.reload_nginx()
|
bench.config.production_setup.reload_nginx()
|
||||||
|
|
||||||
|
|
||||||
@ -62,6 +63,8 @@ def setup_fonts():
|
|||||||
@click.argument("user")
|
@click.argument("user")
|
||||||
@click.option("--yes", help="Yes to regeneration config", is_flag=True, default=False)
|
@click.option("--yes", help="Yes to regeneration config", is_flag=True, default=False)
|
||||||
def setup_production(user, yes=False):
|
def setup_production(user, yes=False):
|
||||||
|
import bench.config.production_setup
|
||||||
|
|
||||||
bench.config.production_setup.setup_production(user=user, yes=yes)
|
bench.config.production_setup.setup_production(user=user, yes=yes)
|
||||||
|
|
||||||
|
|
||||||
@ -104,6 +107,8 @@ def set_ssh_port(port, force=False):
|
|||||||
@click.option("--custom-domain")
|
@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")
|
@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):
|
def setup_letsencrypt(site, custom_domain, non_interactive):
|
||||||
|
import bench.config.lets_encrypt
|
||||||
|
|
||||||
bench.config.lets_encrypt.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)
|
||||||
|
|
||||||
|
|
||||||
@ -112,6 +117,8 @@ def setup_letsencrypt(site, custom_domain, non_interactive):
|
|||||||
@click.option("--email")
|
@click.option("--email")
|
||||||
@click.option("--exclude-base-domain", default=False, is_flag=True, help="SSL Certificate not applicable for base domain")
|
@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):
|
def setup_wildcard_ssl(domain, email, exclude_base_domain):
|
||||||
|
import bench.config.lets_encrypt
|
||||||
|
|
||||||
bench.config.lets_encrypt.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)
|
||||||
|
|
||||||
|
|
||||||
@ -254,8 +261,8 @@ def setup_roles(role, **kwargs):
|
|||||||
|
|
||||||
@click.command("fail2ban", help="Setup fail2ban, an intrusion prevention software framework that protects computer servers from brute-force attacks")
|
@click.command("fail2ban", help="Setup fail2ban, an intrusion prevention software framework that protects computer servers from brute-force attacks")
|
||||||
@click.option("--maxretry", default=6, help="Number of matches (i.e. value of the counter) which triggers ban action on the IP. Default is 6 seconds" )
|
@click.option("--maxretry", default=6, help="Number of matches (i.e. value of the counter) which triggers ban action on the IP. Default is 6 seconds" )
|
||||||
@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("--bantime", default=600, help="Duration (in seconds) for IP to be banned for. Negative number for 'permanent' ban. 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")
|
@click.option("--findtime", default=600, help="The counter is set to zero if match found within 'findtime' seconds doesn't exceed 'maxretry'. Default is 600 seconds")
|
||||||
def setup_nginx_proxy_jail(**kwargs):
|
def setup_nginx_proxy_jail(**kwargs):
|
||||||
run_playbook("roles/fail2ban/tasks/configure_nginx_jail.yml", extra_vars=kwargs)
|
run_playbook("roles/fail2ban/tasks/configure_nginx_jail.yml", extra_vars=kwargs)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""Module for setting up system and respective bench configurations"""
|
"""Module for setting up system and respective bench configurations"""
|
||||||
|
|
||||||
# imports - third party imports
|
|
||||||
from jinja2 import Environment, PackageLoader
|
|
||||||
|
|
||||||
env = Environment(loader=PackageLoader('bench.config'))
|
def env():
|
||||||
|
from jinja2 import Environment, PackageLoader
|
||||||
|
return Environment(loader=PackageLoader('bench.config'))
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
# imports - standard imports
|
# imports - standard imports
|
||||||
import getpass
|
import getpass
|
||||||
import json
|
import json
|
||||||
import multiprocessing
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# imports - third party imports
|
|
||||||
from six.moves.urllib.parse import urlparse
|
|
||||||
|
|
||||||
|
|
||||||
default_config = {
|
default_config = {
|
||||||
@ -54,6 +51,8 @@ def get_config_path(bench_path):
|
|||||||
def get_gunicorn_workers():
|
def get_gunicorn_workers():
|
||||||
'''This function will return the maximum workers that can be started depending upon
|
'''This function will return the maximum workers that can be started depending upon
|
||||||
number of cpu's present on the machine'''
|
number of cpu's present on the machine'''
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"gunicorn_workers": multiprocessing.cpu_count() * 2 + 1
|
"gunicorn_workers": multiprocessing.cpu_count() * 2 + 1
|
||||||
}
|
}
|
||||||
@ -73,6 +72,8 @@ def update_config_for_frappe(config, bench_path):
|
|||||||
# TODO Optionally we need to add the host or domain name in case dns_multitenant is false
|
# TODO Optionally we need to add the host or domain name in case dns_multitenant is false
|
||||||
|
|
||||||
def make_ports(bench_path):
|
def make_ports(bench_path):
|
||||||
|
from six.moves.urllib.parse import urlparse
|
||||||
|
|
||||||
benches_path = os.path.dirname(os.path.abspath(bench_path))
|
benches_path = os.path.dirname(os.path.abspath(bench_path))
|
||||||
|
|
||||||
default_ports = {
|
default_ports = {
|
||||||
|
@ -3,8 +3,6 @@ import os
|
|||||||
|
|
||||||
# imports - third party imports
|
# imports - third party imports
|
||||||
import click
|
import click
|
||||||
from crontab import CronTab
|
|
||||||
from six.moves.urllib.request import urlretrieve
|
|
||||||
|
|
||||||
# imports - module imports
|
# imports - module imports
|
||||||
import bench
|
import bench
|
||||||
@ -48,7 +46,7 @@ def setup_letsencrypt(site, custom_domain, bench_path, interactive):
|
|||||||
|
|
||||||
|
|
||||||
def create_config(site, custom_domain):
|
def create_config(site, custom_domain):
|
||||||
config = bench.config.env.get_template('letsencrypt.cfg').render(domain=custom_domain or site)
|
config = bench.config.env().get_template('letsencrypt.cfg').render(domain=custom_domain or site)
|
||||||
config_path = '/etc/letsencrypt/configs/{site}.cfg'.format(site=custom_domain or site)
|
config_path = '/etc/letsencrypt/configs/{site}.cfg'.format(site=custom_domain or site)
|
||||||
create_dir_if_missing(config_path)
|
create_dir_if_missing(config_path)
|
||||||
|
|
||||||
@ -86,6 +84,8 @@ def run_certbot_and_setup_ssl(site, custom_domain, bench_path, interactive=True)
|
|||||||
|
|
||||||
|
|
||||||
def setup_crontab():
|
def setup_crontab():
|
||||||
|
from crontab import CronTab
|
||||||
|
|
||||||
job_command = '/opt/certbot-auto renew -a nginx --post-hook "systemctl reload nginx"'
|
job_command = '/opt/certbot-auto renew -a nginx --post-hook "systemctl reload nginx"'
|
||||||
job_comment = 'Renew lets-encrypt every month'
|
job_comment = 'Renew lets-encrypt every month'
|
||||||
print("Setting Up cron job to {0}".format(job_comment))
|
print("Setting Up cron job to {0}".format(job_comment))
|
||||||
@ -106,6 +106,8 @@ def create_dir_if_missing(path):
|
|||||||
|
|
||||||
|
|
||||||
def get_certbot():
|
def get_certbot():
|
||||||
|
from six.moves.urllib.request import urlretrieve
|
||||||
|
|
||||||
certbot_path = get_certbot_path()
|
certbot_path = get_certbot_path()
|
||||||
create_dir_if_missing(certbot_path)
|
create_dir_if_missing(certbot_path)
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ def make_nginx_conf(bench_path, yes=False):
|
|||||||
if not click.confirm('nginx.conf already exists and this will overwrite it. Do you want to continue?'):
|
if not click.confirm('nginx.conf already exists and this will overwrite it. Do you want to continue?'):
|
||||||
return
|
return
|
||||||
|
|
||||||
template = bench.config.env.get_template('nginx.conf')
|
template = bench.config.env().get_template('nginx.conf')
|
||||||
bench_path = os.path.abspath(bench_path)
|
bench_path = os.path.abspath(bench_path)
|
||||||
sites_path = os.path.join(bench_path, "sites")
|
sites_path = os.path.join(bench_path, "sites")
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ def make_bench_manager_nginx_conf(bench_path, yes=False, port=23624, domain=None
|
|||||||
from bench.config.site_config import get_site_config
|
from bench.config.site_config import get_site_config
|
||||||
from bench.config.common_site_config import get_config
|
from bench.config.common_site_config import get_config
|
||||||
|
|
||||||
template = bench.config.env.get_template('bench_manager_nginx.conf')
|
template = bench.config.env().get_template('bench_manager_nginx.conf')
|
||||||
bench_path = os.path.abspath(bench_path)
|
bench_path = os.path.abspath(bench_path)
|
||||||
sites_path = os.path.join(bench_path, "sites")
|
sites_path = os.path.join(bench_path, "sites")
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ def setup_procfile(bench_path, yes=False, skip_redis=False):
|
|||||||
click.confirm('A Procfile already exists and this will overwrite it. Do you want to continue?',
|
click.confirm('A Procfile already exists and this will overwrite it. Do you want to continue?',
|
||||||
abort=True)
|
abort=True)
|
||||||
|
|
||||||
procfile = bench.config.env.get_template('Procfile').render(
|
procfile = bench.config.env().get_template('Procfile').render(
|
||||||
node=find_executable("node") or find_executable("nodejs"),
|
node=find_executable("node") or find_executable("nodejs"),
|
||||||
use_rq=use_rq(bench_path),
|
use_rq=use_rq(bench_path),
|
||||||
webserver_port=config.get('webserver_port'),
|
webserver_port=config.get('webserver_port'),
|
||||||
|
@ -3,16 +3,14 @@ import os
|
|||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
# imports - third party imports
|
|
||||||
import semantic_version
|
|
||||||
from six.moves.urllib.parse import urlparse
|
|
||||||
|
|
||||||
# imports - module imports
|
# imports - module imports
|
||||||
import bench
|
import bench
|
||||||
from bench.config.common_site_config import get_config
|
from bench.config.common_site_config import get_config
|
||||||
|
|
||||||
|
|
||||||
def generate_config(bench_path):
|
def generate_config(bench_path):
|
||||||
|
from six.moves.urllib.parse import urlparse
|
||||||
|
|
||||||
config = get_config(bench_path)
|
config = get_config(bench_path)
|
||||||
|
|
||||||
ports = {}
|
ports = {}
|
||||||
@ -52,7 +50,7 @@ def generate_config(bench_path):
|
|||||||
os.makedirs(pid_path)
|
os.makedirs(pid_path)
|
||||||
|
|
||||||
def write_redis_config(template_name, context, bench_path):
|
def write_redis_config(template_name, context, bench_path):
|
||||||
template = bench.config.env.get_template(template_name)
|
template = bench.config.env().get_template(template_name)
|
||||||
|
|
||||||
if "pid_path" not in context:
|
if "pid_path" not in context:
|
||||||
context["pid_path"] = os.path.abspath(os.path.join(bench_path, "config", "pids"))
|
context["pid_path"] = os.path.abspath(os.path.join(bench_path, "config", "pids"))
|
||||||
@ -61,6 +59,8 @@ def write_redis_config(template_name, context, bench_path):
|
|||||||
f.write(template.render(**context))
|
f.write(template.render(**context))
|
||||||
|
|
||||||
def get_redis_version():
|
def get_redis_version():
|
||||||
|
import semantic_version
|
||||||
|
|
||||||
version_string = subprocess.check_output('redis-server --version', shell=True)
|
version_string = subprocess.check_output('redis-server --version', shell=True)
|
||||||
version_string = version_string.decode('utf-8').strip()
|
version_string = version_string.decode('utf-8').strip()
|
||||||
# extract version number from string
|
# extract version number from string
|
||||||
|
@ -4,7 +4,6 @@ import os
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
# imports - module imports
|
# imports - module imports
|
||||||
from bench.config.nginx import make_nginx_conf
|
|
||||||
from bench.utils import get_sites
|
from bench.utils import get_sites
|
||||||
|
|
||||||
|
|
||||||
@ -35,6 +34,8 @@ def set_ssl_certificate_key(site, ssl_certificate_key, bench_path='.', gen_confi
|
|||||||
set_site_config_nginx_property(site, {"ssl_certificate_key": ssl_certificate_key}, bench_path=bench_path, gen_config=gen_config)
|
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_path='.', gen_config=True):
|
def set_site_config_nginx_property(site, config, bench_path='.', gen_config=True):
|
||||||
|
from bench.config.nginx import make_nginx_conf
|
||||||
|
|
||||||
if site not in get_sites(bench_path=bench_path):
|
if site not in get_sites(bench_path=bench_path):
|
||||||
raise Exception("No such site")
|
raise Exception("No such site")
|
||||||
update_site_config(site, config, bench_path=bench_path)
|
update_site_config(site, config, bench_path=bench_path)
|
||||||
|
@ -11,7 +11,6 @@ from bench.config.common_site_config import get_config, update_config, get_gunic
|
|||||||
|
|
||||||
# imports - third party imports
|
# imports - third party imports
|
||||||
import click
|
import click
|
||||||
from six.moves import configparser
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(bench.PROJECT_NAME)
|
logger = logging.getLogger(bench.PROJECT_NAME)
|
||||||
@ -22,7 +21,7 @@ def generate_supervisor_config(bench_path, user=None, yes=False, skip_redis=Fals
|
|||||||
if not user:
|
if not user:
|
||||||
user = getpass.getuser()
|
user = getpass.getuser()
|
||||||
|
|
||||||
template = bench.config.env.get_template('supervisor.conf')
|
template = bench.config.env().get_template('supervisor.conf')
|
||||||
config = get_config(bench_path=bench_path)
|
config = get_config(bench_path=bench_path)
|
||||||
bench_dir = os.path.abspath(bench_path)
|
bench_dir = os.path.abspath(bench_path)
|
||||||
|
|
||||||
@ -69,6 +68,8 @@ def get_supervisord_conf():
|
|||||||
|
|
||||||
def update_supervisord_config(user=None, yes=False):
|
def update_supervisord_config(user=None, yes=False):
|
||||||
"""From bench v5.x, we're moving to supervisor running as user"""
|
"""From bench v5.x, we're moving to supervisor running as user"""
|
||||||
|
from six.moves import configparser
|
||||||
|
|
||||||
from bench.config.production_setup import service
|
from bench.config.production_setup import service
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
|
@ -85,7 +85,7 @@ def setup_systemd_directory(bench_path):
|
|||||||
|
|
||||||
def setup_main_config(bench_info, bench_path):
|
def setup_main_config(bench_info, bench_path):
|
||||||
# Main config
|
# Main config
|
||||||
bench_template = bench.config.env.get_template('systemd/frappe-bench.target')
|
bench_template = bench.config.env().get_template('systemd/frappe-bench.target')
|
||||||
bench_config = bench_template.render(**bench_info)
|
bench_config = bench_template.render(**bench_info)
|
||||||
bench_config_path = os.path.join(bench_path, 'config', 'systemd' , bench_info.get("bench_name") + '.target')
|
bench_config_path = os.path.join(bench_path, 'config', 'systemd' , bench_info.get("bench_name") + '.target')
|
||||||
|
|
||||||
@ -94,11 +94,11 @@ def setup_main_config(bench_info, bench_path):
|
|||||||
|
|
||||||
def setup_workers_config(bench_info, bench_path):
|
def setup_workers_config(bench_info, bench_path):
|
||||||
# Worker Group
|
# Worker Group
|
||||||
bench_workers_target_template = bench.config.env.get_template('systemd/frappe-bench-workers.target')
|
bench_workers_target_template = bench.config.env().get_template('systemd/frappe-bench-workers.target')
|
||||||
bench_default_worker_template = bench.config.env.get_template('systemd/frappe-bench-frappe-default-worker.service')
|
bench_default_worker_template = bench.config.env().get_template('systemd/frappe-bench-frappe-default-worker.service')
|
||||||
bench_short_worker_template = bench.config.env.get_template('systemd/frappe-bench-frappe-short-worker.service')
|
bench_short_worker_template = bench.config.env().get_template('systemd/frappe-bench-frappe-short-worker.service')
|
||||||
bench_long_worker_template = bench.config.env.get_template('systemd/frappe-bench-frappe-long-worker.service')
|
bench_long_worker_template = bench.config.env().get_template('systemd/frappe-bench-frappe-long-worker.service')
|
||||||
bench_schedule_worker_template = bench.config.env.get_template('systemd/frappe-bench-frappe-schedule.service')
|
bench_schedule_worker_template = bench.config.env().get_template('systemd/frappe-bench-frappe-schedule.service')
|
||||||
|
|
||||||
bench_workers_target_config = bench_workers_target_template.render(**bench_info)
|
bench_workers_target_config = bench_workers_target_template.render(**bench_info)
|
||||||
bench_default_worker_config = bench_default_worker_template.render(**bench_info)
|
bench_default_worker_config = bench_default_worker_template.render(**bench_info)
|
||||||
@ -129,9 +129,9 @@ def setup_workers_config(bench_info, bench_path):
|
|||||||
|
|
||||||
def setup_web_config(bench_info, bench_path):
|
def setup_web_config(bench_info, bench_path):
|
||||||
# Web Group
|
# Web Group
|
||||||
bench_web_target_template = bench.config.env.get_template('systemd/frappe-bench-web.target')
|
bench_web_target_template = bench.config.env().get_template('systemd/frappe-bench-web.target')
|
||||||
bench_web_service_template = bench.config.env.get_template('systemd/frappe-bench-frappe-web.service')
|
bench_web_service_template = bench.config.env().get_template('systemd/frappe-bench-frappe-web.service')
|
||||||
bench_node_socketio_template = bench.config.env.get_template('systemd/frappe-bench-node-socketio.service')
|
bench_node_socketio_template = bench.config.env().get_template('systemd/frappe-bench-node-socketio.service')
|
||||||
|
|
||||||
bench_web_target_config = bench_web_target_template.render(**bench_info)
|
bench_web_target_config = bench_web_target_template.render(**bench_info)
|
||||||
bench_web_service_config = bench_web_service_template.render(**bench_info)
|
bench_web_service_config = bench_web_service_template.render(**bench_info)
|
||||||
@ -152,10 +152,10 @@ def setup_web_config(bench_info, bench_path):
|
|||||||
|
|
||||||
def setup_redis_config(bench_info, bench_path):
|
def setup_redis_config(bench_info, bench_path):
|
||||||
# Redis Group
|
# Redis Group
|
||||||
bench_redis_target_template = bench.config.env.get_template('systemd/frappe-bench-redis.target')
|
bench_redis_target_template = bench.config.env().get_template('systemd/frappe-bench-redis.target')
|
||||||
bench_redis_cache_template = bench.config.env.get_template('systemd/frappe-bench-redis-cache.service')
|
bench_redis_cache_template = bench.config.env().get_template('systemd/frappe-bench-redis-cache.service')
|
||||||
bench_redis_queue_template = bench.config.env.get_template('systemd/frappe-bench-redis-queue.service')
|
bench_redis_queue_template = bench.config.env().get_template('systemd/frappe-bench-redis-queue.service')
|
||||||
bench_redis_socketio_template = bench.config.env.get_template('systemd/frappe-bench-redis-socketio.service')
|
bench_redis_socketio_template = bench.config.env().get_template('systemd/frappe-bench-redis-socketio.service')
|
||||||
|
|
||||||
bench_redis_target_config = bench_redis_target_template.render(**bench_info)
|
bench_redis_target_config = bench_redis_target_template.render(**bench_info)
|
||||||
bench_redis_cache_config = bench_redis_cache_template.render(**bench_info)
|
bench_redis_cache_config = bench_redis_cache_template.render(**bench_info)
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
- name: Set home folder perms
|
- name: Set home folder perms
|
||||||
file:
|
file:
|
||||||
path: '/home/{{ frappe_user }}'
|
path: '{{ user_directory }}'
|
||||||
mode: 'o+rx'
|
mode: 'o+rx'
|
||||||
owner: '{{ frappe_user }}'
|
owner: '{{ frappe_user }}'
|
||||||
group: '{{ frappe_user }}'
|
group: '{{ frappe_user }}'
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
- name: Fix permissions
|
- name: Fix permissions
|
||||||
become_user: root
|
become_user: root
|
||||||
command: chown {{ frappe_user }} -R /home/{{ frappe_user }}
|
command: chown {{ frappe_user }} -R {{ user_directory }}
|
||||||
|
|
||||||
- name: python3 bench init for develop
|
- name: python3 bench init for develop
|
||||||
command: bench init {{ bench_path }} --frappe-path {{ frappe_repo_url }} --frappe-branch {{ frappe_branch }} --python {{ python }}
|
command: bench init {{ bench_path }} --frappe-path {{ frappe_repo_url }} --frappe-branch {{ frappe_branch }} --python {{ python }}
|
||||||
@ -77,6 +77,6 @@
|
|||||||
# Setup Bench for production environment
|
# Setup Bench for production environment
|
||||||
- include_tasks: setup_bench_production.yml
|
- include_tasks: setup_bench_production.yml
|
||||||
vars:
|
vars:
|
||||||
bench_path: "/home/{{ frappe_user }}/{{ bench_name }}"
|
bench_path: "{{ user_directory }}/{{ bench_name }}"
|
||||||
when: not run_travis and production
|
when: not run_travis and production
|
||||||
...
|
...
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
- name: insert/update inputrc for history
|
- name: insert/update inputrc for history
|
||||||
blockinfile:
|
blockinfile:
|
||||||
dest: "/home/{{ frappe_user }}/.inputrc"
|
dest: "{{ user_directory }}/.inputrc"
|
||||||
create: yes
|
create: yes
|
||||||
block: |
|
block: |
|
||||||
## arrow up
|
## arrow up
|
||||||
"\e[A":history-search-backward
|
"\e[A":history-search-backward
|
||||||
## arrow down
|
## arrow down
|
||||||
"\e[B":history-search-forward
|
"\e[B":history-search-forward
|
||||||
...
|
...
|
||||||
|
@ -40,8 +40,8 @@
|
|||||||
- name: setup bench and dev environment
|
- name: setup bench and dev environment
|
||||||
hosts: localhost
|
hosts: localhost
|
||||||
vars:
|
vars:
|
||||||
bench_repo_path: "/home/{{ frappe_user }}/.bench"
|
bench_repo_path: "{{ user_directory }}/.bench"
|
||||||
bench_path: "/home/{{ frappe_user }}/{{ bench_name }}"
|
bench_path: "{{ user_directory }}/{{ bench_name }}"
|
||||||
roles:
|
roles:
|
||||||
# setup frappe-bench
|
# setup frappe-bench
|
||||||
- { role: bench, tags: "bench", when: not run_travis and not without_bench_setup }
|
- { role: bench, tags: "bench", when: not run_travis and not without_bench_setup }
|
||||||
|
@ -4,11 +4,8 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import semantic_version
|
import semantic_version
|
||||||
import git
|
import git
|
||||||
import requests
|
|
||||||
import getpass
|
import getpass
|
||||||
import re
|
import re
|
||||||
from requests.auth import HTTPBasicAuth
|
|
||||||
import requests.exceptions
|
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from .config.common_site_config import get_config
|
from .config.common_site_config import get_config
|
||||||
import click
|
import click
|
||||||
@ -47,6 +44,9 @@ def release(bench_path, app, bump_type, from_branch, to_branch,
|
|||||||
repo_name=repo_name, remote=remote, frontport=frontport)
|
repo_name=repo_name, remote=remote, frontport=frontport)
|
||||||
|
|
||||||
def validate(bench_path, config):
|
def validate(bench_path, config):
|
||||||
|
import requests
|
||||||
|
from requests.auth import HTTPBasicAuth
|
||||||
|
|
||||||
global github_username, github_password
|
global github_username, github_password
|
||||||
|
|
||||||
github_username = config.get('github_username')
|
github_username = config.get('github_username')
|
||||||
@ -306,6 +306,9 @@ def push_release(repo_path, from_branch, to_branch, remote='upstream'):
|
|||||||
|
|
||||||
def create_github_release(repo_path, tag_name, message, remote='upstream', owner='frappe', repo_name=None,
|
def create_github_release(repo_path, tag_name, message, remote='upstream', owner='frappe', repo_name=None,
|
||||||
gh_username=None, gh_password=None, prerelease=False):
|
gh_username=None, gh_password=None, prerelease=False):
|
||||||
|
import requests
|
||||||
|
import requests.exceptions
|
||||||
|
from requests.auth import HTTPBasicAuth
|
||||||
|
|
||||||
print('creating release on github')
|
print('creating release on github')
|
||||||
|
|
||||||
|
@ -9,12 +9,10 @@ import grp
|
|||||||
import itertools
|
import itertools
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import multiprocessing
|
|
||||||
import os
|
import os
|
||||||
import pwd
|
import pwd
|
||||||
import re
|
import re
|
||||||
import select
|
import select
|
||||||
import shutil
|
|
||||||
import site
|
import site
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
@ -23,11 +21,7 @@ from distutils.spawn import find_executable
|
|||||||
|
|
||||||
# imports - third party imports
|
# imports - third party imports
|
||||||
import click
|
import click
|
||||||
from crontab import CronTab
|
|
||||||
import requests
|
|
||||||
from semantic_version import Version
|
|
||||||
from six import iteritems
|
from six import iteritems
|
||||||
from six.moves.urllib.parse import urlparse
|
|
||||||
|
|
||||||
# imports - module imports
|
# imports - module imports
|
||||||
import bench
|
import bench
|
||||||
@ -93,6 +87,9 @@ def safe_decode(string, encoding = 'utf-8'):
|
|||||||
|
|
||||||
|
|
||||||
def check_latest_version():
|
def check_latest_version():
|
||||||
|
import requests
|
||||||
|
from semantic_version import Version
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pypi_request = requests.get("https://pypi.org/pypi/frappe-bench/json")
|
pypi_request = requests.get("https://pypi.org/pypi/frappe-bench/json")
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -263,6 +260,8 @@ def update(pull=False, apps=None, patch=False, build=False, requirements=False,
|
|||||||
|
|
||||||
|
|
||||||
def copy_patches_txt(bench_path):
|
def copy_patches_txt(bench_path):
|
||||||
|
import shutil
|
||||||
|
|
||||||
shutil.copy(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'patches', 'patches.txt'),
|
shutil.copy(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'patches', 'patches.txt'),
|
||||||
os.path.join(bench_path, 'patches.txt'))
|
os.path.join(bench_path, 'patches.txt'))
|
||||||
|
|
||||||
@ -386,6 +385,7 @@ def get_sites(bench_path='.'):
|
|||||||
|
|
||||||
|
|
||||||
def setup_backups(bench_path='.'):
|
def setup_backups(bench_path='.'):
|
||||||
|
from crontab import CronTab
|
||||||
from bench.config.common_site_config import get_config
|
from bench.config.common_site_config import get_config
|
||||||
logger.log('setting up backups')
|
logger.log('setting up backups')
|
||||||
|
|
||||||
@ -422,7 +422,7 @@ def setup_sudoers(user):
|
|||||||
if set_permissions:
|
if set_permissions:
|
||||||
os.chmod('/etc/sudoers', 0o440)
|
os.chmod('/etc/sudoers', 0o440)
|
||||||
|
|
||||||
template = bench.config.env.get_template('frappe_sudoers')
|
template = bench.config.env().get_template('frappe_sudoers')
|
||||||
frappe_sudoers = template.render(**{
|
frappe_sudoers = template.render(**{
|
||||||
'user': user,
|
'user': user,
|
||||||
'service': find_executable('service'),
|
'service': find_executable('service'),
|
||||||
@ -815,6 +815,8 @@ sudo supervisorctl reload
|
|||||||
|
|
||||||
|
|
||||||
def update_translations_p(args):
|
def update_translations_p(args):
|
||||||
|
import requests
|
||||||
|
|
||||||
try:
|
try:
|
||||||
update_translations(*args)
|
update_translations(*args)
|
||||||
except requests.exceptions.HTTPError:
|
except requests.exceptions.HTTPError:
|
||||||
@ -822,6 +824,8 @@ def update_translations_p(args):
|
|||||||
|
|
||||||
|
|
||||||
def download_translations_p():
|
def download_translations_p():
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
pool = multiprocessing.Pool(multiprocessing.cpu_count())
|
pool = multiprocessing.Pool(multiprocessing.cpu_count())
|
||||||
|
|
||||||
langs = get_langs()
|
langs = get_langs()
|
||||||
@ -846,6 +850,8 @@ def get_langs():
|
|||||||
|
|
||||||
|
|
||||||
def update_translations(app, lang):
|
def update_translations(app, lang):
|
||||||
|
import requests
|
||||||
|
|
||||||
translations_dir = os.path.join('apps', app, app, 'translations')
|
translations_dir = os.path.join('apps', app, app, 'translations')
|
||||||
csv_file = os.path.join(translations_dir, lang + '.csv')
|
csv_file = os.path.join(translations_dir, lang + '.csv')
|
||||||
url = "https://translate.erpnext.com/files/{}-{}.csv".format(app, lang)
|
url = "https://translate.erpnext.com/files/{}-{}.csv".format(app, lang)
|
||||||
@ -895,6 +901,8 @@ def get_bench_name(bench_path):
|
|||||||
|
|
||||||
|
|
||||||
def setup_fonts():
|
def setup_fonts():
|
||||||
|
import shutil
|
||||||
|
|
||||||
fonts_path = os.path.join('/tmp', 'fonts')
|
fonts_path = os.path.join('/tmp', 'fonts')
|
||||||
|
|
||||||
if os.path.exists('/etc/fonts_backup'):
|
if os.path.exists('/etc/fonts_backup'):
|
||||||
@ -967,6 +975,8 @@ def find_benches(directory=None):
|
|||||||
|
|
||||||
|
|
||||||
def migrate_env(python, backup=False):
|
def migrate_env(python, backup=False):
|
||||||
|
import shutil
|
||||||
|
from six.moves.urllib.parse import urlparse
|
||||||
from bench.config.common_site_config import get_config
|
from bench.config.common_site_config import get_config
|
||||||
from bench.app import get_apps
|
from bench.app import get_apps
|
||||||
|
|
||||||
|
@ -34,6 +34,8 @@ If you are on a fresh server and logged in as root, at first create a dedicated
|
|||||||
|
|
||||||
*(it is very common to use "frappe" as frappe-username, but this comes with the security flaw of ["frappe" ranking very high](https://www.reddit.com/r/dataisbeautiful/comments/b3sirt/i_deployed_over_a_dozen_cyber_honeypots_all_over/?st=JTJ0SC0Q&sh=76e05240) in as a username challenged in hacking attempts. So, for production sites it is highly recommended to use a custom username harder to guess)*
|
*(it is very common to use "frappe" as frappe-username, but this comes with the security flaw of ["frappe" ranking very high](https://www.reddit.com/r/dataisbeautiful/comments/b3sirt/i_deployed_over_a_dozen_cyber_honeypots_all_over/?st=JTJ0SC0Q&sh=76e05240) in as a username challenged in hacking attempts. So, for production sites it is highly recommended to use a custom username harder to guess)*
|
||||||
|
|
||||||
|
*(you can specify the flag --home to specify a directory for your [frappe-user]. Bench will follow the home directory specified by the user's home directory e.g. /data/[frappe-user]/frappe-bench)*
|
||||||
|
|
||||||
Switch to `[frappe-user]` (using `su [frappe-user]`) and start the setup
|
Switch to `[frappe-user]` (using `su [frappe-user]`) and start the setup
|
||||||
|
|
||||||
wget https://raw.githubusercontent.com/frappe/bench/develop/install.py
|
wget https://raw.githubusercontent.com/frappe/bench/develop/install.py
|
||||||
@ -71,7 +73,7 @@ use --python flag to specify virtual environments python version, by default scr
|
|||||||
|
|
||||||
## How do I start ERPNext
|
## How do I start ERPNext
|
||||||
|
|
||||||
1. For development: Go to your bench folder (`frappe-bench` by default) and start the bench with `bench start`
|
1. For development: Go to your bench folder (`~[frappe-user]/frappe-bench` by default) and start the bench with `bench start`
|
||||||
2. For production: Your process will be setup and managed by `nginx` and `supervisor`. Checkout [Setup Production](https://frappe.io/docs/user/en/bench/guides/setup-production.html) for more information.
|
2. For production: Your process will be setup and managed by `nginx` and `supervisor`. Checkout [Setup Production](https://frappe.io/docs/user/en/bench/guides/setup-production.html) for more information.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -234,10 +234,11 @@ def install_bench(args):
|
|||||||
# create user if not exists
|
# create user if not exists
|
||||||
extra_vars = vars(args)
|
extra_vars = vars(args)
|
||||||
extra_vars.update(frappe_user=args.user)
|
extra_vars.update(frappe_user=args.user)
|
||||||
|
|
||||||
|
extra_vars.update(user_directory=get_user_home_directory(args.user))
|
||||||
|
|
||||||
if os.path.exists(tmp_bench_repo):
|
if os.path.exists(tmp_bench_repo):
|
||||||
repo_path = tmp_bench_repo
|
repo_path = tmp_bench_repo
|
||||||
|
|
||||||
else:
|
else:
|
||||||
repo_path = os.path.join(os.path.expanduser('~'), 'bench')
|
repo_path = os.path.join(os.path.expanduser('~'), 'bench')
|
||||||
|
|
||||||
@ -386,6 +387,11 @@ def get_extra_vars_json(extra_args):
|
|||||||
|
|
||||||
return ('@' + json_path)
|
return ('@' + json_path)
|
||||||
|
|
||||||
|
def get_user_home_directory(user):
|
||||||
|
# Return home directory /home/USERNAME or anything else defined as home directory in
|
||||||
|
# passwd for user.
|
||||||
|
return os.path.expanduser('~'+user)
|
||||||
|
|
||||||
|
|
||||||
def run_playbook(playbook_name, sudo=False, extra_vars=None):
|
def run_playbook(playbook_name, sudo=False, extra_vars=None):
|
||||||
args = ['ansible-playbook', '-c', 'local', playbook_name , '-vvvv']
|
args = ['ansible-playbook', '-c', 'local', playbook_name , '-vvvv']
|
||||||
|
Loading…
Reference in New Issue
Block a user