diff --git a/lib/galaxy/webapps/tool_shed/config.py b/lib/galaxy/webapps/tool_shed/config.py index f34a2e49d87..d43437d336a 100644 --- a/lib/galaxy/webapps/tool_shed/config.py +++ b/lib/galaxy/webapps/tool_shed/config.py @@ -65,6 +65,8 @@ class Configuration( object ): self.tool_dependency_dir = None self.use_tool_dependencies = False self.update_integrated_tool_panel = False + # Galaxy flavor Docker Image + self.enable_galaxy_flavor_docker_image = string_as_bool( kwargs.get( "enable_galaxy_flavor_docker_image", "False" ) ) self.use_remote_user = string_as_bool( kwargs.get( "use_remote_user", "False" ) ) self.user_activation_on = kwargs.get( 'user_activation_on', None ) self.activation_grace_period = kwargs.get( 'activation_grace_period', None ) diff --git a/lib/galaxy/webapps/tool_shed/controllers/repository.py b/lib/galaxy/webapps/tool_shed/controllers/repository.py index 912606a256e..f74a723da55 100644 --- a/lib/galaxy/webapps/tool_shed/controllers/repository.py +++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py @@ -55,6 +55,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ): datatypes_grid = repository_grids.DatatypesGrid() deprecated_repositories_i_own_grid = repository_grids.DeprecatedRepositoriesIOwnGrid() email_alerts_repository_grid = repository_grids.EmailAlertsRepositoryGrid() + docker_image_grid = repository_grids.DockerImageGrid() install_matched_repository_grid = repository_grids.InstallMatchedRepositoryGrid() matched_repository_grid = repository_grids.MatchedRepositoryGrid() my_writable_repositories_grid = repository_grids.MyWritableRepositoriesGrid() @@ -985,6 +986,62 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ): # Do all we can to eliminate spam. return trans.show_error_message( "You must be logged in to contact the owner of a repository." ) + @web.expose + def create_galaxy_docker_image( self, trans, **kwd ): + message = kwd.get( 'message', '' ) + status = kwd.get( 'status', 'done' ) + repository_ids = util.listify( kwd.get( 'id', '' ) ) + if 'operation' in kwd: + if repository_ids: + operation = kwd[ 'operation' ].lower() + if operation == "include in docker image": + repository_tups = [] + for repository_id in repository_ids: + repository = suc.get_repository_by_id( trans.app, repository_id ) + repository_tups.append( ( str( repository.name ), + str( repository.user.username ), + str( repository.type ) ) ) + return trans.fill_template( "/webapps/tool_shed/repository/docker_image_repositories.mako", + id=','.join( repository_ids ), + repository_tups=repository_tups, + message=message, + status=status ) + else: + # This can only occur when there is a multi-select grid with check boxes and an operation, + # and the user clicked the operation button without checking any of the check boxes. + kwd[ 'message' ] = "No items were selected." + kwd[ 'status' ] = 'error' + elif kwd.get( 'create_docker_image_button', False ): + tmp_image_dir = tempfile.mkdtemp( prefix="tmp-toolshed-cdidir" ) + docker_file_name = 'Dockerfile' + docker_file_path = os.path.join( tmp_image_dir, docker_file_name ) + tool_shed_url = tool_shed_url = web.url_for( '/', qualified=True ) + repository_string = '' + for repository_id in repository_ids: + repository = suc.get_repository_by_id( trans.app, repository_id ) + template = basic_util.SELECTED_REPOSITORIES_TEMPLATE + repository_template = \ + string.Template( template ).safe_substitute( tool_shed_url=tool_shed_url, + repository_owner=str( repository.user.username ) , + repository_name=str( repository.name ) ) + repository_string = '%s\n%s' % ( repository_string, repository_template ) + template = basic_util.DOCKER_IMAGE_TEMPLATE + docker_image_template = \ + string.Template( template ).safe_substitute( selected_repositories=repository_string ) + docker_image_string = docker_image_template + trans.response.set_content_type( 'application/text/plain' ) + trans.response.headers[ "Content-Disposition" ] = 'attachment; filename="%s"' % docker_file_name + opened_file = open( docker_file_path, "w" ) + opened_file.write( docker_image_string ) + opened_file.close() + opened_file = open( docker_file_path, "r" ) + # Make sure the file is removed from disk after the contents have been downloaded. + os.unlink( docker_file_path ) + docker_file_path, docker_file_name = os.path.split( docker_file_path ) + basic_util.remove_dir( docker_file_path ) + return opened_file + return self.docker_image_grid( trans, **kwd ) + @web.expose def create_repository( self, trans, **kwd ): message = kwd.get( 'message', '' ) diff --git a/lib/tool_shed/grids/repository_grids.py b/lib/tool_shed/grids/repository_grids.py index 9a5296adadc..d057db038ff 100644 --- a/lib/tool_shed/grids/repository_grids.py +++ b/lib/tool_shed/grids/repository_grids.py @@ -329,6 +329,26 @@ class RepositoryGrid( grids.Grid ): .outerjoin( model.Category.table ) +class DockerImageGrid( RepositoryGrid ): + columns = [ + RepositoryGrid.NameColumn( "Name", + key="name", + link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + attach_popup=False ), + RepositoryGrid.DescriptionColumn( "Synopsis", + key="description", + attach_popup=False ), + RepositoryGrid.UserColumn( "Owner", + model_class=model.User, + link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ), + attach_popup=False, + key="User.username" ), + RepositoryGrid.EmailAlertsColumn( "Alert", attach_popup=False ), + ] + operations = [ grids.GridOperation( "Include in Docker image", allow_multiple=True ) ] + show_item_checkboxes = True + + class EmailAlertsRepositoryGrid( RepositoryGrid ): columns = [ RepositoryGrid.NameColumn( "Name", diff --git a/lib/tool_shed/util/basic_util.py b/lib/tool_shed/util/basic_util.py index 7d606081ecd..58dbb17e564 100644 --- a/lib/tool_shed/util/basic_util.py +++ b/lib/tool_shed/util/basic_util.py @@ -20,6 +20,33 @@ NO_OUTPUT_TIMEOUT = 1200.0 MAXDIFFSIZE = 8000 MAX_DISPLAY_SIZE = 32768 +DOCKER_IMAGE_TEMPLATE = ''' +# Galaxy Docker image + +FROM bgruening/galaxy-stable + +MAINTAINER Bjoern A. Gruning, bjoern.gruening@gmail.com + +RUN sed -i 's|brand.*|brand = deepTools|g' ~/galaxy-central/universe_wsgi.ini + +WORKDIR /galaxy-central + +${selected_repositories} + +# Mark one folder as imported from the host. +VOLUME ["/export/"] + +# Expose port 80 to the host +EXPOSE :80 + +# Autostart script that is invoked during container start +CMD ["/usr/bin/startup"] +''' + +SELECTED_REPOSITORIES_TEMPLATE = ''' +RUN service postgresql start && service apache2 start && ./run.sh --daemon && sleep 120 && python ./scripts/api/install_tool_shed_repositories.py --api admin -l http://localhost:8080 --url ${tool_shed_url} -o ${repository_owner} --name ${repository_name} --tool-deps --repository-deps --panel-section-name 'Docker' +''' + def evaluate_template( text, install_environment ): """ Substitute variables defined in XML blocks from dependencies file. The value of the received diff --git a/templates/webapps/tool_shed/index.mako b/templates/webapps/tool_shed/index.mako index 34f6331206a..5826c89acf1 100644 --- a/templates/webapps/tool_shed/index.mako +++ b/templates/webapps/tool_shed/index.mako @@ -155,6 +155,11 @@
+ %if trans.app.config.enable_galaxy_flavor_docker_image: + + %endif %if can_review_repositories: