def stop_maintenance(cls): """ Stop containers """ config_object = Config() config = config_object.get_config() if not config_object.multi_servers or config_object.frontend: # Shut down maintenance container in case it's up&running maintenance_down_command = [ "docker-compose", "-f", "docker-compose.maintenance.yml", "-p", config_object.get_prefix("maintenance"), "down" ] CLI.run_command(maintenance_down_command, config.get("kobodocker_path")) # Create and start NGINX container frontend_command = [ "docker-compose", "-f", "docker-compose.frontend.yml", "-f", "docker-compose.frontend.override.yml", "-p", config_object.get_prefix("frontend"), "up", "-d", "nginx" ] CLI.run_command(frontend_command, config.get("kobodocker_path")) CLI.colored_print("Maintenance mode has been stopped", CLI.COLOR_SUCCESS) config['maintenance_enabled'] = False config_object.write_config()
def logs(cls): config_object = Config() config = config_object.get_config() if config_object.master_backend or config_object.slave_backend: backend_role = config.get("backend_server_role", "master") backend_command = ["docker-compose", "-f", "docker-compose.backend.{}.yml".format(backend_role), "-f", "docker-compose.backend.{}.override.yml".format(backend_role), "logs", "-f"] if config.get("docker_prefix", "") != "": backend_command.insert(-2, "-p") backend_command.insert(-2, config.get("docker_prefix")) CLI.run_command(backend_command, config.get("kobodocker_path"), True) if config_object.frontend: frontend_command = ["docker-compose", "-f", "docker-compose.frontend.yml", "-f", "docker-compose.frontend.override.yml", "logs", "-f"] if config.get("docker_prefix", "") != "": frontend_command.insert(-2, "-p") frontend_command.insert(-2, config.get("docker_prefix")) CLI.run_command(frontend_command, config.get("kobodocker_path"), True)
def logs(cls): config_object = Config() config = config_object.get_config() if config_object.primary_backend or config_object.secondary_backend: backend_role = config.get("backend_server_role", "primary") backend_command = [ "docker-compose", "-f", "docker-compose.backend.{}.yml".format(backend_role), "-f", "docker-compose.backend.{}.override.yml".format(backend_role), "-p", config_object.get_prefix("backend"), "logs", "-f" ] CLI.run_command(backend_command, config.get("kobodocker_path"), True) if config_object.frontend: frontend_command = [ "docker-compose", "-f", "docker-compose.frontend.yml", "-f", "docker-compose.frontend.override.yml", "-p", config_object.get_prefix("frontend"), "logs", "-f" ] CLI.run_command(frontend_command, config.get("kobodocker_path"), True)
def stop_maintenance(cls): """ Stop maintenance mode """ config = Config() dict_ = config.get_dict() if not config.multi_servers or config.frontend: # Shut down maintenance container in case it's up&running maintenance_down_command = [ 'docker-compose', '-f', 'docker-compose.maintenance.yml', '-f', 'docker-compose.maintenance.override.yml', '-p', config.get_prefix('maintenance'), 'down' ] CLI.run_command(maintenance_down_command, dict_['kobodocker_path']) # Create and start NGINX container frontend_command = [ 'docker-compose', '-f', 'docker-compose.frontend.yml', '-f', 'docker-compose.frontend.override.yml', '-p', config.get_prefix('frontend'), 'up', '-d', 'nginx' ] CLI.run_command(frontend_command, dict_['kobodocker_path']) CLI.colored_print('Maintenance mode has been stopped', CLI.COLOR_SUCCESS) dict_['maintenance_enabled'] = False config.write_config()
def logs(cls): config = Config() dict_ = config.get_dict() if config.primary_backend or config.secondary_backend: backend_role = dict_['backend_server_role'] backend_command = ['docker-compose', '-f', 'docker-compose.backend.{}.yml'.format( backend_role), '-f', 'docker-compose.backend.{}.override.yml'.format( backend_role), '-p', config.get_prefix('backend'), 'logs', '-f' ] CLI.run_command(backend_command, dict_['kobodocker_path'], True) if config.frontend: frontend_command = ['docker-compose', '-f', 'docker-compose.frontend.yml', '-f', 'docker-compose.frontend.override.yml', '-p', config.get_prefix('frontend'), 'logs', '-f'] CLI.run_command(frontend_command, dict_['kobodocker_path'], True)
def clone_kobodocker(cls, config): """ Args: config (helpers.config.Config) """ dict_ = config.get_dict() do_update = config.first_time if not os.path.isdir(os.path.join(dict_['kobodocker_path'], '.git')): # Move unique id file to /tmp in order to clone without errors # (e.g. not empty directory) tmp_dirpath = tempfile.mkdtemp() shutil.move( os.path.join(dict_['kobodocker_path'], Config.UNIQUE_ID_FILE), os.path.join(tmp_dirpath, Config.UNIQUE_ID_FILE)) # clone project git_command = [ 'git', 'clone', 'https://github.com/kobotoolbox/kobo-docker', dict_['kobodocker_path'] ] CLI.run_command(git_command, cwd=os.path.dirname(dict_['kobodocker_path'])) shutil.move( os.path.join(tmp_dirpath, Config.UNIQUE_ID_FILE), os.path.join(dict_['kobodocker_path'], Config.UNIQUE_ID_FILE)) shutil.rmtree(tmp_dirpath) do_update = True # Force update if do_update: cls.update_kobodocker(dict_)
def clone_kobodocker(cls, config_object): """ :param config_object: `Config` """ config = config_object.get_config() do_update = config_object.first_time if not os.path.isdir(os.path.join(config["kobodocker_path"], ".git")): # Move unique id file to /tmp in order to clone without errors # (e.g. not empty directory) tmp_dirpath = tempfile.mkdtemp() shutil.move( os.path.join(config["kobodocker_path"], Config.UNIQUE_ID_FILE), os.path.join(tmp_dirpath, Config.UNIQUE_ID_FILE)) # clone project git_command = [ "git", "clone", "https://github.com/kobotoolbox/kobo-docker", config["kobodocker_path"] ] CLI.run_command(git_command, cwd=os.path.dirname(config["kobodocker_path"])) shutil.move( os.path.join(tmp_dirpath, Config.UNIQUE_ID_FILE), os.path.join(config["kobodocker_path"], Config.UNIQUE_ID_FILE)) shutil.rmtree(tmp_dirpath) do_update = True # Force update if do_update: cls.update_kobodocker(config)
def build_image(image_): frontend_command = [ 'docker-compose', '-f', 'docker-compose.frontend.yml', '-f', 'docker-compose.frontend.override.yml', '-p', config.get_prefix('frontend'), 'build', '--force-rm', '--no-cache', image_ ] CLI.run_command(frontend_command, dict_['kobodocker_path'])
def build_image(image_): frontend_command = [ "docker-compose", "-f", "docker-compose.frontend.yml", "-f", "docker-compose.frontend.override.yml", "-p", config_object.get_prefix("frontend"), "build", "--force-rm", "--no-cache", image_ ] CLI.run_command(frontend_command, config.get("kobodocker_path"))
def upgrade(cls): config_object = Config() config = config_object.get_config() Setup.run(config) CLI.colored_print("KoBoToolbox has been upgraded", CLI.COLOR_SUCCESS) # update itself git_command = ["git", "pull", "origin", "master"] CLI.run_command(git_command) CLI.colored_print("KoBoInstall has been upgraded", CLI.COLOR_SUCCESS)
def stop_nginx(cls): config = Config() dict_ = config.get_dict() nginx_stop_command = [ 'docker-compose', '-f', 'docker-compose.frontend.yml', '-f', 'docker-compose.frontend.override.yml', '-p', config.get_prefix('frontend'), 'stop', 'nginx' ] CLI.run_command(nginx_stop_command, dict_['kobodocker_path'])
def stop_nginx(cls): config_object = Config() config = config_object.get_config() nginx_stop_command = [ "docker-compose", "-f", "docker-compose.frontend.yml", "-f", "docker-compose.frontend.override.yml", "-p", config_object.get_prefix("frontend"), "stop", "nginx" ] CLI.run_command(nginx_stop_command, config.get("kobodocker_path"))
def start_maintenance(cls): config_object = Config() config = config_object.get_config() frontend_command = [ "docker-compose", "-f", "docker-compose.maintenance.yml", "-p", config_object.get_prefix("maintenance"), "up", "-d", "maintenance" ] CLI.run_command(frontend_command, config.get("kobodocker_path")) CLI.colored_print("Maintenance mode has been started", CLI.COLOR_SUCCESS)
def build_image(image_): frontend_command = ["docker-compose", "-f", "docker-compose.frontend.yml", "-f", "docker-compose.frontend.override.yml", "build", "--force-rm", "--no-cache", image_] if config.get("docker_prefix", "") != "": frontend_command.insert(-4, "-p") frontend_command.insert(-4, config.get("docker_prefix")) CLI.run_command(frontend_command, config.get("kobodocker_path"))
def start_maintenance(cls): config = Config() dict_ = config.get_dict() frontend_command = [ 'docker-compose', '-f', 'docker-compose.maintenance.yml', '-f', 'docker-compose.maintenance.override.yml', '-p', config.get_prefix('maintenance'), 'up', '-d' ] CLI.run_command(frontend_command, dict_['kobodocker_path']) CLI.colored_print('Maintenance mode has been started', CLI.COLOR_SUCCESS)
def build(cls, image=None): """ Builds kpi/kobocat images with `--no-caches` option Pulls latest `kobotoolbox/koboform_base` as well :param image: str """ config_object = Config() config = config_object.get_config() if config_object.dev_mode or config_object.staging_mode: def build_image(image_): frontend_command = ["docker-compose", "-f", "docker-compose.frontend.yml", "-f", "docker-compose.frontend.override.yml", "build", "--force-rm", "--no-cache", image_] if config.get("docker_prefix", "") != "": frontend_command.insert(-4, "-p") frontend_command.insert(-4, config.get("docker_prefix")) CLI.run_command(frontend_command, config.get("kobodocker_path")) pull_base_command = ["docker", "pull", "kobotoolbox/koboform_base"] CLI.run_command(pull_base_command, config.get("kobodocker_path")) if image is None or image == "kf": config["kpi_dev_build_id"] = "{prefix}{timestamp}".format( prefix="{}.".format(config.get("docker_prefix")) if config.get("docker_prefix") else "", timestamp=str(int(time.time())) ) config_object.write_config() Template.render(config_object) build_image("kpi") if image is None or image == "kc": config["kc_dev_build_id"] = "{prefix}{timestamp}".format( prefix="{}.".format(config.get("docker_prefix")) if config.get("docker_prefix") else "", timestamp=str(int(time.time())) ) config_object.write_config() Template.render(config_object) build_image("kobocat")
def build(cls, image=None): """ Builds kpi/kobocat images with `--no-caches` option Pulls latest `kobotoolbox/koboform_base` as well :param image: str """ config = Config() dict_ = config.get_dict() if config.dev_mode or config.staging_mode: def build_image(image_): frontend_command = [ 'docker-compose', '-f', 'docker-compose.frontend.yml', '-f', 'docker-compose.frontend.override.yml', '-p', config.get_prefix('frontend'), 'build', '--force-rm', '--no-cache', image_ ] CLI.run_command(frontend_command, dict_['kobodocker_path']) if image is None or image == 'kf': dict_['kpi_dev_build_id'] = '{prefix}{timestamp}'.format( prefix=config.get_prefix('frontend'), timestamp=str(int(time.time())) ) config.write_config() Template.render(config) build_image('kpi') if image is None or image == 'kc': pull_base_command = ['docker', 'pull', 'kobotoolbox/koboform_base'] CLI.run_command(pull_base_command, dict_['kobodocker_path']) dict_['kc_dev_build_id'] = '{prefix}{timestamp}'.format( prefix=config.get_prefix('frontend'), timestamp=str(int(time.time())) ) config.write_config() Template.render(config) build_image('kobocat')
def run(cls, version=None, cron=False, update_self=True): # Validate kobo-docker already exists and is valid Setup.validate_already_run() if version is None: git_commit_version_command = [ 'git', 'rev-parse', '--abbrev-ref', 'HEAD', ] version = CLI.run_command(git_commit_version_command).strip() if update_self: # Update kobo-install first Setup.update_koboinstall(version) CLI.colored_print('kobo-install has been updated', CLI.COLOR_SUCCESS) # Reload this script to use `version`. # NB:`argv[0]` does not automatically get set to the executable # path as it usually would, so we have to do it manually--hence the # double `sys.executable` sys.argv.append(cls.NO_UPDATE_SELF_OPTION) os.execl(sys.executable, sys.executable, *sys.argv) # Update kobo-docker Setup.update_kobodocker() CLI.colored_print('kobo-docker has been updated', CLI.COLOR_SUCCESS) Setup.post_update(cron)
def version(cls): git_commit_version_command = ['git', 'rev-parse', 'HEAD'] stdout = CLI.run_command(git_commit_version_command) CLI.colored_print('kobo-install Version: {} (build {})'.format( Config.KOBO_INSTALL_VERSION, stdout.strip()[0:7], ), CLI.COLOR_SUCCESS)
def version(cls): git_commit_version_command = ["git", "rev-parse", "HEAD"] stdout = CLI.run_command(git_commit_version_command) CLI.colored_print( "KoBoInstall Version: {} (build {})".format( Config.KOBO_INSTALL_VERSION, stdout.strip()[0:7], ), CLI.COLOR_SUCCESS)
def stop(cls, output=True, frontend_only=False): """ Stop containers """ config = Config() dict_ = config.get_dict() if not config.multi_servers or config.frontend: # Shut down maintenance container in case it's up&running maintenance_down_command = [ 'docker-compose', '-f', 'docker-compose.maintenance.yml', '-f', 'docker-compose.maintenance.override.yml', '-p', config.get_prefix('maintenance'), 'down' ] CLI.run_command(maintenance_down_command, dict_['kobodocker_path']) # Stop reverse proxy if user uses it. if config.use_letsencrypt: proxy_command = ['docker-compose', 'down'] CLI.run_command(proxy_command, config.get_letsencrypt_repo_path()) # Shut down front-end containers frontend_command = [ 'docker-compose', '-f', 'docker-compose.frontend.yml', '-f', 'docker-compose.frontend.override.yml', '-p', config.get_prefix('frontend'), 'down', ] cls.__validate_custom_yml(config, frontend_command) CLI.run_command(frontend_command, dict_['kobodocker_path']) if not frontend_only and config.backend: backend_role = dict_['backend_server_role'] backend_command = [ 'docker-compose', '-f', 'docker-compose.backend.{}.yml'.format(backend_role), '-f', 'docker-compose.backend.{}.override.yml'.format(backend_role), '-p', config.get_prefix('backend'), 'down' ] cls.__validate_custom_yml(config, backend_command) CLI.run_command(backend_command, dict_['kobodocker_path']) if output: CLI.colored_print('KoboToolbox has been stopped', CLI.COLOR_SUCCESS)
def update(cls): config_object = Config() config = config_object.get_config() Setup.update_kobodocker(config) CLI.colored_print("KoBoToolbox has been updated", CLI.COLOR_SUCCESS) # update itself git_command = ['git', 'pull', 'origin', Config.KOBO_INSTALL_BRANCH] CLI.run_command(git_command) CLI.colored_print("KoBoInstall has been updated", CLI.COLOR_SUCCESS) CLI.colored_print( "╔═════════════════════════════════════════════════════╗", CLI.COLOR_WARNING) CLI.colored_print( "║ After an update, it's strongly recommended to run ║", CLI.COLOR_WARNING) CLI.colored_print( "║ `./run.py --setup` to regenerate environment files. ║", CLI.COLOR_WARNING) CLI.colored_print( "╚═════════════════════════════════════════════════════╝", CLI.COLOR_WARNING) CLI.colored_print("Do you want to proceed?", CLI.COLOR_SUCCESS) CLI.colored_print("\t1) Yes") CLI.colored_print("\t2) No") response = CLI.get_response([Config.TRUE, Config.FALSE], Config.TRUE) if response == Config.TRUE: current_config = config_object.build() Template.render(config_object) config_object.init_letsencrypt() Setup.update_hosts(current_config) CLI.colored_print("Do you want to (re)start containers?", CLI.COLOR_SUCCESS) CLI.colored_print("\t1) Yes") CLI.colored_print("\t2) No") response = CLI.get_response([Config.TRUE, Config.FALSE], Config.TRUE) if response == Config.TRUE: Command.start()
def version(cls): branch_name = CLI.run_command( ["git", "symbolic-ref", "--short", "HEAD"]) git_commit_version_command = ["git", "rev-parse", branch_name.strip()] commit_stdout = CLI.run_command(git_commit_version_command) try: git_tag_version_command = [ "git", "describe", "--tags", commit_stdout.strip() ] tag_stdout = CLI.run_command(git_tag_version_command) git_version = tag_stdout.strip() except: git_version = commit_stdout.strip()[0:7] CLI.colored_print( "KoBoInstall Version: {} (build {})".format( Config.KOBO_INSTALL_VERSION, git_version, ), CLI.COLOR_SUCCESS)
def run(cls, config): """ Clone or pull `kobo-docker` project in installation directory :param config: dict """ if not os.path.isdir("{}/.git".format(config["kobodocker_path"])): # clone project git_command = [ "git", "clone", "https://github.com/kobotoolbox/kobo-docker", config["kobodocker_path"] ] CLI.run_command(git_command, cwd=os.path.dirname(config["kobodocker_path"])) if os.path.isdir("{}/.git".format(config["kobodocker_path"])): # checkout branch git_command = [ "git", "checkout", "--force", Setup.KOBO_DOCKER_BRANCH ] CLI.run_command(git_command, cwd=config["kobodocker_path"]) # update code git_command = ["git", "pull", "origin", Setup.KOBO_DOCKER_BRANCH] CLI.run_command(git_command, cwd=config["kobodocker_path"])
def run(cls, config): """ Clone or pull `kobo-docker` project in installation directory :param config: dict """ if not os.path.isdir(os.path.join(config["kobodocker_path"], ".git")): # Move unique id file to /tmp in order to clone without errors # (e.g. not empty directory) tmp_dirpath = tempfile.mkdtemp() os.rename(os.path.join(config["kobodocker_path"], Config.UNIQUE_ID_FILE), os.path.join(tmp_dirpath, Config.UNIQUE_ID_FILE)) # clone project git_command = [ "git", "clone", "https://github.com/kobotoolbox/kobo-docker", config["kobodocker_path"] ] CLI.run_command(git_command, cwd=os.path.dirname(config["kobodocker_path"])) os.rename(os.path.join(tmp_dirpath, Config.UNIQUE_ID_FILE), os.path.join(config["kobodocker_path"], Config.UNIQUE_ID_FILE)) shutil.rmtree(tmp_dirpath) if os.path.isdir(os.path.join(config["kobodocker_path"], ".git")): # checkout branch git_command = ["git", "checkout", "--force", Setup.KOBO_DOCKER_BRANCH] CLI.run_command(git_command, cwd=config["kobodocker_path"]) # update code git_command = ["git", "pull", "origin", Setup.KOBO_DOCKER_BRANCH] CLI.run_command(git_command, cwd=config["kobodocker_path"])
def stop(cls, output=True, frontend_only=False): """ Stop containers """ config_object = Config() config = config_object.get_config() if not config_object.multi_servers or config_object.frontend: # Shut down maintenance container in case it's up&running maintenance_down_command = [ "docker-compose", "-f", "docker-compose.maintenance.yml", "-f", "docker-compose.maintenance.override.yml", "-p", config_object.get_prefix("maintenance"), "down" ] CLI.run_command(maintenance_down_command, config.get("kobodocker_path")) # Shut down frontend containers frontend_command = [ "docker-compose", "-f", "docker-compose.frontend.yml", "-f", "docker-compose.frontend.override.yml", "-p", config_object.get_prefix("frontend"), "down" ] CLI.run_command(frontend_command, config.get("kobodocker_path")) # Stop reverse proxy if user uses it. if config_object.use_letsencrypt: proxy_command = ["docker-compose", "down"] CLI.run_command(proxy_command, config_object.get_letsencrypt_repo_path()) if not frontend_only: if not config_object.multi_servers or config_object.primary_backend: backend_role = config.get("backend_server_role", "primary") backend_command = [ "docker-compose", "-f", "docker-compose.backend.{}.yml".format(backend_role), "-f", "docker-compose.backend.{}.override.yml".format( backend_role), "-p", config_object.get_prefix("backend"), "down" ] CLI.run_command(backend_command, config.get("kobodocker_path")) if output: CLI.colored_print("KoBoToolbox has been stopped", CLI.COLOR_SUCCESS)
def stop(cls, output=True, frontend_only=False): """ Stop containers """ config_object = Config() config = config_object.get_config() if not frontend_only: if (config.get("multi") == Config.TRUE and config.get("server_role") == "backend") or \ config.get("multi") != Config.TRUE: backend_role = config.get("backend_server_role", "master") backend_command = [ "docker-compose", "-f", "docker-compose.backend.{}.yml".format(backend_role), "-f", "docker-compose.backend.{}.override.yml".format( backend_role), "down" ] if config.get("docker_prefix", "") != "": backend_command.insert(-1, "-p") backend_command.insert(-1, config.get("docker_prefix")) CLI.run_command(backend_command, config.get("kobodocker_path")) if (config.get("multi") == Config.TRUE and config.get("server_role") == "frontend") or \ config.get("multi") != Config.TRUE: frontend_command = [ "docker-compose", "-f", "docker-compose.frontend.yml", "-f", "docker-compose.frontend.override.yml", "down" ] if config.get("docker_prefix", "") != "": frontend_command.insert(-1, "-p") frontend_command.insert(-1, config.get("docker_prefix")) CLI.run_command(frontend_command, config.get("kobodocker_path")) if output: CLI.colored_print("KoBoToolbox has been stopped", CLI.COLOR_SUCCESS)
def update_koboinstall(version): # fetch new tags and prune git_fetch_prune_command = ['git', 'fetch', '-p'] CLI.run_command(git_fetch_prune_command) # checkout branch git_command = ['git', 'checkout', '--force', version] CLI.run_command(git_command) # update code git_command = ['git', 'pull', 'origin', version] CLI.run_command(git_command)
def update_koboinstall(version): # fetch new tags and prune git_fetch_prune_command = ['git', 'fetch', '-p'] CLI.run_command(git_fetch_prune_command) # checkout branch git_command = ["git", "checkout", "--force", version] CLI.run_command(git_command) # update code git_command = ["git", "pull", "origin", version] CLI.run_command(git_command)
def start(cls, frontend_only=False): config = Config() dict_ = config.get_dict() cls.stop(output=False, frontend_only=frontend_only) if frontend_only: CLI.colored_print('Launching frontend containers', CLI.COLOR_INFO) else: CLI.colored_print('Launching environment', CLI.COLOR_INFO) backend_command = [ 'docker-compose', '-f', 'docker-compose.db.yml', '-p', config.get_prefix('backend'), 'up', '-d' ] CLI.run_command(backend_command, dict_['support_api_path']) # Start the front-end containers # if config.frontend: # If this was previously a shared-database setup, migrate to # separate databases for KPI and KoBoCAT #Upgrading.migrate_single_to_two_databases(config) frontend_command = ['docker-compose', '-f', 'docker-compose.frontend.yml', '-f', 'docker-compose.frontend.override.yml', '-p', config.get_prefix('frontend'), 'up', '-d'] CLI.run_command(frontend_command, dict_['support_api_path']) # Start Dashboards container frontend_command = ['docker-compose', '-f', 'docker-compose.shiny.yml', '-p', config.get_prefix('dashboards'), 'up', '-d'] CLI.run_command(frontend_command, dict_['support_api_path'])