Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ausbeth reinstall #1

Open
wants to merge 55 commits into
base: sanger-tol-reinstall
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
5d5e494
Created reinstall file
Ausbeth Jul 29, 2024
840b4f9
Update settings.yml
Ausbeth Jul 29, 2024
68cb1de
reinstall functionality
Ausbeth Jul 30, 2024
27a13e2
Merge branch 'ausbeth-test' of https://github.com/sanger-tol/singular…
Ausbeth Jul 30, 2024
b5e8cbe
Update __init__.py
Ausbeth Jul 30, 2024
69e113c
Update reinstall.py
Ausbeth Jul 30, 2024
1ee0e41
Update reinstall.py
Ausbeth Jul 30, 2024
94dd442
Update reinstall.py
Ausbeth Jul 30, 2024
c57d8bf
cleaning up
Ausbeth Aug 27, 2024
10e0dc0
Adding boolean operations to uninstall function, and making the its m…
Ausbeth Aug 28, 2024
0383a31
Making sure the module to reinstall exists before reinstalling
Ausbeth Aug 28, 2024
e26daa8
fixing user messages
Ausbeth Aug 28, 2024
b780d8e
Modifying uninstall function to keep container.
Ausbeth Sep 2, 2024
fe3a967
flagger for complete reinstallation
Ausbeth Sep 2, 2024
f12534e
fixing bug
Ausbeth Sep 2, 2024
3412eca
fixing bug (install)
Ausbeth Sep 2, 2024
3062fc1
fixing issue where keep_container is not being recognised
Ausbeth Sep 2, 2024
21dcc4d
fixing typo
Ausbeth Sep 2, 2024
f58ad88
fixing bug why complete was not being recognised
Ausbeth Sep 2, 2024
c43c353
Reinstall all
Ausbeth Sep 2, 2024
be0ef72
Changing tcl back to lmod in settings, rename refactoring and simplyi…
Ausbeth Sep 15, 2024
3422d95
removing unnecessary arguements from reinstall
Ausbeth Sep 15, 2024
82611ee
updating help description
Ausbeth Sep 16, 2024
d02852c
Attempting to keep container when reinstalling
Ausbeth Sep 17, 2024
3120e9e
removing boolean return values in uninstall function
Ausbeth Sep 17, 2024
6211739
adding user message during reinstallation regarding keeping containers
Ausbeth Sep 17, 2024
bc484ad
restoring software to view during reinstallation
Ausbeth Sep 17, 2024
caf591a
fixing logger messages
Ausbeth Sep 17, 2024
9572250
rename
Ausbeth Sep 17, 2024
37b0cad
testing error message
Ausbeth Sep 17, 2024
3025043
fixing error message
Ausbeth Sep 17, 2024
14ff749
checking for invalid recipe
Ausbeth Sep 17, 2024
b65c161
Tests for Reinstall
Ausbeth Sep 19, 2024
c490ac1
fixing bug
Ausbeth Sep 19, 2024
1722a47
fixing bug
Ausbeth Sep 19, 2024
70a39d7
adding reinstall tests to test_client.sh
Ausbeth Sep 19, 2024
dbac04f
testing
Ausbeth Sep 19, 2024
26ffec0
testing
Ausbeth Sep 20, 2024
9d55d09
Testing only reinstall functionality before adding it to client test
Ausbeth Sep 20, 2024
af6b2b1
fixing issue
Ausbeth Sep 20, 2024
3b6f2bd
fixing issue
Ausbeth Sep 20, 2024
8c31da3
fixing issue
Ausbeth Sep 20, 2024
14bbfea
fixing issue
Ausbeth Sep 20, 2024
7d84b97
fixing issue
Ausbeth Sep 20, 2024
aa5242e
fixing issue
Ausbeth Sep 20, 2024
62f54a3
fixing issue
Ausbeth Sep 20, 2024
fc79f2f
minor refactoring
Ausbeth Sep 20, 2024
64e1986
updating help message
Ausbeth Sep 21, 2024
8c81761
adding author
Ausbeth Sep 21, 2024
23b0718
Implementing Guoying and Matthieu's suggested changes
Ausbeth Sep 29, 2024
3bb582f
Performing precommit locally and removing temp file
Ausbeth Sep 29, 2024
0347aba
TODO: fix test case ("lmod", "module.lua", "podman", False, False) fo…
Ausbeth Sep 29, 2024
80914ef
fixing linting issue
Ausbeth Sep 29, 2024
e109125
reverting
Ausbeth Sep 29, 2024
e32fef3
Update shpc/client/reinstall.py
Ausbeth Oct 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions shpc/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,34 @@ def get_parser():
action="store_true",
)

