From 4bcfead253b70fb0611e8fe520203ae2d277d91a Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Mon, 9 Feb 2015 20:08:38 -0500 Subject: [PATCH] Review remainder of updater.py --- tuf/interposition/updater.py | 178 ++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 84 deletions(-) diff --git a/tuf/interposition/updater.py b/tuf/interposition/updater.py index 795e3350..c157f865 100755 --- a/tuf/interposition/updater.py +++ b/tuf/interposition/updater.py @@ -321,8 +321,9 @@ def refresh(self): def cleanup(self): """ - Clean up the updater object's temporary directory (and any - sub-directories). + Remove the updater object's temporary directory (and any sub-directories) + created when the updater object is instantiated to store downloaded + targets and metadata. None @@ -344,30 +345,29 @@ def cleanup(self): def download_target(self, target_filepath): """ - It downloads the target files from the path provided named - target_filepath. - Everything here is performed in a temporary directory. - It identifies the target information for target_filepath by calling - target() method of tuf.client.updater. This method also downloads the - metadata of the updated targets. By doing this, the client retrieves the - target information for the targets they want to update. When client - retrieves all the information, the updated_targets() method of - tuf.client.updater is called to determine the list of targets which have - been changed from those saved locally on disk. - tuf.client.upater.download_target() downloads all the targets in the list - in the destination directory which is our temporary directory. + Download the 'target_filepath' target file. Everything here is performed + in a temporary directory. It identifies the target information for + 'target_filepath' by calling the target() method of 'tuf.client.updater'. + This method also downloads the metadata of the updated targets. By doing + this, the client retrieves the target information for the targets they + want to update. When client retrieves all the information, the + updated_targets() method of 'tuf.client.updater' is called to determine + the list of targets which have been changed from those saved locally on + disk. tuf.client.upater.download_target() downloads all the targets in + the list in the destination directory, which is our temporary directory. - This will only store the file at 'destination_directory' if the downloaded - file matches the description of the file in the trusted metadata. + This will only store the file in the temporary directory if the + downloaded file matches the description of the file in the trusted + metadata. - 'target_filepath' is the target's relative path on the remote repository. + target_filepath: + The target's relative path on the remote repository. tuf.FormatError: - If 'target_filepath', 'updated_target' in - tuf.client.updater.download_target and arguments of updated_targets are - improperly formatted. + If 'target_filepath', 'updated_target' in + 'tuf.client.updater.download_target', is improperly formatted. tuf.UnknownTargetError: If 'target_filepath' was not found. @@ -379,20 +379,21 @@ def download_target(self, target_filepath): A target file is saved to the local system. - It returns destination_directory where the target is been stored and - filename of the target file been stored in the directory. + It returns a (destination directory, filename) tuple where the target is + been stored and filename of the target file been stored in the directory. """ + + tuf.formats.RELPATH_SCHEMA.check_match(target_filepath) # Download file into a temporary directory shared over runtime destination_directory = self.tempdir - tuf.formats.RELPATH_SCHEMA.check_match(target_filepath) # A new path is generated by joining the destination directory path that is # our temporary directory path and target file path. # Note: join() discards 'destination_directory' if 'target_filepath' # contains a leading path separator (i.e., is treated as an absolute path). - filename = os.path.join(destination_directory, - target_filepath.lstrip(os.sep)) + filename = \ + os.path.join(destination_directory, target_filepath.lstrip(os.sep)) # Switch TUF context. Switching context before instantiating updater # because updater depends on some module (tuf.conf) variables. @@ -413,7 +414,8 @@ def download_target(self, target_filepath): # determine which targets have changed from those saved locally on disk. # All the targets that have changed are returned in a list. From this list, # a request to download is made by calling 'download_target()'. - updated_targets = self.updater.updated_targets(targets, destination_directory) + updated_targets = \ + self.updater.updated_targets(targets, destination_directory) # The download_target() method in tuf.client.updater performs the actual # download of the specified target. The file is saved to the @@ -424,7 +426,7 @@ def download_target(self, target_filepath): return destination_directory, filename - # TODO: decide prudent course of action in case of failure + # TODO: decide prudent course of action in case of failure. def get_target_filepath(self, source_url): """ @@ -432,8 +434,8 @@ def get_target_filepath(self, source_url): download when a URL is given. - source_url is passed while calling the function. This is the url which - we want to retrieve. For this url, get_target_filepath() method is called. + source_url: + The URL of the target we want to retrieve. tuf.URLMatchesNoPatternError: @@ -444,7 +446,8 @@ def get_target_filepath(self, source_url): None - It returns target_filepath. This is the target which TUF should download. + If the target filepath is matched, return the filepath, otherwise raise + an exception. """ parsed_source_url = six.moves.urllib.parse.urlparse(source_url) @@ -487,7 +490,7 @@ def get_target_filepath(self, source_url): return target_filepath - # TODO: distinguish between urllib and urllib2 contracts + # TODO: distinguish between urllib and urllib2 contracts. def open(self, url, data=None): """ @@ -496,19 +499,16 @@ def open(self, url, data=None): called when TUF wants to open an already existing updater's 'url'. - url, the one which is to be opened. + url: + The one which is to be opened. - data must be a bytes object specifying additional data to be sent to the - server or None, if no such data needed. + data: + Must be a bytes object specifying additional data to be sent to the + server or None, if no such data needed. - tuf.FormatError: - If 'target_filepath', 'updated_target' in - tuf.client.updater.download_target and arguments of updated_targets are - improperly formatted. - - tuf.UnknownTargetError: - If 'target_filepath' was not found. + tuf.FormatError: + TODO: validate arguments. tuf.NoWorkingMirrorError: If a 'target_filepath' could not be downloaded from any of the mirrors. @@ -523,6 +523,9 @@ def open(self, url, data=None): 'response' which is a file object with info() and geturl() methods added. """ + + # TODO: validate arguments. + filename, headers = self.retrieve(url, data=data) # TUF should always open files in binary mode and remain transparent to the @@ -549,15 +552,16 @@ def open(self, url, data=None): def retrieve(self, url, filename=None, reporthook=None, data=None): """ - retrieve() method first get the target file path by calling - get_target_filepath(url) which is in tuf.interposition.updater.Updater - and then calls download_target() method for the above file path. + Get the target file path by calling self.get_target_filepath(url) and + then self.download_target() method for the above file path. - url, which is to be retrieved. + url: + The URL of the target file to retrieve. - filename, if the is given then everywhere the given filename is used. - If the filename is none, then temporary file is used. + filename: + If given, then the given filename is used. If the filename is none, + then temporary file is used. tuf.FormatError: @@ -606,28 +610,29 @@ def retrieve(self, url, filename=None, reporthook=None, data=None): self.download_target(target_filepath) if filename is None: - # If no filename is given, use the temporary file. - filename = temporary_filename + # If no filename is given, use the temporary file. + filename = temporary_filename else: - # Otherwise, copy TUF-downloaded file in its own directory - # to the location user specified. - shutil.copy2(temporary_filename, filename) + # Otherwise, copy TUF-downloaded file in its own directory + # to the location user specified. + shutil.copy2(temporary_filename, filename) return filename, headers - # TODO: thread-safety, perhaps with a context manager + # TODO: thread-safety, perhaps with a context manager. def switch_context(self): """ - There is an updater object for each network location that is interposed. - Context switching is required because there are multiple - tuf.client.updater objects and each one depends on tuf.conf settings + There is an updater object for each network location that is interposed. + Context switching is required because there are multiple + 'tuf.client.updater' objects and each one depends on tuf.conf settings that are shared. - For this, two settings are required - - 1. Setting local repository directory - 2. Setting the local SSL certificate PEM file + For this, two settings are required: + + 1. Setting local repository directory in 'tuf.conf'. + 2. Setting the local SSL certificate PEM file. None @@ -636,8 +641,9 @@ def switch_context(self): None - The given configuration's repository_directory and ssl_certificates are - assigned to tuf.conf.repository_directory and tuf.conf.ssl_certificates. + The given configuration's 'repository_directory' and ssl_certificates + settings are set to 'tuf.conf.repository_directory' and + 'tuf.conf.ssl_certificates', respectively. None @@ -654,9 +660,8 @@ def switch_context(self): class UpdaterController(object): """ - tuf.interposition.updater.UpdaterController is a controller of the Updaters. - Given a configuration, it can build and store an Updater, which can be - used later with the help of get() method. + A controller of Updater() objects. Given a configuration, it can build and + store an Updater, which can be used later with the help of get() method. @@ -670,34 +675,34 @@ class UpdaterController(object): It checks if the given configuration is valid or not. add(configuration): - This method adds the updater by adding an object of - tuf.interposition.updater.Updater in the __updater map and by adding - repository mirror's network location in the empty set initialized when - the object of tuf.interposition.updater.UpdaterController is created. + This method adds the updater by adding an object of + 'tuf.interposition.updater.Updater' in the __updater map and by adding + repository mirror's network location in the empty set initialized when + the object of 'tuf.interposition.updater.UpdaterController' is created. get(url): - This method is to get the updater if it already exists. It takes the url - and parse it. Then it utilizes hostname and port of that url to check if - it already exists or not. If the updater exists, then it calls the - get_target_filepath() method which returns a target file path to be + Get the updater if it already exists. It takes the url and parses it. + Then it utilizes hostname and port of that url to check if it already + exists or not. If the updater exists, then it calls the + get_target_filepath() method which returns a target file path to be downloaded. refresh(configuration): - To refresh the top-level metadata of the given 'configuration'. - It updates the latest copies of the metadata for the top-level roles. + Refreshes the top-level metadata of the given 'configuration'. It + updates the latest copies of the metadata of the top-level roles. remove(configuration): - Remove an Updater matching the given Configuration as well as its + Remove an Updater matching the given 'configuration' as well as its associated mirrors. """ def __init__(self): """ - To initalize a private map of updaters and a private set of repository + Initalize a private map of updaters and a private set of repository mirror network locations (hostname:port) once the object of - tuf.interposition.updater.UpdaterController is created. This empty map - and set is later used to add, get and remove updaters and their mirrors. + 'tuf.interposition.updater.UpdaterController' is created. This empty map + and set is later used to add, get, and remove updaters and their mirrors. None @@ -812,8 +817,8 @@ def __check_configuration_on_add(self, configuration): def add(self, configuration): """ - Add an Updater based on the given Configuration. Tuf keeps the track of - the updaters so that it can be fetched for later use. + Add an Updater based on the given 'configuration'. TUF keeps track of the + updaters so that it can be fetched for later use. 'configuration' is an object and on the basis of this configuration, an @@ -837,13 +842,17 @@ def add(self, configuration): None """ - repository_mirror_network_locations = self.__check_configuration_on_add(configuration) + repository_mirror_network_locations = \ + self.__check_configuration_on_add(configuration) - # If all is well, build and store an Updater, and remember network locations. + # If all is well, build and store an Updater, and remember network + # locations. logger.info('Adding updater for interposed ' + repr(configuration)) + # Adding an object of the tuf.interposition.updater.Updater with the given # configuration. self.__updaters[configuration.network_location] = Updater(configuration) + # Adding the new the repository mirror network locations to the list. self.__repository_mirror_network_locations.update(repository_mirror_network_locations) @@ -928,7 +937,8 @@ def get(self, url): downloaded. - url, for which tuf is trying to get an updater. Assumption that url is a + url: + URL which TUF is trying to get an updater. Assumption that url is a string. @@ -1000,7 +1010,7 @@ def get(self, url): def remove(self, configuration): """ - Remove an Updater matching the given Configuration as well as its + Remove an Updater matching the given 'configuration', as well as its associated mirrors.