Add puppet configuration for ldap container
Add Dockerfile for ldap container
Demonstrate the problem of no service management

Without this patch the LDAP service is not configured in the ldap
container.  This patch addresses the problem by adding the same Puppet
configuration from the shared VM to the ldap node classification.

This patch demonstrates the issue of no service management when the
docker container is being built.  There are basic operations, like
adding files, and running simple commands, but the overall task of
starting the LDAP service and then loading an initial set of data into
it is problematic in the Docker model of super-lightweight services.

There are two paths forward from here.  The same Puppet code should be
usable with a heavier, but still "light" container that has systemd and
looks more like a full VM or VPS.  The Puppet code could be modified to
work in conjunction with docker to load the data in multiple stages.

The problem looks like:

    Info: Class[Openldap::Server::Config]: Scheduling refresh of Class[Openldap::Server::Service]
    Info: Class[Openldap::Server::Service]: Scheduling refresh of Service[slapd]
    Error: /Service[slapd]: Could not evaluate: Could not find init script for 'slapd'
    Error: /Service[slapd]: Failed to call refresh: Could not find init script for 'slapd'
    Notice: /Stage[main]/Openldap::Server::Slapdconf/File[/etc/openldap/slapd.d]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Openldap::Server::Slapdconf/Openldap::Server::Database[dc=jeffmccune,dc=net]/File[/var/lib/ldap]: Dependency Service[slapd] has failures: true
    Error: /Service[slapd]: Could not find init script for 'slapd'
    Warning: /Stage[main]/Openldap::Server::Slapdconf/File[/etc/openldap/slapd.d]: Skipping because of failed dependencies
    Warning: /Stage[main]/Openldap::Server::Slapdconf/Openldap::Server::Database[dc=jeffmccune,dc=net]/File[/var/lib/ldap]: Skipping because of failed dependencies
    Warning: /Stage[main]/Openldap::Server::Slapdconf/Openldap::Server::Database[dc=jeffmccune,dc=net]/Openldap_database[dc=jeffmccune,dc=net]: Skipping because of failed dependencies
    Notice: /Stage[main]/Openldap::Server::Slapdconf/Openldap::Server::Database[dc=jeffmccune,dc=net]/Openldap_database[dc=jeffmccune,dc=net]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Site::Packages/Package[ruby-devel]/ensure: created
    Warning: /Stage[main]/Site::Openldap/Exec[core schema]: Skipping because of failed dependencies
    Warning: /Stage[main]/Site::Openldap/File[/etc/openldap/data]: Skipping because of failed dependencies
    Notice: /Stage[main]/Site::Openldap/Exec[core schema]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data/jeff_user.ldif]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data/groups.ldif]: Dependency Service[slapd] has failures: true
    Warning: /Stage[main]/Site::Openldap/File[/etc/openldap/data/jeff_user.ldif]: Skipping because of failed dependencies
    Warning: /Stage[main]/Site::Openldap/File[/etc/openldap/data/groups.ldif]: Skipping because of failed dependencies
    Warning: /Stage[main]/Site::Openldap/File[/etc/openldap/data/jeff_group.ldif]: Skipping because of failed dependencies
    Warning: /Stage[main]/Site::Openldap/File[/etc/openldap/data/site.ldif]: Skipping because of failed dependencies
    Warning: /Stage[main]/Site::Openldap/File[/etc/openldap/data/users.ldif]: Skipping because of failed dependencies
    Warning: /Stage[main]/Site::Openldap/Exec[cosine schema]: Skipping because of failed dependencies
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data/jeff_group.ldif]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data/site.ldif]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data/users.ldif]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Site::Openldap/Exec[cosine schema]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Site::Openldap/Exec[inetorgperson schema]: Dependency Service[slapd] has failures: true
    Warning: /Stage[main]/Site::Openldap/Exec[inetorgperson schema]: Skipping because of failed dependencies
    Notice: /Stage[main]/Site::Openldap/Exec[nis schema]: Dependency Service[slapd] has failures: true
    Warning: /Stage[main]/Site::Openldap/Exec[nis schema]: Skipping because of failed dependencies
    Notice: /Stage[main]/Site::Openldap/Exec[dc=jeffmccune,dc=net]: Dependency Service[slapd] has failures: true
    Warning: /Stage[main]/Site::Openldap/Exec[dc=jeffmccune,dc=net]: Skipping because of failed dependencies
    Warning: /Stage[main]/Site::Openldap/Exec[ou=Groups]: Skipping because of failed dependencies
    Warning: /Stage[main]/Site::Openldap/Exec[ou=Users]: Skipping because of failed dependencies
    Warning: /Stage[main]/Site::Openldap/Exec[cn=jeff,ou=Groups]: Skipping because of failed dependencies
    Warning: /Stage[main]/Site::Openldap/Exec[uid=jeff,ou=Users]: Skipping because of failed dependencies
    Notice: /Stage[main]/Site::Openldap/Exec[ou=Groups]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Site::Openldap/Exec[ou=Users]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Site::Openldap/Exec[cn=jeff,ou=Groups]: Dependency Service[slapd] has failures: true
    Notice: /Stage[main]/Site::Openldap/Exec[uid=jeff,ou=Users]: Dependency Service[slapd] has failures: true
    Info: Creating state file /var/lib/puppet/state/state.yaml
    Notice: Finished catalog run in 32.12 seconds
Add centos7vps base image that works with puppet but fails with systemd

Without this patch puppet cannot successfully configure the LDAP service
in the docker container because there is no functional service
management framework.  The centos:centos7 image has the fakesystemd
package installed as a replacement for the real systemd package.

This patch addresses the problem by creating a new base image that has a
fully functional system management framework in the form of the real
systemd package.

Puppet is able to configure the LDAP service using this base image,
albeit as a process running in a container that has systemd running
already.

For example, the following works to stand up LDAP.  What remains is to
port this process over to the ldap/Dockerfile.

First, make sure you have the docker-enter command, installed into
/usr/local/bin using:

    $ docker run -v /usr/local/bin:/target jpetazzo/nsenter

Then, build the centos7vps base image, run it, and run puppet inside the
container.  Note that /puppet is mounted from the Vagrant VM into the container
at /puppet.  This directory is mounted as a shared filesystem with the host
relative to the Vagrantfile.

    $ docker build -t centos7vps .
    $ CID=$(docker run --privileged -v /puppet:/puppet -t -i -d centos7vps)
    $ sudo /usr/local/bin/docker-enter $CID

Inside the container:

    bash-4.2# puppet apply -v --node_name_value ldap --modulepath /puppet/modules /puppet/manifests/ldap.pp
    Info: Loading facts
    Notice: Compiled catalog for ldap in environment production in 1.05 seconds
    Info: Applying configuration version '1411075793'
    Notice: /Stage[main]/Site::Packages/Package[make]/ensure: created
    Notice: /Stage[main]/Site::Packages/Package[rubygem-bundler]/ensure: created
    Notice: /Stage[main]/Site::Packages/Package[gcc]/ensure: created
    Notice: /Stage[main]/Openldap::Server::Install/Package[openldap-servers]/ensure: created
    Notice: /Stage[main]/Site::Packages/Package[telnet]/ensure: created
    Notice: /Stage[main]/Openldap::Client::Config/Augeas[ldap.conf+base]/returns: executed successfully
    Notice: /Stage[main]/Openldap::Client::Config/Augeas[ldap.conf+uri]/returns: executed successfully
    Notice: /Stage[main]/Openldap::Client::Utils/Package[openldap-clients]/ensure: created
    Notice: /Stage[main]/Openldap::Server::Config/Shellvar[SLAPD_LDAPS]/ensure: created
    Notice: /Stage[main]/Openldap::Server::Config/Shellvar[SLAPD_LDAPI]/ensure: created
    Notice: /Stage[main]/Site::Packages/Package[sqlite-devel]/ensure: created
    Notice: /Stage[main]/Openldap::Server::Config/Shellvar[SLAPD_LDAP]/ensure: created
    Notice: /Stage[main]/Main/Node[ldap]/File[/identity.json]/ensure: defined content as '{md5}3fea1400bfa4716e51a28bced8f7e1fc'
    Notice: /Stage[main]/Openldap::Server::Config/Shellvar[SLAPD_URLS]/ensure: created
    Info: Class[Openldap::Server::Config]: Scheduling refresh of Class[Openldap::Server::Service]
    Info: Class[Openldap::Server::Service]: Scheduling refresh of Service[slapd]
    Notice: /Stage[main]/Openldap::Server::Service/Service[slapd]/ensure: ensure changed 'stopped' to 'running'
    Info: /Stage[main]/Openldap::Server::Service/Service[slapd]: Unscheduling refresh on Service[slapd]
    Notice: /Stage[main]/Openldap::Server::Slapdconf/File[/etc/openldap/slapd.d]/mode: mode changed '0700' to '0750'
    Notice: /Stage[main]/Openldap::Server::Slapdconf/Openldap::Server::Database[dc=jeffmccune,dc=net]/Openldap_database[dc=jeffmccune,dc=net]/ensure: created
    Notice: /Stage[main]/Site::Packages/Package[ruby-devel]/ensure: created
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data]/ensure: created
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data/jeff_user.ldif]/ensure: defined content as '{md5}fd506aa952f7bc2eb90ea39bd73f5837'
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data/groups.ldif]/ensure: defined content as '{md5}76d02e92946e5ecbdf375a32fe027d23'
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data/jeff_group.ldif]/ensure: defined content as '{md5}4d320620378e9ac39d659e94ea45102d'
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data/site.ldif]/ensure: defined content as '{md5}23d49a0d2d4ee0c9c7ab546639c45e9f'
    Notice: /Stage[main]/Site::Openldap/File[/etc/openldap/data/users.ldif]/ensure: defined content as '{md5}2e82c9608c202a00843d0c196d825a45'
    Notice: /Stage[main]/Site::Openldap/Exec[cosine schema]/returns: executed successfully
    Notice: /Stage[main]/Site::Openldap/Exec[inetorgperson schema]/returns: executed successfully
    Notice: /Stage[main]/Site::Openldap/Exec[nis schema]/returns: executed successfully
    Notice: /Stage[main]/Site::Openldap/Exec[dc=jeffmccune,dc=net]/returns: executed successfully
    Notice: /Stage[main]/Site::Openldap/Exec[ou=Groups]/returns: executed successfully
    Notice: /Stage[main]/Site::Openldap/Exec[ou=Users]/returns: executed successfully
    Notice: /Stage[main]/Site::Openldap/Exec[cn=jeff,ou=Groups]/returns: executed successfully
    Notice: /Stage[main]/Site::Openldap/Exec[uid=jeff,ou=Users]/returns: executed successfully
    Info: Creating state file /var/lib/puppet/state/state.yaml
    Notice: Finished catalog run in 30.15 seconds
Update ldap dockerfile to use centos7vps base image (REVISIT)

Without this patch the ldap Dockerfile does not build a suitable base
image for ldap because it starts from the centos:centos7 image which
contains a fake systemd package.

This patch addresses the problem by changing the ldap container build
file to use the centos7vps image which contains a functional systemd
implementation.

The build process is still incomplete because systemd is not running
during the docker build phase, however it will be running during the run
phase.

The puppet code still needs to be modified to account for systemd not
being present during build time.

REVISIT: With this change, does it still make sense to change the base
image to one that includes systemd?  It may make more sense to simply
override the Service[slapd] resource to use a start command that does
not rely on systemd.
Add `docker build` Dockerfile for ldap systemd container

Without this patch there is no single Dockerfile that implements a build
process that results in a working LDAP container.  This patch addresses
the problem by using the centos7vps base image, which includes systemd,
to build a LDAP service container.

The LDAP service can be started, mapping 389 on the host to 389 in the
container:

    CID=$(docker run -p 127.0.0.1:389:389 --privileged -d ldap_sysd)

This patch modifies the original Puppet code for the shared jenkins+ldap
VM overriding the Service[slapd] resource.  This is necessary because
Puppet defaults to systemd service management while systemd is not
running during the build phase.  The override manually starts the LDAP
process as a dependency of loading the initial schema and branches.

