def process_settings(app_instance, app_py_path, channel_layer):
    app_settings = get_app_settings(app_instance.package)

    # In the case the app isn't installed, has no settings, or it is an extension,
    # skip configuring services/settings
    if not app_settings:
        send_notification("No Services found to configure.", channel_layer)
        return
    unlinked_settings = app_settings['unlinked_settings']

    services = []
    for setting in unlinked_settings:
        if setting.__class__.__name__ == "CustomSetting":
            continue
        service_type = get_service_type_from_setting(setting)
        newSetting = {
            "name": setting.name,
            "required": setting.required,
            "description": setting.description,
            "service_type": service_type,
            "setting_type": get_setting_type_from_setting(setting),
            "options": get_service_options(service_type)
        }
        services.append(newSetting)

    get_data_json = {
        "data": services,
        "returnMethod": "configure_services",
        "jsHelperFunction": "processServices",
        "app_py_path": app_py_path,
        "current_app_name": app_instance.package
    }
    send_notification(get_data_json, channel_layer)
Example #2
0
def app_settings_list_command(args):
    load_apps()
    app_settings = get_app_settings(args.app)
    if app_settings is None:
        return
    unlinked_settings = app_settings['unlinked_settings']
    linked_settings = app_settings['linked_settings']

    with pretty_output(BOLD) as p:
        p.write("\nUnlinked Settings:")

    if len(unlinked_settings) == 0:
        with pretty_output() as p:
            p.write('None')
    else:
        is_first_row = True
        for setting in unlinked_settings:
            if is_first_row:
                with pretty_output(BOLD) as p:
                    p.write('{0: <10}{1: <40}{2: <15}'.format(
                        'ID', 'Name', 'Type'))
                is_first_row = False
            with pretty_output() as p:
                p.write('{0: <10}{1: <40}{2: <15}'.format(
                    setting.pk, setting.name, get_setting_type(setting)))

    with pretty_output(BOLD) as p:
        p.write("\nLinked Settings:")

    if len(linked_settings) == 0:
        with pretty_output() as p:
            p.write('None')
    else:
        is_first_row = True
        for setting in linked_settings:
            if is_first_row:
                with pretty_output(BOLD) as p:
                    p.write('{0: <10}{1: <40}{2: <15}{3: <20}'.format(
                        'ID', 'Name', 'Type', 'Linked With'))
                is_first_row = False

            if hasattr(setting, 'persistent_store_service'):
                service_name = setting.persistent_store_service.name
            elif hasattr(setting, 'spatial_dataset_service'):
                service_name = setting.spatial_dataset_service.name
            elif hasattr(setting, 'dataset_service'):
                service_name = setting.dataset_service.name
            elif hasattr(setting, 'web_processing_service'):
                service_name = setting.web_processing_service.name
            elif hasattr(setting, 'value'):
                service_name = setting.value

            with pretty_output() as p:
                p.write(
                    f'{setting.pk: <10}{setting.name: <40}{get_setting_type(setting): <15}{service_name: <20}'
                )
Example #3
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 #4
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 #5
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)