Example #1
0
def app_factory( global_conf, **kwargs ):
    """Return a wsgi application serving the root object"""
    # Create the Galaxy application unless passed in
    kwargs = load_app_properties(
        kwds=kwargs
    )
    if 'app' in kwargs:
        app = kwargs.pop( 'app' )
    else:
        from galaxy.webapps.reports.app import UniverseApplication
        app = UniverseApplication( global_conf=global_conf, **kwargs )
    atexit.register( app.shutdown )
    # Create the universe WSGI application
    webapp = ReportsWebApplication( app, session_cookie='galaxyreportssession', name="reports" )
    add_ui_controllers( webapp, app )
    # These two routes handle our simple needs at the moment
    webapp.add_route( '/{controller}/{action}', controller="root", action='index' )
    webapp.add_route( '/{action}', controller='root', action='index' )
    webapp.finalize_config()
    # Wrap the webapp in some useful middleware
    if kwargs.get( 'middleware', True ):
        webapp = wrap_in_middleware( webapp, global_conf, **kwargs )
    if asbool( kwargs.get( 'static_enabled', True ) ):
        webapp = wrap_in_static( webapp, global_conf, **kwargs )
    # Close any pooled database connections before forking
    try:
        galaxy.model.mapping.metadata.bind.dispose()
    except:
        log.exception("Unable to dispose of pooled galaxy model database connections.")
    # Return
    return webapp
Example #2
0
def app_factory( global_conf, **kwargs ):
    """Return a wsgi application serving the root object"""
    # Create the Galaxy application unless passed in
    kwargs = load_app_properties(
        kwds=kwargs
    )
    if 'app' in kwargs:
        app = kwargs.pop( 'app' )
    else:
        from galaxy.webapps.reports.app import UniverseApplication
        app = UniverseApplication( global_conf=global_conf, **kwargs )
    atexit.register( app.shutdown )
    # Create the universe WSGI application
    webapp = ReportsWebApplication( app, session_cookie='galaxyreportssession', name="reports" )
    add_ui_controllers( webapp, app )
    # These two routes handle our simple needs at the moment
    webapp.add_route( '/{controller}/{action}', controller="root", action='index' )
    webapp.add_route( '/{action}', controller='root', action='index' )
    webapp.finalize_config()
    # Wrap the webapp in some useful middleware
    if kwargs.get( 'middleware', True ):
        webapp = wrap_in_middleware( webapp, global_conf, **kwargs )
    if asbool( kwargs.get( 'static_enabled', True ) ):
        webapp = wrap_in_static( webapp, global_conf, **kwargs )
    # Close any pooled database connections before forking
    try:
        galaxy.model.mapping.metadata.bind.dispose()
    except:
        log.exception("Unable to dispose of pooled galaxy model database connections.")
    # Return
    return webapp