# Reinstall an installed software
reinstall = subparsers.add_parser(
"reinstall",
description=help.reinstall_description,
formatter_class=argparse.RawTextHelpFormatter,
)
reinstall.add_argument(
"reinstall_recipe",
help="recipe to reinstall",
nargs="?",
)

reinstall.add_argument(
"--update-containers",
"-u",
dest="update_containers",
help="Also reinstall the containers (by default, containers are preserved)",
default=False,
action="store_true",
)

reinstall.add_argument(
"--all",
"-a",
help="reinstall all installed software",
action="store_true",
)

# List installed modules
listing = subparsers.add_parser(
"list",
Expand Down Expand Up @@ -397,6 +425,7 @@ def get_parser():
install,
listing,
remove,
reinstall,
shell,
test,
uninstall,
Expand Down Expand Up @@ -535,6 +564,8 @@ def help(return_code=0):
from .pull import main
elif args.command == "remove":
from .remove import main
elif args.command == "reinstall":
from .reinstall import main
elif args.command == "shell":
from .shell import main
elif args.command == "show":
Expand Down
39 changes: 39 additions & 0 deletions shpc/client/help.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,45 @@
$ shpc install python:3.9.5-alpine
"""

reinstall_description = """Reinstall a software. Containers are kept by default

# Reinstall a specific version of a software
$ shpc reinstall quay.io/biocontainers/samtools:1.20--h50ea8bc_1

# Reinstall all versions of a software
$ shpc reinstall quay.io/biocontainers/samtools

# Reinstall all installed software
$ shpc reinstall --all
OR
$ shpc reinstall -a

# Completely reinstall a specific version of a software without keeping the container
$ shpc reinstall quay.io/biocontainers/samtools:1.20--h50ea8bc_1 --update_container
OR
$ shpc reinstall quay.io/biocontainers/samtools:1.20--h50ea8bc_1 -u

# Completely reinstall all versions of a software without keeping the container
$ shpc reinstall quay.io/biocontainers/samtools --update_container
OR
$ shpc reinstall quay.io/biocontainers/samtools -u

# Completely reinstall all software without keeping the container
$ shpc reinstall --all --update_container
OR
$ shpc reinstall -a -u

# Invalid arguement combinations:
$ shpc reinstall quay.io/biocontainers/samtools:1.20--h50ea8bc_1 --all
OR
$ shpc reinstall quay.io/biocontainers/samtools:1.20--h50ea8bc_1 -a

$ shpc reinstall quay.io/biocontainers/samtools --all
OR
$ shpc reinstall quay.io/biocontainers/samtools -a
"""


listing_description = """List installed modules.

# Show installed modules
Expand Down
129 changes: 129 additions & 0 deletions shpc/client/reinstall.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
__author__ = "Vanessa Sochat"
__copyright__ = "Copyright 2021-2024, Vanessa Sochat"
__license__ = "MPL 2.0"

import shpc.utils
from shpc.logger import logger


def main(args, parser, extra, subparser):
from shpc.main import get_client

shpc.utils.ensure_no_extra(extra)

cli = get_client(
quiet=args.quiet,
settings_file=args.settings_file,
module_sys=args.module_sys,
container_tech=args.container_tech,
)

# Update config settings on the fly
cli.settings.update_params(args.config_params)

# Check if user entered an incomplete command
if not args.reinstall_recipe and not args.all:
subparser.error(
"You must specify a recipe to reinstall or use --all to reinstall all installed software."
)

# Reinstall all software
if args.all:
# Check if the user typed an invalid argument combination
if args.reinstall_recipe:
logger.exit(
"You cannot specify a recipe with --all. Use shpc reinstall --all to reinstall all installed software."
)

# Check if the user has any software installed
installed_software = cli.list(return_modules=True)
if not installed_software:
logger.exit("You currently don't have any installed software to reinstall.")

# Reinstall all installed software
print("Reinstalling all installed software...")
for software in installed_software.keys():
reinstall(software, cli, args, update_containers=args.update_containers)
logger.info("All software reinstalled.")

# Reinstall a specific software
else:
# Add namespace
name = cli.add_namespace(args.reinstall_recipe)

# Reinstall the software
reinstall(name, cli, args, update_containers=args.update_containers)


def reinstall(name, cli, args, update_containers=False):
"""
Reinstall a specific version or all versions of a software.
"""
# Check if the provided recipe is known in any registry
try:
cli._load_container(name)
except SystemExit:
# Give additional messages relating to shpc reinstall, to the original exit message in _load_container function
logger.exit(
"This means it cannot be reinstalled because it is not installed, and cannot be installed because it is not known in any registry.\nPlease check the name or try a different recipe."
)

# Check if the software or version is installed
installed_versions = cli.list(return_modules=True).get(name.split(":")[0], [])
if not installed_versions:
logger.exit(
f"You currently don't have '{name}' installed.\nTry: shpc install", 0
)

# Determine if a specific version is requested
specific_version = ":" in name
if specific_version and name.split(":")[1] not in installed_versions:
logger.exit(
f"You currently don't have '{name}' installed.\nTry: shpc install", 0
)

# Handle reinstallation logic
if specific_version:
print(f"Reinstalling {name}...")
reinstall_version(name, cli, args, update_containers)
logger.info(f"Successfully reinstalled {name}.")
else:
print(f"Reinstalling all versions of {name}...")
for version in installed_versions:
version_name = f"{name}:{version}"
reinstall_version(version_name, cli, args, update_containers)
logger.info(f"Successfully reinstalled all versions of {name}.")


def reinstall_version(name, cli, args, update_containers):
"""
Sub-function to handle the actual reinstallation
"""
# Get the list of views the software was in
views_with_module = set()
views_dir = cli.new_module(name).module_dir
for view_name, entry in cli.views.items():
if entry.exists(views_dir):
views_with_module.add(view_name)

# Uninstallation process. By default, uninstall without prompting the user and keep the container except the user wants a complete reinstall
cli.uninstall(name, force=True, keep_container=not update_containers)

# Display a helpful message to the user about the state of the container during reinstall process
if not update_containers:
print(
"Container was successfully preserved, module files and wrapper scripts will be overwritten..."
)
else:
print("No container was preserved, all files will be overwritten...")

# Installation process
cli.install(name)

# Restore the software to the captured views
print(
f"Restoring {name} to the views it was uninstalled from during reinstallation"
)
for view_name in views_with_module:
cli.view_install(view_name, name)
logger.info(f"Restored {name} to view: {view_name}")
10 changes: 10 additions & 0 deletions shpc/main/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ def install(self, name, tag=None, **kwargs):
"""
raise NotImplementedError

def reinstall(self, name, update_containers=False):
Ausbeth marked this conversation as resolved.
Show resolved Hide resolved
"""
Reinstall an installed software
"""
from shpc.client.reinstall import reinstall

cli = self
args = {}
reinstall(name, cli, args, update_containers=update_containers)

def uninstall(self, name, tag=None):
"""
Uninstall must also implemented by the subclass (e.g., lmod)
Expand Down
19 changes: 11 additions & 8 deletions shpc/main/modules/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def view_uninstall(self, view, name, force=False):
logger.exit("View %s does not exist, cannot uninstall." % view)
return self.views[view].uninstall(module.module_dir)

def uninstall(self, name, force=False):
def uninstall(self, name, force=False, keep_container=False):
"""
Given a unique resource identifier, uninstall a module.
Set "force" to True to bypass the confirmation prompt.
Expand All @@ -100,7 +100,7 @@ def uninstall(self, name, force=False):

# Ask before deleting anything!
if not force:
msg = name + "?"
msg = "Do you wish to uninstall " + name + "?"
if views_with_module:
msg += (
"\nThis will uninstall the module from views:\n %s\nAre you sure?"
Expand All @@ -110,14 +110,17 @@ def uninstall(self, name, force=False):
return

# Podman needs image deletion
self.container.delete(module.name)
if not keep_container: # For reinstall
self.container.delete(module.name)

if module.container_dir != module.module_dir:
self._uninstall(
module.container_dir,
self.container_base,
"$container_base/%s" % module.name,
)
if not keep_container:
self._uninstall(
module.container_dir,
self.container_base,
"$container_base/%s" % module.name,
)

self._uninstall(
module.module_dir,
self.settings.module_base,
Expand Down
Loading
Loading