2019-12-18 14:33:21 +05:30
#!/usr/bin/env python3
2021-05-11 19:57:24 +05:30
from __future__ import print_function
2020-02-20 19:46:40 +05:30
import os
import sys
import subprocess
import getpass
import json
import multiprocessing
import shutil
import platform
import warnings
import datetime
2016-03-15 12:24:17 +05:30
2019-12-27 13:14:33 +05:30
tmp_bench_repo = os . path . join ( ' / ' , ' tmp ' , ' .bench ' )
tmp_log_folder = os . path . join ( ' / ' , ' tmp ' , ' logs ' )
2020-01-09 12:06:59 +05:30
execution_timestamp = datetime . datetime . utcnow ( )
execution_day = " { : % Y- % m- %d } " . format ( execution_timestamp )
execution_time = " { : % H: % M} " . format ( execution_timestamp )
log_file_name = " easy-install__ {0} __ {1} .log " . format ( execution_day , execution_time . replace ( ' : ' , ' - ' ) )
2020-01-07 15:34:34 +05:30
log_path = os . path . join ( tmp_log_folder , log_file_name )
2019-12-18 14:33:21 +05:30
log_stream = sys . stdout
2020-08-14 20:29:46 +05:30
distro_required = not ( ( sys . version_info . major < 3 ) or ( sys . version_info . major == 3 and sys . version_info . minor < 5 ) )
2019-12-18 14:33:21 +05:30
2019-12-19 14:38:46 +05:30
def log ( message , level = 0 ) :
2019-12-18 14:33:21 +05:30
levels = {
0 : ' \033 [94m ' , # normal
1 : ' \033 [92m ' , # success
2 : ' \033 [91m ' , # fail
3 : ' \033 [93m ' # warn/suggest
}
start = levels . get ( level ) or ' '
end = ' \033 [0m '
2019-12-19 14:38:46 +05:30
print ( start + message + end )
2019-12-18 14:33:21 +05:30
2019-12-27 13:14:33 +05:30
def setup_log_stream ( args ) :
global log_stream
sys . stderr = sys . stdout
if not args . verbose :
if not os . path . exists ( tmp_log_folder ) :
os . makedirs ( tmp_log_folder )
log_stream = open ( log_path , ' w ' )
log ( " Logs are saved under {0} " . format ( log_path ) , level = 3 )
2020-01-09 12:06:59 +05:30
print ( " Install script run at {0} on {1} \n \n " . format ( execution_time , execution_day ) , file = log_stream )
2019-12-27 13:14:33 +05:30
2019-12-19 14:01:24 +05:30
def check_environment ( ) :
needed_environ_vars = [ ' LANG ' , ' LC_ALL ' ]
message = ' '
for var in needed_environ_vars :
if var not in os . environ :
2019-12-27 13:14:33 +05:30
message + = " \n export {0} =C.UTF-8 " . format ( var )
2019-12-19 14:01:24 +05:30
if message :
2019-12-19 14:38:46 +05:30
log ( " Bench ' s CLI needs these to be defined! " , level = 3 )
2019-12-27 13:14:33 +05:30
log ( " Run the following commands in shell: {0} " . format ( message ) , level = 2 )
2019-12-19 14:01:24 +05:30
sys . exit ( )
2019-12-27 13:14:33 +05:30
def check_system_package_managers ( ) :
if ' Darwin ' in os . uname ( ) :
if not shutil . which ( ' brew ' ) :
raise Exception ( '''
Please install brew package manager before proceeding with bench setup . Please run following
to install brew package manager on your machine ,
/ usr / bin / ruby - e " $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install) "
''' )
if ' Linux ' in os . uname ( ) :
if not any ( [ shutil . which ( x ) for x in [ ' apt-get ' , ' yum ' ] ] ) :
raise Exception ( ' Cannot find any compatible package manager! ' )
2020-08-14 16:11:40 +08:00
def check_distribution_compatibility ( ) :
dist_name , dist_version = get_distribution_info ( )
2019-12-27 13:14:33 +05:30
supported_dists = {
' macos ' : [ 10.9 , 10.10 , 10.11 , 10.12 ] ,
2020-08-14 13:20:36 +08:00
' ubuntu ' : [ 14 , 15 , 16 , 18 , 19 , 20 ] ,
2020-08-05 16:31:27 +05:30
' debian ' : [ 8 , 9 , 10 ] ,
2019-12-27 13:14:33 +05:30
' centos ' : [ 7 ]
}
log ( " Checking System Compatibility... " )
if dist_name in supported_dists :
if float ( dist_version ) in supported_dists [ dist_name ] :
log ( " {0} {1} is compatible! " . format ( dist_name , dist_version ) , level = 1 )
else :
2020-01-07 15:34:34 +05:30
log ( " {0} {1} is detected " . format ( dist_name , dist_version ) , level = 1 )
2019-12-27 13:14:33 +05:30
log ( " Install on {0} {1} instead " . format ( dist_name , supported_dists [ dist_name ] [ - 1 ] ) , level = 3 )
else :
log ( " Sorry, the installer doesn ' t support {0} . Aborting installation! " . format ( dist_name ) , level = 2 )
2020-08-14 20:29:46 +05:30
2020-08-14 13:20:36 +08:00
def import_with_install ( package ) :
# copied from https://discuss.erpnext.com/u/nikunj_patel
# https://discuss.erpnext.com/t/easy-install-setup-guide-for-erpnext-installation-on-ubuntu-20-04-lts-with-some-modification-of-course/62375/5
# need to move to top said v13 for fully python3 era
import importlib
try :
importlib . import_module ( package )
except ImportError :
# caveat : pip3 must be installed
import pip
pip . main ( [ ' install ' , package ] )
finally :
globals ( ) [ package ] = importlib . import_module ( package )
2020-08-14 16:11:40 +08:00
def get_distribution_info ( ) :
2019-12-27 13:14:33 +05:30
# return distribution name and major version
if platform . system ( ) == " Linux " :
2020-08-14 20:29:46 +05:30
if distro_required :
2020-08-14 13:20:36 +08:00
current_dist = distro . linux_distribution ( full_distribution_name = True )
else :
current_dist = platform . dist ( )
2020-08-14 20:29:46 +05:30
2019-12-27 13:14:33 +05:30
return current_dist [ 0 ] . lower ( ) , current_dist [ 1 ] . rsplit ( ' . ' ) [ 0 ]
elif platform . system ( ) == " Darwin " :
current_dist = platform . mac_ver ( )
return " macos " , current_dist [ 0 ] . rsplit ( ' . ' , 1 ) [ 0 ]
2019-12-18 14:33:21 +05:30
def run_os_command ( command_map ) :
''' command_map is a dictionary of { ' executable ' : command}. For ex. { ' apt-get ' : ' sudo apt-get install -y python2.7 ' } '''
success = True
for executable , commands in command_map . items ( ) :
2019-12-20 14:45:56 +05:30
if shutil . which ( executable ) :
2019-12-18 14:33:21 +05:30
if isinstance ( commands , str ) :
commands = [ commands ]
for command in commands :
returncode = subprocess . check_call ( command , shell = True , stdout = log_stream , stderr = sys . stderr )
success = success and ( returncode == 0 )
return success
2019-12-27 13:14:33 +05:30
def install_prerequisites ( ) :
# pre-requisites for bench repo cloning
run_os_command ( {
' apt-get ' : [
' sudo apt-get update ' ,
' sudo apt-get install -y git build-essential python3-setuptools python3-dev libffi-dev '
] ,
' yum ' : [
' sudo yum groupinstall -y " Development tools " ' ,
' sudo yum install -y epel-release redhat-lsb-core git python-setuptools python-devel openssl-devel libffi-devel '
]
} )
2020-11-24 15:46:51 +05:30
2020-10-04 00:13:23 +07:00
# until psycopg2-binary is available for aarch64 (Arm 64-bit), we'll need libpq and libssl dev packages to build psycopg2 from source
if platform . machine ( ) == ' aarch64 ' :
log ( " Installing libpq and libssl dev packages to build psycopg2 for aarch64... " )
run_os_command ( {
' apt-get ' : [ ' sudo apt-get install -y libpq-dev libssl-dev ' ] ,
' yum ' : [ ' sudo yum install -y libpq-devel openssl-devel ' ]
} )
2019-12-27 13:14:33 +05:30
install_package ( ' curl ' )
install_package ( ' wget ' )
install_package ( ' git ' )
2020-01-02 14:21:29 +05:30
install_package ( ' pip3 ' , ' python3-pip ' )
2019-12-27 13:14:33 +05:30
2021-02-16 20:17:49 +05:30
run_os_command ( {
' python3 ' : " sudo -H python3 -m pip install --upgrade pip setuptools-rust "
} )
2016-03-17 15:20:21 +05:30
success = run_os_command ( {
2021-02-16 20:17:49 +05:30
' python3 ' : " sudo -H python3 -m pip install --upgrade setuptools wheel cryptography ansible~=2.8.15 "
2016-03-17 15:20:21 +05:30
} )
2016-03-15 12:24:17 +05:30
2020-01-02 14:21:29 +05:30
if not ( success or shutil . which ( ' ansible ' ) ) :
2016-03-22 13:14:31 +05:30
could_not_install ( ' Ansible ' )
2019-12-27 13:14:33 +05:30
def could_not_install ( package ) :
raise Exception ( ' Could not install {0} . Please install it manually. ' . format ( package ) )
def is_sudo_user ( ) :
return os . geteuid ( ) == 0
2020-01-02 14:21:29 +05:30
def install_package ( package , package_name = None ) :
2019-12-27 13:14:33 +05:30
if shutil . which ( package ) :
log ( " {0} already installed! " . format ( package ) , level = 1 )
else :
log ( " Installing {0} ... " . format ( package ) )
2020-01-02 14:21:29 +05:30
package_name = package_name or package
2019-12-27 13:14:33 +05:30
success = run_os_command ( {
2020-01-02 14:21:29 +05:30
' apt-get ' : [ ' sudo apt-get install -y {0} ' . format ( package_name ) ] ,
' yum ' : [ ' sudo yum install -y {0} ' . format ( package_name ) ] ,
' brew ' : [ ' brew install {0} ' . format ( package_name ) ]
2019-12-27 13:14:33 +05:30
} )
if success :
log ( " {0} installed! " . format ( package ) , level = 1 )
return success
could_not_install ( package )
def install_bench ( args ) :
2016-03-15 12:24:17 +05:30
# clone bench repo
2016-06-28 12:11:06 +05:30
if not args . run_travis :
clone_bench_repo ( args )
2016-05-25 16:17:48 +05:30
2016-06-28 15:06:12 +05:30
if not args . user :
if args . production :
args . user = ' frappe '
2016-06-30 16:40:07 +05:30
2017-04-17 17:28:18 +05:30
elif ' SUDO_USER ' in os . environ :
2016-06-30 16:40:07 +05:30
args . user = os . environ [ ' SUDO_USER ' ]
2016-06-28 15:06:12 +05:30
else :
args . user = getpass . getuser ( )
2016-03-15 12:24:17 +05:30
2016-06-28 15:06:12 +05:30
if args . user == ' root ' :
2016-06-30 16:40:07 +05:30
raise Exception ( ' Please run this script as a non-root user with sudo privileges, but without using sudo or pass --user=USER ' )
2016-05-27 12:25:12 +05:30
2018-03-26 16:55:31 +05:30
# Python executable
2020-08-14 16:11:40 +08:00
dist_name , dist_version = get_distribution_info ( )
2019-06-21 08:40:13 +05:30
if dist_name == ' centos ' :
args . python = ' python3.6 '
else :
args . python = ' python3 '
2018-03-26 16:55:31 +05:30
2016-05-27 12:25:12 +05:30
# create user if not exists
2016-05-30 16:42:55 +05:30
extra_vars = vars ( args )
2016-06-28 15:06:12 +05:30
extra_vars . update ( frappe_user = args . user )
2021-05-11 11:55:46 +05:30
2021-02-16 16:45:07 +01:00
extra_vars . update ( user_directory = get_user_home_directory ( args . user ) )
2016-05-30 16:42:55 +05:30
2016-08-01 12:09:54 +05:30
if os . path . exists ( tmp_bench_repo ) :
repo_path = tmp_bench_repo
else :
repo_path = os . path . join ( os . path . expanduser ( ' ~ ' ) , ' bench ' )
extra_vars . update ( repo_path = repo_path )
2018-02-05 15:07:14 +05:30
run_playbook ( ' create_user.yml ' , extra_vars = extra_vars )
2016-05-27 12:25:12 +05:30
2017-08-03 16:33:57 +05:30
extra_vars . update ( get_passwords ( args ) )
2016-06-28 15:06:12 +05:30
if args . production :
extra_vars . update ( max_worker_connections = multiprocessing . cpu_count ( ) * 1024 )
2021-12-01 21:31:22 +05:30
if args . version < = 10 :
frappe_branch = " {0} .x.x " . format ( args . version )
erpnext_branch = " {0} .x.x " . format ( args . version )
else :
frappe_branch = " version- {0} " . format ( args . version )
erpnext_branch = " version- {0} " . format ( args . version )
2019-07-23 12:04:47 +05:30
2020-10-03 16:12:39 +07:00
# Allow override of frappe_branch and erpnext_branch, regardless of args.version (which always has a default set)
if args . frappe_branch :
frappe_branch = args . frappe_branch
if args . erpnext_branch :
erpnext_branch = args . erpnext_branch
2019-07-23 12:04:47 +05:30
extra_vars . update ( frappe_branch = frappe_branch )
extra_vars . update ( erpnext_branch = erpnext_branch )
2019-05-07 09:47:35 +05:30
2017-08-28 19:10:38 +05:30
bench_name = ' frappe-bench ' if not args . bench_name else args . bench_name
extra_vars . update ( bench_name = bench_name )
2016-06-28 15:06:12 +05:30
2018-02-05 15:07:14 +05:30
# Will install ERPNext production setup by default
2020-10-30 17:35:19 +07:00
if args . without_erpnext :
log ( " Initializing bench {bench_name} : \n \t Frappe Branch: {frappe_branch} \n \t ERPNext will not be installed due to --without-erpnext " . format ( bench_name = bench_name , frappe_branch = frappe_branch ) )
else :
log ( " Initializing bench {bench_name} : \n \t Frappe Branch: {frappe_branch} \n \t ERPNext Branch: {erpnext_branch} " . format ( bench_name = bench_name , frappe_branch = frappe_branch , erpnext_branch = erpnext_branch ) )
2018-02-05 15:07:14 +05:30
run_playbook ( ' site.yml ' , sudo = True , extra_vars = extra_vars )
2016-05-25 16:17:48 +05:30
2016-06-28 12:11:06 +05:30
if os . path . exists ( tmp_bench_repo ) :
shutil . rmtree ( tmp_bench_repo )
2016-03-15 12:24:17 +05:30
2016-08-02 11:58:28 +05:30
2016-05-25 16:17:48 +05:30
def clone_bench_repo ( args ) :
2016-03-22 13:14:31 +05:30
''' Clones the bench repository in the user folder '''
2020-09-03 13:07:13 +05:30
branch = args . bench_branch or ' develop '
2019-12-18 14:33:21 +05:30
repo_url = args . repo_url or ' https://github.com/frappe/bench '
2016-05-25 16:17:48 +05:30
if os . path . exists ( tmp_bench_repo ) :
2020-10-30 17:35:19 +07:00
log ( ' Not cloning already existing Bench repository at {tmp_bench_repo} ' . format ( tmp_bench_repo = tmp_bench_repo ) )
2016-03-15 12:24:17 +05:30
return 0
2016-08-01 12:09:54 +05:30
elif args . without_bench_setup :
clone_path = os . path . join ( os . path . expanduser ( ' ~ ' ) , ' bench ' )
2020-10-30 17:35:19 +07:00
log ( ' --without-bench-setup specified, clone path is: {clone_path} ' . format ( clone_path = clone_path ) )
2016-08-01 12:09:54 +05:30
else :
clone_path = tmp_bench_repo
2020-10-30 17:35:19 +07:00
# Not logging repo_url to avoid accidental credential leak in case credential is embedded in URL
log ( ' Cloning bench repository branch {branch} into {clone_path} ' . format ( branch = branch , clone_path = clone_path ) )
2016-08-01 12:09:54 +05:30
2016-03-15 12:24:17 +05:30
success = run_os_command (
2019-12-18 14:33:21 +05:30
{ ' git ' : ' git clone --quiet {repo_url} {bench_repo} --depth 1 --branch {branch} ' . format (
2016-08-01 12:09:54 +05:30
repo_url = repo_url , bench_repo = clone_path , branch = branch ) }
2016-03-15 12:24:17 +05:30
)
return success
2016-03-22 13:14:31 +05:30
2020-01-07 15:34:34 +05:30
def passwords_didnt_match ( context = ' ' ) :
log ( " {} passwords did not match! " . format ( context ) , level = 3 )
2017-08-03 16:33:57 +05:30
def get_passwords ( args ) :
"""
Returns a dict of passwords for further use
and creates passwords . txt in the bench user ' s home directory
"""
2020-01-07 15:34:34 +05:30
log ( " Input MySQL and Frappe Administrator passwords: " )
2017-08-03 16:33:57 +05:30
ignore_prompt = args . run_travis or args . without_bench_setup
mysql_root_password , admin_password = ' ' , ' '
passwords_file_path = os . path . join ( os . path . expanduser ( ' ~ ' + args . user ) , ' passwords.txt ' )
2016-08-01 11:14:01 +05:30
if not ignore_prompt :
2017-08-03 16:33:57 +05:30
# set passwords from existing passwords.txt
if os . path . isfile ( passwords_file_path ) :
with open ( passwords_file_path , ' r ' ) as f :
passwords = json . load ( f )
mysql_root_password , admin_password = passwords [ ' mysql_root_password ' ] , passwords [ ' admin_password ' ]
# set passwords from cli args
if args . mysql_root_password :
mysql_root_password = args . mysql_root_password
if args . admin_password :
admin_password = args . admin_password
# prompt for passwords
2016-05-04 13:23:33 +05:30
pass_set = True
while pass_set :
# mysql root password
if not mysql_root_password :
mysql_root_password = getpass . unix_getpass ( prompt = ' Please enter mysql root password: ' )
conf_mysql_passwd = getpass . unix_getpass ( prompt = ' Re-enter mysql root password: ' )
2018-04-09 15:41:01 +05:30
if mysql_root_password != conf_mysql_passwd or mysql_root_password == ' ' :
2020-01-07 15:34:34 +05:30
passwords_didnt_match ( " MySQL " )
2016-05-04 13:23:33 +05:30
mysql_root_password = ' '
continue
2020-10-04 07:07:41 +00:00
# admin password, only needed if we're also creating a site
if not admin_password and not args . without_site :
2016-10-13 13:08:12 +05:30
admin_password = getpass . unix_getpass ( prompt = ' Please enter the default Administrator user password: ' )
2016-05-04 13:23:33 +05:30
conf_admin_passswd = getpass . unix_getpass ( prompt = ' Re-enter Administrator password: ' )
2018-04-09 15:41:01 +05:30
if admin_password != conf_admin_passswd or admin_password == ' ' :
2020-01-07 15:34:34 +05:30
passwords_didnt_match ( " Administrator " )
2016-05-04 13:23:33 +05:30
admin_password = ' '
continue
2020-10-30 17:35:19 +07:00
elif args . without_site :
log ( " Not creating a new site due to --without-site " )
2016-05-04 13:23:33 +05:30
pass_set = False
else :
mysql_root_password = admin_password = ' travis '
2016-09-22 14:53:36 +05:30
passwords = {
2016-05-04 13:23:33 +05:30
' mysql_root_password ' : mysql_root_password ,
' admin_password ' : admin_password
}
2016-09-22 14:53:36 +05:30
if not ignore_prompt :
with open ( passwords_file_path , ' w ' ) as f :
json . dump ( passwords , f , indent = 1 )
2019-12-19 14:38:46 +05:30
log ( ' Passwords saved at ~/passwords.txt ' )
2016-10-13 13:08:12 +05:30
2016-09-22 14:53:36 +05:30
return passwords
2017-08-03 16:33:57 +05:30
2016-06-28 15:06:12 +05:30
def get_extra_vars_json ( extra_args ) :
2016-05-30 16:42:55 +05:30
# We need to pass production as extra_vars to the playbook to execute conditionals in the
# playbook. Extra variables can passed as json or key=value pair. Here, we will use JSON.
2019-12-27 13:14:33 +05:30
json_path = os . path . join ( ' / ' , ' tmp ' , ' extra_vars.json ' )
2017-04-17 17:28:18 +05:30
extra_vars = dict ( list ( extra_args . items ( ) ) )
2019-12-27 13:14:33 +05:30
2016-05-30 16:42:55 +05:30
with open ( json_path , mode = ' w ' ) as j :
json . dump ( extra_vars , j , indent = 1 , sort_keys = True )
return ( ' @ ' + json_path )
2016-05-27 12:25:12 +05:30
2021-02-16 16:45:07 +01:00
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 )
2019-12-27 13:14:33 +05:30
2016-05-27 12:25:12 +05:30
def run_playbook ( playbook_name , sudo = False , extra_vars = None ) :
2019-07-23 19:50:07 +05:30
args = [ ' ansible-playbook ' , ' -c ' , ' local ' , playbook_name , ' -vvvv ' ]
2016-05-27 12:25:12 +05:30
if extra_vars :
2016-05-30 16:42:55 +05:30
args . extend ( [ ' -e ' , get_extra_vars_json ( extra_vars ) ] )
2016-05-27 12:25:12 +05:30
2016-03-15 12:24:17 +05:30
if sudo :
2016-05-30 16:42:55 +05:30
user = extra_vars . get ( ' user ' ) or getpass . getuser ( )
2016-05-25 16:17:48 +05:30
args . extend ( [ ' --become ' , ' --become-user= {0} ' . format ( user ) ] )
2016-05-04 13:23:33 +05:30
2016-08-01 12:09:54 +05:30
if os . path . exists ( tmp_bench_repo ) :
cwd = tmp_bench_repo
else :
cwd = os . path . join ( os . path . expanduser ( ' ~ ' ) , ' bench ' )
2020-05-07 15:00:34 +05:30
playbooks_locations = [ os . path . join ( cwd , ' bench ' , ' playbooks ' ) , os . path . join ( cwd , ' playbooks ' ) ]
playbooks_folder = [ x for x in playbooks_locations if os . path . exists ( x ) ] [ 0 ]
success = subprocess . check_call ( args , cwd = playbooks_folder , stdout = log_stream , stderr = sys . stderr )
2016-03-15 12:24:17 +05:30
return success
2019-12-18 14:33:21 +05:30
2020-08-14 20:29:46 +05:30
def setup_script_requirements ( ) :
if distro_required :
install_package ( ' pip3 ' , ' python3-pip ' )
import_with_install ( ' distro ' )
2016-03-15 12:24:17 +05:30
def parse_commandline_args ( ) :
import argparse
parser = argparse . ArgumentParser ( description = ' Frappe Installer ' )
2016-05-25 16:17:48 +05:30
# Arguments develop and production are mutually exclusive both can't be specified together.
2016-05-04 13:23:33 +05:30
# Hence, we need to create a group for discouraging use of both options at the same time.
args_group = parser . add_mutually_exclusive_group ( )
2019-12-18 14:33:21 +05:30
args_group . add_argument ( ' --develop ' , dest = ' develop ' , action = ' store_true ' , default = False , help = ' Install developer setup ' )
args_group . add_argument ( ' --production ' , dest = ' production ' , action = ' store_true ' , default = False , help = ' Setup Production environment for bench ' )
2020-10-30 17:35:19 +07:00
parser . add_argument ( ' --site ' , dest = ' site ' , action = ' store ' , default = ' site1.local ' , help = ' Specify name for your first ERPNext site ' )
parser . add_argument ( ' --without-site ' , dest = ' without_site ' , action = ' store_true ' , default = False , help = ' Do not create a new site ' )
2019-12-18 14:33:21 +05:30
parser . add_argument ( ' --verbose ' , dest = ' verbose ' , action = ' store_true ' , default = False , help = ' Run the script in verbose mode ' )
2016-05-25 16:17:48 +05:30
parser . add_argument ( ' --user ' , dest = ' user ' , help = ' Install frappe-bench for this user ' )
parser . add_argument ( ' --bench-branch ' , dest = ' bench_branch ' , help = ' Clone a particular branch of bench repository ' )
2016-05-30 16:42:55 +05:30
parser . add_argument ( ' --repo-url ' , dest = ' repo_url ' , help = ' Clone bench from the given url ' )
2019-12-18 14:33:21 +05:30
parser . add_argument ( ' --frappe-repo-url ' , dest = ' frappe_repo_url ' , action = ' store ' , default = ' https://github.com/frappe/frappe ' , help = ' Clone frappe from the given url ' )
parser . add_argument ( ' --frappe-branch ' , dest = ' frappe_branch ' , action = ' store ' , help = ' Clone a particular branch of frappe ' )
parser . add_argument ( ' --erpnext-repo-url ' , dest = ' erpnext_repo_url ' , action = ' store ' , default = ' https://github.com/frappe/erpnext ' , help = ' Clone erpnext from the given url ' )
parser . add_argument ( ' --erpnext-branch ' , dest = ' erpnext_branch ' , action = ' store ' , help = ' Clone a particular branch of erpnext ' )
parser . add_argument ( ' --without-erpnext ' , dest = ' without_erpnext ' , action = ' store_true ' , default = False , help = ' Prevent fetching ERPNext ' )
2019-07-22 16:01:36 +05:30
# direct provision to install versions
2021-12-01 21:31:22 +05:30
parser . add_argument ( ' --version ' , dest = ' version ' , action = ' store ' , default = 13 , type = int , help = ' Clone particular version of frappe and erpnext ' )
2016-05-04 13:23:33 +05:30
# To enable testing of script using Travis, this should skip the prompt
2019-12-18 14:33:21 +05:30
parser . add_argument ( ' --run-travis ' , dest = ' run_travis ' , action = ' store_true ' , default = False , help = argparse . SUPPRESS )
parser . add_argument ( ' --without-bench-setup ' , dest = ' without_bench_setup ' , action = ' store_true ' , default = False , help = argparse . SUPPRESS )
2017-05-15 17:43:37 +02:00
# whether to overwrite an existing bench
2019-12-18 14:33:21 +05:30
parser . add_argument ( ' --overwrite ' , dest = ' overwrite ' , action = ' store_true ' , default = False , help = ' Whether to overwrite an existing bench ' )
2017-08-03 16:33:57 +05:30
# set passwords
parser . add_argument ( ' --mysql-root-password ' , dest = ' mysql_root_password ' , help = ' Set mysql root password ' )
2020-08-05 16:31:27 +05:30
parser . add_argument ( ' --mariadb-version ' , dest = ' mariadb_version ' , default = ' 10.4 ' , help = ' Specify mariadb version ' )
2017-08-03 16:33:57 +05:30
parser . add_argument ( ' --admin-password ' , dest = ' admin_password ' , help = ' Set admin password ' )
2017-08-28 19:10:38 +05:30
parser . add_argument ( ' --bench-name ' , dest = ' bench_name ' , help = ' Create bench with specified name. Default name is frappe-bench ' )
2018-03-26 16:55:31 +05:30
# Python interpreter to be used
2019-12-18 14:33:21 +05:30
parser . add_argument ( ' --python ' , dest = ' python ' , default = ' python3 ' , help = argparse . SUPPRESS )
2018-12-11 23:26:15 +05:30
# LXC Support
2019-12-18 14:33:21 +05:30
parser . add_argument ( ' --container ' , dest = ' container ' , default = False , action = ' store_true ' , help = ' Use if you \' re creating inside LXC ' )
2020-08-14 13:20:36 +08:00
2016-03-15 12:24:17 +05:30
args = parser . parse_args ( )
return args
2020-08-14 20:29:46 +05:30
2016-03-22 13:14:31 +05:30
if __name__ == ' __main__ ' :
2020-02-20 20:02:35 +05:30
if sys . version [ 0 ] == ' 2 ' :
if not os . environ . get ( ' CI ' ) :
if not raw_input ( " It is recommended to run this script with Python 3 \n Do you still wish to continue? [Y/n]: " ) . lower ( ) == " y " :
sys . exit ( )
2020-01-02 14:21:29 +05:30
2020-02-27 21:19:20 +05:30
try :
from distutils . spawn import find_executable
except ImportError :
try :
subprocess . check_call ( ' pip install --upgrade setuptools ' )
except subprocess . CalledProcessError :
print ( " Install distutils or use Python3 to run the script " )
sys . exit ( 1 )
shutil . which = find_executable
2019-12-19 14:01:24 +05:30
if not is_sudo_user ( ) :
2019-12-19 14:38:46 +05:30
log ( " Please run this script as a non-root user with sudo privileges " , level = 3 )
2019-12-19 14:01:24 +05:30
sys . exit ( )
2016-03-15 12:24:17 +05:30
args = parse_commandline_args ( )
2019-12-27 13:14:33 +05:30
2019-12-18 14:33:21 +05:30
with warnings . catch_warnings ( ) :
warnings . simplefilter ( " ignore " )
2019-12-27 13:14:33 +05:30
setup_log_stream ( args )
2020-09-03 12:46:28 +05:30
install_prerequisites ( )
2020-08-14 20:29:46 +05:30
setup_script_requirements ( )
2020-08-14 16:11:40 +08:00
check_distribution_compatibility ( )
2019-12-27 13:14:33 +05:30
check_system_package_managers ( )
2019-12-19 14:01:24 +05:30
check_environment ( )
2019-12-18 14:33:21 +05:30
install_bench ( args )
2019-12-19 14:01:24 +05:30
2019-12-19 14:38:46 +05:30
log ( " Bench + Frappe + ERPNext has been successfully installed! " )