Review remainder of updater.py

This commit is contained in:
Vladimir Diaz 2015-02-09 20:08:38 -05:00
parent a0ab601b7f
commit 4bcfead253

View file

@ -321,8 +321,9 @@ def refresh(self):
def cleanup(self):
"""
<Purpose>
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.
<Arguments>
None
@ -344,30 +345,29 @@ def cleanup(self):
def download_target(self, target_filepath):
"""
<Purpose>
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.
<Arguments>
'target_filepath' is the target's relative path on the remote repository.
target_filepath:
The target's relative path on the remote repository.
<Exceptions>
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.
<Returns>
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):
"""
<Purpose>
@ -432,8 +434,8 @@ def get_target_filepath(self, source_url):
download when a URL is given.
<Arguments>
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.
<Exceptions>
tuf.URLMatchesNoPatternError:
@ -444,7 +446,8 @@ def get_target_filepath(self, source_url):
None
<Returns>
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):
"""
<Purpose>
@ -496,19 +499,16 @@ def open(self, url, data=None):
called when TUF wants to open an already existing updater's 'url'.
<Arguments>
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.
<Exceptions>
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):
<Returns>
'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):
"""
<Purpose>
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.
<Arguments>
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.
<Exceptions>
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):
"""
<Purpose>
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.
<Arguments>
None
@ -636,8 +641,9 @@ def switch_context(self):
None
<Side Effects>
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.
<Returns>
None
@ -654,9 +660,8 @@ def switch_context(self):
class UpdaterController(object):
"""
<Purpose>
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.
<UpdaterController's Methods>
@ -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):
"""
<Purpose>
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.
<Arguments>
None
@ -812,8 +817,8 @@ def __check_configuration_on_add(self, configuration):
def add(self, configuration):
"""
<Purpose>
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.
<Arguments>
'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.
<Arguments>
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.
<Exceptions>
@ -1000,7 +1010,7 @@ def get(self, url):
def remove(self, configuration):
"""
<Purpose>
Remove an Updater matching the given Configuration as well as its
Remove an Updater matching the given 'configuration', as well as its
associated mirrors.
<Arguments>