Optimize calls for operating system version

Previously, Facter.value() was being called every time the operating
system version was required in the directoryservice user provider.
This commit creates a method on the instance of the class that memoizes
the lookup for the operatingsystem version.
Wrap ShadowHashData setting into its own method

Previously, the act of setting the ShadowHashData key in the
user's plist was performed in the set_salted_sha512() and
set_salted_pbkdf2() methods.  This commit wraps that behavior
into its own method for uniformity.

There was also a condition where a user account that has an
old-style password hash (10.6 or earlier) could exist on a
10.7 or 10.8 machine that had been upgraded.  If this user
hadn't logged-in to the machine, then their password hash
would continue to be stored on-disk (versus being stored
in the ShadowHashData key of the user's plist). Previously,
the code made the assumption that if the machine had an
operating system version of 10.7 or 10.8, then the
ShadowHashData key would exist in the user's plist. This
was a false assumption, based on the edge case I described
previously.  This commit adds the check for the ShadowHashData
key in the set_shadow_hash_data method and will adapt accordingly.
Wrap user plist retrieval into get_users_plist()

Previously, the act of retrieving the user's plist was
performed on an ad-hoc basis by running the plutil command.
Because this binary is only available on OS X, it needed
to be stubbed out to successfully test its behavior on
Linux. To make this process easier (and also encapsulate
the behavior into its own method for future upgrades), the
plutil call has been wrapped in its own method
(get_users_plist).
Do not fail if ShadowHashData doesn't exist

It's possible that a user account on a 10.7 or 10.8 machine
could still have an old-style password hash that's been stored
on-disk versus being stored in the user's plist (this occurs
if a machine has been upgraded from 10.6 to 10.7 or 10.8).
With this edge-case, the ShadowHashData key would be absent
in the user's plist, and thus the shadow_hash_data variable would
be false and not a Hash (as is expected).  Previously, there was
no check for if the shadow_hash_data key was a Hash (it was assumed).
This commit adds that check and handles a false value without failing.
Provide wrapper method for new StringIO objects

Previously, StringIO objects were being created directly from
the provider methods. This worked just fine, except for the
fact that the StringIO objects were identified by a serial number.
When you would try to provide rspec test coverage around these
provider methods, you could never provide a complete match for
the StringIO objects as you would first need to mock StringIO.new,
and then hope that the serial numbers matched.

This commit wraps the StringIO.new method into its own provider
method called 'new_stringio_object', which makes it easier to mock
for rspec tests.
Create base64_decode_string

Previously, the code for Base64 decoding a hex string into
a binary string was provided inline within the body of the
provider methods that needed this behavior.  This meant that
code was duplicated, but, more importantly, to test the
behaviour you would need to mock out the Base64.decode64
method, which is not the best case in the world.

To remedy this, this commit creates a new method, base64_decode_string,
and wraps the necessary behaviour within that method.  This should
reduce code duplication and also make it easier to test.
Clean up comments
Update spec tests

This commit updates the spec tests for the directoryservice
user provider according to recent commits that introduced
helper methods for common behavior.  These tests should be
tighter around behavior that was difficult to test (testing
StringIO objects), as well as adding tests to catch edge-
cases (10.6-style users that exist in 10.8).

First shot at spec tests
Update Documentation to YARD standard

Previously, class documentation was listed AFTER the class
definition instead of BEFORE it. This commit modifies each
class's documentation to realign it prior to the class
definition.
Merge branch 'glarizza-bug/3.0.x/12833_fix_salt' into 3.0.x

* glarizza-bug/3.0.x/12833_fix_salt:
  Update Documentation to YARD standard
  Update spec tests
  Clean up comments
  Create base64_decode_string
  Provide wrapper method for new StringIO objects
  Do not fail if ShadowHashData doesn't exist
  Wrap user plist retrieval into get_users_plist()
  Wrap ShadowHashData setting into its own method
  Optimize calls for operating system version
Merge branch '3.0.x'

* 3.0.x:
  Update Documentation to YARD standard
  Update spec tests
  Clean up comments
  Create base64_decode_string
  Provide wrapper method for new StringIO objects
  Do not fail if ShadowHashData doesn't exist
  Wrap user plist retrieval into get_users_plist()
  Wrap ShadowHashData setting into its own method
  Optimize calls for operating system version
[15929] [17624] Handle malformed plists

Previously, if launchd encountered a plist that did NOT have a 'label' key, or
a malformed plist that plutil couldn't read, Puppet would throw a stacktrace or
log a nebulous error that looked like:

`Error: Could not run: No resource and no name in property hash in launchd
instance`

That was not ideal. This commit will catch the situation where a plist is
missing a 'label' key Puppet is skipping the plist.  It will also catch the
case the where a plist is malformed and plutil cannot read it.  With either
condition, the commit adds code that logs a Puppet.warning and skips the
malformed plist gracefully.
Merge branch 'glarizza-bug/3.0.x/17624_launchd_fails' into 3.0.x

* glarizza-bug/3.0.x/17624_launchd_fails:
  [15929] [17624] Handle malformed plists
Merge branch '3.0.x'

* 3.0.x:
  [15929] [17624] Handle malformed plists