Add Travis CI support

We can make use of Travis CI to help improve testing of the code in
multiple environments.
Add diff_attribute_ops util

A helper utility to do most of the heavy lifting of figuring out what
operations need to be performed on an LDAP entry to modify it from its
original state to the desired one, so we don't have to do this manually
in tasks that update existing entries.
Implement modify() method for LdapConnector

While syncing LDAP directories we will need to be able to modify the
attribute values of entries that already exist in the destination
directory.
Fix typo in CreateTask docstring
Add basic UpdateTask

A simple task to update the attributes of entries that already exist in
the destination LDAP directory. There are still some corner cases
relating to how DN attributes are dealt with that are not yet handled.
What to do when these corner cases occur still needs to be determined
and implemented.
Correctly reset the server list for MultipleLdapsTestCase

The self.servers list was getting new lists appended to it for each test
case instead of being cleared out after each test case.
Remove some debugging code from the tasks tests
Add support for mapping a list of values to attributes

Being able to define a list of values for an attribute like
'objectClass' would seems like a common use-case, so we need to include
support to be able to do it.
Pass objectClass to LdapConnector.add() as part of attributes

The 'objectClass' is just another attribute, so its values should be
included the attributes dict just like other attributes. This also
removes the need to map the 'objectClass' value as a separate step from
the other attribute mappings.
LdapConnector.search() defaults to self.attributes if set

Generally if we have already set a value for the LdapConnector
attributes then we want those returned by default when we do a search.
If no value for attributes has been set we will still default to all
attributes.
Rely on default attribute list when matching entires in UpdateTask

The LdapConnector.search() method has been altered to default to the
LdapConnector attributes if they have been set. These should always be
set when running a task so we don't need to pass them in again.
Base create entry DNs on destination attributes

The DN of any new entries should have its RDN equal to one of the
attributes in the destination directory, so it doesn't make sense to
pass in source attributes to format()
Implement modify_dn method for LdapConnector

While syncing LDAP directories we will need to be able to modify the DN
of entries in the destination directory. The modify_dn() method handles
most of the steps we need to perform when altering an entry DN.
f: f5b41bdd21
Enable UpdateTask to modify of the destination DN

Inevitably the DN value will need to be updated when a RDN values is
modified, so we need to support these sort of modifications as part of
the UpdateTask.
Correctly handle MappingErrors

There is a reasonable change that users will attempt to use bad
attribute mapping definitions, so we should at least try to handle these
error gracefully.
Rename the CreateTask 'translations' attribute to 'mappings'

This change is mainly to improve consistency. Translations we a term
previously being used before mappings was settled upon.
Rename LdapUpdateError to LdapModifyError

LdapModifyError more accurately describes the error which is the
potential side-effect of an LDAP modify operation.
Require 'dn' mapping definition for Create/Update tasks

To be able to do anything useful to the entries in the destination LDAP
we need to know the (potential) DN of those entries, hence the 'dn'
mapping definition is required.
Metadata for v0.3.0

There seems to be enough basic functionality, so it seems a good a time
as any to tag an initial v0.3.0 release.