Example #1
0
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)
Example #2
0
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'
            )
Example #3
0
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)
Example #4
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)
Example #5
0
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...')
Example #6
0
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)
Example #7
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
Example #8
0
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)