def verify(realArgs): options,arguments=parseCliArgs(realArgs) user = subuserlib.classes.user.User() try: with user.getRegistry().getLock() as LockFileHandle: subuserlib.verify.verify(user) user.getRegistry().commit() except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.")
def list(sysargs): """ List various things: image sources, subusers, ect. >>> import sys >>> import list #import self >>> list.list([sys.argv[0]]+["list","available"]) Images available for instalation from the repo: default foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo >>> list.list([sys.argv[0]]+["list","subusers"]) The following subusers are registered. Subuser: foo ------------------ Progam: foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo >>> list.list([sys.argv[0]]+["list","subusers","--short"]) foo """ options, args = parseCliArgs(sysargs) if len(args) == 0: sys.exit( "Nothing to list. Issue this command with the -h argument for help." ) user = subuserlib.classes.user.User() if 'available' in args: for repoName, repository in user.getRegistry().getRepositories( ).iteritems(): if not options.short: print("Images available for instalation from the repo: " + repoName) for imageName, imageSource in repository.iteritems(): if options.short: print(imageName) else: imageSource.describe() if 'subusers' in args: if not options.short: print("The following subusers are registered.") for name, subuser in user.getRegistry().getSubusers().iteritems(): if options.short: print(name) else: subuser.describe()
def verify(realArgs): options, arguments = parseCliArgs(realArgs) user = subuserlib.classes.user.User() try: with user.getRegistry().getLock() as LockFileHandle: subuserlib.verify.verify(user) user.getRegistry().commit() except subuserlib.portalocker.portalocker.LockException: sys.exit( "Another subuser process is currently running and has a lock on the registry. Please try again later." )
def add(user,name,url): repository = subuserlib.resolve.lookupRepositoryByURI(user,url) if repository: if type(repository.getName()) is int: sys.exit("A temporary repository with this url already exists. Cannot add. The ability to uprade temporary repositories to named repositories is a wanted feature. Feal free to send a quality, well thought out, pull request.") else: sys.exit("The repository named:" +repository.getName()+" already has this URL. Cannot add.") else: repository = subuserlib.classes.repository.Repository(user,name=name,gitOriginURI=url,gitCommitHash="master") user.getRegistry().getRepositories().addRepository(repository) user.getRegistry().commit()
def describe(sysargs): """ Describe subusers and images. >>> import describe #import self Describing a subuser prints its permissions. >>> describe.describe(["subuser","foo"]) Subuser: foo ------------------ Progam: foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo Describing an image prints the default permissions for that image. >>> describe.describe(["image","foo"]) foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo Images can be refered to with their full paths as well. Even remote images can be described. >>> describe.describe(["image","foo@default"]) foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo """ user = subuserlib.classes.user.User() (options,args) = parseCliArgs(sysargs) if len(args) < 2: print("Args: '"+"' '".join(args)+"'") print("Wrong number of arguments.") #parseCliArgs(["","subuser","describe","--help"]) elif args[0] == "image": for image in args[1:]: subuserlib.resolve.resolveImageSource(user,image).describe() elif args[0] == "subuser": for subuser in args[1:]: try: user.getRegistry().getSubusers()[subuser].describe() except KeyError: sys.exit("Subuser "+subuser+" does not exist.") else: print("Args: '"+"' '".join(args)+"'") print("Option not supported.")
def describe(sysargs): """ Describe subusers and images. >>> import describe #import self Describing a subuser prints its permissions. >>> describe.describe(["subuser","foo"]) Subuser: foo ------------------ Progam: foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo Describing an image prints the default permissions for that image. >>> describe.describe(["image","foo"]) foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo Images can be refered to with their full paths as well. Even remote images can be described. >>> describe.describe(["image","foo@default"]) foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo """ user = subuserlib.classes.user.User() (options, args) = parseCliArgs(sysargs) if len(args) < 2: print("Args: '" + "' '".join(args) + "'") print("Wrong number of arguments.") #parseCliArgs(["","subuser","describe","--help"]) elif args[0] == "image": for image in args[1:]: subuserlib.resolve.resolveImageSource(user, image).describe() elif args[0] == "subuser": for subuser in args[1:]: try: user.getRegistry().getSubusers()[subuser].describe() except KeyError: sys.exit("Subuser " + subuser + " does not exist.") else: print("Args: '" + "' '".join(args) + "'") print("Option not supported.")
def run(args): if len(args) == 1 or {"help","-h","--help"} & set(args): sys.exit(helpString) subuserName = args[1] argsToPassToImage = args[2:] user = subuserlib.classes.user.User() if subuserName in user.getRegistry().getSubusers(): subuserlib.run.run(user.getRegistry().getSubusers()[subuserName],argsToPassToImage) else: sys.exit(subuserName + " not found.\n"+helpString)
def removeOldImages(user): """ Remove images that are installed, but are not associated with any subusers. >>> remove_old_images = __import__("remove-old-images")#import self >>> import subuserlib.classes.user,subuserlib.subuser >>> user = subuserlib.classes.user.User() >>> user.getRegistry().getSubusers().keys() [u'foo'] >>> subuserlib.subuser.add(user,"bar","bar@file:///home/travis/remote-test-repo") Adding new temporary repository file:///home/travis/remote-test-repo Adding subuser bar bar@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Installing bar ... Installed new image for subuser bar Running garbage collector on temporary repositories... >>> user.getRegistry().getSubusers().keys() [u'foo', 'bar'] >>> [i.getImageSourceName() for i in user.getInstalledImages().values()] [u'foo', u'bar'] >>> subuserlib.subuser.remove(user,"bar") Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... >>> [i.getImageSourceName() for i in user.getInstalledImages().values()] [u'foo', u'bar'] >>> remove_old_images.removeOldImages(user) Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... Removing uneeded temporary repository: file:///home/travis/remote-test-repo >>> [i.getImageSourceName() for i in user.getInstalledImages().values()] [u'foo'] """ for installedImageId, installedImage in user.getInstalledImages( ).iteritems(): imageInUse = False for _, subuser in user.getRegistry().getSubusers().iteritems(): if subuser.getImageId() == installedImageId: imageInUse = True if not imageInUse: installedImage.removeDockerImage() subuserlib.verify.verify(user) user.getRegistry().commit()
def run(args): if len(args) == 1 or {"help", "-h", "--help"} & set(args): sys.exit(helpString) subuserName = args[1] argsToPassToImage = args[2:] user = subuserlib.classes.user.User() if subuserName in user.getRegistry().getSubusers(): subuserlib.run.run(user.getRegistry().getSubusers()[subuserName], argsToPassToImage) else: sys.exit(subuserName + " not found.\n" + helpString)
def removeOldImages(user): """ Remove images that are installed, but are not associated with any subusers. >>> remove_old_images = __import__("remove-old-images")#import self >>> import subuserlib.classes.user,subuserlib.subuser >>> user = subuserlib.classes.user.User() >>> user.getRegistry().getSubusers().keys() [u'foo'] >>> subuserlib.subuser.add(user,"bar","bar@file:///home/travis/remote-test-repo") Adding new temporary repository file:///home/travis/remote-test-repo Adding subuser bar bar@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Installing bar ... Installed new image for subuser bar Running garbage collector on temporary repositories... >>> user.getRegistry().getSubusers().keys() [u'foo', 'bar'] >>> [i.getImageSourceName() for i in user.getInstalledImages().values()] [u'foo', u'bar'] >>> subuserlib.subuser.remove(user,"bar") Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... >>> [i.getImageSourceName() for i in user.getInstalledImages().values()] [u'foo', u'bar'] >>> remove_old_images.removeOldImages(user) Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... Removing uneeded temporary repository: file:///home/travis/remote-test-repo >>> [i.getImageSourceName() for i in user.getInstalledImages().values()] [u'foo'] """ for installedImageId,installedImage in user.getInstalledImages().iteritems(): imageInUse = False for _,subuser in user.getRegistry().getSubusers().iteritems(): if subuser.getImageId() == installedImageId: imageInUse = True if not imageInUse: installedImage.removeDockerImage() subuserlib.verify.verify(user) user.getRegistry().commit()
def run(args): if len(args) == 1 or args[1] == "--help": print(helpString) sys.exit() subuserName = args[1] argsToPassToImage = args[2:] user = subuserlib.classes.user.User() if subuserName in user.getRegistry().getSubusers(): user.getRegistry().getSubusers()[subuserName].getRuntime(os.environ).run(argsToPassToImage) else: sys.exit(subuserName + " not found.\n"+helpString)
def list(sysargs): """ List various things: image sources, subusers, ect. >>> import sys >>> import list #import self >>> list.list([sys.argv[0]]+["list","available"]) Images available for instalation from the repo: default foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo >>> list.list([sys.argv[0]]+["list","subusers"]) The following subusers are registered. Subuser: foo ------------------ Progam: foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo >>> list.list([sys.argv[0]]+["list","subusers","--short"]) foo """ options,args = parseCliArgs(sysargs) if len(args)==0: sys.exit("Nothing to list. Issue this command with the -h argument for help.") user = subuserlib.classes.user.User() if 'available' in args: for repoName,repository in user.getRegistry().getRepositories().iteritems(): if not options.short: print("Images available for instalation from the repo: " + repoName) for imageName,imageSource in repository.iteritems(): if options.short: print(imageName) else: imageSource.describe() if 'subusers' in args: if not options.short: print("The following subusers are registered.") for name,subuser in user.getRegistry().getSubusers().iteritems(): if options.short: print(name) else: subuser.describe()
def add(user,name,url): repository = subuserlib.resolve.lookupRepositoryByURIOrPath(user,url) if repository: if repository.isTemporary(): sys.exit("A temporary repository with this url already exists. Cannot add. The ability to uprade temporary repositories to named repositories is a wanted feature. Feal free to send a quality, well thought out, pull request.") else: sys.exit("The repository named:" +repository.getName()+" already has this URL. Cannot add.") else: if url.startswith("/"): repository = subuserlib.classes.repository.Repository(user,name=name,sourceDir=url) else: repository = subuserlib.classes.repository.Repository(user,name=name,gitOriginURI=url,gitCommitHash="master") user.getRegistry().getRepositories().addRepository(repository) user.getRegistry().commit()
def run(args): if len(args) == 1 or args[1] == "--help": print(helpString) sys.exit() subuserName = args[1] argsToPassToImage = args[2:] user = subuserlib.classes.user.User() if subuserName in user.getRegistry().getSubusers(): user.getRegistry().getSubusers()[subuserName].getRuntime( os.environ).run(argsToPassToImage) else: sys.exit(subuserName + " not found.\n" + helpString)
def add(user,subuserName,imageSourceIdentifier): try: try: imageSource = subuserlib.resolve.resolveImageSource(user,imageSourceIdentifier) except KeyError as keyError: sys.exit("Could not add subuser. The image source "+imageSourceIdentifier+" does not exist.") user.getRegistry().logChange("Adding subuser "+subuserName+" "+imageSourceIdentifier) user.getRegistry().getSubusers()[subuserName] = subuserlib.classes.subuser.Subuser(user,subuserName,imageSource,None,False) subuserlib.verify.verify(user) user.getRegistry().commit() except subuserlib.classes.dockerDaemon.ImageBuildException as e: print("Adding subuser failed.") print(str(e)) subuserlib.update.checkoutNoCommit(user,"HEAD")
def setExecutableShortcutInstalled(user,subuserName,installed): if installed: user.getRegistry().logChange("Creating shortcut for subuser "+subuserName) else: user.getRegistry().logChange("Removing shortcut for subuser "+subuserName) user.getRegistry().getSubusers()[subuserName].setExecutableShortcutInstalled(installed) subuserlib.verify.verify(user) user.getRegistry().commit()
def verify(realArgs): options, arguments = parseCliArgs(realArgs) user = subuserlib.classes.user.User() permissionsAccepter = AcceptPermissionsAtCLI(user, alwaysAccept=options.accept) try: with user.getRegistry().getLock() as LockFileHandle: subuserNames = list(user.getRegistry().getSubusers().keys()) subuserNames.sort() subuserlib.verify.verify(user, subuserNames=subuserNames, permissionsAccepter=permissionsAccepter) user.getRegistry().commit() except subuserlib.portalocker.portalocker.LockException: sys.exit( "Another subuser process is currently running and has a lock on the registry. Please try again later." )
def add(user, subuserName, imageSourceIdentifier): try: try: imageSource = subuserlib.resolve.resolveImageSource( user, imageSourceIdentifier) except KeyError as keyError: sys.exit("Could not add subuser. The image source " + imageSourceIdentifier + " does not exist.") user.getRegistry().logChange("Adding subuser " + subuserName + " " + imageSourceIdentifier) user.getRegistry().getSubusers( )[subuserName] = subuserlib.classes.subuser.Subuser( user, subuserName, imageSource, None, False) subuserlib.verify.verify(user) user.getRegistry().commit() except subuserlib.classes.dockerDaemon.ImageBuildException as e: print("Adding subuser failed.") print(str(e)) subuserlib.update.checkoutNoCommit(user, "HEAD")
def run(args): if len(args) == 1 or args[1] == "-h" or args[1] == "--help": print(helpString) sys.exit() subuserName = args[1] argsToPassToImage = args[2:] user = subuserlib.classes.user.User() user.getRegistry().setLogOutputVerbosity(0) if subuserName in user.getRegistry().getSubusers(): runtime = user.getRegistry().getSubusers()[subuserName].getRuntime(os.environ) if runtime: runtime.run(argsToPassToImage) else: sys.exit( "The subuser's image failed to build. Please use the subuser update log and subuser repair commands for more information." ) else: sys.exit(subuserName + " not found.\n" + helpString)
def dryRun(args): """ Print the command that would have been run if this wasn't a dry run. >>> dry_run = __import__("dry-run") >>> dry_run.dryRunTestSetup() >>> dry_run.dryRun([sys.argv[0]]+["foo"]) docker 'run' '-i' '-t' '--rm' '--workdir=/home/travis/test-home' '-v=/home/travis/test-home/.subuser/homes/foo:/home/travis/test-home:rw' '-e' 'HOME=/home/travis/test-home' '--net=none' '--user=1000' '1' '/usr/bin/foo' """ if len(args) == 1 or {"help","-h","--help"} & set(args): sys.exit(helpString) subuserName = args[1] argsToPassToImage = args[2:] user = subuserlib.classes.user.User() if subuserName in user.getRegistry().getSubusers(): print(subuserlib.run.getPrettyCommand(user.getRegistry().getSubusers()[subuserName],argsToPassToImage)) else: sys.exit(subuserName + " not found.\n"+helpString)
def runCommand(sysargs): """ Describe subusers and images. """ user = subuserlib.classes.user.User() (options,args) = parseCliArgs(sysargs) if len(args) < 2: subuserlib.print.printWithoutCrashing("Nothing to describe. Use -h for help.") elif args[0] == "image": for image in args[1:]: subuserlib.resolve.resolveImageSource(user,image).describe() elif args[0] == "subuser": for subuser in args[1:]: try: user.getRegistry().getSubusers()[subuser].describe() except KeyError: sys.exit("Subuser "+subuser+" does not exist.") else: subuserlib.print.printWithoutCrashing("Args: '"+"' '".join(args)+"'") subuserlib.print.printWithoutCrashing("Option not supported.")
def run(args): if len(args) == 1 or args[1] == "-h" or args[1] == "--help": print(helpString) sys.exit() subuserName = args[1] argsToPassToImage = args[2:] user = subuserlib.classes.user.User() user.getRegistry().setLogOutputVerbosity(0) if subuserName in user.getRegistry().getSubusers(): runtime = user.getRegistry().getSubusers()[subuserName].getRuntime( os.environ) if runtime: runtime.run(argsToPassToImage) else: sys.exit( "The subuser's image failed to build. Please use the subuser update log and subuser repair commands for more information." ) else: sys.exit(subuserName + " not found.\n" + helpString)
def testImages(realArgs): """ Test the given images. """ options,args = parseCliArgs(realArgs) user = subuserlib.classes.user.User() try: with user.getRegistry().getLock() as lockFileHandler: subuserlib.testImages.testImages(user=user,sourceRepoId=args[0],imageSourceNames=args[1:]) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.")
def runCommand(sysargs): """ Describe subusers and images. """ user = subuserlib.classes.user.User() (options, args) = parseCliArgs(sysargs) if len(args) < 2: subuserlib.print.printWithoutCrashing( "Nothing to describe. Use -h for help.") elif args[0] == "image": for image in args[1:]: subuserlib.resolve.resolveImageSource(user, image).describe() elif args[0] == "subuser": for subuser in args[1:]: try: user.getRegistry().getSubusers()[subuser].describe() except KeyError: sys.exit("Subuser " + subuser + " does not exist.") else: subuserlib.print.printWithoutCrashing("Args: '" + "' '".join(args) + "'") subuserlib.print.printWithoutCrashing("Option not supported.")
def remove(user,subuserName): if subuserName in user.getRegistry().getSubusers(): user.getRegistry().logChange("Removing subuser "+subuserName) del user.getRegistry().getSubusers()[subuserName] subuserlib.verify.verify(user) user.getRegistry().commit() else: sys.exit("Cannot remove: subuser "+subuserName+" does not exist.")
def remove(user, subuserName): if subuserName in user.getRegistry().getSubusers(): user.getRegistry().logChange("Removing subuser " + subuserName) del user.getRegistry().getSubusers()[subuserName] subuserlib.verify.verify(user) user.getRegistry().commit() else: sys.exit("Cannot remove: subuser " + subuserName + " does not exist.")
def dryRun(args): if len(args) == 0 or {"help", "-h", "--help"} & set(args): print(helpString) sys.exit() subuserName = args[0] argsToPassToImage = args[1:] user = subuserlib.classes.user.User() if subuserName in user.getRegistry().getSubusers(): subuser = user.getRegistry().getSubusers()[subuserName] print("The image will be prepared using the Dockerfile:") print(subuser.getRunReadyImage().generateImagePreparationDockerfile()) print("The command to launch the image is:") print(subuser.getRuntime(os.environ).getPrettyCommand(argsToPassToImage)) else: availableSubusers = ",".join(user.getRegistry().getSubusers().keys()) sys.exit( subuserName + " not found.\n" + helpString + "\n" + "The following subusers are available for use:" + availableSubusers )
def dryRun(args): """ Print the command that would have been run if this wasn't a dry run. >>> dry_run = __import__("dry-run") >>> dry_run.dryRunTestSetup() >>> dry_run.dryRun([sys.argv[0]]+["foo"]) docker 'run' '-i' '-t' '--rm' '--workdir=/home/travis/test-home' '-v=/home/travis/test-home/.subuser/homes/foo:/home/travis/test-home:rw' '-e' 'HOME=/home/travis/test-home' '--net=none' '--user=1000' '1' '/usr/bin/foo' """ if len(args) == 1 or {"help", "-h", "--help"} & set(args): sys.exit(helpString) subuserName = args[1] argsToPassToImage = args[2:] user = subuserlib.classes.user.User() if subuserName in user.getRegistry().getSubusers(): print( subuserlib.run.getPrettyCommand( user.getRegistry().getSubusers()[subuserName], argsToPassToImage)) else: sys.exit(subuserName + " not found.\n" + helpString)
def testImages(realArgs): """ Test the given images. """ options, args = parseCliArgs(realArgs) user = subuserlib.classes.user.User() permissionsAccepter = AcceptPermissionsAtCLI(user, alwaysAccept=options.accept) try: with user.getRegistry().getLock() as lockFileHandler: subuserlib.testImages.testImages( user=user, sourceRepoId=args[0], imageSourceNames=args[1:], permissionsAccepter=permissionsAccepter) except subuserlib.portalocker.portalocker.LockException: sys.exit( "Another subuser process is currently running and has a lock on the registry. Please try again later." )
def update(realArgs): """ Update your subuser installation. Tests ----- **Setup:** >>> import os >>> import update,subuser,subuserlib.git,repository Check initial test environment: >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'bar']) True Add a subuser who's image has a lot of dependencies. >>> subuser.subuser(["add","dependent","dependent@file:///home/travis/remote-test-repo"]) Adding subuser dependent dependent@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Installing dependency1 ... Building... Building... Building... Successfully built 10 Building... Building... Building... Successfully built 11 Installing intermediary ... Building... Building... Building... Successfully built 12 Building... Building... Building... Successfully built 13 Installing dependent ... Building... Building... Building... Successfully built 14 Building... Building... Building... Successfully built 15 Installed new image for subuser dependent Running garbage collector on temporary repositories... Check that our new subuser was successfully added. >>> user = subuserlib.classes.user.User() >>> subuserNamesBeforeUpdate = user.getRegistry().getSubusers().keys() >>> set(subuserNamesBeforeUpdate) == set(['dependent', u'foo']) True And that its image, along with all of its dependencies were added as well. >>> installedImagesBeforeUpdate = [i.getImageSourceName() for i in user.getInstalledImages().values()] >>> set(installedImagesBeforeUpdate) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary']) True Running update, when there is nothing to be updated, does nothing. >>> update.update(["all"]) Updating... Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... The same subusers are still installed. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(subuserNamesBeforeUpdate) True And the same images too. >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set(installedImagesBeforeUpdate) True Now we change the ImageSource for the ``dependent`` image. >>> with open(user.getRegistry().getRepositories()[u'1']["intermediary"].getSubuserImagefilePath(),mode="w") as subuserImagefile: ... _ = subuserImagefile.write("FROM-SUBUSER-IMAGE dependency2") And commit the changes to git. >>> subuserlib.git.runGit(["commit","-a","-m","changed dependency for intermediate from dependency1 to dependency2"],cwd=user.getRegistry().getRepositories()[u'1'].getRepoPath()) Running an update after a change installs new images and registers them with their subusers. But it does not delete the old ones. >>> update.update(["all"]) Updating... Updated repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Installing dependency2 ... Building... Building... Building... Successfully built 16 Building... Building... Building... Successfully built 17 Installing intermediary ... Building... Building... Building... Successfully built 18 Building... Building... Building... Successfully built 19 Installing dependent ... Building... Building... Building... Successfully built 20 Building... Building... Building... Successfully built 21 Installed new image for subuser dependent Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2', u'dependent']) True Old images are not deleted so that update lock-subuser-to and update rollback still work. In this example, dependency1 stays installed. Now we lock the dependent subuser and try changing it again. >>> update.update(["lock-subuser-to","dependent","HEAD"]) Locking subuser dependent to commit: HEAD Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... >>> with open(user.getRegistry().getRepositories()[u'1']["intermediary"].getSubuserImagefilePath(),mode="w") as subuserImagefile: ... _ = subuserImagefile.write("FROM-SUBUSER-IMAGE dependency3") And commit the changes to git. >>> subuserlib.git.runGit(["commit","-a","-m","changed dependency for intermediate from dependency2 to dependency3"],cwd=user.getRegistry().getRepositories()[u'1'].getRepoPath()) Running an update after a change does nothing because the affected subuser is locked. >>> update.update(["all"]) Updating... Updated repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2', u'dependent']) True When we unlock the subuser it gets updated imediately. >>> update.update(["unlock-subuser","dependent"]) Unlocking subuser dependent Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Installing dependency3 ... Building... Building... Building... Successfully built 22 Building... Building... Building... Successfully built 23 Installing intermediary ... Building... Building... Building... Successfully built 24 Building... Building... Building... Successfully built 25 Installing dependent ... Building... Building... Building... Successfully built 26 Building... Building... Building... Successfully built 27 Installed new image for subuser dependent Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2',u'dependency3', u'dependent']) True """ options,args = parseCliArgs(realArgs) user = subuserlib.classes.user.User() if len(args) < 1: sys.exit("No arguments given. Please use subuser update -h for help.") elif ["all"] == args: try: with user.getRegistry().getLock(): subuserlib.update.updateAll(user) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif ["log"] == args: subuserlib.update.showLog(user) elif "lock-subuser-to" == args[0]: try: subuserName = args[1] commit = args[2] except KeyError: sys.exit("Wrong number of arguments. Expected a subuser name and a commit. Try running\nsubuser update --help\n for more info.") try: with user.getRegistry().getLock(): subuserlib.update.lockSubuser(user,subuserName=subuserName,commit=commit) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif "unlock-subuser" == args[0]: try: subuserName = args[1] except KeyError: sys.exit("Wrong number of arguments. Expected a subuser's name. Try running\nsubuser update --help\nfor more information.") try: with user.getRegistry().getLock(): subuserlib.update.unlockSubuser(user,subuserName=subuserName) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif "rollback" == args[0]: try: commit = args[1] except KeyError: sys.exit("Wrong number of arguments. Expected a commit. Try running \nsubuser update --help\nfor more info.") try: with user.getRegistry().getLock(): subuserlib.update.rollback(user,commit=commit) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif len(args) == 1: sys.exit(" ".join(args) + " is not a valid update subcommand. Please use subuser update -h for help.") else: sys.exit(" ".join(args) + " is not a valid update subcommand. Please use subuser update -h for help.")
def dryRun(args): """ Print the command that would have been run if this wasn't a dry run. >>> dry_run = __import__("dry-run") >>> dry_run.dryRunTestSetup() >>> import subuser,subuserlib.classes.user >>> remove_old_images = __import__("remove-old-images") If we dry run the basic foo test subuser, we will see the generated pre-run Dockerfile and also the docker command that will launch our subuser. >>> dry_run.dryRun(["foo"]) The image will be prepared using the Dockerfile: FROM 2 RUN useradd --uid=1000 travis ;export exitstatus=$? ; if [ $exitstatus -eq 4 ] ; then echo uid exists ; elif [ $exitstatus -eq 9 ]; then echo username exists. ; else exit $exitstatus ; fi RUN test -d /home/travis || mkdir /home/travis && chown travis /home/travis <BLANKLINE> The command to launch the image is: docker 'run' '-i' '-t' '--rm' '-e' 'HOME=/home/travis/test-home' '--workdir=/home/travis/test-home' '--net=none' '--user=1000' '3' '/usr/bin/foo' Running subusers installed through temporary repositories works as well. Here, we add a subuser named bar, run it, and then remove it again. >>> subuser.subuser(["add","bar","bar@file:///home/travis/remote-test-repo"]) Adding subuser bar bar@file:///home/travis/remote-test-repo Adding new temporary repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Installing bar ... Installed new image for subuser bar Running garbage collector on temporary repositories... The actual dry-run call. >>> dry_run.dryRun(["bar"]) The image will be prepared using the Dockerfile: FROM 5 RUN useradd --uid=1000 travis ;export exitstatus=$? ; if [ $exitstatus -eq 4 ] ; then echo uid exists ; elif [ $exitstatus -eq 9 ]; then echo username exists. ; else exit $exitstatus ; fi RUN test -d /home/travis || mkdir /home/travis && chown travis /home/travis <BLANKLINE> The command to launch the image is: docker 'run' '-i' '-t' '--rm' '-e' 'HOME=/home/travis/test-home' '--workdir=/home/travis/test-home' '--net=none' '--user=1000' '6' '/usr/bin/bar' Cleanup. >>> subuser.subuser(["remove","bar"]) Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... >>> remove_old_images.removeOldImages([]) Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... Removing uneeded temporary repository: file:///home/travis/remote-test-repo """ if len(args) == 0 or {"help", "-h", "--help"} & set(args): print(helpString) sys.exit() subuserName = args[0] argsToPassToImage = args[1:] user = subuserlib.classes.user.User() if subuserName in user.getRegistry().getSubusers(): subuser = user.getRegistry().getSubusers()[subuserName] print("The image will be prepared using the Dockerfile:") print( subuserlib.runReadyImages.generateImagePreparationDockerfile( subuser)) print("The command to launch the image is:") print( subuser.getRuntime(os.environ).getPrettyCommand(argsToPassToImage)) else: sys.exit(subuserName + " not found.\n" + helpString)
def removeOldImages(realArgs): """ Remove images that are installed, but are not associated with any subusers. Tests ----- **Setup:** >>> remove_old_images = __import__("remove-old-images")#import self >>> import subuser >>> import subuserlib.classes.user Check our assumptions about what subusers are installed in the test environment. We load a new user object each time we checked, because we are interested about whether the changes we want are present on disk. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(["foo"]) True Add a ``bar`` subuser, which we will then remove. This will leave us with a leftover image. >>> subuser.subuser(["add","bar","bar@file:///home/travis/remote-test-repo"]) Adding subuser bar bar@file:///home/travis/remote-test-repo Adding new temporary repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Installing bar ... Building... Building... Building... Successfully built 5 Building... Building... Building... Successfully built 6 Installed new image for subuser bar Running garbage collector on temporary repositories... Check to see if subuser ``bar`` was successfully added. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo', 'bar']) True Check to see if the image for ``bar`` was also installed. >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'bar']) True Remove the ``bar`` subuser. >>> subuser.subuser(["remove","bar"]) Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... See that the image for ``bar`` was indeed left behind. >>> user = subuserlib.classes.user.User() >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'bar']) True Use dry-run to see which images are to be deleted. >>> remove_old_images.removeOldImages(["--dry-run"]) The following images are uneeded and would be deleted. DOCKER-ID : SUBUSER-ID Removing unneeded image 6 : bar@file:///home/travis/remote-test-repo Now we use ``remove-old-images`` to clean up our installed images. >>> remove_old_images.removeOldImages([]) Removing unneeded image 6 : bar@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... Removing uneeded temporary repository: file:///home/travis/remote-test-repo And now the uneccesary ``bar`` image is gone. >>> user = subuserlib.classes.user.User() >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo']) True """ options,args = parseCliArgs(realArgs) user = subuserlib.classes.user.User() try: with user.getRegistry().getLock() as lockFileHandler: if options.dryrun: print("The following images are uneeded and would be deleted.") print("DOCKER-ID : SUBUSER-ID") subuserlib.removeOldImages.removeOldImages(user=user,dryrun=options.dryrun) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.")
def verify(realArgs): options,arguments=parseCliArgs(realArgs) user = subuserlib.classes.user.User() subuserlib.verify.verify(user) user.getRegistry().commit()
def subuser(sysargs): """ Manage subusers Tests ----- **Setup:** >>> import subuser #import self >>> import subuserlib.classes.user At the start of our tests, the test environment has one subuser named ``foo``. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo']) True We add another subuser named ``bar``. >>> subuser.subuser(["add","--accept","bar","bar@file:///home/travis/remote-test-repo"]) Adding subuser bar bar@file:///home/travis/remote-test-repo Adding new temporary repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. bar would like to have the following permissions: Description: Maintainer: Executable: /usr/bin/bar A - Accept and apply changes E - Apply changes and edit result A Checking if images need to be updated or installed... Checking if subuser bar is up to date. Installing bar ... Building... Building... Building... Successfully built 6 Building... Building... Building... Successfully built 8 Installed new image <8> for subuser bar Running garbage collector on temporary repositories... Now we have two subusers. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo', 'bar']) True We remove ``bar``. >>> subuser.subuser(["remove","bar"]) Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... Now we only have one subuser. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo']) True We add another subuser named ``bar`` using a local folder rather than from a git repo. >>> subuser.subuser(["add","--accept","bar","bar@/home/travis/remote-test-repo"]) Adding subuser bar bar@/home/travis/remote-test-repo Adding new temporary repository /home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. bar would like to have the following permissions: Description: Maintainer: Executable: /usr/bin/bar A - Accept and apply changes E - Apply changes and edit result A Checking if images need to be updated or installed... Checking if subuser bar is up to date. Installing bar ... Building... Building... Building... Successfully built 9 Building... Building... Building... Successfully built 10 Installed new image <10> for subuser bar Running garbage collector on temporary repositories... Now we have two subusers. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo', 'bar']) True We remove ``bar``. >>> subuser.subuser(["remove","bar"]) Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... Now we only have one subuser. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo']) True If we try adding a subuser which fails to install do to a bad ``SubuserImagefile`` an error is displayed, a cleanup process occures, and nothing terribly bad happens. This works for syntax errors. >>> try: ... subuser.subuser(["add","--accept","broken-syntax","broken-syntax@file:///home/travis/remote-test-repo"]) ... except SystemExit: ... pass Adding subuser broken-syntax broken-syntax@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. broken-syntax would like to have the following permissions: Description: Maintainer: Is a library. A - Accept and apply changes E - Apply changes and edit result A Checking if images need to be updated or installed... Checking if subuser broken-syntax is up to date. Error while building image: Error in broken-syntax's SubuserImagefile on line 0 Subuser image does not exist: "" Cleaning up. >>> try: ... subuser.subuser(["add","--accept","broken-non-existant-dependency","broken-non-existant-dependency@file:///home/travis/remote-test-repo"]) ... except SystemExit: ... pass Adding subuser broken-non-existant-dependency broken-non-existant-dependency@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. broken-non-existant-dependency would like to have the following permissions: Description: Maintainer: Is a library. A - Accept and apply changes E - Apply changes and edit result A Checking if images need to be updated or installed... Checking if subuser broken-non-existant-dependency is up to date. Error while building image: Error in broken-non-existant-dependency's SubuserImagefile on line 0 Subuser image does not exist: "non-existant-I-do-not-exist!!!!!" Cleaning up. """ options,args = parseCliArgs(sysargs) try: action = args[0] except IndexError: parseCliArgs(["--help"]) user = subuserlib.classes.user.User() permissionsAccepter = AcceptPermissionsAtCLI(user,alwaysAccept = options.accept) if action == "add": if not len(args) == 3: sys.exit("Wrong number of arguments to add. See `subuser subuser -h`.") name = args[1] imageSourceId = args[2] try: with user.getRegistry().getLock(): subuserlib.subuser.add(user,name,imageSourceId,permissionsAccepter=permissionsAccepter) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif action == "remove": names = args[1:] if not options.prefix is None: allSubuserNames = user.getRegistry().getSubusers().keys() names.extend([subuserName for subuserName in allSubuserNames if subuserName.startswith(options.prefix)]) try: with user.getRegistry().getLock(): subuserlib.subuser.remove(user,names) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif action == "create-shortcut": name = args[1] try: with user.getRegistry().getLock(): subuserlib.subuser.setExecutableShortcutInstalled(user,name,True) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif action == "remove-shortcut": name = args[1] try: with user.getRegistry().getLock(): subuserlib.subuser.setExecutableShortcutInstalled(user,name,False) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif action == "edit-permissions": name = args[1] try: with user.getRegistry().getLock(): user.getRegistry().logChange("Edit "+name+"'s permissions.") subuserlib.subprocessExtras.call([os.environ["EDITOR"],user.getRegistry().getSubusers()[name].getPermissions().getWritePath()]) subuserlib.verify.verify(user,subuserNames=[name],permissionsAccepter=permissionsAccepter) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") else: sys.exit("Action "+args[0]+" does not exist. Try:\n subuser subuser --help")
def list(sysargs): """ List various things: image sources, subusers, ect. >>> import sys >>> import list #import self Listing available images lists the images along with their default permissions. >>> list.list(["available"]) Images available for instalation from the repo: default foo@default Description: Maintainer: Executable: /usr/bin/foo Similar result when listing subusers. >>> list.list(["subusers"]) The following subusers are registered. Subuser: foo ------------------ foo@default Description: Maintainer: Executable: /usr/bin/foo <BLANKLINE> And listing installed images: >>> list.list(["installed-images"]) The following images are installed. ------------------ Image Id: 2 Image source: foo@default Last update time: 1 > list.list(["repositories"]) Repository: default ------------ Cloned from: file:///home/travis/default-test-repo Currently at commit: 72e7d9c17192d47b2b2344d9eb8a325262d738fe In all cases, there is a ``--short`` option. >>> list.list(["subusers","--short"]) foo >>> list.list(["available","--short"]) foo@default >>> list.list(["installed-images","--short"]) foo@default 2 >>> list.list(["repositories","--short"]) default """ options, args = parseCliArgs(sysargs) if len(args) == 0: sys.exit( "Nothing to list. Issue this command with the -h argument for help." ) user = subuserlib.classes.user.User() if 'available' in args: for repoName, repository in user.getRegistry().getRepositories().items( ): if not options.short: print("Images available for instalation from the repo: " + repoName) for _, imageSource in repository.items(): if options.short: print(imageSource.getIdentifier()) else: imageSource.describe() if 'subusers' in args: if not options.short: print("The following subusers are registered.") for name, subuser in user.getRegistry().getSubusers().items(): if options.internal or not name.startswith("!"): if options.short: print(name) else: subuser.describe() if 'installed-images' in args: if not options.short: print("The following images are installed.") for id, installedImage in user.getInstalledImages().items(): if options.short: try: identifier = installedImage.getImageSource().getIdentifier( ) if not options.broken: print(identifier + " " + id) except KeyError: if options.broken: print(id) else: print("------------------") installedImage.describe() if 'repositories' in args: for name, repo in user.getRegistry().getRepositories().items(): if options.short: print(repo.getDisplayName()) else: repo.describe() print("")
def remove(user, subuserName): if subuserName in user.getRegistry().getSubusers(): user.getRegistry().logChange("Removing subuser " + subuserName) subuserHome = user.getRegistry().getSubusers( )[subuserName].getHomeDirOnHost() if subuserHome: user.getRegistry().logChange( " If you wish to remove the subusers home directory, issule the command $ rm -r " + subuserHome) user.getRegistry().logChange( " If you wish to remove the subusers image, issue the command $ subuser remove-old-images" ) del user.getRegistry().getSubusers()[subuserName] subuserlib.verify.verify(user) user.getRegistry().commit() else: sys.exit("Cannot remove: subuser " + subuserName + " does not exist.")
def list(sysargs): """ List various things: image sources, subusers, ect. >>> import sys >>> import list #import self Listing available images lists the images along with their default permissions. >>> list.list(["available"]) Images available for instalation from the repo: default foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo Similar result when listing subusers. >>> list.list(["subusers"]) The following subusers are registered. Subuser: foo ------------------ Progam: foo: Description: Maintainer: Last update time(version): 0 Executable: /usr/bin/foo And listing installed images: >>> list.list(["installed-images"]) The following images are installed. ------------------ Image Id: 2 Image source: foo@default Last update time: 0 In all cases, there is a ``--short`` option. >>> list.list(["subusers","--short"]) foo >>> list.list(["available","--short"]) foo@default >>> list.list(["installed-images","--short"]) foo@default 2 """ options,args = parseCliArgs(sysargs) if len(args)==0: sys.exit("Nothing to list. Issue this command with the -h argument for help.") user = subuserlib.classes.user.User() if 'available' in args: for repoName,repository in user.getRegistry().getRepositories().items(): if not options.short: print("Images available for instalation from the repo: " + repoName) for _,imageSource in repository.items(): if options.short: print(imageSource.getIdentifier()) else: imageSource.describe() if 'subusers' in args: if not options.short: print("The following subusers are registered.") for name,subuser in user.getRegistry().getSubusers().items(): if options.short: print(name) else: subuser.describe() if 'installed-images' in args: if not options.short: print("The following images are installed.") for id,installedImage in user.getInstalledImages().items(): if options.short: try: identifier = installedImage.getImageSource().getIdentifier() if not options.broken: print(identifier+" "+id) except KeyError: if options.broken: print(id) else: print("------------------") installedImage.describe()
#!/usr/bin/env python # This file should be compatible with both Python 2 and 3. # If it is not, please file a bug report. #external imports import optparse #internal imports import subuserlib.classes.user,subuserlib.verify,subuserlib.commandLineArguments #################################################### def parseCliArgs(): usage = "usage: subuser %prog [options]" description = """ Repair your subuser installation. This is usefull when migrating from one machine to another. You can copy your ~/.subuser folder to the new machine and run repair, and things should just work. """ parser = optparse.OptionParser(usage=usage,description=description,formatter=subuserlib.commandLineArguments.HelpFormatterThatDoesntReformatDescription()) return parser.parse_args() if __name__ == "__main__": options,arguments=parseCliArgs() user = subuserlib.classes.user.User() subuserlib.verify.verify(user) user.getRegistry().commit()
# This file should be compatible with both Python 2 and 3. # If it is not, please file a bug report. #external imports import optparse #internal imports import subuserlib.classes.user, subuserlib.verify, subuserlib.commandLineArguments #################################################### def parseCliArgs(): usage = "usage: subuser %prog [options]" description = """ Repair your subuser installation. This is usefull when migrating from one machine to another. You can copy your ~/.subuser folder to the new machine and run repair, and things should just work. """ parser = optparse.OptionParser( usage=usage, description=description, formatter=subuserlib.commandLineArguments. HelpFormatterThatDoesntReformatDescription()) return parser.parse_args() if __name__ == "__main__": options, arguments = parseCliArgs() user = subuserlib.classes.user.User() subuserlib.verify.verify(user) user.getRegistry().commit()
def remove(user, name): user.getRegistry().getRepositories().removeRepository(name)
def subuser(sysargs): """ Manage subusers Tests ----- **Setup:** >>> import subuser #import self >>> import subuserlib.classes.user At the start of our tests, the test environment has one subuser named ``foo``. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo']) True We add another subuser named ``bar``. >>> subuser.subuser(["add","bar","bar@file:///home/travis/remote-test-repo"]) Adding subuser bar bar@file:///home/travis/remote-test-repo Adding new temporary repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Installing bar ... Building... Building... Building... Successfully built 6 Building... Building... Building... Successfully built 7 Installed new image for subuser bar Running garbage collector on temporary repositories... Now we have two subusers. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo', 'bar']) True We remove ``bar``. >>> subuser.subuser(["remove","bar"]) Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... Now we only have one subuser. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo']) True We add another subuser named ``bar`` using a local folder rather than from a git repo. >>> subuser.subuser(["add","bar","bar@/home/travis/remote-test-repo"]) Adding subuser bar bar@/home/travis/remote-test-repo Adding new temporary repository /home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Installing bar ... Building... Building... Building... Successfully built 8 Building... Building... Building... Successfully built 9 Installed new image for subuser bar Running garbage collector on temporary repositories... Now we have two subusers. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo', 'bar']) True We remove ``bar``. >>> subuser.subuser(["remove","bar"]) Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... Now we only have one subuser. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo']) True If we try adding a subuser which fails to install do to a bad ``SubuserImagefile`` an error is displayed, a cleanup process occures, and nothing terribly bad happens. This works for syntax errors. >>> try: ... subuser.subuser(["add","broken-syntax","broken-syntax@file:///home/travis/remote-test-repo"]) ... except SystemExit: ... pass Adding subuser broken-syntax broken-syntax@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Error while building image: Error in SubuserImagefile one line 0 Subuser image does not exist: "" Cleaning up. >>> try: ... subuser.subuser(["add","broken-non-existant-dependency","broken-non-existant-dependency@file:///home/travis/remote-test-repo"]) ... except SystemExit: ... pass Adding subuser broken-non-existant-dependency broken-non-existant-dependency@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Error while building image: Error in SubuserImagefile one line 0 Subuser image does not exist: "non-existant-I-do-not-exist!!!!!" Cleaning up. """ options,args = parseCliArgs(sysargs) try: action = args[0] except IndexError: parseCliArgs(["--help"]) user = subuserlib.classes.user.User() if action == "add": if not len(args) == 3: sys.exit("Wrong number of arguments to add. See `subuser subuser -h`.") name = args[1] imageSourceId = args[2] try: with user.getRegistry().getLock(): subuserlib.subuser.add(user,name,imageSourceId) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif action == "remove": names = args[1:] try: with user.getRegistry().getLock(): subuserlib.subuser.remove(user,names) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif action == "create-shortcut": name = args[1] try: with user.getRegistry().getLock(): subuserlib.subuser.setExecutableShortcutInstalled(user,name,True) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif action == "remove-shortcut": name = args[1] try: with user.getRegistry().getLock(): subuserlib.subuser.setExecutableShortcutInstalled(user,name,False) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") else: sys.exit("Action "+args[0]+" does not exist. Try:\n subuser subuser --help")
def dryRun(args): """ Print the command that would have been run if this wasn't a dry run. >>> dry_run = __import__("dry-run") >>> dry_run.dryRunTestSetup() >>> dry_run.dryRun([sys.argv[0]]+["foo"]) The image will be prepared using the Dockerfile: FROM 2 RUN useradd --uid=1000 travis ;export exitstatus=$? ; if [ $exitstatus -eq 4 ] ; then echo uid exists ; elif [ $exitstatus -eq 9 ]; then echo username exists. ; else exit $exitstatus ; fi RUN test -d /home/travis || mkdir /home/travis && chown travis /home/travis <BLANKLINE> The command to launch the image is: docker 'run' '-i' '-t' '--rm' '--workdir=/home/travis/test-home' '-e' 'HOME=/home/travis/test-home' '--net=none' '--user=1000' 'imageId' '/usr/bin/foo' Running subusers installed through temporary repositories works as well. >>> import subuser,subuserlib.classes.user >>> remove_old_images = __import__("remove-old-images") >>> user = subuserlib.classes.user.User() >>> subuser.subuser(user,["subuser","add","bar","bar@file:///home/travis/remote-test-repo"]) Adding new temporary repository file:///home/travis/remote-test-repo Adding subuser bar bar@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Installing bar ... Installed new image for subuser bar Running garbage collector on temporary repositories... >>> dry_run.dryRun([sys.argv[0]]+["bar"]) The image will be prepared using the Dockerfile: FROM 4 RUN useradd --uid=1000 travis ;export exitstatus=$? ; if [ $exitstatus -eq 4 ] ; then echo uid exists ; elif [ $exitstatus -eq 9 ]; then echo username exists. ; else exit $exitstatus ; fi RUN test -d /home/travis || mkdir /home/travis && chown travis /home/travis <BLANKLINE> The command to launch the image is: docker 'run' '-i' '-t' '--rm' '--workdir=/home/travis/test-home' '-e' 'HOME=/home/travis/test-home' '--net=none' '--user=1000' 'imageId' '/usr/bin/bar' >>> subuser.subuser(user,["subuser","remove","bar"]) Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... >>> remove_old_images.removeOldImages(user) Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... Removing uneeded temporary repository: file:///home/travis/remote-test-repo """ if len(args) == 1 or {"help","-h","--help"} & set(args): print(helpString) sys.exit() subuserName = args[1] argsToPassToImage = args[2:] user = subuserlib.classes.user.User() if subuserName in user.getRegistry().getSubusers(): print("The image will be prepared using the Dockerfile:") print(subuserlib.run.generateImagePreparationDockerfile(user.getRegistry().getSubusers()[subuserName])) print("The command to launch the image is:") print(subuserlib.run.getPrettyCommand(user.getRegistry().getSubusers()[subuserName],"imageId",argsToPassToImage)) else: sys.exit(subuserName + " not found.\n"+helpString)
def list(sysargs): """ List various things: image sources, subusers, ect. >>> import sys >>> list = __import__("subuser-list") #import self Listing available images lists the images along with their default permissions. >>> list.list(["available"]) foo@default Similar result when listing subusers. >>> list.list(["subusers"]) foo And listing installed images: >>> list.list(["installed-images"]) foo@default 2 > list.list(["repositories"]) foo In all cases, there is a ``--long`` option. (We don't test this, because the hash changes every time.) >> list.list(["repositories","--long"]) Repository: default ------------ Cloned from: file:///home/travis/default-test-repo Currently at commit: 7ef30a4e1267f9f026e3be064f120290c28ef29e <BLANKLINE> >>> list.list(["subusers","--long"]) The following subusers are registered. Subuser: foo ------------------ foo@default Description: Maintainer: Executable: /usr/bin/foo <BLANKLINE> >>> list.list(["available","--long"]) Images available for instalation from the repo: default foo@default Description: Maintainer: Executable: /usr/bin/foo You can specify which repository to list image sources from. >>> list.list(["available","default","--long"]) Images available for instalation from the repo: default foo@default Description: Maintainer: Executable: /usr/bin/foo When listing available image sources, refering to a repository via a URI works as well. >>> list.list(["available","file:///home/travis/version-constrained-test-repo"]) Adding new temporary repository file:///home/travis/version-constrained-test-repo bop@file:///home/travis/version-constrained-test-repo >>> list.list(["installed-images"]) foo@default 2 >>> list.list(["repositories"]) default """ options, args = parseCliArgs(sysargs) if len(args) == 0: sys.exit( "Nothing to list. Issue this command with the -h argument for help." ) user = subuserlib.classes.user.User() if args[0] == 'available': if len(args) > 1: reposToList = args[1:] else: reposToList = user.getRegistry().getRepositories().keys() if options.json: availableDict = {} for repoIdentifier in reposToList: if repoIdentifier in user.getRegistry().getRepositories(): temp = False else: temp = True repository = subuserlib.resolve.resolveRepository( user, repoIdentifier) availableDict[ repository.getName()] = repository.serializeToDict() if temp: repository.removeGitRepo() print(json.dumps(availableDict, indent=1, separators=(",", ": "))) sys.exit() for repoIdentifier in reposToList: if repoIdentifier in user.getRegistry().getRepositories(): temp = False else: temp = True repository = subuserlib.resolve.resolveRepository( user, repoIdentifier) if options.long: print("Images available for instalation from the repo: " + repository.getName()) for _, imageSource in repository.items(): if not options.long: print(imageSource.getIdentifier()) else: imageSource.describe() if temp: repository.removeGitRepo() elif args[0] == 'subusers': if options.json: print( json.dumps(user.getRegistry().getSubusers().serializeToDict(), indent=1, separators=(",", ": "))) sys.exit() if options.long: print("The following subusers are registered.") for name, subuser in user.getRegistry().getSubusers().items(): if options.internal or not name.startswith("!"): if not options.long: print(name) else: subuser.describe() elif args[0] == 'installed-images': if options.json: print( json.dumps(user.getInstalledImages().serializeToDict(), indent=1, separators=(",", ": "))) sys.exit() if options.long: print("The following images are installed.") for id, installedImage in user.getInstalledImages().items(): if not options.long: try: identifier = installedImage.getImageSource().getIdentifier( ) if not options.broken: print(identifier + " " + id) except KeyError: if options.broken: print(id) else: print("------------------") installedImage.describe() elif args[0] == 'repositories': if options.json: print( json.dumps( user.getRegistry().getRepositories().serializeToDict(), indent=1, separators=(",", ": "))) sys.exit() for name, repo in user.getRegistry().getRepositories().items(): if not options.long: print(repo.getDisplayName()) else: repo.describe() print("") else: sys.exit(args[0] + " cannot be listed. Option unrecognized.")
def removeOldImages(realArgs): """ Remove images that are installed, but are not associated with any subusers. Tests ----- **Setup:** >>> remove_old_images = __import__("remove-old-images")#import self >>> import subuser >>> import subuserlib.classes.user Check our assumptions about what subusers are installed in the test environment. We load a new user object each time we checked, because we are interested about whether the changes we want are present on disk. >>> user = subuserlib.classes.user.User() >>> subuserList = list(user.getRegistry().getSubusers().keys()) >>> subuserList.sort() >>> for sb in subuserList: ... print(sb) foo Add a ``bar`` subuser, which we will then remove. This will leave us with a leftover image. >>> subuser.subuser(["add","--accept","bar","bar@file:///home/travis/remote-test-repo"]) Adding subuser bar bar@file:///home/travis/remote-test-repo Adding new temporary repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. bar would like to have the following permissions: Description: Maintainer: Executable: /usr/bin/bar A - Accept and apply changes E - Apply changes and edit result A Checking if images need to be updated or installed... Checking if subuser bar is up to date. Installing bar ... Building... Building... Building... Successfully built 5 Building... Building... Building... Successfully built 6 Installed new image <6> for subuser bar Running garbage collector on temporary repositories... Check to see if subuser ``bar`` was successfully added. >>> user = subuserlib.classes.user.User() >>> subuserList = list(user.getRegistry().getSubusers().keys()) >>> subuserList.sort() >>> for sb in subuserList: ... print(sb) bar foo Check to see if the image for ``bar`` was also installed. >>> installedImages = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImages.sort() >>> for installedImage in installedImages: ... print(installedImage) bar foo Remove the ``bar`` subuser. >>> subuser.subuser(["remove","bar"]) Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... See that the image for ``bar`` was indeed left behind. >>> user = subuserlib.classes.user.User() >>> installedImages = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImages.sort() >>> for installedImage in installedImages: ... print(installedImage) bar foo Use dry-run to see which images are to be deleted. >>> remove_old_images.removeOldImages(["--dry-run"]) The following images are uneeded and would be deleted. DOCKER-ID : SUBUSER-ID Removing unneeded image 6 : bar@file:///home/travis/remote-test-repo Check to see that dry-run didn't actually remove the un-needed image. >>> user = subuserlib.classes.user.User() >>> installedImages = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImages.sort() >>> for installedImage in installedImages: ... print(installedImage) bar foo Add another subuser blah >>> subuser.subuser(["add","--accept","blah","foo@/home/travis/local-test-repo"]) Adding subuser blah foo@/home/travis/local-test-repo Adding new temporary repository /home/travis/local-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. blah would like to have the following permissions: Description: Maintainer: Executable: /usr/bin/foo A - Accept and apply changes E - Apply changes and edit result A Checking if images need to be updated or installed... Checking if subuser blah is up to date. Installing foo ... Building... Building... Building... Successfully built 7 Building... Building... Building... Successfully built 8 Installed new image <8> for subuser blah Running garbage collector on temporary repositories... Check to see if subuser ``blah`` was successfully added. >>> user = subuserlib.classes.user.User() >>> subuserList = list(user.getRegistry().getSubusers().keys()) >>> subuserList.sort() >>> for sb in subuserList: ... print(sb) blah foo Check to see if the image for ``blah`` was also installed. >>> installedImageList = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImageList.sort() >>> for installedImage in installedImageList: ... print(installedImage) bar foo foo Remove the ``blah`` subuser. >>> subuser.subuser(["remove","blah"]) Removing subuser blah If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... See that the image for ``blah`` was indeed left behind. >>> user = subuserlib.classes.user.User() >>> installedImageList = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImageList.sort() >>> for installedImage in installedImageList: ... print(installedImage) bar foo foo Now we use ``remove-old-images`` to remove images which belong to the local repository. >>> remove_old_images.removeOldImages(["--repo=/home/travis/local-test-repo"]) Removing unneeded image 8 : foo@/home/travis/local-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... Removing uneeded temporary repository: /home/travis/local-test-repo Now we use ``remove-old-images`` to clean up the rest of our un-needed installed images. >>> remove_old_images.removeOldImages([]) Removing unneeded image 6 : bar@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... Removing uneeded temporary repository: file:///home/travis/remote-test-repo And now the uneccesary ``bar`` image is gone. >>> user = subuserlib.classes.user.User() >>> installedImages = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImages.sort() >>> for installedImage in installedImages: ... print(installedImage) foo """ options,args = parseCliArgs(realArgs) user = subuserlib.classes.user.User() try: with user.getRegistry().getLock() as lockFileHandler: if options.dryrun: print("The following images are uneeded and would be deleted.") print("DOCKER-ID : SUBUSER-ID") repoId = options.repo if not repoId is None: if not repoId in user.getRegistry().getRepositories(): repo = subuserlib.resolve.lookupRepositoryByURI(user,options.repo) if repo is None: sys.exit("The repository <"+repoId+"> does not exist.") else: repoId = repo.getName() subuserlib.removeOldImages.removeOldImages(user=user,dryrun=options.dryrun,sourceRepoId=repoId) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.")
def update(realArgs): """ Update your subuser installation. Tests ----- **Setup:** >>> import os >>> import update,subuser,subuserlib.classes.gitRepository,repository Check initial test environment: >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'bar']) True Add a subuser who's image has a lot of dependencies. >>> subuser.subuser(["add","dependent","dependent@file:///home/travis/remote-test-repo"]) Adding subuser dependent dependent@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Installing dependency1 ... Building... Building... Building... Successfully built 10 Building... Building... Building... Successfully built 11 Installing intermediary ... Building... Building... Building... Successfully built 12 Building... Building... Building... Successfully built 13 Installing dependent ... Building... Building... Building... Successfully built 14 Building... Building... Building... Successfully built 15 Installed new image <15> for subuser dependent Running garbage collector on temporary repositories... Check that our new subuser was successfully added. >>> user = subuserlib.classes.user.User() >>> subuserNamesBeforeUpdate = user.getRegistry().getSubusers().keys() >>> set(subuserNamesBeforeUpdate) == set(['dependent', u'foo']) True And that its image, along with all of its dependencies were added as well. >>> installedImagesBeforeUpdate = [i.getImageSourceName() for i in user.getInstalledImages().values()] >>> set(installedImagesBeforeUpdate) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary']) True Running update, when there is nothing to be updated, does nothing. >>> update.update(["all"]) Updating... Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Checking for updates to: dependency1@file:///home/travis/remote-test-repo Checking for updates to: intermediary@file:///home/travis/remote-test-repo Checking for updates to: dependent@file:///home/travis/remote-test-repo Checking if subuser foo is up to date. Checking for updates to: foo@default Running garbage collector on temporary repositories... The same subusers are still installed. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(subuserNamesBeforeUpdate) True And the same images too. >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set(installedImagesBeforeUpdate) True Now we change the ImageSource for the ``dependent`` image. >>> with open(user.getRegistry().getRepositories()[u'1']["intermediary"].getSubuserImagefilePath(),mode="w") as subuserImagefile: ... _ = subuserImagefile.write("FROM-SUBUSER-IMAGE dependency2") And commit the changes to git. >>> repo1 = subuserlib.classes.gitRepository.GitRepository(user.getRegistry().getRepositories()[u'1'].getRepoPath()) >>> repo1.run(["commit","-a","-m","changed dependency for intermediate from dependency1 to dependency2"]) 0 Running an update after a change installs new images and registers them with their subusers. But it does not delete the old ones. >>> update.update(["all"]) Updating... Updated repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Installing dependency2 ... Building... Building... Building... Successfully built 16 Building... Building... Building... Successfully built 17 Installing intermediary ... Building... Building... Building... Successfully built 18 Building... Building... Building... Successfully built 19 Installing dependent ... Building... Building... Building... Successfully built 20 Building... Building... Building... Successfully built 21 Installed new image <21> for subuser dependent Checking if subuser foo is up to date. Checking for updates to: foo@default Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2', u'dependent']) True Old images are not deleted so that update lock-subuser-to and update rollback still work. In this example, dependency1 stays installed. Now we lock the dependent subuser and try changing it again. >>> update.update(["lock-subuser-to","dependent","HEAD"]) Locking subuser dependent to commit: HEAD Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... >>> with open(user.getRegistry().getRepositories()[u'1']["intermediary"].getSubuserImagefilePath(),mode="w") as subuserImagefile: ... _ = subuserImagefile.write("FROM-SUBUSER-IMAGE dependency3") And commit the changes to git. >>> repo1.run(["commit","-a","-m","changed dependency for intermediate from dependency2 to dependency3"]) 0 Running an update after a change does nothing because the affected subuser is locked. >>> update.update(["all"]) Updating... Updated repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser foo is up to date. Checking for updates to: foo@default Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2', u'dependent']) True When we unlock the subuser it gets updated imediately. >>> update.update(["unlock-subuser","dependent"]) Unlocking subuser dependent Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Installing dependency3 ... Building... Building... Building... Successfully built 22 Building... Building... Building... Successfully built 23 Installing intermediary ... Building... Building... Building... Successfully built 24 Building... Building... Building... Successfully built 25 Installing dependent ... Building... Building... Building... Successfully built 26 Building... Building... Building... Successfully built 27 Installed new image <27> for subuser dependent Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2',u'dependency3', u'dependent']) True """ options,args = parseCliArgs(realArgs) user = subuserlib.classes.user.User() if len(args) < 1: sys.exit("No arguments given. Please use subuser update -h for help.") elif ["all"] == args: try: with user.getRegistry().getLock(): subuserlib.update.updateAll(user) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif "subusers" == args[0]: try: with user.getRegistry().getLock(): subuserlib.update.updateSubusers(user,args[1:]) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif ["log"] == args: subuserlib.update.showLog(user) elif "lock-subuser-to" == args[0]: try: subuserName = args[1] commit = args[2] except KeyError: sys.exit("Wrong number of arguments. Expected a subuser name and a commit. Try running\nsubuser update --help\n for more info.") try: with user.getRegistry().getLock(): subuserlib.update.lockSubuser(user,subuserName=subuserName,commit=commit) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif "unlock-subuser" == args[0]: try: subuserName = args[1] except KeyError: sys.exit("Wrong number of arguments. Expected a subuser's name. Try running\nsubuser update --help\nfor more information.") try: with user.getRegistry().getLock(): subuserlib.update.unlockSubuser(user,subuserName=subuserName) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif "rollback" == args[0]: try: commit = args[1] except KeyError: sys.exit("Wrong number of arguments. Expected a commit. Try running \nsubuser update --help\nfor more info.") try: with user.getRegistry().getLock(): subuserlib.update.rollback(user,commit=commit) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif len(args) == 1: sys.exit(" ".join(args) + " is not a valid update subcommand. Please use subuser update -h for help.") else: sys.exit(" ".join(args) + " is not a valid update subcommand. Please use subuser update -h for help.")
def dryRun(args): """ Print the command that would have been run if this wasn't a dry run. >>> dry_run = __import__("dry-run") >>> dry_run.dryRunTestSetup() >>> import subuser >>> remove_old_images = __import__("remove-old-images") If we dry run the basic foo test subuser, we will see the generated pre-run Dockerfile and also the docker command that will launch our subuser. >>> dry_run.dryRun(["foo"]) The image will be prepared using the Dockerfile: FROM 2 RUN useradd --uid=1000 travis ;export exitstatus=$? ; if [ $exitstatus -eq 4 ] ; then echo uid exists ; elif [ $exitstatus -eq 9 ]; then echo username exists. ; else exit $exitstatus ; fi RUN test -d /home/travis || mkdir /home/travis && chown travis /home/travis <BLANKLINE> The command to launch the image is: docker 'run' '--rm' '-i' '-t' '-e' 'HOME=/home/travis/test-home' '--workdir=/home/travis/test-home' '--net=none' '--user=1000' '--hostname' '<random-hostname>' '--entrypoint' '/usr/bin/foo' '3' Running subusers installed through temporary repositories works as well. Here, we add a subuser named bar, run it, and then remove it again. >>> subuser.subuser(["add","bar","--accept","bar@file:///home/travis/remote-test-repo"]) Adding subuser bar bar@file:///home/travis/remote-test-repo Adding new temporary repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. bar would like to have the following permissions: Description: Maintainer: Executable: /usr/bin/bar A - Accept and apply changes E - Apply changes and edit result A Checking if images need to be updated or installed... Checking if subuser bar is up to date. Installing bar ... Building... Building... Building... Successfully built 4 Building... Building... Building... Successfully built 5 Installed new image <5> for subuser bar Running garbage collector on temporary repositories... The actual dry-run call. >>> dry_run.dryRun(["bar"]) The image will be prepared using the Dockerfile: FROM 5 RUN useradd --uid=1000 travis ;export exitstatus=$? ; if [ $exitstatus -eq 4 ] ; then echo uid exists ; elif [ $exitstatus -eq 9 ]; then echo username exists. ; else exit $exitstatus ; fi RUN test -d /home/travis || mkdir /home/travis && chown travis /home/travis <BLANKLINE> The command to launch the image is: docker 'run' '--rm' '-i' '-t' '-e' 'HOME=/home/travis/test-home' '--workdir=/home/travis/test-home' '--net=none' '--user=1000' '--hostname' '<random-hostname>' '--entrypoint' '/usr/bin/bar' '6' Cleanup. >>> subuser.subuser(["remove","bar"]) Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... >>> remove_old_images.removeOldImages([]) Removing unneeded image 5 : bar@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... Removing uneeded temporary repository: file:///home/travis/remote-test-repo """ if len(args) == 0 or {"help","-h","--help"} & set(args): print(helpString) sys.exit() subuserName = args[0] argsToPassToImage = args[1:] user = subuserlib.classes.user.User() if subuserName in user.getRegistry().getSubusers(): subuser = user.getRegistry().getSubusers()[subuserName] print("The image will be prepared using the Dockerfile:") print(subuser.getRunReadyImage().generateImagePreparationDockerfile()) print("The command to launch the image is:") print(subuser.getRuntime(os.environ).getPrettyCommand(argsToPassToImage)) else: sys.exit(subuserName + " not found.\n"+helpString+"\n The following subusers are available for use:"+str(user.getRegistry().getSubusers().keys()))
def removeOldImages(realArgs): """ Remove images that are installed, but are not associated with any subusers. Tests ----- **Setup:** >>> remove_old_images = __import__("remove-old-images")#import self >>> import subuser >>> import subuserlib.classes.user Check our assumptions about what subusers are installed in the test environment. We load a new user object each time we checked, because we are interested about whether the changes we want are present on disk. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(["foo"]) True Add a ``bar`` subuser, which we will then remove. This will leave us with a leftover image. >>> subuser.subuser(["add","bar","bar@file:///home/travis/remote-test-repo"]) Adding subuser bar bar@file:///home/travis/remote-test-repo Adding new temporary repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Installing bar ... Building... Building... Building... Successfully built 5 Building... Building... Building... Successfully built 6 Installed new image for subuser bar Running garbage collector on temporary repositories... Check to see if subuser ``bar`` was successfully added. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo', 'bar']) True Check to see if the image for ``bar`` was also installed. >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'bar']) True Remove the ``bar`` subuser. >>> subuser.subuser(["remove","bar"]) Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... See that the image for ``bar`` was indeed left behind. >>> user = subuserlib.classes.user.User() >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'bar']) True Use dry-run to see which images are to be deleted. >>> remove_old_images.removeOldImages(["--dry-run"]) The following images are uneeded and would be deleted. DOCKER-ID : SUBUSER-ID Removing unneeded image 6 : bar@file:///home/travis/remote-test-repo Now we use ``remove-old-images`` to clean up our installed images. >>> remove_old_images.removeOldImages([]) Removing unneeded image 6 : bar@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Running garbage collector on temporary repositories... Removing uneeded temporary repository: file:///home/travis/remote-test-repo And now the uneccesary ``bar`` image is gone. >>> user = subuserlib.classes.user.User() >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo']) True """ options, args = parseCliArgs(realArgs) user = subuserlib.classes.user.User() try: with user.getRegistry().getLock() as lockFileHandler: if options.dryrun: print("The following images are uneeded and would be deleted.") print("DOCKER-ID : SUBUSER-ID") subuserlib.removeOldImages.removeOldImages(user=user, dryrun=options.dryrun) except subuserlib.portalocker.portalocker.LockException: sys.exit( "Another subuser process is currently running and has a lock on the registry. Please try again later." )
def remove(user,subuserName): if subuserName in user.getRegistry().getSubusers(): user.getRegistry().logChange("Removing subuser "+subuserName) subuserHome = user.getRegistry().getSubusers()[subuserName].getHomeDirOnHost() if subuserHome: user.getRegistry().logChange(" If you wish to remove the subusers home directory, issule the command $ rm -r "+subuserHome) user.getRegistry().logChange(" If you wish to remove the subusers image, issue the command $ subuser remove-old-images") del user.getRegistry().getSubusers()[subuserName] subuserlib.verify.verify(user) user.getRegistry().commit() else: sys.exit("Cannot remove: subuser "+subuserName+" does not exist.")
def list(sysargs): """ List various things: image sources, subusers, ect. >>> import sys >>> list = __import__("subuser-list") #import self Listing available images lists the images along with their default permissions. >>> list.list(["available"]) Images available for instalation from the repo: default foo@default Description: Maintainer: Executable: /usr/bin/foo Similar result when listing subusers. >>> list.list(["subusers"]) The following subusers are registered. Subuser: foo ------------------ foo@default Description: Maintainer: Executable: /usr/bin/foo <BLANKLINE> And listing installed images: >>> list.list(["installed-images"]) The following images are installed. ------------------ Image Id: 2 Image source: foo@default Last update time: 1 > list.list(["repositories"]) Repository: default ------------ Cloned from: file:///home/travis/default-test-repo Currently at commit: 72e7d9c17192d47b2b2344d9eb8a325262d738fe In all cases, there is a ``--short`` option. >>> list.list(["subusers","--short"]) foo >>> list.list(["available","--short"]) foo@default You can specify which repository to list image sources from. >>> list.list(["available","default","--short"]) foo@default When listing available image sources, refering to a repository via a URI works as well. >>> list.list(["available","file:///home/travis/version-constrained-test-repo","--short"]) Adding new temporary repository file:///home/travis/version-constrained-test-repo bop@file:///home/travis/version-constrained-test-repo >>> list.list(["installed-images","--short"]) foo@default 2 >>> list.list(["repositories","--short"]) default """ options,args = parseCliArgs(sysargs) if len(args)==0: sys.exit("Nothing to list. Issue this command with the -h argument for help.") user = subuserlib.classes.user.User() if args[0] == 'available': if len(args) > 1: reposToList = args[1:] else: reposToList = user.getRegistry().getRepositories().keys() if options.json: availableDict = {} for repoIdentifier in reposToList: if repoIdentifier in user.getRegistry().getRepositories(): temp = False else: temp = True repository = subuserlib.resolve.resolveRepository(user,repoIdentifier) availableDict[repository.getName()] = repository.serializeToDict() if temp: repository.removeGitRepo() print(json.dumps(availableDict,indent=1,separators=(",",": "))) sys.exit() for repoIdentifier in reposToList: if repoIdentifier in user.getRegistry().getRepositories(): temp = False else: temp = True repository = subuserlib.resolve.resolveRepository(user,repoIdentifier) if not options.short: print("Images available for instalation from the repo: " + repository.getName()) for _,imageSource in repository.items(): if options.short: print(imageSource.getIdentifier()) else: imageSource.describe() if temp: repository.removeGitRepo() elif args[0] == 'subusers': if options.json: print(json.dumps(user.getRegistry().getSubusers().serializeToDict(),indent=1,separators=(",",": "))) sys.exit() if not options.short: print("The following subusers are registered.") for name,subuser in user.getRegistry().getSubusers().items(): if options.internal or not name.startswith("!"): if options.short: print(name) else: subuser.describe() elif args[0] == 'installed-images': if options.json: print(json.dumps(user.getInstalledImages().serializeToDict(),indent=1,separators=(",",": "))) sys.exit() if not options.short: print("The following images are installed.") for id,installedImage in user.getInstalledImages().items(): if options.short: try: identifier = installedImage.getImageSource().getIdentifier() if not options.broken: print(identifier+" "+id) except KeyError: if options.broken: print(id) else: print("------------------") installedImage.describe() elif args[0] == 'repositories': if options.json: print(json.dumps(user.getRegistry().getRepositories().serializeToDict(),indent=1,separators=(",",": "))) sys.exit() for name,repo in user.getRegistry().getRepositories().items(): if options.short: print(repo.getDisplayName()) else: repo.describe() print("")
def verify(realArgs): options, arguments = parseCliArgs(realArgs) user = subuserlib.classes.user.User() subuserlib.verify.verify(user) user.getRegistry().commit()
def update(realArgs): """ Update your subuser installation. Tests ----- **Setup:** >>> import os >>> import update,subuser,subuserlib.classes.gitRepository,repository Check initial test environment: >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'bar']) True Add a subuser who's image has a lot of dependencies. >>> subuser.subuser(["add","--accept","dependent","dependent@file:///home/travis/remote-test-repo"]) Adding subuser dependent dependent@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. dependent would like to have the following permissions: Description: a dependent Maintainer: Is a library. Moderate permissions(These are probably safe): - user-dirs: To access to the following user directories: '~/Downloads' - sound-card: To access to your soundcard, can play sounds/record sound. Liberal permissions(These may pose a security risk): - x11: To display X11 windows and interact with your X11 server directly(log keypresses, read over your shoulder, steal your passwords, controll your computer ect.) - system-dirs: To read and write to the host's `/var/log` directory, mounted in the container as:`/var/log` WARNING: this subuser has full access to your system when run. - privileged: To have full access to your system. To even do things as root outside of its container. A - Accept and apply changes E - Apply changes and edit result A Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Installing dependency1 ... Building... Building... Building... Successfully built 13 Building... Building... Building... Successfully built 14 Installing intermediary ... Building... Building... Building... Successfully built 15 Building... Building... Building... Successfully built 16 Installing dependent ... Building... Building... Building... Successfully built 17 Building... Building... Building... Successfully built 18 Installed new image <18> for subuser dependent Running garbage collector on temporary repositories... Check that our new subuser was successfully added. >>> user = subuserlib.classes.user.User() >>> subuserNamesBeforeUpdate = user.getRegistry().getSubusers().keys() >>> set(subuserNamesBeforeUpdate) == set(['dependent', u'foo']) True And that its image, along with all of its dependencies were added as well. >>> installedImagesBeforeUpdate = [i.getImageSourceName() for i in user.getInstalledImages().values()] >>> set(installedImagesBeforeUpdate) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary']) True Running update, when there is nothing to be updated, does nothing. >>> update.update(["all","--accept"]) Updating... Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Checking for updates to: dependency1@file:///home/travis/remote-test-repo Checking for updates to: intermediary@file:///home/travis/remote-test-repo Checking for updates to: dependent@file:///home/travis/remote-test-repo Checking if subuser foo is up to date. Checking for updates to: foo@default Running garbage collector on temporary repositories... The same subusers are still installed. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(subuserNamesBeforeUpdate) True And the same images too. >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set(installedImagesBeforeUpdate) True However, if we change ``dependent``'s image source's permissions, the user is asked to approve the new permissions: >>> permissions = user.getRegistry().getRepositories()[u'1']["dependent"].getPermissions() >>> del permissions["sound-card"] >>> permissions["user-dirs"] = ["Images","Downloads"] >>> permissions.save() >>> repo1 = subuserlib.classes.gitRepository.GitRepository(user.getRegistry().getRepositories()[u'1'].getRepoPath()) >>> repo1.run(["commit","-a","-m","changed dependent's permissions"]) 0 >>> update.update(["all","--accept"]) Updating... Updated repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. dependent would like to add/change the following permissions: - To access to the following user directories: '~/Images' '~/Downloads' dependent no longer needs the following permissions: - To access to your soundcard, can play sounds/record sound. A - Accept and apply changes E - Apply changes and edit result e - Ignore request and edit permissions by hand A Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Checking for updates to: dependency1@file:///home/travis/remote-test-repo Checking for updates to: intermediary@file:///home/travis/remote-test-repo Checking for updates to: dependent@file:///home/travis/remote-test-repo Checking if subuser foo is up to date. Checking for updates to: foo@default Running garbage collector on temporary repositories... Now we change the ImageSource for the ``intermediary`` image. >>> with open(user.getRegistry().getRepositories()[u'1']["intermediary"].getSubuserImagefilePath(),mode="w") as subuserImagefile: ... _ = subuserImagefile.write("FROM-SUBUSER-IMAGE dependency2") And commit the changes to git. >>> repo1.run(["commit","-a","-m","changed dependency for intermediate from dependency1 to dependency2"]) 0 Running an update after a change installs new images and registers them with their subusers. But it does not delete the old ones. >>> update.update(["all","--accept"]) Updating... Updated repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Installing dependency2 ... Building... Building... Building... Successfully built 21 Building... Building... Building... Successfully built 22 Installing intermediary ... Building... Building... Building... Successfully built 23 Building... Building... Building... Successfully built 24 Installing dependent ... Building... Building... Building... Successfully built 25 Building... Building... Building... Successfully built 26 Installed new image <26> for subuser dependent Checking if subuser foo is up to date. Checking for updates to: foo@default Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2', u'dependent']) True Old images are not deleted so that update lock-subuser-to and update rollback still work. In this example, dependency1 stays installed. Now we lock the dependent subuser and try changing it again. >>> update.update(["lock-subuser-to","dependent","HEAD"]) Locking subuser dependent to commit: HEAD Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... >>> with open(user.getRegistry().getRepositories()[u'1']["intermediary"].getSubuserImagefilePath(),mode="w") as subuserImagefile: ... _ = subuserImagefile.write("FROM-SUBUSER-IMAGE dependency3") And commit the changes to git. >>> repo1.run(["commit","-a","-m","changed dependency for intermediate from dependency2 to dependency3"]) 0 Running an update after a change does nothing because the affected subuser is locked. >>> update.update(["all","--accept"]) Updating... Updated repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser foo is up to date. Checking for updates to: foo@default Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2', u'dependent']) True When we unlock the subuser it gets updated imediately. >>> update.update(["unlock-subuser","--accept","dependent"]) Unlocking subuser dependent Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Installing dependency3 ... Building... Building... Building... Successfully built 28 Building... Building... Building... Successfully built 29 Installing intermediary ... Building... Building... Building... Successfully built 30 Building... Building... Building... Successfully built 31 Installing dependent ... Building... Building... Building... Successfully built 32 Building... Building... Building... Successfully built 33 Installed new image <33> for subuser dependent Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2',u'dependency3', u'dependent']) True """ options,args = parseCliArgs(realArgs) user = subuserlib.classes.user.User() permissionsAccepter = AcceptPermissionsAtCLI(user,alwaysAccept = options.accept) if len(args) < 1: sys.exit("No arguments given. Please use subuser update -h for help.") elif ["all"] == args: try: with user.getRegistry().getLock(): subuserlib.update.updateAll(user,permissionsAccepter=permissionsAccepter) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif "subusers" == args[0]: try: with user.getRegistry().getLock(): subuserlib.update.updateSubusers(user,args[1:],permissionsAccepter=permissionsAccepter) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif ["log"] == args: subuserlib.update.showLog(user) elif "lock-subuser-to" == args[0]: try: subuserName = args[1] commit = args[2] except KeyError: sys.exit("Wrong number of arguments. Expected a subuser name and a commit. Try running\nsubuser update --help\n for more info.") try: with user.getRegistry().getLock(): subuserlib.update.lockSubuser(user,subuserName=subuserName,commit=commit) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif "unlock-subuser" == args[0]: try: subuserName = args[1] except KeyError: sys.exit("Wrong number of arguments. Expected a subuser's name. Try running\nsubuser update --help\nfor more information.") try: with user.getRegistry().getLock(): subuserlib.update.unlockSubuser(user,subuserName=subuserName,permissionsAccepter=permissionsAccepter) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif "rollback" == args[0]: try: commit = args[1] except KeyError: sys.exit("Wrong number of arguments. Expected a commit. Try running \nsubuser update --help\nfor more info.") try: with user.getRegistry().getLock(): subuserlib.update.rollback(user,commit=commit) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif len(args) == 1: sys.exit(" ".join(args) + " is not a valid update subcommand. Please use subuser update -h for help.") else: sys.exit(" ".join(args) + " is not a valid update subcommand. Please use subuser update -h for help.")
def remove(user,subuserNames): didSomething = False for subuserName in subuserNames: if subuserName in user.getRegistry().getSubusers(): user.getRegistry().logChange("Removing subuser "+str(subuserName)) try: subuserHome = user.getRegistry().getSubusers()[subuserName].getHomeDirOnHost() if subuserHome: user.getRegistry().logChange(" If you wish to remove the subusers home directory, issule the command $ rm -r "+subuserHome) except: pass user.getRegistry().logChange(" If you wish to remove the subusers image, issue the command $ subuser remove-old-images") del user.getRegistry().getSubusers()[subuserName] didSomething = True else: print("Cannot remove: subuser "+subuserName+" does not exist.") if didSomething: subuserlib.verify.verify(user) user.getRegistry().commit()
def remove(user,name): user.getRegistry().getRepositories().removeRepository(name)
def runCommand(sysargs): """ List various things: image sources, subusers, ect. """ options, args = parseCliArgs(sysargs) if len(args) == 0: sys.exit( "Nothing to list. Issue this command with the -h argument for help." ) user = subuserlib.classes.user.User() if args[0] == 'available': if len(args) > 1: reposToList = args[1:] else: reposToList = user.getRegistry().getRepositories().keys() availableDict = {} for repoIdentifier in reposToList: try: repoIdentifier = repoIdentifier.decode("utf-8") except AttributeError: pass if repoIdentifier in user.getRegistry().getRepositories(): temp = False else: temp = True try: repository = subuserlib.resolve.resolveRepository( user, repoIdentifier) except (OSError, subuserlib.resolve.ResolutionError): sys.exit("Repository id: " + repoIdentifier + " could not be resolved.") if options.json: availableDict[ repository.getName()] = repository.serializeToDict() else: if options.long: subuserlib.print.printWithoutCrashing( "Images available for instalation from the repo: " + repository.getName()) for imageSource in repository.getSortedList(): if not options.long: identifier = imageSource.getIdentifier() subuserlib.print.printWithoutCrashing(identifier) else: try: imageSource.describe() except SyntaxError as e: subuserlib.print.printWithoutCrashing(str(e)) subuserlib.print.printWithoutCrashing( "Cannot describe this image source as loading it is forbidden." ) if temp: repository.removeGitRepo() if options.json: subuserlib.print.printWithoutCrashing( json.dumps(availableDict, indent=1, separators=(",", ": "))) sys.exit() elif args[0] == 'subusers': if options.json: subuserlib.print.printWithoutCrashing( json.dumps(user.getRegistry().getSubusers().serializeToDict(), indent=1, separators=(",", ": "))) sys.exit() if options.long: subuserlib.print.printWithoutCrashing( "The following subusers are registered.") for name, subuser in user.getRegistry().getSubusers().items(): if options.internal or not name.startswith("!"): if not options.long: subuserlib.print.printWithoutCrashing(name) else: subuser.describe() elif args[0] == 'installed-images': if options.json: subuserlib.print.printWithoutCrashing( json.dumps(user.getInstalledImages().serializeToDict(), indent=1, separators=(",", ": "))) sys.exit() if options.long: subuserlib.print.printWithoutCrashing( "The following images are installed.") for id, installedImage in user.getInstalledImages().items(): if not options.long: try: identifier = installedImage.getImageSource().getIdentifier( ) if not options.broken: subuserlib.print.printWithoutCrashing(identifier + " " + id) except KeyError: if options.broken: subuserlib.print.printWithoutCrashing(id) else: subuserlib.print.printWithoutCrashing("------------------") installedImage.describe() elif args[0] == 'repositories': if options.json: subuserlib.print.printWithoutCrashing( json.dumps( user.getRegistry().getRepositories().serializeToDict(), indent=1, separators=(",", ": "))) sys.exit() for name, repo in user.getRegistry().getRepositories().items(): if not options.long: subuserlib.print.printWithoutCrashing(repo.getDisplayName()) else: repo.describe() subuserlib.print.printWithoutCrashing("") else: sys.exit( args[0] + " cannot be listed. Option unrecognized. Use --help for help.")
def list(sysargs): """ List various things: image sources, subusers, ect. >>> import sys >>> import list #import self Listing available images lists the images along with their default permissions. >>> list.list(["available"]) Images available for instalation from the repo: default foo@default Description: Maintainer: Executable: /usr/bin/foo Similar result when listing subusers. >>> list.list(["subusers"]) The following subusers are registered. Subuser: foo ------------------ foo@default Description: Maintainer: Executable: /usr/bin/foo <BLANKLINE> And listing installed images: >>> list.list(["installed-images"]) The following images are installed. ------------------ Image Id: 2 Image source: foo@default Last update time: 1 > list.list(["repositories"]) Repository: default ------------ Cloned from: file:///home/travis/default-test-repo Currently at commit: 72e7d9c17192d47b2b2344d9eb8a325262d738fe In all cases, there is a ``--short`` option. >>> list.list(["subusers","--short"]) foo >>> list.list(["available","--short"]) foo@default >>> list.list(["installed-images","--short"]) foo@default 2 >>> list.list(["repositories","--short"]) default """ options,args = parseCliArgs(sysargs) if len(args)==0: sys.exit("Nothing to list. Issue this command with the -h argument for help.") user = subuserlib.classes.user.User() if 'available' in args: for repoName,repository in user.getRegistry().getRepositories().items(): if not options.short: print("Images available for instalation from the repo: " + repoName) for _,imageSource in repository.items(): if options.short: print(imageSource.getIdentifier()) else: imageSource.describe() if 'subusers' in args: if not options.short: print("The following subusers are registered.") for name,subuser in user.getRegistry().getSubusers().items(): if options.internal or not name.startswith("!"): if options.short: print(name) else: subuser.describe() if 'installed-images' in args: if not options.short: print("The following images are installed.") for id,installedImage in user.getInstalledImages().items(): if options.short: try: identifier = installedImage.getImageSource().getIdentifier() if not options.broken: print(identifier+" "+id) except KeyError: if options.broken: print(id) else: print("------------------") installedImage.describe() if 'repositories' in args: for name,repo in user.getRegistry().getRepositories().items(): if options.short: print(repo.getDisplayName()) else: repo.describe() print("")
def removeOldImages(realArgs): """ Remove images that are installed, but are not associated with any subusers. Tests ----- **Setup:** >>> remove_old_images = __import__("remove-old-images")#import self >>> import subuser >>> import subuserlib.classes.user Check our assumptions about what subusers are installed in the test environment. We load a new user object each time we checked, because we are interested about whether the changes we want are present on disk. >>> user = subuserlib.classes.user.User() >>> subuserList = list(user.getRegistry().getSubusers().keys()) >>> subuserList.sort() >>> for sb in subuserList: ... print(sb) foo Add a ``bar`` subuser, which we will then remove. This will leave us with a leftover image. >>> subuser.subuser(["add","--accept","bar","bar@file:///home/travis/remote-test-repo"]) Adding subuser bar bar@file:///home/travis/remote-test-repo Adding new temporary repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. bar would like to have the following permissions: Description: Maintainer: Executable: /usr/bin/bar A - Accept and apply changes E - Apply changes and edit result A Checking if images need to be updated or installed... Checking if subuser bar is up to date. Installing bar ... Building... Building... Building... Successfully built 5 Building... Building... Building... Successfully built 6 Installed new image <6> for subuser bar Running garbage collector on temporary repositories... Check to see if subuser ``bar`` was successfully added. >>> user = subuserlib.classes.user.User() >>> subuserList = list(user.getRegistry().getSubusers().keys()) >>> subuserList.sort() >>> for sb in subuserList: ... print(sb) bar foo Check to see if the image for ``bar`` was also installed. >>> installedImages = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImages.sort() >>> for installedImage in installedImages: ... print(installedImage) bar foo Remove the ``bar`` subuser. >>> subuser.subuser(["remove","bar"]) Removing subuser bar If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... See that the image for ``bar`` was indeed left behind. >>> user = subuserlib.classes.user.User() >>> installedImages = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImages.sort() >>> for installedImage in installedImages: ... print(installedImage) bar foo Use dry-run to see which images are to be deleted. >>> remove_old_images.removeOldImages(["--dry-run"]) The following images are uneeded and would be deleted. DOCKER-ID : SUBUSER-ID Removing unneeded image 6 : bar@file:///home/travis/remote-test-repo Check to see that dry-run didn't actually remove the un-needed image. >>> user = subuserlib.classes.user.User() >>> installedImages = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImages.sort() >>> for installedImage in installedImages: ... print(installedImage) bar foo Add another subuser blah >>> subuser.subuser(["add","--accept","blah","foo@/home/travis/local-test-repo"]) Adding subuser blah foo@/home/travis/local-test-repo Adding new temporary repository /home/travis/local-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. blah would like to have the following permissions: Description: Maintainer: Executable: /usr/bin/foo A - Accept and apply changes E - Apply changes and edit result A Checking if images need to be updated or installed... Checking if subuser blah is up to date. Installing foo ... Building... Building... Building... Successfully built 8 Building... Building... Building... Successfully built 9 Installed new image <9> for subuser blah Running garbage collector on temporary repositories... Check to see if subuser ``blah`` was successfully added. >>> user = subuserlib.classes.user.User() >>> subuserList = list(user.getRegistry().getSubusers().keys()) >>> subuserList.sort() >>> for sb in subuserList: ... print(sb) blah foo Check to see if the image for ``blah`` was also installed. >>> installedImageList = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImageList.sort() >>> for installedImage in installedImageList: ... print(installedImage) bar foo foo Remove the ``blah`` subuser. >>> subuser.subuser(["remove","blah"]) Removing subuser blah If you wish to remove the subusers image, issue the command $ subuser remove-old-images Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... See that the image for ``blah`` was indeed left behind. >>> user = subuserlib.classes.user.User() >>> installedImageList = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImageList.sort() >>> for installedImage in installedImageList: ... print(installedImage) bar foo foo Now we use ``remove-old-images`` to remove images which belong to the local repository. >>> remove_old_images.removeOldImages(["--repo=/home/travis/local-test-repo"]) Removing unneeded image 9 : foo@/home/travis/local-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... Removing uneeded temporary repository: /home/travis/local-test-repo Now we use ``remove-old-images`` to clean up the rest of our un-needed installed images. >>> remove_old_images.removeOldImages([]) Removing unneeded image 6 : bar@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... Removing uneeded temporary repository: file:///home/travis/remote-test-repo And now the uneccesary ``bar`` image is gone. >>> user = subuserlib.classes.user.User() >>> installedImages = list([i.getImageSourceName() for i in user.getInstalledImages().values()]) >>> installedImages.sort() >>> for installedImage in installedImages: ... print(installedImage) foo """ options, args = parseCliArgs(realArgs) user = subuserlib.classes.user.User() try: with user.getRegistry().getLock() as lockFileHandler: if options.dryrun: print("The following images are uneeded and would be deleted.") print("DOCKER-ID : SUBUSER-ID") repoId = options.repo if not repoId is None: if not repoId in user.getRegistry().getRepositories(): repo = subuserlib.resolve.lookupRepositoryByURI( user, options.repo) if repo is None: sys.exit("The repository <" + repoId + "> does not exist.") else: repoId = repo.getName() subuserlib.removeOldImages.removeOldImages(user=user, dryrun=options.dryrun, sourceRepoId=repoId) except subuserlib.portalocker.portalocker.LockException: sys.exit( "Another subuser process is currently running and has a lock on the registry. Please try again later." )
def repository(sysargs): """ Manage named subuser repositories. Tests ----- **Setup:** >>> import repository #import self Check our assumptions about the initial state of the test environment. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getRepositories().keys()) == set([u'default']) True Add a new repository named ``remote-repo``. >>> repository.repository(["add","remote-repo","file:///home/travis/remote-test-repo"]) Adding new repository remote-repo See that it was actually successfully added. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getRepositories().keys()) == set([u'default', 'remote-repo']) True Remove the ``remote-repo`` repository. >>> repository.repository(["remove","remote-repo"]) Removing repository remote-repo See that it was actually removed. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getRepositories().keys()) == set([u'default']) True Add a new repository named ``local-repo`` which is just a folder on the local system. >>> repository.repository(["add","local-repo","/home/travis/remote-test-repo"]) Adding new repository local-repo See that it was actually successfully added. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getRepositories().keys()) == set([u'default', 'local-repo']) True Remove the ``local-repo`` repository. >>> repository.repository(["remove","local-repo"]) Removing repository local-repo See that it was actually removed. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getRepositories().keys()) == set([u'default']) True """ options, args = parseCliArgs(sysargs) user = subuserlib.classes.user.User() action = args[0] if action == "add": if not len(args) == 3: sys.exit("Use subuser repository --help for help.") name = args[1] url = args[2] try: with user.getRegistry().getLock(): subuserlib.repository.add(user, name, url) except subuserlib.portalocker.portalocker.LockException: sys.exit( "Another subuser process is currently running and has a lock on the registry. Please try again later." ) elif action == "remove": if not len(args) == 2: sys.exit("Use subuser repository --help for help.") name = args[1] try: with user.getRegistry().getLock(): subuserlib.repository.remove(user, name) except subuserlib.portalocker.portalocker.LockException: sys.exit( "Another subuser process is currently running and has a lock on the registry. Please try again later." ) else: sys.exit("Action " + args[0] + " not supported. Please see:\n subuser repository --help")
def update(realArgs): """ Update your subuser installation. Tests ----- **Setup:** >>> import os >>> import update,subuser,subuserlib.classes.gitRepository,repository Check initial test environment: >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set([u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'bar']) True Add a subuser who's image has a lot of dependencies. >>> subuser.subuser(["add","--accept","dependent","dependent@file:///home/travis/remote-test-repo"]) Adding subuser dependent dependent@file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. dependent would like to have the following permissions: Description: a dependent Maintainer: Is a library. Moderate permissions(These are probably safe): - user-dirs: To access to the following user directories: '~/Downloads' - sound-card: To access to your soundcard, can play sounds/record sound. Liberal permissions(These may pose a security risk): - x11: To display X11 windows and interact with your X11 server directly(log keypresses, read over your shoulder, steal your passwords, controll your computer ect.) - system-dirs: To read and write to the host's `/var/log` directory, mounted in the container as:`/var/log` WARNING: this subuser has full access to your system when run. - privileged: To have full access to your system. To even do things as root outside of its container. A - Accept and apply changes E - Apply changes and edit result A Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Installing dependency1 ... Building... Building... Building... Successfully built 11 Building... Building... Building... Successfully built 12 Installing intermediary ... Building... Building... Building... Successfully built 13 Building... Building... Building... Successfully built 14 Installing dependent ... Building... Building... Building... Successfully built 15 Building... Building... Building... Successfully built 16 Installed new image <16> for subuser dependent Running garbage collector on temporary repositories... Check that our new subuser was successfully added. >>> user = subuserlib.classes.user.User() >>> subuserNamesBeforeUpdate = user.getRegistry().getSubusers().keys() >>> set(subuserNamesBeforeUpdate) == set(['dependent', u'foo']) True And that its image, along with all of its dependencies were added as well. >>> installedImagesBeforeUpdate = [i.getImageSourceName() for i in user.getInstalledImages().values()] >>> set(installedImagesBeforeUpdate) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary']) True Running update, when there is nothing to be updated, does nothing. >>> update.update(["all","--accept"]) Updating... Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Checking for updates to: dependency1@file:///home/travis/remote-test-repo Checking for updates to: intermediary@file:///home/travis/remote-test-repo Checking for updates to: dependent@file:///home/travis/remote-test-repo Checking if subuser foo is up to date. Checking for updates to: foo@default Running garbage collector on temporary repositories... The same subusers are still installed. >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(subuserNamesBeforeUpdate) True And the same images too. >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set(installedImagesBeforeUpdate) True However, if we change ``dependent``'s image source's permissions, the user is asked to approve the new permissions: >>> permissions = user.getRegistry().getRepositories()[u'1']["dependent"].getPermissions() >>> del permissions["sound-card"] >>> permissions["user-dirs"] = ["Images","Downloads"] >>> permissions.save() >>> repo1 = subuserlib.classes.gitRepository.GitRepository(user.getRegistry().getRepositories()[u'1'].getRepoPath()) >>> repo1.run(["commit","-a","-m","changed dependent's permissions"]) 0 >>> update.update(["all","--accept"]) Updating... Updated repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. dependent would like to add/change the following permissions: - To access to the following user directories: '~/Images' '~/Downloads' dependent no longer needs the following permissions: - To access to your soundcard, can play sounds/record sound. A - Accept and apply changes E - Apply changes and edit result e - Ignore request and edit permissions by hand A Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Checking for updates to: dependency1@file:///home/travis/remote-test-repo Checking for updates to: intermediary@file:///home/travis/remote-test-repo Checking for updates to: dependent@file:///home/travis/remote-test-repo Checking if subuser foo is up to date. Checking for updates to: foo@default Running garbage collector on temporary repositories... Now we change the ImageSource for the ``intermediary`` image. >>> with open(user.getRegistry().getRepositories()[u'1']["intermediary"].getSubuserImagefilePath(),mode="w") as subuserImagefile: ... _ = subuserImagefile.write("FROM-SUBUSER-IMAGE dependency2") And commit the changes to git. >>> repo1.run(["commit","-a","-m","changed dependency for intermediate from dependency1 to dependency2"]) 0 Running an update after a change installs new images and registers them with their subusers. But it does not delete the old ones. >>> update.update(["all","--accept"]) Updating... Updated repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Installing dependency2 ... Building... Building... Building... Successfully built 17 Building... Building... Building... Successfully built 18 Installing intermediary ... Building... Building... Building... Successfully built 19 Building... Building... Building... Successfully built 20 Installing dependent ... Building... Building... Building... Successfully built 21 Building... Building... Building... Successfully built 22 Installed new image <22> for subuser dependent Checking if subuser foo is up to date. Checking for updates to: foo@default Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2', u'dependent']) True Old images are not deleted so that update lock-subuser-to and update rollback still work. In this example, dependency1 stays installed. Now we lock the dependent subuser and try changing it again. >>> update.update(["lock-subuser-to","dependent","HEAD"]) Locking subuser dependent to commit: HEAD Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Running garbage collector on temporary repositories... >>> with open(user.getRegistry().getRepositories()[u'1']["intermediary"].getSubuserImagefilePath(),mode="w") as subuserImagefile: ... _ = subuserImagefile.write("FROM-SUBUSER-IMAGE dependency3") And commit the changes to git. >>> repo1.run(["commit","-a","-m","changed dependency for intermediate from dependency2 to dependency3"]) 0 Running an update after a change does nothing because the affected subuser is locked. >>> update.update(["all","--accept"]) Updating... Updated repository file:///home/travis/remote-test-repo Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser foo is up to date. Checking for updates to: foo@default Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2', u'dependent']) True When we unlock the subuser it gets updated imediately. >>> update.update(["unlock-subuser","--accept","dependent"]) Unlocking subuser dependent Verifying subuser configuration. Verifying registry consistency... Unregistering any non-existant installed images. Checking if images need to be updated or installed... Checking if subuser dependent is up to date. Installing dependency3 ... Building... Building... Building... Successfully built 23 Building... Building... Building... Successfully built 24 Installing intermediary ... Building... Building... Building... Successfully built 25 Building... Building... Building... Successfully built 26 Installing dependent ... Building... Building... Building... Successfully built 27 Building... Building... Building... Successfully built 28 Installed new image <28> for subuser dependent Running garbage collector on temporary repositories... >>> user = subuserlib.classes.user.User() >>> set(user.getRegistry().getSubusers().keys()) == set(['dependent', u'foo']) True >>> set([i.getImageSourceName() for i in user.getInstalledImages().values()]) == set([u'foo', u'dependency1', u'bar', u'dependent', u'intermediary', u'intermediary', u'dependency2',u'dependency3', u'dependent']) True """ options,args = parseCliArgs(realArgs) user = subuserlib.classes.user.User() permissionsAccepter = AcceptPermissionsAtCLI(user,alwaysAccept = options.accept) if len(args) < 1: sys.exit("No arguments given. Please use subuser update -h for help.") elif ["all"] == args: try: with user.getRegistry().getLock(): subuserlib.update.updateAll(user,permissionsAccepter=permissionsAccepter) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif "subusers" == args[0]: try: with user.getRegistry().getLock(): subuserlib.update.updateSubusers(user,args[1:],permissionsAccepter=permissionsAccepter) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif ["log"] == args: subuserlib.update.showLog(user) elif "lock-subuser-to" == args[0]: try: subuserName = args[1] commit = args[2] except KeyError: sys.exit("Wrong number of arguments. Expected a subuser name and a commit. Try running\nsubuser update --help\n for more info.") try: with user.getRegistry().getLock(): subuserlib.update.lockSubuser(user,subuserName=subuserName,commit=commit) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif "unlock-subuser" == args[0]: try: subuserName = args[1] except KeyError: sys.exit("Wrong number of arguments. Expected a subuser's name. Try running\nsubuser update --help\nfor more information.") try: with user.getRegistry().getLock(): subuserlib.update.unlockSubuser(user,subuserName=subuserName,permissionsAccepter=permissionsAccepter) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif "rollback" == args[0]: try: commit = args[1] except KeyError: sys.exit("Wrong number of arguments. Expected a commit. Try running \nsubuser update --help\nfor more info.") try: with user.getRegistry().getLock(): subuserlib.update.rollback(user,commit=commit) except subuserlib.portalocker.portalocker.LockException: sys.exit("Another subuser process is currently running and has a lock on the registry. Please try again later.") elif len(args) == 1: sys.exit(" ".join(args) + " is not a valid update subcommand. Please use subuser update -h for help.") else: sys.exit(" ".join(args) + " is not a valid update subcommand. Please use subuser update -h for help.")