def check_and_install_prereqs(tests_path): try: import tethysapp.test_app # noqa: F401 if tethysapp.test_app is None: raise ImportError except Exception: write_warning("Test App not found. Installing.....") setup_path = os.path.join(tests_path, 'apps', 'tethysapp-test_app') subprocess.call(['python', 'setup.py', 'develop'], stdout=FNULL, stderr=subprocess.STDOUT, cwd=setup_path) try: import tethysext.test_extension # noqa: F401 if tethysext.test_extension is None: raise ImportError except Exception: write_warning("Test Extension not found. Installing.....") setup_path = os.path.join(tests_path, 'extensions', 'tethysext-test_extension') subprocess.call(['python', 'setup.py', 'develop'], stdout=FNULL, stderr=subprocess.STDOUT, cwd=setup_path)
def install_packages(conda_config, update_installed=False): # Compile channels arguments install_args = [] if validate_schema('channels', conda_config): channels = conda_config['channels'] for channel in channels: install_args.extend(['-c', channel]) # Install all Packages if validate_schema('packages', conda_config): if not update_installed: install_args.extend(['--freeze-installed']) else: write_warning( 'Warning: Updating previously installed packages. This could break your Tethys environment.' ) install_args.extend(conda_config['packages']) write_msg("Running conda installation tasks...") [resp, err, code] = conda_run(Commands.INSTALL, *install_args, use_exception_handler=False, stdout=None, stderr=None) if code != 0: write_error( 'Warning: Packages installation ran into an error. Please try again or a manual install' )
def check_for_existing_file(destination_path, destination_file, overwrite): # Check for pre-existing file if os.path.isfile(destination_path): valid_inputs = ('y', 'n', 'yes', 'no') no_inputs = ('n', 'no') if overwrite: overwrite_input = 'yes' else: overwrite_input = input('WARNING: "{0}" already exists. ' 'Overwrite? (y/n): '.format(destination_file)).lower() while overwrite_input not in valid_inputs: overwrite_input = input('Invalid option. Overwrite? (y/n): ').lower() if overwrite_input in no_inputs: write_warning('Generation of "{0}" cancelled.'.format(destination_file)) exit(0)
def install_command(args): """ install Command """ app_name = None skip_config = False file_path = Path('./install.yml') if args.file is None else Path(args.file) # Check for install.yml file if not file_path.exists(): write_warning('WARNING: No install file found.') if not args.quiet: valid_inputs = ('y', 'n', 'yes', 'no') no_inputs = ('n', 'no') generate_input = input( 'Would you like to generate a template install.yml file in your current directory ' 'now? (y/n): ') while generate_input not in valid_inputs: generate_input = input( 'Invalid option. Try again. (y/n): ').lower() if generate_input in no_inputs: skip_config = True write_msg('Generation of Install File cancelled.') else: call(['tethys', 'gen', 'install']) write_msg( 'Install file generated. Fill out necessary information and re-install.' ) exit(0) write_warning('Continuing install without configuration.') # Install Dependencies if not skip_config: write_msg("Installing dependencies...") install_options = open_file(file_path) if "name" in install_options: app_name = install_options['name'] if validate_schema('requirements', install_options): requirements_config = install_options['requirements'] skip = False if "skip" in requirements_config: skip = requirements_config['skip'] if skip: write_warning( "Skipping package installation, Skip option found.") elif args.without_dependencies: write_warning("Skipping package installation.") else: if validate_schema('conda', requirements_config): # noqa: E501 conda_config = requirements_config['conda'] install_packages(conda_config, update_installed=args.update_installed) if validate_schema('pip', requirements_config): write_msg("Running pip installation tasks...") call(['pip', 'install', *requirements_config["pip"]]) # Skip the rest if we are installing dependencies only if args.only_dependencies: successful_exit(app_name, "installed dependencies for") # Run Setup.py write_msg("Running application install....") if args.verbose: call(['python', 'setup.py', 'clean', '--all'], stderr=STDOUT) if args.develop: call(['python', 'setup.py', 'develop'], stderr=STDOUT) else: call(['python', 'setup.py', 'install'], stderr=STDOUT) else: call(['python', 'setup.py', 'clean', '--all'], stdout=FNULL, stderr=STDOUT) if args.develop: call(['python', 'setup.py', 'develop'], stdout=FNULL, stderr=STDOUT) else: call(['python', 'setup.py', 'install'], stdout=FNULL, stderr=STDOUT) if args.no_db_sync: successful_exit(app_name) call(['tethys', 'db', 'sync']) # Run Portal Level Config if present if not skip_config: load_apps() if args.force_services: run_services(app_name, args) else: portal_result = run_portal_install(app_name) if not portal_result: run_services(app_name, args) if args.quiet: write_msg( "Quiet mode: No additional service setting validation will be performed." ) else: run_interactive_services(app_name) write_success("Services Configuration Completed.") app_settings = get_app_settings(app_name) if app_settings is not None: linked_settings = app_settings['linked_settings'] unlinked_settings = app_settings['unlinked_settings'] if args.no_sync_stores: write_msg('Skipping syncstores.') else: run_sync_stores(app_name, linked_settings) print_unconfigured_settings(app_name, unlinked_settings) # Check to see if any extra scripts need to be run if validate_schema('post', install_options): write_msg("Running post installation tasks...") for post in install_options["post"]: path_to_post = file_path.resolve().parent / post # Attempting to run processes. process = Popen(str(path_to_post), shell=True, stdout=PIPE) stdout = process.communicate()[0] write_msg("Post Script Result: {}".format(stdout)) successful_exit(app_name)
def configure_services_from_file(services, app_name): from tethys_apps.models import CustomSetting if services['version']: del services['version'] for service_type in services: if services[service_type] is not None: current_services = services[service_type] for setting_name in current_services: if service_type == 'custom_setting': try: custom_setting = CustomSetting.objects.get( name=setting_name) except ObjectDoesNotExist: write_warning( f'Custom setting named "{setting_name}" could not be found in app "{app_name}". ' f'Skipping...') continue try: custom_setting.value = current_services[setting_name] custom_setting.clean() custom_setting.save() write_success( f'CustomSetting: "{setting_name}" was assigned the value: ' f'"{current_services[setting_name]}"') except ValidationError: write_error( "Incorrect value type given for custom setting '{}'. Please adjust " "services.yml or set the value in the app's settings page." .format(setting_name)) else: app_settings = get_app_settings(app_name) # In the case the app isn't installed, has no settings, or it is an extension, # skip configuring services/settings if not app_settings: write_msg( f'No settings found for app "{app_name}". Skipping automated configuration...' ) return unlinked_settings = app_settings['unlinked_settings'] setting_found = False for setting in unlinked_settings: if setting.name != setting_name: continue setting_found = True service_id = current_services[setting_name] if not service_id: write_warning( f'No service given for setting "{setting_name}". Skipping...' ) continue find_and_link(service_type, setting_name, service_id, app_name, setting) if not setting_found: write_warning( f'Service setting "{setting_name}" already configured or does not exist in app ' f'"{app_name}". Skipping...')
def run_interactive_services(app_name): write_msg( 'Running Interactive Service Mode. ' 'Any configuration options in services.yml or portal_config.yml will be ignored...' ) write_msg('Hit return at any time to skip a step.') app_settings = get_app_settings(app_name) # In the case the app isn't installed, has no settings, or it is an extension, # skip configuring services/settings if not app_settings: write_msg( f'No settings found for app "{app_name}". Skipping interactive configuration...' ) return unlinked_settings = app_settings['unlinked_settings'] for setting in unlinked_settings: valid = False configure_text = "Configuring {}".format(setting.name) star_out = '*' * len(configure_text) write_msg(f"\n{star_out}\n{configure_text}\n{star_out}") write_msg(f"Type: {setting.__class__.__name__}\n" f"Description: {setting.description}\n" f"Required: {setting.required}") if hasattr(setting, 'value'): while not valid: write_msg( '\nEnter the desired value for the current custom setting: {}' .format(setting.name)) try: value = get_interactive_input() if value != "": try: setting.value = value setting.clean() setting.save() valid = True write_success( "{} successfully set with value: {}.".format( setting.name, value)) except ValidationError: write_error( "Incorrect value type given for custom setting '{}'. Please try again" .format(setting.name)) else: write_msg("Skipping setup of {}".format(setting.name)) valid = True except (KeyboardInterrupt, SystemExit): write_msg('\nInstall Command cancelled.') exit(0) else: # List existing services args = Namespace() for conf in ['spatial', 'persistent', 'wps', 'dataset']: setattr(args, conf, False) setattr(args, get_setting_type(setting), True) services = services_list_command(args)[0] if len(services) <= 0: write_warning( 'No compatible services found. See:\n\n tethys services create {} -h\n' .format(get_setting_type(setting))) continue while not valid: write_msg( '\nEnter the service ID/Name to link to the current service setting: {}.' .format(setting.name)) try: service_id = get_interactive_input() if service_id != "": try: setting_type = get_setting_type_from_setting( setting) service_type = get_service_type_from_setting( setting) except RuntimeError as e: write_error(str(e) + ' Skipping...') break # Validate the given service id valid_service = validate_service_id( service_type, service_id) if valid_service: link_service_to_app_setting( service_type, service_id, app_name, setting_type, setting.name) valid = True else: write_error( 'Incorrect service ID/Name. Please try again.') else: write_msg("Skipping setup of {}".format(setting.name)) valid = True except (KeyboardInterrupt, SystemExit): write_msg('\nInstall Command cancelled.') exit(0)
def __init__( self, jobs, column_fields, show_status=True, show_actions=True, monitor_url='', results_url='', hover=False, striped=False, bordered=False, condensed=False, attributes=None, classes='', refresh_interval=5000, delay_loading_status=True, show_detailed_status=False, actions=None, enable_data_table=False, data_table_options=None, # Deprecated options: status_actions=None, show_resubmit_btn=None, run_btn=None, delete_btn=None, show_log_btn=None): """ Constructor """ # Initialize super class super().__init__(attributes=attributes, classes=classes) self.jobs = jobs self.rows = None self.column_fields = None self.column_names = None self.set_rows_and_columns(jobs, column_fields) self.show_status = show_status self.show_actions = show_actions self.monitor_url = monitor_url self.results_url = results_url self.hover = hover self.striped = striped self.bordered = bordered self.condensed = condensed self.attributes = attributes or {} self.classes = classes self.refresh_interval = refresh_interval self.delay_loading_status = delay_loading_status self.show_detailed_status = show_detailed_status self.enable_data_table = enable_data_table self.data_table_options = data_table_options or { 'ordering': True, 'searching': False, 'paging': False } actions = actions or ['run', 'resubmit', 'logs', 'terminate', 'delete'] if monitor_url: actions.append('monitor') if results_url: actions.append('results') # code for backwards compatibility. Remove in Tethys v3.3 if status_actions is not None: # deprecation warning write_warning( 'Deprecation Warning: The "status_actions" option in JobsTable will be removed in ' 'the next release of Tethys. Please use "show_status" and "show_actions" instead.' ) self.show_actions = status_actions lcl = locals() for option, action in (('run_btn', 'run'), ('delete_btn', 'delete'), ('show_resubmit_btn', 'resubmit'), ('show_log_btn', 'logs')): option_val = lcl[option] if option_val is not None: # deprecation warning write_warning( f'Deprecation Warning: The "{option}" option in JobsTable will be removed in the ' f'next release of Tethys. Please use the "show_actions" and "actions" options instead.' ) if option_val: actions.append(action) else: try: actions.remove(action) except ValueError: pass # end compatibility code self.actions = dict( run='run' in actions, resubmit='resubmit' in actions, logs='logs' in actions, monitor='monitor' in actions and monitor_url, results='results' in actions and monitor_url, terminate='terminate' in actions, delete='delete' in actions, ) # Compute column count self.num_cols = len(column_fields) if self.show_status: self.num_cols += 1 if self.show_actions: self.num_cols += 1
def generate_portal_config_file(): write_warning( 'No Tethys Portal configuration file was found. Generating one now...') args = Namespace(type='portal_config', directory=None, overwrite=False) generate_command(args)