This approach differs from the approach of "side-loading" [1] the data
using two containers at runtime.

Details:

Start the service on port 389:

    $ CID=$(docker run -p 127.0.0.1:389:389 --privileged -d --name ldap ldap_sysd)

List the service:

    $ docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
    8c2daa7ca724        ldap_sysd:latest    "/usr/sbin/init"    3 seconds ago       Up 3 seconds        127.0.0.1:389->389/tcp   ldap

There are 5 processes using the systemd approach:

    $ sudo ps auxww --forest
    root      1378  1.1  0.4 645540 39092 ?        Ssl  11:33   0:21 /usr/bin/docker -d --selinux-enabled
    root      8493  0.0  0.0 180136  4864 ?        Sl   12:04   0:00  \_ docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 389 -container-ip 172.17.0.10 -container-port 389
    root      8499  0.0  0.0  44616  2696 ?        Ss   12:04   0:00  \_ /usr/sbin/init
    root      8528  0.0  0.0  42992  3872 ?        Ss   12:04   0:00      \_ /usr/lib/systemd/systemd-journald
    55        8578  0.2  9.1 856940 734732 ?       Ssl  12:04   0:00      \_ /usr/sbin/slapd -u ldap -h ldapi:/// ldap:///

Access the service:

    ldapsearch -h localhost -p 389 \
               -D cn=admin,dc=jeffmccune,dc=net \
               -w Password1 \
               -b dc=jeffmccune,dc=net

[1]: http://jpetazzo.github.io/2014/06/23/docker-ssh-considered-evil/
Add Rakefile to build ldap_sysd base image
Add Rakefile to build centos7vps base image
Add Dockerfile for lightweight ldap with no systemd

Without this patch the only docker base image for ldap uses systemd.
This is a problem because it is not as lightweight as running ldap
without systemd and it goes against the principle of Docker [1], which
is to run as minimal of a container as possible.

This patch addresses the problem by taking the systemd enabled base
image as a starting point and replacing /usr/sbin/init with
/usr/sbin/slapd as the entry point of a running container.

The container no longer needs to be started in privileged mode.
Starting and stopping the container is also much faster without having
to go through systemd to start slapd.

Start the container:

    $ CID=$(docker run -p 127.0.0.1:10389:389 -d --name ldap2 ldap_lite)

List the containers:

    $ docker ps
    CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                      NAMES
    0dce5b7994ab        ldap_lite:latest    "/usr/sbin/slapd -u    47 seconds ago      Up 47 seconds       127.0.0.1:10389->389/tcp   ldap2
    8c2daa7ca724        0d0bfe8aafcf        "/usr/sbin/init"       49 minutes ago      Up 48 minutes       127.0.0.1:389->389/tcp     ldap

There are fewer processes running (2 without systemd compared to 6 with
systemd).  This table shows the comparison between the systemd container on 389
and the slapd container on 1039.

    /usr/bin/docker -d --selinux-enabled
     \_ docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 389 -container-ip 172.17.0.10 -container-port 389
     \_ /usr/sbin/init
     |   \_ /usr/lib/systemd/systemd-journald
     |   \_ /usr/sbin/slapd -u ldap -h ldapi:/// ldap:///
     |   \_ /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
     |   \_ /usr/lib/systemd/systemd-logind
     \_ docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 10389 -container-ip 172.17.0.21 -container-port 389
     \_ /usr/sbin/slapd -u ldap -h ldapi:/// ldap:/// -d 0

[1]: http://jpetazzo.github.io/2014/06/23/docker-ssh-considered-evil/