Example #3
0
def app_factory( global_conf, **kwargs ):
    """Return a wsgi application serving the root object"""
    # Create the Galaxy tool shed application unless passed in
    kwargs = load_app_properties(
        kwds=kwargs,
        config_prefix='TOOL_SHED_CONFIG_'
    )
    if 'app' in kwargs:
        app = kwargs.pop( 'app' )
    else:
        try:
            from galaxy.webapps.tool_shed.app import UniverseApplication
            app = UniverseApplication( global_conf=global_conf, **kwargs )
        except:
            import traceback
            import sys
            traceback.print_exc()
            sys.exit( 1 )
    atexit.register( app.shutdown )
    # Create the universe WSGI application
    webapp = CommunityWebApplication( app, session_cookie='galaxycommunitysession', name="tool_shed" )
    add_ui_controllers( webapp, app )
    webapp.add_route( '/view/{owner}', controller='repository', action='sharable_owner' )
    webapp.add_route( '/view/{owner}/{name}', controller='repository', action='sharable_repository' )
    webapp.add_route( '/view/{owner}/{name}/{changeset_revision}', controller='repository', action='sharable_repository_revision' )
    # Handle displaying tool help images and README file images for tools contained in repositories.
    webapp.add_route( '/repository/static/images/{repository_id}/{image_file:.+?}',
                      controller='repository',
                      action='display_image_in_repository',
                      repository_id=None,
                      image_file=None )
    webapp.add_route( '/{controller}/{action}', action='index' )
    webapp.add_route( '/{action}', controller='repository', action='index' )
    webapp.add_route( '/repos/*path_info', controller='hg', action='handle_request', path_info='/' )
    # Add the web API.  # A good resource for RESTful services - http://routes.readthedocs.org/en/latest/restful.html
    webapp.add_api_controllers( 'galaxy.webapps.tool_shed.api', app )
    webapp.mapper.connect( 'api_key_retrieval',
                           '/api/authenticate/baseauth/',
                           controller='authenticate',
                           action='get_tool_shed_api_key',
                           conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.connect( 'group',
                           '/api/groups/',
                           controller='groups',
                           action='index',
                           conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.connect( 'group',
                           '/api/groups/',
                           controller='groups',
                           action='create',
                           conditions=dict( method=[ "POST" ] ) )
    webapp.mapper.connect( 'group',
                           '/api/groups/{encoded_id}',
                           controller='groups',
                           action='show',
                           conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.resource( 'category',
                            'categories',
                            controller='categories',
                            name_prefix='category_',
                            path_prefix='/api',
                            parent_resources=dict( member_name='category', collection_name='categories' ) )
    webapp.mapper.resource( 'repository',
                            'repositories',
                            controller='repositories',
                            collection={ 'add_repository_registry_entry' : 'POST',
                                         'get_repository_revision_install_info' : 'GET',
                                         'get_ordered_installable_revisions' : 'GET',
                                         'remove_repository_registry_entry' : 'POST',
                                         'repository_ids_for_setting_metadata' : 'GET',
                                         'reset_metadata_on_repositories' : 'POST',
                                         'reset_metadata_on_repository' : 'POST' },
                            name_prefix='repository_',
                            path_prefix='/api',
                            new={ 'import_capsule' : 'POST' },
                            parent_resources=dict( member_name='repository', collection_name='repositories' ) )
    webapp.mapper.resource( 'repository_revision',
                            'repository_revisions',
                            member={ 'repository_dependencies' : 'GET',
                                     'export' : 'POST' },
                            controller='repository_revisions',
                            name_prefix='repository_revision_',
                            path_prefix='/api',
                            parent_resources=dict( member_name='repository_revision', collection_name='repository_revisions' ) )
    webapp.mapper.resource( 'user',
                            'users',
                            controller='users',
                            name_prefix='user_',
                            path_prefix='/api',
                            parent_resources=dict( member_name='user', collection_name='users' ) )
    webapp.mapper.connect( 'update_repository',
                           '/api/repositories/{id}',
                           controller='repositories',
                           action='update',
                           conditions=dict( method=[ "PATCH", "PUT" ] ) )
    webapp.mapper.connect( 'repository_create_changeset_revision',
                           '/api/repositories/{id}/changeset_revision',
                           controller='repositories',
                           action='create_changeset_revision',
                           conditions=dict( method=[ "POST" ] ) )
    webapp.mapper.connect( 'create_repository',
                           '/api/repositories',
                           controller='repositories',
                           action='create',
                           conditions=dict( method=[ "POST" ] ) )
    webapp.mapper.connect( 'tools',
                           '/api/tools',
                           controller='tools',
                           action='index',
                           conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.connect( "version", "/api/version", controller="configuration", action="version", conditions=dict( method=[ "GET" ] ) )

    webapp.finalize_config()
    # Wrap the webapp in some useful middleware
    if kwargs.get( 'middleware', True ):
        webapp = wrap_in_middleware( webapp, global_conf, **kwargs )
    if asbool( kwargs.get( 'static_enabled', True) ):
        if process_is_uwsgi:
            log.error("Static middleware is enabled in your configuration but this is a uwsgi process.  Refusing to wrap in static middleware.")
        else:
            webapp = wrap_in_static( webapp, global_conf, **kwargs )
    # Close any pooled database connections before forking
    try:
        galaxy.webapps.tool_shed.model.mapping.metadata.bind.dispose()
    except:
        log.exception("Unable to dispose of pooled tool_shed model database connections.")
    # Return
    return webapp
Example #4
0
def paste_app_factory(global_conf, **kwargs):
    """
    Return a wsgi application serving the root object
    """
    kwargs = load_app_properties(kwds=kwargs)
    # Create the Galaxy application unless passed in
    if 'app' in kwargs:
        app = kwargs.pop('app')
        galaxy.app.app = app
    else:
        try:
            app = galaxy.app.UniverseApplication(global_conf=global_conf,
                                                 **kwargs)
            galaxy.app.app = app
        except:
            import traceback
            traceback.print_exc()
            sys.exit(1)
    # Call app's shutdown method when the interpeter exits, this cleanly stops
    # the various Galaxy application daemon threads
    atexit.register(app.shutdown)
    # Create the universe WSGI application
    webapp = GalaxyWebApplication(app,
                                  session_cookie='galaxysession',
                                  name='galaxy')
    webapp.add_ui_controllers('galaxy.webapps.galaxy.controllers', app)
    # Force /history to go to view of current
    webapp.add_route('/history', controller='history', action='view')
    # Force /activate to go to the controller
    webapp.add_route('/activate', controller='user', action='activate')
    # These two routes handle our simple needs at the moment
    webapp.add_route('/async/{tool_id}/{data_id}/{data_secret}',
                     controller='async',
                     action='index',
                     tool_id=None,
                     data_id=None,
                     data_secret=None)
    webapp.add_route('/{controller}/{action}', action='index')
    webapp.add_route('/{action}', controller='root', action='index')

    # allow for subdirectories in extra_files_path
    webapp.add_route('/datasets/{dataset_id}/display/{filename:.+?}',
                     controller='dataset',
                     action='display',
                     dataset_id=None,
                     filename=None)
    webapp.add_route('/datasets/{dataset_id}/{action}/{filename}',
                     controller='dataset',
                     action='index',
                     dataset_id=None,
                     filename=None)
    webapp.add_route(
        '/display_application/{dataset_id}/{app_name}/{link_name}/{user_id}/{app_action}/{action_param}/{action_param_extra:.+?}',
        controller='dataset',
        action='display_application',
        dataset_id=None,
        user_id=None,
        app_name=None,
        link_name=None,
        app_action=None,
        action_param=None,
        action_param_extra=None)
    webapp.add_route('/u/{username}/d/{slug}/{filename}',
                     controller='dataset',
                     action='display_by_username_and_slug',
                     filename=None)
    webapp.add_route('/u/{username}/p/{slug}',
                     controller='page',
                     action='display_by_username_and_slug')
    webapp.add_route('/u/{username}/h/{slug}',
                     controller='history',
                     action='display_by_username_and_slug')
    webapp.add_route('/u/{username}/w/{slug}',
                     controller='workflow',
                     action='display_by_username_and_slug')
    webapp.add_route('/u/{username}/w/{slug}/{format}',
                     controller='workflow',
                     action='display_by_username_and_slug')
    webapp.add_route('/u/{username}/v/{slug}',
                     controller='visualization',
                     action='display_by_username_and_slug')
    webapp.add_route('/search', controller='search', action='index')

    # TODO: Refactor above routes into external method to allow testing in
    # isolation as well.
    populate_api_routes(webapp, app)

    # ==== Done
    # Indicate that all configuration settings have been provided
    webapp.finalize_config()

    # Wrap the webapp in some useful middleware
    if kwargs.get('middleware', True):
        webapp = wrap_in_middleware(webapp, global_conf, **kwargs)
    if asbool(kwargs.get('static_enabled', True)):
        if process_is_uwsgi:
            log.error(
                "Static middleware is enabled in your configuration but this is a uwsgi process.  Refusing to wrap in static middleware."
            )
        else:
            webapp = wrap_in_static(
                webapp,
                global_conf,
                plugin_frameworks=[app.visualizations_registry],
                **kwargs)
    # Close any pooled database connections before forking
    try:
        galaxy.model.mapping.metadata.bind.dispose()
    except:
        log.exception(
            "Unable to dispose of pooled galaxy model database connections.")
    try:
        # This model may not actually be bound.
        if galaxy.model.tool_shed_install.mapping.metadata.bind:
            galaxy.model.tool_shed_install.mapping.metadata.bind.dispose()
    except:
        log.exception(
            "Unable to dispose of pooled toolshed install model database connections."
        )

    if not process_is_uwsgi:
        postfork_setup()

    # Return
    return webapp
Example #5
0
def populate_api_routes(webapp, app):
    webapp.add_api_controllers('galaxy.webapps.galaxy.api', app)

    valid_history_contents_types = [
        'dataset',
        'dataset_collection',
    ]

    # Accesss HDA details via histories/{history_id}/contents/datasets/{hda_id}
    webapp.mapper.resource(
        "content_typed",
        "{type:%s}s" % "|".join(valid_history_contents_types),
        name_prefix="history_",
        controller='history_contents',
        path_prefix='/api/histories/{history_id}/contents',
        parent_resources=dict(member_name='history',
                              collection_name='histories'),
    )

    # Legacy access to HDA details via histories/{history_id}/contents/{hda_id}
    webapp.mapper.resource('content',
                           'contents',
                           controller='history_contents',
                           name_prefix='history_',
                           path_prefix='/api/histories/{history_id}',
                           parent_resources=dict(member_name='history',
                                                 collection_name='histories'))
    webapp.mapper.connect(
        "history_contents_display",
        "/api/histories/{history_id}/contents/{history_content_id}/display",
        controller="datasets",
        action="display",
        conditions=dict(method=["GET"]))
    webapp.mapper.resource('user',
                           'users',
                           controller='group_users',
                           name_prefix='group_',
                           path_prefix='/api/groups/{group_id}',
                           parent_resources=dict(member_name='group',
                                                 collection_name='groups'))
    webapp.mapper.resource('role',
                           'roles',
                           controller='group_roles',
                           name_prefix='group_',
                           path_prefix='/api/groups/{group_id}',
                           parent_resources=dict(member_name='group',
                                                 collection_name='groups'))
    _add_item_tags_controller(
        webapp,
        name_prefix="history_content_",
        path_prefix='/api/histories/{history_id}/contents/{history_content_id}'
    )
    webapp.mapper.connect('/api/histories/published',
                          action='published',
                          controller="histories",
                          conditions=dict(method=["GET"]))
    webapp.mapper.connect('/api/histories/shared_with_me',
                          action='shared_with_me',
                          controller="histories")
    _add_item_tags_controller(webapp,
                              name_prefix="history_",
                              path_prefix='/api/histories/{history_id}')
    _add_item_tags_controller(webapp,
                              name_prefix="workflow_",
                              path_prefix='/api/workflows/{workflow_id}')
    _add_item_annotation_controller(
        webapp,
        name_prefix="history_content_",
        path_prefix='/api/histories/{history_id}/contents/{history_content_id}'
    )
    _add_item_annotation_controller(webapp,
                                    name_prefix="history_",
                                    path_prefix='/api/histories/{history_id}')
    _add_item_annotation_controller(webapp,
                                    name_prefix="workflow_",
                                    path_prefix='/api/workflows/{workflow_id}')
    _add_item_provenance_controller(
        webapp,
        name_prefix="history_content_",
        path_prefix='/api/histories/{history_id}/contents/{history_content_id}'
    )

    webapp.mapper.resource('dataset', 'datasets', path_prefix='/api')
    webapp.mapper.resource('tool_data', 'tool_data', path_prefix='/api')
    webapp.mapper.connect(
        '/api/tool_data/{id:.+?}/fields/{value:.+?}/files/{path:.+?}',
        action='download_field_file',
        controller="tool_data")
    webapp.mapper.connect('/api/tool_data/{id:.+?}/fields/{value:.+?}',
                          action='show_field',
                          controller="tool_data")
    webapp.mapper.connect('/api/tool_data/{id:.+?}/reload',
                          action='reload',
                          controller="tool_data")
    webapp.mapper.resource('dataset_collection',
                           'dataset_collections',
                           path_prefix='/api/')
    webapp.mapper.resource('sample', 'samples', path_prefix='/api')
    webapp.mapper.resource('request', 'requests', path_prefix='/api')
    webapp.mapper.resource('form', 'forms', path_prefix='/api')
    webapp.mapper.resource('request_type', 'request_types', path_prefix='/api')
    webapp.mapper.resource('role', 'roles', path_prefix='/api')
    webapp.mapper.connect('/api/ftp_files', controller='remote_files')
    webapp.mapper.resource('remote_file', 'remote_files', path_prefix='/api')
    webapp.mapper.resource('group', 'groups', path_prefix='/api')
    webapp.mapper.resource_with_deleted('quota', 'quotas', path_prefix='/api')

    # =======================
    # ====== TOOLS API ======
    # =======================

    webapp.mapper.connect('/api/tools/{id:.+?}/build',
                          action='build',
                          controller="tools")
    webapp.mapper.connect('/api/tools/{id:.+?}/reload',
                          action='reload',
                          controller="tools")
    webapp.mapper.connect('/api/tools/{id:.+?}/diagnostics',
                          action='diagnostics',
                          controller="tools")
    webapp.mapper.connect('/api/tools/{id:.+?}/citations',
                          action='citations',
                          controller="tools")
    webapp.mapper.connect('/api/tools/{id:.+?}/download',
                          action='download',
                          controller="tools")
    webapp.mapper.connect('/api/tools/{id:.+?}',
                          action='show',
                          controller="tools")
    webapp.mapper.resource('tool', 'tools', path_prefix='/api')

    webapp.mapper.resource_with_deleted('user', 'users', path_prefix='/api')
    webapp.mapper.resource('genome', 'genomes', path_prefix='/api')
    webapp.mapper.resource('visualization',
                           'visualizations',
                           path_prefix='/api')
    webapp.mapper.connect('/api/workflows/build_module',
                          action='build_module',
                          controller="workflows")
    webapp.mapper.resource('workflow', 'workflows', path_prefix='/api')
    webapp.mapper.resource_with_deleted('history',
                                        'histories',
                                        path_prefix='/api')
    webapp.mapper.connect('/api/histories/{history_id}/citations',
                          action='citations',
                          controller="histories")
    webapp.mapper.connect('dynamic_tool_confs',
                          '/api/configuration/dynamic_tool_confs',
                          controller="configuration",
                          action="dynamic_tool_confs")
    webapp.mapper.connect('tool_lineages',
                          '/api/configuration/tool_lineages',
                          controller="configuration",
                          action="tool_lineages")
    webapp.mapper.resource('configuration',
                           'configuration',
                           path_prefix='/api')
    webapp.mapper.connect("configuration_version",
                          "/api/version",
                          controller="configuration",
                          action="version",
                          conditions=dict(method=["GET"]))
    webapp.mapper.resource('datatype',
                           'datatypes',
                           path_prefix='/api',
                           collection={
                               'sniffers': 'GET',
                               'mapping': 'GET',
                               'converters': 'GET',
                               'edam_formats': 'GET'
                           },
                           parent_resources=dict(member_name='datatype',
                                                 collection_name='datatypes'))
    webapp.mapper.resource('search', 'search', path_prefix='/api')
    webapp.mapper.resource('page', 'pages', path_prefix="/api")
    webapp.mapper.resource('revision',
                           'revisions',
                           path_prefix='/api/pages/{page_id}',
                           controller='page_revisions',
                           parent_resources=dict(member_name='page',
                                                 collection_name='pages'))

    webapp.mapper.connect("history_archive_export",
                          "/api/histories/{id}/exports",
                          controller="histories",
                          action="archive_export",
                          conditions=dict(method=["PUT"]))
    webapp.mapper.connect("history_archive_download",
                          "/api/histories/{id}/exports/{jeha_id}",
                          controller="histories",
                          action="archive_download",
                          conditions=dict(method=["GET"]))

    webapp.mapper.connect("create_api_key",
                          "/api/users/{user_id}/api_key",
                          controller="users",
                          action="api_key",
                          user_id=None,
                          conditions=dict(method=["POST"]))

    # visualizations registry generic template renderer
    webapp.add_route('/visualization/show/{visualization_name}',
                     controller='visualization',
                     action='render',
                     visualization_name=None)

    # Deprecated in favor of POST /api/workflows with 'workflow' in payload.
    webapp.mapper.connect('import_workflow_deprecated',
                          '/api/workflows/upload',
                          controller='workflows',
                          action='import_new_workflow_deprecated',
                          conditions=dict(method=['POST']))
    webapp.mapper.connect('workflow_dict',
                          '/api/workflows/{workflow_id}/download',
                          controller='workflows',
                          action='workflow_dict',
                          conditions=dict(method=['GET']))
    # Preserve the following download route for now for dependent applications  -- deprecate at some point
    webapp.mapper.connect('workflow_dict',
                          '/api/workflows/download/{workflow_id}',
                          controller='workflows',
                          action='workflow_dict',
                          conditions=dict(method=['GET']))
    # Deprecated in favor of POST /api/workflows with shared_workflow_id in payload.
    webapp.mapper.connect('import_shared_workflow_deprecated',
                          '/api/workflows/import',
                          controller='workflows',
                          action='import_shared_workflow_deprecated',
                          conditions=dict(method=['POST']))

    # route for creating/getting converted datasets
    webapp.mapper.connect('/api/datasets/{dataset_id}/converted',
                          controller='datasets',
                          action='converted',
                          ext=None)
    webapp.mapper.connect('/api/datasets/{dataset_id}/converted/{ext}',
                          controller='datasets',
                          action='converted')

    # API refers to usages and invocations - these mean the same thing but the
    # usage routes should be considered deprecated.
    invoke_names = {
        "invocations": "",
        "usage": "_deprecated",
    }
    for noun, suffix in invoke_names.iteritems():
        name = "%s%s" % (noun, suffix)
        webapp.mapper.connect('list_workflow_%s' % name,
                              '/api/workflows/{workflow_id}/%s' % noun,
                              controller='workflows',
                              action='index_invocations',
                              conditions=dict(method=['GET']))

        webapp.mapper.connect(
            'workflow_%s_contents' % name,
            '/api/workflows/{workflow_id}/%s/{invocation_id}' % noun,
            controller='workflows',
            action='show_invocation',
            conditions=dict(method=['GET']))

        webapp.mapper.connect(
            'cancel_workflow_%s' % name,
            '/api/workflows/{workflow_id}/%s/{invocation_id}' % noun,
            controller='workflows',
            action='cancel_invocation',
            conditions=dict(method=['DELETE']))

        webapp.mapper.connect(
            'workflow_%s_step' % name,
            '/api/workflows/{workflow_id}/%s/{invocation_id}/steps/{step_id}' %
            noun,
            controller='workflows',
            action='invocation_step',
            conditions=dict(method=['GET']))

        webapp.mapper.connect(
            'workflow_%s_step_update' % name,
            '/api/workflows/{workflow_id}/%s/{invocation_id}/steps/{step_id}' %
            noun,
            controller='workflows',
            action='update_invocation_step',
            conditions=dict(method=['PUT']))

        webapp.mapper.connect('workflow_%s' % name,
                              '/api/workflows/{workflow_id}/%s' % noun,
                              controller='workflows',
                              action='invoke',
                              conditions=dict(method=['POST']))
    # ============================
    # ===== AUTHENTICATE API =====
    # ============================

    webapp.mapper.connect('api_key_retrieval',
                          '/api/authenticate/baseauth/',
                          controller='authenticate',
                          action='get_api_key',
                          conditions=dict(method=["GET"]))

    # =======================
    # ===== LIBRARY API =====
    # =======================

    webapp.mapper.connect('update_library',
                          '/api/libraries/{id}',
                          controller='libraries',
                          action='update',
                          conditions=dict(method=["PATCH", "PUT"]))

    webapp.mapper.connect('show_library_permissions',
                          '/api/libraries/{encoded_library_id}/permissions',
                          controller='libraries',
                          action='get_permissions',
                          conditions=dict(method=["GET"]))

    webapp.mapper.connect('set_library_permissions',
                          '/api/libraries/{encoded_library_id}/permissions',
                          controller='libraries',
                          action='set_permissions',
                          conditions=dict(method=["POST"]))

    webapp.mapper.connect('show_ld_item',
                          '/api/libraries/datasets/{id}',
                          controller='lda_datasets',
                          action='show',
                          conditions=dict(method=["GET"]))

    webapp.mapper.connect('load_ld',
                          '/api/libraries/datasets/',
                          controller='lda_datasets',
                          action='load',
                          conditions=dict(method=["POST"]))

    webapp.mapper.connect(
        'show_version_of_ld_item',
        '/api/libraries/datasets/{encoded_dataset_id}/versions/{encoded_ldda_id}',
        controller='lda_datasets',
        action='show_version',
        conditions=dict(method=["GET"]))

    webapp.mapper.connect(
        'show_legitimate_lda_roles',
        '/api/libraries/datasets/{encoded_dataset_id}/permissions',
        controller='lda_datasets',
        action='show_roles',
        conditions=dict(method=["GET"]))

    webapp.mapper.connect(
        'update_lda_permissions',
        '/api/libraries/datasets/{encoded_dataset_id}/permissions',
        controller='lda_datasets',
        action='update_permissions',
        conditions=dict(method=["POST"]))

    webapp.mapper.connect('delete_lda_item',
                          '/api/libraries/datasets/{encoded_dataset_id}',
                          controller='lda_datasets',
                          action='delete',
                          conditions=dict(method=["DELETE"]))

    webapp.mapper.connect('download_lda_items',
                          '/api/libraries/datasets/download/{format}',
                          controller='lda_datasets',
                          action='download',
                          conditions=dict(method=["POST", "GET"]))

    webapp.mapper.resource_with_deleted('library',
                                        'libraries',
                                        path_prefix='/api')

    webapp.mapper.resource('content',
                           'contents',
                           controller='library_contents',
                           name_prefix='library_',
                           path_prefix='/api/libraries/{library_id}',
                           parent_resources=dict(member_name='library',
                                                 collection_name='libraries'))

    _add_item_extended_metadata_controller(
        webapp,
        name_prefix="library_dataset_",
        path_prefix='/api/libraries/{library_id}/contents/{library_content_id}'
    )

    # =======================
    # ===== FOLDERS API =====
    # =======================

    webapp.mapper.connect('add_history_datasets_to_library',
                          '/api/folders/{encoded_folder_id}/contents',
                          controller='folder_contents',
                          action='create',
                          conditions=dict(method=["POST"]))

    webapp.mapper.connect('create_folder',
                          '/api/folders/{encoded_parent_folder_id}',
                          controller='folders',
                          action='create',
                          conditions=dict(method=["POST"]))

    webapp.mapper.resource('folder', 'folders', path_prefix='/api')

    webapp.mapper.connect('show_folder_permissions',
                          '/api/folders/{encoded_folder_id}/permissions',
                          controller='folders',
                          action='get_permissions',
                          conditions=dict(method=["GET"]))

    webapp.mapper.connect('set_folder_permissions',
                          '/api/folders/{encoded_folder_id}/permissions',
                          controller='folders',
                          action='set_permissions',
                          conditions=dict(method=["POST"]))

    webapp.mapper.resource('content',
                           'contents',
                           controller='folder_contents',
                           name_prefix='folder_',
                           path_prefix='/api/folders/{folder_id}',
                           parent_resources=dict(member_name='folder',
                                                 collection_name='folders'),
                           conditions=dict(method=["GET"]))

    webapp.mapper.resource('job', 'jobs', path_prefix='/api')
    webapp.mapper.connect('job_search',
                          '/api/jobs/search',
                          controller='jobs',
                          action='search',
                          conditions=dict(method=['POST']))
    webapp.mapper.connect('job_inputs',
                          '/api/jobs/{id}/inputs',
                          controller='jobs',
                          action='inputs',
                          conditions=dict(method=['GET']))
    webapp.mapper.connect('job_outputs',
                          '/api/jobs/{id}/outputs',
                          controller='jobs',
                          action='outputs',
                          conditions=dict(method=['GET']))

    # Job files controllers. Only for consumption by remote job runners.
    webapp.mapper.resource('file',
                           'files',
                           controller="job_files",
                           name_prefix="job_",
                           path_prefix='/api/jobs/{job_id}',
                           parent_resources=dict(member_name="job",
                                                 collection_name="jobs"))

    _add_item_extended_metadata_controller(
        webapp,
        name_prefix="history_dataset_",
        path_prefix='/api/histories/{history_id}/contents/{history_content_id}'
    )

    # ====================
    # ===== TOOLSHED =====
    # ====================

    # Handle displaying tool help images and README file images contained in repositories installed from the tool shed.
    webapp.add_route(
        '/admin_toolshed/static/images/{repository_id}/{image_file:.+?}',
        controller='admin_toolshed',
        action='display_image_in_repository',
        repository_id=None,
        image_file=None)

    # Galaxy API for tool shed features.
    webapp.mapper.resource(
        'tool_shed_repository',
        'tool_shed_repositories',
        member={
            'repair_repository_revision': 'POST',
            'exported_workflows': 'GET',
            'import_workflow': 'POST',
            'import_workflows': 'POST'
        },
        collection={
            'get_latest_installable_revision': 'POST',
            'reset_metadata_on_installed_repositories': 'POST'
        },
        controller='tool_shed_repositories',
        name_prefix='tool_shed_repository_',
        path_prefix='/api',
        new={'install_repository_revision': 'POST'},
        parent_resources=dict(member_name='tool_shed_repository',
                              collection_name='tool_shed_repositories'))

    # ==== Trace/Metrics Logger
    # Connect logger from app
    if app.trace_logger:
        webapp.trace_logger = app.trace_logger

    # metrics logging API
    # webapp.mapper.connect( "index", "/api/metrics",
    #    controller="metrics", action="index", conditions=dict( method=["GET"] ) )
    # webapp.mapper.connect( "show", "/api/metrics/{id}",
    #    controller="metrics", action="show", conditions=dict( method=["GET"] ) )
    webapp.mapper.connect("create",
                          "/api/metrics",
                          controller="metrics",
                          action="create",
                          conditions=dict(method=["POST"]))
Example #6
0
def paste_app_factory( global_conf, **kwargs ):
    """
    Return a wsgi application serving the root object
    """
    kwargs = load_app_properties(
        kwds=kwargs
    )
    # Create the Galaxy application unless passed in
    if 'app' in kwargs:
        app = kwargs.pop( 'app' )
        galaxy.app.app = app
    else:
        try:
            app = galaxy.app.UniverseApplication( global_conf=global_conf, **kwargs )
            galaxy.app.app = app
        except:
            import traceback
            traceback.print_exc()
            sys.exit( 1 )
    # Call app's shutdown method when the interpeter exits, this cleanly stops
    # the various Galaxy application daemon threads
    atexit.register( app.shutdown )
    # Create the universe WSGI application
    webapp = GalaxyWebApplication( app, session_cookie='galaxysession', name='galaxy' )

    # STANDARD CONTROLLER ROUTES
    webapp.add_ui_controllers( 'galaxy.webapps.galaxy.controllers', app )
    # Force /history to go to view of current
    webapp.add_route( '/history', controller='history', action='view' )
    webapp.add_route( '/history/view/{id}', controller='history', action='view' )
    # THIS IS A TEMPORARY ROUTE FOR THE 17.01 RELEASE
    # This route supports the previous hide/delete-all-hidden functionality in a history.
    # It will be removed after 17.01.
    webapp.add_route( '/history/adjust_hidden', controller='history', action='adjust_hidden')

    # Force /activate to go to the controller
    webapp.add_route( '/activate', controller='user', action='activate' )
    webapp.add_route( '/login', controller='root', action='login' )

    # These two routes handle our simple needs at the moment
    webapp.add_route( '/async/{tool_id}/{data_id}/{data_secret}', controller='async', action='index', tool_id=None, data_id=None, data_secret=None )
    webapp.add_route( '/{controller}/{action}', action='index' )
    webapp.add_route( '/{action}', controller='root', action='index' )

    # allow for subdirectories in extra_files_path
    webapp.add_route( '/datasets/{dataset_id}/display/{filename:.+?}', controller='dataset', action='display', dataset_id=None, filename=None)
    webapp.add_route( '/datasets/{dataset_id}/{action}/{filename}', controller='dataset', action='index', dataset_id=None, filename=None)
    webapp.add_route( '/display_application/{dataset_id}/{app_name}/{link_name}/{user_id}/{app_action}/{action_param}/{action_param_extra:.+?}',
                      controller='dataset', action='display_application', dataset_id=None, user_id=None,
                      app_name=None, link_name=None, app_action=None, action_param=None, action_param_extra=None )
    webapp.add_route( '/u/{username}/d/{slug}/{filename}', controller='dataset', action='display_by_username_and_slug', filename=None )
    webapp.add_route( '/u/{username}/p/{slug}', controller='page', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/h/{slug}', controller='history', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/w/{slug}', controller='workflow', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/w/{slug}/{format}', controller='workflow', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/v/{slug}', controller='visualization', action='display_by_username_and_slug' )
    webapp.add_route( '/search', controller='search', action='index' )

    # TODO: Refactor above routes into external method to allow testing in
    # isolation as well.
    populate_api_routes( webapp, app )

    # CLIENTSIDE ROUTES
    # The following are routes that are handled completely on the clientside.
    # The following routes don't bootstrap any information, simply provide the
    # base analysis interface at which point the application takes over.

    webapp.add_client_route( '/tours' )
    webapp.add_client_route( '/tours/{tour_id}' )
    webapp.add_client_route( '/user' )
    webapp.add_client_route( '/user/{form_id}' )

    # ==== Done
    # Indicate that all configuration settings have been provided
    webapp.finalize_config()

    # Wrap the webapp in some useful middleware
    if kwargs.get( 'middleware', True ):
        webapp = wrap_in_middleware(webapp, global_conf, app.application_stack, **kwargs)
    if asbool( kwargs.get( 'static_enabled', True) ):
        webapp = wrap_if_allowed(webapp, app.application_stack, wrap_in_static,
                                 args=(global_conf,),
                                 kwargs=dict(plugin_frameworks=[app.visualizations_registry], **kwargs))
    # Close any pooled database connections before forking
    try:
        galaxy.model.mapping.metadata.bind.dispose()
    except:
        log.exception("Unable to dispose of pooled galaxy model database connections.")
    try:
        # This model may not actually be bound.
        if galaxy.model.tool_shed_install.mapping.metadata.bind:
            galaxy.model.tool_shed_install.mapping.metadata.bind.dispose()
    except:
        log.exception("Unable to dispose of pooled toolshed install model database connections.")

    app.application_stack.register_postfork_function(postfork_setup)

    for th in threading.enumerate():
        if th.is_alive():
            log.debug("Prior to webapp return, Galaxy thread %s is alive.", th)
    # Return
    return webapp
Example #7
0
def app_factory( global_conf, **kwargs ):
    """Return a wsgi application serving the root object"""
    # Create the Galaxy tool shed application unless passed in
    if 'app' in kwargs:
        app = kwargs.pop( 'app' )
    else:
        try:
            from galaxy.webapps.tool_shed.app import UniverseApplication
            app = UniverseApplication( global_conf=global_conf, **kwargs )
        except:
            import traceback, sys
            traceback.print_exc()
            sys.exit( 1 )
    atexit.register( app.shutdown )
    # Create the universe WSGI application
    webapp = CommunityWebApplication( app, session_cookie='galaxycommunitysession', name="tool_shed" )
    add_ui_controllers( webapp, app )
    webapp.add_route( '/view/{owner}', controller='repository', action='sharable_owner' )
    webapp.add_route( '/view/{owner}/{name}', controller='repository', action='sharable_repository' )
    webapp.add_route( '/view/{owner}/{name}/{changeset_revision}', controller='repository', action='sharable_repository_revision' )
    # Handle displaying tool help images and README file images for tools contained in repositories.
    webapp.add_route( '/repository/static/images/:repository_id/:image_file',
                      controller='repository',
                      action='display_image_in_repository',
                      repository_id=None,
                      image_file=None )
    webapp.add_route( '/:controller/:action', action='index' )
    webapp.add_route( '/:action', controller='repository', action='index' )
    webapp.add_route( '/repos/*path_info', controller='hg', action='handle_request', path_info='/' )
    # Add the web API.  # A good resource for RESTful services - http://routes.readthedocs.org/en/latest/restful.html
    webapp.add_api_controllers( 'galaxy.webapps.tool_shed.api', app )
    webapp.mapper.connect( 'api_key_retrieval',
                           '/api/authenticate/baseauth/',
                           controller='authenticate',
                           action='get_tool_shed_api_key',
                           conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.connect( 'repo_search',
                           '/api/search/',
                           controller='search',
                           action='search',
                           conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.resource( 'category',
                            'categories',
                            controller='categories',
                            name_prefix='category_',
                            path_prefix='/api',
                            parent_resources=dict( member_name='category', collection_name='categories' ) )
    webapp.mapper.resource( 'repository',
                            'repositories',
                            controller='repositories',
                            collection={ 'add_repository_registry_entry' : 'POST',
                                         'get_repository_revision_install_info' : 'GET',
                                         'get_ordered_installable_revisions' : 'GET',
                                         'remove_repository_registry_entry' : 'POST',
                                         'repository_ids_for_setting_metadata' : 'GET',
                                         'reset_metadata_on_repositories' : 'POST',
                                         'reset_metadata_on_repository' : 'POST' },
                            name_prefix='repository_',
                            path_prefix='/api',
                            new={ 'import_capsule' : 'POST' },
                            parent_resources=dict( member_name='repository', collection_name='repositories' ) )
    webapp.mapper.resource( 'repository_revision',
                            'repository_revisions',
                            member={ 'repository_dependencies' : 'GET',
                                     'export' : 'POST' },
                            controller='repository_revisions',
                            name_prefix='repository_revision_',
                            path_prefix='/api',
                            parent_resources=dict( member_name='repository_revision', collection_name='repository_revisions' ) )
    webapp.mapper.resource( 'user',
                            'users',
                            controller='users',
                            name_prefix='user_',
                            path_prefix='/api',
                            parent_resources=dict( member_name='user', collection_name='users' ) )
    webapp.mapper.connect( 'repository_create_changeset_revision',
                           '/api/repositories/:id/changeset_revision',
                           controller='repositories',
                           action='create_changeset_revision',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.finalize_config()
    # Wrap the webapp in some useful middleware
    if kwargs.get( 'middleware', True ):
        webapp = wrap_in_middleware( webapp, global_conf, **kwargs )
    # TEST FOR UWSGI -- TODO save this somewhere so we only have to do it once.
    is_uwsgi = False
    try:
        # The uwsgi module is automatically injected by the parent uwsgi
        # process and only exists that way.  If anything works, this is a
        # uwsgi-managed process.
        import uwsgi
        is_uwsgi = uwsgi.numproc
        is_uwsgi = True
    except ImportError:
        # This is not a uwsgi process, or something went horribly wrong.
        pass
    if asbool( kwargs.get( 'static_enabled', True) ):
        if is_uwsgi:
            log.error("Static middleware is enabled in your configuration but this is a uwsgi process.  Refusing to wrap in static middleware.")
        else:
            webapp = wrap_in_static( webapp, global_conf, **kwargs )
    # Close any pooled database connections before forking
    try:
        galaxy.webapps.tool_shed.model.mapping.metadata.bind.dispose()
    except:
        log.exception("Unable to dispose of pooled tool_shed model database connections.")
    # Return
    return webapp
Example #8
0
def app_factory( global_conf, **kwargs ):
    """Return a wsgi application serving the root object"""
    # Create the Galaxy tool shed application unless passed in
    if 'app' in kwargs:
        app = kwargs.pop( 'app' )
    else:
        try:
            from galaxy.webapps.tool_shed.app import UniverseApplication
            app = UniverseApplication( global_conf=global_conf, **kwargs )
        except:
            import traceback
            import sys
            traceback.print_exc()
            sys.exit( 1 )
    atexit.register( app.shutdown )
    # Create the universe WSGI application
    webapp = CommunityWebApplication( app, session_cookie='galaxycommunitysession', name="tool_shed" )
    add_ui_controllers( webapp, app )
    webapp.add_route( '/view/{owner}', controller='repository', action='sharable_owner' )
    webapp.add_route( '/view/{owner}/{name}', controller='repository', action='sharable_repository' )
    webapp.add_route( '/view/{owner}/{name}/{changeset_revision}', controller='repository', action='sharable_repository_revision' )
    # Handle displaying tool help images and README file images for tools contained in repositories.
    webapp.add_route( '/repository/static/images/{repository_id}/{image_file:.+?}',
                      controller='repository',
                      action='display_image_in_repository',
                      repository_id=None,
                      image_file=None )
    webapp.add_route( '/{controller}/{action}', action='index' )
    webapp.add_route( '/{action}', controller='repository', action='index' )
    webapp.add_route( '/repos/*path_info', controller='hg', action='handle_request', path_info='/' )
    # Add the web API.  # A good resource for RESTful services - http://routes.readthedocs.org/en/latest/restful.html
    webapp.add_api_controllers( 'galaxy.webapps.tool_shed.api', app )
    webapp.mapper.connect( 'api_key_retrieval',
                           '/api/authenticate/baseauth/',
                           controller='authenticate',
                           action='get_tool_shed_api_key',
                           conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.connect( 'group',
                           '/api/groups/',
                           controller='groups',
                           action='index',
                           conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.connect( 'group',
                           '/api/groups/',
                           controller='groups',
                           action='create',
                           conditions=dict( method=[ "POST" ] ) )
    webapp.mapper.connect( 'group',
                           '/api/groups/{encoded_id}',
                           controller='groups',
                           action='show',
                           conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.resource( 'category',
                            'categories',
                            controller='categories',
                            name_prefix='category_',
                            path_prefix='/api',
                            parent_resources=dict( member_name='category', collection_name='categories' ) )
    webapp.mapper.resource( 'repository',
                            'repositories',
                            controller='repositories',
                            collection={ 'add_repository_registry_entry' : 'POST',
                                         'get_repository_revision_install_info' : 'GET',
                                         'get_ordered_installable_revisions' : 'GET',
                                         'remove_repository_registry_entry' : 'POST',
                                         'repository_ids_for_setting_metadata' : 'GET',
                                         'reset_metadata_on_repositories' : 'POST',
                                         'reset_metadata_on_repository' : 'POST' },
                            name_prefix='repository_',
                            path_prefix='/api',
                            new={ 'import_capsule' : 'POST' },
                            parent_resources=dict( member_name='repository', collection_name='repositories' ) )
    webapp.mapper.resource( 'repository_revision',
                            'repository_revisions',
                            member={ 'repository_dependencies' : 'GET',
                                     'export' : 'POST' },
                            controller='repository_revisions',
                            name_prefix='repository_revision_',
                            path_prefix='/api',
                            parent_resources=dict( member_name='repository_revision', collection_name='repository_revisions' ) )
    webapp.mapper.resource( 'user',
                            'users',
                            controller='users',
                            name_prefix='user_',
                            path_prefix='/api',
                            parent_resources=dict( member_name='user', collection_name='users' ) )
    webapp.mapper.connect( 'update_repository',
                           '/api/repositories/{id}',
                           controller='repositories',
                           action='update',
                           conditions=dict( method=[ "PATCH", "PUT" ] ) )
    webapp.mapper.connect( 'repository_create_changeset_revision',
                           '/api/repositories/{id}/changeset_revision',
                           controller='repositories',
                           action='create_changeset_revision',
                           conditions=dict( method=[ "POST" ] ) )
    webapp.mapper.connect( 'create_repository',
                           '/api/repositories',
                           controller='repositories',
                           action='create',
                           conditions=dict( method=[ "POST" ] ) )
    webapp.mapper.connect( 'tools',
                           '/api/tools',
                           controller='tools',
                           action='index',
                           conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.connect( "version", "/api/version", controller="configuration", action="version", conditions=dict( method=[ "GET" ] ) )

    webapp.finalize_config()
    # Wrap the webapp in some useful middleware
    if kwargs.get( 'middleware', True ):
        webapp = wrap_in_middleware( webapp, global_conf, **kwargs )
    if asbool( kwargs.get( 'static_enabled', True) ):
        if process_is_uwsgi:
            log.error("Static middleware is enabled in your configuration but this is a uwsgi process.  Refusing to wrap in static middleware.")
        else:
            webapp = wrap_in_static( webapp, global_conf, **kwargs )
    # Close any pooled database connections before forking
    try:
        galaxy.webapps.tool_shed.model.mapping.metadata.bind.dispose()
    except:
        log.exception("Unable to dispose of pooled tool_shed model database connections.")
    # Return
    return webapp
Example #9
0
def app_factory(global_conf, **kwargs):
    """
    Return a wsgi application serving the root object
    """
    kwargs = load_app_properties(kwds=kwargs)
    # Create the Galaxy application unless passed in
    if 'app' in kwargs:
        app = kwargs.pop('app')
    else:
        try:
            from galaxy.app import UniverseApplication
            app = UniverseApplication(global_conf=global_conf, **kwargs)
        except:
            import traceback
            traceback.print_exc()
            sys.exit(1)
    # Call app's shutdown method when the interpeter exits, this cleanly stops
    # the various Galaxy application daemon threads
    atexit.register(app.shutdown)
    # Create the universe WSGI application
    webapp = GalaxyWebApplication(app,
                                  session_cookie='galaxysession',
                                  name='galaxy')
    webapp.add_ui_controllers('galaxy.webapps.galaxy.controllers', app)
    # Force /history to go to /root/history -- needed since the tests assume this
    webapp.add_route('/history', controller='root', action='history')
    # Force /activate to go to the controller
    webapp.add_route('/activate', controller='user', action='activate')
    # These two routes handle our simple needs at the moment
    webapp.add_route('/async/:tool_id/:data_id/:data_secret',
                     controller='async',
                     action='index',
                     tool_id=None,
                     data_id=None,
                     data_secret=None)
    webapp.add_route('/:controller/:action', action='index')
    webapp.add_route('/:action', controller='root', action='index')

    # allow for subdirectories in extra_files_path
    webapp.add_route('/datasets/:dataset_id/display/{filename:.+?}',
                     controller='dataset',
                     action='display',
                     dataset_id=None,
                     filename=None)
    webapp.add_route('/datasets/:dataset_id/:action/:filename',
                     controller='dataset',
                     action='index',
                     dataset_id=None,
                     filename=None)
    webapp.add_route(
        '/display_application/:dataset_id/:app_name/:link_name/:user_id/:app_action/:action_param',
        controller='dataset',
        action='display_application',
        dataset_id=None,
        user_id=None,
        app_name=None,
        link_name=None,
        app_action=None,
        action_param=None)
    webapp.add_route('/u/:username/d/:slug/:filename',
                     controller='dataset',
                     action='display_by_username_and_slug',
                     filename=None)
    webapp.add_route('/u/:username/p/:slug',
                     controller='page',
                     action='display_by_username_and_slug')
    webapp.add_route('/u/:username/h/:slug',
                     controller='history',
                     action='display_by_username_and_slug')
    webapp.add_route('/u/:username/w/:slug',
                     controller='workflow',
                     action='display_by_username_and_slug')
    webapp.add_route('/u/:username/w/:slug/:format',
                     controller='workflow',
                     action='display_by_username_and_slug')
    webapp.add_route('/u/:username/v/:slug',
                     controller='visualization',
                     action='display_by_username_and_slug')
    webapp.add_route('/search', controller='search', action='index')

    # TODO: Refactor above routes into external method to allow testing in
    # isolation as well.
    populate_api_routes(webapp, app)

    # ==== Done
    # Indicate that all configuration settings have been provided
    webapp.finalize_config()

    # Wrap the webapp in some useful middleware
    if kwargs.get('middleware', True):
        webapp = wrap_in_middleware(webapp, global_conf, **kwargs)
    if asbool(kwargs.get('static_enabled', True)):
        webapp = wrap_in_static(
            webapp,
            global_conf,
            plugin_frameworks=[app.visualizations_registry],
            **kwargs)
        #webapp = wrap_in_static( webapp, global_conf, plugin_frameworks=None, **kwargs )
    if asbool(kwargs.get('pack_scripts', False)):
        pack_scripts()
    # Close any pooled database connections before forking
    try:
        galaxy.model.mapping.metadata.engine.connection_provider._pool.dispose(
        )
    except:
        pass
    # Close any pooled database connections before forking
    try:
        galaxy.model.tool_shed_install.mapping.metadata.engine.connection_provider._pool.dispose(
        )
    except:
        pass

    # Return
    return webapp
Example #10
0
def populate_api_routes( webapp, app ):
    webapp.add_api_controllers( 'galaxy.webapps.galaxy.api', app )

    valid_history_contents_types = [
        'dataset',
        'dataset_collection',
    ]

    # Accesss HDA details via histories/{history_id}/contents/datasets/{hda_id}
    webapp.mapper.resource( "content_typed",
                            "{type:%s}s" % "|".join( valid_history_contents_types ),
                            name_prefix="history_",
                            controller='history_contents',
                            path_prefix='/api/histories/{history_id}/contents',
                            parent_resources=dict( member_name='history', collection_name='histories' ),
                            )

    # Legacy access to HDA details via histories/{history_id}/contents/{hda_id}
    webapp.mapper.resource( 'content',
                            'contents',
                            controller='history_contents',
                            name_prefix='history_',
                            path_prefix='/api/histories/{history_id}',
                            parent_resources=dict( member_name='history', collection_name='histories' ) )
    webapp.mapper.connect( "history_contents_display",
                           "/api/histories/{history_id}/contents/{history_content_id}/display",
                           controller="datasets",
                           action="display",
                           conditions=dict(method=["GET"]))
    webapp.mapper.resource( 'user',
                            'users',
                            controller='group_users',
                            name_prefix='group_',
                            path_prefix='/api/groups/{group_id}',
                            parent_resources=dict( member_name='group', collection_name='groups' ) )
    webapp.mapper.resource( 'role',
                            'roles',
                            controller='group_roles',
                            name_prefix='group_',
                            path_prefix='/api/groups/{group_id}',
                            parent_resources=dict( member_name='group', collection_name='groups' ) )
    _add_item_tags_controller( webapp,
                               name_prefix="history_content_",
                               path_prefix='/api/histories/{history_id}/contents/{history_content_id}' )
    webapp.mapper.connect( '/api/histories/published', action='published', controller="histories", conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.connect( '/api/histories/shared_with_me', action='shared_with_me', controller="histories" )
    _add_item_tags_controller( webapp,
                               name_prefix="history_",
                               path_prefix='/api/histories/{history_id}' )
    _add_item_tags_controller( webapp,
                               name_prefix="workflow_",
                               path_prefix='/api/workflows/{workflow_id}' )
    _add_item_annotation_controller( webapp,
                                     name_prefix="history_content_",
                                     path_prefix='/api/histories/{history_id}/contents/{history_content_id}' )
    _add_item_annotation_controller( webapp,
                                     name_prefix="history_",
                                     path_prefix='/api/histories/{history_id}' )
    _add_item_annotation_controller( webapp,
                                     name_prefix="workflow_",
                                     path_prefix='/api/workflows/{workflow_id}' )
    _add_item_provenance_controller( webapp,
                                     name_prefix="history_content_",
                                     path_prefix='/api/histories/{history_id}/contents/{history_content_id}' )

    webapp.mapper.resource( 'dataset', 'datasets', path_prefix='/api' )
    webapp.mapper.resource( 'tool_data', 'tool_data', path_prefix='/api' )
    webapp.mapper.connect( '/api/tool_data/{id:.+?}/fields/{value:.+?}/files/{path:.+?}', action='download_field_file', controller="tool_data" )
    webapp.mapper.connect( '/api/tool_data/{id:.+?}/fields/{value:.+?}', action='show_field', controller="tool_data" )
    webapp.mapper.connect( '/api/tool_data/{id:.+?}/reload', action='reload', controller="tool_data" )
    webapp.mapper.resource( 'dataset_collection', 'dataset_collections', path_prefix='/api/')
    webapp.mapper.resource( 'sample', 'samples', path_prefix='/api' )
    webapp.mapper.resource( 'request', 'requests', path_prefix='/api' )
    webapp.mapper.resource( 'form', 'forms', path_prefix='/api' )
    webapp.mapper.resource( 'request_type', 'request_types', path_prefix='/api' )
    webapp.mapper.resource( 'role', 'roles', path_prefix='/api' )
    webapp.mapper.connect( '/api/ftp_files', controller='remote_files' )
    webapp.mapper.resource( 'remote_file', 'remote_files', path_prefix='/api' )
    webapp.mapper.resource( 'group', 'groups', path_prefix='/api' )
    webapp.mapper.resource_with_deleted( 'quota', 'quotas', path_prefix='/api' )

    # =======================
    # ====== TOOLS API ======
    # =======================

    webapp.mapper.connect( '/api/tools/{id:.+?}/build', action='build', controller="tools" )
    webapp.mapper.connect( '/api/tools/{id:.+?}/reload', action='reload', controller="tools" )
    webapp.mapper.connect( '/api/tools/{id:.+?}/diagnostics', action='diagnostics', controller="tools" )
    webapp.mapper.connect( '/api/tools/{id:.+?}/citations', action='citations', controller="tools" )
    webapp.mapper.connect( '/api/tools/{id:.+?}/download', action='download', controller="tools" )
    webapp.mapper.connect( '/api/tools/{id:.+?}', action='show', controller="tools" )
    webapp.mapper.resource( 'tool', 'tools', path_prefix='/api' )

    webapp.mapper.resource_with_deleted( 'user', 'users', path_prefix='/api' )
    webapp.mapper.resource( 'genome', 'genomes', path_prefix='/api' )
    webapp.mapper.resource( 'visualization', 'visualizations', path_prefix='/api' )
    webapp.mapper.connect( '/api/workflows/build_module', action='build_module', controller="workflows" )
    webapp.mapper.resource( 'workflow', 'workflows', path_prefix='/api' )
    webapp.mapper.resource_with_deleted( 'history', 'histories', path_prefix='/api' )
    webapp.mapper.connect( '/api/histories/{history_id}/citations', action='citations', controller="histories" )
    webapp.mapper.connect(
        'dynamic_tool_confs',
        '/api/configuration/dynamic_tool_confs',
        controller="configuration",
        action="dynamic_tool_confs"
    )
    webapp.mapper.connect(
        'tool_lineages',
        '/api/configuration/tool_lineages',
        controller="configuration",
        action="tool_lineages"
    )
    webapp.mapper.resource( 'configuration', 'configuration', path_prefix='/api' )
    webapp.mapper.connect( "configuration_version",
                           "/api/version", controller="configuration",
                           action="version", conditions=dict( method=[ "GET" ] ) )
    webapp.mapper.resource( 'datatype',
                            'datatypes',
                            path_prefix='/api',
                            collection={ 'sniffers': 'GET', 'mapping': 'GET', 'converters': 'GET', 'edam_formats': 'GET' },
                            parent_resources=dict( member_name='datatype', collection_name='datatypes' ) )
    webapp.mapper.resource( 'search', 'search', path_prefix='/api' )
    webapp.mapper.resource( 'page', 'pages', path_prefix="/api")
    webapp.mapper.resource( 'revision', 'revisions',
                            path_prefix='/api/pages/{page_id}',
                            controller='page_revisions',
                            parent_resources=dict( member_name='page', collection_name='pages' ) )

    webapp.mapper.connect( "history_archive_export",
                           "/api/histories/{id}/exports", controller="histories",
                           action="archive_export", conditions=dict( method=[ "PUT" ] ) )
    webapp.mapper.connect( "history_archive_download",
                           "/api/histories/{id}/exports/{jeha_id}", controller="histories",
                           action="archive_download", conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( "create_api_key", "/api/users/{user_id}/api_key",
                           controller="users", action="api_key", user_id=None,
                           conditions=dict( method=["POST"] ) )

    # visualizations registry generic template renderer
    webapp.add_route( '/visualization/show/{visualization_name}', controller='visualization', action='render', visualization_name=None )

    # Deprecated in favor of POST /api/workflows with 'workflow' in payload.
    webapp.mapper.connect( 'import_workflow_deprecated',
                           '/api/workflows/upload',
                           controller='workflows',
                           action='import_new_workflow_deprecated',
                           conditions=dict( method=['POST'] ) )
    webapp.mapper.connect( 'workflow_dict',
                           '/api/workflows/{workflow_id}/download',
                           controller='workflows',
                           action='workflow_dict',
                           conditions=dict( method=['GET'] ) )
    # Preserve the following download route for now for dependent applications  -- deprecate at some point
    webapp.mapper.connect( 'workflow_dict',
                           '/api/workflows/download/{workflow_id}',
                           controller='workflows',
                           action='workflow_dict',
                           conditions=dict( method=['GET'] ) )
    # Deprecated in favor of POST /api/workflows with shared_workflow_id in payload.
    webapp.mapper.connect( 'import_shared_workflow_deprecated',
                           '/api/workflows/import',
                           controller='workflows',
                           action='import_shared_workflow_deprecated',
                           conditions=dict( method=['POST'] ) )

    # route for creating/getting converted datasets
    webapp.mapper.connect( '/api/datasets/{dataset_id}/converted', controller='datasets', action='converted', ext=None )
    webapp.mapper.connect( '/api/datasets/{dataset_id}/converted/{ext}', controller='datasets', action='converted' )

    # API refers to usages and invocations - these mean the same thing but the
    # usage routes should be considered deprecated.
    invoke_names = {
        "invocations": "",
        "usage": "_deprecated",
    }
    for noun, suffix in invoke_names.iteritems():
        name = "%s%s" % (noun, suffix)
        webapp.mapper.connect(
            'list_workflow_%s' % name,
            '/api/workflows/{workflow_id}/%s' % noun,
            controller='workflows',
            action='index_invocations',
            conditions=dict(method=['GET'])
        )

        webapp.mapper.connect(
            'workflow_%s_contents' % name,
            '/api/workflows/{workflow_id}/%s/{invocation_id}' % noun,
            controller='workflows',
            action='show_invocation',
            conditions=dict(method=['GET'])
        )

        webapp.mapper.connect(
            'cancel_workflow_%s' % name,
            '/api/workflows/{workflow_id}/%s/{invocation_id}' % noun,
            controller='workflows',
            action='cancel_invocation',
            conditions=dict(method=['DELETE'])
        )

        webapp.mapper.connect(
            'workflow_%s_step' % name,
            '/api/workflows/{workflow_id}/%s/{invocation_id}/steps/{step_id}' % noun,
            controller='workflows',
            action='invocation_step',
            conditions=dict(method=['GET'])
        )

        webapp.mapper.connect(
            'workflow_%s_step_update' % name,
            '/api/workflows/{workflow_id}/%s/{invocation_id}/steps/{step_id}' % noun,
            controller='workflows',
            action='update_invocation_step',
            conditions=dict(method=['PUT'])
        )

        webapp.mapper.connect(
            'workflow_%s' % name,
            '/api/workflows/{workflow_id}/%s' % noun,
            controller='workflows',
            action='invoke',
            conditions=dict( method=['POST'] )
        )
    # ============================
    # ===== AUTHENTICATE API =====
    # ============================

    webapp.mapper.connect( 'api_key_retrieval',
                           '/api/authenticate/baseauth/',
                           controller='authenticate',
                           action='get_api_key',
                           conditions=dict( method=[ "GET" ] ) )

    # =======================
    # ===== LIBRARY API =====
    # =======================

    webapp.mapper.connect( 'update_library',
                           '/api/libraries/{id}',
                           controller='libraries',
                           action='update',
                           conditions=dict( method=[ "PATCH", "PUT" ] ) )

    webapp.mapper.connect( 'show_library_permissions',
                           '/api/libraries/{encoded_library_id}/permissions',
                           controller='libraries',
                           action='get_permissions',
                           conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( 'set_library_permissions',
                           '/api/libraries/{encoded_library_id}/permissions',
                           controller='libraries',
                           action='set_permissions',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.connect( 'show_ld_item',
                           '/api/libraries/datasets/{id}',
                           controller='lda_datasets',
                           action='show',
                           conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( 'load_ld',
                           '/api/libraries/datasets/',
                           controller='lda_datasets',
                           action='load',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.connect( 'show_version_of_ld_item',
                           '/api/libraries/datasets/{encoded_dataset_id}/versions/{encoded_ldda_id}',
                           controller='lda_datasets',
                           action='show_version',
                           conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( 'show_legitimate_lda_roles',
                           '/api/libraries/datasets/{encoded_dataset_id}/permissions',
                           controller='lda_datasets',
                           action='show_roles',
                           conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( 'update_lda_permissions',
                           '/api/libraries/datasets/{encoded_dataset_id}/permissions',
                           controller='lda_datasets',
                           action='update_permissions',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.connect( 'delete_lda_item',
                           '/api/libraries/datasets/{encoded_dataset_id}',
                           controller='lda_datasets',
                           action='delete',
                           conditions=dict( method=[ "DELETE" ] ) )

    webapp.mapper.connect( 'download_lda_items',
                           '/api/libraries/datasets/download/{format}',
                           controller='lda_datasets',
                           action='download',
                           conditions=dict( method=[ "POST", "GET" ] ) )

    webapp.mapper.resource_with_deleted( 'library',
                                         'libraries',
                                         path_prefix='/api' )

    webapp.mapper.resource( 'content',
                            'contents',
                            controller='library_contents',
                            name_prefix='library_',
                            path_prefix='/api/libraries/{library_id}',
                            parent_resources=dict( member_name='library', collection_name='libraries' ) )

    _add_item_extended_metadata_controller( webapp,
                                            name_prefix="library_dataset_",
                                            path_prefix='/api/libraries/{library_id}/contents/{library_content_id}' )

    # =======================
    # ===== FOLDERS API =====
    # =======================

    webapp.mapper.connect( 'add_history_datasets_to_library',
                           '/api/folders/{encoded_folder_id}/contents',
                           controller='folder_contents',
                           action='create',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.connect( 'create_folder',
                           '/api/folders/{encoded_parent_folder_id}',
                           controller='folders',
                           action='create',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.connect( 'delete_folder',
                           '/api/folders/{encoded_folder_id}',
                           controller='folders',
                           action='delete',
                           conditions=dict( method=[ "DELETE" ] ) )

    webapp.mapper.connect( 'update_folder',
                           '/api/folders/{encoded_folder_id}',
                           controller='folders',
                           action='update',
                           conditions=dict( method=[ "PATCH", "PUT" ] ) )

    webapp.mapper.resource( 'folder',
                            'folders',
                            path_prefix='/api' )

    webapp.mapper.connect( 'show_folder_permissions',
                           '/api/folders/{encoded_folder_id}/permissions',
                           controller='folders',
                           action='get_permissions',
                           conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( 'set_folder_permissions',
                           '/api/folders/{encoded_folder_id}/permissions',
                           controller='folders',
                           action='set_permissions',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.resource( 'content',
                            'contents',
                            controller='folder_contents',
                            name_prefix='folder_',
                            path_prefix='/api/folders/{folder_id}',
                            parent_resources=dict( member_name='folder', collection_name='folders' ),
                            conditions=dict( method=[ "GET" ] )  )

    webapp.mapper.resource( 'job',
                            'jobs',
                            path_prefix='/api' )
    webapp.mapper.connect( 'job_search', '/api/jobs/search', controller='jobs', action='search', conditions=dict( method=['POST'] ) )
    webapp.mapper.connect( 'job_inputs', '/api/jobs/{id}/inputs', controller='jobs', action='inputs', conditions=dict( method=['GET'] ) )
    webapp.mapper.connect( 'job_outputs', '/api/jobs/{id}/outputs', controller='jobs', action='outputs', conditions=dict( method=['GET'] ) )
    webapp.mapper.connect( 'build_for_rerun', '/api/jobs/{id}/build_for_rerun', controller='jobs', action='build_for_rerun', conditions=dict( method=['GET'] ) )

    # Job files controllers. Only for consumption by remote job runners.
    webapp.mapper.resource( 'file',
                            'files',
                            controller="job_files",
                            name_prefix="job_",
                            path_prefix='/api/jobs/{job_id}',
                            parent_resources=dict( member_name="job", collection_name="jobs" ) )

    _add_item_extended_metadata_controller( webapp,
                                            name_prefix="history_dataset_",
                                            path_prefix='/api/histories/{history_id}/contents/{history_content_id}' )

    # ====================
    # ===== TOOLSHED =====
    # ====================

    # Handle displaying tool help images and README file images contained in repositories installed from the tool shed.
    webapp.add_route( '/admin_toolshed/static/images/{repository_id}/{image_file:.+?}',
                      controller='admin_toolshed',
                      action='display_image_in_repository',
                      repository_id=None,
                      image_file=None )

    # Galaxy API for tool shed features.
    webapp.mapper.resource( 'tool_shed_repository',
                            'tool_shed_repositories',
                            member={ 'repair_repository_revision': 'POST',
                                     'exported_workflows': 'GET',
                                     'import_workflow': 'POST',
                                     'import_workflows': 'POST' },
                            collection={ 'get_latest_installable_revision': 'POST',
                                         'reset_metadata_on_installed_repositories': 'POST' },
                            controller='tool_shed_repositories',
                            name_prefix='tool_shed_repository_',
                            path_prefix='/api',
                            new={ 'install_repository_revision': 'POST' },
                            parent_resources=dict( member_name='tool_shed_repository', collection_name='tool_shed_repositories' ) )

    # ==== Trace/Metrics Logger
    # Connect logger from app
    if app.trace_logger:
        webapp.trace_logger = app.trace_logger

    # metrics logging API
    # webapp.mapper.connect( "index", "/api/metrics",
    #    controller="metrics", action="index", conditions=dict( method=["GET"] ) )
    # webapp.mapper.connect( "show", "/api/metrics/{id}",
    #    controller="metrics", action="show", conditions=dict( method=["GET"] ) )
    webapp.mapper.connect( "create", "/api/metrics", controller="metrics",
                           action="create", conditions=dict( method=["POST"] ) )
Example #11
0
def paste_app_factory( global_conf, **kwargs ):
    """
    Return a wsgi application serving the root object
    """
    kwargs = load_app_properties(
        kwds=kwargs
    )
    # Create the Galaxy application unless passed in
    if 'app' in kwargs:
        app = kwargs.pop( 'app' )
        galaxy.app.app = app
    else:
        try:
            app = galaxy.app.UniverseApplication( global_conf=global_conf, **kwargs )
            galaxy.app.app = app
        except:
            import traceback
            traceback.print_exc()
            sys.exit( 1 )
    # Call app's shutdown method when the interpeter exits, this cleanly stops
    # the various Galaxy application daemon threads
    atexit.register( app.shutdown )
    # Create the universe WSGI application
    webapp = GalaxyWebApplication( app, session_cookie='galaxysession', name='galaxy' )

    webapp.add_ui_controllers( 'galaxy.webapps.galaxy.controllers', app )
    # Force /history to go to view of current
    webapp.add_route( '/history', controller='history', action='view' )
    # Force /activate to go to the controller
    webapp.add_route( '/activate', controller='user', action='activate' )
    webapp.add_route( '/login', controller='root', action='login' )

    # These two routes handle our simple needs at the moment
    webapp.add_route( '/async/{tool_id}/{data_id}/{data_secret}', controller='async', action='index', tool_id=None, data_id=None, data_secret=None )
    webapp.add_route( '/{controller}/{action}', action='index' )
    webapp.add_route( '/{action}', controller='root', action='index' )

    # allow for subdirectories in extra_files_path
    webapp.add_route( '/datasets/{dataset_id}/display/{filename:.+?}', controller='dataset', action='display', dataset_id=None, filename=None)
    webapp.add_route( '/datasets/{dataset_id}/{action}/{filename}', controller='dataset', action='index', dataset_id=None, filename=None)
    webapp.add_route( '/display_application/{dataset_id}/{app_name}/{link_name}/{user_id}/{app_action}/{action_param}/{action_param_extra:.+?}',
                      controller='dataset', action='display_application', dataset_id=None, user_id=None,
                      app_name=None, link_name=None, app_action=None, action_param=None, action_param_extra=None )
    webapp.add_route( '/u/{username}/d/{slug}/{filename}', controller='dataset', action='display_by_username_and_slug', filename=None )
    webapp.add_route( '/u/{username}/p/{slug}', controller='page', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/h/{slug}', controller='history', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/w/{slug}', controller='workflow', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/w/{slug}/{format}', controller='workflow', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/v/{slug}', controller='visualization', action='display_by_username_and_slug' )
    webapp.add_route( '/search', controller='search', action='index' )

    # TODO: Refactor above routes into external method to allow testing in
    # isolation as well.
    populate_api_routes( webapp, app )

    # ==== Done
    # Indicate that all configuration settings have been provided
    webapp.finalize_config()

    # Wrap the webapp in some useful middleware
    if kwargs.get( 'middleware', True ):
        webapp = wrap_in_middleware( webapp, global_conf, **kwargs )
    if asbool( kwargs.get( 'static_enabled', True) ):
        if process_is_uwsgi:
            log.error("Static middleware is enabled in your configuration but this is a uwsgi process.  Refusing to wrap in static middleware.")
        else:
            webapp = wrap_in_static( webapp, global_conf, plugin_frameworks=[ app.visualizations_registry ], **kwargs )
    # Close any pooled database connections before forking
    try:
        galaxy.model.mapping.metadata.bind.dispose()
    except:
        log.exception("Unable to dispose of pooled galaxy model database connections.")
    try:
        # This model may not actually be bound.
        if galaxy.model.tool_shed_install.mapping.metadata.bind:
            galaxy.model.tool_shed_install.mapping.metadata.bind.dispose()
    except:
        log.exception("Unable to dispose of pooled toolshed install model database connections.")

    if not process_is_uwsgi:
        postfork_setup()

    # Return
    return webapp
def app_factory( global_conf, **kwargs ):
    """
    Return a wsgi application serving the root object
    """
    # Create the Galaxy application unless passed in
    if 'app' in kwargs:
        app = kwargs.pop( 'app' )
    else:
        try:
            from galaxy.app import UniverseApplication
            app = UniverseApplication( global_conf = global_conf, **kwargs )
        except:
            import traceback
            traceback.print_exc()
            sys.exit( 1 )
    # Call app's shutdown method when the interpeter exits, this cleanly stops
    # the various Galaxy application daemon threads
    atexit.register( app.shutdown )
    # Create the universe WSGI application
    webapp = GalaxyWebApplication( app, session_cookie='galaxysession', name='galaxy' )
    webapp.add_ui_controllers( 'galaxy.webapps.galaxy.controllers', app )
    # Force /history to go to /root/history -- needed since the tests assume this
    webapp.add_route( '/history', controller='root', action='history' )
    # Force /activate to go to the controller
    webapp.add_route( '/activate', controller='user', action='activate' )
    # These two routes handle our simple needs at the moment
    webapp.add_route( '/async/:tool_id/:data_id/:data_secret', controller='async', action='index', tool_id=None, data_id=None, data_secret=None )
    webapp.add_route( '/:controller/:action', action='index' )
    webapp.add_route( '/:action', controller='root', action='index' )

    # allow for subdirectories in extra_files_path
    webapp.add_route( '/datasets/:dataset_id/display/{filename:.+?}', controller='dataset', action='display', dataset_id=None, filename=None)
    webapp.add_route( '/datasets/:dataset_id/:action/:filename', controller='dataset', action='index', dataset_id=None, filename=None)
    webapp.add_route( '/display_application/:dataset_id/:app_name/:link_name/:user_id/:app_action/:action_param',
        controller='dataset', action='display_application', dataset_id=None, user_id=None,
        app_name = None, link_name = None, app_action = None, action_param = None )
    webapp.add_route( '/u/:username/d/:slug/:filename', controller='dataset', action='display_by_username_and_slug', filename=None )
    webapp.add_route( '/u/:username/p/:slug', controller='page', action='display_by_username_and_slug' )
    webapp.add_route( '/u/:username/h/:slug', controller='history', action='display_by_username_and_slug' )
    webapp.add_route( '/u/:username/w/:slug', controller='workflow', action='display_by_username_and_slug' )
    webapp.add_route( '/u/:username/w/:slug/:format', controller='workflow', action='display_by_username_and_slug' )
    webapp.add_route( '/u/:username/v/:slug', controller='visualization', action='display_by_username_and_slug' )
    webapp.add_route( '/search', controller='search', action='index' )

    # TODO: Refactor above routes into external method to allow testing in
    # isolation as well.
    populate_api_routes( webapp, app )

    # ==== Done
    # Indicate that all configuration settings have been provided
    webapp.finalize_config()

    # Wrap the webapp in some useful middleware
    if kwargs.get( 'middleware', True ):
        webapp = wrap_in_middleware( webapp, global_conf, **kwargs )
    if asbool( kwargs.get( 'static_enabled', True ) ):
        webapp = wrap_in_static( webapp, global_conf, plugin_frameworks=[ app.visualizations_registry ], **kwargs )
        #webapp = wrap_in_static( webapp, global_conf, plugin_frameworks=None, **kwargs )
    if asbool(kwargs.get('pack_scripts', False)):
        pack_scripts()
    # Close any pooled database connections before forking
    try:
        galaxy.model.mapping.metadata.engine.connection_provider._pool.dispose()
    except:
        pass
     # Close any pooled database connections before forking
    try:
        galaxy.model.tool_shed_install.mapping.metadata.engine.connection_provider._pool.dispose()
    except:
        pass

    # Return
    return webapp
def populate_api_routes( webapp, app ):
    webapp.add_api_controllers( 'galaxy.webapps.galaxy.api', app )

    valid_history_contents_types = [
        'dataset',
        'dataset_collection',
    ]

    # Accesss HDA details via histories/:history_id/contents/datasets/:hda_id
    webapp.mapper.resource( "content_typed",
                            "{type:%s}s" % "|".join( valid_history_contents_types ),
                            name_prefix="history_",
                            controller='history_contents',
                            path_prefix='/api/histories/:history_id/contents',
                            parent_resources=dict( member_name='history', collection_name='histories' ),
                          )

    # Legacy access to HDA details via histories/:history_id/contents/:hda_id
    webapp.mapper.resource( 'content',
                                'contents',
                                controller='history_contents',
                                name_prefix='history_',
                                path_prefix='/api/histories/:history_id',
                                parent_resources=dict( member_name='history', collection_name='histories' ) )
    webapp.mapper.connect("history_contents_display",
                              "/api/histories/:history_id/contents/:history_content_id/display",
                              controller="datasets",
                              action="display",
                              conditions=dict(method=["GET"]))
    webapp.mapper.resource( 'user',
                                'users',
                                controller='group_users',
                                name_prefix='group_',
                                path_prefix='/api/groups/:group_id',
                                parent_resources=dict( member_name='group', collection_name='groups' ) )
    webapp.mapper.resource( 'role',
                                'roles',
                                controller='group_roles',
                                name_prefix='group_',
                                path_prefix='/api/groups/:group_id',
                                parent_resources=dict( member_name='group', collection_name='groups' ) )
    _add_item_tags_controller( webapp,
                               name_prefix="history_content_",
                               path_prefix='/api/histories/:history_id/contents/:history_content_id' )
    _add_item_tags_controller( webapp,
                               name_prefix="history_",
                               path_prefix='/api/histories/:history_id' )
    _add_item_tags_controller( webapp,
                               name_prefix="workflow_",
                               path_prefix='/api/workflows/:workflow_id' )
    _add_item_annotation_controller( webapp,
                               name_prefix="history_content_",
                               path_prefix='/api/histories/:history_id/contents/:history_content_id' )
    _add_item_annotation_controller( webapp,
                               name_prefix="history_",
                               path_prefix='/api/histories/:history_id' )
    _add_item_annotation_controller( webapp,
                               name_prefix="workflow_",
                               path_prefix='/api/workflows/:workflow_id' )
    _add_item_provenance_controller( webapp,
                               name_prefix="history_content_",
                               path_prefix='/api/histories/:history_id/contents/:history_content_id' )

    webapp.mapper.resource( 'dataset', 'datasets', path_prefix='/api' )
    webapp.mapper.resource( 'dataset_collection', 'dataset_collections', path_prefix='/api/')
    webapp.mapper.resource( 'sample', 'samples', path_prefix='/api' )
    webapp.mapper.resource( 'request', 'requests', path_prefix='/api' )
    webapp.mapper.resource( 'form', 'forms', path_prefix='/api' )
    webapp.mapper.resource( 'request_type', 'request_types', path_prefix='/api' )
    webapp.mapper.resource( 'role', 'roles', path_prefix='/api' )
    webapp.mapper.resource( 'ftp_file', 'ftp_files', path_prefix='/api' )
    webapp.mapper.resource( 'group', 'groups', path_prefix='/api' )
    webapp.mapper.resource_with_deleted( 'quota', 'quotas', path_prefix='/api' )
    webapp.mapper.connect( '/api/tools/{id:.+?}/citations', action='citations', controller="tools" )
    webapp.mapper.connect( '/api/tools/{id:.+?}', action='show', controller="tools" )
    webapp.mapper.resource( 'tool', 'tools', path_prefix='/api' )
    webapp.mapper.resource_with_deleted( 'user', 'users', path_prefix='/api' )
    webapp.mapper.resource( 'genome', 'genomes', path_prefix='/api' )
    webapp.mapper.resource( 'visualization', 'visualizations', path_prefix='/api' )
    webapp.mapper.resource( 'workflow', 'workflows', path_prefix='/api' )
    webapp.mapper.resource_with_deleted( 'history', 'histories', path_prefix='/api' )
    webapp.mapper.connect( '/api/histories/{history_id}/citations', action='citations', controller="histories" )
    webapp.mapper.resource( 'configuration', 'configuration', path_prefix='/api' )
    webapp.mapper.resource( 'datatype',
                            'datatypes',
                            path_prefix='/api',
                            collection={ 'sniffers': 'GET' },
                            parent_resources=dict( member_name='datatype', collection_name='datatypes' ) )
    #webapp.mapper.connect( 'run_workflow', '/api/workflow/{workflow_id}/library/{library_id}', controller='workflows', action='run', workflow_id=None, library_id=None, conditions=dict(method=["GET"]) )
    webapp.mapper.resource( 'search', 'search', path_prefix='/api' )
    webapp.mapper.resource( 'page', 'pages', path_prefix="/api")
    webapp.mapper.resource( 'revision', 'revisions',
                                path_prefix='/api/pages/:page_id',
                                controller='page_revisions',
                                parent_resources=dict( member_name='page', collection_name='pages' ) )

    webapp.mapper.connect( "history_archive_export", "/api/histories/{id}/exports",
        controller="histories", action="archive_export", conditions=dict( method=[ "PUT" ] ) )
    webapp.mapper.connect( "history_archive_download", "/api/histories/{id}/exports/{jeha_id}",
        controller="histories", action="archive_download", conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( "create_api_key", "/api/users/:user_id/api_key",
        controller="users", action="api_key", user_id=None, conditions=dict( method=["POST"] ) )

    # visualizations registry generic template renderer
    webapp.add_route( '/visualization/show/:visualization_name',
        controller='visualization', action='render', visualization_name=None )

    # Deprecated in favor of POST /api/workflows with 'workflow' in payload.
    webapp.mapper.connect( 'import_workflow_deprecated', '/api/workflows/upload', controller='workflows', action='import_new_workflow_deprecated', conditions=dict( method=['POST'] ) )
    webapp.mapper.connect( 'workflow_dict', '/api/workflows/{workflow_id}/download', controller='workflows', action='workflow_dict', conditions=dict( method=['GET'] ) )
    # Preserve the following download route for now for dependent applications  -- deprecate at some point
    webapp.mapper.connect( 'workflow_dict', '/api/workflows/download/{workflow_id}', controller='workflows', action='workflow_dict', conditions=dict( method=['GET'] ) )
    # Deprecated in favor of POST /api/workflows with shared_workflow_id in payload.
    webapp.mapper.connect( 'import_shared_workflow_deprecated', '/api/workflows/import', controller='workflows', action='import_shared_workflow_deprecated', conditions=dict( method=['POST'] ) )
    webapp.mapper.connect( 'workflow_usage', '/api/workflows/{workflow_id}/usage', controller='workflows', action='workflow_usage', conditions=dict(method=['GET']))
    webapp.mapper.connect( 'workflow_usage_contents', '/api/workflows/{workflow_id}/usage/{usage_id}', controller='workflows', action='workflow_usage_contents', conditions=dict(method=['GET']))

    # ============================
    # ===== AUTHENTICATE API =====
    # ============================

    webapp.mapper.connect( 'api_key_retrieval',
                           '/api/authenticate/baseauth/',
                           controller='authenticate',
                           action='get_api_key',
                           conditions=dict( method=[ "GET" ] ) )

    # =======================
    # ===== LIBRARY API =====
    # =======================

    webapp.mapper.connect( 'update_library',
                           '/api/libraries/:id',
                           controller='libraries',
                           action='update',
                           conditions=dict( method=[ "PATCH", "PUT" ] ) )

    webapp.mapper.connect( 'show_library_permissions',
                           '/api/libraries/:encoded_library_id/permissions',
                           controller='libraries',
                           action='get_permissions',
                           conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( 'set_library_permissions',
                           '/api/libraries/:encoded_library_id/permissions',
                           controller='libraries',
                           action='set_permissions',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.connect( 'show_ld_item',
                           '/api/libraries/datasets/:id',
                           controller='lda_datasets',
                           action='show',
                           conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( 'load_ld',
                           '/api/libraries/datasets/',
                           controller='lda_datasets',
                           action='load',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.connect( 'show_version_of_ld_item',
                           '/api/libraries/datasets/:encoded_dataset_id/versions/:encoded_ldda_id',
                           controller='lda_datasets',
                           action='show_version',
                           conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( 'show_legitimate_lda_roles',
                           '/api/libraries/datasets/:encoded_dataset_id/permissions',
                           controller='lda_datasets',
                           action='show_roles',
                           conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( 'update_lda_permissions',
                           '/api/libraries/datasets/:encoded_dataset_id/permissions',
                           controller='lda_datasets',
                           action='update_permissions',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.connect( 'delete_lda_item',
                           '/api/libraries/datasets/:encoded_dataset_id',
                           controller='lda_datasets',
                           action='delete',
                           conditions=dict( method=[ "DELETE" ] ) )

    webapp.mapper.connect( 'download_lda_items',
                           '/api/libraries/datasets/download/:format',
                           controller='lda_datasets',
                           action='download',
                           conditions=dict( method=[ "POST", "GET" ] ) )

    webapp.mapper.resource_with_deleted( 'library',
                                         'libraries',
                                         path_prefix='/api' )

    webapp.mapper.resource( 'content',
                            'contents',
                            controller='library_contents',
                            name_prefix='library_',
                            path_prefix='/api/libraries/:library_id',
                            parent_resources=dict( member_name='library', collection_name='libraries' ) )

    _add_item_extended_metadata_controller( webapp,
                                            name_prefix="library_dataset_",
                                            path_prefix='/api/libraries/:library_id/contents/:library_content_id' )

    # =======================
    # ===== FOLDERS API =====
    # =======================

    webapp.mapper.connect( 'add_history_datasets_to_library',
                           '/api/folders/:encoded_folder_id/contents',
                           controller='folder_contents',
                           action='create',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.connect( 'create_folder',
                           '/api/folders/:encoded_parent_folder_id',
                           controller='folders',
                           action='create',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.resource( 'folder',
                            'folders',
                            path_prefix='/api' )

    webapp.mapper.connect( 'show_folder_permissions',
                           '/api/folders/:encoded_folder_id/permissions',
                           controller='folders',
                           action='get_permissions',
                           conditions=dict( method=[ "GET" ] ) )

    webapp.mapper.connect( 'set_folder_permissions',
                           '/api/folders/:encoded_folder_id/permissions',
                           controller='folders',
                           action='set_permissions',
                           conditions=dict( method=[ "POST" ] ) )

    webapp.mapper.resource( 'content',
                            'contents',
                            controller='folder_contents',
                            name_prefix='folder_',
                            path_prefix='/api/folders/:folder_id',
                            parent_resources=dict( member_name='folder', collection_name='folders' ),
                            conditions=dict( method=[ "GET" ] )  )

    webapp.mapper.resource( 'job',
                            'jobs',
                            path_prefix='/api' )
    webapp.mapper.connect( 'job_search', '/api/jobs/search', controller='jobs', action='search', conditions=dict( method=['POST'] ) )
    webapp.mapper.connect( 'job_inputs', '/api/jobs/{id}/inputs', controller='jobs', action='inputs', conditions=dict( method=['GET'] ) )
    webapp.mapper.connect( 'job_outputs', '/api/jobs/{id}/outputs', controller='jobs', action='outputs', conditions=dict( method=['GET'] ) )

    # Job files controllers. Only for consumption by remote job runners.
    webapp.mapper.resource( 'file',
                            'files',
                            controller="job_files",
                            name_prefix="job_",
                            path_prefix='/api/jobs/:job_id',
                            parent_resources=dict( member_name="job", collection_name="jobs" ) )

    _add_item_extended_metadata_controller( webapp,
                               name_prefix="history_dataset_",
                               path_prefix='/api/histories/:history_id/contents/:history_content_id' )

    # ====================
    # ===== TOOLSHED =====
    # ====================

    # Handle displaying tool help images and README file images contained in repositories installed from the tool shed.
    webapp.add_route( '/admin_toolshed/static/images/:repository_id/{image_file:.+?}',
                      controller='admin_toolshed',
                      action='display_image_in_repository',
                      repository_id=None,
                      image_file=None )

    # Galaxy API for tool shed features.
    webapp.mapper.resource( 'tool_shed_repository',
                            'tool_shed_repositories',
                            member={ 'repair_repository_revision' : 'POST',
                                     'exported_workflows' : 'GET',
                                     'import_workflow' : 'POST',
                                     'import_workflows' : 'POST' },
                            collection={ 'get_latest_installable_revision' : 'POST',
                                         'reset_metadata_on_installed_repositories' : 'POST' },
                            controller='tool_shed_repositories',
                            name_prefix='tool_shed_repository_',
                            path_prefix='/api',
                            new={ 'install_repository_revision' : 'POST' },
                            parent_resources=dict( member_name='tool_shed_repository', collection_name='tool_shed_repositories' ) )


    # ==== Trace/Metrics Logger
    # Connect logger from app
    if app.trace_logger:
        webapp.trace_logger = app.trace_logger

    # metrics logging API
    #webapp.mapper.connect( "index", "/api/metrics",
    #    controller="metrics", action="index", conditions=dict( method=["GET"] ) )
    #webapp.mapper.connect( "show", "/api/metrics/{id}",
    #    controller="metrics", action="show", conditions=dict( method=["GET"] ) )
    webapp.mapper.connect( "create", "/api/metrics",
        controller="metrics", action="create", conditions=dict( method=["POST"] ) )
Example #14
0
def app_factory(global_conf, **kwargs):
    """Return a wsgi application serving the root object"""
    # Create the Galaxy tool shed application unless passed in
    if 'app' in kwargs:
        app = kwargs.pop('app')
    else:
        try:
            from galaxy.webapps.tool_shed.app import UniverseApplication
            app = UniverseApplication(global_conf=global_conf, **kwargs)
        except:
            import traceback, sys
            traceback.print_exc()
            sys.exit(1)
    atexit.register(app.shutdown)
    # Create the universe WSGI application
    webapp = CommunityWebApplication(app,
                                     session_cookie='galaxycommunitysession',
                                     name="tool_shed")
    add_ui_controllers(webapp, app)
    webapp.add_route('/view/{owner}',
                     controller='repository',
                     action='sharable_owner')
    webapp.add_route('/view/{owner}/{name}',
                     controller='repository',
                     action='sharable_repository')
    webapp.add_route('/view/{owner}/{name}/{changeset_revision}',
                     controller='repository',
                     action='sharable_repository_revision')
    # Handle displaying tool help images and README file images for tools contained in repositories.
    webapp.add_route('/repository/static/images/:repository_id/:image_file',
                     controller='repository',
                     action='display_image_in_repository',
                     repository_id=None,
                     image_file=None)
    webapp.add_route('/:controller/:action', action='index')
    webapp.add_route('/:action', controller='repository', action='index')
    webapp.add_route('/repos/*path_info',
                     controller='hg',
                     action='handle_request',
                     path_info='/')
    # Add the web API.  # A good resource for RESTful services - http://routes.readthedocs.org/en/latest/restful.html
    webapp.add_api_controllers('galaxy.webapps.tool_shed.api', app)
    webapp.mapper.connect('api_key_retrieval',
                          '/api/authenticate/baseauth/',
                          controller='authenticate',
                          action='get_tool_shed_api_key',
                          conditions=dict(method=["GET"]))
    webapp.mapper.connect('repo_search',
                          '/api/search/',
                          controller='search',
                          action='search',
                          conditions=dict(method=["GET"]))
    webapp.mapper.resource('category',
                           'categories',
                           controller='categories',
                           name_prefix='category_',
                           path_prefix='/api',
                           parent_resources=dict(member_name='category',
                                                 collection_name='categories'))
    webapp.mapper.resource('repository',
                           'repositories',
                           controller='repositories',
                           collection={
                               'add_repository_registry_entry': 'POST',
                               'get_repository_revision_install_info': 'GET',
                               'get_ordered_installable_revisions': 'GET',
                               'remove_repository_registry_entry': 'POST',
                               'repository_ids_for_setting_metadata': 'GET',
                               'reset_metadata_on_repositories': 'POST',
                               'reset_metadata_on_repository': 'POST'
                           },
                           name_prefix='repository_',
                           path_prefix='/api',
                           new={'import_capsule': 'POST'},
                           parent_resources=dict(
                               member_name='repository',
                               collection_name='repositories'))
    webapp.mapper.resource('repository_revision',
                           'repository_revisions',
                           member={
                               'repository_dependencies': 'GET',
                               'export': 'POST'
                           },
                           controller='repository_revisions',
                           name_prefix='repository_revision_',
                           path_prefix='/api',
                           parent_resources=dict(
                               member_name='repository_revision',
                               collection_name='repository_revisions'))
    webapp.mapper.resource('user',
                           'users',
                           controller='users',
                           name_prefix='user_',
                           path_prefix='/api',
                           parent_resources=dict(member_name='user',
                                                 collection_name='users'))
    webapp.mapper.connect('repository_create_changeset_revision',
                          '/api/repositories/:id/changeset_revision',
                          controller='repositories',
                          action='create_changeset_revision',
                          conditions=dict(method=["POST"]))
    webapp.mapper.connect('create_repository',
                          '/api/repositories',
                          controller='repositories',
                          action='create',
                          conditions=dict(method=["POST"]))

    webapp.finalize_config()
    # Wrap the webapp in some useful middleware
    if kwargs.get('middleware', True):
        webapp = wrap_in_middleware(webapp, global_conf, **kwargs)
    if asbool(kwargs.get('static_enabled', True)):
        webapp = wrap_in_static(webapp, global_conf, **kwargs)
    # Close any pooled database connections before forking
    try:
        galaxy.webapps.tool_shed.model.mapping.metadata.engine.connection_provider._pool.dispose(
        )
    except:
        pass
    # Return
    return webapp
Example #15
0
def paste_app_factory( global_conf, **kwargs ):
    """
    Return a wsgi application serving the root object
    """
    kwargs = load_app_properties(
        kwds=kwargs
    )
    # Create the Galaxy application unless passed in
    if 'app' in kwargs:
        app = kwargs.pop( 'app' )
        galaxy.app.app = app
    else:
        try:
            app = galaxy.app.UniverseApplication( global_conf=global_conf, **kwargs )
            galaxy.app.app = app
        except:
            import traceback
            traceback.print_exc()
            sys.exit( 1 )
    # Call app's shutdown method when the interpeter exits, this cleanly stops
    # the various Galaxy application daemon threads
    atexit.register( app.shutdown )
    # Create the universe WSGI application
    webapp = GalaxyWebApplication( app, session_cookie='galaxysession', name='galaxy' )

    # STANDARD CONTROLLER ROUTES
    webapp.add_ui_controllers( 'galaxy.webapps.galaxy.controllers', app )
    # Force /history to go to view of current
    webapp.add_route( '/history', controller='history', action='view' )
    webapp.add_route( '/history/view/{id}', controller='history', action='view' )

    # Force /activate to go to the controller
    webapp.add_route( '/activate', controller='user', action='activate' )

    # These two routes handle our simple needs at the moment
    webapp.add_route( '/async/{tool_id}/{data_id}/{data_secret}', controller='async', action='index', tool_id=None, data_id=None, data_secret=None )
    webapp.add_route( '/{controller}/{action}', action='index' )
    webapp.add_route( '/{action}', controller='root', action='index' )

    # allow for subdirectories in extra_files_path
    webapp.add_route( '/datasets/{dataset_id}/display/{filename:.+?}', controller='dataset', action='display', dataset_id=None, filename=None)
    webapp.add_route( '/datasets/{dataset_id}/{action}/{filename}', controller='dataset', action='index', dataset_id=None, filename=None)
    webapp.add_route( '/display_application/{dataset_id}/{app_name}/{link_name}/{user_id}/{app_action}/{action_param}/{action_param_extra:.+?}',
                      controller='dataset', action='display_application', dataset_id=None, user_id=None,
                      app_name=None, link_name=None, app_action=None, action_param=None, action_param_extra=None )
    webapp.add_route( '/u/{username}/d/{slug}/{filename}', controller='dataset', action='display_by_username_and_slug', filename=None )
    webapp.add_route( '/u/{username}/p/{slug}', controller='page', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/h/{slug}', controller='history', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/w/{slug}', controller='workflow', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/w/{slug}/{format}', controller='workflow', action='display_by_username_and_slug' )
    webapp.add_route( '/u/{username}/v/{slug}', controller='visualization', action='display_by_username_and_slug' )

    # TODO: Refactor above routes into external method to allow testing in
    # isolation as well.
    populate_api_routes( webapp, app )

    # CLIENTSIDE ROUTES
    # The following are routes that are handled completely on the clientside.
    # The following routes don't bootstrap any information, simply provide the
    # base analysis interface at which point the application takes over.

    webapp.add_client_route( '/tours' )
    webapp.add_client_route( '/tours/{tour_id}' )
    webapp.add_client_route( '/user' )
    webapp.add_client_route( '/user/{form_id}' )
    webapp.add_client_route( '/custom_builds' )

    # ==== Done
    # Indicate that all configuration settings have been provided
    webapp.finalize_config()

    # Wrap the webapp in some useful middleware
    if kwargs.get( 'middleware', True ):
        webapp = wrap_in_middleware(webapp, global_conf, app.application_stack, **kwargs)
    if asbool( kwargs.get( 'static_enabled', True) ):
        webapp = wrap_if_allowed(webapp, app.application_stack, wrap_in_static,
                                 args=(global_conf,),
                                 kwargs=dict(plugin_frameworks=[app.visualizations_registry], **kwargs))
    # Close any pooled database connections before forking
    try:
        galaxy.model.mapping.metadata.bind.dispose()
    except:
        log.exception("Unable to dispose of pooled galaxy model database connections.")
    try:
        # This model may not actually be bound.
        if galaxy.model.tool_shed_install.mapping.metadata.bind:
            galaxy.model.tool_shed_install.mapping.metadata.bind.dispose()
    except:
        log.exception("Unable to dispose of pooled toolshed install model database connections.")

    app.application_stack.register_postfork_function(postfork_setup)

    for th in threading.enumerate():
        if th.is_alive():
            log.debug("Prior to webapp return, Galaxy thread %s is alive.", th)
    # Return
    return webapp
Example #16
0
def app_factory(global_conf, **kwargs):
    """Return a wsgi application serving the root object"""
    # Create the Galaxy tool shed application unless passed in
    if 'app' in kwargs:
        app = kwargs.pop('app')
    else:
        try:
            from galaxy.webapps.tool_shed.app import UniverseApplication
            app = UniverseApplication(global_conf=global_conf, **kwargs)
        except:
            import traceback, sys
            traceback.print_exc()
            sys.exit(1)
    atexit.register(app.shutdown)
    # Create the universe WSGI application
    webapp = CommunityWebApplication(app,
                                     session_cookie='galaxycommunitysession',
                                     name="tool_shed")
    add_ui_controllers(webapp, app)
    webapp.add_route('/view/{owner}',
                     controller='repository',
                     action='sharable_owner')
    webapp.add_route('/view/{owner}/{name}',
                     controller='repository',
                     action='sharable_repository')
    webapp.add_route('/view/{owner}/{name}/{changeset_revision}',
                     controller='repository',
                     action='sharable_repository_revision')
    # Handle displaying tool help images and README file images for tools contained in repositories.
    webapp.add_route('/repository/static/images/:repository_id/:image_file',
                     controller='repository',
                     action='display_image_in_repository',
                     repository_id=None,
                     image_file=None)
    webapp.add_route('/:controller/:action', action='index')
    webapp.add_route('/:action', controller='repository', action='index')
    webapp.add_route('/repos/*path_info',
                     controller='hg',
                     action='handle_request',
                     path_info='/')
    # Add the web API.  # A good resource for RESTful services - http://routes.readthedocs.org/en/latest/restful.html
    webapp.add_api_controllers('galaxy.webapps.tool_shed.api', app)
    webapp.mapper.connect('api_key_retrieval',
                          '/api/authenticate/baseauth/',
                          controller='authenticate',
                          action='get_tool_shed_api_key',
                          conditions=dict(method=["GET"]))
    webapp.mapper.connect('repo_search',
                          '/api/search/',
                          controller='search',
                          action='search',
                          conditions=dict(method=["GET"]))
    webapp.mapper.resource('category',
                           'categories',
                           controller='categories',
                           name_prefix='category_',
                           path_prefix='/api',
                           parent_resources=dict(member_name='category',
                                                 collection_name='categories'))
    webapp.mapper.resource('repository',
                           'repositories',
                           controller='repositories',
                           collection={
                               'add_repository_registry_entry': 'POST',
                               'get_repository_revision_install_info': 'GET',
                               'get_ordered_installable_revisions': 'GET',
                               'remove_repository_registry_entry': 'POST',
                               'repository_ids_for_setting_metadata': 'GET',
                               'reset_metadata_on_repositories': 'POST',
                               'reset_metadata_on_repository': 'POST'
                           },
                           name_prefix='repository_',
                           path_prefix='/api',
                           new={'import_capsule': 'POST'},
                           parent_resources=dict(
                               member_name='repository',
                               collection_name='repositories'))
    webapp.mapper.resource('repository_revision',
                           'repository_revisions',
                           member={
                               'repository_dependencies': 'GET',
                               'export': 'POST'
                           },
                           controller='repository_revisions',
                           name_prefix='repository_revision_',
                           path_prefix='/api',
                           parent_resources=dict(
                               member_name='repository_revision',
                               collection_name='repository_revisions'))
    webapp.mapper.resource('user',
                           'users',
                           controller='users',
                           name_prefix='user_',
                           path_prefix='/api',
                           parent_resources=dict(member_name='user',
                                                 collection_name='users'))
    webapp.mapper.connect('repository_create_changeset_revision',
                          '/api/repositories/:id/changeset_revision',
                          controller='repositories',
                          action='create_changeset_revision',
                          conditions=dict(method=["POST"]))

    webapp.finalize_config()
    # Wrap the webapp in some useful middleware
    if kwargs.get('middleware', True):
        webapp = wrap_in_middleware(webapp, global_conf, **kwargs)
    # TEST FOR UWSGI -- TODO save this somewhere so we only have to do it once.
    is_uwsgi = False
    try:
        # The uwsgi module is automatically injected by the parent uwsgi
        # process and only exists that way.  If anything works, this is a
        # uwsgi-managed process.
        import uwsgi
        is_uwsgi = uwsgi.numproc
        is_uwsgi = True
    except ImportError:
        # This is not a uwsgi process, or something went horribly wrong.
        pass
    if asbool(kwargs.get('static_enabled', True)):
        if is_uwsgi:
            log.error(
                "Static middleware is enabled in your configuration but this is a uwsgi process.  Refusing to wrap in static middleware."
            )
        else:
            webapp = wrap_in_static(webapp, global_conf, **kwargs)
    # Close any pooled database connections before forking
    try:
        galaxy.webapps.tool_shed.model.mapping.metadata.bind.dispose()
    except:
        log.exception(
            "Unable to dispose of pooled tool_shed model database connections."
        )
    # Return
    return webapp