Add contributor edition
authorymh <ymh.work@gmail.com>
Fri, 15 Jan 2016 15:35:00 +0100
changeset 28 b0b56e0f8c7f
parent 27 a2342f26c9de
child 29 50702e620af4
Add contributor edition - added viaf resolver - improve contributors list display - add update of document objects - propagate update to back office - update back office - add bo-client to back office - setup language initializer - add options mechanism - add language information in language list - add lexvo resolver service + api - add language and lexvo resolver to js app - correct env template - refresh bootstrap - download google font - add version information - update dev virtual machine to centos7 - add a readme + clean folders - add local .env file to start commands
.hgignore
build/Vagrantfile
build/build_rpm.sh
build/post_install.sh
build/post_uninstall.sh
build/post_upgrade.sh
build/provisioning/playbook.yml
dev/Vagrantfile
dev/provisioning/bootstrap-puppet.sh
dev/provisioning/custom.yaml
dev/provisioning/custom.yaml.tmpl
dev/provisioning/default.pp
dev/provisioning/files/.bashrc
dev/provisioning/files/.profile
dev/provisioning/files/site.j2
dev/provisioning/files/sysconfig_php-fpm
dev/provisioning/hiera.yaml
dev/provisioning/modules/apache/CHANGELOG.md
dev/provisioning/modules/apache/CONTRIBUTING.md
dev/provisioning/modules/apache/Gemfile
dev/provisioning/modules/apache/LICENSE
dev/provisioning/modules/apache/README.md
dev/provisioning/modules/apache/README.passenger.md
dev/provisioning/modules/apache/Rakefile
dev/provisioning/modules/apache/checksums.json
dev/provisioning/modules/apache/examples/apache.pp
dev/provisioning/modules/apache/examples/dev.pp
dev/provisioning/modules/apache/examples/init.pp
dev/provisioning/modules/apache/examples/mod_load_params.pp
dev/provisioning/modules/apache/examples/mods.pp
dev/provisioning/modules/apache/examples/mods_custom.pp
dev/provisioning/modules/apache/examples/php.pp
dev/provisioning/modules/apache/examples/vhost.pp
dev/provisioning/modules/apache/examples/vhost_directories.pp
dev/provisioning/modules/apache/examples/vhost_filter.pp
dev/provisioning/modules/apache/examples/vhost_ip_based.pp
dev/provisioning/modules/apache/examples/vhost_proxypass.pp
dev/provisioning/modules/apache/examples/vhost_ssl.pp
dev/provisioning/modules/apache/examples/vhosts_without_listen.pp
dev/provisioning/modules/apache/files/httpd
dev/provisioning/modules/apache/lib/puppet/parser/functions/bool2httpd.rb
dev/provisioning/modules/apache/lib/puppet/parser/functions/validate_apache_log_level.rb
dev/provisioning/modules/apache/lib/puppet/provider/a2mod.rb
dev/provisioning/modules/apache/lib/puppet/provider/a2mod/a2mod.rb
dev/provisioning/modules/apache/lib/puppet/provider/a2mod/gentoo.rb
dev/provisioning/modules/apache/lib/puppet/provider/a2mod/modfix.rb
dev/provisioning/modules/apache/lib/puppet/provider/a2mod/redhat.rb
dev/provisioning/modules/apache/lib/puppet/type/a2mod.rb
dev/provisioning/modules/apache/manifests/balancer.pp
dev/provisioning/modules/apache/manifests/balancermember.pp
dev/provisioning/modules/apache/manifests/confd/no_accf.pp
dev/provisioning/modules/apache/manifests/custom_config.pp
dev/provisioning/modules/apache/manifests/default_confd_files.pp
dev/provisioning/modules/apache/manifests/default_mods.pp
dev/provisioning/modules/apache/manifests/default_mods/load.pp
dev/provisioning/modules/apache/manifests/dev.pp
dev/provisioning/modules/apache/manifests/fastcgi/server.pp
dev/provisioning/modules/apache/manifests/init.pp
dev/provisioning/modules/apache/manifests/listen.pp
dev/provisioning/modules/apache/manifests/mod.pp
dev/provisioning/modules/apache/manifests/mod/actions.pp
dev/provisioning/modules/apache/manifests/mod/alias.pp
dev/provisioning/modules/apache/manifests/mod/auth_basic.pp
dev/provisioning/modules/apache/manifests/mod/auth_cas.pp
dev/provisioning/modules/apache/manifests/mod/auth_kerb.pp
dev/provisioning/modules/apache/manifests/mod/auth_mellon.pp
dev/provisioning/modules/apache/manifests/mod/authn_core.pp
dev/provisioning/modules/apache/manifests/mod/authn_file.pp
dev/provisioning/modules/apache/manifests/mod/authnz_ldap.pp
dev/provisioning/modules/apache/manifests/mod/authz_default.pp
dev/provisioning/modules/apache/manifests/mod/authz_user.pp
dev/provisioning/modules/apache/manifests/mod/autoindex.pp
dev/provisioning/modules/apache/manifests/mod/cache.pp
dev/provisioning/modules/apache/manifests/mod/cgi.pp
dev/provisioning/modules/apache/manifests/mod/cgid.pp
dev/provisioning/modules/apache/manifests/mod/dav.pp
dev/provisioning/modules/apache/manifests/mod/dav_fs.pp
dev/provisioning/modules/apache/manifests/mod/dav_svn.pp
dev/provisioning/modules/apache/manifests/mod/deflate.pp
dev/provisioning/modules/apache/manifests/mod/dev.pp
dev/provisioning/modules/apache/manifests/mod/dir.pp
dev/provisioning/modules/apache/manifests/mod/disk_cache.pp
dev/provisioning/modules/apache/manifests/mod/event.pp
dev/provisioning/modules/apache/manifests/mod/expires.pp
dev/provisioning/modules/apache/manifests/mod/ext_filter.pp
dev/provisioning/modules/apache/manifests/mod/fastcgi.pp
dev/provisioning/modules/apache/manifests/mod/fcgid.pp
dev/provisioning/modules/apache/manifests/mod/filter.pp
dev/provisioning/modules/apache/manifests/mod/geoip.pp
dev/provisioning/modules/apache/manifests/mod/headers.pp
dev/provisioning/modules/apache/manifests/mod/include.pp
dev/provisioning/modules/apache/manifests/mod/info.pp
dev/provisioning/modules/apache/manifests/mod/itk.pp
dev/provisioning/modules/apache/manifests/mod/ldap.pp
dev/provisioning/modules/apache/manifests/mod/mime.pp
dev/provisioning/modules/apache/manifests/mod/mime_magic.pp
dev/provisioning/modules/apache/manifests/mod/negotiation.pp
dev/provisioning/modules/apache/manifests/mod/nss.pp
dev/provisioning/modules/apache/manifests/mod/pagespeed.pp
dev/provisioning/modules/apache/manifests/mod/passenger.pp
dev/provisioning/modules/apache/manifests/mod/perl.pp
dev/provisioning/modules/apache/manifests/mod/peruser.pp
dev/provisioning/modules/apache/manifests/mod/php.pp
dev/provisioning/modules/apache/manifests/mod/prefork.pp
dev/provisioning/modules/apache/manifests/mod/proxy.pp
dev/provisioning/modules/apache/manifests/mod/proxy_ajp.pp
dev/provisioning/modules/apache/manifests/mod/proxy_balancer.pp
dev/provisioning/modules/apache/manifests/mod/proxy_connect.pp
dev/provisioning/modules/apache/manifests/mod/proxy_html.pp
dev/provisioning/modules/apache/manifests/mod/proxy_http.pp
dev/provisioning/modules/apache/manifests/mod/python.pp
dev/provisioning/modules/apache/manifests/mod/remoteip.pp
dev/provisioning/modules/apache/manifests/mod/reqtimeout.pp
dev/provisioning/modules/apache/manifests/mod/rewrite.pp
dev/provisioning/modules/apache/manifests/mod/rpaf.pp
dev/provisioning/modules/apache/manifests/mod/security.pp
dev/provisioning/modules/apache/manifests/mod/setenvif.pp
dev/provisioning/modules/apache/manifests/mod/shib.pp
dev/provisioning/modules/apache/manifests/mod/speling.pp
dev/provisioning/modules/apache/manifests/mod/ssl.pp
dev/provisioning/modules/apache/manifests/mod/status.pp
dev/provisioning/modules/apache/manifests/mod/suexec.pp
dev/provisioning/modules/apache/manifests/mod/suphp.pp
dev/provisioning/modules/apache/manifests/mod/userdir.pp
dev/provisioning/modules/apache/manifests/mod/version.pp
dev/provisioning/modules/apache/manifests/mod/vhost_alias.pp
dev/provisioning/modules/apache/manifests/mod/worker.pp
dev/provisioning/modules/apache/manifests/mod/wsgi.pp
dev/provisioning/modules/apache/manifests/mod/xsendfile.pp
dev/provisioning/modules/apache/manifests/mpm.pp
dev/provisioning/modules/apache/manifests/namevirtualhost.pp
dev/provisioning/modules/apache/manifests/package.pp
dev/provisioning/modules/apache/manifests/params.pp
dev/provisioning/modules/apache/manifests/peruser/multiplexer.pp
dev/provisioning/modules/apache/manifests/peruser/processor.pp
dev/provisioning/modules/apache/manifests/php.pp
dev/provisioning/modules/apache/manifests/proxy.pp
dev/provisioning/modules/apache/manifests/python.pp
dev/provisioning/modules/apache/manifests/security/rule_link.pp
dev/provisioning/modules/apache/manifests/service.pp
dev/provisioning/modules/apache/manifests/ssl.pp
dev/provisioning/modules/apache/manifests/version.pp
dev/provisioning/modules/apache/manifests/vhost.pp
dev/provisioning/modules/apache/metadata.json
dev/provisioning/modules/apache/spec/acceptance/apache_parameters_spec.rb
dev/provisioning/modules/apache/spec/acceptance/apache_ssl_spec.rb
dev/provisioning/modules/apache/spec/acceptance/class_spec.rb
dev/provisioning/modules/apache/spec/acceptance/custom_config_spec.rb
dev/provisioning/modules/apache/spec/acceptance/default_mods_spec.rb
dev/provisioning/modules/apache/spec/acceptance/itk_spec.rb
dev/provisioning/modules/apache/spec/acceptance/mod_dav_svn_spec.rb
dev/provisioning/modules/apache/spec/acceptance/mod_deflate_spec.rb
dev/provisioning/modules/apache/spec/acceptance/mod_fcgid_spec.rb
dev/provisioning/modules/apache/spec/acceptance/mod_mime_spec.rb
dev/provisioning/modules/apache/spec/acceptance/mod_negotiation_spec.rb
dev/provisioning/modules/apache/spec/acceptance/mod_pagespeed_spec.rb
dev/provisioning/modules/apache/spec/acceptance/mod_passenger_spec.rb
dev/provisioning/modules/apache/spec/acceptance/mod_php_spec.rb
dev/provisioning/modules/apache/spec/acceptance/mod_proxy_html_spec.rb
dev/provisioning/modules/apache/spec/acceptance/mod_security_spec.rb
dev/provisioning/modules/apache/spec/acceptance/mod_suphp_spec.rb
dev/provisioning/modules/apache/spec/acceptance/nodesets/centos-70-x64.yml
dev/provisioning/modules/apache/spec/acceptance/nodesets/debian-607-x64.yml
dev/provisioning/modules/apache/spec/acceptance/nodesets/debian-70rc1-x64.yml
dev/provisioning/modules/apache/spec/acceptance/nodesets/debian-73-i386.yml
dev/provisioning/modules/apache/spec/acceptance/nodesets/debian-73-x64.yml
dev/provisioning/modules/apache/spec/acceptance/nodesets/default.yml
dev/provisioning/modules/apache/spec/acceptance/nodesets/fedora-18-x64.yml
dev/provisioning/modules/apache/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml
dev/provisioning/modules/apache/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml
dev/provisioning/modules/apache/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml
dev/provisioning/modules/apache/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml
dev/provisioning/modules/apache/spec/acceptance/prefork_worker_spec.rb
dev/provisioning/modules/apache/spec/acceptance/service_spec.rb
dev/provisioning/modules/apache/spec/acceptance/unsupported_spec.rb
dev/provisioning/modules/apache/spec/acceptance/version.rb
dev/provisioning/modules/apache/spec/acceptance/vhost_spec.rb
dev/provisioning/modules/apache/spec/classes/apache_spec.rb
dev/provisioning/modules/apache/spec/classes/dev_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/alias_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/auth_cas_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/auth_kerb_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/auth_mellon_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/authnz_ldap_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/dav_svn_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/deflate_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/dev_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/dir_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/disk_cache.rb
dev/provisioning/modules/apache/spec/classes/mod/event_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/expires_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/ext_filter_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/fastcgi_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/fcgid_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/info_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/itk_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/mime_magic_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/mime_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/negotiation_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/pagespeed_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/passenger_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/perl_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/peruser_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/php_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/prefork_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/proxy_connect_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/proxy_html_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/python_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/remoteip_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/reqtimeout_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/rpaf_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/security_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/shib_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/speling_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/ssl_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/status_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/suphp_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/worker_spec.rb
dev/provisioning/modules/apache/spec/classes/mod/wsgi_spec.rb
dev/provisioning/modules/apache/spec/classes/params_spec.rb
dev/provisioning/modules/apache/spec/classes/service_spec.rb
dev/provisioning/modules/apache/spec/defines/balancermember_spec.rb
dev/provisioning/modules/apache/spec/defines/custom_config_spec.rb
dev/provisioning/modules/apache/spec/defines/fastcgi_server_spec.rb
dev/provisioning/modules/apache/spec/defines/mod_spec.rb
dev/provisioning/modules/apache/spec/defines/modsec_link_spec.rb
dev/provisioning/modules/apache/spec/defines/vhost_spec.rb
dev/provisioning/modules/apache/spec/spec.opts
dev/provisioning/modules/apache/spec/spec_helper.rb
dev/provisioning/modules/apache/spec/spec_helper_acceptance.rb
dev/provisioning/modules/apache/spec/unit/provider/a2mod/gentoo_spec.rb
dev/provisioning/modules/apache/spec/unit/puppet/parser/functions/bool2httpd_spec.rb
dev/provisioning/modules/apache/spec/unit/puppet/parser/functions/validate_apache_log_level.rb
dev/provisioning/modules/apache/templates/confd/no-accf.conf.erb
dev/provisioning/modules/apache/templates/fastcgi/server.erb
dev/provisioning/modules/apache/templates/httpd.conf.erb
dev/provisioning/modules/apache/templates/listen.erb
dev/provisioning/modules/apache/templates/mod/alias.conf.erb
dev/provisioning/modules/apache/templates/mod/auth_cas.conf.erb
dev/provisioning/modules/apache/templates/mod/auth_mellon.conf.erb
dev/provisioning/modules/apache/templates/mod/authnz_ldap.conf.erb
dev/provisioning/modules/apache/templates/mod/autoindex.conf.erb
dev/provisioning/modules/apache/templates/mod/cgid.conf.erb
dev/provisioning/modules/apache/templates/mod/dav_fs.conf.erb
dev/provisioning/modules/apache/templates/mod/deflate.conf.erb
dev/provisioning/modules/apache/templates/mod/dir.conf.erb
dev/provisioning/modules/apache/templates/mod/disk_cache.conf.erb
dev/provisioning/modules/apache/templates/mod/event.conf.erb
dev/provisioning/modules/apache/templates/mod/expires.conf.erb
dev/provisioning/modules/apache/templates/mod/ext_filter.conf.erb
dev/provisioning/modules/apache/templates/mod/fastcgi.conf.erb
dev/provisioning/modules/apache/templates/mod/geoip.conf.erb
dev/provisioning/modules/apache/templates/mod/info.conf.erb
dev/provisioning/modules/apache/templates/mod/itk.conf.erb
dev/provisioning/modules/apache/templates/mod/ldap.conf.erb
dev/provisioning/modules/apache/templates/mod/load.erb
dev/provisioning/modules/apache/templates/mod/mime.conf.erb
dev/provisioning/modules/apache/templates/mod/mime_magic.conf.erb
dev/provisioning/modules/apache/templates/mod/mpm_event.conf.erb
dev/provisioning/modules/apache/templates/mod/negotiation.conf.erb
dev/provisioning/modules/apache/templates/mod/nss.conf.erb
dev/provisioning/modules/apache/templates/mod/pagespeed.conf.erb
dev/provisioning/modules/apache/templates/mod/passenger.conf.erb
dev/provisioning/modules/apache/templates/mod/peruser.conf.erb
dev/provisioning/modules/apache/templates/mod/php5.conf.erb
dev/provisioning/modules/apache/templates/mod/prefork.conf.erb
dev/provisioning/modules/apache/templates/mod/proxy.conf.erb
dev/provisioning/modules/apache/templates/mod/proxy_html.conf.erb
dev/provisioning/modules/apache/templates/mod/remoteip.conf.erb
dev/provisioning/modules/apache/templates/mod/reqtimeout.conf.erb
dev/provisioning/modules/apache/templates/mod/rpaf.conf.erb
dev/provisioning/modules/apache/templates/mod/security.conf.erb
dev/provisioning/modules/apache/templates/mod/security_crs.conf.erb
dev/provisioning/modules/apache/templates/mod/setenvif.conf.erb
dev/provisioning/modules/apache/templates/mod/ssl.conf.erb
dev/provisioning/modules/apache/templates/mod/status.conf.erb
dev/provisioning/modules/apache/templates/mod/suphp.conf.erb
dev/provisioning/modules/apache/templates/mod/unixd_fcgid.conf.erb
dev/provisioning/modules/apache/templates/mod/userdir.conf.erb
dev/provisioning/modules/apache/templates/mod/worker.conf.erb
dev/provisioning/modules/apache/templates/mod/wsgi.conf.erb
dev/provisioning/modules/apache/templates/namevirtualhost.erb
dev/provisioning/modules/apache/templates/ports_header.erb
dev/provisioning/modules/apache/templates/vhost/_access_log.erb
dev/provisioning/modules/apache/templates/vhost/_action.erb
dev/provisioning/modules/apache/templates/vhost/_additional_includes.erb
dev/provisioning/modules/apache/templates/vhost/_aliases.erb
dev/provisioning/modules/apache/templates/vhost/_allow_encoded_slashes.erb
dev/provisioning/modules/apache/templates/vhost/_auth_kerb.erb
dev/provisioning/modules/apache/templates/vhost/_block.erb
dev/provisioning/modules/apache/templates/vhost/_charsets.erb
dev/provisioning/modules/apache/templates/vhost/_custom_fragment.erb
dev/provisioning/modules/apache/templates/vhost/_directories.erb
dev/provisioning/modules/apache/templates/vhost/_docroot.erb
dev/provisioning/modules/apache/templates/vhost/_error_document.erb
dev/provisioning/modules/apache/templates/vhost/_fallbackresource.erb
dev/provisioning/modules/apache/templates/vhost/_fastcgi.erb
dev/provisioning/modules/apache/templates/vhost/_file_footer.erb
dev/provisioning/modules/apache/templates/vhost/_file_header.erb
dev/provisioning/modules/apache/templates/vhost/_filters.erb
dev/provisioning/modules/apache/templates/vhost/_header.erb
dev/provisioning/modules/apache/templates/vhost/_itk.erb
dev/provisioning/modules/apache/templates/vhost/_limits.erb
dev/provisioning/modules/apache/templates/vhost/_logging.erb
dev/provisioning/modules/apache/templates/vhost/_passenger.erb
dev/provisioning/modules/apache/templates/vhost/_passenger_base_uris.erb
dev/provisioning/modules/apache/templates/vhost/_php.erb
dev/provisioning/modules/apache/templates/vhost/_php_admin.erb
dev/provisioning/modules/apache/templates/vhost/_proxy.erb
dev/provisioning/modules/apache/templates/vhost/_rack.erb
dev/provisioning/modules/apache/templates/vhost/_redirect.erb
dev/provisioning/modules/apache/templates/vhost/_requestheader.erb
dev/provisioning/modules/apache/templates/vhost/_rewrite.erb
dev/provisioning/modules/apache/templates/vhost/_scriptalias.erb
dev/provisioning/modules/apache/templates/vhost/_security.erb
dev/provisioning/modules/apache/templates/vhost/_serveralias.erb
dev/provisioning/modules/apache/templates/vhost/_serversignature.erb
dev/provisioning/modules/apache/templates/vhost/_setenv.erb
dev/provisioning/modules/apache/templates/vhost/_ssl.erb
dev/provisioning/modules/apache/templates/vhost/_suexec.erb
dev/provisioning/modules/apache/templates/vhost/_suphp.erb
dev/provisioning/modules/apache/templates/vhost/_wsgi.erb
dev/provisioning/modules/archive/CHANGELOG.md
dev/provisioning/modules/archive/Gemfile
dev/provisioning/modules/archive/LICENSE
dev/provisioning/modules/archive/README.md
dev/provisioning/modules/archive/Rakefile
dev/provisioning/modules/archive/checksums.json
dev/provisioning/modules/archive/manifests/download.pp
dev/provisioning/modules/archive/manifests/extract.pp
dev/provisioning/modules/archive/manifests/init.pp
dev/provisioning/modules/archive/manifests/tar_gz.pp
dev/provisioning/modules/archive/manifests/zip.pp
dev/provisioning/modules/archive/metadata.json
dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-5-x86_64-docker.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-6-x86_64-docker.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-6-x86_64-openstack.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-6-x86_64-vagrant.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-7-x86_64-docker.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-7-x86_64-openstack.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-7-x86_64-vagrant.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-6-x86_64-docker.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-6-x86_64-openstack.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-6-x86_64-vagrant.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-7-x86_64-docker.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-7-x86_64-openstack.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-7-x86_64-vagrant.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-8-x86_64-docker.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-8-x86_64-openstack.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-8-x86_64-vagrant.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-10.04-x86_64-docker.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-12.04-x86_64-docker.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-12.04-x86_64-openstack.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-14.04-x86_64-docker.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-14.04-x86_64-openstack.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-14.04-x86_64-vagrant.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-14.10-x86_64-docker.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-14.10-x86_64-openstack.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-15.04-x86_64-docker.yml
dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-15.04-x86_64-openstack.yml
dev/provisioning/modules/archive/spec/defines/archive_spec.rb
dev/provisioning/modules/archive/spec/spec.opts
dev/provisioning/modules/archive/spec/spec_helper.rb
dev/provisioning/modules/augeas/.fixtures.yml
dev/provisioning/modules/augeas/.gitignore
dev/provisioning/modules/augeas/.puppet-lint.rc
dev/provisioning/modules/augeas/.sync.yml
dev/provisioning/modules/augeas/.travis.yml
dev/provisioning/modules/augeas/CHANGELOG.md
dev/provisioning/modules/augeas/Gemfile
dev/provisioning/modules/augeas/LICENSE
dev/provisioning/modules/augeas/README.md
dev/provisioning/modules/augeas/Rakefile
dev/provisioning/modules/augeas/lib/puppet/parser/functions/augeas.rb
dev/provisioning/modules/augeas/manifests/files.pp
dev/provisioning/modules/augeas/manifests/init.pp
dev/provisioning/modules/augeas/manifests/lens.pp
dev/provisioning/modules/augeas/manifests/packages.pp
dev/provisioning/modules/augeas/manifests/params.pp
dev/provisioning/modules/augeas/metadata.json
dev/provisioning/modules/augeas/spec/.rspec
dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-5-x86_64-docker.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-6-x86_64-docker.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-6-x86_64-openstack.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-6-x86_64-vagrant.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-7-x86_64-docker.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-7-x86_64-openstack.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-7-x86_64-vagrant.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-6-x86_64-docker.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-6-x86_64-openstack.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-6-x86_64-vagrant.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-7-x86_64-docker.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-7-x86_64-openstack.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-7-x86_64-vagrant.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-8-x86_64-docker.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-8-x86_64-openstack.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-8-x86_64-vagrant.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-10.04-x86_64-docker.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-12.04-x86_64-docker.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-12.04-x86_64-openstack.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-14.04-x86_64-docker.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-14.04-x86_64-openstack.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-14.04-x86_64-vagrant.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-14.10-x86_64-docker.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-14.10-x86_64-openstack.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-15.04-x86_64-docker.yml
dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-15.04-x86_64-openstack.yml
dev/provisioning/modules/augeas/spec/classes/augeas_spec.rb
dev/provisioning/modules/augeas/spec/defines/augeas_lens_spec.rb
dev/provisioning/modules/augeas/spec/spec.opts
dev/provisioning/modules/augeas/spec/spec_helper.rb
dev/provisioning/modules/augeas/spec/unit/puppet/parser/functions/augeas_spec.rb
dev/provisioning/modules/concat/CHANGELOG.md
dev/provisioning/modules/concat/CONTRIBUTING.md
dev/provisioning/modules/concat/Gemfile
dev/provisioning/modules/concat/LICENSE
dev/provisioning/modules/concat/README.md
dev/provisioning/modules/concat/Rakefile
dev/provisioning/modules/concat/checksums.json
dev/provisioning/modules/concat/files/concatfragments.rb
dev/provisioning/modules/concat/lib/facter/concat_basedir.rb
dev/provisioning/modules/concat/lib/puppet/parser/functions/concat_getparam.rb
dev/provisioning/modules/concat/lib/puppet/parser/functions/concat_is_bool.rb
dev/provisioning/modules/concat/manifests/fragment.pp
dev/provisioning/modules/concat/manifests/init.pp
dev/provisioning/modules/concat/manifests/setup.pp
dev/provisioning/modules/concat/metadata.json
dev/provisioning/modules/concat/spec/acceptance/backup_spec.rb
dev/provisioning/modules/concat/spec/acceptance/concat_spec.rb
dev/provisioning/modules/concat/spec/acceptance/deprecation_warnings_spec.rb
dev/provisioning/modules/concat/spec/acceptance/empty_spec.rb
dev/provisioning/modules/concat/spec/acceptance/fragment_source_spec.rb
dev/provisioning/modules/concat/spec/acceptance/fragments_are_always_replaced_spec.rb
dev/provisioning/modules/concat/spec/acceptance/newline_spec.rb
dev/provisioning/modules/concat/spec/acceptance/nodesets/aix-71-vcloud.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/centos-59-x64.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/centos-64-x64-pe.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/centos-64-x64.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/centos-65-x64.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/debian-607-x64.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/debian-70rc1-x64.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/debian-73-x64.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/default.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/fedora-18-x64.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/sles-11-x64.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/sles-11sp1-x64.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml
dev/provisioning/modules/concat/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml
dev/provisioning/modules/concat/spec/acceptance/order_spec.rb
dev/provisioning/modules/concat/spec/acceptance/quoted_paths_spec.rb
dev/provisioning/modules/concat/spec/acceptance/replace_spec.rb
dev/provisioning/modules/concat/spec/acceptance/specinfra_stubs.rb
dev/provisioning/modules/concat/spec/acceptance/symbolic_name_spec.rb
dev/provisioning/modules/concat/spec/acceptance/validation_spec.rb
dev/provisioning/modules/concat/spec/acceptance/warn_spec.rb
dev/provisioning/modules/concat/spec/spec.opts
dev/provisioning/modules/concat/spec/spec_helper.rb
dev/provisioning/modules/concat/spec/spec_helper_acceptance.rb
dev/provisioning/modules/concat/spec/unit/classes/concat_setup_spec.rb
dev/provisioning/modules/concat/spec/unit/defines/concat_fragment_spec.rb
dev/provisioning/modules/concat/spec/unit/defines/concat_spec.rb
dev/provisioning/modules/concat/spec/unit/facts/concat_basedir_spec.rb
dev/provisioning/modules/concat/tests/fragment.pp
dev/provisioning/modules/concat/tests/init.pp
dev/provisioning/modules/datacat/Changes
dev/provisioning/modules/datacat/Gemfile
dev/provisioning/modules/datacat/NOTES.md
dev/provisioning/modules/datacat/README.md
dev/provisioning/modules/datacat/Rakefile
dev/provisioning/modules/datacat/TODO.md
dev/provisioning/modules/datacat/checksums.json
dev/provisioning/modules/datacat/lib/puppet/parser/functions/template_body.rb
dev/provisioning/modules/datacat/lib/puppet/provider/datacat_collector/datacat_collector.rb
dev/provisioning/modules/datacat/lib/puppet/provider/datacat_fragment/datacat_fragment.rb
dev/provisioning/modules/datacat/lib/puppet/type/datacat_collector.rb
dev/provisioning/modules/datacat/lib/puppet/type/datacat_fragment.rb
dev/provisioning/modules/datacat/lib/puppet_x/richardc/datacat.rb
dev/provisioning/modules/datacat/manifests/init.pp
dev/provisioning/modules/datacat/metadata.json
dev/provisioning/modules/datacat/spec/classes/demo1_spec.rb
dev/provisioning/modules/datacat/spec/defines/datacat_spec.rb
dev/provisioning/modules/datacat/spec/fixtures/modules/demo1/manifests/init.pp
dev/provisioning/modules/datacat/spec/fixtures/modules/demo1/templates/sheeps.erb
dev/provisioning/modules/datacat/spec/fixtures/modules/demo2/manifests/init.pp
dev/provisioning/modules/datacat/spec/fixtures/modules/demo2/templates/merging.erb
dev/provisioning/modules/datacat/spec/fixtures/modules/demo3/manifests/init.pp
dev/provisioning/modules/datacat/spec/fixtures/modules/demo3/templates/hostgroups.cfg.erb
dev/provisioning/modules/datacat/spec/fixtures/modules/issue1/manifests/init.pp
dev/provisioning/modules/datacat/spec/fixtures/modules/issue1/templates/refers_to_scope.erb
dev/provisioning/modules/datacat/spec/fixtures/modules/template_body/templates/test1.erb
dev/provisioning/modules/datacat/spec/functions/template_body_spec.rb
dev/provisioning/modules/datacat/spec/spec_helper.rb
dev/provisioning/modules/datacat/spec/spec_helper_system.rb
dev/provisioning/modules/datacat/spec/system/basic_spec.rb
dev/provisioning/modules/datacat/spec/unit/type/datacat_collector_spec.rb
dev/provisioning/modules/elasticsearch/.fixtures.yml
dev/provisioning/modules/elasticsearch/.gitignore
dev/provisioning/modules/elasticsearch/.pmtignore
dev/provisioning/modules/elasticsearch/CHANGELOG.md
dev/provisioning/modules/elasticsearch/CONTRIBUTING.md
dev/provisioning/modules/elasticsearch/CONTRIBUTORS
dev/provisioning/modules/elasticsearch/Gemfile
dev/provisioning/modules/elasticsearch/LICENSE
dev/provisioning/modules/elasticsearch/README.md
dev/provisioning/modules/elasticsearch/Rakefile
dev/provisioning/modules/elasticsearch/lib/facter/es_facts.rb
dev/provisioning/modules/elasticsearch/lib/puppet/parser/functions/array_suffix.rb
dev/provisioning/modules/elasticsearch/lib/puppet/parser/functions/plugin_dir.rb
dev/provisioning/modules/elasticsearch/lib/puppet/provider/elasticsearch_plugin/plugin.rb
dev/provisioning/modules/elasticsearch/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb
dev/provisioning/modules/elasticsearch/lib/puppet/type/elasticsearch_plugin.rb
dev/provisioning/modules/elasticsearch/lib/puppet/type/es_instance_conn_validator.rb
dev/provisioning/modules/elasticsearch/lib/puppet/util/es_instance_validator.rb
dev/provisioning/modules/elasticsearch/manifests/config.pp
dev/provisioning/modules/elasticsearch/manifests/init.pp
dev/provisioning/modules/elasticsearch/manifests/instance.pp
dev/provisioning/modules/elasticsearch/manifests/package.pp
dev/provisioning/modules/elasticsearch/manifests/params.pp
dev/provisioning/modules/elasticsearch/manifests/plugin.pp
dev/provisioning/modules/elasticsearch/manifests/python.pp
dev/provisioning/modules/elasticsearch/manifests/repo.pp
dev/provisioning/modules/elasticsearch/manifests/ruby.pp
dev/provisioning/modules/elasticsearch/manifests/script.pp
dev/provisioning/modules/elasticsearch/manifests/service.pp
dev/provisioning/modules/elasticsearch/manifests/service/init.pp
dev/provisioning/modules/elasticsearch/manifests/service/systemd.pp
dev/provisioning/modules/elasticsearch/manifests/template.pp
dev/provisioning/modules/elasticsearch/metadata.json
dev/provisioning/modules/elasticsearch/spec/acceptance/001_basic_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/002_class_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/003_template_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/004_plugin_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/009_datapath_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/010_pkg_url_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/011_service_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/012_instances_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/013_config_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/014_hiera_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/015_staged_removal.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/016_package_pin_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/017_restart_on_change_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/020_usergroup_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/021_es2x_spec.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/integration001.rb
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/centos-6-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/centos-7-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/debian-6-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/debian-7-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/debian-8-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/opensuse-121-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/opensuse-131-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/sles-11sp3-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1204-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1210-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1304-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml
dev/provisioning/modules/elasticsearch/spec/acceptance/xplugins001.rb
dev/provisioning/modules/elasticsearch/spec/classes/000_elasticsearch_init_spec.rb
dev/provisioning/modules/elasticsearch/spec/classes/001_hiera_spec.rb
dev/provisioning/modules/elasticsearch/spec/classes/005_elasticsearch_repo_spec.rb
dev/provisioning/modules/elasticsearch/spec/classes/010_elasticsearch_init_unkown_spec.rb
dev/provisioning/modules/elasticsearch/spec/classes/099_coverage_spec.rb
dev/provisioning/modules/elasticsearch/spec/defines/001_elasticsearch_python_spec.rb
dev/provisioning/modules/elasticsearch/spec/defines/002_elasticsearch_ruby_spec.rb
dev/provisioning/modules/elasticsearch/spec/defines/003_elasticsearch_template_spec.rb
dev/provisioning/modules/elasticsearch/spec/defines/004_elasticsearch_plugin_spec.rb
dev/provisioning/modules/elasticsearch/spec/defines/005_elasticsearch_instance_spec.rb
dev/provisioning/modules/elasticsearch/spec/defines/006_elasticsearch_script_spec.rb
dev/provisioning/modules/elasticsearch/spec/defines/010_elasticsearch_service_init_spec.rb
dev/provisioning/modules/elasticsearch/spec/defines/011_elasticsearch_service_system_spec.rb
dev/provisioning/modules/elasticsearch/spec/fixtures/facts/facts_url1.json
dev/provisioning/modules/elasticsearch/spec/fixtures/facts/facts_url2.json
dev/provisioning/modules/elasticsearch/spec/fixtures/hiera/hiera.yaml
dev/provisioning/modules/elasticsearch/spec/fixtures/hiera/hieradata/envs/defaultinstance.yaml
dev/provisioning/modules/elasticsearch/spec/fixtures/hiera/hieradata/multipleinstances.yaml
dev/provisioning/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleinstance.yaml
dev/provisioning/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleplugin.yaml
dev/provisioning/modules/elasticsearch/spec/functions/es_facts_spec.rb
dev/provisioning/modules/elasticsearch/spec/functions/plugin_dir_spec.rb
dev/provisioning/modules/elasticsearch/spec/spec_acceptance_common.rb
dev/provisioning/modules/elasticsearch/spec/spec_acceptance_integration.rb
dev/provisioning/modules/elasticsearch/spec/spec_helper.rb
dev/provisioning/modules/elasticsearch/spec/spec_helper_acceptance.rb
dev/provisioning/modules/elasticsearch/spec/unit/provider/plugin_spec.rb
dev/provisioning/modules/elasticsearch/spec/unit/type/plugin_spec.rb
dev/provisioning/modules/elasticsearch/templates/etc/elasticsearch/elasticsearch.yml.erb
dev/provisioning/modules/elasticsearch/templates/etc/elasticsearch/logging.yml.erb
dev/provisioning/modules/elasticsearch/templates/etc/init.d/elasticsearch.Debian.erb
dev/provisioning/modules/elasticsearch/templates/etc/init.d/elasticsearch.RedHat.erb
dev/provisioning/modules/elasticsearch/templates/etc/init.d/elasticsearch.systemd.erb
dev/provisioning/modules/elasticsearch/templates/etc/sysconfig/defaults.erb
dev/provisioning/modules/elasticsearch/templates/usr/lib/tmpfiles.d/elasticsearch.conf.erb
dev/provisioning/modules/mysql/CHANGELOG.md
dev/provisioning/modules/mysql/CONTRIBUTING.md
dev/provisioning/modules/mysql/Gemfile
dev/provisioning/modules/mysql/LICENSE
dev/provisioning/modules/mysql/README.md
dev/provisioning/modules/mysql/Rakefile
dev/provisioning/modules/mysql/TODO
dev/provisioning/modules/mysql/checksums.json
dev/provisioning/modules/mysql/examples/backup.pp
dev/provisioning/modules/mysql/examples/bindings.pp
dev/provisioning/modules/mysql/examples/java.pp
dev/provisioning/modules/mysql/examples/mysql_database.pp
dev/provisioning/modules/mysql/examples/mysql_db.pp
dev/provisioning/modules/mysql/examples/mysql_grant.pp
dev/provisioning/modules/mysql/examples/mysql_plugin.pp
dev/provisioning/modules/mysql/examples/mysql_user.pp
dev/provisioning/modules/mysql/examples/perl.pp
dev/provisioning/modules/mysql/examples/python.pp
dev/provisioning/modules/mysql/examples/ruby.pp
dev/provisioning/modules/mysql/examples/server.pp
dev/provisioning/modules/mysql/examples/server/account_security.pp
dev/provisioning/modules/mysql/examples/server/config.pp
dev/provisioning/modules/mysql/lib/facter/mysql_server_id.rb
dev/provisioning/modules/mysql/lib/facter/mysql_version.rb
dev/provisioning/modules/mysql/lib/puppet/parser/functions/mysql_deepmerge.rb
dev/provisioning/modules/mysql/lib/puppet/parser/functions/mysql_dirname.rb
dev/provisioning/modules/mysql/lib/puppet/parser/functions/mysql_password.rb
dev/provisioning/modules/mysql/lib/puppet/parser/functions/mysql_strip_hash.rb
dev/provisioning/modules/mysql/lib/puppet/provider/mysql.rb
dev/provisioning/modules/mysql/lib/puppet/provider/mysql_database/mysql.rb
dev/provisioning/modules/mysql/lib/puppet/provider/mysql_grant/mysql.rb
dev/provisioning/modules/mysql/lib/puppet/provider/mysql_plugin/mysql.rb
dev/provisioning/modules/mysql/lib/puppet/provider/mysql_user/mysql.rb
dev/provisioning/modules/mysql/lib/puppet/type/mysql_database.rb
dev/provisioning/modules/mysql/lib/puppet/type/mysql_grant.rb
dev/provisioning/modules/mysql/lib/puppet/type/mysql_plugin.rb
dev/provisioning/modules/mysql/lib/puppet/type/mysql_user.rb
dev/provisioning/modules/mysql/manifests/backup/mysqlbackup.pp
dev/provisioning/modules/mysql/manifests/backup/mysqldump.pp
dev/provisioning/modules/mysql/manifests/backup/xtrabackup.pp
dev/provisioning/modules/mysql/manifests/bindings.pp
dev/provisioning/modules/mysql/manifests/bindings/client_dev.pp
dev/provisioning/modules/mysql/manifests/bindings/daemon_dev.pp
dev/provisioning/modules/mysql/manifests/bindings/java.pp
dev/provisioning/modules/mysql/manifests/bindings/perl.pp
dev/provisioning/modules/mysql/manifests/bindings/php.pp
dev/provisioning/modules/mysql/manifests/bindings/python.pp
dev/provisioning/modules/mysql/manifests/bindings/ruby.pp
dev/provisioning/modules/mysql/manifests/client.pp
dev/provisioning/modules/mysql/manifests/client/install.pp
dev/provisioning/modules/mysql/manifests/db.pp
dev/provisioning/modules/mysql/manifests/params.pp
dev/provisioning/modules/mysql/manifests/server.pp
dev/provisioning/modules/mysql/manifests/server/account_security.pp
dev/provisioning/modules/mysql/manifests/server/backup.pp
dev/provisioning/modules/mysql/manifests/server/config.pp
dev/provisioning/modules/mysql/manifests/server/install.pp
dev/provisioning/modules/mysql/manifests/server/installdb.pp
dev/provisioning/modules/mysql/manifests/server/monitor.pp
dev/provisioning/modules/mysql/manifests/server/mysqltuner.pp
dev/provisioning/modules/mysql/manifests/server/providers.pp
dev/provisioning/modules/mysql/manifests/server/root_password.pp
dev/provisioning/modules/mysql/manifests/server/service.pp
dev/provisioning/modules/mysql/metadata.json
dev/provisioning/modules/mysql/spec/acceptance/mysql_backup_spec.rb
dev/provisioning/modules/mysql/spec/acceptance/mysql_db_spec.rb
dev/provisioning/modules/mysql/spec/acceptance/mysql_server_spec.rb
dev/provisioning/modules/mysql/spec/acceptance/nodesets/centos-510-x64.yml
dev/provisioning/modules/mysql/spec/acceptance/nodesets/centos-59-x64.yml
dev/provisioning/modules/mysql/spec/acceptance/nodesets/centos-64-x64-pe.yml
dev/provisioning/modules/mysql/spec/acceptance/nodesets/centos-65-x64.yml
dev/provisioning/modules/mysql/spec/acceptance/nodesets/default.yml
dev/provisioning/modules/mysql/spec/acceptance/nodesets/fedora-18-x64.yml
dev/provisioning/modules/mysql/spec/acceptance/nodesets/sles-11-x64.yml
dev/provisioning/modules/mysql/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml
dev/provisioning/modules/mysql/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml
dev/provisioning/modules/mysql/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml
dev/provisioning/modules/mysql/spec/acceptance/types/mysql_database_spec.rb
dev/provisioning/modules/mysql/spec/acceptance/types/mysql_grant_spec.rb
dev/provisioning/modules/mysql/spec/acceptance/types/mysql_plugin_spec.rb
dev/provisioning/modules/mysql/spec/acceptance/types/mysql_user_spec.rb
dev/provisioning/modules/mysql/spec/classes/graceful_failures_spec.rb
dev/provisioning/modules/mysql/spec/classes/mycnf_template_spec.rb
dev/provisioning/modules/mysql/spec/classes/mysql_bindings_spec.rb
dev/provisioning/modules/mysql/spec/classes/mysql_client_spec.rb
dev/provisioning/modules/mysql/spec/classes/mysql_server_account_security_spec.rb
dev/provisioning/modules/mysql/spec/classes/mysql_server_backup_spec.rb
dev/provisioning/modules/mysql/spec/classes/mysql_server_monitor_spec.rb
dev/provisioning/modules/mysql/spec/classes/mysql_server_mysqltuner_spec.rb
dev/provisioning/modules/mysql/spec/classes/mysql_server_spec.rb
dev/provisioning/modules/mysql/spec/defines/mysql_db_spec.rb
dev/provisioning/modules/mysql/spec/spec.opts
dev/provisioning/modules/mysql/spec/spec_helper.rb
dev/provisioning/modules/mysql/spec/spec_helper_acceptance.rb
dev/provisioning/modules/mysql/spec/unit/facter/mysql_server_id_spec.rb
dev/provisioning/modules/mysql/spec/unit/facter/mysql_version_spec.rb
dev/provisioning/modules/mysql/spec/unit/puppet/functions/mysql_deepmerge_spec.rb
dev/provisioning/modules/mysql/spec/unit/puppet/functions/mysql_password_spec.rb
dev/provisioning/modules/mysql/spec/unit/puppet/provider/mysql_database/mysql_spec.rb
dev/provisioning/modules/mysql/spec/unit/puppet/provider/mysql_plugin/mysql_spec.rb
dev/provisioning/modules/mysql/spec/unit/puppet/provider/mysql_user/mysql_spec.rb
dev/provisioning/modules/mysql/spec/unit/puppet/type/mysql_database_spec.rb
dev/provisioning/modules/mysql/spec/unit/puppet/type/mysql_grant_spec.rb
dev/provisioning/modules/mysql/spec/unit/puppet/type/mysql_plugin_spec.rb
dev/provisioning/modules/mysql/spec/unit/puppet/type/mysql_user_spec.rb
dev/provisioning/modules/mysql/templates/meb.cnf.erb
dev/provisioning/modules/mysql/templates/my.cnf.erb
dev/provisioning/modules/mysql/templates/my.cnf.pass.erb
dev/provisioning/modules/mysql/templates/mysqlbackup.sh.erb
dev/provisioning/modules/mysql/templates/xtrabackup.sh.erb
dev/provisioning/modules/puppi/.fixtures.yml
dev/provisioning/modules/puppi/.gitignore
dev/provisioning/modules/puppi/.project
dev/provisioning/modules/puppi/.travis.yml
dev/provisioning/modules/puppi/Gemfile
dev/provisioning/modules/puppi/LICENSE
dev/provisioning/modules/puppi/Modulefile
dev/provisioning/modules/puppi/README.md
dev/provisioning/modules/puppi/README_check.md
dev/provisioning/modules/puppi/README_deploy.md
dev/provisioning/modules/puppi/README_info.md
dev/provisioning/modules/puppi/README_log.md
dev/provisioning/modules/puppi/Rakefile
dev/provisioning/modules/puppi/composer.json
dev/provisioning/modules/puppi/files/info/readme/readme
dev/provisioning/modules/puppi/files/info/readme/readme-default
dev/provisioning/modules/puppi/files/mailpuppicheck
dev/provisioning/modules/puppi/files/mcollective/mc-puppi
dev/provisioning/modules/puppi/files/mcollective/puppi.ddl
dev/provisioning/modules/puppi/files/mcollective/puppi.rb
dev/provisioning/modules/puppi/files/mcollective/puppicheck
dev/provisioning/modules/puppi/files/mcollective/puppideploy
dev/provisioning/modules/puppi/files/scripts/archive.sh
dev/provisioning/modules/puppi/files/scripts/check_project.sh
dev/provisioning/modules/puppi/files/scripts/checkwardir.sh
dev/provisioning/modules/puppi/files/scripts/clean_filelist.sh
dev/provisioning/modules/puppi/files/scripts/database.sh
dev/provisioning/modules/puppi/files/scripts/delete.sh
dev/provisioning/modules/puppi/files/scripts/deploy.sh
dev/provisioning/modules/puppi/files/scripts/deploy_files.sh
dev/provisioning/modules/puppi/files/scripts/execute.sh
dev/provisioning/modules/puppi/files/scripts/firewall.sh
dev/provisioning/modules/puppi/files/scripts/functions
dev/provisioning/modules/puppi/files/scripts/get_file.sh
dev/provisioning/modules/puppi/files/scripts/get_filesfromlist.sh
dev/provisioning/modules/puppi/files/scripts/get_maven_files.sh
dev/provisioning/modules/puppi/files/scripts/get_metadata.sh
dev/provisioning/modules/puppi/files/scripts/git.sh
dev/provisioning/modules/puppi/files/scripts/header
dev/provisioning/modules/puppi/files/scripts/hg.sh
dev/provisioning/modules/puppi/files/scripts/predeploy.sh
dev/provisioning/modules/puppi/files/scripts/predeploy_tar.sh
dev/provisioning/modules/puppi/files/scripts/report_mail.sh
dev/provisioning/modules/puppi/files/scripts/report_mongo.sh
dev/provisioning/modules/puppi/files/scripts/service.sh
dev/provisioning/modules/puppi/files/scripts/svn.sh
dev/provisioning/modules/puppi/files/scripts/wait.sh
dev/provisioning/modules/puppi/files/scripts/yant.sh
dev/provisioning/modules/puppi/files/scripts/yum.sh
dev/provisioning/modules/puppi/lib/facter/last_run.rb
dev/provisioning/modules/puppi/lib/facter/puppi_projects.rb
dev/provisioning/modules/puppi/lib/facter/windows_common_appdata.rb
dev/provisioning/modules/puppi/lib/puppet/functions/params_lookup.rb
dev/provisioning/modules/puppi/lib/puppet/parser/functions/any2bool.rb
dev/provisioning/modules/puppi/lib/puppet/parser/functions/bool2ensure.rb
dev/provisioning/modules/puppi/lib/puppet/parser/functions/get_class_args.rb
dev/provisioning/modules/puppi/lib/puppet/parser/functions/get_magicvar.rb
dev/provisioning/modules/puppi/lib/puppet/parser/functions/get_module_path.rb
dev/provisioning/modules/puppi/lib/puppet/parser/functions/nslookup.rb
dev/provisioning/modules/puppi/lib/puppet/parser/functions/options_lookup.rb
dev/provisioning/modules/puppi/lib/puppet/parser/functions/params_lookup.rb
dev/provisioning/modules/puppi/lib/puppet/parser/functions/url_parse.rb
dev/provisioning/modules/puppi/manifests/check.pp
dev/provisioning/modules/puppi/manifests/configure.pp
dev/provisioning/modules/puppi/manifests/dependencies.pp
dev/provisioning/modules/puppi/manifests/deploy.pp
dev/provisioning/modules/puppi/manifests/extras.pp
dev/provisioning/modules/puppi/manifests/helper.pp
dev/provisioning/modules/puppi/manifests/helpers.pp
dev/provisioning/modules/puppi/manifests/info.pp
dev/provisioning/modules/puppi/manifests/info/instance.pp
dev/provisioning/modules/puppi/manifests/info/module.pp
dev/provisioning/modules/puppi/manifests/info/readme.pp
dev/provisioning/modules/puppi/manifests/init.pp
dev/provisioning/modules/puppi/manifests/initialize.pp
dev/provisioning/modules/puppi/manifests/install_packages.pp
dev/provisioning/modules/puppi/manifests/log.pp
dev/provisioning/modules/puppi/manifests/mcollective/client.pp
dev/provisioning/modules/puppi/manifests/mcollective/server.pp
dev/provisioning/modules/puppi/manifests/netinstall.pp
dev/provisioning/modules/puppi/manifests/one.pp
dev/provisioning/modules/puppi/manifests/params.pp
dev/provisioning/modules/puppi/manifests/project.pp
dev/provisioning/modules/puppi/manifests/project/README
dev/provisioning/modules/puppi/manifests/project/archive.pp
dev/provisioning/modules/puppi/manifests/project/builder.pp
dev/provisioning/modules/puppi/manifests/project/dir.pp
dev/provisioning/modules/puppi/manifests/project/files.pp
dev/provisioning/modules/puppi/manifests/project/git.pp
dev/provisioning/modules/puppi/manifests/project/hg.pp
dev/provisioning/modules/puppi/manifests/project/maven.pp
dev/provisioning/modules/puppi/manifests/project/mysql.pp
dev/provisioning/modules/puppi/manifests/project/service.pp
dev/provisioning/modules/puppi/manifests/project/svn.pp
dev/provisioning/modules/puppi/manifests/project/tar.pp
dev/provisioning/modules/puppi/manifests/project/war.pp
dev/provisioning/modules/puppi/manifests/project/y4maven.pp
dev/provisioning/modules/puppi/manifests/project/yum.pp
dev/provisioning/modules/puppi/manifests/report.pp
dev/provisioning/modules/puppi/manifests/rollback.pp
dev/provisioning/modules/puppi/manifests/run.pp
dev/provisioning/modules/puppi/manifests/runscript.pp
dev/provisioning/modules/puppi/manifests/skel.pp
dev/provisioning/modules/puppi/manifests/todo.pp
dev/provisioning/modules/puppi/manifests/two.pp
dev/provisioning/modules/puppi/manifests/ze.pp
dev/provisioning/modules/puppi/spec/classes/puppi_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_check_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_deploy_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_helper_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_info_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_initialize_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_log_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_project_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_report_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_rollback_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_run_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_todo_spec.rb
dev/provisioning/modules/puppi/spec/defines/puppi_ze_spec.rb
dev/provisioning/modules/puppi/spec/functions/any2bool_spec.rb
dev/provisioning/modules/puppi/spec/functions/bool2ensure_spec.rb
dev/provisioning/modules/puppi/spec/functions/url_parse_spec.rb
dev/provisioning/modules/puppi/spec/spec_helper.rb
dev/provisioning/modules/puppi/templates/helpers/standard.yml.erb
dev/provisioning/modules/puppi/templates/info.erb
dev/provisioning/modules/puppi/templates/info/instance.erb
dev/provisioning/modules/puppi/templates/info/module.erb
dev/provisioning/modules/puppi/templates/info/puppet.erb
dev/provisioning/modules/puppi/templates/info/readme.erb
dev/provisioning/modules/puppi/templates/install_packages.erb
dev/provisioning/modules/puppi/templates/log.erb
dev/provisioning/modules/puppi/templates/project/config.erb
dev/provisioning/modules/puppi/templates/puppi.conf.erb
dev/provisioning/modules/puppi/templates/puppi.erb
dev/provisioning/modules/puppi/templates/puppi_clean.erb
dev/provisioning/modules/puppi/templates/todo.erb
dev/provisioning/modules/stdlib/CHANGELOG.md
dev/provisioning/modules/stdlib/CONTRIBUTING.md
dev/provisioning/modules/stdlib/Gemfile
dev/provisioning/modules/stdlib/LICENSE
dev/provisioning/modules/stdlib/README.markdown
dev/provisioning/modules/stdlib/README_DEVELOPER.markdown
dev/provisioning/modules/stdlib/README_SPECS.markdown
dev/provisioning/modules/stdlib/RELEASE_PROCESS.markdown
dev/provisioning/modules/stdlib/Rakefile
dev/provisioning/modules/stdlib/checksums.json
dev/provisioning/modules/stdlib/examples/file_line.pp
dev/provisioning/modules/stdlib/examples/has_interface_with.pp
dev/provisioning/modules/stdlib/examples/has_ip_address.pp
dev/provisioning/modules/stdlib/examples/has_ip_network.pp
dev/provisioning/modules/stdlib/examples/init.pp
dev/provisioning/modules/stdlib/lib/facter/facter_dot_d.rb
dev/provisioning/modules/stdlib/lib/facter/pe_version.rb
dev/provisioning/modules/stdlib/lib/facter/puppet_vardir.rb
dev/provisioning/modules/stdlib/lib/facter/root_home.rb
dev/provisioning/modules/stdlib/lib/facter/util/puppet_settings.rb
dev/provisioning/modules/stdlib/lib/puppet/functions/type_of.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/abs.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/any2array.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/assert_private.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/base64.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/basename.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/bool2num.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/bool2str.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/camelcase.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/capitalize.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/ceiling.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/chomp.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/chop.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/concat.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/convert_base.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/count.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/deep_merge.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/defined_with_params.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/delete.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/delete_at.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/delete_undef_values.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/delete_values.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/difference.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/dirname.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/dos2unix.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/downcase.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/empty.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/ensure_packages.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/ensure_resource.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/flatten.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/floor.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/fqdn_rotate.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/get_module_path.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/getparam.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/getvar.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/grep.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/has_interface_with.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/has_ip_address.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/has_ip_network.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/has_key.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/hash.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/intersection.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_array.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_bool.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_domain_name.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_float.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_function_available.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_hash.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_integer.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_ip_address.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_mac_address.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_numeric.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_string.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/join.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/join_keys_to_values.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/keys.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/load_module_metadata.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/loadyaml.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/lstrip.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/max.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/member.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/merge.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/min.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/num2bool.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/parsejson.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/parseyaml.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/pick.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/pick_default.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/prefix.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/private.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/pw_hash.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/range.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/reject.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/reverse.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/rstrip.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/shuffle.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/size.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/sort.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/squeeze.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/str2bool.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/str2saltedsha512.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/strftime.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/strip.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/suffix.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/swapcase.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/time.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/to_bytes.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/try_get_value.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/type.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/type3x.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/union.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/unique.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/unix2dos.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/upcase.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/uriescape.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_absolute_path.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_array.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_augeas.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_bool.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_cmd.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_hash.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_integer.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_ipv4_address.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_ipv6_address.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_numeric.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_re.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_slength.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_string.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/values.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/values_at.rb
dev/provisioning/modules/stdlib/lib/puppet/parser/functions/zip.rb
dev/provisioning/modules/stdlib/lib/puppet/provider/file_line/ruby.rb
dev/provisioning/modules/stdlib/lib/puppet/type/anchor.rb
dev/provisioning/modules/stdlib/lib/puppet/type/file_line.rb
dev/provisioning/modules/stdlib/manifests/init.pp
dev/provisioning/modules/stdlib/manifests/stages.pp
dev/provisioning/modules/stdlib/metadata.json
dev/provisioning/modules/stdlib/spec/acceptance/abs_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/anchor_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/any2array_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/base64_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/bool2num_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/build_csv.rb
dev/provisioning/modules/stdlib/spec/acceptance/capitalize_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/ceiling_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/chomp_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/chop_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/concat_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/count_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/deep_merge_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/defined_with_params_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/delete_at_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/delete_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/delete_undef_values_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/delete_values_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/difference_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/dirname_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/downcase_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/empty_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/ensure_resource_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/flatten_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/floor_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/fqdn_rand_string_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/fqdn_rotate_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/get_module_path_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/getparam_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/getvar_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/grep_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/has_interface_with_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/has_ip_address_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/has_ip_network_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/has_key_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/hash_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/intersection_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/is_array_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/is_bool_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/is_domain_name_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/is_float_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/is_function_available_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/is_hash_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/is_integer_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/is_ip_address_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/is_mac_address_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/is_numeric_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/is_string_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/join_keys_to_values_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/join_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/keys_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/loadyaml_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/lstrip_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/max_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/member_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/merge_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/min_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/centos-59-x64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/centos-6-vcloud.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/centos-64-x64-pe.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/centos-64-x64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/centos-65-x64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/default.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/fedora-18-x64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/sles-11-x64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2003-i386.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2003-x86_64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2008-x86_64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2008r2-x86_64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2012-x86_64.yml
dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2012r2-x86_64.yml
dev/provisioning/modules/stdlib/spec/acceptance/num2bool_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/parsejson_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/parseyaml_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/pick_default_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/pick_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/prefix_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/pw_hash_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/range_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/reject_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/reverse_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/rstrip_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/shuffle_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/size_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/sort_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/squeeze_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/str2bool_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/str2saltedsha512_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/strftime_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/strip_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/suffix_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/swapcase_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/time_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/to_bytes_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/try_get_value_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/type_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/union_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/unique_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/unsupported_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/upcase_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/uriescape_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/validate_absolute_path_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/validate_array_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/validate_augeas_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/validate_bool_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/validate_cmd_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/validate_hash_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/validate_ipv4_address_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/validate_ipv6_address_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/validate_re_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/validate_slength_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/validate_string_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/values_at_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/values_spec.rb
dev/provisioning/modules/stdlib/spec/acceptance/zip_spec.rb
dev/provisioning/modules/stdlib/spec/fixtures/dscacheutil/root
dev/provisioning/modules/stdlib/spec/fixtures/lsuser/root
dev/provisioning/modules/stdlib/spec/functions/abs_spec.rb
dev/provisioning/modules/stdlib/spec/functions/any2array_spec.rb
dev/provisioning/modules/stdlib/spec/functions/assert_private_spec.rb
dev/provisioning/modules/stdlib/spec/functions/base64_spec.rb
dev/provisioning/modules/stdlib/spec/functions/basename_spec.rb
dev/provisioning/modules/stdlib/spec/functions/bool2num_spec.rb
dev/provisioning/modules/stdlib/spec/functions/bool2str_spec.rb
dev/provisioning/modules/stdlib/spec/functions/camelcase_spec.rb
dev/provisioning/modules/stdlib/spec/functions/capitalize_spec.rb
dev/provisioning/modules/stdlib/spec/functions/ceiling_spec.rb
dev/provisioning/modules/stdlib/spec/functions/chomp_spec.rb
dev/provisioning/modules/stdlib/spec/functions/chop_spec.rb
dev/provisioning/modules/stdlib/spec/functions/concat_spec.rb
dev/provisioning/modules/stdlib/spec/functions/convert_base_spec.rb
dev/provisioning/modules/stdlib/spec/functions/count_spec.rb
dev/provisioning/modules/stdlib/spec/functions/deep_merge_spec.rb
dev/provisioning/modules/stdlib/spec/functions/defined_with_params_spec.rb
dev/provisioning/modules/stdlib/spec/functions/delete_at_spec.rb
dev/provisioning/modules/stdlib/spec/functions/delete_spec.rb
dev/provisioning/modules/stdlib/spec/functions/delete_undef_values_spec.rb
dev/provisioning/modules/stdlib/spec/functions/delete_values_spec.rb
dev/provisioning/modules/stdlib/spec/functions/difference_spec.rb
dev/provisioning/modules/stdlib/spec/functions/dirname_spec.rb
dev/provisioning/modules/stdlib/spec/functions/dos2unix_spec.rb
dev/provisioning/modules/stdlib/spec/functions/downcase_spec.rb
dev/provisioning/modules/stdlib/spec/functions/empty_spec.rb
dev/provisioning/modules/stdlib/spec/functions/ensure_packages_spec.rb
dev/provisioning/modules/stdlib/spec/functions/ensure_resource_spec.rb
dev/provisioning/modules/stdlib/spec/functions/flatten_spec.rb
dev/provisioning/modules/stdlib/spec/functions/floor_spec.rb
dev/provisioning/modules/stdlib/spec/functions/fqdn_rand_string_spec.rb
dev/provisioning/modules/stdlib/spec/functions/fqdn_rotate_spec.rb
dev/provisioning/modules/stdlib/spec/functions/get_module_path_spec.rb
dev/provisioning/modules/stdlib/spec/functions/getparam_spec.rb
dev/provisioning/modules/stdlib/spec/functions/getvar_spec.rb
dev/provisioning/modules/stdlib/spec/functions/grep_spec.rb
dev/provisioning/modules/stdlib/spec/functions/has_interface_with_spec.rb
dev/provisioning/modules/stdlib/spec/functions/has_ip_address_spec.rb
dev/provisioning/modules/stdlib/spec/functions/has_ip_network_spec.rb
dev/provisioning/modules/stdlib/spec/functions/has_key_spec.rb
dev/provisioning/modules/stdlib/spec/functions/hash_spec.rb
dev/provisioning/modules/stdlib/spec/functions/intersection_spec.rb
dev/provisioning/modules/stdlib/spec/functions/is_array_spec.rb
dev/provisioning/modules/stdlib/spec/functions/is_bool_spec.rb
dev/provisioning/modules/stdlib/spec/functions/is_domain_name_spec.rb
dev/provisioning/modules/stdlib/spec/functions/is_float_spec.rb
dev/provisioning/modules/stdlib/spec/functions/is_function_available.rb
dev/provisioning/modules/stdlib/spec/functions/is_hash_spec.rb
dev/provisioning/modules/stdlib/spec/functions/is_integer_spec.rb
dev/provisioning/modules/stdlib/spec/functions/is_ip_address_spec.rb
dev/provisioning/modules/stdlib/spec/functions/is_mac_address_spec.rb
dev/provisioning/modules/stdlib/spec/functions/is_numeric_spec.rb
dev/provisioning/modules/stdlib/spec/functions/is_string_spec.rb
dev/provisioning/modules/stdlib/spec/functions/join_keys_to_values_spec.rb
dev/provisioning/modules/stdlib/spec/functions/join_spec.rb
dev/provisioning/modules/stdlib/spec/functions/keys_spec.rb
dev/provisioning/modules/stdlib/spec/functions/load_module_metadata.rb
dev/provisioning/modules/stdlib/spec/functions/loadyaml_spec.rb
dev/provisioning/modules/stdlib/spec/functions/lstrip_spec.rb
dev/provisioning/modules/stdlib/spec/functions/max_spec.rb
dev/provisioning/modules/stdlib/spec/functions/member_spec.rb
dev/provisioning/modules/stdlib/spec/functions/merge_spec.rb
dev/provisioning/modules/stdlib/spec/functions/min_spec.rb
dev/provisioning/modules/stdlib/spec/functions/num2bool_spec.rb
dev/provisioning/modules/stdlib/spec/functions/parsejson_spec.rb
dev/provisioning/modules/stdlib/spec/functions/parseyaml_spec.rb
dev/provisioning/modules/stdlib/spec/functions/pick_default_spec.rb
dev/provisioning/modules/stdlib/spec/functions/pick_spec.rb
dev/provisioning/modules/stdlib/spec/functions/prefix_spec.rb
dev/provisioning/modules/stdlib/spec/functions/private_spec.rb
dev/provisioning/modules/stdlib/spec/functions/pw_hash_spec.rb
dev/provisioning/modules/stdlib/spec/functions/range_spec.rb
dev/provisioning/modules/stdlib/spec/functions/reject_spec.rb
dev/provisioning/modules/stdlib/spec/functions/reverse_spec.rb
dev/provisioning/modules/stdlib/spec/functions/rstrip_spec.rb
dev/provisioning/modules/stdlib/spec/functions/shuffle_spec.rb
dev/provisioning/modules/stdlib/spec/functions/size_spec.rb
dev/provisioning/modules/stdlib/spec/functions/sort_spec.rb
dev/provisioning/modules/stdlib/spec/functions/squeeze_spec.rb
dev/provisioning/modules/stdlib/spec/functions/str2bool_spec.rb
dev/provisioning/modules/stdlib/spec/functions/str2saltedsha512_spec.rb
dev/provisioning/modules/stdlib/spec/functions/strftime_spec.rb
dev/provisioning/modules/stdlib/spec/functions/strip_spec.rb
dev/provisioning/modules/stdlib/spec/functions/suffix_spec.rb
dev/provisioning/modules/stdlib/spec/functions/swapcase_spec.rb
dev/provisioning/modules/stdlib/spec/functions/time_spec.rb
dev/provisioning/modules/stdlib/spec/functions/to_bytes_spec.rb
dev/provisioning/modules/stdlib/spec/functions/try_get_value_spec.rb
dev/provisioning/modules/stdlib/spec/functions/type3x_spec.rb
dev/provisioning/modules/stdlib/spec/functions/type_of_spec.rb
dev/provisioning/modules/stdlib/spec/functions/type_spec.rb
dev/provisioning/modules/stdlib/spec/functions/union_spec.rb
dev/provisioning/modules/stdlib/spec/functions/unique_spec.rb
dev/provisioning/modules/stdlib/spec/functions/unix2dos_spec.rb
dev/provisioning/modules/stdlib/spec/functions/upcase_spec.rb
dev/provisioning/modules/stdlib/spec/functions/uriescape_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_absolute_path_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_array_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_augeas_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_bool_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_cmd_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_hash_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_integer_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_ipv4_address_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_ipv6_address_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_numeric_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_re_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_slength_spec.rb
dev/provisioning/modules/stdlib/spec/functions/validate_string_spec.rb
dev/provisioning/modules/stdlib/spec/functions/values_at_spec.rb
dev/provisioning/modules/stdlib/spec/functions/values_spec.rb
dev/provisioning/modules/stdlib/spec/functions/zip_spec.rb
dev/provisioning/modules/stdlib/spec/monkey_patches/alias_should_to_must.rb
dev/provisioning/modules/stdlib/spec/monkey_patches/publicize_methods.rb
dev/provisioning/modules/stdlib/spec/puppetlabs_spec_helper_clone.rb
dev/provisioning/modules/stdlib/spec/spec.opts
dev/provisioning/modules/stdlib/spec/spec_helper.rb
dev/provisioning/modules/stdlib/spec/spec_helper_acceptance.rb
dev/provisioning/modules/stdlib/spec/unit/facter/facter_dot_d_spec.rb
dev/provisioning/modules/stdlib/spec/unit/facter/pe_version_spec.rb
dev/provisioning/modules/stdlib/spec/unit/facter/root_home_spec.rb
dev/provisioning/modules/stdlib/spec/unit/facter/util/puppet_settings_spec.rb
dev/provisioning/modules/stdlib/spec/unit/puppet/provider/file_line/ruby_spec.rb
dev/provisioning/modules/stdlib/spec/unit/puppet/type/anchor_spec.rb
dev/provisioning/modules/stdlib/spec/unit/puppet/type/file_line_spec.rb
dev/provisioning/modules/sysconfig/files/httpd/httpd.conf
dev/provisioning/modules/sysconfig/files/httpd/welcome.conf
dev/provisioning/modules/sysconfig/files/memcached_socket_dir.conf
dev/provisioning/modules/sysconfig/files/phpinfo.php
dev/provisioning/modules/sysconfig/files/sesame/console_commands.txt
dev/provisioning/modules/sysconfig/files/sesame/lexvo_2013-02-09_cleaned.rdf.bz2
dev/provisioning/modules/sysconfig/lib/puppet/parser/functions/memcached_max_memory.rb
dev/provisioning/modules/sysconfig/manifests/apache.pp
dev/provisioning/modules/sysconfig/manifests/corpus.pp
dev/provisioning/modules/sysconfig/manifests/elasticsearch.pp
dev/provisioning/modules/sysconfig/manifests/init.pp
dev/provisioning/modules/sysconfig/manifests/mariadb.pp
dev/provisioning/modules/sysconfig/manifests/memcached.pp
dev/provisioning/modules/sysconfig/manifests/packages.pp
dev/provisioning/modules/sysconfig/manifests/params.pp
dev/provisioning/modules/sysconfig/manifests/php.pp
dev/provisioning/modules/sysconfig/manifests/sesame.pp
dev/provisioning/modules/sysconfig/manifests/sys_upgrade.pp
dev/provisioning/modules/sysconfig/manifests/tomcat.pp
dev/provisioning/modules/sysconfig/templates/corpus/corpus_env.conf.erb
dev/provisioning/modules/sysconfig/templates/corpus/local.env.erb
dev/provisioning/modules/sysconfig/templates/httpd/vhost.conf.erb
dev/provisioning/modules/yum/CHANGELOG.md
dev/provisioning/modules/yum/LICENSE
dev/provisioning/modules/yum/README.md
dev/provisioning/modules/yum/checksums.json
dev/provisioning/modules/yum/manifests/config.pp
dev/provisioning/modules/yum/manifests/gpgkey.pp
dev/provisioning/modules/yum/manifests/group.pp
dev/provisioning/modules/yum/manifests/init.pp
dev/provisioning/modules/yum/manifests/params.pp
dev/provisioning/modules/yum/manifests/plugin.pp
dev/provisioning/modules/yum/manifests/plugin/versionlock.pp
dev/provisioning/modules/yum/manifests/versionlock.pp
dev/provisioning/modules/yum/metadata.json
dev/provisioning/modules/yum/tests/gpgkey.pp
dev/provisioning/modules/yum/tests/group.pp
dev/provisioning/modules/yum/tests/plugin.pp
dev/provisioning/modules/yum/tests/versionlock.pp
dev/provisioning/playbook.yml
readme.md
server/bo_client/.ember-cli
server/bo_client/app/adapters/application.js
server/bo_client/app/components/bo-doc-contributors.js
server/bo_client/app/index.html
server/bo_client/app/initializers/constants.js
server/bo_client/app/initializers/options.js
server/bo_client/app/instance-initializers/i18n.js
server/bo_client/app/locales/en/translations.js
server/bo_client/app/locales/fr/translations.js
server/bo_client/app/mixins/cell-editing-mixin.js
server/bo_client/app/mixins/click-outside-mixin.js
server/bo_client/app/models/document.js
server/bo_client/app/pods/components/bo-doc-contributor-list-item/component.js
server/bo_client/app/pods/components/bo-doc-contributor-list-item/template.hbs
server/bo_client/app/pods/components/bo-doc-contributor-nameurl-cell/component.js
server/bo_client/app/pods/components/bo-doc-contributor-nameurl-cell/styles.scss
server/bo_client/app/pods/components/bo-doc-contributor-nameurl-cell/template.hbs
server/bo_client/app/pods/components/bo-doc-contributor-role-cell/component.js
server/bo_client/app/pods/components/bo-doc-contributor-role-cell/template.hbs
server/bo_client/app/pods/components/bo-doc-contributor-role-select/component.js
server/bo_client/app/pods/components/bo-doc-contributor-role-select/template.hbs
server/bo_client/app/pods/components/bo-doc-contributor-row/component.js
server/bo_client/app/pods/components/bo-doc-contributor-row/styles.scss
server/bo_client/app/pods/components/bo-doc-contributor-row/template.hbs
server/bo_client/app/pods/components/bo-doc-contributors/component.js
server/bo_client/app/pods/components/bo-doc-contributors/template.hbs
server/bo_client/app/pods/components/bo-doc-language/component.js
server/bo_client/app/pods/components/bo-doc-language/template.hbs
server/bo_client/app/pods/components/bo-doc-new-contributor/component.js
server/bo_client/app/pods/components/bo-doc-new-contributor/template.hbs
server/bo_client/app/pods/components/bo-doc-viaf-autocomplete/component.js
server/bo_client/app/pods/components/bo-doc-viaf-autocomplete/template.hbs
server/bo_client/app/pods/components/bo-doc-viaf-autocomplete/template.hbs.old
server/bo_client/app/routes/doc.js
server/bo_client/app/routes/index.js
server/bo_client/app/services/constants.js
server/bo_client/app/services/lexvo-resolver.js
server/bo_client/app/services/viaf-resolver.js
server/bo_client/app/styles/_icons.scss
server/bo_client/app/styles/app.scss
server/bo_client/app/templates/components/bo-doc-contributors.hbs
server/bo_client/app/templates/components/bo-doc-viaf-autocomplete/suggestion.hbs
server/bo_client/app/templates/doc.hbs
server/bo_client/bower.json
server/bo_client/config/environment.js
server/bo_client/ember-cli-build.js
server/bo_client/package.json
server/bo_client/public/assets/css/fonts.css
server/bo_client/public/assets/fonts/Roboto-300/LICENSE.txt
server/bo_client/public/assets/fonts/Roboto-300/Roboto-300.eot
server/bo_client/public/assets/fonts/Roboto-300/Roboto-300.svg
server/bo_client/public/assets/fonts/Roboto-300/Roboto-300.ttf
server/bo_client/public/assets/fonts/Roboto-300/Roboto-300.woff
server/bo_client/public/assets/fonts/Roboto-300/Roboto-300.woff2
server/bo_client/public/assets/fonts/Roboto-regular/LICENSE.txt
server/bo_client/public/assets/fonts/Roboto-regular/Roboto-regular.eot
server/bo_client/public/assets/fonts/Roboto-regular/Roboto-regular.svg
server/bo_client/public/assets/fonts/Roboto-regular/Roboto-regular.ttf
server/bo_client/public/assets/fonts/Roboto-regular/Roboto-regular.woff
server/bo_client/public/assets/fonts/Roboto-regular/Roboto-regular.woff2
server/bo_client/public/assets/img/viaf-logo-32x32.gif
server/bo_client/public/assets/img/viaf-logo-64x64.gif
server/bo_client/server/index.js
server/bo_client/server/mocks/documents.js
server/bo_client/server/mocks/lexvo.js
server/bo_client/server/mocks/viaf.js
server/bo_client/tests/integration/components/bo-doc-contributors-test.js
server/bo_client/tests/integration/pods/components/bo-doc-contributor-editpanel/component-test.js
server/bo_client/tests/integration/pods/components/bo-doc-contributor-list-item/component-test.js
server/bo_client/tests/integration/pods/components/bo-doc-contributor-nameurl-cell/component-test.js
server/bo_client/tests/integration/pods/components/bo-doc-contributor-role-cell/component-test.js
server/bo_client/tests/integration/pods/components/bo-doc-contributor-role-select/component-test.js
server/bo_client/tests/integration/pods/components/bo-doc-contributor-row/component-test.js
server/bo_client/tests/integration/pods/components/bo-doc-contributors/component-test.js
server/bo_client/tests/integration/pods/components/bo-doc-language/component-test.js
server/bo_client/tests/integration/pods/components/bo-doc-new-contributor/component-test.js
server/bo_client/tests/integration/pods/components/bo-doc-viaf-autocomplete/component-test.js
server/bo_client/tests/unit/initializers/constants-test.js
server/bo_client/tests/unit/initializers/options-test.js
server/bo_client/tests/unit/mixins/cell-editing-test.js
server/bo_client/tests/unit/mixins/click-outside-mixin-test.js
server/bo_client/tests/unit/services/constants-test.js
server/bo_client/tests/unit/services/lexvo-resolver-test.js
server/bo_client/tests/unit/services/viaf-resolver-test.js
server/bo_client/vendor/shims/store.js
server/bo_client/vendor/shims/urijs.js
server/src/.env.example
server/src/app/Http/Controllers/Api/DocumentController.php
server/src/app/Http/Controllers/Api/LexvoController.php
server/src/app/Http/Controllers/Bo/DocumentListController.php
server/src/app/Http/Middleware/VerifyCsrfToken.php
server/src/app/Http/routes.php
server/src/app/Libraries/Mergers/JsonDocumentMerger.php
server/src/app/Libraries/RdfModel/RdfModelResource.php
server/src/app/Libraries/Sparql/SparqlClient.php
server/src/app/Models/Document.php
server/src/app/Providers/LexvoServiceProvider.php
server/src/app/Providers/VersionServiceProvider.php
server/src/app/Repositories/RdfDocumentRepository.php
server/src/app/Services/LexvoResolver.php
server/src/app/Services/LexvoResolverException.php
server/src/app/Services/LexvoResolverInterface.php
server/src/app/Services/Version.php
server/src/config/app.php
server/src/config/corpusparole.php
server/src/config/version.php
server/src/gulpfile.js
server/src/public/css/app.css
server/src/resources/assets/sass/_app-core.scss
server/src/resources/views/app.blade.php
server/src/resources/views/bo/docDetailClient.blade.php
server/src/resources/views/bo/docList.blade.php
server/src/tests/Models/DocumentTest.php
server/src/tests/Repositories/DocumentRepositoryIntegrationTest.php
server/src/tests/Repositories/DocumentRepositoryTest.php
server/src/tests/Services/LexvoResolverTest.php
server/src/tests/Services/ViafResolverTest.php
--- a/.hgignore	Fri Jan 15 15:27:56 2016 +0100
+++ b/.hgignore	Fri Jan 15 15:35:00 2016 +0100
@@ -1,6 +1,8 @@
 syntax: regexp
+^dev2
 ^dev/\.vagrant
 ^dev/corpus-dev.box$
+^dev/.*\.rpm
 ^server/data
 ^server/src/\.git.*
 ^server/src/\.env
@@ -37,5 +39,8 @@
 ^cms/app-client/tmp
 ^cms/corpus_module/app-client
 ^.*\.DS_Store
+^build/\.vagrant
+^build/root
+^build/.*\.rpm
 ^dev2/
 ^build/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/Vagrantfile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,82 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+# All Vagrant configuration is done below. The "2" in Vagrant.configure
+# configures the configuration version (we support older styles for
+# backwards compatibility). Please don't change it unless you know what
+# you're doing.
+Vagrant.configure(2) do |config|
+  # The most common configuration options are documented and commented below.
+  # For a complete reference, please see the online documentation at
+  # https://docs.vagrantup.com.
+
+  # Every Vagrant development environment requires a box. You can search for
+  # boxes at https://atlas.hashicorp.com/search.
+  config.vm.box = "puppetlabs/centos-7.0-64-nocm"
+  #config.vm.box = "centos/7"
+
+  # Disable automatic box update checking. If you disable this, then
+  # boxes will only be checked for updates when the user runs
+  # `vagrant box outdated`. This is not recommended.
+  # config.vm.box_check_update = false
+
+  # Create a forwarded port mapping which allows access to a specific port
+  # within the machine from a port on the host machine. In the example below,
+  # accessing "localhost:8080" will access port 80 on the guest machine.
+  # config.vm.network "forwarded_port", guest: 80, host: 8080
+
+  # Create a private network, which allows host-only access to the machine
+  # using a specific IP.
+  # config.vm.network "private_network", ip: "192.168.33.10"
+
+  # Create a public network, which generally matched to bridged network.
+  # Bridged networks make the machine appear as another physical device on
+  # your network.
+  # config.vm.network "public_network"
+
+  # Share an additional folder to the guest VM. The first argument is
+  # the path on the host to the actual folder. The second argument is
+  # the path on the guest to mount the folder. And the optional third
+  # argument is a set of non-required options.
+  # config.vm.synced_folder "../data", "/vagrant_data"
+  #config.vm.synced_folder ".", "/home/vagrant/sync", disabled: true
+  #config.vm.synced_folder ".", "/vagrant"
+
+  # Provider-specific configuration so you can fine-tune various
+  # backing providers for Vagrant. These expose provider-specific options.
+  # Example for VirtualBox:
+  #
+  # config.vm.provider "virtualbox" do |vb|
+  #   # Display the VirtualBox GUI when booting the machine
+  #   vb.gui = true
+  #
+  #   # Customize the amount of memory on the VM:
+  #   vb.memory = "1024"
+  # end
+  #
+  # View the documentation for the provider you are using for more
+  # information on available options.
+
+  # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies
+  # such as FTP and Heroku are also available. See the documentation at
+  # https://docs.vagrantup.com/v2/push/atlas.html for more information.
+  # config.push.define "atlas" do |push|
+  #   push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME"
+  # end
+
+  # Enable provisioning with a shell script. Additional provisioners such as
+  # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
+  # documentation for more information about their specific syntax and use.
+  config.vm.provision "shell", inline: <<-SHELL
+    sed -i '/Subsystem sftp \\/usr\\/lib\\/openssh\\/sftp-server/c\\Subsystem sftp internal-sftp' /etc/ssh/sshd_config
+    systemctl restart sshd
+  SHELL
+
+  config.vm.provision "ansible" do |ansible|
+    ansible.playbook = "provisioning/playbook.yml"
+    ansible.extra_vars = {
+    }
+    ansible.sudo = true
+    #ansible.verbose = 'vvvv'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/build_rpm.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+
+pushd /vagrant/root/var/www/corpusdelaparole/corpus/
+echo "---> Launching composer"
+php composer.phar install --ignore-platform-reqs -o
+echo "---> Composer done"
+popd
+
+pushd /vagrant
+echo "---> Launching packaging"
+rm -f *.rpm
+#TODO: read version from corpus
+version=$(grep -oP "\'version\'\s*=>\s*\'\K[\.0-9]+(?=\')" /vagrant/root/var/www/corpusdelaparole/corpus/config/version.php)
+version=${version:-0.0.0}
+
+fpm \
+    --verbose \
+    -a all \
+    -s dir \
+    -t rpm \
+    -C /vagrant/root \
+    -d httpd \
+    -d php56 \
+    -d mariadb-server \
+    --name corpusdelaparole \
+    --version "$version" \
+    --iteration $(date +%s) \
+    --description "Corpus de la parole source rpm" \
+    --url "http://corpusdelaparole.huma-num.fr" \
+    --rpm-user apache \
+    --rpm-group apache \
+    --directories /var/www/corpusdelaparole \
+    --after-install /vagrant/post_install.sh \
+    --after-remove /vagrant/post_uninstall.sh \
+    --after-upgrade /vagrant/post_upgrade.sh \
+    .
+echo "---> Packaging done."
+popd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/post_install.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+
+/usr/bin/systemctl restart httpd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/post_uninstall.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+
+/usr/bin/systemctl restart httpd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/post_upgrade.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+
+/usr/bin/systemctl restart httpd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build/provisioning/playbook.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,133 @@
+---
+- hosts: all
+
+  vars:
+
+  tasks:
+
+#    - name: ensure correct locale LC_ALL
+#      lineinfile: dest=/etc/sysconfig/i18n regexp=^LC_ALL= line=LC_ALL="en_US.UTF-8"
+#    - name: ensure correct locale LANG
+#      lineinfile: dest=/etc/sysconfig/i18n regexp=^LANG= line=LANG="en_US.UTF-8"
+
+    # - name: set .bashrc
+    #   copy: src=files/.bashrc dest=/home/vagrant/.bashrc force=yes
+    # - name: set .profile
+    #   copy: src=files/.profile dest=/home/vagrant/.profile force=yes
+    - name: set hostname
+      hostname: name=corpus-build
+
+    - name: check yum base last update
+      stat: path=/var/cache/yum/x86_64/6/base/cachecookie
+      register: yum_cache_stat_base
+
+    - name: additional repos install
+      yum: name={{item}} state=latest enablerepo=extras
+      with_items:
+        - epel-release
+
+    # Remi yum repository.
+    - stat: path=/etc/yum.repos.d/remi.repo
+      register: remi_repo
+
+    - name: Download Remi repo.
+      get_url: url=http://rpms.famillecollet.com/enterprise/remi-release-6.rpm dest=/tmp/
+      when: remi_repo.stat.exists == False
+
+    - name: Install Remi repo.
+      command: rpm -Uvh --force /tmp/remi-release-6.rpm creates=/etc/yum.repos.d/remi.repo
+      when: remi_repo.stat.exists == False
+
+    - name : delete remi rpm
+      file: path=/tmp/remi-release-6.rpm state=absent
+
+    - name: additional repos install epel
+      ini_file:
+        dest: /etc/yum.repos.d/epel.repo
+        section: epel
+        option: enabled
+        value: 1
+
+    - name: yum update
+      yum: name=* update_cache=yes state=latest
+#      when: ansible_date_time.epoch|float - yum_cache_stat_base.stat.mtime > 60*60*12*24
+
+    - name: install packages
+      yum: name={{item}} state=latest enablerepo=remi
+      with_items:
+        - git-core
+        - zlib
+        - zlib-devel
+        - gcc-c++
+        - patch
+        - readline
+        - readline-devel
+        - libyaml-devel
+        - libffi-devel
+        - openssl-devel
+        - make
+        - bzip2
+        - autoconf
+        - automake
+        - libtool
+        - bison
+        - curl
+        - sqlite-devel
+        - rpm-build
+        - redhat-rpm-config
+        - php56
+        - php56-php-pdo
+        - php56-php-mbstring
+        - php56-php-mcrypt
+
+    - name: activate remi php scl
+      lineinfile: dest=/home/vagrant/.bash_profile regexp="^source \/opt\/remi\/php56\/enable$" line="source /opt/remi/php56/enable"
+
+    - stat: path=/home/vagrant/.rbenv
+      register: rbenv_stat
+
+    - name: clone rbenv github repo
+      git: repo=https://github.com/rbenv/rbenv.git dest=/home/vagrant/.rbenv
+      become: yes
+      become_user: vagrant
+      when: rbenv_stat.stat.exists == False
+
+    - name: configure rbenv
+      command: chdir=/home/vagrant/.rbenv {{ item }}
+      with_items:
+          - src/configure
+          - /usr/bin/make -C src
+      become: yes
+      become_user: vagrant
+      when: rbenv_stat.stat.exists == False
+
+    - name: add rbenv to path
+      lineinfile: dest=/home/vagrant/.bash_profile regexp="^PATH=" line="PATH=$PATH:$HOME/.local/bin:$HOME/bin:$HOME/.rbenv/bin"
+
+    - name: add rbenv init to profile
+      lineinfile: dest=/home/vagrant/.bash_profile regexp="^eval \"\$\(rbenv init \-\)\"$" line="eval \"$(rbenv init -)\""
+
+    - name: clone ruby-build github repo
+      git: repo=https://github.com/rbenv/ruby-build.git dest=/home/vagrant/.rbenv/plugins/ruby-build
+      become: yes
+      become_user: vagrant
+      when: rbenv_stat.stat.exists == False
+
+    - name: install ruby 2.3.0
+      command: chdir=/home/vagrant/.rbenv creates=/home/vagrant/.rbenv/versions/2.3.0 /home/vagrant/.rbenv/bin/rbenv install 2.3.0
+      become: yes
+      become_user: vagrant
+
+    - name: make ruby 2.3.0 global
+      command: chdir=/home/vagrant/.rbenv /home/vagrant/.rbenv/bin/rbenv global 2.3.0
+      become: yes
+      become_user: vagrant
+
+    - name: install fpm
+      shell: source ~/.bash_profile && gem install fpm
+      args:
+          chdir: /home/vagrant
+          executable: /usr/bin/bash
+          creates: /home/vagrant/.rbenv/shims/fpm
+      become: yes
+      become_user: vagrant
--- a/dev/Vagrantfile	Fri Jan 15 15:27:56 2016 +0100
+++ b/dev/Vagrantfile	Fri Jan 15 15:35:00 2016 +0100
@@ -1,13 +1,11 @@
 # -*- mode: ruby -*-
 # vi: set ft=ruby :
-
 require 'yaml'
 
 custom_file_path = File.join(__dir__, (ENV['SYSCONFIG'] || 'custom.yaml'))
 
 context = (File.exist?(custom_file_path)?YAML::load_file(custom_file_path):{}) || {}
 
-
 # All Vagrant configuration is done below. The "2" in Vagrant.configure
 # configures the configuration version (we support older styles for
 # backwards compatibility). Please don't change it unless you know what
@@ -19,19 +17,23 @@
 
   # Every Vagrant development environment requires a box. You can search for
   # boxes at https://atlas.hashicorp.com/search.
-  config.vm.box = "puppetlabs/centos-6.6-64-nocm"
+  #config.vm.box = "centos/7"
+  config.vm.box = "puppetlabs/centos-7.0-64-nocm"
 
   # Disable automatic box update checking. If you disable this, then
   # boxes will only be checked for updates when the user runs
   # `vagrant box outdated`. This is not recommended.
   # config.vm.box_check_update = false
 
+  # Create a private network, which allows host-only access to the machine
+  # using a specific IP.
+  # config.vm.network "private_network", ip: "192.168.33.10"
+  config.vm.network :private_network, ip: (ENV['VM_IP'] || context['vm_ip'] || "172.16.1.6")
+
   # Create a forwarded port mapping which allows access to a specific port
   # within the machine from a port on the host machine. In the example below,
   # accessing "localhost:8080" will access port 80 on the guest machine.
   # config.vm.network "forwarded_port", guest: 80, host: 8080
-  config.vm.network :private_network, ip: (ENV['VM_IP'] || context['vm_ip'] || "172.16.1.5")
-
   default_ports = {
     80   => 40000,
     443  => 44300,
@@ -45,11 +47,6 @@
     config.vm.network "forwarded_port", guest: guest, host: host
   end
 
-
-  # Create a private network, which allows host-only access to the machine
-  # using a specific IP.
-  # config.vm.network "private_network", ip: "192.168.33.10"
-
   # Create a public network, which generally matched to bridged network.
   # Bridged networks make the machine appear as another physical device on
   # your network.
@@ -59,10 +56,12 @@
   # the path on the host to the actual folder. The second argument is
   # the path on the guest to mount the folder. And the optional third
   # argument is a set of non-required options.
-  config.vm.synced_folder "../server", "/code", id: "code-root",
-    owner: "vagrant",
-    group: 498,
-    mount_options: ["dmode=775,fmode=664"]
+  # config.vm.synced_folder "../data", "/vagrant_data"
+  # config.vm.synced_folder "../server/src", "/var/www/corpus", id: "code-root",
+  #   owner: "vagrant",
+  #   group: 498,
+  #   mount_options: ["dmode=775,fmode=664"]
+
 
   # Provider-specific configuration so you can fine-tune various
   # backing providers for Vagrant. These expose provider-specific options.
@@ -75,12 +74,12 @@
   #   # Customize the amount of memory on the VM:
   #   vb.memory = "1024"
   # end
-  #
   config.vm.provider "virtualbox" do |v|
     v.memory = 1024
     v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
   end
 
+  #
   # View the documentation for the provider you are using for more
   # information on available options.
 
@@ -98,17 +97,25 @@
   #   sudo apt-get update
   #   sudo apt-get install -y apache2
   # SHELL
-
   config.vm.provision :shell do |shell|
-    shell.inline = "getent group nginx || groupadd -g 498 nginx;"
+    #initialize puppet
+    shell.name = "puppet_initialize"
+    shell.path = "provisioning/bootstrap-puppet.sh"
   end
 
-  config.vm.provision "ansible" do |ansible|
-    ansible.playbook = "provisioning/playbook.yml"
-    ansible.extra_vars = {
-        site_name: "corpus-parole.local"
-    }
-    ansible.sudo = true
+  config.vm.provision :shell do |shell|
+    #initialize puppet
+    shell.name = "system_initialize"
+    shell.inline = "[ ! -d '/tmp/vagrant-puppet' ] && mkdir -p '/tmp/vagrant-puppet' || :;"
+  end
+
+  config.vm.provision :puppet do |puppet|
+      puppet.manifests_path = "provisioning"
+      puppet.manifest_file = "default.pp"
+      puppet.module_path = "provisioning/modules"
+      puppet.hiera_config_path = "provisioning/hiera.yaml"
+      puppet.working_directory = "/vagrant/provisioning/"
+      puppet.options = "--verbose --debug"
   end
 
 end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/bootstrap-puppet.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+# This bootstraps Puppet on CentOS 7.x
+# It has been tested on CentOS 7.0 64bit
+
+set -e
+
+REPO_URL="http://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm"
+
+if [ "$EUID" -ne "0" ]; then
+  echo "This script must be run as root." >&2
+  exit 1
+fi
+
+if which puppet > /dev/null 2>&1; then
+  echo "Puppet is already installed."
+  exit 0
+fi
+
+# Install wget
+echo "Installing wget..."
+yum install -y wget > /dev/null
+
+
+# Install puppet labs repo
+echo "Configuring PuppetLabs repo..."
+repo_path=$(mktemp)
+wget --output-document="${repo_path}" "${REPO_URL}" 2>/dev/null
+rpm -i "${repo_path}" >/dev/null
+
+# Install Puppet...
+echo "Installing puppet"
+yum install -y puppet > /dev/null
+
+echo "Puppet installed!"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/custom.yaml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+---
+sysconfig::params::vhost : "int.corpusdelaparole.huma-num.fr"
+
+sysconfig::params::db_name : corpus
+sysconfig::params::db_drpl_name : corpusdelaparole
+sysconfig::params::db_user : corpus
+sysconfig::params::db_pw   : corpus@mariadb
+sysconfig::params::db_host : 127.0.0.1
+sysconfig::params::db_port : 3306
+
+sysconfig::params::es_host     : 127.0.0.1
+sysconfig::params::es_port     : 9200
+sysconfig::params::es_instance : "es_01"
+
+sysconfig::params::tomcat_open_port : true
+
+sysconfig::params::corpus_app_key : "v6kgofcM4mCqon7ioz9NKSjeug5wiKt6"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/custom.yaml.tmpl	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+---
+# Serveur hostname (ex: the first ip of the server : %{ipaddress_eth0})
+sysconfig::params::vhost : "int.corpusdelaparole.huma-num.fr"
+
+# database name
+sysconfig::params::db_name : corpus
+# Drupal database name
+sysconfig::params::db_drpl_name : corpusdelaparole
+# database user
+sysconfig::params::db_user : corpus
+# database password
+sysconfig::params::db_pw   : corpus_pw_custom
+# database server host (ip or domain)
+sysconfig::params::db_host : 127.0.0.1
+# database server port
+sysconfig::params::db_port : 3306
+
+# elasticsearch host
+sysconfig::params::es_host     : 127.0.0.1
+# elasticsearch port
+sysconfig::params::es_port     : 9200
+# elasticsearch instamce
+sysconfig::params::es_instance : es_01
+
+# memory percentage used by memcached
+sysconfig::params::memcached_max_memory : 25%
+
+# open tomcat port
+sysconfig::params::tomcat_open_port : false
+
+# corpus application key 32 character random string (Array.new(32){"abcdefghijklmnopqrstuvwxyz0123456789!@#\$%^&*(-_=+)".split("").sample}.join )
+sysconfig::params::corpus_app_key :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/default.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+include sysconfig
+
+# params
+class { 'sysconfig::params': } ->
+
+# upgrade system
+class { 'sysconfig::sys_upgrade': }->
+
+# install mariadb
+class { 'sysconfig::mariadb': }->
+
+# install packages
+class { 'sysconfig::packages': }->
+
+# install apache
+class { 'sysconfig::apache': }
+
+# install php
+class { 'sysconfig::php': }
+
+# install tomcat
+class { 'sysconfig::tomcat': }
+
+# install sesame
+class { 'sysconfig::sesame': }->
+
+# install elasticsearch
+class { 'sysconfig::elasticsearch': }->
+
+# install memcached
+class { 'sysconfig::memcached': }->
+
+# install corpus
+class { 'sysconfig::corpus': }->
+
+# mark first provision
+file { "/var/lib/puppet/state/first_run":
+    ensure => present
+}
--- a/dev/provisioning/files/.bashrc	Fri Jan 15 15:27:56 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-# ~/.bashrc: executed by bash(1) for non-login shells.
-# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
-# for examples
-
-# Source global definitions
-if [ -f /etc/bashrc ]; then
-        . /etc/bashrc
-fi
-
-# If not running interactively, don't do anything
-# [ -z "$PS1" ] && return
-case $- in
-    *i*) ;;
-      *) return;;
-esac
-
-# don't put duplicate lines or lines starting with space in the history.
-# See bash(1) for more options
-HISTCONTROL=ignoreboth
-
-# append to the history file, don't overwrite it
-shopt -s histappend
-
-# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
-HISTSIZE=10000
-HISTFILESIZE=100000000
-
-# avoid losing history
-PROMPT_COMMAND="history -a"
-export HISTSIZE PROMPT_COMMAND
-
-TERM=xterm-256color
-
-# check the window size after each command and, if necessary,
-# update the values of LINES and COLUMNS.
-shopt -s checkwinsize
-
-# If set, the pattern "**" used in a pathname expansion context will
-# match all files and zero or more directories and subdirectories.
-#shopt -s globstar
-
-# make less more friendly for non-text input files, see lesspipe(1)
-[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
-
-# set a fancy prompt (non-color, unless we know we "want" color)
-case "$TERM" in
-    xterm-256color) color_prompt=yes;;
-esac
-
-# uncomment for a colored prompt, if the terminal has the capability; turned
-# off by default to not distract the user: the focus in a terminal window
-# should be on the output of commands, not on the prompt
-# force_color_prompt=yes
-
-if [ -n "$force_color_prompt" ]; then
-    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
-	# We have color support; assume it's compliant with Ecma-48
-	# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
-	# a case would tend to support setf rather than setaf.)
-	color_prompt=yes
-    else
-	color_prompt=
-    fi
-fi
-
-if [ "$color_prompt" = yes ]; then
-    # PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
-    PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
-else
-    # PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
-    PS1='\u@\h:\w\$ '
-fi
-unset color_prompt force_color_prompt
-
-# If this is an xterm set the title to user@host:dir
-case "$TERM" in
-xterm*|rxvt*)
-    # Do it ONLY when connecting via pts BUT NOT tty
-    # pts - ssh or terminal emulators like konsole or gnome-terminal
-    # otherwise it'll mess up the Bash prompt PS1
-    mytty=$(tty)
-    if [[ ${mytty:5:3} = "pts" ]]; then
-        PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
-        # PS1="\[\e]0;\u@\h: \w\a\]$PS1"
-    fi
-    ;;
-*)
-    ;;
-esac
-
-# enable color support of ls and also add handy aliases
-if [ -x /usr/bin/dircolors ]; then
-    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
-    alias ls='ls --color=auto'
-    #alias dir='dir --color=auto'
-    #alias vdir='vdir --color=auto'
-
-    alias grep='grep --color=auto'
-    alias fgrep='fgrep --color=auto'
-    alias egrep='egrep --color=auto'
-fi
-
-# color for man pages
-man() {
-    env LESS_TERMCAP_mb=$(printf "\e[1;31m") \
-        LESS_TERMCAP_md=$(printf "\e[1;31m") \
-        LESS_TERMCAP_me=$(printf "\e[0m") \
-        LESS_TERMCAP_se=$(printf "\e[0m") \
-        LESS_TERMCAP_so=$(printf "\e[1;44;33m") \
-        LESS_TERMCAP_ue=$(printf "\e[0m") \
-        LESS_TERMCAP_us=$(printf "\e[1;32m") \
-        man "$@"
-}
-
-# some more ls aliases
-alias ll='ls -alF'
-alias la='ls -A'
-alias l='ls -CF'
-
-# Add an "alert" alias for long running commands.
-# Use like so: sleep 10; alert
-alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
-
-# Alias definitions.
-# You may want to put all your additions into a separate file like
-# ~/.bash_aliases, instead of adding them here directly.
-# See /usr/share/doc/bash-doc/examples in the bash-doc package.
-
-if [ -f ~/.bash_aliases ]; then
-    . ~/.bash_aliases
-fi
-
-# enable programmable completion features (you don't need to enable
-# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
-# sources /etc/bash.bashrc).
-# if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
-#     . /etc/bash_completion
-# fi
-
-if ! shopt -oq posix; then
-    if [ -f /usr/share/bash-completion/bash_completion ]; then
-        . /usr/share/bash-completion/bash_completion
-    elif [ -f /etc/bash_completion ]; then
-        . /etc/bash_completion
-    fi
-fi
-
-
-#activate remi php56 scl
-source /opt/remi/php56/enable
--- a/dev/provisioning/files/.profile	Fri Jan 15 15:27:56 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-# ~/.profile: executed by the command interpreter for login shells.
-# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
-# exists.
-# see /usr/share/doc/bash/examples/startup-files for examples.
-# the files are located in the bash-doc package.
-
-# the default umask is set in /etc/profile; for setting the umask
-# for ssh logins, install and configure the libpam-umask package.
-umask 027
-
-# if running bash
-if [ -n "$BASH_VERSION" ]; then
-    # include .bashrc if it exists
-    if [ -f "$HOME/.bashrc" ]; then
-        . "$HOME/.bashrc"
-    fi
-fi
-
-# set PATH so it includes user's private bin if it exists
-if [ -d "$HOME/bin" ]; then
-    PATH="$HOME/bin:$PATH"
-fi
--- a/dev/provisioning/files/site.j2	Fri Jan 15 15:27:56 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-#user  nobody;
-worker_processes  1;
-
-#error_log  logs/error.log;
-#error_log  logs/error.log  notice;
-#error_log  logs/error.log  info;
-
-#pid        logs/nginx.pid;
-
-events {
-    worker_connections  1024;
-}
-
-http {
-
-    include       mime.types;
-    default_type  application/octet-stream;
-
-    server {
-        listen 80;
-        server_name {{ site_name }};
-        root /code/src/public;
-
-        index index.html index.htm index.php;
-
-        charset utf-8;
-
-        location / {
-            try_files $uri $uri/ /index.php?$query_string;
-        }
-
-        location = /favicon.ico { access_log off; log_not_found off; }
-        location = /robots.txt  { access_log off; log_not_found off; }
-
-        access_log off;
-        error_log  /var/log/nginx/{{ site_name }}-error.log error;
-
-        sendfile off;
-
-        client_max_body_size 100m;
-
-        location ~ \.php$ {
-            fastcgi_split_path_info ^(.+\.php)(/.+)$;
-            fastcgi_pass unix:/opt/remi/php56/root/var/run/php-fpm/php-fpm.sock;
-            fastcgi_index index.php;
-            include fastcgi_params;
-            fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
-            fastcgi_param PATH_TRANSLATED $document_root/$fastcgi_script_name;
-            fastcgi_intercept_errors off;
-            fastcgi_buffer_size 16k;
-            fastcgi_buffers 4 16k;
-        }
-
-        location ~ /\.ht {
-            deny all;
-        }
-    }
-    server {
-        listen 443;
-        server_name {{ site_name }};
-        root /code/src/public;
-
-        index index.html index.htm index.php;
-
-        charset utf-8;
-
-        location / {
-            try_files $uri $uri/ /index.php?$query_string;
-        }
-
-        location = /favicon.ico { access_log off; log_not_found off; }
-        location = /robots.txt  { access_log off; log_not_found off; }
-
-        access_log off;
-        error_log  /var/log/nginx/{{ site_name }}-ssl-error.log error;
-
-        sendfile off;
-
-        client_max_body_size 100m;
-
-        location ~ \.php$ {
-            fastcgi_split_path_info ^(.+\.php)(/.+)$;
-            fastcgi_pass unix:/opt/remi/php56/root/var/run/php-fpm/php-fpm.sock;
-            fastcgi_index index.php;
-            include fastcgi_params;
-            fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
-            fastcgi_param PATH_TRANSLATED $document_root/$fastcgi_script_name;
-            fastcgi_intercept_errors off;
-            fastcgi_buffer_size 16k;
-            fastcgi_buffers 4 16k;
-        }
-
-        location ~ /\.ht {
-            deny all;
-        }
-
-        ssl on;
-        ssl_certificate     /etc/nginx/ssl/{{ site_name }}.crt;
-        ssl_certificate_key /etc/nginx/ssl/{{ site_name }}.key;
-    }
-
-}
--- a/dev/provisioning/files/sysconfig_php-fpm	Fri Jan 15 15:27:56 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-# Additional environment file for php-fpm
-
-if [ ! -d /var/run/php-fpm ]; then
-    mkdir -p /var/run/php-fpm
-fi
-
-chown nginx:nginx /var/run/php-fpm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/hiera.yaml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+---
+:hierarchy:
+  - custom
+:backends:
+  - yaml
+:yaml:
+  :datadir: "."
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/CHANGELOG.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,595 @@
+## Supported Release 1.7.1
+###Summary
+
+Small release for support of newer PE versions. This increments the version of PE in the metadata.json file.
+
+## 2015-11-17 - Supported Release 1.7.0
+### Summary
+This release includes many new features and bugfixes. There are test, documentation and misc improvements.
+
+#### Features
+- allow groups with - like vhost-users 
+- ability to enable/disable the secruleengine through a parameter
+- add mod_auth_kerb parameters to vhost
+- client auth for reverse proxy
+- support for mod_auth_mellon
+- change SSLProtocol in apache::vhost to be space separated
+- RewriteLock support
+
+#### Bugfixes
+- fix apache::mod::cgid so it can be used with the event MPM 
+- load unixd before fcgid on all operating systems
+- fixes conditional in vhost aliases
+- corrects mod_cgid worker/event defaults
+- ProxyPassMatch parameters were ending up on a newline
+- catch that mod_authz_default has been removed in Apache 2.4
+- mod::ssl fails on SLES
+- fix typo of MPM_PREFORK for FreeBSD package install 
+- install all modules before adding custom configs
+- fix acceptance testing for SSLProtocol behaviour for real
+- fix ordering issue with conf_file and ports_file 
+
+#### Known Issues
+- mod_passenger is having issues installing on Redhat/Centos 6, This is due to package dependency issues.
+
+#### Improvements
+- added docs for forcetype directive
+- removes ruby 1.8.7 from the travisci test matrix
+- readme reorganisation, minor fixups
+- support the mod_proxy ProxyPassReverseCookiePath directive
+- the purge_vhost_configs parameter is actually called purge_vhost_dir
+- add ListenBacklog for mod worker
+- deflate application/json by default 
+- install mod_authn_alias as default mod in debian for apache < 2.4
+- optionally set LimitRequestFieldSize on an apache::vhost
+- add SecUploadDir parameter to support file uploads with mod_security
+- optionally set parameters for mod_ext_filter module
+- allow SetOutputFilter to be set on a directory
+- RC4 is deprecated
+- allow empty docroot
+- add option to configure the include pattern for the vhost_enable dir
+- allow multiple IP addresses per vhost
+- default document root update for Ubuntu 14.04 and Debian 8 
+
+## 2015-07-28 - Supported Release 1.6.0
+### Summary
+This release includes a couple of new features, along with test and documentation updates, and support for the latest AIO puppet builds.
+
+#### Features
+- Add `scan_proxy_header_field` parameter to `apache::mod::geoip`
+- Add `ssl_openssl_conf_cmd` parameter to `apache::vhost` and `apache::mod::ssl`
+- Add `filters` parameter to `apache::vhost`
+
+#### Bugfixes
+- Test updates
+- Do not use systemd on Amazon Linux
+- Add missing docs for `timeout` parameter (MODULES-2148)
+
+## 2015-06-11 - Supported Release 1.5.0
+### Summary
+This release primarily adds Suse compatibility. It also adds a handful of other
+parameters for greater configuration control.
+
+#### Features
+- Add `apache::lib_path` parameter
+- Add `apache::service_restart` parameter
+- Add `apache::vhost::geoip_enable` parameter
+- Add `apache::mod::geoip` class
+- Add `apache::mod::remoteip` class
+- Add parameters to `apache::mod::expires` class
+- Add `index_style_sheet` handling to `apache::vhost::directories`
+- Add some compatibility for SLES 11
+- Add `apache::mod::ssl::ssl_sessioncachetimeout` parameter
+- Add `apache::mod::ssl::ssl_cryptodevice` parameter
+- Add `apache::mod::ssl::ssl_honorcipherorder` parameter
+- Add `apache::mod::userdir::options` parameter
+
+#### Bugfixes
+- Document `apache::user` parameter
+- Document `apache::group` parameter
+- Fix apache::dev on FreeBSD
+- Fix proxy\_connect on apache >= 2.2
+- Validate log levels better
+- Fix `apache::apache_name` for package and vhost
+- Fix Debian Jessie mod\_prefork package name
+- Fix alias module being declared even when vhost is absent
+- Fix proxy\_pass\_match handling in vhost's proxy template
+- Fix userdir access permissions
+- Fix issue where the module was trying to use systemd on Amazon Linux.
+
+## 2015-04-28 - Supported Release 1.4.1
+
+This release corrects a metadata issue that has been present since release 1.2.0. The refactoring of `apache::vhost` to use `puppetlabs-concat` requires a version of concat newer than the version required in PE. If you are using PE 3.3.0 or earlier you will need to use version 1.1.1 or earlier of the `puppetlabs-apache` module.
+
+## 2015-03-17 - Supported Release 1.4.0
+###Summary
+
+This release fixes the issue where the docroot was still managed even if the default vhosts were disabled and has many other features and bugfixes including improved support for 'deny' and 'require' as arrays in the 'directories' parameter under `apache::vhost`
+
+#### Features
+- New parameters to `apache`
+  - `default_charset`
+  - `default_type`
+- New parameters to `apache::vhost`
+  - `proxy_error_override`
+  - `passenger_app_env` (MODULES-1776)
+  - `proxy_dest_match`
+  - `proxy_dest_reverse_match`
+  - `proxy_pass_match`
+  - `no_proxy_uris_match`
+- New parameters to `apache::mod::passenger`
+  - `passenger_app_env`
+  - `passenger_min_instances`
+- New parameter to `apache::mod::alias`
+  - `icons_options`
+- New classes added under `apache::mod::*`
+  - `authn_file`
+  - `authz_default`
+  - `authz_user`
+- Added support for 'deny' as an array in 'directories' under `apache::vhost`
+- Added support for RewriteMap
+- Improved support for FreeBSD. (Note: If using apache < 2.4.12, see the discussion [here](https://github.com/puppetlabs/puppetlabs-apache/pull/1030))
+- Added check for deprecated options in directories and fail when they are unsupported
+- Added gentoo compatibility
+- Added proper array support for `require` in the `directories` parameter in `apache::vhost`
+- Added support for `setenv` inside proxy locations
+
+### Bugfixes
+- Fix issue in `apache::vhost` that was preventing the scriptalias fragment from being included (MODULES-1784)
+- Install required `mod_ldap` package for EL7 (MODULES-1779)
+- Change default value of `maxrequestworkers` in `apache::mod::event` to be a multiple of the default `ThreadsPerChild` of 25.
+- Use the correct `mod_prefork` package name for trusty and jessie
+- Don't manage docroot when default vhosts are disabled
+- Ensure resources notify `Class['Apache::Service']` instead of `Service['httpd']` (MODULES-1829)
+- Change the loadfile name for `mod_passenger` so `mod_proxy` will load by default before `mod_passenger`
+- Remove old Debian work-around that removed `passenger_extra.conf`
+
+## 2015-02-17 - Supported Release 1.3.0
+### Summary
+
+This release has many new features and bugfixes, including the ability to optionally not trigger service restarts on config changes.
+
+#### Features
+- New parameters - `apache`
+  - `service_manage`
+  - `use_optional_includes`
+- New parameters - `apache::service`
+  - `service_manage`
+- New parameters - `apache::vhost`
+  - `access_logs`
+  - `php_flags`
+  - `php_values`
+  - `modsec_disable_vhost`
+  - `modsec_disable_ids`
+  - `modsec_disable_ips`
+  - `modsec_body_limit`
+- Improved FreeBSD support
+- Add ability to omit priority prefix if `$priority` is set to false
+- Add `apache::security::rule_link` define
+- Improvements to `apache::mod::*`
+  - Add `apache::mod::auth_cas` class
+  - Add `threadlimit`, `listenbacklog`, `maxrequestworkers`, `maxconnectionsperchild` parameters to `apache::mod::event`
+  - Add `apache::mod::filter` class
+  - Add `root_group` to `apache::mod::php`
+  - Add `apache::mod::proxy_connect` class
+  - Add `apache::mod::security` class
+  - Add `ssl_pass_phrase_dialog` and `ssl_random_seed_bytes parameters to `apache::mod::ssl` (MODULES-1719)
+  - Add `status_path` parameter to `apache::mod::status`
+  - Add `apache_version` parameter to `apache::mod::version`
+  - Add `package_name` and `mod_path` parameters to `apache::mod::wsgi` (MODULES-1458)
+- Improved SCL support
+  - Add support for specifying the docroot
+- Updated `_directories.erb` to add support for SetEnv
+- Support multiple access log directives (MODULES-1382)
+- Add passenger support for Debian Jessie
+- Add support for not having puppet restart the apache service (MODULES-1559)
+
+#### Bugfixes
+- For apache 2.4 `mod_itk` requires `mod_prefork` (MODULES-825)
+- Allow SSLCACertificatePath to be unset in `apache::vhost` (MODULES-1457)
+- Load fcgid after unixd on RHEL7
+- Allow disabling default vhost for Apache 2.4
+- Test fixes
+- `mod_version` is now built-in (MODULES-1446)
+- Sort LogFormats for idempotency
+- `allow_encoded_slashes` was omitted from `apache::vhost`
+- Fix documentation bug (MODULES-1403, MODULES-1510)
+- Sort `wsgi_script_aliases` for idempotency (MODULES-1384)
+- lint fixes
+- Fix automatic version detection for Debian Jessie
+- Fix error docs and icons path for RHEL7-based systems (MODULES-1554)
+- Sort php_* hashes for idempotency (MODULES-1680)
+- Ensure `mod::setenvif` is included if needed (MODULES-1696)
+- Fix indentation in `vhost/_directories.erb` template (MODULES-1688)
+- Create symlinks on all distros if `vhost_enable_dir` is specified
+
+## 2014-09-30 - Supported Release 1.2.0
+### Summary
+
+This release features many improvements and bugfixes, including several new defines, a reworking of apache::vhost for more extensibility, and many new parameters for more customization. This release also includes improved support for strict variables and the future parser.
+
+#### Features
+- Convert apache::vhost to use concat for easier extensions
+- Test improvements
+- Synchronize files with modulesync
+- Strict variable and future parser support
+- Added apache::custom_config defined type to allow validation of configs before they are created
+- Added bool2httpd function to convert true/false to apache 'On' and 'Off'. Intended for internal use in the module.
+- Improved SCL support
+  - allow overriding of the mod_ssl package name
+- Add support for reverse_urls/ProxyPassReverse in apache::vhost
+- Add satisfy directive in apache::vhost::directories
+- Add apache::fastcgi::server defined type
+- New parameters - apache
+  - allow_encoded_slashes
+  - apache_name
+  - conf_dir
+  - default_ssl_crl_check
+  - docroot
+  - logroot_mode
+  - purge_vhost_dir
+- New parameters - apache::vhost
+  - add_default_charset
+  - allow_encoded_slashes
+  - logroot_ensure
+  - logroot_mode
+  - manage_docroot
+  - passenger_app_root
+  - passenger_min_instances
+  - passenger_pre_start
+  - passenger_ruby
+  - passenger_start_timeout
+  - proxy_preserve_host
+  - redirectmatch_dest
+  - ssl_crl_check
+  - wsgi_chunked_request
+  - wsgi_pass_authorization
+- Add support for ScriptAlias and ScriptAliasMatch in the apache::vhost::aliases parameter
+- Add support for rewrites in the apache::vhost::directories parameter
+- If the service_ensure parameter in apache::service is set to anything other than true, false, running, or stopped, ensure will not be passed to the service resource, allowing for the service to not be managed by puppet
+- Turn of SSLv3 by default
+- Improvements to apache::mod*
+  - Add restrict_access parameter to apache::mod::info
+  - Add force_language_priority and language_priority parameters to apache::mod::negotiation
+  - Add threadlimit parameter to apache::mod::worker
+  - Add content, template, and source parameters to apache::mod::php
+  - Add mod_authz_svn support via the authz_svn_enabled parameter in apache::mod::dav_svn
+  - Add loadfile_name parameter to apache::mod
+  - Add apache::mod::deflate class
+  - Add options parameter to apache::mod::fcgid
+  - Add timeouts parameter to apache::mod::reqtimeout
+  - Add apache::mod::shib
+  - Add apache_version parameter to apache::mod::ldap
+  - Add magic_file parameter to apache::mod::mime_magic
+  - Add apache_version parameter to apache::mod::pagespeed
+  - Add passenger_default_ruby parameter to apache::mod::passenger
+  - Add content, template, and source parameters to apache::mod::php
+  - Add apache_version parameter to apache::mod::proxy
+  - Add loadfiles parameter to apache::mod::proxy_html
+  - Add ssl_protocol and package_name parameters to apache::mod::ssl
+  - Add apache_version parameter to apache::mod::status
+  - Add apache_version parameter to apache::mod::userdir
+  - Add apache::mod::version class
+
+#### Bugfixes
+- Set osfamily defaults for wsgi_socket_prefix
+- Support multiple balancermembers with the same url
+- Validate apache::vhost::custom_fragment
+- Add support for itk with mod_php
+- Allow apache::vhost::ssl_certs_dir to not be set
+- Improved passenger support for Debian
+- Improved 2.4 support without mod_access_compat
+- Support for more than one 'Allow from'-directive in _directories.erb
+- Don't load systemd on Amazon linux based on CentOS6 with apache 2.4
+- Fix missing newline in ModPagespeed filter and memcached servers directive
+- Use interpolated strings instead of numbers where required by future parser
+- Make auth_require take precedence over default with apache 2.4
+- Lint fixes
+- Set default for php_admin_flags and php_admin_values to be empty hash instead of empty array
+- Correct typo in mod::pagespeed
+- spec_helper fixes
+- Install mod packages before dealing with the configuration
+- Use absolute scope to check class definition in apache::mod::php
+- Fix dependency loop in apache::vhost
+- Properly scope variables in the inline template in apache::balancer
+- Documentation clarification, typos, and formatting
+- Set apache::mod::ssl::ssl_mutex to default for debian on apache >= 2.4
+- Strict variables fixes
+- Add authn_core mode to Ubuntu trusty defaults
+- Keep default loadfile for authz_svn on Debian
+- Remove '.conf' from the site-include regexp for better Ubuntu/Debian support
+- Load unixd before fcgid for EL7
+- Fix RedirectMatch rules
+- Fix misleading error message in apache::version
+
+#### Known Bugs
+* By default, the version of Apache that ships with Ubuntu 10.04 does not work with `wsgi_import_script`.
+* SLES is unsupported.
+
+## 2014-07-15 - Supported Release 1.1.1
+### Summary
+
+This release merely updates metadata.json so the module can be uninstalled and
+upgraded via the puppet module command.
+
+## 2014-04-14 Supported Release 1.1.0
+
+### Summary
+
+This release primarily focuses on extending the httpd 2.4 support, tested
+through adding RHEL7 and Ubuntu 14.04 support.  It also includes Passenger 
+4 support, as well as several new modules and important bugfixes.
+
+#### Features
+
+- Add support for RHEL7 and Ubuntu 14.04
+- More complete apache24 support
+- Passenger 4 support
+- Add support for max_keepalive_requests and log_formats parameters
+- Add mod_pagespeed support
+- Add mod_speling support
+- Added several parameters for mod_passenger
+- Added ssl_cipher parameter to apache::mod::ssl
+- Improved examples in documentation
+- Added docroot_mode, action, and suexec_user_group parameters to apache::vhost
+- Add support for custom extensions for mod_php
+- Improve proxy_html support for Debian
+
+#### Bugfixes
+
+- Remove NameVirtualHost directive for apache >= 2.4
+- Order proxy_set option so it doesn't change between runs
+- Fix inverted SSL compression
+- Fix missing ensure on concat::fragment resources
+- Fix bad dependencies in apache::mod and apache::mod::mime
+
+#### Known Bugs
+* By default, the version of Apache that ships with Ubuntu 10.04 does not work with `wsgi_import_script`.
+* SLES is unsupported.
+
+## 2014-03-04 Supported Release 1.0.1
+### Summary
+
+This is a supported release.  This release removes a testing symlink that can
+cause trouble on systems where /var is on a seperate filesystem from the
+modulepath.
+
+#### Features
+#### Bugfixes
+#### Known Bugs
+* By default, the version of Apache that ships with Ubuntu 10.04 does not work with `wsgi_import_script`.
+* SLES is unsupported.
+ 
+## 2014-03-04 Supported Release 1.0.0
+### Summary
+
+This is a supported release. This release introduces Apache 2.4 support for
+Debian and RHEL based osfamilies.
+
+#### Features
+
+- Add apache24 support
+- Add rewrite_base functionality to rewrites
+- Updated README documentation
+- Add WSGIApplicationGroup and WSGIImportScript directives
+
+#### Bugfixes
+
+- Replace mutating hashes with merge() for Puppet 3.5
+- Fix WSGI import_script and mod_ssl issues on Lucid
+
+#### Known Bugs
+* By default, the version of Apache that ships with Ubuntu 10.04 does not work with `wsgi_import_script`.
+* SLES is unsupported.
+
+---
+
+## 2014-01-31 Release 0.11.0
+### Summary:
+
+This release adds preliminary support for Windows compatibility and multiple rewrite support.
+
+#### Backwards-incompatible Changes:
+
+- The rewrite_rule parameter is deprecated in favor of the new rewrite parameter
+  and will be removed in a future release.
+
+#### Features:
+
+- add Match directive
+- quote paths for windows compatibility
+- add auth_group_file option to README.md
+- allow AuthGroupFile directive for vhosts
+- Support Header directives in vhost context
+- Don't purge mods-available dir when separate enable dir is used
+- Fix the servername used in log file name
+- Added support for mod_include
+- Remove index parameters.
+- Support environment variable control for CustomLog
+- added redirectmatch support
+- Setting up the ability to do multiple rewrites and conditions.
+- Convert spec tests to beaker.
+- Support php_admin_(flag|value)s
+
+#### Bugfixes:
+
+- directories are either a Hash or an Array of Hashes
+- Configure Passenger in separate .conf file on RH so PassengerRoot isn't lost
+- (docs) Update list of `apache::mod::[name]` classes
+- (docs) Fix apache::namevirtualhost example call style
+- Fix $ports_file reference in apache::listen.
+- Fix $ports_file reference in Namevirtualhost.
+
+
+## 2013-12-05 Release 0.10.0
+### Summary:
+
+This release adds FreeBSD osfamily support and various other improvements to some mods.
+
+#### Features:
+
+- Add suPHP_UserGroup directive to directory context
+- Add support for ScriptAliasMatch directives
+- Set SSLOptions StdEnvVars in server context
+- No implicit <Directory> entry for ScriptAlias path
+- Add support for overriding ErrorDocument
+- Add support for AliasMatch directives
+- Disable default "allow from all" in vhost-directories
+- Add WSGIPythonPath as an optional parameter to mod_wsgi. 
+- Add mod_rpaf support
+- Add directives: IndexOptions, IndexOrderDefault
+- Add ability to include additional external configurations in vhost
+- need to use the provider variable not the provider key value from the directory hash for matches
+- Support for FreeBSD and few other features
+- Add new params to apache::mod::mime class
+- Allow apache::mod to specify module id and path
+- added $server_root parameter
+- Add Allow and ExtendedStatus support to mod_status
+- Expand vhost/_directories.pp directive support
+- Add initial support for nss module (no directives in vhost template yet)
+- added peruser and event mpms
+- added $service_name parameter
+- add parameter for TraceEnable
+- Make LogLevel configurable for server and vhost
+- Add documentation about $ip
+- Add ability to pass ip (instead of wildcard) in default vhost files
+
+#### Bugfixes:
+
+- Don't listen on port or set NameVirtualHost for non-existent vhost
+- only apply Directory defaults when provider is a directory
+- Working mod_authnz_ldap support on Debian/Ubuntu
+
+## 2013-09-06 Release 0.9.0
+### Summary:
+This release adds more parameters to the base apache class and apache defined
+resource to make the module more flexible. It also adds or enhances SuPHP,
+WSGI, and Passenger mod support, and support for the ITK mpm module.
+
+#### Backwards-incompatible Changes:
+- Remove many default mods that are not normally needed.
+- Remove `rewrite_base` `apache::vhost` parameter; did not work anyway.
+- Specify dependencies on stdlib >=2.4.0 (this was already the case, but
+making explicit)
+- Deprecate `a2mod` in favor of the `apache::mod::*` classes and `apache::mod`
+defined resource.
+
+#### Features:
+- `apache` class
+  - Add `httpd_dir` parameter to change the location of the configuration
+  files.
+  - Add `logroot` parameter to change the logroot
+  - Add `ports_file` parameter to changes the `ports.conf` file location
+  - Add `keepalive` parameter to enable persistent connections
+  - Add `keepalive_timeout` parameter to change the timeout
+  - Update `default_mods` to be able to take an array of mods to enable.
+- `apache::vhost`
+  - Add `wsgi_daemon_process`, `wsgi_daemon_process_options`,
+  `wsgi_process_group`, and `wsgi_script_aliases` parameters for per-vhost
+  WSGI configuration.
+  - Add `access_log_syslog` parameter to enable syslogging.
+  - Add `error_log_syslog` parameter to enable syslogging of errors.
+  - Add `directories` hash parameter. Please see README for documentation.
+  - Add `sslproxyengine` parameter to enable SSLProxyEngine
+  - Add `suphp_addhandler`, `suphp_engine`, and `suphp_configpath` for
+  configuring SuPHP.
+  - Add `custom_fragment` parameter to allow for arbitrary apache
+  configuration injection. (Feature pull requests are prefered over using
+  this, but it is available in a pinch.)
+- Add `apache::mod::suphp` class for configuring SuPHP.
+- Add `apache::mod::itk` class for configuring ITK mpm module.
+- Update `apache::mod::wsgi` class for global WSGI configuration with
+`wsgi_socket_prefix` and `wsgi_python_home` parameters.
+- Add README.passenger.md to document the `apache::mod::passenger` usage.
+Added `passenger_high_performance`, `passenger_pool_idle_time`,
+`passenger_max_requests`, `passenger_stat_throttle_rate`, `rack_autodetect`,
+and `rails_autodetect` parameters.
+- Separate the httpd service resource into a new `apache::service` class for
+dependency chaining of `Class['apache'] -> <resource> ~>
+Class['apache::service']`
+- Added `apache::mod::proxy_balancer` class for `apache::balancer`
+
+#### Bugfixes:
+- Change dependency to puppetlabs-concat
+- Fix ruby 1.9 bug for `a2mod`
+- Change servername to be `$::hostname` if there is no `$::fqdn`
+- Make `/etc/ssl/certs` the default ssl certs directory for RedHat non-5.
+- Make `php` the default php package for RedHat non-5.
+- Made `aliases` able to take a single alias hash instead of requiring an
+array.
+
+## 2013-07-26 Release 0.8.1
+#### Bugfixes:
+- Update `apache::mpm_module` detection for worker/prefork
+- Update `apache::mod::cgi` and `apache::mod::cgid` detection for
+worker/prefork
+
+## 2013-07-16 Release 0.8.0
+#### Features:
+- Add `servername` parameter to `apache` class
+- Add `proxy_set` parameter to `apache::balancer` define
+
+#### Bugfixes:
+- Fix ordering for multiple `apache::balancer` clusters
+- Fix symlinking for sites-available on Debian-based OSs
+- Fix dependency ordering for recursive confdir management
+- Fix `apache::mod::*` to notify the service on config change
+- Documentation updates
+
+## 2013-07-09 Release 0.7.0
+#### Changes:
+- Essentially rewrite the module -- too many to list
+- `apache::vhost` has many abilities -- see README.md for details
+- `apache::mod::*` classes provide httpd mod-loading capabilities
+- `apache` base class is much more configurable
+
+#### Bugfixes:
+- Many. And many more to come
+
+## 2013-03-2 Release 0.6.0
+- update travis tests (add more supported versions)
+- add access log_parameter
+- make purging of vhost dir configurable
+
+## 2012-08-24 Release 0.4.0
+#### Changes:
+- `include apache` is now required when using `apache::mod::*`
+
+#### Bugfixes:
+- Fix syntax for validate_re
+- Fix formatting in vhost template
+- Fix spec tests such that they pass
+
+## 2012-05-08 Puppet Labs <info@puppetlabs.com> - 0.0.4
+* e62e362 Fix broken tests for ssl, vhost, vhost::*
+* 42c6363 Changes to match style guide and pass puppet-lint without error
+* 42bc8ba changed name => path for file resources in order to name namevar by it's name
+* 72e13de One end too much
+* 0739641 style guide fixes: 'true' <> true, $operatingsystem needs to be $::operatingsystem, etc.
+* 273f94d fix tests
+* a35ede5 (#13860) Make a2enmod/a2dismo commands optional
+* 98d774e (#13860) Autorequire Package['httpd']
+* 05fcec5 (#13073) Add missing puppet spec tests
+* 541afda (#6899) Remove virtual a2mod definition
+* 976cb69 (#13072) Move mod python and wsgi package names to params
+* 323915a (#13060) Add .gitignore to repo
+* fdf40af (#13060) Remove pkg directory from source tree
+* fd90015 Add LICENSE file and update the ModuleFile
+* d3d0d23 Re-enable local php class
+* d7516c7 Make management of firewalls configurable for vhosts
+* 60f83ba Explicitly lookup scope of apache_name in templates.
+* f4d287f (#12581) Add explicit ordering for vdir directory
+* 88a2ac6 (#11706) puppetlabs-apache depends on puppetlabs-firewall
+* a776a8b (#11071) Fix to work with latest firewall module
+* 2b79e8b (#11070) Add support for Scientific Linux
+* 405b3e9 Fix for a2mod
+* 57b9048 Commit apache::vhost::redirect Manifest
+* 8862d01 Commit apache::vhost::proxy Manifest
+* d5c1fd0 Commit apache::mod::wsgi Manifest
+* a825ac7 Commit apache::mod::python Manifest
+* b77062f Commit Templates
+* 9a51b4a Vhost File Declarations
+* 6cf7312 Defaults for Parameters
+* 6a5b11a Ensure installed
+* f672e46 a2mod fix
+* 8a56ee9 add pthon support to apache
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/CONTRIBUTING.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,220 @@
+Checklist (and a short version for the impatient)
+=================================================
+
+  * Commits:
+
+    - Make commits of logical units.
+
+    - Check for unnecessary whitespace with "git diff --check" before
+      committing.
+
+    - Commit using Unix line endings (check the settings around "crlf" in
+      git-config(1)).
+
+    - Do not check in commented out code or unneeded files.
+
+    - The first line of the commit message should be a short
+      description (50 characters is the soft limit, excluding ticket
+      number(s)), and should skip the full stop.
+
+    - Associate the issue in the message. The first line should include
+      the issue number in the form "(#XXXX) Rest of message".
+
+    - The body should provide a meaningful commit message, which:
+
+      - uses the imperative, present tense: "change", not "changed" or
+        "changes".
+
+      - includes motivation for the change, and contrasts its
+        implementation with the previous behavior.
+
+    - Make sure that you have tests for the bug you are fixing, or
+      feature you are adding.
+
+    - Make sure the test suites passes after your commit:
+      `bundle exec rspec spec/acceptance` More information on [testing](#Testing) below
+
+    - When introducing a new feature, make sure it is properly
+      documented in the README.md
+
+  * Submission:
+
+    * Pre-requisites:
+
+      - Make sure you have a [GitHub account](https://github.com/join)
+
+      - [Create a ticket](https://tickets.puppetlabs.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppetlabs.com/browse/) you are patching for.
+
+    * Preferred method:
+
+      - Fork the repository on GitHub.
+
+      - Push your changes to a topic branch in your fork of the
+        repository. (the format ticket/1234-short_description_of_change is
+        usually preferred for this project).
+
+      - Submit a pull request to the repository in the puppetlabs
+        organization.
+
+The long version
+================
+
+  1.  Make separate commits for logically separate changes.
+
+      Please break your commits down into logically consistent units
+      which include new or changed tests relevant to the rest of the
+      change.  The goal of doing this is to make the diff easier to
+      read for whoever is reviewing your code.  In general, the easier
+      your diff is to read, the more likely someone will be happy to
+      review it and get it into the code base.
+
+      If you are going to refactor a piece of code, please do so as a
+      separate commit from your feature or bug fix changes.
+
+      We also really appreciate changes that include tests to make
+      sure the bug is not re-introduced, and that the feature is not
+      accidentally broken.
+
+      Describe the technical detail of the change(s).  If your
+      description starts to get too long, that is a good sign that you
+      probably need to split up your commit into more finely grained
+      pieces.
+
+      Commits which plainly describe the things which help
+      reviewers check the patch and future developers understand the
+      code are much more likely to be merged in with a minimum of
+      bike-shedding or requested changes.  Ideally, the commit message
+      would include information, and be in a form suitable for
+      inclusion in the release notes for the version of Puppet that
+      includes them.
+
+      Please also check that you are not introducing any trailing
+      whitespace or other "whitespace errors".  You can do this by
+      running "git diff --check" on your changes before you commit.
+
+  2.  Sending your patches
+
+      To submit your changes via a GitHub pull request, we _highly_
+      recommend that you have them on a topic branch, instead of
+      directly on "master".
+      It makes things much easier to keep track of, especially if
+      you decide to work on another thing before your first change
+      is merged in.
+
+      GitHub has some pretty good
+      [general documentation](http://help.github.com/) on using
+      their site.  They also have documentation on
+      [creating pull requests](http://help.github.com/send-pull-requests/).
+
+      In general, after pushing your topic branch up to your
+      repository on GitHub, you can switch to the branch in the
+      GitHub UI and click "Pull Request" towards the top of the page
+      in order to open a pull request.
+
+
+  3.  Update the related GitHub issue.
+
+      If there is a GitHub issue associated with the change you
+      submitted, then you should update the ticket to include the
+      location of your branch, along with any other commentary you
+      may wish to make.
+
+Testing
+=======
+
+Getting Started
+---------------
+
+Our puppet modules provide [`Gemfile`](./Gemfile)s which can tell a ruby
+package manager such as [bundler](http://bundler.io/) what Ruby packages,
+or Gems, are required to build, develop, and test this software.
+
+Please make sure you have [bundler installed](http://bundler.io/#getting-started)
+on your system, then use it to install all dependencies needed for this project,
+by running
+
+```shell
+% bundle install
+Fetching gem metadata from https://rubygems.org/........
+Fetching gem metadata from https://rubygems.org/..
+Using rake (10.1.0)
+Using builder (3.2.2)
+-- 8><-- many more --><8 --
+Using rspec-system-puppet (2.2.0)
+Using serverspec (0.6.3)
+Using rspec-system-serverspec (1.0.0)
+Using bundler (1.3.5)
+Your bundle is complete!
+Use `bundle show [gemname]` to see where a bundled gem is installed.
+```
+
+NOTE some systems may require you to run this command with sudo.
+
+If you already have those gems installed, make sure they are up-to-date:
+
+```shell
+% bundle update
+```
+
+With all dependencies in place and up-to-date we can now run the tests:
+
+```shell
+% rake spec
+```
+
+This will execute all the [rspec tests](http://rspec-puppet.com/) tests
+under [spec/defines](./spec/defines), [spec/classes](./spec/classes),
+and so on. rspec tests may have the same kind of dependencies as the
+module they are testing. While the module defines in its [Modulefile](./Modulefile),
+rspec tests define them in [.fixtures.yml](./fixtures.yml).
+
+Some puppet modules also come with [beaker](https://github.com/puppetlabs/beaker)
+tests. These tests spin up a virtual machine under
+[VirtualBox](https://www.virtualbox.org/)) with, controlling it with
+[Vagrant](http://www.vagrantup.com/) to actually simulate scripted test
+scenarios. In order to run these, you will need both of those tools
+installed on your system.
+
+You can run them by issuing the following command
+
+```shell
+% rake spec_clean
+% rspec spec/acceptance
+```
+
+This will now download a pre-fabricated image configured in the [default node-set](./spec/acceptance/nodesets/default.yml),
+install puppet, copy this module and install its dependencies per [spec/spec_helper_acceptance.rb](./spec/spec_helper_acceptance.rb)
+and then run all the tests under [spec/acceptance](./spec/acceptance).
+
+Writing Tests
+-------------
+
+XXX getting started writing tests.
+
+If you have commit access to the repository
+===========================================
+
+Even if you have commit access to the repository, you will still need to
+go through the process above, and have someone else review and merge
+in your changes.  The rule is that all changes must be reviewed by a
+developer on the project (that did not write the code) to ensure that
+all changes go through a code review process.
+
+Having someone other than the author of the topic branch recorded as
+performing the merge is the record that they performed the code
+review.
+
+
+Additional Resources
+====================
+
+* [Getting additional help](http://puppetlabs.com/community/get-help)
+
+* [Writing tests](http://projects.puppetlabs.com/projects/puppet/wiki/Development_Writing_Tests)
+
+* [Patchwork](https://patchwork.puppetlabs.com)
+
+* [General GitHub documentation](http://help.github.com/)
+
+* [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/Gemfile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,48 @@
+source ENV['GEM_SOURCE'] || "https://rubygems.org"
+
+def location_for(place, fake_version = nil)
+  if place =~ /^(git:[^#]*)#(.*)/
+    [fake_version, { :git => $1, :branch => $2, :require => false }].compact
+  elsif place =~ /^file:\/\/(.*)/
+    ['>= 0', { :path => File.expand_path($1), :require => false }]
+  else
+    [place, { :require => false }]
+  end
+end
+
+group :development, :unit_tests do
+  gem 'rspec-core', '3.1.7',     :require => false
+  gem 'puppetlabs_spec_helper',  :require => false
+  gem 'simplecov',               :require => false
+  gem 'puppet_facts',            :require => false
+  gem 'json',                    :require => false
+end
+
+group :system_tests do
+  if beaker_version = ENV['BEAKER_VERSION']
+    gem 'beaker', *location_for(beaker_version)
+  end
+  if beaker_rspec_version = ENV['BEAKER_RSPEC_VERSION']
+    gem 'beaker-rspec', *location_for(beaker_rspec_version)
+  else
+    gem 'beaker-rspec',  :require => false
+  end
+  gem 'serverspec',    :require => false
+  gem 'beaker-puppet_install_helper', :require => false
+end
+
+
+
+if facterversion = ENV['FACTER_GEM_VERSION']
+  gem 'facter', facterversion, :require => false
+else
+  gem 'facter', :require => false
+end
+
+if puppetversion = '4.2.0'
+  gem 'puppet', puppetversion, :require => false
+else
+  gem 'puppet', :require => false
+end
+
+# vim:ft=ruby
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/LICENSE	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+Copyright (C) 2012 Puppet Labs Inc
+
+Puppet Labs can be contacted at: info@puppetlabs.com
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/README.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3332 @@
+# apache
+
+[Module description]: #module-description
+
+[Setup]: #setup
+[Beginning with Apache]: #beginning-with-apache
+
+[Usage]: #usage
+[Configuring virtual hosts]: #configuring-virtual-hosts
+[Configuring virtual hosts with SSL]: #configuring-virtual-hosts-with-ssl
+[Configuring virtual host port and address bindings]: #configuring-virtual-host-port-and-address-bindings
+[Configuring virtual hosts for apps and processors]: #configuring-virtual-hosts-for-apps-and-processors
+[Configuring IP-based virtual hosts]: #configuring-ip-based-virtual-hosts
+[Installing Apache modules]: #installing-apache-modules
+[Installing arbitrary modules]: #installing-arbitrary-modules
+[Installing specific modules]: #installing-specific-modules
+[Configuring FastCGI servers]: #configuring-fastcgi-servers-to-handle-php-files
+[Load balancing examples]: #load-balancing-examples
+
+[Reference]: #reference
+[Public classes]: #public-classes
+[Private classes]: #private-classes
+[Public defines]: #public-defines
+[Private defines]: #private-defines
+[Templates]: #templates
+
+[Limitations]: #limitations
+
+[Development]: #development
+[Contributing]: #contributing
+[Running tests]: #running-tests
+
+[`AddDefaultCharset`]: http://httpd.apache.org/docs/current/mod/core.html#adddefaultcharset
+[`add_listen`]: #add_listen
+[`Alias`]: https://httpd.apache.org/docs/current/mod/mod_alias.html#alias
+[`AliasMatch`]: https://httpd.apache.org/docs/current/mod/mod_alias.html#aliasmatch
+[aliased servers]: https://httpd.apache.org/docs/current/urlmapping.html
+[`AllowEncodedSlashes`]: http://httpd.apache.org/docs/current/mod/core.html#allowencodedslashes
+[`apache`]: #class-apache
+[`apache_version`]: #apache_version
+[`apache::balancer`]: #define-apachebalancer
+[`apache::balancermember`]: #define-apachebalancermember
+[`apache::fastcgi::server`]: #define-apachefastcgiserver
+[`apache::mod`]: #define-apachemod
+[`apache::mod::<MODULE NAME>`]: #classes-apachemodmodule-name
+[`apache::mod::alias`]: #class-apachemodalias
+[`apache::mod::auth_cas`]: #class-apachemodauth_cas
+[`apache::mod::auth_mellon`]: #class-apachemodauth_mellon
+[`apache::mod::disk_cache`]: #class-apachemoddisk_cache
+[`apache::mod::event`]: #class-apachemodevent
+[`apache::mod::ext_filter`]: #class-apachemodext_filter
+[`apache::mod::geoip`]: #class-apachemodgeoip
+[`apache::mod::itk`]: #class-apachemoditk
+[`apache::mod::passenger`]: #class-apachemodpassenger
+[`apache::mod::peruser`]: #class-apachemodperuser
+[`apache::mod::prefork`]: #class-apachemodprefork
+[`apache::mod::proxy_html`]: #class-apachemodproxy_html
+[`apache::mod::security`]: #class-apachemodsecurity
+[`apache::mod::shib`]: #class-apachemodshib
+[`apache::mod::ssl`]: #class-apachemodssl
+[`apache::mod::status`]: #class-apachemodstatus
+[`apache::mod::worker`]: #class-apachemodworker
+[`apache::mod::wsgi`]: #class-apachemodwsgi
+[`apache::params`]: #class-apacheparams
+[`apache::version`]: #class-apacheversion
+[`apache::vhost`]: #define-apachevhost
+[`apache::vhost::WSGIImportScript`]: #wsgiimportscript
+[Apache HTTP Server]: http://httpd.apache.org
+[Apache modules]: http://httpd.apache.org/docs/current/mod/
+[array]: https://docs.puppetlabs.com/puppet/latest/reference/lang_data_array.html
+
+[beaker-rspec]: https://github.com/puppetlabs/beaker-rspec
+
+[certificate revocation list]: http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcarevocationfile
+[certificate revocation list path]: http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcarevocationpath
+[common gateway interface]: http://httpd.apache.org/docs/current/howto/cgi.html
+[`confd_dir`]: #confd_dir
+[`content`]: #content
+[custom error documents]: http://httpd.apache.org/docs/current/custom-error.html
+[`custom_fragment`]: #custom_fragment
+
+[`default_mods`]: #default_mods
+[`default_ssl_crl`]: #default_ssl_crl
+[`default_ssl_crl_path`]: #default_ssl_crl_path
+[`default_ssl_vhost`]: #default_ssl_vhost
+[`dev_packages`]: #dev_packages
+[`directory`]: #directory
+[`directories`]: #parameter-directories-for-apachevhost
+[`DirectoryIndex`]: http://httpd.apache.org/docs/current/mod/mod_dir.html#directoryindex
+[`docroot`]: #docroot
+[`docroot_owner`]: #docroot_owner
+[`docroot_group`]: #docroot_group
+[`DocumentRoot`]: https://httpd.apache.org/docs/current/mod/core.html#documentroot
+
+[`EnableSendfile`]: http://httpd.apache.org/docs/current/mod/core.html#enablesendfile
+[`ExpiresByType`]: http://httpd.apache.org/docs/current/mod/mod_expires.html#expiresbytype
+[enforcing mode]: http://selinuxproject.org/page/Guide/Mode
+[`ensure`]: https://docs.puppetlabs.com/references/latest/type.html#package-attribute-ensure
+[exported resources]: http://docs.puppetlabs.com/latest/reference/lang_exported.md
+[`ExtendedStatus`]: http://httpd.apache.org/docs/current/mod/core.html#extendedstatus
+
+[Facter]: http://docs.puppetlabs.com/facter/
+[FastCGI]: http://www.fastcgi.com/
+[FallbackResource]: https://httpd.apache.org/docs/current/mod/mod_dir.html#fallbackresource
+[`fallbackresource`]: #fallbackresource
+[filter rules]: http://httpd.apache.org/docs/current/filter.html
+[`filters`]: #filters
+[`ForceType`]: http://httpd.apache.org/docs/current/mod/core.html#forcetype
+
+[GeoIPScanProxyHeaders]: http://dev.maxmind.com/geoip/legacy/mod_geoip2/#Proxy-Related_Directives
+[`gentoo/puppet-portage`]: https://github.com/gentoo/puppet-portage
+
+[Hash]: https://docs.puppetlabs.com/puppet/latest/reference/lang_data_hash.html
+
+[`IncludeOptional`]: http://httpd.apache.org/docs/current/mod/core.html#includeoptional
+[`Include`]: http://httpd.apache.org/docs/current/mod/core.html#include
+[interval syntax]: http://httpd.apache.org/docs/current/mod/mod_expires.html#AltSyn
+[`ip`]: #ip
+[`ip_based`]: #ip_based
+[IP-based virtual hosts]: http://httpd.apache.org/docs/current/vhosts/ip-based.html
+
+[`KeepAlive`]: http://httpd.apache.org/docs/current/mod/core.html#keepalive
+[`KeepAliveTimeout`]: http://httpd.apache.org/docs/current/mod/core.html#keepalivetimeout
+[`keepalive` parameter]: #keepalive
+[`keepalive_timeout`]: #keepalive_timeout
+
+[`lib`]: #lib
+[`lib_path`]: #lib_path
+[`Listen`]: http://httpd.apache.org/docs/current/bind.html
+[`ListenBackLog`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#listenbacklog
+[`LoadFile`]: https://httpd.apache.org/docs/current/mod/mod_so.html#loadfile
+[`LogFormat`]: https://httpd.apache.org/docs/current/mod/mod_log_config.html#logformat
+[`logroot`]: #logroot
+[Log security]: http://httpd.apache.org/docs/current/logs.html#security
+
+[`manage_docroot`]: #manage_docroot
+[`manage_user`]: #manage_user
+[`manage_group`]: #manage_group
+[`MaxConnectionsPerChild`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#maxconnectionsperchild
+[`max_keepalive_requests`]: #max_keepalive_requests
+[`MaxRequestWorkers`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#maxrequestworkers
+[`MaxSpareThreads`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#maxsparethreads
+[MIME `content-type`]: https://www.iana.org/assignments/media-types/media-types.xhtml
+[`MinSpareThreads`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#minsparethreads
+[`mod_alias`]: https://httpd.apache.org/docs/current/mod/mod_alias.html
+[`mod_auth_cas`]: https://github.com/Jasig/mod_auth_cas
+[`mod_auth_kerb`]: http://modauthkerb.sourceforge.net/configure.html
+[`mod_authnz_external`]: https://code.google.com/p/mod-auth-external/
+[`mod_auth_mellon`]: https://github.com/UNINETT/mod_auth_mellon
+[`mod_disk_cache`]: https://httpd.apache.org/docs/2.2/mod/mod_disk_cache.html
+[`mod_cache_disk`]: https://httpd.apache.org/docs/current/mod/mod_cache_disk.html
+[`mod_expires`]: http://httpd.apache.org/docs/current/mod/mod_expires.html
+[`mod_ext_filter`]: http://httpd.apache.org/docs/current/mod/mod_ext_filter.html
+[`mod_fcgid`]: https://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html
+[`mod_geoip`]: http://dev.maxmind.com/geoip/legacy/mod_geoip2/
+[`mod_info`]: https://httpd.apache.org/docs/current/mod/mod_info.html
+[`mod_mpm_event`]: https://httpd.apache.org/docs/current/mod/event.html
+[`mod_negotiation`]: http://httpd.apache.org/docs/current/mod/mod_negotiation.html
+[`mod_pagespeed`]: https://developers.google.com/speed/pagespeed/module/?hl=en
+[`mod_php`]: http://php.net/manual/en/book.apache.php
+[`mod_proxy`]: https://httpd.apache.org/docs/current/mod/mod_proxy.html
+[`mod_proxy_balancer`]: http://httpd.apache.org/docs/current/mod/mod_proxy_balancer.html
+[`mod_reqtimeout`]: http://httpd.apache.org/docs/current/mod/mod_reqtimeout.html
+[`mod_security`]: https://www.modsecurity.org/
+[`mod_ssl`]: http://httpd.apache.org/docs/current/mod/mod_ssl.html
+[`mod_status`]: http://httpd.apache.org/docs/current/mod/mod_status.html
+[`mod_version`]: http://httpd.apache.org/docs/current/mod/mod_version.html
+[`mod_wsgi`]: http://modwsgi.readthedocs.org/en/latest/
+[module contribution guide]: http://docs.puppetlabs.com/forge/contributing.html
+[`mpm_module`]: #mpm_module
+[multi-processing module]: http://httpd.apache.org/docs/current/mpm.html
+
+[name-based virtual hosts]: https://httpd.apache.org/docs/current/vhosts/name-based.html
+
+[open source Puppet]: http://docs.puppetlabs.com/puppet/
+[`Options`]: https://httpd.apache.org/docs/current/mod/core.html#options
+
+[`path`]: #path
+[`Peruser`]: http://www.freebsd.org/cgi/url.cgi?ports/www/apache22-peruser-mpm/pkg-descr
+[`port`]: #port
+[`priority`]: #defines-apachevhost
+[`ProxyPass`]: http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypass
+[`ProxySet`]: http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxyset
+[Puppet Enterprise]: http://docs.puppetlabs.com/pe/
+[Puppet Forge]: http://forge.puppetlabs.com
+[Puppet Labs]: http://puppetlabs.com
+[Puppet module]: http://docs.puppetlabs.com/puppet/latest/reference/modules_fundamentals.html
+[Puppet module's code]: https://github.com/puppetlabs/puppetlabs-apache/blob/master/manifests/default_mods.pp
+[`purge_configs`]: #purge_configs
+[`purge_vhost_dir`]: #purge_vhost_dir
+[Python]: https://www.python.org/
+
+[Rack]: http://rack.github.io/
+[`rack_base_uris`]: #rack_base_uris
+[RFC 2616]: https://www.ietf.org/rfc/rfc2616.txt
+[`RequestReadTimeout`]: http://httpd.apache.org/docs/current/mod/mod_reqtimeout.html#requestreadtimeout
+[rspec-puppet]: http://rspec-puppet.com/
+
+[`ScriptAlias`]: https://httpd.apache.org/docs/current/mod/mod_alias.html#scriptalias
+[`ScriptAliasMatch`]: https://httpd.apache.org/docs/current/mod/mod_alias.html#scriptaliasmatch
+[`scriptalias`]: #scriptalias
+[SELinux]: http://selinuxproject.org/
+[`ServerAdmin`]: http://httpd.apache.org/docs/current/mod/core.html#serveradmin
+[`serveraliases`]: #serveraliases
+[`ServerLimit`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#serverlimit
+[`ServerName`]: http://httpd.apache.org/docs/current/mod/core.html#servername
+[`ServerRoot`]: http://httpd.apache.org/docs/current/mod/core.html#serverroot
+[`ServerTokens`]: http://httpd.apache.org/docs/current/mod/core.html#servertokens
+[`ServerSignature`]: http://httpd.apache.org/docs/current/mod/core.html#serversignature
+[Service attribute restart]: http://docs.puppetlabs.com/references/latest/type.html#service-attribute-restart
+[`source`]: #source
+[`SSLCARevocationCheck`]: http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcarevocationcheck
+[SSL certificate key file]: http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcertificatekeyfile
+[SSL chain]: https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcertificatechainfile
+[SSL encryption]: https://httpd.apache.org/docs/current/ssl/index.html
+[`ssl`]: #ssl
+[`ssl_cert`]: #ssl_cert
+[`ssl_compression`]: #ssl_compression
+[`ssl_key`]: #ssl_key
+[`StartServers`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#startservers
+[suPHP]: http://www.suphp.org/Home.html
+[`suphp_addhandler`]: #suphp_addhandler
+[`suphp_configpath`]: #suphp_configpath
+[`suphp_engine`]: #suphp_engine
+[supported operating system]: https://forge.puppetlabs.com/supported#puppet-supported-modules-compatibility-matrix
+
+[`ThreadLimit`]: http://httpd.apache.org/docs/current/mod/mpm_common.html#threadlimit
+[`ThreadsPerChild`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#threadsperchild
+[`TimeOut`]: http://httpd.apache.org/docs/current/mod/core.html#timeout
+[template]: http://docs.puppetlabs.com/puppet/latest/reference/lang_template.html
+[`TraceEnable`]: http://httpd.apache.org/docs/current/mod/core.html#traceenable
+
+[`verify_config`]: #verify_config
+[`vhost`]: #define-apachevhost
+[`vhost_dir`]: #vhost_dir
+[`virtual_docroot`]: #virtual_docroot
+
+[Web Server Gateway Interface]: https://www.python.org/dev/peps/pep-3333/#abstract
+[`WSGIPythonPath`]: https://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPythonPath
+[`WSGIPythonHome`]: https://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPythonHome
+
+#### Table of Contents
+
+1. [Module description - What is the apache module, and what does it do?][Module description]
+2. [Setup - The basics of getting started with apache][Setup]
+    - [Beginning with Apache - Installation][Beginning with Apache]
+3. [Usage - The classes and defined types available for configuration][Usage]
+    - [Configuring virtual hosts - Examples to help get started][Configuring virtual hosts]
+    - [Configuring FastCGI servers to handle PHP files][Configuring FastCGI servers]
+    - [Load balancing with exported and non-exported resources][Load balancing examples]
+4. [Reference - An under-the-hood peek at what the module is doing and how][Reference]
+    - [Public classes][]
+    - [Private classes][]
+    - [Public defines][]
+    - [Private defines][]
+    - [Templates][]
+5. [Limitations - OS compatibility, etc.][Limitations]
+6. [Development - Guide for contributing to the module][Development]
+    - [Contributing to the apache module][Contributing]
+    - [Running tests - A quick guide][Running tests]
+
+## Module description
+
+[Apache HTTP Server][] (also called Apache HTTPD, or simply Apache) is a widely used web server. This [Puppet module][] simplifies the task of creating configurations to manage Apache servers in your infrastructure. It can configure and manage a range of virtual host setups and provides a streamlined way to install and configure [Apache modules][].
+
+## Setup
+
+**What the apache Puppet module affects:**
+
+- Configuration files and directories (created and written to)
+  - **WARNING**: Configurations *not* managed by Puppet will be purged.
+- Package/service/configuration files for Apache
+- Apache modules
+- Virtual hosts
+- Listened-to ports
+- `/etc/make.conf` on FreeBSD and Gentoo
+
+On Gentoo, this module depends on the [`gentoo/puppet-portage`][] Puppet module. Note that while several options apply or enable certain features and settings for Gentoo, it is not a [supported operating system][] for this module.
+
+**Note**: This module modifies Apache configuration files and directories and purges any configuration not managed by Puppet. Apache configuration should be managed by Puppet, as unmanaged configuration files can cause unexpected failures.
+
+To temporarily disable full Puppet management, set the [`purge_configs`][] parameter in the [`apache`][] class declaration to 'false'. We recommend using this only as a temporary means of saving and relocating customized configurations.
+
+### Beginning with Apache
+
+To have Puppet install Apache with the default parameters, declare the [`apache`][] class:
+
+~~~ puppet
+class { 'apache': }
+~~~
+
+The Puppet module applies a default configuration based on your operating system; Debian, Red Hat, FreeBSD, and Gentoo systems each have unique default configurations. These defaults work in testing environments but are not suggested for production, and Puppet recommends customizing the class's parameters to suit your site. Use the [Reference](#reference) section to find information about the class's parameters and their default values.
+
+You can customize parameters when declaring the `apache` class. For instance, this declaration installs Apache without the apache module's [default virtual host configuration][Configuring virtual hosts], allowing you to customize all Apache virtual hosts:
+
+~~~ puppet
+class { 'apache':
+  default_vhost => false,
+}
+~~~
+
+## Usage
+
+### Configuring a virtual host
+
+The default [`apache`][] class sets up a virtual host on port 80, listening on all interfaces and serving the [`docroot`][] parameter's default directory of `/var/www`.
+
+**Note**: See the [`apache::vhost`][] define's reference for a list of all virtual host parameters.
+
+To configure basic [name-based virtual hosts][], specify the [`port`][] and [`docroot`][] parameters in the [`apache::vhost`][] define:
+
+~~~ puppet
+apache::vhost { 'vhost.example.com':
+  port    => '80',
+  docroot => '/var/www/vhost',
+}
+~~~
+
+**Note**: Apache processes virtual hosts in alphabetical order, and server administrators can prioritize Apache's virtual host processing by prefixing a virtual host's configuration file name with a number. The [`apache::vhost`][] define applies a default [`priority`][] of 15, which Puppet interprets by prefixing the virtual host's file name with `15-`. This all means that if multiple sites have the same priority, or if you disable priority numbers by setting the `priority` parameter's value to 'false', Apache still processes virtual hosts in alphabetical order.
+
+To configure user and group ownership for `docroot`, use the [`docroot_owner`][] and [`docroot_group`][] parameters:
+
+~~~ puppet
+apache::vhost { 'user.example.com':
+  port          => '80',
+  docroot       => '/var/www/user',
+  docroot_owner => 'www-data',
+  docroot_group => 'www-data',
+}
+~~~
+
+#### Configuring virtual hosts with SSL
+
+To configure a virtual host to use [SSL encryption][] and default SSL certificates, set the [`ssl`][] parameter. You must also specify the [`port`][] parameter, typically with a value of '443', to accommodate HTTPS requests:
+
+~~~ puppet
+apache::vhost { 'ssl.example.com':
+  port    => '443',
+  docroot => '/var/www/ssl',
+  ssl     => true,
+}
+~~~
+
+To configure a virtual host to use SSL and specific SSL certificates, use the paths to the certificate and key in the [`ssl_cert`][] and [`ssl_key`][] parameters, respectively:
+
+~~~ puppet
+apache::vhost { 'cert.example.com':
+  port     => '443',
+  docroot  => '/var/www/cert',
+  ssl      => true,
+  ssl_cert => '/etc/ssl/fourth.example.com.cert',
+  ssl_key  => '/etc/ssl/fourth.example.com.key',
+}
+~~~
+
+To configure a mix of SSL and unencrypted virtual hosts at the same domain, declare them with separate [`apache::vhost`] defines:
+
+~~~ puppet
+# The non-ssl virtual host
+apache::vhost { 'mix.example.com non-ssl':
+  servername => 'mix.example.com',
+  port       => '80',
+  docroot    => '/var/www/mix',
+}
+
+# The SSL virtual host at the same domain
+apache::vhost { 'mix.example.com ssl':
+  servername => 'mix.example.com',
+  port       => '443',
+  docroot    => '/var/www/mix',
+  ssl        => true,
+}
+~~~
+
+To configure a virtual host to redirect unencrypted connections to SSL, declare them with separate [`apache::vhost`] defines and redirect unencrypted requests to the virtual host with SSL enabled:
+
+~~~ puppet
+apache::vhost { 'redirect.example.com non-ssl':
+  servername      => 'redirect.example.com',
+  port            => '80',
+  docroot         => '/var/www/redirect',
+  redirect_status => 'permanent',
+  redirect_dest   => 'https://redirect.example.com/'
+}
+
+apache::vhost { 'redirect.example.com ssl':
+  servername => 'redirect.example.com',
+  port       => '443',
+  docroot    => '/var/www/redirect',
+  ssl        => true,
+}
+~~~
+
+#### Configuring virtual host port and address bindings
+
+Virtual hosts listen on all IP addresses ('*') by default. To configure the virtual host to listen on a specific IP address, use the [`ip`][] parameter:
+
+~~~ puppet
+apache::vhost { 'ip.example.com':
+  ip      => '127.0.0.1',
+  port    => '80',
+  docroot => '/var/www/ip',
+}
+~~~
+
+It is also possible to configure more than one IP address per vhost by using an array of IP addresses for the [`ip`][] parameter:
+
+~~~ puppet
+apache::vhost { 'ip.example.com':
+  ip      => ['127.0.0.1','169.254.1.1'],
+  port    => '80',
+  docroot => '/var/www/ip',
+}
+~~~
+
+To configure a virtual host with [aliased servers][], refer to the aliases using the [`serveraliases`][] parameter:
+
+~~~ puppet
+apache::vhost { 'aliases.example.com':
+  serveraliases => [
+    'aliases.example.org',
+    'aliases.example.net',
+  ],
+  port          => '80',
+  docroot       => '/var/www/aliases',
+}
+~~~
+
+To set up a virtual host with a wildcard alias for the subdomain mapped to a same-named directory, such as 'http://example.com.loc' mapped to `/var/www/example.com`, define the wildcard alias using the [`serveraliases`][] parameter and the document root with the [`virtual_docroot`][] parameter:
+
+~~~ puppet
+apache::vhost { 'subdomain.loc':
+  vhost_name      => '*',
+  port            => '80',
+  virtual_docroot => '/var/www/%-2+',
+  docroot         => '/var/www',
+  serveraliases   => ['*.loc',],
+}
+~~~
+
+To configure a virtual host with [filter rules][], pass the filter directives as an [array][] using the [`filters`][] parameter:
+
+~~~ puppet
+apache::vhost { 'subdomain.loc':
+  port    => '80',
+  filters => [
+    'FilterDeclare  COMPRESS',
+    'FilterProvider COMPRESS DEFLATE resp=Content-Type $text/html',
+    'FilterChain    COMPRESS',
+    'FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no',
+  ],
+  docroot => '/var/www/html',
+}
+~~~
+
+#### Configuring virtual hosts for apps and processors
+
+To set up a virtual host with [suPHP][], use the [`suphp_engine`][] parameter to enable the suPHP engine, [`suphp_addhandler`][] parameter to define a MIME type, [`suphp_configpath`][] to set which path suPHP passes to the PHP interpreter, and the [`directory`][] parameter to configure Directory, File, and Location directive blocks:
+
+~~~ puppet
+apache::vhost { 'suphp.example.com':
+  port             => '80',
+  docroot          => '/home/appuser/myphpapp',
+  suphp_addhandler => 'x-httpd-php',
+  suphp_engine     => 'on',
+  suphp_configpath => '/etc/php5/apache2',
+  directories      => [
+    { 'path'  => '/home/appuser/myphpapp',
+      'suphp' => {
+        user  => 'myappuser',
+        group => 'myappgroup',
+      },
+    },
+  ],
+}
+~~~
+
+You can use a set of parameters to configure a virtual host to use the [Web Server Gateway Interface][] (WSGI) for [Python][] applications:
+
+~~~ puppet
+apache::vhost { 'wsgi.example.com':
+  port                        => '80',
+  docroot                     => '/var/www/pythonapp',
+  wsgi_application_group      => '%{GLOBAL}',
+  wsgi_daemon_process         => 'wsgi',
+  wsgi_daemon_process_options => {
+    processes    => '2',
+    threads      => '15',
+    display-name => '%{GROUP}',
+  },
+  wsgi_import_script          => '/var/www/demo.wsgi',
+  wsgi_import_script_options  => {
+    process-group     => 'wsgi',
+    application-group => '%{GLOBAL}',
+  },
+  wsgi_process_group          => 'wsgi',
+  wsgi_script_aliases         => { '/' => '/var/www/demo.wsgi' },
+}
+~~~
+
+Starting in Apache 2.2.16, Apache supports [FallbackResource][], a simple replacement for common RewriteRules. You can set a FallbackResource using the [`fallbackresource`][] parameter:
+
+~~~ puppet
+apache::vhost { 'wordpress.example.com':
+  port             => '80',
+  docroot          => '/var/www/wordpress',
+  fallbackresource => '/index.php',
+}
+~~~
+
+**Note**: The `fallbackresource` parameter only supports the 'disabled' value since Apache 2.2.24.
+
+To configure a virtual host with a designated directory for [Common Gateway Interface][] (CGI) files, use the [`scriptalias`][] parameter to define the `cgi-bin` path:
+
+~~~ puppet
+apache::vhost { 'cgi.example.com':
+  port        => '80',
+  docroot     => '/var/www/cgi',
+  scriptalias => '/usr/lib/cgi-bin',
+}
+~~~
+
+To configure a virtual host for [Rack][], use the [`rack_base_uris`][] parameter:
+
+~~~ puppet
+apache::vhost { 'rack.example.com':
+  port           => '80',
+  docroot        => '/var/www/rack',
+  rack_base_uris => ['/rackapp1', '/rackapp2'],
+}
+~~~
+
+#### Configuring IP-based virtual hosts
+
+You can configure [IP-based virtual hosts][] to listen on any port and have them respond to requests on specific IP addresses. In this example, we set the server to listen on ports 80 and 81 because the example virtual hosts are _not_ declared with a [`port`][] parameter:
+
+~~~ puppet
+apache::listen { '80': }
+
+apache::listen { '81': }
+~~~
+
+Then we configure the IP-based virtual hosts with the [`ip_based`][] parameter:
+
+~~~ puppet
+apache::vhost { 'first.example.com':
+  ip       => '10.0.0.10',
+  docroot  => '/var/www/first',
+  ip_based => true,
+}
+
+apache::vhost { 'second.example.com':
+  ip       => '10.0.0.11',
+  docroot  => '/var/www/second',
+  ip_based => true,
+}
+~~~
+
+You can also configure a mix of IP- and [name-based virtual hosts][], and in any combination of [SSL][SSL encryption] and unencrypted configurations. First, we add two IP-based virtual hosts on an IP address (in this example, 10.0.0.10). One uses SSL and the other is unencrypted:
+
+~~~ puppet
+apache::vhost { 'The first IP-based virtual host, non-ssl':
+  servername => 'first.example.com',
+  ip         => '10.0.0.10',
+  port       => '80',
+  ip_based   => true,
+  docroot    => '/var/www/first',
+}
+
+apache::vhost { 'The first IP-based vhost, ssl':
+  servername => 'first.example.com',
+  ip         => '10.0.0.10',
+  port       => '443',
+  ip_based   => true,
+  docroot    => '/var/www/first-ssl',
+  ssl        => true,
+}
+~~~
+
+Next, we add two name-based virtual hosts listening on a second IP address (10.0.0.20):
+
+~~~ puppet
+apache::vhost { 'second.example.com':
+  ip      => '10.0.0.20',
+  port    => '80',
+  docroot => '/var/www/second',
+}
+
+apache::vhost { 'third.example.com':
+  ip      => '10.0.0.20',
+  port    => '80',
+  docroot => '/var/www/third',
+}
+~~~
+
+To add name-based virtual hosts that answer on either 10.0.0.10 or 10.0.0.20, you **must** set the [`add_listen`][] parameter to 'false' to disable the default Apache setting of `Listen 80`, as it conflicts with the preceding IP-based virtual hosts.
+
+~~~ puppet
+apache::vhost { 'fourth.example.com':
+  port       => '80',
+  docroot    => '/var/www/fourth',
+  add_listen => false,
+}
+
+apache::vhost { 'fifth.example.com':
+  port       => '80',
+  docroot    => '/var/www/fifth',
+  add_listen => false,
+}
+~~~
+
+### Installing Apache modules
+
+There's two ways to install [Apache modules][] using the Puppet apache module:
+
+- Use the [`apache::mod::<MODULE NAME>`][] classes to [install specific Apache modules with parameters][Installing specific modules].
+- Use the [`apache::mod`][] define to [install arbitrary Apache modules][Installing arbitrary modules].
+
+#### Installing specific modules
+
+The Puppet apache module supports installing many common [Apache modules][], often with parameterized configuration options. For a list of supported Apache modules, see the [`apache::mod::<MODULE NAME>`][] class references.
+
+For example, you can install the `mod_ssl` Apache module with default settings by declaring the [`apache::mod::ssl`][] class:
+
+~~~ puppet
+class { 'apache::mod::ssl': }
+~~~
+
+[`apache::mod::ssl`][] has several parameterized options that you can set when declaring it. For instance, to enable `mod_ssl` with compression enabled, set the [`ssl_compression`][] parameter to 'true':
+
+~~~ puppet
+class { 'apache::mod::ssl':
+  ssl_compression => true,
+}
+~~~
+
+Note that some modules have prerequisites, which are documented in their references under [`apache::mod::<MODULE NAME>`][].
+
+#### Installing arbitrary modules
+
+You can pass the name of any module that your operating system's package manager can install to the [`apache::mod`][] define to install it. Unlike the specific-module classes, the [`apache::mod`][] define doesn't tailor the installation based on other installed modules or with specific parameters---Puppet only grabs and installs the module's package, leaving detailed configuration up to you.
+
+For example, to install the [`mod_authnz_external`][] Apache module, declare the define with the 'mod_authnz_external' name:
+
+~~~ puppet
+apache::mod { 'mod_authnz_external': }
+~~~
+
+There's several optional parameters you can specify when defining Apache modules this way. See the [define's reference][`apache::mod`] for details.
+
+### Configuring FastCGI servers to handle PHP files
+
+Add the [`apache::fastcgi::server`][] define to allow [FastCGI][] servers to handle requests for specific files. For example, the following defines a FastCGI server at 127.0.0.1 (localhost) on port 9000 to handle PHP requests:
+
+~~~ puppet
+apache::fastcgi::server { 'php':
+  host       => '127.0.0.1:9000',
+  timeout    => 15,
+  flush      => false,
+  faux_path  => '/var/www/php.fcgi',
+  fcgi_alias => '/php.fcgi',
+  file_type  => 'application/x-httpd-php'
+}
+~~~
+
+You can then use the [`custom_fragment`] parameter to configure the virtual host to have the FastCGI server handle the specified file type:
+
+~~~ puppet
+apache::vhost { 'www':
+  ...
+  custom_fragment => 'AddType application/x-httpd-php .php'
+  ...
+}
+~~~
+
+### Load balancing examples
+
+Apache supports load balancing across groups of servers through the [`mod_proxy`][] Apache module. Puppet supports configuring Apache load balancing groups (also known as balancer clusters) through the [`apache::balancer`][] and [`apache::balancermember`][] defines.
+
+To enable load balancing with [exported resources][], export the [`apache::balancermember`][] define from the load balancer member server:
+
+~~~ puppet
+@@apache::balancermember { "${::fqdn}-puppet00":
+  balancer_cluster => 'puppet00',
+  url              => "ajp://${::fqdn}:8009",
+  options          => ['ping=5', 'disablereuse=on', 'retry=5', 'ttl=120'],
+}
+~~~
+
+Then, on the proxy server, create the load balancing group:
+
+~~~ puppet
+apache::balancer { 'puppet00': }
+~~~
+
+To enable load balancing without exporting resources, declare the following on the proxy server:
+
+~~~ puppet
+apache::balancer { 'puppet00': }
+
+apache::balancermember { "${::fqdn}-puppet00":
+    balancer_cluster => 'puppet00',
+    url              => "ajp://${::fqdn}:8009",
+    options          => ['ping=5', 'disablereuse=on', 'retry=5', 'ttl=120'],
+  }
+~~~
+
+Then declare the `apache::balancer` and `apache::balancermember` defines on the proxy server.
+
+If you need to use the [ProxySet](http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxyset) directive on the balancer, use the [`proxy_set`](#proxy_set) parameter of `apache::balancer`:
+
+~~~ puppet
+apache::balancer { 'puppet01':
+  proxy_set => {
+    'stickysession' => 'JSESSIONID',
+  },
+}
+~~~
+
+## Reference
+
+- [**Public Classes**](#public-classes)
+    - [Class: apache](#class-apache)
+    - [Class: apache::dev](#class-apachedev)
+    - [Classes: apache::mod::*](#classes-apachemodname)
+- [**Private Classes**](#private-classes)
+    - [Class: apache::confd::no_accf](#class-apacheconfdno_accf)
+    - [Class: apache::default_confd_files](#class-apachedefault_confd_files)
+    - [Class: apache::default_mods](#class-apachedefault_mods)
+    - [Class: apache::package](#class-apachepackage)
+    - [Class: apache::params](#class-apacheparams)
+    - [Class: apache::service](#class-apacheservice)
+    - [Class: apache::version](#class-apacheversion)
+- [**Public Defines**](#public-defines)
+    - [Define: apache::balancer](#define-apachebalancer)
+    - [Define: apache::balancermember](#define-apachebalancermember)
+    - [Define: apache::custom_config](#define-apachecustom_config)
+    - [Define: apache::fastcgi::server](#define-fastcgi-server)
+    - [Define: apache::listen](#define-apachelisten)
+    - [Define: apache::mod](#define-apachemod)
+    - [Define: apache::namevirtualhost](#define-apachenamevirtualhost)
+    - [Define: apache::vhost](#define-apachevhost)
+- [**Private Defines**](#private-defines)
+    - [Define: apache::default_mods::load](#define-default_mods-load)
+    - [Define: apache::peruser::multiplexer](#define-apacheperusermultiplexer)
+    - [Define: apache::peruser::processor](#define-apacheperuserprocessor)
+    - [Define: apache::security::file_link](#define-apachesecurityfile_link)
+- [**Templates**](#templates)
+
+### Public Classes
+
+#### Class: `apache`
+
+Guides the basic setup and installation of Apache on your system.
+
+When this class is declared with the default options, Puppet:
+
+- Installs the appropriate Apache software package and [required Apache modules](#default_mods) for your operating system.
+- Places the required configuration files in a directory, with the [default location](#conf_dir) determined by your operating system.
+- Configures the server with a default virtual host and standard port ('80') and address ('*') bindings.
+- Creates a document root directory determined by your operating system, typically `/var/www`.
+- Starts the Apache service.
+
+You can simply declare the default `apache` class:
+
+~~~ puppet
+class { 'apache': }
+~~~
+
+You can establish a default virtual host in this class, by using the [`apache::vhost`][] define, or both. You can also configure additional specific virtual hosts with the [`apache::vhost`][] define. Puppet recommends customizing the `apache` class's declaration with the following parameters, as its default settings are not optimized for production.
+
+**Parameters within `apache`:**
+
+##### `allow_encoded_slashes`
+
+Sets the server default for the [`AllowEncodedSlashes`][] declaration, which modifies the responses to URLs containing '\' and '/' characters. Valid options: 'on', 'off', 'nodecode'. Default: 'undef', which omits the declaration from the server's configuration and uses Apache's default setting of 'off'.
+
+##### `apache_version`
+
+Configures module template behavior, package names, and default Apache modules by defining the version of Apache to use. Default: Determined by your operating system family and release via the [`apache::version`][] class. Puppet recommends against manually configuring this parameter without reason.
+
+##### `conf_dir`
+
+Sets the directory where the Apache server's main configuration file is located. Default: Depends on your operating system.
+
+- **Debian**: `/etc/apache2`
+- **FreeBSD**: `/usr/local/etc/apache22`
+- **Gentoo**: `/etc/apache2`
+- **Red Hat**: `/etc/httpd/conf`
+
+##### `conf_template`
+
+Defines the [template][] used for the main Apache configuration file. Default: `apache/httpd.conf.erb`. Modifying this parameter is potentially risky, as the apache Puppet module is designed to use a minimal configuration file customized by `conf.d` entries.
+
+##### `confd_dir`
+
+Sets the location of the Apache server's custom configuration directory. Default: Depends on your operating system.
+
+- **Debian**: `/etc/apache2/conf.d`
+- **FreeBSD**: `/usr/local/etc/apache22`
+- **Gentoo**: `/etc/apache2/conf.d`
+- **Red Hat**: `/etc/httpd/conf.d`
+
+##### `default_charset`
+
+Used as the [`AddDefaultCharset`][] directive in the main configuration file. Default: 'undef'.
+
+##### `default_confd_files`
+
+Determines whether Puppet generates a default set of includable Apache configuration files in the directory defined by the [`confd_dir`][] parameter. These configuration files correspond to what is typically installed with the Apache package on the server's operating system. Valid options: Boolean. Default: 'true'.
+
+##### `default_mods`
+
+Determines whether to configure and enable a set of default [Apache modules][] depending on your operating system. Valid options: 'true', 'false', or an array of Apache module names. Default: 'true'.
+
+If this parameter's value is 'false', Puppet only includes the Apache modules required to make the HTTP daemon work on your operating system, and you can declare any other modules separately using the [`apache::mod::<MODULE NAME>`][] class or [`apache::mod`][] define.
+
+If 'true', Puppet installs additional modules, the list of which depends on the operating system as well as the [`apache_version`][] and [`mpm_module`][] parameters' values. As these lists of modules can change frequently, consult the [Puppet module's code][] for up-to-date lists.
+
+If this parameter contains an array, Puppet instead enables all passed Apache modules.
+
+##### `default_ssl_ca`
+
+Sets the default certificate authority for the Apache server. Default: 'undef'.
+
+While this default value results in a functioning Apache server, you **must** update this parameter with your certificate authority information before deploying this server in a production environment.
+
+##### `default_ssl_cert`
+
+Sets the [SSL encryption][] certificate location. Default: Determined by your operating system.
+
+- **Debian**: `/etc/ssl/certs/ssl-cert-snakeoil.pem`
+- **FreeBSD**: `/usr/local/etc/apache22/server.crt`
+- **Gentoo**: `/etc/ssl/apache2/server.crt`
+- **Red Hat**: `/etc/pki/tls/certs/localhost.crt`
+
+While the default value results in a functioning Apache server, you **must** update this parameter with your certificate location before deploying this server in a production environment.
+
+##### `default_ssl_chain`
+
+Sets the default [SSL chain][] location. Default: 'undef'.
+
+While this default value results in a functioning Apache server, you **must** update this parameter with your SSL chain before deploying this server in a production environment.
+
+##### `default_ssl_crl`
+
+Sets the path of the default [certificate revocation list][] (CRL) file to use. Default: 'undef'.
+
+While this default value results in a functioning Apache server, you **must** update this parameter with your CRL file's path before deploying this server in a production environment. You can use this parameter with or in place of the [`default_ssl_crl_path`][].
+
+##### `default_ssl_crl_path`
+
+Sets the server's [certificate revocation list path][], which contains your CRLs. Default: 'undef'.
+
+While this default value results in a functioning Apache server, you **must** update this parameter with the CRL path before deploying this server in a production environment.
+
+##### `default_ssl_crl_check`
+
+Sets the default certificate revocation check level via the [`SSLCARevocationCheck`][] directive. Default: 'undef'.
+
+While this default value results in a functioning Apache server, you **must** specify this parameter when using certificate revocation lists in a production environment.
+
+This parameter only applies to Apache 2.4 or higher and is ignored on older versions.
+
+##### `default_ssl_key`
+
+Sets the [SSL certificate key file][] location. Default: Determined by your operating system.
+
+- **Debian**: `/etc/ssl/private/ssl-cert-snakeoil.key`
+- **FreeBSD**: `/usr/local/etc/apache22/server.key`
+- **Gentoo**: `/etc/ssl/apache2/server.key`
+- **Red Hat**: `/etc/pki/tls/private/localhost.key`
+
+While these default values result in a functioning Apache server, you **must** update this parameter with your SSL key's location before deploying this server in a production environment.
+
+##### `default_ssl_vhost`
+
+Configures a default [SSL][SSL encryption] virtual host. Valid options: Boolean. Default: 'false'.
+
+If 'true', Puppet automatically configures the following virtual host using the [`apache::vhost`][] define:
+
+~~~ puppet
+apache::vhost { 'default-ssl':
+  port            => 443,
+  ssl             => true,
+  docroot         => $docroot,
+  scriptalias     => $scriptalias,
+  serveradmin     => $serveradmin,
+  access_log_file => "ssl_${access_log_file}",
+  }
+~~~
+
+**Note**: SSL virtual hosts only respond to HTTPS queries.
+
+##### `default_type`
+
+_Apache 2.2 only_. Sets the [MIME `content-type`][] sent if the server cannot otherwise determine an appropriate `content-type`. This directive is deprecated in Apache 2.4 and newer and only exists for backwards compatibility in configuration files. Default: 'undef'.
+
+##### `default_vhost`
+
+Configures a default virtual host when the class is declared. Valid options: Boolean. Default: 'true'.
+
+To configure [customized virtual hosts][Configuring virtual hosts], set this parameter's value to 'false'.
+
+##### `dev_packages`
+
+Configures a specific dev package to use. Valid options: String.  Default: 'OS default httpd dev package'.
+
+Example for using httpd 2.4 from the IUS yum repo:
+
+~~~ puppet
+include ::apache::dev
+class { 'apache':
+  apache_name  => 'httpd24u',
+  dev_packages => 'httpd24u-devel',
+}
+~~~
+
+##### `docroot`
+
+Sets the default [`DocumentRoot`][] location. Default: Determined by your operating system.
+
+- **Debian**: `/var/www/html`
+- **FreeBSD**: `/usr/local/www/apache22/data`
+- **Gentoo**: `/var/www/localhost/htdocs`
+- **Red Hat**: `/var/www/html`
+
+##### `error_documents`
+
+Determines whether to enable [custom error documents][] on the Apache server. Valid options: Boolean. Default: 'false'.
+
+##### `group`
+
+Sets the group ID that owns any Apache processes spawned to answer requests.
+
+By default, Puppet attempts to manage this group as a resource under the `apache` class, determining the group based on the operating system as detected by the [`apache::params`][] class. To to prevent the group resource from being created and use a group created by another Puppet module, set the [`manage_group`][] parameter's value to 'false'.
+
+**Note**: Modifying this parameter only changes the group ID that Apache uses to spawn child processes to access resources. It does not change the user that owns the parent server process.
+
+##### `httpd_dir`
+
+Sets the Apache server's base configuration directory. This is useful for specially repackaged Apache server builds but might have unintended consequences when combined with the default distribution packages. Default: Determined by your operating system.
+
+- **Debian**: `/etc/apache2`
+- **FreeBSD**: `/usr/local/etc/apache22`
+- **Gentoo**: `/etc/apache2`
+- **Red Hat**: `/etc/httpd`
+
+##### `keepalive`
+
+Determines whether to enable persistent HTTP connections with the [`KeepAlive`][] directive. Valid options: 'Off', 'On'. Default: 'Off'.
+
+If 'On', use the [`keepalive_timeout`][] and [`max_keepalive_requests`][] parameters to set relevant options.
+
+##### `keepalive_timeout`
+
+Sets the [`KeepAliveTimeout`] directive, which determines the amount of time the Apache server waits for subsequent requests on a persistent HTTP connection. Default: '15'.
+
+This parameter is only relevant if the [`keepalive` parameter][] is enabled.
+
+##### `max_keepalive_requests`
+
+Limits the number of requests allowed per connection when the [`keepalive` parameter][] is enabled. Default: '100'.
+
+##### `lib_path`
+
+Specifies the location where [Apache module][Apache modules] files are stored. Default: Depends on the operating system.
+
+- **Debian** and **Gentoo**: `/usr/lib/apache2/modules`
+- **FreeBSD**: `/usr/local/libexec/apache24`
+- **Red Hat**: `modules`
+
+**Note**: Do not configure this parameter manually without special reason.
+
+##### `loadfile_name`
+
+Sets the [`LoadFile`] directive's filename. Valid options: Filenames in the format `\*.load`.
+
+This can be used to set the module load order.
+
+##### `log_level`
+
+Changes the error log's verbosity. Valid options: 'alert', 'crit', 'debug', 'emerg', 'error', 'info', 'notice', 'warn'. Default: 'warn'.
+
+##### `log_formats`
+
+Define additional [`LogFormat`][] directives. Valid options: A [Hash][], such as:
+
+~~~ puppet
+$log_formats = { vhost_common => '%v %h %l %u %t \"%r\" %>s %b' }
+~~~
+
+There are a number of predefined `LogFormats` in the `httpd.conf` that Puppet creates:
+
+~~~ httpd
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+~~~
+
+If your `log_formats` parameter contains one of those, it will be overwritten with **your** definition.
+
+##### `logroot`
+
+Changes the directory of Apache log files for the virtual host. Default: Determined by your operating system.
+
+- **Debian**: `/var/log/apache2`
+- **FreeBSD**: `/var/log/apache22`
+- **Gentoo**: `/var/log/apache2`
+- **Red Hat**: `/var/log/httpd`
+
+##### `logroot_mode`
+
+Overrides the default [`logroot`][] directory's mode. Default: 'undef'.
+
+**Note**: Do _not_ grant write access to the directory where the logs are stored without being aware of the consequences. See the [Apache documentation][Log security] for details.
+
+##### `manage_group`
+
+When 'false', stops Puppet from creating the group resource. Valid options: Boolean. Default: 'true'.
+
+If you have a group created from another Puppet module that you want to use to run Apache, set this to 'false'. Without this parameter, attempting to use a previously established group results in a duplicate resource error.
+
+##### `manage_user`
+
+When 'false', stops Puppet from creating the user resource. Valid options: Boolean. Default: 'true'.
+
+This is for instances when you have a user, created from another Puppet module, you want to use to run Apache. Without this parameter, attempting to use a previously established user would result in a duplicate resource error.
+
+##### `mod_dir`
+
+Sets where Puppet places configuration files for your [Apache modules][]. Default: Determined by your operating system.
+
+- **Debian**: `/etc/apache2/mods-available`
+- **FreeBSD**: `/usr/local/etc/apache22/Modules`
+- **Gentoo**: `/etc/apache2/modules.d`
+- **Red Hat**: `/etc/httpd/conf.d`
+
+##### `mpm_module`
+
+Determines which [multi-processing module][] (MPM) is loaded and configured for the HTTPD process. Valid options: 'event', 'itk', 'peruser', 'prefork', 'worker', or 'false'. Default: Determined by your operating system.
+
+- **Debian**: `worker`
+- **FreeBSD, Gentoo, and Red Hat**: `prefork`
+
+You must set this to 'false' to explicitly declare the following classes with custom parameters:
+
+- [`apache::mod::event`][]
+- [`apache::mod::itk`][]
+- [`apache::mod::peruser`][]
+- [`apache::mod::prefork`][]
+- [`apache::mod::worker`][]
+
+**Note**: Switching between different MPMs on FreeBSD is possible but quite difficult. Before changing `mpm_module`, you must uninstall all packages that depend on your installed Apache server.
+
+##### `package_ensure`
+
+Controls the `package` resource's [`ensure`][] attribute. Valid options: 'absent', 'installed' (or the equivalent 'present'), or a version string. Default: 'installed'.
+
+##### `pidfile`
+
+Allows settting a custom location for the pid file - useful if using a custom built Apache rpm. Defaults to 'run/httpd.pid' on RedHat, '/var/run/httpd.pid on FreeBSD and '\${APACHE_PID_FILE}' on Debian.
+
+##### `ports_file`
+
+Sets the path to the file containing Apache ports configuration. Default: `{$conf_dir}/ports.conf`.
+
+##### `purge_configs`
+
+Removes all other Apache configs and virtual hosts. Valid options: Boolean. Default: 'true'.
+
+Setting this to 'false' is a stopgap measure to allow the apache Puppet module to coexist with existing or unmanaged configurations. We recommend moving your configuration to resources within this module. For virtual host configurations, see [`purge_vhost_dir`][].
+
+##### `purge_vhost_dir`
+
+If the [`vhost_dir`][] parameter's value differs from the [`confd_dir`][] parameter's, the Boolean parameter `purge_vhost_dir` determines whether Puppet removes any configurations inside `vhost_dir` _not_ managed by Puppet. Default: same as [`purge_configs`][].
+
+Setting `purge_vhost_dir` to 'false' is a stopgap measure to allow the apache Puppet module to coexist with existing or otherwise unmanaged configurations within `vhost_dir`.
+
+##### `rewrite_lock`
+
+Allows setting a custom location for a rewrite lock - considered best practice if using a RewriteMap of type prg in the [`rewrites`][] parameter of your vhost. Default: 'undef'.
+
+This parameter only applies to Apache version 2.2 or lower and is ignored on newer versions.
+
+##### `sendfile`
+
+Forces Apache to use the Linux kernel's `sendfile` support to serve static files, via the [`EnableSendfile`][] directive. Valid options: 'On', 'Off'. Default: 'On'.
+
+##### `serveradmin`
+
+Sets the Apache server administrator's contact information via Apache's [`ServerAdmin`][] directive. Default: 'root@localhost'.
+
+##### `servername`
+
+Sets the Apache server name via Apache's [`ServerName`][] directive. Default: the 'fqdn' fact reported by [Facter][].
+
+##### `server_root`
+
+Sets the Apache server's root directory via Apache's [`ServerRoot`][] directive. Default: determined by your operating system.
+
+- **Debian**: `/etc/apache2`
+- **FreeBSD**: `/usr/local`
+- **Gentoo**: `/var/www`
+- **Red Hat**: `/etc/httpd`
+
+##### `server_signature`
+
+Configures a trailing footer line to display at the bottom of server-generated documents, such as error documents and output of certain [Apache modules][], via Apache's [`ServerSignature`][] directive. Valid options: 'Off', 'On'. Default: 'On'.
+
+##### `server_tokens`
+
+Controls how much information Apache sends to the browser about itself and the operating system, via Apache's [`ServerTokens`][] directive. Defaults to 'OS'.
+
+##### `service_enable`
+
+Determines whether Puppet enables the Apache HTTPD service when the system is booted. Valid options: Boolean. Default: 'true'.
+
+##### `service_ensure`
+
+Determines whether Puppet should make sure the service is running. Valid options: 'true' (equivalent to 'running'), 'false' (equivalent to 'stopped'). Default: 'running'.
+
+The 'false' or 'stopped' values set the 'httpd' service resource's `ensure` parameter to 'false', which is useful when you want to let the service be managed by another application, such as Pacemaker.
+
+##### `service_name`
+
+Sets the name of the Apache service. Default: determined by your operating system.
+
+- **Debian and Gentoo**: `apache2`
+- **FreeBSD**: `apache22`
+- **Red Hat**: `httpd`
+
+##### `service_manage`
+
+Determines whether Puppet manages the HTTPD service's state. Default: 'true'.
+
+##### `service_restart`
+
+Determines whether Puppet should use a specific command to restart the HTTPD service. Valid options: a command to restart the Apache service. Default: 'undef', which uses the [default Puppet behavior][Service attribute restart].
+
+##### `timeout`
+
+Sets Apache's [`TimeOut`][] directive, which defines the number of seconds Apache waits for certain events before failing a request. Defaults to 120.
+
+##### `trace_enable`
+
+Controls how Apache handles `TRACE` requests (per [RFC 2616][]) via the [`TraceEnable`][] directive. Valid options: 'Off', 'On'. Default: 'On'.
+
+##### `use_systemd`
+
+Controls whether the systemd module should be installed on Centos 7 servers, this is especially useful if using custom built rpms. This can either be 'true' or 'false, defaults to 'true'.
+
+##### `vhost_dir`
+
+Changes your virtual host configuration files' location. Default: determined by your operating system.
+
+- **Debian**: `/etc/apache2/sites-available`
+- **FreeBSD**: `/usr/local/etc/apache22/Vhosts`
+- **Gentoo**: `/etc/apache2/vhosts.d`
+- **Red Hat**: `/etc/httpd/conf.d`
+
+##### `vhost_include_pattern`
+
+Defines the pattern for files included from the `vhost_dir`. This defaults to '*', also for BC with previous versions of this module.
+
+However, you may want to set this to a value like '[^.#]\*.conf[^~]' to make sure files accidentally created in this directory (from version
+control systems, editor backups or the like) are *not* included in your server configuration.
+
+A value of '*.conf' is what is shipped by some operating systems. Also note that this module will, by default, create config files ending
+in '.conf'.
+
+##### `user`
+
+Changes the user Apache uses to answer requests. Apache's parent process will continue to be run as root, but child processes will access resources as the user defined by this parameter.
+
+Default: Puppet sets the default value via the [`apache::params`][] class, which manages the user based on your operating system:
+
+- **Debian**: 'www-data'
+- **FreeBSD**: 'www'
+- **Gentoo** and **Red Hat**: 'apache'
+
+To prevent Puppet from managing the user, set the [`manage_user`][] parameter to 'false'.
+
+##### `apache_name`
+
+The name of the Apache package to install. Default: Puppet sets the default value via the [`apache::params`][] class, which manages the user based on your operating system:
+
+The default value is determined by your operating system:
+
+- **Debian**: 'apache2'
+- **FreeBSD**: 'apache24'
+- **Gentoo**: 'www-servers/apache'
+- **Red Hat**: 'httpd'
+
+You might need to override this if you are using a non-standard Apache package, such as those from Red Hat's software collections.
+
+#### Class: `apache::dev`
+
+Installs Apache development libraries. By default, the package name is defined by the [`dev_packages`][] parameter of the [`apache::params`][] class based on your operating system:
+
+The default value is determined by your operating system:
+
+- **Debian** : 'libaprutil1-dev', 'libapr1-dev'; 'apache2-dev' on Ubuntu 13.10 and Debian 8; 'apache2-prefork-dev' on other versions
+- **FreeBSD**: 'undef'; see note below
+- **Gentoo**: 'undef'
+- **Red Hat**: 'httpd-devel'
+
+**Note**: On FreeBSD, you must declare the `apache::package` or `apache` classes before declaring `apache::dev`.
+
+#### Classes: `apache::mod::<MODULE NAME>`
+
+Enables specific [Apache modules][]. You can enable and configure an Apache module by declaring its class. For example, to install and enable [`mod_alias`][] with no icons, you can declare the [`apache::mod::alias`][] class with the `icons_options` parameter set to 'None':
+
+~~~ puppet
+class { 'apache::mod::alias':
+  icons_options => 'None',
+}
+~~~
+
+The following Apache modules have supported classes, many of which allow for parameterized configuration. You can install other Apache modules with the [`apache::mod`][] define.
+
+* `actions`
+* `alias` (see [`apache::mod::alias`][])
+* `auth_basic`
+* `auth_cas`* (see [`apache::mod::auth_cas`][])
+* `auth_mellon`* (see [`apache::mod::auth_mellon`][])
+* `auth_kerb`
+* `authn_core`
+* `authn_file`
+* `authnz_ldap`*
+* `authz_default`
+* `authz_user`
+* `autoindex`
+* `cache`
+* `cgi`
+* `cgid`
+* `dav`
+* `dav_fs`
+* `dav_svn`*
+* `deflate`
+* `dev`
+* `dir`*
+* `disk_cache` (see [`apache::mod::disk_cache`][])
+* `event` (see [`apache::mod::event`][])
+* `expires`
+* `ext_filter` (see [`apache::mod::ext_filter`][])
+* `fastcgi`
+* `fcgid`
+* `filter`
+* `geoip` (see [`apache::mod::geoip`][])
+* `headers`
+* `include`
+* `info`*
+* `itk`
+* `ldap`
+* `mime`
+* `mime_magic`*
+* `negotiation`
+* `nss`*
+* `pagespeed` (see [`apache::mod::pagespeed`][])
+* `passenger`*
+* `perl`
+* `peruser`
+* `php` (requires [`mpm_module`][] set to `prefork`)
+* `prefork`*
+* `proxy`*
+* `proxy_ajp`
+* `proxy_balancer`
+* `proxy_html`
+* `proxy_http`
+* `python`
+* `reqtimeout`
+* `remoteip`*
+* `rewrite`
+* `rpaf`*
+* `setenvif`
+* `security`
+* `shib`* (see [`apache::mod::shib`])
+* `speling`
+* `ssl`* (see [`apache::mod::ssl`][])
+* `status`* (see [`apache::mod::status`][])
+* `suphp`
+* `userdir`*
+* `version`
+* `vhost_alias`
+* `worker`*
+* `wsgi` (see [`apache::mod::wsgi`][])
+* `xsendfile`
+
+Modules noted with a * indicate that the module has settings and a template that includes parameters to configure the module. Most Apache module class parameters have default values and don't require configuration. For modules with templates, Puppet installs template files with the module; these template files are required for the module to work.
+
+##### Class: `apache::mod::alias`
+
+Installs and manages [`mod_alias`][].
+
+**Parameters within `apache::mod::alias`**:
+
+* `icons_options`: Disables directory listings for the icons directory, via Apache [`Options`] directive. Default: 'Indexes MultiViews'.
+* `icons_path`: Sets the local path for an `/icons/` Alias. Default: depends on your operating system.
+
+- **Debian**: `/usr/share/apache2/icons`
+- **FreeBSD**: `/usr/local/www/apache24/icons`
+- **Gentoo**: `/var/www/icons`
+- **Red Hat**: `/var/www/icons`, except on Apache 2.4, where it's `/usr/share/httpd/icons`
+
+#### Class: `apache::mod::disk_cache`
+
+Installs and configures [`mod_disk_cache`][] on Apache 2.2, or [`mod_cache_disk`][] on Apache 2.4. The default cache root depends on the Apache version and operating system: 
+
+- **Debian**: `/var/cache/apache2/mod_cache_disk`
+- **FreeBSD**: `/var/cache/mod_cache_disk`
+- **Red Hat, Apache 2.4**: `/var/cache/httpd/proxy`
+- **Red Hat, Apache 2.2**: `/var/cache/mod_proxy`
+
+You can specify the cache root by passing a path as a string to the `cache_root` parameter.
+
+~~~ puppet
+class {'::apache::mod::disk_cache':
+  cache_root => '/path/to/cache',
+}
+~~~
+
+##### Class: `apache::mod::event`
+
+Installs and manages [`mod_mpm_event`][]. You can't include both `apache::mod::event` and [`apache::mod::itk`][], [`apache::mod::peruser`][], [`apache::mod::prefork`][], or [`apache::mod::worker`][] on the same server.
+
+**Parameters within `apache::mod::event`**:
+
+- `listenbacklog`: Sets the maximum length of the pending connections queue via the module's [`ListenBackLog`][] directive. Default: '511'.
+- `maxclients` (_Apache 2.3.12 or older_: `maxrequestworkers`): Sets the maximum number of connections Apache can simultaneously process, via the module's [`MaxRequestWorkers`][] directive. Default: '150'.
+- `maxconnectionsperchild` (_Apache 2.3.8 or older_: `maxrequestsperchild`): Limits the number of connections a child server handles during its life, via the module's [`MaxConnectionsPerChild`][] directive. Default: '0'.
+- `maxsparethreads` and `minsparethreads`: Sets the maximum and minimum number of idle threads, via the [`MaxSpareThreads`][] and [`MinSpareThreads`][] directives. Default: '75' and '25', respectively.
+- `serverlimit`: Limits the configurable number of processes via the [`ServerLimit`][] directive. Default: '25'.
+- `startservers`: Sets the number of child server processes created at startup, via the module's [`StartServers`][] directive. Default: '2'.
+- `threadlimit`: Limits the number of event threads via the module's [`ThreadLimit`][] directive. Default: '64'.
+- `threadsperchild`: Sets the number of threads created by each child process, via the [`ThreadsPerChild`][] directive. Default: '25'.
+
+##### Class: `apache::mod::auth_cas`
+
+Installs and manages [`mod_auth_cas`][]. Its parameters share names with the Apache module's directives.
+
+The `cas_login_url` and `cas_validate_url` parameters are required; several other parameters have 'undef' default values.
+
+**Parameters within `apache::mod::auth_cas`**:
+
+- `cas_authoritative`: Determines whether an optional authorization directive is authoritative and binding. Default: 'undef'.
+- `cas_certificate_path`: Sets the path to the X509 certificate of the Certificate Authority for the server in `cas_login_url` and `cas_validate_url`. Default: 'undef'.
+- `cas_cache_clean_interval`: Sets the minimum number of seconds that must pass between cache cleanings. Default: 'undef'.
+- `cas_cookie_domain`: Sets the value of the `Domain=` parameter in the `Set-Cookie` HTTP header. Default: 'undef'.
+- `cas_cookie_entropy`: Sets the number of bytes to use when creating session identifiers. Default: 'undef'.
+- `cas_cookie_http_only`: Sets the optional `HttpOnly` flag when `mod_auth_cas` issues cookies. Default: 'undef'.
+- `cas_debug`: Determines whether to enable the module's debugging mode. Default: 'Off'.
+- `cas_idle_timeout`: Default: 'undef'.
+- `cas_login_url`: **Required**. Sets the URL to which the module redirects users when they attempt to access a CAS-protected resource and don't have an active session.
+- `cas_root_proxied_as`: Sets the URL end users see when access to this Apache server is proxied. Default: 'undef'.
+- `cas_timeout`: Limits the number of seconds a `mod_auth_cas` session can remain active. Default: 'undef'.
+- `cas_validate_depth`: Limits the depth for chained certificate validation. Default: 'undef'.
+- `cas_validate_url`: **Required**. Sets the URL to use when validating a client-presented ticket in an HTTP query string.
+- `cas_version`: The CAS protocol version to adhere to. Valid options: '1', '2'. Default: '2'.
+
+##### Class: `apache::mod::auth_mellon`
+
+Installs and manages [`mod_auth_mellon`][]. Its parameters share names with the Apache module's directives.
+
+~~~ puppet
+class{ 'apache::mod::auth_mellon':
+  mellon_cache_size => 101,
+}
+~~~
+
+**Parameters within `apache::mod::auth_mellon`**:
+
+- `mellon_cache_entry_size`: Maximum size for a single session. Default: 'undef'.
+- `mellon_cache_size`: Size in megabytes of the mellon cache. Default: 100.
+- `mellon_lock_file`: Location of lock file. Default: '`/run/mod_auth_mellon/lock`'.
+- `mellon_post_directory`: Full path where post requests are saved. Default: '`/var/cache/apache2/mod_auth_mellon/`'
+- `mellon_post_ttl`: Time to keep post requests. Default: 'undef'.
+- `mellon_post_size`: Maximum size of post requests. Default: 'undef'.
+- `mellon_post_count`: Maximum number of post requests. Default: 'undef'.
+
+##### Class: `apache::mod::deflate`
+
+Installs and configures [`mod_deflate`][].
+
+**Parameters within `apache::mod::deflate`**:
+
+- `types`: An [array][] of [MIME types][MIME `content-type`] to be deflated. Default: [ 'text/html text/plain text/xml', 'text/css', 'application/x-javascript application/javascript application/ecmascript', 'application/rss+xml', 'application/json' ].
+- `notes`: A [Hash][] where the key represents the type and the value represents the note name. Default: { 'Input'  => 'instream', 'Output' => 'outstream', 'Ratio'  => 'ratio' }
+
+##### Class: `apache::mod::expires`
+
+Installs [`mod_expires`][] and uses the `expires.conf.erb` template to generate its configuration.
+
+**Parameters within `apache::mod::expires`**:
+
+- `expires_active`: Enables generation of `Expires` headers for a document realm. Default: 'true'.
+- `expires_default`: Default algorithm for calculating expiration time using [`ExpiresByType`][] syntax or [interval syntax][]. Default: undef.
+- `expires_by_type`: Describes a set of [MIME `content-type`][] and their expiration times. Valid options: An [array][] of [Hashes][Hash], with each Hash's key a valid MIME `content-type` (i.e. 'text/json') and its value following valid [interval syntax][]. Default: undef.
+
+##### Class: `apache::mod::ext_filter`
+
+Installs and configures [`mod_ext_filter`][].
+
+~~~ puppet
+class { 'apache::mod::ext_filter':
+  ext_filter_define => {
+    'slowdown'       => 'mode=output cmd=/bin/cat preservescontentlength',
+    'puppetdb-strip' => 'mode=output outtype=application/json cmd="pdb-resource-filter"',
+  },
+}
+~~~
+
+**Parameters within `apache::mod::ext_filter`**:
+
+- `ext_filter_define`: A hash of filter names and their parameters. Default: undef.
+
+##### Class: `apache::mod::fcgid`
+
+Installs and configures [`mod_fcgid`][].
+
+The class makes no effort to individually parameterize all available options. Instead, configure `mod_fcgid` using the `options` [hash][]. For example:
+
+~~~ puppet
+class { 'apache::mod::fcgid':
+  options => {
+    'FcgidIPCDir'  => '/var/run/fcgidsock',
+    'SharememPath' => '/var/run/fcgid_shm',
+    'AddHandler'   => 'fcgid-script .fcgi',
+  },
+}
+~~~
+
+For a full list of options, see the [official `mod_fcgid` documentation][`mod_fcgid`].
+
+If you include `apache::mod::fcgid`, you can set the [`FcgidWrapper`][] per directory, per virtual host. The module must be loaded first; Puppet will not automatically enable it if you set the `fcgiwrapper` parameter in `apache::vhost`.
+
+~~~ puppet
+include apache::mod::fcgid
+
+apache::vhost { 'example.org':
+  docroot     => '/var/www/html',
+  directories => {
+    path        => '/var/www/html',
+    fcgiwrapper => {
+      command => '/usr/local/bin/fcgiwrapper',
+    }
+  },
+}
+~~~
+
+##### Class: `apache::mod::geoip`
+
+Installs and manages [`mod_geoip`][].
+
+**Parameters within `apache::mod::geoip`**:
+
+- `db_file`: Sets the path to your GeoIP database file. Valid options: a path, or an [array][] paths for multiple GeoIP database files. Default: `/usr/share/GeoIP/GeoIP.dat`.
+- `enable`: Determines whether to globally enable [`mod_geoip`][]. Valid options: Boolean. Default: 'false'.
+- `flag`: Sets the GeoIP flag. Valid options: 'CheckCache', 'IndexCache', 'MemoryCache', 'Standard'. Default: 'Standard'.
+- `output`: Defines which output variables to use. Valid options: 'All', 'Env', 'Request', 'Notes'. Default: 'All'.
+- `enable_utf8`: Changes the output from ISO-8859-1 (Latin-1) to UTF-8. Valid options: Boolean. Default: 'undef'.
+- `scan_proxy_headers`: Enables the [GeoIPScanProxyHeaders][] option. Valid options: Boolean. Default: 'undef'.
+- `scan_proxy_header_field`: Specifies which header [`mod_geoip`][] should look at to determine the client's IP address. Default: 'undef'.
+- `use_last_xforwarededfor_ip` (sic): Determines whether to use the first or last IP address for the client's IP if a comma-separated list of IP addresses is found. Valid options: Boolean. Default: 'undef'.
+
+##### Class: `apache::mod::info`
+
+Installs and manages [`mod_info`][], which provides a comprehensive overview of the server configuration.
+
+**Parameters within `apache::mod::info`**:
+
+- `allow_from`: Whitelist of IPv4 or IPv6 addresses or ranges that can access `/server-info`. Valid options: One or more octets of an IPv4 address, an IPv6 address or range, or an array of either. Default: ['127.0.0.1','::1']
+- `apache_version`: Default: `$::apache::apache_version`,
+- `restrict_access`: Determines whether to enable access restrictions. If 'false', the `allow_from` whitelist is ignored and any IP address can access `/server-info`. Valid options: Boolean. Default: 'true'.
+
+##### Class: `apache::mod::negotiation`
+
+Installs and configures [`mod_negotiation`][].
+
+**Parameters within `apache::mod::negotiation`:**
+
+- `force_language_priority`: Sets the `ForceLanguagePriority` option. Valid option: String. Default: `Prefer Fallback`.
+- `language_priority`: An [array][] of languages to set the `LanguagePriority` option of the module. Default: [ 'en', 'ca', 'cs', 'da', 'de', 'el', 'eo', 'es', 'et', 'fr', 'he', 'hr', 'it', 'ja', 'ko', 'ltz', 'nl', 'nn', 'no', 'pl', 'pt', 'pt-BR', 'ru', 'sv', 'zh-CN', 'zh-TW' ]
+
+##### Class: `apache::mod::pagespeed`
+
+Installs and manages [`mod_pagespeed`], a Google module that rewrites web pages to reduce latency and bandwidth.
+
+While this Apache module requires the `mod-pagespeed-stable` package, Puppet **doesn't** manage the software repositories required to automatically install the package. If you declare this class when the package is either not installed or not available to your package manager, your Puppet run will fail.
+
+**Parameters within `apache::mod::info`**:
+
+- `inherit_vhost_config`: Default: 'on'.
+- `filter_xhtml`: Default: false.
+- `cache_path`: Default: '/var/cache/mod_pagespeed/'.
+- `log_dir`: Default: '/var/log/pagespeed'.
+- `memcache_servers`: Default: [].
+- `rewrite_level`: Default: 'CoreFilters'.
+- `disable_filters`: Default: [].
+- `enable_filters`: Default: [].
+- `forbid_filters`: Default: [].
+- `rewrite_deadline_per_flush_ms`: Default: 10.
+- `additional_domains`: Default: undef.
+- `file_cache_size_kb`: Default: 102400.
+- `file_cache_clean_interval_ms`: Default: 3600000.
+- `lru_cache_per_process`: Default: 1024.
+- `lru_cache_byte_limit`: Default: 16384.
+- `css_flatten_max_bytes`: Default: 2048.
+- `css_inline_max_bytes`: Default: 2048.
+- `css_image_inline_max_bytes`: Default: 2048.
+- `image_inline_max_bytes`: Default: 2048.
+- `js_inline_max_bytes`: Default: 2048.
+- `css_outline_min_bytes`: Default: 3000.
+- `js_outline_min_bytes`: Default: 3000.
+- `inode_limit`: Default: 500000.
+- `image_max_rewrites_at_once`: Default: 8.
+- `num_rewrite_threads`: Default: 4.
+- `num_expensive_rewrite_threads`: Default: 4.
+- `collect_statistics`: Default: 'on'.
+- `statistics_logging`: Default: 'on'.
+- `allow_view_stats`: Default: [].
+- `allow_pagespeed_console`: Default: [].
+- `allow_pagespeed_message`: Default: [].
+- `message_buffer_size`: Default: 100000.
+- `additional_configuration`: Default: { }.
+
+The class's parameters correspond to the module's directives. See the [module's documentation][`mod_pagespeed`] for details.
+
+##### Class: `apache::mod::php`
+
+Installs and configures [`mod_php`][].
+
+**Parameters within `apache::mod::php`**:
+
+Default values depend on your operating system.
+
+> **Note**: This list is incomplete. Most of this class's parameters correspond to `mod_php` directives; see the [module's documentation][`mod_php`] for details.
+
+- `package_name`: Names the package that installs `php_mod`.
+- `path`: Defines the path to the `mod_php` shared object (`.so`) file.
+- `source`: Defines the path to the default configuration. Valid options include a `puppet:///` path.
+- `template`: Defines the path to the `php.conf` template Puppet uses to generate the configuration file.
+- `content`: Adds arbitrary content to `php.conf`.
+
+##### Class: `apache::mod::reqtimeout`
+
+Installs and configures [`mod_reqtimeout`][].
+
+**Parameters within `apache::mod::reqtimeout`**:
+
+- `timeouts`: A string or [array][] that sets the [`RequestReadTimeout`][] option. Default: ['header=20-40,MinRate=500', 'body=20,MinRate=500'].
+
+##### Class: `apache::mod::shib`
+
+Installs the [Shibboleth](http://shibboleth.net/) Apache module `mod_shib`, which enables SAML2 single sign-on (SSO) authentication by Shibboleth Identity Providers and Shibboleth Federations. This class only installs and configures the Apache components of a web application that consumes Shibboleth SSO identities, also known as a Shibboleth Service Provider. You can manage the Shibboleth configuration manually, with Puppet, or using a [Shibboleth Puppet Module](https://github.com/aethylred/puppet-shibboleth).
+
+Defining this class enables Shibboleth-specific parameters in `apache::vhost` instances.
+
+##### Class: `apache::mod::ssl`
+
+Installs [Apache SSL features][`mod_ssl`] and uses the `ssl.conf.erb` template to generate its configuration.
+
+**Parameters within `apache::mod::ssl`**:
+
+- `ssl_cipher`: Default: 'HIGH:MEDIUM:!aNULL:!MD5:!RC4'.
+- `ssl_compression`: Default: 'false'.
+- `ssl_cryptodevice`: Default: 'builtin'.
+- `ssl_honorcipherorder`: Default: 'On'.
+- `ssl_openssl_conf_cmd`: Default: 'undef'.
+- `ssl_options`: Default: [ 'StdEnvVars' ]
+- `ssl_pass_phrase_dialog`: Default: 'builtin'.
+- `ssl_protocol`: Default: [ 'all', '-SSLv2', '-SSLv3' ].
+- `ssl_random_seed_bytes`: Default: '512'.
+- `ssl_sessioncachetimeout`: Default: '300'.
+
+To use SSL with a virtual host, you must either set the [`default_ssl_vhost`][] parameter in `::apache` to 'true' **o**r the [`ssl`][] parameter in [`apache::vhost`][] to 'true'.
+
+##### Class: `apache::mod::status`
+
+Installs [`mod_status`][] and uses the `status.conf.erb` template to generate its configuration.
+
+**Parameters within `apache::mod::status`**:
+
+- `allow_from`: An [array][] of IPv4 or IPv6 addresses that can access `/server-status`. Default: ['127.0.0.1','::1'].
+- `extended_status`: Determines whether to track extended status information for each request, via the [`ExtendedStatus`][] directive. Valid options: 'Off', 'On'. Default: 'On'.
+- `status_path`: The server location of the status page. Default: '/server-status'.
+
+##### Class: `apache::mod::version`
+
+Installs [`mod_version`][] on many operating systems and Apache configurations.
+
+If Debian and Ubuntu systems with Apache 2.4 are classified with `apache::mod::version`, Puppet warns that `mod_version` is built-in and can't be loaded.
+
+##### Class: `apache::mod::security`
+
+Installs and configures Trustwave's [`mod_security`][]. It is enabled and runs by default on all virtual hosts.
+
+**Parameters within `apache::mod::security`**:
+
+- `activated_rules`: An [array][] of rules from the `modsec_crs_path` to activate via symlinks. Default: `modsec_default_rules` in [`apache::params`][].
+- `allowed_methods`: A space-separated list of allowed HTTP methods. Default: 'GET HEAD POST OPTIONS'.
+- `content_types`: A list of one or more allowed [MIME types][MIME `content-type`]. Default: 'application/x-www-form-urlencoded|multipart/form-data|text/xml|application/xml|application/x-amf'
+- `crs_package`: Names the package that installs CRS rules. Default: `modsec_crs_package` in [`apache::params`][].
+- `modsec_dir`: Defines the path where Puppet installs the modsec configuration and activated rules links. Default: 'On', set by `modsec_dir` in [`apache::params`][].
+${modsec_dir}/activated_rules.
+- `modsec_secruleengine`: Configures the modsec rules engine. Valid options: 'On', 'Off', and 'DetectionOnly'. Default: `modsec_secruleengine` in [`apache::params`][].
+- `restricted_extensions`: A space-separated list of prohibited file extensions. Default: '.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .resources/ .resx/ .sql/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'.
+- `restricted_headers`: A list of restricted headers separated by slashes and spaces. Default: 'Proxy-Connection/ /Lock-Token/ /Content-Range/ /Translate/ /via/ /if/'.
+
+##### Class: `apache::mod::wsgi`
+
+Enables Python support via [`mod_wsgi`][].
+
+**Parameters within `apache::mod::wsgi`**:
+
+- `mod_path`: Defines the path to the `mod_wsgi` shared object (`.so`) file. Default: undef.
+  - If the `mod_path` parameter doesn't contain `/`, Puppet prefixes it with your operating system's default module path.
+Otherwise, Puppet follows it literally.
+- `package_name`: Names the package that installs `mod_wsgi`. Default: undef.
+- `wsgi_python_home`: Defines the [`WSGIPythonHome`][] directive, such as '/path/to/venv'. Valid options: path. Default: undef.
+- `wsgi_python_path`: Defines the [`WSGIPythonPath`][] directive, such as '/path/to/venv/site-packages'. Valid options: path. Default: undef.
+- `wsgi_socket_prefix`: Defines the [`WSGISocketPrefix`][] directive, such as "\${APACHE_RUN_DIR}WSGI". Default: `wsgi_socket_prefix` in [`apache::params`][].
+
+The class's parameters correspond to the module's directives. See the [module's documentation][`mod_wsgi`] for details.
+
+### Private Classes
+
+#### Class: `apache::confd::no_accf`
+
+Creates the `no-accf.conf` configuration file in `conf.d`, required by FreeBSD's Apache 2.4.
+
+#### Class: `apache::default_confd_files`
+
+Includes `conf.d` files for FreeBSD.
+
+#### Class: `apache::default_mods`
+
+Installs the Apache modules required to run the default configuration. See the `apache` class's [`default_mods`][] parameter for details.
+
+#### Class: `apache::package`
+
+Installs and configures basic Apache packages.
+
+#### Class: `apache::params`
+
+Manages Apache parameters for different operating systems.
+
+#### Class: `apache::service`
+
+Manages the Apache daemon.
+
+#### Class: `apache::version`
+
+Attempts to automatically detect the Apache version based on the operating system.
+
+### Public Defines
+
+#### Define: `apache::balancer`
+
+Creates an Apache load balancing group, also known as a balancer cluster, using [`mod_proxy`][]. Each load balancing group needs one or more balancer members, which you can declare in Puppet with the  [`apache::balancermember`][] define.
+
+Declare one `apache::balancer` define for each Apache load balancing group. You can export `apache::balancermember` defines for all balancer members and collect them on a single Apache load balancer server using [exported resources][].
+
+**Parameters within `apache::balancer`**:
+
+##### `name`
+
+Sets the title of the balancer cluster and name of the `conf.d` file containing its configuration.
+
+##### `proxy_set`
+
+Configures key-value pairs as [`ProxySet`][] lines. Valid options: [Hash][]. Default: '{}'.
+
+##### `collect_exported`
+
+Determines whether to use [exported resources][]. Valid options: Boolean. Default: 'true'.
+
+If you statically declare all of your backend servers, set this parameter to 'false' to rely on existing, declared balancer member resources. Also, use `apache::balancermember` with [array][] arguments.
+
+To dynamically declare backend servers via exported resources collected on a central node, set this parameter to 'true' to collect the balancer member resources exported by the balancer member nodes.
+
+If you don't use exported resources, a single Puppet run configures all balancer members. If you use exported resources, Puppet has to run on the balanced nodes first, then run on the balancer.
+
+#### Define: `apache::balancermember`
+
+Defines members of [`mod_proxy_balancer`][], which sets up a balancer member inside a listening service configuration block in the load balancer's `apache.cfg`.
+
+**Parameters within `apache::balancermember`**:
+
+##### `balancer_cluster`
+
+**Required**. Sets the Apache service's instance name, and must match the name of a declared [`apache::balancer`][] resource.
+
+##### `url`
+
+Specifies the URL used to contact the balancer member server. Default:  'http://${::fqdn}/'.
+
+##### `options`
+
+Specifies an [array][] of [options](http://httpd.apache.org/docs/current/mod/mod_proxy.html#balancermember) after the URL, and accepts any key-value pairs available to [`ProxyPass`][]. Default: an empty array.
+
+#### Define: `apache::custom_config`
+
+Adds a custom configuration file to the Apache server's `conf.d` directory. If the file is invalid and this define's `$verify_config` parameter is 'true', Puppet throws an error during a Puppet run.
+
+**Parameters within `apache::custom_config`**:
+
+##### `ensure`
+
+Specifies whether the configuration file should be present. Valid options: 'absent', 'present'. Default: 'present'.
+
+##### `confdir`
+
+Sets the directory in which Puppet places configuration files. Default: '$::apache::confd_dir'.
+
+##### `content`
+
+Sets the configuration file's content. The `content` and [`source`][] parameters are exclusive of each other.
+
+##### `priority`
+
+Sets the configuration file's priority by prefixing its filename with this parameter's numeric value, as Apache processes configuration files in alphanumeric order. The default value is `25`.
+
+To omit the priority prefix in the configuration file's name, set this parameter to `false`.
+
+##### `source`
+
+Points to the configuration file's source. The [`content`][] and `source` parameters are exclusive of each other.
+
+##### `verify_command`
+
+Specifies the command Puppet uses to verify the configuration file. Use a fully qualified command. Default: `/usr/sbin/apachectl -t`.
+
+This parameter is only used if the [`verify_config`][] parameter's value is 'true'. If the `verify_command` fails, the Puppet run deletes the configuration file, does not notify the Apache service, and raises an error.
+
+##### `verify_config`
+
+Specifies whether to validate the configuration file before notifying the Apache service. Valid options: Boolean. Default: `true`.
+
+#### Define: `apache::fastcgi::server`
+
+Defines one or more external FastCGI servers to handle specific file types. Use this define with [`mod_fastcgi`][FastCGI].
+
+**Parameters within `apache::fastcgi::server`:**
+
+##### `host`
+
+Determines the FastCGI's hostname or IP address and TCP port number (1-65535).
+
+##### `timeout`
+
+Sets the number of seconds a [FastCGI][] application can be inactive before aborting the request and logging the event at the error LogLevel. The inactivity timer applies only as long as a connection is pending with the FastCGI application. If a request is queued to an application, but the application doesn't respond by writing and flushing within this period, the request is aborted. If communication is complete with the application but incomplete with the client (the response is buffered), the timeout does not apply.
+
+##### `flush`
+
+Forces [`mod_fastcgi`][FastCGI] to write to the client as data is received from the application. By default, `mod_fastcgi` buffers data in order to free the application as quickly as possible.
+
+##### `faux_path`
+
+Apache has [FastCGI][] handle URIs that resolve to this filename. The path set in this parameter does not have to exist in the local filesystem.
+
+##### `alias`
+
+Internally links actions with the FastCGI server. This alias must be unique.
+
+##### `file_type`
+
+Sets the [MIME `content-type`][] of the file to be processed by the FastCGI server.
+
+#### Define: `apache::listen`
+
+Adds [`Listen`][] directives to `ports.conf` in the Apache configuration directory that define the Apache server's or a virtual host's listening address and port. The [`apache::vhost`][] class uses this define, and titles take the form '<PORT>', '<IPV4>:<PORT>', or '<IPV6>:<PORT>'.
+
+#### Define: `apache::mod`
+
+Installs packages for an Apache module that doesn't have a corresponding [`apache::mod::<MODULE NAME>`][] class, and checks for or places the module's default configuration files in the Apache server's `module` and `enable` directories. The default locations depend on your operating system.
+
+**Parameters within `apache::mod`**:
+
+##### `package`
+
+**Required**. Names the package Puppet uses to install the Apache module.
+
+##### `package_ensure`
+
+Determines whether Puppet ensures the Apache module should be installed. Valid options: 'absent', 'present'. Default: 'present'.
+
+##### `lib`
+
+Defines the module's shared object name. Its default value is `mod_$name.so`, and it should not be configured manually without special reason.
+
+##### `lib_path`
+
+Specifies a path to the module's libraries. Default: the `apache` class's [`lib_path`][] parameter.
+
+Don't manually set this parameter without special reason. The [`path`][] parameter overrides this value.
+
+##### `loadfile_name`
+
+Sets the filename for the module's [`LoadFile`][] directive, which can also set the module load order as Apache processes them in alphanumeric order. Valid options: filenames formatted `\*.load`. Default: `$name.load`.
+
+##### `loadfiles`
+
+Specifies an [array][] of [`LoadFile`][] directives.
+
+##### `path`
+
+Specifies a path to the module. Default: [`lib_path`][]/[`lib`][]. Don't manually set this parameter without special reason.
+
+#### Define: `apache::namevirtualhost`
+
+Enables [name-based virtual hosts][] and adds all related directives to the `ports.conf` file in the Apache HTTPD configuration directory. Titles can take the forms '\*', '*:<PORT>', '\_default_:<PORT>, '<IP>', or '<IP>:<PORT>'.
+
+#### Define: `apache::vhost`
+
+The Apache module allows a lot of flexibility in the setup and configuration of virtual hosts. This flexibility is due, in part, to `vhost` being a defined resource type, which allows Apache to evaluate it multiple times with different parameters.
+
+The `apache::vhost` define allows you to have specialized configurations for virtual hosts that have requirements outside the defaults. You can set up a default virtual host within the base `::apache` class, as well as set a customized virtual host as the default. Customized virtual hosts have a lower numeric [`priority`][] than the base class's, causing Apache to process the customized virtual host first.
+
+The `apache::vhost` define uses `concat::fragment` to build the configuration file. To inject custom fragments for pieces of the configuration that the define doesn't inherently support, add a custom fragment.
+
+For the custom fragment's `order` parameter, the `apache::vhost` define uses multiples of 10, so any `order` that isn't a multiple of 10 should work.
+
+**Parameters within `apache::vhost`**:
+
+##### `access_log`
+
+Determines whether to configure `*_access.log` directives (`*_file`,`*_pipe`, or `*_syslog`). Valid options: Boolean. Default: 'true'.
+
+##### `access_log_env_var`
+
+Specifies that only requests with particular environment variables be logged. Defaults to 'undef'.
+
+##### `access_log_file`
+
+Sets the filename of the `*_access.log` placed in [`logroot`][]. Given a virtual host---for instance, example.com---it defaults to 'example.com_ssl.log' for [SSL-encrypted][SSL encryption] virtual hosts and 'example.com_access.log' for unencrypted virtual hosts.
+
+##### `access_log_format`
+
+Specifies the use of either a [`LogFormat`][] nickname or a custom-formatted string for the access log. Default: 'combined'.
+
+##### `access_log_pipe`
+
+Specifies a pipe where Apache sends access log messages. Default: 'undef'.
+
+##### `access_log_syslog`
+
+Sends all access log messages to syslog. Default: 'undef'.
+
+##### `add_default_charset`
+
+Sets a default media charset value for the [`AddDefaultCharset`][] directive, which is added to `text/plain` and `text/html` responses.
+
+##### `add_listen`
+
+Determines whether the virtual host creates a [`Listen`][] statement. Valid options: Boolean. Default: 'true'.
+
+Setting `add_listen` to 'false' prevents the virtual host from creating a `Listen` statement. This is important when combining virtual hosts that aren't passed an `ip` parameter with those that are.
+
+##### `use_optional_includes`
+
+Specifies whether Apache uses the [`IncludeOptional`][] directive instead of [`Include`][] for `additional_includes` in Apache 2.4 or newer. Valid options: Boolean. Default: 'false'.
+
+##### `additional_includes`
+
+Specifies paths to additional static, virtual host-specific Apache configuration files. You can use this parameter to implement a unique, custom configuration not supported by this module. Valid options: a string path or [array][] of them. Default: an empty array.
+
+##### `aliases`
+
+Passes a list of [Hashes][Hash] to the virtual host to create [`Alias`][], [`AliasMatch`][], [`ScriptAlias`][] or [`ScriptAliasMatch`][] directives as per the [`mod_alias`][] documentation.
+
+For example:
+
+~~~ puppet
+aliases => [
+  { aliasmatch       => '^/image/(.*)\.jpg$',
+    path             => '/files/jpg.images/$1.jpg',
+  },
+  { alias            => '/image',
+    path             => '/ftp/pub/image',
+  },
+  { scriptaliasmatch => '^/cgi-bin(.*)',
+    path             => '/usr/local/share/cgi-bin$1',
+  },
+  { scriptalias      => '/nagios/cgi-bin/',
+    path             => '/usr/lib/nagios/cgi-bin/',
+  },
+  { alias            => '/nagios',
+    path             => '/usr/share/nagios/html',
+  },
+],
+~~~
+
+For the `alias`, `aliasmatch`, `scriptalias` and `scriptaliasmatch` keys to work, each needs a corresponding context, such as `<Directory /path/to/directory>` or `<Location /some/location/here>`. Puppet creates the directives in the order specified in the `aliases` parameter. As described in the [`mod_alias`][] documentation, add more specific `alias`, `aliasmatch`, `scriptalias` or `scriptaliasmatch` parameters before the more general ones to avoid shadowing.
+
+**Note**: Use the `aliases` parameter instead of the `scriptaliases` parameter because you can precisely control the various alias directives' order. Defining `ScriptAliases` using the `scriptaliases` parameter means *all* `ScriptAlias` directives will come after *all* `Alias` directives, which can lead to `Alias` directives shadowing `ScriptAlias` directives. This often causes problems, for example with Nagios.
+
+If [`apache::mod::passenger`][] is loaded and `PassengerHighPerformance` is 'true', the `Alias` directive might not be able to honor the `PassengerEnabled => off` statement. See [this article](http://www.conandalton.net/2010/06/passengerenabled-off-not-working.html) for details.
+
+##### `allow_encoded_slashes`
+
+Sets the [`AllowEncodedSlashes`][] declaration for the virtual host, overriding the server default. This modifies the virtual host responses to URLs with `\` and `/` characters. Valid options: 'nodecode', 'off', 'on'. Default: undef, which omits the declaration from the server configuration and selects the Apache default setting of `Off`.
+
+##### `block`
+
+Specifies the list of things to which Apache blocks access. Valid option: 'scm', which blocks web access to `.svn`, `.git`, and `.bzr` directories. Default: an empty [array][].
+
+##### `custom_fragment`
+
+Passes a string of custom configuration directives to place at the end of the virtual host configuration. Default: 'undef'.
+
+##### `default_vhost`
+
+Sets a given `apache::vhost` define as the default to serve requests that do not match any other `apache::vhost` defines. Default: 'false'.
+
+##### `directories`
+
+See the [`directories`](#parameter-directories-for-apachevhost) section.
+
+##### `directoryindex`
+
+Sets the list of resources to look for when a client requests an index of the directory by specifying a '/' at the end of the directory name. See the [`DirectoryIndex`][] directive documentation for details. Default: 'undef'.
+
+##### `docroot`
+
+**Required**. Sets the [`DocumentRoot`][] location, from which Apache serves files.
+
+If `docroot` and [`manage_docroot`][] are both set to `false`, no [`DocumentRoot`][] will be set and the accompanying `<Directory /path/to/directory>` block will not be created.
+
+##### `docroot_group`
+
+Sets group access to the [`docroot`][] directory. Defaults to 'root'.
+
+##### `docroot_owner`
+
+Sets individual user access to the docroot directory. Defaults to 'root'.
+
+##### `docroot_mode`
+
+Sets access permissions of the docroot directory. Defaults to 'undef'.
+
+##### `manage_docroot`
+
+Whether to manage to docroot directory at all. Defaults to 'true'.
+
+##### `error_log`
+
+Specifies whether `*_error.log` directives should be configured. Defaults to 'true'.
+
+##### `error_log_file`
+
+Points to the `*_error.log` file. Given a vhost, example.com, it defaults to 'example.com_ssl_error.log' for SSL vhosts and 'example.com_access_error.log' for non-SSL vhosts.
+
+##### `error_log_pipe`
+
+Specifies a pipe to send error log messages to. Defaults to 'undef'.
+
+##### `error_log_syslog`
+
+Sends all error log messages to syslog. Defaults to 'undef'.
+
+##### `error_documents`
+
+A list of hashes which can be used to override the [ErrorDocument](https://httpd.apache.org/docs/current/mod/core.html#errordocument) settings for this vhost. Defaults to '[]'. Example:
+
+~~~ puppet
+    apache::vhost { 'sample.example.net':
+      error_documents => [
+        { 'error_code' => '503', 'document' => '/service-unavail' },
+        { 'error_code' => '407', 'document' => 'https://example.com/proxy/login' },
+      ],
+    }
+~~~
+
+##### `ensure`
+
+Specifies if the vhost file is present or absent. Defaults to 'present'.
+
+##### `fallbackresource`
+
+Sets the [FallbackResource](http://httpd.apache.org/docs/current/mod/mod_dir.html#fallbackresource) directive, which specifies an action to take for any URL that doesn't map to anything in your filesystem and would otherwise return 'HTTP 404 (Not Found)'. Valid values must either begin with a / or be 'disabled'. Defaults to 'undef'.
+
+##### `filters`
+
+[Filters](http://httpd.apache.org/docs/2.2/mod/mod_filter.html) enable smart, context-sensitive configuration of output content filters.
+
+~~~ puppet
+    apache::vhost { "$::fqdn":
+      filters => [
+        'FilterDeclare   COMPRESS',
+        'FilterProvider  COMPRESS DEFLATE resp=Content-Type $text/html',
+        'FilterChain     COMPRESS',
+        'FilterProtocol  COMPRESS DEFLATE change=yes;byteranges=no',
+      ],
+    }
+~~~
+
+##### `force_type`
+
+Sets the [`ForceType`][] directive, which forces Apache to serve all matching files with the specified [MIME `content-type`][].
+
+##### `headers`
+
+Adds lines to replace, merge, or remove response headers. See [Header](http://httpd.apache.org/docs/current/mod/mod_headers.html#header) for more information. Can be an array. Defaults to 'undef'.
+
+##### `ip`
+
+Sets the IP address the vhost listens on. Defaults to listen on all IPs.
+
+##### `ip_based`
+
+Enables an [IP-based](http://httpd.apache.org/docs/current/vhosts/ip-based.html) vhost. This parameter inhibits the creation of a NameVirtualHost directive, since those are used to funnel requests to name-based vhosts. Defaults to 'false'.
+
+##### `itk`
+
+Configures [ITK](http://mpm-itk.sesse.net/) in a hash. Keys can be:
+
+* user + group
+* `assignuseridexpr`
+* `assigngroupidexpr`
+* `maxclientvhost`
+* `nice`
+* `limituidrange` (Linux 3.5.0 or newer)
+* `limitgidrange` (Linux 3.5.0 or newer)
+
+Usage typically looks like:
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot => '/path/to/directory',
+  itk     => {
+    user  => 'someuser',
+    group => 'somegroup',
+  },
+}
+~~~
+
+##### `auth_kerb`
+
+Enable [`mod_auth_kerb`][] parameters for a virtual host. Valid values are 'true' or 'false'. Defaults to 'false'.
+
+Usage typically looks like:
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  auth_kerb              => true,
+  krb_method_negotiate   => 'on',
+  krb_auth_realms        => ['EXAMPLE.ORG'],
+  krb_local_user_mapping => 'on',
+  directories            => {
+    path         => '/var/www/html',
+    auth_name    => 'Kerberos Login',
+    auth_type    => 'Kerberos',
+    auth_require => 'valid-user',
+  },
+}
+~~~
+
+Related parameters follow the names of `mod_auth_kerb` directives:
+
+- `krb_method_negotiate`: Determines whether to use the Negotiate method. Default: 'on'.
+- `krb_method_k5passwd`: Determines whether to use password-based authentication for Kerberos v5. Default: 'on'.
+- `krb_authoritative`: If set to 'off', authentication controls can be passed on to another module. Default: 'on'.
+- `krb_auth_realms`: Specifies an array of Kerberos realms to use for authentication. Default: `[]`.
+- `krb_5keytab`: Specifies the Kerberos v5 keytab file's location. Default: undef.
+- `krb_local_user_mapping`: Strips @REALM from usernames for further use. Default: undef.
+
+##### `limit_request_field_size`
+
+[Limits](http://httpd.apache.org/docs/2.4/mod/core.html#limitrequestfieldsize) the size of the HTTP request header allowed from the client. Default is 'undef'.
+
+##### `logroot`
+
+Specifies the location of the virtual host's logfiles. Defaults to '/var/log/<apache log location>/'.
+
+##### `$logroot_ensure`
+
+Determines whether or not to remove the logroot directory for a virtual host. Valid values are 'directory', or 'absent'.
+
+##### `logroot_mode`
+
+Overrides the mode the logroot directory is set to. Defaults to undef. Do NOT give people write access to the directory the logs are stored
+in without being aware of the consequences; see http://httpd.apache.org/docs/2.4/logs.html#security for details.
+
+##### `log_level`
+
+Specifies the verbosity of the error log. Defaults to 'warn' for the global server configuration and can be overridden on a per-vhost basis. Valid values are 'emerg', 'alert', 'crit', 'error', 'warn', 'notice', 'info' or 'debug'.
+
+###### `modsec_body_limit`
+
+Configures the maximum request body size (in bytes) ModSecurity will accept for buffering
+
+###### `modsec_disable_vhost`
+
+Boolean.  Only valid if apache::mod::security is included.  Used to disable mod_security on an individual vhost.  Only relevant if apache::mod::security is included.
+
+###### `modsec_disable_ids`
+
+Array of mod_security IDs to remove from the vhost.  Also takes a hash allowing removal of an ID from a specific location.
+
+~~~ puppet
+    apache::vhost { 'sample.example.net':
+      modsec_disable_ids => [ 90015, 90016 ],
+    }
+~~~
+
+~~~ puppet
+    apache::vhost { 'sample.example.net':
+      modsec_disable_ids => { '/location1' => [ 90015, 90016 ] },
+    }
+~~~
+
+###### `modsec_disable_ips`
+
+Array of IPs to exclude from mod_security rule matching
+
+##### `no_proxy_uris`
+
+Specifies URLs you do not want to proxy. This parameter is meant to be used in combination with [`proxy_dest`](#proxy_dest).
+
+##### `no_proxy_uris_match`
+
+This directive is equivalent to `no_proxy_uris`, but takes regular expressions.
+
+##### `proxy_preserve_host`
+
+Sets the [ProxyPreserveHost Directive](http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypreservehost). Valid options: Boolean. Default: 'false'.
+
+Setting this parameter to 'true' enables the `Host:` line from an incoming request to be proxied to the host instead of hostname. 'false' sets this option to 'Off'.
+
+##### `proxy_error_override`
+
+Sets the [ProxyErrorOverride Directive](http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxyerroroverride). This directive controls whether apache should override error pages for proxied content. This option is off by default.
+
+##### `options`
+
+Sets the [`Options`][] for the specified virtual host. Default: ['Indexes','FollowSymLinks','MultiViews'], as demonstrated below:
+
+~~~ puppet
+    apache::vhost { 'site.name.fdqn':
+      …
+      options => ['Indexes','FollowSymLinks','MultiViews'],
+    }
+~~~
+
+**Note**: If you use the [`directories`][] parameter of [`apache::vhost`][], 'Options', 'Override', and 'DirectoryIndex' are ignored because they are parameters within `directories`.
+
+##### `override`
+
+Sets the overrides for the specified virtual host. Accepts an array of [AllowOverride](http://httpd.apache.org/docs/current/mod/core.html#allowoverride) arguments. Defaults to '[none]'.
+
+##### `passenger_app_root`
+
+Sets [PassengerRoot](https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#PassengerAppRoot), the location of the Passenger application root if different from the DocumentRoot.
+
+##### `passenger_app_env`
+
+Sets [PassengerAppEnv](https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#PassengerAppEnv), the environment for the Passenger application. If not specifies, defaults to the global setting or 'production'.
+
+##### `passenger_ruby`
+
+Sets [PassengerRuby](https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#PassengerRuby) on this virtual host, the Ruby interpreter to use for the application.
+
+##### `passenger_min_instances`
+
+Sets [PassengerMinInstances](https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#PassengerMinInstances), the minimum number of application processes to run.
+
+##### `passenger_start_timeout`
+
+Sets [PassengerStartTimeout](https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#_passengerstarttimeout_lt_seconds_gt), the timeout for the application startup.
+
+##### `passenger_pre_start`
+
+Sets [PassengerPreStart](https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#PassengerPreStart), the URL of the application if pre-starting is required.
+
+##### `php_flags & values`
+
+Allows per-vhost setting [`php_value`s or `php_flag`s](http://php.net/manual/en/configuration.changes.php). These flags or values can be overwritten by a user or an application. Defaults to '{}'.
+
+##### `php_admin_flags & values`
+
+Allows per-vhost setting [`php_admin_value`s or `php_admin_flag`s](http://php.net/manual/en/configuration.changes.php). These flags or values cannot be overwritten by a user or an application. Defaults to '{}'.
+
+##### `port`
+
+Sets the port the host is configured on. The module's defaults ensure the host listens on port 80 for non-SSL vhosts and port 443 for SSL vhosts. The host only listens on the port set in this parameter.
+
+##### `priority`
+
+Sets the relative load-order for Apache HTTPD VirtualHost configuration files. Defaults to '25'.
+
+If nothing matches the priority, the first name-based vhost is used. Likewise, passing a higher priority causes the alphabetically first name-based vhost to be used if no other names match.
+
+*Note:* You should not need to use this parameter. However, if you do use it, be aware that the `default_vhost` parameter for `apache::vhost` passes a priority of '15'.
+
+Pass priority `false` to omit the priority prefix in file names.
+
+##### `proxy_dest`
+
+Specifies the destination address of a [ProxyPass](http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypass) configuration. Defaults to 'undef'.
+
+##### `proxy_pass`
+
+Specifies an array of `path => URI` for a [ProxyPass](http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypass) configuration. Defaults to 'undef'. Optionally parameters can be added as an array.
+
+~~~ puppet
+apache::vhost { 'site.name.fdqn':
+  …
+  proxy_pass => [
+    { 'path' => '/a', 'url' => 'http://backend-a/' },
+    { 'path' => '/b', 'url' => 'http://backend-b/' },
+    { 'path' => '/c', 'url' => 'http://backend-a/c', 'params' => {'max'=>20, 'ttl'=>120, 'retry'=>300}},
+    { 'path' => '/l', 'url' => 'http://backend-xy',
+      'reverse_urls' => ['http://backend-x', 'http://backend-y'] },
+    { 'path' => '/d', 'url' => 'http://backend-a/d',
+      'params' => { 'retry' => '0', 'timeout' => '5' }, },
+    { 'path' => '/e', 'url' => 'http://backend-a/e',
+      'keywords' => ['nocanon', 'interpolate'] },
+    { 'path' => '/f', 'url' => 'http://backend-f/',
+      'setenv' => ['proxy-nokeepalive 1','force-proxy-request-1.0 1']},
+    { 'path' => '/g', 'url' => 'http://backend-g/',
+      'reverse_cookies' => [{'path' => '/g', 'url' => 'http://backend-g/',}], },
+  ],
+}
+~~~
+
+`reverse_urls` is optional and can be an array or a string. It is useful when used with `mod_proxy_balancer`.
+`reverse_cookies` is optional and is used to set ProxyPassReverseCookiePath.
+`params` is an optional parameter. It allows to provide the ProxyPass key=value parameters (Connection settings).
+`setenv` is optional and is an array to set environment variables for the proxy directive, for details see http://httpd.apache.org/docs/current/mod/mod_proxy.html#envsettings
+
+##### `proxy_dest_match`
+
+This directive is equivalent to proxy_dest, but takes regular expressions, see [ProxyPassMatch](http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypassmatch) for details.
+
+##### `proxy_dest_reverse_match`
+
+Allows you to pass a ProxyPassReverse if `proxy_dest_match` is specified. See [ProxyPassReverse](http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypassreverse) for details.
+
+##### `proxy_pass_match`
+
+This directive is equivalent to proxy_pass, but takes regular expressions, see [ProxyPassMatch](http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypassmatch) for details.
+
+##### `rack_base_uris`
+
+Specifies the resource identifiers for a rack configuration. The file paths specified are listed as rack application roots for [Phusion Passenger](http://www.modrails.com/documentation/Users%20guide%20Apache.html#_railsbaseuri_and_rackbaseuri) in the _rack.erb template. Defaults to 'undef'.
+
+#####`passenger_base_uris`
+
+Used to specify that the given URI is a Phusion Passenger-served application. The file paths specified are listed as passenger application roots for [Phusion Passenger](https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#PassengerBaseURI) in the _passenger_base_uris.erb template. Defaults to 'undef'.
+
+##### `redirect_dest`
+
+Specifies the address to redirect to. Defaults to 'undef'.
+
+##### `redirect_source`
+
+Specifies the source URIs that redirect to the destination specified in `redirect_dest`. If more than one item for redirect is supplied, the source and destination must be the same length, and the items are order-dependent.
+
+~~~ puppet
+apache::vhost { 'site.name.fdqn':
+  …
+  redirect_source => ['/images','/downloads'],
+  redirect_dest   => ['http://img.example.com/','http://downloads.example.com/'],
+}
+~~~
+
+##### `redirect_status`
+
+Specifies the status to append to the redirect. Defaults to 'undef'.
+
+~~~ puppet
+apache::vhost { 'site.name.fdqn':
+  …
+  redirect_status => ['temp','permanent'],
+}
+~~~
+
+##### `redirectmatch_regexp` & `redirectmatch_status` & `redirectmatch_dest`
+
+Determines which server status should be raised for a given regular expression and where to forward the user to. Entered as arrays. Defaults to 'undef'.
+
+~~~ puppet
+apache::vhost { 'site.name.fdqn':
+  …
+  redirectmatch_status => ['404','404'],
+  redirectmatch_regexp => ['\.git(/.*|$)/','\.svn(/.*|$)'],
+  redirectmatch_dest => ['http://www.example.com/1','http://www.example.com/2'],
+}
+~~~
+
+##### `request_headers`
+
+Modifies collected [request headers](http://httpd.apache.org/docs/current/mod/mod_headers.html#requestheader) in various ways, including adding additional request headers, removing request headers, etc. Defaults to 'undef'.
+
+~~~ puppet
+apache::vhost { 'site.name.fdqn':
+  …
+  request_headers => [
+    'append MirrorID "mirror 12"',
+    'unset MirrorID',
+  ],
+}
+~~~
+##### `rewrites`
+
+Creates URL rewrite rules. Expects an array of hashes, and the hash keys can be any of 'comment', 'rewrite_base', 'rewrite_cond', 'rewrite_rule' or 'rewrite_map'. Defaults to 'undef'.
+
+For example, you can specify that anyone trying to access index.html is served welcome.html
+
+~~~ puppet
+apache::vhost { 'site.name.fdqn':
+  …
+  rewrites => [ { rewrite_rule => ['^index\.html$ welcome.html'] } ]
+}
+~~~
+
+The parameter allows rewrite conditions that, when true, execute the associated rule. For instance, if you wanted to rewrite URLs only if the visitor is using IE
+
+~~~ puppet
+apache::vhost { 'site.name.fdqn':
+  …
+  rewrites => [
+    {
+      comment      => 'redirect IE',
+      rewrite_cond => ['%{HTTP_USER_AGENT} ^MSIE'],
+      rewrite_rule => ['^index\.html$ welcome.html'],
+    },
+  ],
+}
+~~~
+
+You can also apply multiple conditions. For instance, rewrite index.html to welcome.html only when the browser is Lynx or Mozilla (version 1 or 2)
+
+~~~ puppet
+apache::vhost { 'site.name.fdqn':
+  …
+  rewrites => [
+    {
+      comment      => 'Lynx or Mozilla v1/2',
+      rewrite_cond => ['%{HTTP_USER_AGENT} ^Lynx/ [OR]', '%{HTTP_USER_AGENT} ^Mozilla/[12]'],
+      rewrite_rule => ['^index\.html$ welcome.html'],
+    },
+  ],
+}
+~~~
+
+Multiple rewrites and conditions are also possible
+
+~~~ puppet
+apache::vhost { 'site.name.fdqn':
+  …
+  rewrites => [
+    {
+      comment      => 'Lynx or Mozilla v1/2',
+      rewrite_cond => ['%{HTTP_USER_AGENT} ^Lynx/ [OR]', '%{HTTP_USER_AGENT} ^Mozilla/[12]'],
+      rewrite_rule => ['^index\.html$ welcome.html'],
+    },
+    {
+      comment      => 'Internet Explorer',
+      rewrite_cond => ['%{HTTP_USER_AGENT} ^MSIE'],
+      rewrite_rule => ['^index\.html$ /index.IE.html [L]'],
+    },
+    {
+      rewrite_base => /apps/,
+      rewrite_rule => ['^index\.cgi$ index.php', '^index\.html$ index.php', '^index\.asp$ index.html'],
+    },
+    { comment      => 'Rewrite to lower case',
+      rewrite_cond => ['%{REQUEST_URI} [A-Z]'],
+      rewrite_map  => ['lc int:tolower'],
+      rewrite_rule => ['(.*) ${lc:$1} [R=301,L]'],
+    },
+  ],
+}
+~~~
+
+Refer to the [`mod_rewrite` documentation](http://httpd.apache.org/docs/current/mod/mod_rewrite.html) for more details on what is possible with rewrite rules and conditions.
+
+##### `scriptalias`
+
+Defines a directory of CGI scripts to be aliased to the path '/cgi-bin', for example: '/usr/scripts'. Defaults to 'undef'.
+
+##### `scriptaliases`
+
+**Note**: This parameter is deprecated in favor of the `aliases` parameter.
+
+Passes an array of hashes to the vhost to create either ScriptAlias or ScriptAliasMatch statements per the [`mod_alias` documentation](http://httpd.apache.org/docs/current/mod/mod_alias.html).
+
+~~~ puppet
+scriptaliases => [
+  {
+    alias => '/myscript',
+    path  => '/usr/share/myscript',
+  },
+  {
+    aliasmatch => '^/foo(.*)',
+    path       => '/usr/share/fooscripts$1',
+  },
+  {
+    aliasmatch => '^/bar/(.*)',
+    path       => '/usr/share/bar/wrapper.sh/$1',
+  },
+  {
+    alias => '/neatscript',
+    path  => '/usr/share/neatscript',
+  },
+]
+~~~
+
+The ScriptAlias and ScriptAliasMatch directives are created in the order specified. As with [Alias and AliasMatch](#aliases) directives, specify more specific aliases before more general ones to avoid shadowing.
+
+##### `serveradmin`
+
+Specifies the email address Apache displays when it renders one of its error pages. Defaults to 'undef'.
+
+##### `serveraliases`
+
+Sets the [ServerAliases](http://httpd.apache.org/docs/current/mod/core.html#serveralias) of the site. Defaults to '[]'.
+
+##### `servername`
+
+Sets the servername corresponding to the hostname you connect to the virtual host at. Defaults to the title of the resource.
+
+##### `setenv`
+
+Used by HTTPD to set environment variables for vhosts. Defaults to '[]'.
+
+Example:
+
+~~~ puppet
+apache::vhost { 'setenv.example.com':
+  setenv => ['SPECIAL_PATH /foo/bin'],
+}
+~~~
+
+##### `setenvif`
+
+Used by HTTPD to conditionally set environment variables for vhosts. Defaults to '[]'.
+
+##### `suphp_addhandler`, `suphp_configpath`, & `suphp_engine`
+
+Set up a virtual host with [suPHP](http://suphp.org/DocumentationView.html?file=apache/CONFIG).
+
+`suphp_addhandler` defaults to 'php5-script' on RedHat and FreeBSD, and 'x-httpd-php' on Debian and Gentoo.
+
+`suphp_configpath` defaults to 'undef' on RedHat and FreeBSD, and '/etc/php5/apache2' on Debian and Gentoo.
+
+`suphp_engine` allows values 'on' or 'off'. Defaults to 'off'
+
+To set up a virtual host with suPHP
+
+~~~ puppet
+apache::vhost { 'suphp.example.com':
+  port                => '80',
+  docroot             => '/home/appuser/myphpapp',
+  suphp_addhandler    => 'x-httpd-php',
+  suphp_engine        => 'on',
+  suphp_configpath    => '/etc/php5/apache2',
+  directories         => { path => '/home/appuser/myphpapp',
+    'suphp'           => { user => 'myappuser', group => 'myappgroup' },
+  }
+}
+~~~
+
+##### `vhost_name`
+
+Enables name-based virtual hosting. If no IP is passed to the virtual host, but the vhost is assigned a port, then the vhost name is 'vhost_name:port'. If the virtual host has no assigned IP or port, the vhost name is set to the title of the resource. Defaults to '*'.
+
+##### `virtual_docroot`
+
+Sets up a virtual host with a wildcard alias subdomain mapped to a directory with the same name. For example, 'http://example.com' would map to '/var/www/example.com'. Defaults to 'false'.
+
+~~~ puppet
+apache::vhost { 'subdomain.loc':
+  vhost_name       => '*',
+  port             => '80',
+  virtual_docroot' => '/var/www/%-2+',
+  docroot          => '/var/www',
+  serveraliases    => ['*.loc',],
+}
+~~~
+
+##### `wsgi_daemon_process`, `wsgi_daemon_process_options`, `wsgi_process_group`, `wsgi_script_aliases`, & `wsgi_pass_authorization`
+
+Set up a virtual host with [WSGI](https://code.google.com/p/modwsgi/).
+
+`wsgi_daemon_process` sets the name of the WSGI daemon. It is a hash, accepting [these keys](http://modwsgi.readthedocs.org/en/latest/configuration-directives/WSGIDaemonProcess.html), and it defaults to 'undef'.
+
+`wsgi_daemon_process_options` is optional and defaults to 'undef'.
+
+`wsgi_process_group` sets the group ID the virtual host runs under. Defaults to 'undef'.
+
+`wsgi_script_aliases` requires a hash of web paths to filesystem .wsgi paths. Defaults to 'undef'.
+
+`wsgi_pass_authorization` the WSGI application handles authorisation instead of Apache when set to 'On'. For more information see [here] (http://modwsgi.readthedocs.org/en/latest/configuration-directives/WSGIPassAuthorization.html).  Defaults to 'undef' where apache sets the defaults setting to 'Off'.
+
+`wsgi_chunked_request` enables support for chunked requests. Defaults to 'undef'.
+
+To set up a virtual host with WSGI
+
+~~~ puppet
+apache::vhost { 'wsgi.example.com':
+  port                        => '80',
+  docroot                     => '/var/www/pythonapp',
+  wsgi_daemon_process         => 'wsgi',
+  wsgi_daemon_process_options =>
+    { processes    => '2',
+      threads      => '15',
+      display-name => '%{GROUP}',
+     },
+  wsgi_process_group          => 'wsgi',
+  wsgi_script_aliases         => { '/' => '/var/www/demo.wsgi' },
+  wsgi_chunked_request        => 'On',
+}
+~~~
+
+#### Parameter `directories` for `apache::vhost`
+
+The `directories` parameter within the `apache::vhost` class passes an array of hashes to the vhost to create [Directory](http://httpd.apache.org/docs/current/mod/core.html#directory), [File](http://httpd.apache.org/docs/current/mod/core.html#files), and [Location](http://httpd.apache.org/docs/current/mod/core.html#location) directive blocks. These blocks take the form, '< Directory /path/to/directory>...< /Directory>'.
+
+The `path` key sets the path for the directory, files, and location blocks. Its value must be a path for the 'directory', 'files', and 'location' providers, or a regex for the 'directorymatch', 'filesmatch', or 'locationmatch' providers. Each hash passed to `directories` **must** contain `path` as one of the keys.
+
+The `provider` key is optional. If missing, this key defaults to 'directory'. Valid values for `provider` are 'directory', 'files', 'location', 'directorymatch', 'filesmatch', or 'locationmatch'. If you set `provider` to 'directorymatch', it uses the keyword 'DirectoryMatch' in the Apache config file.
+
+General `directories` usage looks something like
+
+~~~ puppet
+apache::vhost { 'files.example.net':
+  docroot     => '/var/www/files',
+  directories => [
+    { 'path'     => '/var/www/files',
+      'provider' => 'files',
+      'deny'     => 'from all',
+     },
+  ],
+}
+~~~
+
+*Note:* At least one directory should match the `docroot` parameter. After you start declaring directories, `apache::vhost` assumes that all required Directory blocks will be declared. If not defined, a single default Directory block is created that matches the `docroot` parameter.
+
+Available handlers, represented as keys, should be placed within the `directory`, `files`, or `location` hashes.  This looks like
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [ { path => '/path/to/directory', handler => value } ],
+}
+~~~
+
+Any handlers you do not set in these hashes are considered 'undefined' within Puppet and are not added to the virtual host, resulting in the module using their default values. Supported handlers are:
+
+###### `addhandlers`
+
+Sets [AddHandler](http://httpd.apache.org/docs/current/mod/mod_mime.html#addhandler) directives, which map filename extensions to the specified handler. Accepts a list of hashes, with `extensions` serving to list the extensions being managed by the handler, and takes the form: `{ handler => 'handler-name', extensions => ['extension']}`.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path        => '/path/to/directory',
+      addhandlers => [{ handler => 'cgi-script', extensions => ['.cgi']}],
+    },
+  ],
+}
+~~~
+
+###### `allow`
+
+Sets an [Allow](http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#allow) directive, which groups authorizations based on hostnames or IPs. **Deprecated:** This parameter is being deprecated due to a change in Apache. It only works with Apache 2.2 and lower. You can use it as a single string for one rule or as an array for more than one.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path  => '/path/to/directory',
+      allow => 'from example.org',
+    },
+  ],
+}
+~~~
+
+###### `allow_override`
+
+Sets the types of directives allowed in [.htaccess](http://httpd.apache.org/docs/current/mod/core.html#allowoverride) files. Accepts an array.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot      => '/path/to/directory',
+  directories  => [
+    { path           => '/path/to/directory',
+      allow_override => ['AuthConfig', 'Indexes'],
+    },
+  ],
+}
+~~~
+
+###### `auth_basic_authoritative`
+
+Sets the value for [AuthBasicAuthoritative](https://httpd.apache.org/docs/current/mod/mod_auth_basic.html#authbasicauthoritative), which determines whether authorization and authentication are passed to lower level Apache modules.
+
+###### `auth_basic_fake`
+
+Sets the value for [AuthBasicFake](http://httpd.apache.org/docs/current/mod/mod_auth_basic.html#authbasicfake), which statically configures authorization credentials for a given directive block.
+
+###### `auth_basic_provider`
+
+Sets the value for [AuthBasicProvider] (http://httpd.apache.org/docs/current/mod/mod_auth_basic.html#authbasicprovider), which sets the authentication provider for a given location.
+
+###### `auth_digest_algorithm`
+
+Sets the value for [AuthDigestAlgorithm](http://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestalgorithm), which selects the algorithm used to calculate the challenge and response hashes.
+
+###### `auth_digest_domain`
+
+Sets the value for [AuthDigestDomain](http://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestdomain), which allows you to specify one or more URIs in the same protection space for digest authentication.
+
+###### `auth_digest_nonce_lifetime`
+
+Sets the value for [AuthDigestNonceLifetime](http://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestnoncelifetime), which controls how long the server nonce is valid.
+
+###### `auth_digest_provider`
+
+Sets the value for [AuthDigestProvider](http://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestprovider), which sets the authentication provider for a given location.
+
+###### `auth_digest_qop`
+
+Sets the value for [AuthDigestQop](http://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestqop), which determines the quality-of-protection to use in digest authentication.
+
+###### `auth_digest_shmem_size`
+
+Sets the value for [AuthAuthDigestShmemSize](http://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestshmemsize), which defines the amount of shared memory allocated to the server for keeping track of clients.
+
+###### `auth_group_file`
+
+Sets the value for [AuthGroupFile](https://httpd.apache.org/docs/current/mod/mod_authz_groupfile.html#authgroupfile), which sets the name of the text file containing the list of user groups for authorization.
+
+###### `auth_name`
+
+Sets the value for [AuthName](http://httpd.apache.org/docs/current/mod/mod_authn_core.html#authname), which sets the name of the authorization realm.
+
+###### `auth_require`
+
+Sets the entity name you're requiring to allow access. Read more about [Require](http://httpd.apache.org/docs/current/mod/mod_authz_host.html#requiredirectives).
+
+###### `auth_type`
+
+Sets the value for [AuthType](http://httpd.apache.org/docs/current/mod/mod_authn_core.html#authtype), which guides the type of user authentication.
+
+###### `auth_user_file`
+
+Sets the value for [AuthUserFile](http://httpd.apache.org/docs/current/mod/mod_authn_file.html#authuserfile), which sets the name of the text file containing the users/passwords for authentication.
+
+###### `custom_fragment`
+
+Pass a string of custom configuration directives to be placed at the end of the directory configuration.
+
+~~~ puppet
+  apache::vhost { 'monitor':
+    …
+    directories => [
+      {
+        path => '/path/to/directory',
+        custom_fragment => '
+  <Location /balancer-manager>
+    SetHandler balancer-manager
+    Order allow,deny
+    Allow from all
+  </Location>
+  <Location /server-status>
+    SetHandler server-status
+    Order allow,deny
+    Allow from all
+  </Location>
+  ProxyStatus On',
+      },
+    ]
+  }
+~~~
+
+###### `deny`
+
+Sets a [Deny](http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#deny) directive, specifying which hosts are denied access to the server. **Deprecated:** This parameter is being deprecated due to a change in Apache. It only works with Apache 2.2 and lower. You can use it as a single string for one rule or as an array for more than one.
+
+~~~ puppet
+    apache::vhost { 'sample.example.net':
+      docroot     => '/path/to/directory',
+      directories => [
+        { path => '/path/to/directory',
+          deny => 'from example.org',
+        },
+      ],
+    }
+~~~
+
+###### `error_documents`
+
+An array of hashes used to override the [ErrorDocument](https://httpd.apache.org/docs/current/mod/core.html#errordocument) settings for the directory.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  directories => [
+    { path            => '/srv/www',
+      error_documents => [
+        { 'error_code' => '503',
+          'document'   => '/service-unavail',
+        },
+      ],
+    },
+  ],
+}
+~~~
+
+###### `ext_filter_options`
+
+Sets the [ExtFilterOptions](https://httpd.apache.org/docs/current/mod/mod_ext_filter.html) directive.
+Note that you must declare `class { 'apache::mod::ext_filter': }` before using this directive.
+
+~~~ puppet
+apache::vhost { 'filter.example.org':
+  docroot     => '/var/www/filter',
+  directories => [
+    { path               => '/var/www/filter',
+      ext_filter_options => 'LogStderr Onfail=abort',
+    },
+  ],
+}
+~~~
+
+###### `geoip_enable`
+
+Sets the [GeoIPEnable](http://dev.maxmind.com/geoip/legacy/mod_geoip2/#Configuration) directive.
+Note that you must declare `class {'apache::mod::geoip': }` before using this directive.
+
+~~~ puppet
+apache::vhost { 'first.example.com':
+  docroot     => '/var/www/first',
+  directories => [
+    { path         => '/var/www/first',
+      geoip_enable => true,
+    },
+  ],
+}
+~~~
+
+###### `headers`
+
+Adds lines for [Header](http://httpd.apache.org/docs/current/mod/mod_headers.html#header) directives.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => {
+    path    => '/path/to/directory',
+    headers => 'Set X-Robots-Tag "noindex, noarchive, nosnippet"',
+  },
+}
+~~~
+
+###### `index_options`
+
+Allows configuration settings for [directory indexing](http://httpd.apache.org/docs/current/mod/mod_autoindex.html#indexoptions).
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path           => '/path/to/directory',
+      directoryindex => 'disabled', # this is needed on Apache 2.4 or mod_autoindex doesn't work
+      options        => ['Indexes','FollowSymLinks','MultiViews'],
+      index_options  => ['IgnoreCase', 'FancyIndexing', 'FoldersFirst', 'NameWidth=*', 'DescriptionWidth=*', 'SuppressHTMLPreamble'],
+    },
+  ],
+}
+~~~
+
+###### `index_order_default`
+
+Sets the [default ordering](https://httpd.apache.org/docs/current/mod/mod_autoindex.html#indexorderdefault) of the directory index.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path                => '/path/to/directory',
+      order               => 'Allow,Deny',
+      index_order_default => ['Descending', 'Date'],
+    },
+  ],
+}
+~~~
+
+###### `index_style_sheet`
+
+Sets the [IndexStyleSheet](https://httpd.apache.org/docs/current/mod/mod_autoindex.html#indexstylesheet), which adds a CSS stylesheet to the directory index.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path              => '/path/to/directory',
+      options           => ['Indexes','FollowSymLinks','MultiViews'],
+      index_options     => ['FancyIndexing'],
+      index_style_sheet => '/styles/style.css',
+    },
+  ],
+}
+~~~
+
+###### `mellon_enable`
+
+Sets the [MellonEnable][`mod_auth_mellon`] directory to enable [`mod_auth_melon`][]. You can use [`apache::mod::auth_mellon`][] to install `mod_auth_mellon`.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path                       => '/',
+      provider                   => 'directory',
+      mellon_enable              => 'info',
+      mellon_sp_private_key_file => '/etc/certs/${::fqdn}.key,
+      mellon_endpoint_path       => '/mellon',
+      mellon_set_env_no_prefix   => { 'ADFS_GROUP' => 'http://schemas.xmlsoap.org/claims/Group',
+                                      'ADFS_EMAIL' => 'http://schemas.xmlsoap.org/claims/EmailAddress', },
+      mellon_user => 'ADFS_LOGIN',
+    },
+    { path          => '/protected',
+      provider      => 'location',
+      mellon_enable => 'auth',
+      auth_type     => 'Mellon',
+      auth_require  => 'valid-user',
+      mellon_cond   => ['ADFS_LOGIN userA [MAP]','ADFS_LOGIN userB [MAP]'],
+    },
+  ]
+}
+~~~
+
+Related parameters follow the names of `mod_auth_melon` directives:
+
+- `mellon_cond`: Takes an array of mellon conditions that must be met to grant access, and creates a [MellonCond][`mod_auth_melon`] directive for each item in the array.
+- `mellon_endpoint_path`: Sets the [MellonEndpointPath][`mod_auth_melon`] to set the mellon endpoint path.
+- `mellon_idp_metadata_file`: Sets the [MellonIDPMetadataFile][`mod_auth_melon`] location of the IDP metadata file.
+- `mellon_saml_rsponse_dump`: Sets the [MellonSamlResponseDump][`mod_auth_melon`] directive to enable debug of SAML.
+- `mellon_set_env_no_prefix`: Sets the [MellonSetEnvNoPrefix][`mod_auth_melon`] directive to a hash of attribute names to map
+to environment variables.
+- `mellon_sp_private_key_file`: Sets the [MellonSPPrivateKeyFile][`mod_auth_melon`] directive for the private key location of the service provider.
+- `mellon_sp_cert_file`: Sets the [MellonSPCertFile][`mod_auth_melon`] directive for the public key location of the service provider.
+- `mellon_user`: Sets the [MellonUser][`mod_auth_melon`] attribute to use for the username.
+
+###### `options`
+
+Lists the [Options](https://httpd.apache.org/docs/current/mod/core.html#options) for the given Directory block.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path    => '/path/to/directory',
+      options => ['Indexes','FollowSymLinks','MultiViews'],
+    },
+  ],
+}
+~~~
+
+###### `order`
+
+Sets the order of processing Allow and Deny statements as per [Apache core documentation](http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#order). **Deprecated:** This parameter is being deprecated due to a change in Apache. It only works with Apache 2.2 and lower.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path  => '/path/to/directory',
+      order => 'Allow,Deny',
+    },
+  ],
+}
+~~~
+
+###### `passenger_enabled`
+
+Sets the value for the [PassengerEnabled](http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerEnabled) directive to 'on' or 'off'. Requires `apache::mod::passenger` to be included.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path              => '/path/to/directory',
+      passenger_enabled => 'on',
+    },
+  ],
+}
+~~~
+
+**Note:** There is an [issue](http://www.conandalton.net/2010/06/passengerenabled-off-not-working.html) using the PassengerEnabled directive with the PassengerHighPerformance directive.
+
+###### `php_value` and `php_flag`
+
+`php_value` sets the value of the directory, and `php_flag` uses a boolean to configure the directory. Further information can be found [here](http://php.net/manual/en/configuration.changes.php).
+
+###### `php_admin_value` and `php_admin_flag`
+
+`php_admin_value` sets the value of the directory, and `php_admin_flag` uses a boolean to configure the directory. Further information can be found [here](http://php.net/manual/en/configuration.changes.php).
+
+
+###### `satisfy`
+
+Sets a `Satisfy` directive per the [Apache Core documentation](http://httpd.apache.org/docs/2.2/mod/core.html#satisfy). **Deprecated:** This parameter is deprecated due to a change in Apache and only works with Apache 2.2 and lower.
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path    => '/path/to/directory',
+      satisfy => 'Any',
+    }
+  ],
+}
+~~~
+
+###### `sethandler`
+
+Sets a `SetHandler` directive per the [Apache Core documentation](http://httpd.apache.org/docs/2.2/mod/core.html#sethandler).
+
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path       => '/path/to/directory',
+      sethandler => 'None',
+    }
+  ],
+}
+~~~
+
+###### `set_output_filter`
+
+Sets a `SetOutputFilter` directive per the [Apache Core documentation](http://httpd.apache.org/docs/current/mod/core.html#setoutputfilter).
+
+~~~ puppet
+apache::vhost{ 'filter.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path              => '/path/to/directory',
+      set_output_filter => puppetdb-strip-resource-params,
+    },
+  ],
+}
+~~~
+
+###### `rewrites`
+
+Creates URL [`rewrites`](#rewrites) rules in vhost directories. Expects an array of hashes, and the hash keys can be any of 'comment', 'rewrite_base', 'rewrite_cond', or 'rewrite_rule'.
+
+~~~ puppet
+apache::vhost { 'secure.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path        => '/path/to/directory',
+      rewrites => [ { comment      => 'Permalink Rewrites',
+                      rewrite_base => '/'
+                    },
+                    { rewrite_rule => [ '^index\.php$ - [L]' ]
+                    },
+                    { rewrite_cond => [ '%{REQUEST_FILENAME} !-f',
+                                        '%{REQUEST_FILENAME} !-d',
+                                      ],
+                      rewrite_rule => [ '. /index.php [L]' ],
+                    }
+                  ],
+    },
+  ],
+}
+~~~
+
+***Note**: If you include rewrites in your directories, also include `apache::mod::rewrite` and consider setting the rewrites using the `rewrites` parameter in `apache::vhost` rather than setting the rewrites in the vhost directories.
+
+###### `shib_request_setting`
+
+Allows a valid content setting to be set or altered for the application request. This command takes two parameters: the name of the content setting, and the value to set it to. Check the Shibboleth [content setting documentation](https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPContentSettings) for valid settings. This key is disabled if `apache::mod::shib` is not defined. Check the [`mod_shib` documentation](https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPApacheConfig#NativeSPApacheConfig-Server/VirtualHostOptions) for more details.
+
+~~~ puppet
+apache::vhost { 'secure.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path                  => '/path/to/directory',
+      shib_request_settings => { 'requiresession' => 'On' },
+      shib_use_headers      => 'On',
+    },
+  ],
+}
+~~~
+
+###### `shib_use_headers`
+
+When set to 'On', this turns on the use of request headers to publish attributes to applications. Valid values for this key is 'On' or 'Off', and the default value is 'Off'. This key is disabled if `apache::mod::shib` is not defined. Check the [`mod_shib` documentation](https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPApacheConfig#NativeSPApacheConfig-Server/VirtualHostOptions) for more details.
+
+###### `ssl_options`
+
+String or list of [SSLOptions](https://httpd.apache.org/docs/current/mod/mod_ssl.html#ssloptions), which configure SSL engine run-time options. This handler takes precedence over SSLOptions set in the parent block of the vhost.
+
+~~~ puppet
+apache::vhost { 'secure.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path        => '/path/to/directory',
+      ssl_options => '+ExportCertData',
+    },
+    { path        => '/path/to/different/dir',
+      ssl_options => [ '-StdEnvVars', '+ExportCertData'],
+    },
+  ],
+}
+~~~
+
+###### `suphp`
+
+A hash containing the 'user' and 'group' keys for the [suPHP_UserGroup](http://www.suphp.org/DocumentationView.html?file=apache/CONFIG) setting. It must be used with `suphp_engine => on` in the vhost declaration, and can only be passed within `directories`.
+
+~~~ puppet
+apache::vhost { 'secure.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path  => '/path/to/directory',
+      suphp => {
+        user  => 'myappuser',
+        group => 'myappgroup',
+      },
+    },
+  ],
+}
+~~~
+
+#### SSL parameters for `apache::vhost`
+
+All of the SSL parameters for `::vhost` default to whatever is set in the base `apache` class. Use the below parameters to tweak individual SSL settings for specific vhosts.
+
+##### `ssl`
+
+Enables SSL for the virtual host. SSL vhosts only respond to HTTPS queries. Valid values are 'true' or 'false'. Defaults to 'false'.
+
+##### `ssl_ca`
+
+Specifies the SSL certificate authority. Defaults to 'undef'.
+
+##### `ssl_cert`
+
+Specifies the SSL certification. Defaults are based on your OS: '/etc/pki/tls/certs/localhost.crt' for RedHat, '/etc/ssl/certs/ssl-cert-snakeoil.pem' for Debian, '/usr/local/etc/apache22/server.crt' for FreeBSD, and '/etc/ssl/apache2/server.crt' on Gentoo.
+
+##### `ssl_protocol`
+
+Specifies [SSLProtocol](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslprotocol). Expects an array or space separated string of accepted protocols. Defaults to 'all', '-SSLv2', '-SSLv3'.
+
+##### `ssl_cipher`
+
+Specifies [SSLCipherSuite](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslciphersuite). Defaults to 'HIGH:MEDIUM:!aNULL:!MD5'.
+
+##### `ssl_honorcipherorder`
+
+Sets [SSLHonorCipherOrder](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslhonorcipherorder), which is used to prefer the server's cipher preference order. Defaults to 'On' in the base `apache` config.
+
+##### `ssl_certs_dir`
+
+Specifies the location of the SSL certification directory. Defaults to '/etc/ssl/certs' on Debian, '/etc/pki/tls/certs' on RedHat, '/usr/local/etc/apache22' on FreeBSD, and '/etc/ssl/apache2' on Gentoo.
+
+##### `ssl_chain`
+
+Specifies the SSL chain. Defaults to 'undef'. (This default works out of the box, but it must be updated in the base `apache` class with your specific certificate information before being used in production.)
+
+##### `ssl_crl`
+
+Specifies the certificate revocation list to use. Defaults to 'undef'. (This default works out of the box but must be updated in the base `apache` class with your specific certificate information before being used in production.)
+
+##### `ssl_crl_path`
+
+Specifies the location of the certificate revocation list. Defaults to 'undef'. (This default works out of the box but must be updated in the base `apache` class with your specific certificate information before being used in production.)
+
+##### `ssl_crl_check`
+
+Sets the certificate revocation check level via the [SSLCARevocationCheck directive](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcarevocationcheck), defaults to 'undef'. This default works out of the box but must be specified when using CRLs in production. Only applicable to Apache 2.4 or higher; the value is ignored on older versions.
+
+##### `ssl_key`
+
+Specifies the SSL key. Defaults are based on your operating system: '/etc/pki/tls/private/localhost.key' for RedHat, '/etc/ssl/private/ssl-cert-snakeoil.key' for Debian, '/usr/local/etc/apache22/server.key' for FreeBSD, and '/etc/ssl/apache2/server.key' on Gentoo. (This default works out of the box but must be updated in the base `apache` class with your specific certificate information before being used in production.)
+
+##### `ssl_verify_client`
+
+Sets the [SSLVerifyClient](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslverifyclient) directive, which sets the certificate verification level for client authentication. Valid values are: 'none', 'optional', 'require', and 'optional_no_ca'. Defaults to 'undef'.
+
+~~~ puppet
+    apache::vhost { 'sample.example.net':
+      …
+      ssl_verify_client => 'optional',
+    }
+~~~
+
+##### `ssl_verify_depth`
+
+Sets the [SSLVerifyDepth](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslverifydepth) directive, which specifies the maximum depth of CA certificates in client certificate verification. Defaults to 'undef'.
+
+~~~ puppet
+    apache::vhost { 'sample.example.net':
+      …
+      ssl_verify_depth => 1,
+    }
+~~~
+
+##### `ssl_proxy_machine_cert`
+
+Sets the [SSLProxyMachineCertificateFile](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxymachinecertificatefile) directive, which specifies an all-in-one file where you keep the certs and keys used for this server to authenticate itself to remote servers.  This file should be a concatenation of the PEM-encoded certificate files in order of preference.  Defaults to 'undef'.
+
+~~~ puppet
+    apache::vhost { 'sample.example.net':
+      …
+      ssl_proxy_machine_cert => '/etc/httpd/ssl/client_certificate.pem',
+    }
+~~~
+
+##### `ssl_options`
+
+Sets the [SSLOptions](http://httpd.apache.org/docs/current/mod/mod_ssl.html#ssloptions) directive, which configures various SSL engine run-time options. This is the global setting for the given vhost and can be a string or an array. Defaults to 'undef'.
+
+A string:
+
+~~~ puppet
+    apache::vhost { 'sample.example.net':
+      …
+      ssl_options => '+ExportCertData',
+    }
+~~~
+
+An array:
+
+~~~ puppet
+    apache::vhost { 'sample.example.net':
+      …
+      ssl_options => [ '+StrictRequire', '+ExportCertData' ],
+    }
+~~~
+
+##### `ssl_openssl_conf_cmd`
+
+Sets the [SSLOpenSSLConfCmd](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslopensslconfcmd) directive, which provides direct configuration of OpenSSL parameters. Defaults to 'undef'.
+
+##### `ssl_proxyengine`
+
+Specifies whether or not to use [SSLProxyEngine](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxyengine). Valid values are 'true' and 'false'. Defaults to 'false'.
+
+####Define: FastCGI Server
+
+This type is intended for use with mod_fastcgi. It allows you to define one or more external FastCGI servers to handle specific file types.
+
+Ex:
+
+~~~ puppet
+apache::fastcgi::server { 'php':
+  host       => '127.0.0.1:9000',
+  timeout    => 15,
+  flush      => false,
+  faux_path  => '/var/www/php.fcgi',
+  fcgi_alias => '/php.fcgi',
+  file_type  => 'application/x-httpd-php'
+}
+~~~
+
+Within your virtual host, you can then configure the specified file type to be handled by the fastcgi server specified above.
+
+~~~ puppet
+apache::vhost { 'www':
+  ...
+  custom_fragment => 'AddType application/x-httpd-php .php'
+  ...
+}
+~~~
+
+##### `host`
+
+The hostname or IP address and TCP port number (1-65535) of the FastCGI server.
+
+##### `timeout`
+
+The number of seconds of FastCGI application inactivity allowed before the request is aborted and the event is logged (at the error LogLevel). The inactivity timer applies only as long as a connection is pending with the FastCGI application. If a request is queued to an application, but the application doesn't respond (by writing and flushing) within this period, the request is aborted. If communication is complete with the application but incomplete with the client (the response is buffered), the timeout does not apply.
+
+##### `flush`
+
+Force a write to the client as data is received from the application. By default, mod_fastcgi buffers data in order to free the application as quickly as possible.
+
+##### `faux_path`
+
+`faux_path` does not have to exist in the local filesystem. URIs that Apache resolves to this filename are handled by this external FastCGI application.
+
+##### `alias`
+
+A unique alias. This is used internally to link the action with the FastCGI server.
+
+##### `file_type`
+
+The MIME-type of the file to be processed by the FastCGI server.
+
+### Private Defines
+
+#### Define: `apache::peruser::multiplexer`
+
+This define checks if an Apache module has a class. If it does, it includes that class. If it does not, it passes the module name to the [`apache::mod`][] define.
+
+#### Define: `apache::peruser::multiplexer`
+
+Enables the [`Peruser`][] module for FreeBSD only.
+
+#### Define: `apache::peruser::processor`
+
+Enables the [`Peruser`][] module for FreeBSD only.
+
+#### Define: `apache::security::file_link`
+
+Links the `activated_rules` from [`apache::mod::security`][] to the respective CRS rules on disk.
+
+### Templates
+
+The Apache module relies heavily on templates to enable the [`apache::vhost`][] and [`apache::mod`][] defines. These templates are built based on [Facter][] facts specific to your operating system. Unless explicitly called out, most templates are not meant for configuration.
+
+## Limitations
+
+### Ubuntu 10.04
+
+The [`apache::vhost::WSGIImportScript`][] parameter creates a statement inside the virtual host that is unsupported on older versions of Apache, causing it to fail. This will be remedied in a future refactoring.
+
+### RHEL/CentOS 5
+
+The [`apache::mod::passenger`][] and [`apache::mod::proxy_html`][] classes are untested since repositories are missing compatible packages.
+
+### RHEL/CentOS 6
+
+The [`apache::mod::passenger`][] class is not installing as the the EL6 repository is missing compatible packages.
+
+### RHEL/CentOS 7
+
+The [`apache::mod::passenger`][] class is untested as the EL7 repository is missing compatible packages, which also blocks us from testing the [`apache::vhost`][] define's [`rack_base_uris`][] parameter.
+
+### General
+
+This module is CI tested against both [open source Puppet][] and [Puppet Enterprise][] on:
+
+- CentOS 5 and 6
+- Ubuntu 12.04 and 14.04
+- Debian 7
+- RHEL 5, 6, and 7
+
+This module also provides functions for other distributions and operating systems, such as FreeBSD, Gentoo, and Amazon Linux, but is not formally tested on them and are subject to regressions.
+
+### SELinux and custom paths
+
+If [SELinux][] is in [enforcing mode][] and you want to use custom paths for `logroot`, `mod_dir`, `vhost_dir`, and `docroot`, you need to manage the files' context yourself.
+
+You can do this with Puppet:
+
+~~~ puppet
+exec { 'set_apache_defaults':
+  command => 'semanage fcontext -a -t httpd_sys_content_t "/custom/path(/.*)?"',
+  path    => '/bin:/usr/bin/:/sbin:/usr/sbin',
+  require => Package['policycoreutils-python'],
+}
+
+package { 'policycoreutils-python':
+  ensure => installed,
+}
+
+exec { 'restorecon_apache':
+  command => 'restorecon -Rv /apache_spec',
+  path    => '/bin:/usr/bin/:/sbin:/usr/sbin',
+  before  => Class['Apache::Service'],
+  require => Class['apache'],
+}
+
+class { 'apache': }
+
+host { 'test.server':
+  ip => '127.0.0.1',
+}
+
+file { '/custom/path':
+  ensure => directory,
+}
+
+file { '/custom/path/include':
+  ensure  => present,
+  content => '#additional_includes',
+}
+
+apache::vhost { 'test.server':
+  docroot             => '/custom/path',
+  additional_includes => '/custom/path/include',
+}
+~~~
+
+You need to set the contexts using `semanage fcontext` instead of `chcon` because Puppet's `file` resources reset the values' context in the database if the resource doesn't specify it.
+
+### FreeBSD
+
+In order to use this module on FreeBSD, you _must_ use apache24-2.4.12 (www/apache24) or newer.
+
+## Development
+
+### Contributing
+
+[Puppet Labs][] modules on the [Puppet Forge][] are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad hardware, software, and deployment configurations that Puppet is intended to serve.
+
+We want to make it as easy as possible to contribute changes so our modules work in your environment, but we also need contributors to follow a few guidelines to help us maintain and improve the modules' quality.
+
+For more information, please read the complete [module contribution guide][].
+
+### Running tests
+
+This project contains tests for both [rspec-puppet][] and [beaker-rspec][] to verify functionality. For detailed information on using these tools, please see their respective documentation.
+
+#### Testing quickstart: Ruby > 1.8.7
+
+~~~
+gem install bundler
+bundle install
+bundle exec rake spec
+bundle exec rspec spec/acceptance
+RS_DEBUG=yes bundle exec rspec spec/acceptance
+~~~
+
+#### Testing quickstart: Ruby = 1.8.7
+
+~~~
+gem install bundler
+bundle install --without system_tests
+bundle exec rake spec
+~~~
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/README.passenger.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,296 @@
+# Passenger
+
+Just enabling the Passenger module is insufficient for the use of Passenger in
+production. Passenger should be tunable to better fit the environment in which
+it is run while being aware of the resources it required.
+
+To this end the Apache passenger module has been modified to apply system wide
+Passenger tuning declarations to `passenger.conf`. Declarations specific to a
+virtual host should be passed through when defining a `vhost` (e.g.
+`rack_base_uris` parameter on the `apache::vhost` type, check `README.md`).
+
+Also, general apache module loading parameters can be supplied to enable using
+a customized passenger module in place of a default-package-based version of
+the module.
+
+## Operating system support and Passenger versions
+
+The most important configuration directive for the Apache Passenger module is
+`PassengerRoot`. Its value depends on the Passenger version used (2.x, 3.x or
+4.x) and on the operating system package from which the Apache Passenger module
+is installed.
+
+The following table summarises the current *default versions* and
+`PassengerRoot` settings for the operating systems supported by
+puppetlabs-apache:
+
+OS               | Passenger version  | `PassengerRoot` 
+---------------- | ------------------ | ----------------
+Debian 7         | 3.0.13             | /usr
+Debian 8         | 4.0.53             | /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini
+Ubuntu 12.04     | 2.2.11             | /usr
+Ubuntu 14.04     | 4.0.37             | /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini 
+RHEL with EPEL6  | 3.0.21             | /usr/lib/ruby/gems/1.8/gems/passenger-3.0.21 
+
+As mentioned in `README.md` there are no compatible packages available for
+RHEL/CentOS 5 or RHEL/CentOS 7.
+
+### Configuration files and locations on RHEL/CentOS
+
+Notice two important points:
+
+1. The Passenger version packaged in the EPEL repositories may change over time.
+2. The value of `PassengerRoot` depends on the Passenger version installed.
+
+To prevent the puppetlabs-apache module from having to keep up with these
+package versions the Passenger configuration files installed by the
+packages are left untouched by this module. All configuration is placed in an
+extra configuration file managed by puppetlabs-apache.
+
+This means '/etc/httpd/conf.d/passenger.conf' is installed by the
+`mod_passenger` package and contains correct values for `PassengerRoot` and
+`PassengerRuby`. Puppet will ignore this file. Additional configuration
+directives as described in the remainder of this document are placed in
+'/etc/httpd/conf.d/passenger_extra.conf', managed by Puppet.
+
+This pertains *only* to RHEL/CentOS, *not* Debian and Ubuntu.
+
+### Third-party and custom Passenger packages and versions
+
+The Passenger version distributed by the default OS packages may be too old to
+be useful. Newer versions may be installed via Gems, from source or from
+third-party OS packages.
+
+Most notably the Passenger developers officially provide Debian packages for a
+variety of Debian and Ubuntu releases in the [Passenger APT
+repository](https://oss-binaries.phusionpassenger.com/apt/passenger). Read more
+about [installing these packages in the offical user
+guide](http://www.modrails.com/documentation/Users%20guide%20Apache.html#install_on_debian_ubuntu).
+
+If you install custom Passenger packages and newer version make sure to set the
+directives `PassengerRoot`, `PassengerRuby` and/or `PassengerDefaultRuby`
+correctly, or Passenger and Apache will fail to function properly.
+
+For Passenger 4.x packages on Debian and Ubuntu the `PassengerRoot` directive
+should almost universally be set to
+`/usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini`.
+
+## Parameters for `apache::mod::passenger`
+
+The following class parameters configure Passenger in a global, server-wide
+context.
+
+Example:
+
+```puppet
+class { 'apache::mod::passenger':
+  passenger_root             => '/usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini',
+  passenger_default_ruby     => '/usr/bin/ruby1.9.3',
+  passenger_high_performance => 'on',
+  rails_autodetect           => 'off',
+  mod_lib_path               => '/usr/lib/apache2/custom_modules',
+}
+```
+
+The general form is using the all lower-case version of the configuration
+directive, with underscores instead of CamelCase.
+
+### Parameters used with passenger.conf
+
+If you pass a default value to `apache::mod::passenger` it will be ignored and
+not passed through to the configuration file. 
+
+#### passenger_root
+
+The location to the Phusion Passenger root directory. This configuration option
+is essential to Phusion Passenger, and allows Phusion Passenger to locate its
+own data files. 
+
+The default depends on the Passenger version and the means of installation. See
+the above section on operating system support, versions and packages for more
+information.
+
+http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerroot_lt_directory_gt
+
+#### passenger_default_ruby
+
+This option specifies the default Ruby interpreter to use for web apps as well
+as for all sorts of internal Phusion Passenger helper scripts, e.g. the one
+used by PassengerPreStart.
+
+This directive was introduced in Passenger 4.0.0 and will not work in versions
+< 4.x. Do not set this parameter if your Passenger version is older than 4.0.0.
+
+Defaults to `undef` for all operating systems except Ubuntu 14.04, where it is
+set to '/usr/bin/ruby'.
+
+http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerDefaultRuby
+
+#### passenger_ruby
+
+This directive is the same as `passenger_default_ruby` for Passenger versions
+< 4.x and must be used instead of `passenger_default_ruby` for such versions.
+
+It makes no sense to set `PassengerRuby` for Passenger >= 4.x. That
+directive should only be used to override the value of `PassengerDefaultRuby`
+on a non-global context, i.e. in `<VirtualHost>`, `<Directory>`, `<Location>`
+and so on.
+
+Defaults to `/usr/bin/ruby` for all supported operating systems except Ubuntu
+14.04, where it is set to `undef`.
+
+http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerRuby
+
+#### passenger_high_performance
+
+Default is `off`. When turned `on` Passenger runs in a higher performance mode
+that can be less compatible with other Apache modules.
+
+http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerHighPerformance
+
+#### passenger_max_pool_size
+
+Sets the maximum number of Passenger application processes that may
+simultaneously run. The default value is 6.
+
+http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengermaxpoolsize_lt_integer_gt
+
+#### passenger_pool_idle_time
+
+The maximum number of seconds a Passenger Application process will be allowed
+to remain idle before being shut down. The default value is 300.
+
+http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerPoolIdleTime
+
+#### passenger_max_requests
+
+The maximum number of request a Passenger application will process before being
+restarted. The default value is 0, which indicates that a process will only
+shut down if the Pool Idle Time (see above) expires.
+
+http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerMaxRequests
+
+#### passenger_spawn_method
+
+Sets the method by which Ruby application processes are spawned. Default is 'smart',
+which caches code using the app preloader.
+
+Passenger >= 4.0 renamed `conservative` to `direct` and `smart-lv2` to `smart`.
+
+https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#PassengerSpawnMethod
+
+#### passenger_stat_throttle_rate
+
+Sets how often Passenger performs file system checks, at most once every _x_
+seconds. Default is 0, which means the checks are performed with every request.
+
+http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerstatthrottlerate_lt_integer_gt
+
+#### rack_autodetect
+
+Should Passenger automatically detect if the document root of a virtual host is
+a Rack application. Not set by default (`undef`). Note that this directive has
+been removed in Passenger 4.0.0 and `PassengerEnabled` should be used instead.
+Use this directive only on Passenger < 4.x.
+
+http://www.modrails.com/documentation/Users%20guide%20Apache.html#_rackautodetect_lt_on_off_gt
+
+#### rails_autodetect
+
+Should Passenger automatically detect if the document root of a virtual host is
+a Rails application.  Not set by default (`undef`). Note that this directive
+has been removed in Passenger 4.0.0 and `PassengerEnabled` should be used
+instead. Use this directive only on Passenger < 4.x.
+
+http://www.modrails.com/documentation/Users%20guide%20Apache.html#_railsautodetect_lt_on_off_gt
+
+#### passenger_use_global_queue
+
+Allows toggling of PassengerUseGlobalQueue.  NOTE: PassengerUseGlobalQueue is
+the default in Passenger 4.x and the versions >= 4.x have disabled this
+configuration option altogether.  Use with caution.
+
+#### passenger_app_env
+
+Sets the global default `PassengerAppEnv` for Passenger applications. Not set by
+default (`undef`) and thus defaults to Passenger's built-in value of 'production'.
+This directive can be overridden in an `apache::vhost` resource.
+
+https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#PassengerAppEnv
+
+### Parameters used to load the module
+
+Unlike the tuning parameters specified above, the following parameters are only
+used when loading customized passenger modules.
+
+#### mod_package
+
+Allows overriding the default package name used for the passenger module
+package.
+
+#### mod_package_ensure
+
+Allows overriding the package installation setting used by puppet when
+installing the passenger module. The default is 'present'.
+
+#### mod_id
+
+Allows overriding the value used by apache to identify the passenger module.
+The default is 'passenger_module'.
+
+#### mod_lib_path
+
+Allows overriding the directory path used by apache when loading the passenger
+module. The default is the value of `$apache::params::lib_path`.
+
+#### mod_lib
+
+Allows overriding the library file name used by apache when loading the
+passenger module. The default is 'mod_passenger.so'.
+
+#### mod_path
+
+Allows overriding the full path to the library file used by apache when loading
+the passenger module. The default is the concatenation of the `mod_lib_path`
+and `mod_lib` parameters.
+
+## Dependencies
+
+RedHat-based systems will need to configure additional package repositories in
+order to install Passenger, specifically:
+
+* [Extra Packages for Enterprise Linux](https://fedoraproject.org/wiki/EPEL)
+* [Phusion Passenger](http://passenger.stealthymonkeys.com)
+
+Configuration of these repositories is beyond the scope of this module and is
+left to the user.
+
+## Attribution
+
+The Passenger tuning parameters for the `apache::mod::passenger` Puppet class
+was modified by Aaron Hicks (hicksa@landcareresearch.co.nz) for work on the
+NeSI Project and the Tuakiri New Zealand Access Federation as a fork from the
+PuppetLabs Apache module on GitHub.
+
+* https://github.com/puppetlabs/puppetlabs-apache
+* https://github.com/nesi/puppetlabs-apache
+* http://www.nesi.org.nz//
+* https://tuakiri.ac.nz/confluence/display/Tuakiri/Home
+
+## Copyright and License
+
+Copyright (C) 2012 [Puppet Labs](https://www.puppetlabs.com/) Inc
+
+Puppet Labs can be contacted at: info@puppetlabs.com
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/Rakefile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+require 'puppetlabs_spec_helper/rake_tasks'
+require 'puppet-lint/tasks/puppet-lint'
+
+PuppetLint.configuration.fail_on_warnings = true
+PuppetLint.configuration.send('relative')
+PuppetLint.configuration.send('disable_80chars')
+PuppetLint.configuration.send('disable_class_inherits_from_params_class')
+PuppetLint.configuration.send('disable_documentation')
+PuppetLint.configuration.send('disable_single_quote_string_with_variables')
+PuppetLint.configuration.send('disable_only_variable_string')
+PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/checksums.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,306 @@
+{
+  "CHANGELOG.md": "4239b3b5d09a705701f0f094f5f3bc19",
+  "CONTRIBUTING.md": "e2b8e8e433fc76b3798b7fe435f49375",
+  "Gemfile": "d262f36a5323e0401b5f6adfb503b050",
+  "LICENSE": "b3f8a01d8699078d82e8c3c992307517",
+  "README.md": "d42f537c4d44d81284f169b76eda4300",
+  "README.passenger.md": "99ec9f5efc167ec7edc6f92f5afdf757",
+  "Rakefile": "ed3db0e49f5fcb381a19542c08ec473f",
+  "examples/apache.pp": "819cf9116ffd349e6757e1926d11ca2f",
+  "examples/dev.pp": "9f5727f69f536538f8d840fad0852308",
+  "examples/init.pp": "4eac4a7ef68499854c54a78879e25535",
+  "examples/mod_load_params.pp": "5981af4d625a906fce1cedeb3f70cb90",
+  "examples/mods.pp": "0085911ba562b7e56ad8d793099c9240",
+  "examples/mods_custom.pp": "9afd068edce0538b5c55a3bc19f9c24a",
+  "examples/php.pp": "60e7939034d531dd6b95af35338bcbe7",
+  "examples/vhost.pp": "bd91438534d12511b01f31fe8d10cd35",
+  "examples/vhost_directories.pp": "b4e6b5a596e5bae122233652b9a33e32",
+  "examples/vhost_filter.pp": "cd8ec7303f3bb508c88a473c43d31f0a",
+  "examples/vhost_ip_based.pp": "7d9f7b6976de7488ab6ff0a6e647fc73",
+  "examples/vhost_proxypass.pp": "59b87f88943aa809578288e26b41aade",
+  "examples/vhost_ssl.pp": "9f3716bc15a9a6760f1d6cc3bf8ce8ac",
+  "examples/vhosts_without_listen.pp": "a6692104056a56517b4365bcc816e7f4",
+  "files/httpd": "295f5e924afe6f752d29327e73fe6d0a",
+  "lib/puppet/parser/functions/bool2httpd.rb": "05d5deeb6e0c31acee7c55b249ec8e06",
+  "lib/puppet/parser/functions/validate_apache_log_level.rb": "d75bc4ef17ff5c9a1f94dd3948e733d1",
+  "lib/puppet/provider/a2mod/a2mod.rb": "d986d8e8373f3f31c97359381c180628",
+  "lib/puppet/provider/a2mod/gentoo.rb": "2492d446adbb68f678e86a75eb7ff3bd",
+  "lib/puppet/provider/a2mod/modfix.rb": "b689a1c83c9ccd8590399c67f3e588e5",
+  "lib/puppet/provider/a2mod/redhat.rb": "c39b80e75e7d0666def31c2a6cdedb0b",
+  "lib/puppet/provider/a2mod.rb": "03ed73d680787dd126ea37a03be0b236",
+  "lib/puppet/type/a2mod.rb": "9042ccc045bfeecca28bebb834114f05",
+  "manifests/balancer.pp": "59ae0052030a0b077192f697a5b42e9e",
+  "manifests/balancermember.pp": "8f44f65124330b7e9b49a7100f86fe6d",
+  "manifests/confd/no_accf.pp": "406d0ca41c3b90f83740ca218dc3f484",
+  "manifests/custom_config.pp": "a09cee5fafab474343e291f319d51dc4",
+  "manifests/default_confd_files.pp": "86fdbe5773abb7c2da26db096973865c",
+  "manifests/default_mods/load.pp": "bc0b3b65edd1ba6178c09672352f9bce",
+  "manifests/default_mods.pp": "f6f6ecfaaca79a7eec50335daa9eaf40",
+  "manifests/dev.pp": "9285af7f4e3b343a8695af3897dfdb07",
+  "manifests/fastcgi/server.pp": "a47073f4447baef318c823f93b5f59ee",
+  "manifests/init.pp": "4aae6d1d55218dd512b1e87a5bfc2668",
+  "manifests/listen.pp": "f7e224cba3b8021f90511af4f43d8b1f",
+  "manifests/mod/actions.pp": "ec2a5d1cf54790204750f9b67938d230",
+  "manifests/mod/alias.pp": "b920887e67857a09252c10e30949c85c",
+  "manifests/mod/auth_basic.pp": "dffef6ff10145393cb78fcaa27220c53",
+  "manifests/mod/auth_cas.pp": "a20c718cc3ffab32f7c72f42160a5602",
+  "manifests/mod/auth_kerb.pp": "08d536cb13281db3b9ed9a966ad431fd",
+  "manifests/mod/auth_mellon.pp": "85e7085a44b3039e4a2c7b463ca8bdb2",
+  "manifests/mod/authn_core.pp": "4db773ddbc0d875230085782d4521951",
+  "manifests/mod/authn_file.pp": "eeb11513490beee901574746faaeabdf",
+  "manifests/mod/authnz_ldap.pp": "e3f91908be35306a488b44c55608b2a0",
+  "manifests/mod/authz_default.pp": "b7c94cfa4e008155fffd241d35834064",
+  "manifests/mod/authz_user.pp": "d446c90c44304594206bd2a0112be625",
+  "manifests/mod/autoindex.pp": "05112ccb06dc218f9a7b937767a6ea2d",
+  "manifests/mod/cache.pp": "b56d68b9401ba3e02a1f2fe55cdfbcca",
+  "manifests/mod/cgi.pp": "558a0350d1e8634a706543e0c6e28687",
+  "manifests/mod/cgid.pp": "f9cea0ad9269bf134637c7c667469842",
+  "manifests/mod/dav.pp": "9df80d36dd609be9032a8260aa9d10c1",
+  "manifests/mod/dav_fs.pp": "4528673b6e8d0af6935d9d630028b9f0",
+  "manifests/mod/dav_svn.pp": "f021fe8048deaa06759cd0b96b450363",
+  "manifests/mod/deflate.pp": "324c867212f6d9e4593cc4aba392f590",
+  "manifests/mod/dev.pp": "42673bab60b6fc0f3aa6e2357ec0a27c",
+  "manifests/mod/dir.pp": "8e577c570ba5e835c4f82232a1c01a4e",
+  "manifests/mod/disk_cache.pp": "e5b39902f6198d9e0851e551b7a5bf40",
+  "manifests/mod/event.pp": "0d70f0733492c6c192e5ba6f6b3f3698",
+  "manifests/mod/expires.pp": "069783635a7a4f97af535cc149da6589",
+  "manifests/mod/ext_filter.pp": "ba8f2bb429a0ed12880b80294430ae7e",
+  "manifests/mod/fastcgi.pp": "237ff6ebc17c35ee2e3c82d2e19cd442",
+  "manifests/mod/fcgid.pp": "1e57a267408ca82fc258a244299ee15f",
+  "manifests/mod/filter.pp": "b0039f3ae932b1204994ef2180dd76d2",
+  "manifests/mod/geoip.pp": "2a963d07231897e8d6928df6dc913676",
+  "manifests/mod/headers.pp": "ef3de538a0a4c9406236faf43eb89710",
+  "manifests/mod/include.pp": "a3b66eda88e38d90825c16b834bacd8d",
+  "manifests/mod/info.pp": "bad325232ff8038449dcafc11ff37ca1",
+  "manifests/mod/itk.pp": "5dea86531cd543d26436bfae4a357481",
+  "manifests/mod/ldap.pp": "367f13080f78b3e8527172cbb8a2fd4a",
+  "manifests/mod/mime.pp": "9d13abceb29f36c2f6c3a5a71a77561f",
+  "manifests/mod/mime_magic.pp": "481e016b74b0649bfdcbb32104a62054",
+  "manifests/mod/negotiation.pp": "6860ed514001b9f3f6945c78d250fd32",
+  "manifests/mod/nss.pp": "9d1573a9af62cc17cb9b8e322cf2a2b7",
+  "manifests/mod/pagespeed.pp": "2638c14081f8065bc8940b8d47782cc3",
+  "manifests/mod/passenger.pp": "905ffc24cd4693bdc34beade9ec1c919",
+  "manifests/mod/perl.pp": "0bc488e1ac33e4e8987e0b07aa909682",
+  "manifests/mod/peruser.pp": "70cdb0592f53ec17f06365812e3e59c9",
+  "manifests/mod/php.pp": "628b672c8a28d1ebd43bedde63a5dfd3",
+  "manifests/mod/prefork.pp": "1dd2f9b1dfc702138401ca9b923548b4",
+  "manifests/mod/proxy.pp": "39e224390d43ffe082ff60fba2b97fc4",
+  "manifests/mod/proxy_ajp.pp": "073e2406aea7822750d4c21f02d8ac80",
+  "manifests/mod/proxy_balancer.pp": "6d16440ba6bed5427b331b6c6abf4063",
+  "manifests/mod/proxy_connect.pp": "574df18a67e478a3be903238ade3d334",
+  "manifests/mod/proxy_html.pp": "1a8ef7d17e65954aab303e3547e02f22",
+  "manifests/mod/proxy_http.pp": "0db1b26f8b4036b0d46ba86b7eaac561",
+  "manifests/mod/python.pp": "15f03d79e45737fdf0afca9665706b88",
+  "manifests/mod/remoteip.pp": "7fa5b92322df550f58421b24a53dbb01",
+  "manifests/mod/reqtimeout.pp": "aee3d869e6ca6eed18071c8d2aa97aff",
+  "manifests/mod/rewrite.pp": "292f2d6ce2078fa9df7f686105ea7b95",
+  "manifests/mod/rpaf.pp": "4844d717d6577aee8a788a7fbdc5e8dd",
+  "manifests/mod/security.pp": "316e0fe56fa245777035fb9b7e3db8ff",
+  "manifests/mod/setenvif.pp": "b2ae43541bf1df5374187339e50a081f",
+  "manifests/mod/shib.pp": "3e2d3b5bf864fd292fa30f7c98d449f6",
+  "manifests/mod/speling.pp": "fa89a82933d30d2ebfe11e3ad9966bd1",
+  "manifests/mod/ssl.pp": "3d733329e9f568f68229617cf806b0c1",
+  "manifests/mod/status.pp": "0b24de931fd8d54b2db0e3d16f0d0d8c",
+  "manifests/mod/suexec.pp": "2a8671856a0ece597e9b57867dc35e76",
+  "manifests/mod/suphp.pp": "6905059571fa21b7de957fd90540acff",
+  "manifests/mod/userdir.pp": "bbe716e8ff38815a51cc4eaaa0c1e4df",
+  "manifests/mod/version.pp": "6cb31057ebffa796f95642cc95f9499d",
+  "manifests/mod/vhost_alias.pp": "ee1225a748daaf50aca39a6d93fb8470",
+  "manifests/mod/worker.pp": "f806408a8f9fcb66ca3719ed4d17f9bc",
+  "manifests/mod/wsgi.pp": "0377fe287e51f4a396bd15b47f2628cc",
+  "manifests/mod/xsendfile.pp": "fba06f05a19c466654aca5ecaa705bf0",
+  "manifests/mod.pp": "4030a00ce143488fe988988ded36f059",
+  "manifests/mpm.pp": "32ed668ad674ed01a4b1c53e480a34be",
+  "manifests/namevirtualhost.pp": "67618d40112e4ddc1b46f64af2a5e875",
+  "manifests/package.pp": "90f8e969c4f920a1e898ae2f6420e438",
+  "manifests/params.pp": "8b00de3c0b1f48d4f7a592ca02875a4f",
+  "manifests/peruser/multiplexer.pp": "0ea75341b7a93e55bcfb431a93b1a6c9",
+  "manifests/peruser/processor.pp": "62f0ad5ed2ec36dadc7f40ad2a9e1bb9",
+  "manifests/php.pp": "9c9d07e12bf5d112b0b54f5bd69046fc",
+  "manifests/proxy.pp": "7c8515b88406922e148322ee15044b29",
+  "manifests/python.pp": "ddef4cd73850fdc2dc126d4579c30adf",
+  "manifests/security/rule_link.pp": "4635131018b0c5cd5f57ecea9f708b65",
+  "manifests/service.pp": "e0821dac17ef2bc00068ceae06bc17d9",
+  "manifests/ssl.pp": "173f3d6a7fd2b5f4100c4ff03d84e13b",
+  "manifests/version.pp": "bcc947740e4357cbdc9a1d54f44305c7",
+  "manifests/vhost.pp": "bb2a1fd81cc567fd47757f11ff0554f9",
+  "metadata.json": "3a0834423fe75c8ceefa4df90bee9868",
+  "spec/acceptance/apache_parameters_spec.rb": "b861261b4483bca8c852096848580605",
+  "spec/acceptance/apache_ssl_spec.rb": "9813a93162e56c80b9eb6c286084437a",
+  "spec/acceptance/class_spec.rb": "1e4477b142bf6705a3145da1271be7e1",
+  "spec/acceptance/custom_config_spec.rb": "3593b2427367a1db5198ada9ef7eb30c",
+  "spec/acceptance/default_mods_spec.rb": "32826e1a7f6b99511b2937ab37b8f5cd",
+  "spec/acceptance/itk_spec.rb": "45401fe10b565ee9bf86900346a51a85",
+  "spec/acceptance/mod_dav_svn_spec.rb": "921cddd8b1f7f506859aaaae6cfd2c8a",
+  "spec/acceptance/mod_deflate_spec.rb": "cc2d1a68c6c53b17b1b9642e3fa2631f",
+  "spec/acceptance/mod_fcgid_spec.rb": "514cfb3b6bc81ddd0417271be8925956",
+  "spec/acceptance/mod_mime_spec.rb": "d753fad7136ef4c4b9034b32f0ddbcf8",
+  "spec/acceptance/mod_negotiation_spec.rb": "9d83d468dc13b179791fd4360c465aaf",
+  "spec/acceptance/mod_pagespeed_spec.rb": "0cc476dde6ba35804bb550b2b6f8e168",
+  "spec/acceptance/mod_passenger_spec.rb": "ab5d64d96ffbf54f50c11d71f37544d7",
+  "spec/acceptance/mod_php_spec.rb": "a91b953539eba21e64e9ddeee4a37f21",
+  "spec/acceptance/mod_proxy_html_spec.rb": "649c2bf1f251900fac5e9c81930aa6fd",
+  "spec/acceptance/mod_security_spec.rb": "78e0f0c5640f962a4df9ed86f448d49c",
+  "spec/acceptance/mod_suphp_spec.rb": "1e675ae7fcdbba8b1abbd1a96b59a060",
+  "spec/acceptance/nodesets/centos-70-x64.yml": "0ae796256280ca157abc98f7cb492ea4",
+  "spec/acceptance/nodesets/debian-607-x64.yml": "52f42f3b8fc507a5fc825977d62665a3",
+  "spec/acceptance/nodesets/debian-70rc1-x64.yml": "717aa92150ebe3fca718807c7c93126f",
+  "spec/acceptance/nodesets/debian-73-i386.yml": "40aeb7ceab29148bb98a1e2bd51aba86",
+  "spec/acceptance/nodesets/debian-73-x64.yml": "df78f357e1bd0f7f9818d552eeb35026",
+  "spec/acceptance/nodesets/default.yml": "40a4f108ab83030fdfdcc230ecaaed9a",
+  "spec/acceptance/nodesets/fedora-18-x64.yml": "9c907e4416a5fd487ff30a672a6b1c9e",
+  "spec/acceptance/nodesets/ubuntu-server-10044-x64.yml": "75e86400b7889888dc0781c0ae1a1297",
+  "spec/acceptance/nodesets/ubuntu-server-12042-x64.yml": "d30d73e34cd50b043c7d14e305955269",
+  "spec/acceptance/nodesets/ubuntu-server-1310-x64.yml": "9deb39279e104d765179b471c6ebb3a2",
+  "spec/acceptance/nodesets/ubuntu-server-1404-x64.yml": "5f0aed10098ac5b78e4217bb27c7aaf0",
+  "spec/acceptance/prefork_worker_spec.rb": "0994c75d9f6aab28040c86c2ae4e4eac",
+  "spec/acceptance/service_spec.rb": "24ce3caa9990b2f06ac98c7c438e1d5c",
+  "spec/acceptance/unsupported_spec.rb": "ecb65438d469b70dd7c611414f535771",
+  "spec/acceptance/version.rb": "bedfcffe1a6f47824defd167f1d3330e",
+  "spec/acceptance/vhost_spec.rb": "3e9984063d47f1ab711981aeca7b2a59",
+  "spec/classes/apache_spec.rb": "78aca0aa08985673b985cc43b440bfcd",
+  "spec/classes/dev_spec.rb": "549f0e09b6b0c2b8f612b44150d8d357",
+  "spec/classes/mod/alias_spec.rb": "cb7fa1744b0624ec6d04d6dba80bccda",
+  "spec/classes/mod/auth_cas_spec.rb": "34af1e2489fe7f805c760c40b2bc3f5b",
+  "spec/classes/mod/auth_kerb_spec.rb": "56066a4060352f76efdad26fe51b2e20",
+  "spec/classes/mod/auth_mellon_spec.rb": "7c2051910216cf069752f5a2f34e89e0",
+  "spec/classes/mod/authnz_ldap_spec.rb": "ce2f5fb517d4cc760c913fe131b1550f",
+  "spec/classes/mod/dav_svn_spec.rb": "6cf5fbd5e73c455f0f5afa01561cc704",
+  "spec/classes/mod/deflate_spec.rb": "a5b6afd416cbad17f21d5c86c83c3485",
+  "spec/classes/mod/dev_spec.rb": "78d215d7ef3a8e2df3e8789eb75fc4ca",
+  "spec/classes/mod/dir_spec.rb": "555e4b21a18422034b8b16560a1034a1",
+  "spec/classes/mod/disk_cache.rb": "50f464d34fda0d1e07248b3f7ff0cfef",
+  "spec/classes/mod/event_spec.rb": "d8d0bd5dee8a4bf2dcd709326dfdd4e2",
+  "spec/classes/mod/expires_spec.rb": "a9ff97bcca20bb17102efd88ea0462e6",
+  "spec/classes/mod/ext_filter_spec.rb": "7dea570f81d62613823e9800c12a4e5b",
+  "spec/classes/mod/fastcgi_spec.rb": "76ac8328da6c2fe1e126d8dcdcdb5519",
+  "spec/classes/mod/fcgid_spec.rb": "5baa913ba69842771fab4b58c8677544",
+  "spec/classes/mod/info_spec.rb": "4b829ceca7c9b90c3eefafa391eb8e80",
+  "spec/classes/mod/itk_spec.rb": "437d4e4e776e082db051c99cb05a1058",
+  "spec/classes/mod/mime_magic_spec.rb": "8291c37b89f9d50f58fa94ab9cbb1bfe",
+  "spec/classes/mod/mime_spec.rb": "5e527739b595f9b0638ce384648c3187",
+  "spec/classes/mod/negotiation_spec.rb": "f1b10fe931b96f72f5d0eaf86354fce9",
+  "spec/classes/mod/pagespeed_spec.rb": "482d0dc3ebf002155d3c728d2043bcac",
+  "spec/classes/mod/passenger_spec.rb": "4f535abcd2f9fa8f9910866133c6b48f",
+  "spec/classes/mod/perl_spec.rb": "11fb2ae842e64d467ccf70813ef3de7d",
+  "spec/classes/mod/peruser_spec.rb": "c379ce85a997789856b12c27957bf994",
+  "spec/classes/mod/php_spec.rb": "a88c78ba9bf9dd190c93617257d1ad15",
+  "spec/classes/mod/prefork_spec.rb": "d82f0f25691ba019b912cd000dbb845f",
+  "spec/classes/mod/proxy_connect_spec.rb": "bc0d0d6328288cd91d84ac9de66e9019",
+  "spec/classes/mod/proxy_html_spec.rb": "893bfa8dba37e63a24229e28cc74d073",
+  "spec/classes/mod/python_spec.rb": "45736e6305ca541ba29f997b8e7dd0ef",
+  "spec/classes/mod/remoteip_spec.rb": "e8840c791f3561c6d466040b888551ed",
+  "spec/classes/mod/reqtimeout_spec.rb": "cee7de04531d3fb49d75f8f8a7c2b493",
+  "spec/classes/mod/rpaf_spec.rb": "1845e640c44f8daeeffb13b29a26da84",
+  "spec/classes/mod/security_spec.rb": "a6c7526a69306c1993376e9e0646354f",
+  "spec/classes/mod/shib_spec.rb": "18107e156dd4682f59ddcc33c0dfc0d7",
+  "spec/classes/mod/speling_spec.rb": "4727fbb92f074e0cf3911e6cffe3322f",
+  "spec/classes/mod/ssl_spec.rb": "ce2114982774840242ab652f5fa985c3",
+  "spec/classes/mod/status_spec.rb": "1c7520050c8bed47492acd51588be52d",
+  "spec/classes/mod/suphp_spec.rb": "0c4d625a64124e7c9c14ea2b68dc7ebe",
+  "spec/classes/mod/worker_spec.rb": "c326e36fbcfe9f0c59dc1db389a33926",
+  "spec/classes/mod/wsgi_spec.rb": "532da8779e878372ff29b51dfaefceea",
+  "spec/classes/params_spec.rb": "7bb6270f0338de41e1c34bd77cd844b7",
+  "spec/classes/service_spec.rb": "2d0abb70fc2b14f37121f6f7a683cc68",
+  "spec/defines/balancermember_spec.rb": "6071ddc9a56be6ecccfade6e233fb34b",
+  "spec/defines/custom_config_spec.rb": "a7e3392933cabc8ed6bb57deaebb36d9",
+  "spec/defines/fastcgi_server_spec.rb": "5798af8e6380d05f3ab38f4788b5c47c",
+  "spec/defines/mod_spec.rb": "a71fbfa5d62e9118a84c08138de9a248",
+  "spec/defines/modsec_link_spec.rb": "3421b21f8234637dd1c32ebcf89e44c3",
+  "spec/defines/vhost_spec.rb": "af562b687be3c1dbe748710d3d27b0e3",
+  "spec/spec.opts": "a600ded995d948e393fbe2320ba8e51c",
+  "spec/spec_helper.rb": "eb7ec6afb39e2282e62f2ebf69712707",
+  "spec/spec_helper_acceptance.rb": "795da947f77a56cebcbc059c7d549952",
+  "spec/unit/provider/a2mod/gentoo_spec.rb": "8cf6574e75a4a7e8ff5a92d75a8d7ea8",
+  "spec/unit/puppet/parser/functions/bool2httpd_spec.rb": "3c47a968139400e5b81af8650f2d0e21",
+  "spec/unit/puppet/parser/functions/validate_apache_log_level.rb": "8f558fd81d1655e9ab20896152eca512",
+  "templates/confd/no-accf.conf.erb": "a614f28c4b54370e4fa88403dfe93eb0",
+  "templates/fastcgi/server.erb": "482ce7a72a08f21e3592e584178d5917",
+  "templates/httpd.conf.erb": "fbe8a36d798a0e1c39d31bcd969f837a",
+  "templates/listen.erb": "6286aa08f9e28caee54b1e1ee031b9d6",
+  "templates/mod/alias.conf.erb": "71028c659b7d1784c0e9f373846c8457",
+  "templates/mod/auth_cas.conf.erb": "74595985c3b0f9df1aaa0ad5dd7a7906",
+  "templates/mod/auth_mellon.conf.erb": "4e17d22a8f1bc312e976e8513199c945",
+  "templates/mod/authnz_ldap.conf.erb": "12c9a1482694ddad3143e5eef03fb531",
+  "templates/mod/autoindex.conf.erb": "2421a3c6df32c7e38c2a7a22afdf5728",
+  "templates/mod/cgid.conf.erb": "f8ce27d60bc495bab16de2696ebb2fd0",
+  "templates/mod/dav_fs.conf.erb": "10c1131168e35319e22b3fbfe51aebfd",
+  "templates/mod/deflate.conf.erb": "e866ecf2bfe8e42ea984267f569723db",
+  "templates/mod/dir.conf.erb": "2485da78a2506c14bf51dde38dd03360",
+  "templates/mod/disk_cache.conf.erb": "48d1b54ec1dedea7f68451bc0774790e",
+  "templates/mod/event.conf.erb": "469ef574b0ae1728203002a52f3d5a3b",
+  "templates/mod/expires.conf.erb": "7a77f8b1d50c53ee77a6cb798c51a2b9",
+  "templates/mod/ext_filter.conf.erb": "4e4e4143ab402a9f9d51301b1a192202",
+  "templates/mod/fastcgi.conf.erb": "ab125b9bfdc494b621eec41587bf6101",
+  "templates/mod/geoip.conf.erb": "93b95f44ec733ee8231be82381e02782",
+  "templates/mod/info.conf.erb": "dd434aca2b3693c425a2c252a2c39f46",
+  "templates/mod/itk.conf.erb": "eff84b78e4f2f8c5c3a2e9fc4b8aad16",
+  "templates/mod/ldap.conf.erb": "57a006daca5fdacc094a872f9f0a4535",
+  "templates/mod/load.erb": "01132434e6101080c41548b0ba7e57d8",
+  "templates/mod/mime.conf.erb": "8f953519790a5900369fb656054cae35",
+  "templates/mod/mime_magic.conf.erb": "db7ac6bbf365d016852744d339c12d16",
+  "templates/mod/mpm_event.conf.erb": "80097a19d063a4f973465d9ef5c0c0bf",
+  "templates/mod/negotiation.conf.erb": "a2f0fb40cd038cb17bedc2b84d9f48ea",
+  "templates/mod/nss.conf.erb": "688c134cb37159a92cf85010ea3c67e6",
+  "templates/mod/pagespeed.conf.erb": "0d1ba456a798d1404205b7fbdee3294e",
+  "templates/mod/passenger.conf.erb": "43ff9002267227dec86f317ec7148eda",
+  "templates/mod/peruser.conf.erb": "c4f4054aee899249ea6fef5a9e5c14ff",
+  "templates/mod/php5.conf.erb": "e92f4b41e71318d35f44859b71999887",
+  "templates/mod/prefork.conf.erb": "f9ec5a7eaea78a19b04fa69f8acd8a84",
+  "templates/mod/proxy.conf.erb": "7eef34af57278ea572b267cff9fb6631",
+  "templates/mod/proxy_html.conf.erb": "69c9ce9b7f24e1337065f1ce26b057a0",
+  "templates/mod/remoteip.conf.erb": "5e3fae3bb4532d351d3860652215af92",
+  "templates/mod/reqtimeout.conf.erb": "314ef068b786ae5afded290a8b6eab15",
+  "templates/mod/rpaf.conf.erb": "5447539c083ae54f3a9e93c1ac8c988b",
+  "templates/mod/security.conf.erb": "e708c110f4bfe2fe6fdb9fc61e8498e4",
+  "templates/mod/security_crs.conf.erb": "0533f947d1d418774213bc9eb0444358",
+  "templates/mod/setenvif.conf.erb": "c7ede4173da1915b7ec088201f030c28",
+  "templates/mod/ssl.conf.erb": "5009e83ef1b9c626e04fe6e469f35a05",
+  "templates/mod/status.conf.erb": "9e959900ac58c8de34783886efeebce7",
+  "templates/mod/suphp.conf.erb": "05bb7b3ea23976b032ce405bfd4edd18",
+  "templates/mod/unixd_fcgid.conf.erb": "1780c7808bb3811deaf0007c890df4dc",
+  "templates/mod/userdir.conf.erb": "efd4cb18056690f2bddc4332c88bdd94",
+  "templates/mod/worker.conf.erb": "923ce06f97c04e548a438025b81abf50",
+  "templates/mod/wsgi.conf.erb": "9a416fa3b71be0795679069809686300",
+  "templates/namevirtualhost.erb": "fbfca19a639e18e6c477e191344ac8ae",
+  "templates/ports_header.erb": "afe35cb5747574b700ebaa0f0b3a626e",
+  "templates/vhost/_access_log.erb": "a0c804cb6fc03e5c573f9bfbcf73d9c6",
+  "templates/vhost/_action.erb": "a004dfcac2e63cef65cf8aa0e270b636",
+  "templates/vhost/_additional_includes.erb": "10e9c0056e962c49459839a1576b082e",
+  "templates/vhost/_aliases.erb": "6412f695e911feac18986da38f290dae",
+  "templates/vhost/_allow_encoded_slashes.erb": "37dee0b6fe9287342a10b533955dff81",
+  "templates/vhost/_auth_kerb.erb": "864ef8e3ce938f7b344d02639e35050e",
+  "templates/vhost/_block.erb": "cab4365316621b4e06cd1258abeb1d23",
+  "templates/vhost/_charsets.erb": "d152b6a7815e9edc0fe9bf9acbe2f1ec",
+  "templates/vhost/_custom_fragment.erb": "67a4475275ec9208e6421b047b9ed7f4",
+  "templates/vhost/_directories.erb": "983994277ca6f63edea68c0715715b75",
+  "templates/vhost/_docroot.erb": "65d882a3c9d6b6bdd2f9b771f378035a",
+  "templates/vhost/_error_document.erb": "81d3007c1301a5c5f244c082cfee9de2",
+  "templates/vhost/_fallbackresource.erb": "e6c103bee7f6f76b10f244fc9fd1cd3b",
+  "templates/vhost/_fastcgi.erb": "d07c41eae32671b38b5dba14724c14cc",
+  "templates/vhost/_file_footer.erb": "e27b2525783e590ca1820f1e2118285d",
+  "templates/vhost/_file_header.erb": "c9041e54c534d6d1d01676779ddbe49f",
+  "templates/vhost/_filters.erb": "597b9de5ae210af9182a1c95172115e7",
+  "templates/vhost/_header.erb": "9eb9d4075f288183d8224ddec5b2f126",
+  "templates/vhost/_itk.erb": "8bf90b9855a9277f7a665b10f6c57fe9",
+  "templates/vhost/_limits.erb": "d9da387dab6c7beab87e14be745e79af",
+  "templates/vhost/_logging.erb": "5bc4cbb1bc8a292acc0ba0420f96ca4e",
+  "templates/vhost/_passenger.erb": "6b8f937fffe27e65f9aa72e950c4dbfc",
+  "templates/vhost/_passenger_base_uris.erb": "c8d7f4da1434078e856c72671942dcd8",
+  "templates/vhost/_php.erb": "0be13b20951791db0f09c328e13b7eaf",
+  "templates/vhost/_php_admin.erb": "107a57e9e7b3f86d1abcf743f672a292",
+  "templates/vhost/_proxy.erb": "4828a17182010b2c68bd706b493911af",
+  "templates/vhost/_rack.erb": "ebe187c1bdc81eec9c8e0d9026120b18",
+  "templates/vhost/_redirect.erb": "639e170cafa9e703ab38797c8fc3030b",
+  "templates/vhost/_requestheader.erb": "db1b0cdda069ae809b5b83b0871ef991",
+  "templates/vhost/_rewrite.erb": "63a86545cd1c1a8e9e8518dd270deb3e",
+  "templates/vhost/_scriptalias.erb": "98713f33cca15b22c749bd35ea9a7b41",
+  "templates/vhost/_security.erb": "58cd0f606e104be456dea0b5d52212e8",
+  "templates/vhost/_serveralias.erb": "95fed45853629924467aefc271d5b396",
+  "templates/vhost/_serversignature.erb": "9bf5a458783ab459e5043e1cdf671fa7",
+  "templates/vhost/_setenv.erb": "818f65d2936be12a24e59079e28f8f47",
+  "templates/vhost/_ssl.erb": "e3c83e4bce93b85c067844a9c3653a7d",
+  "templates/vhost/_suexec.erb": "f2b3f9b9ff8fbac4e468e02cd824675a",
+  "templates/vhost/_suphp.erb": "a1c4a5e4461adbfce870df0abd158b59",
+  "templates/vhost/_wsgi.erb": "c4ea9a97580489edc6b589ac46816462"
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/apache.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+include apache
+include apache::mod::php
+include apache::mod::cgi
+include apache::mod::userdir
+include apache::mod::disk_cache
+include apache::mod::proxy_http
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/dev.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+include apache::mod::dev
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+include apache
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/mod_load_params.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+# Tests the path and identifier parameters for the apache::mod class
+
+# Base class for clarity:
+class { 'apache': }
+
+
+# Exaple parameter usage:
+apache::mod { 'testmod':
+  path => '/usr/some/path/mod_testmod.so',
+  id   => 'testmod_custom_name',
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/mods.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+## Default mods
+
+# Base class. Declares default vhost on port 80 and default ssl
+# vhost on port 443 listening on all interfaces and serving
+# $apache::docroot, and declaring our default set of modules.
+class { 'apache':
+  default_mods => true,
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/mods_custom.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+## custom mods
+
+# Base class. Declares default vhost on port 80 and default ssl
+# vhost on port 443 listening on all interfaces and serving
+# $apache::docroot, and declaring a custom set of modules.
+class { 'apache':
+  default_mods => [
+    'info',
+    'alias',
+    'mime',
+    'env',
+    'setenv',
+    'expires',
+  ],
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/php.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+class { 'apache':
+  mpm_module => 'prefork',
+}
+include apache::mod::php
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/vhost.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,261 @@
+## Default vhosts, and custom vhosts
+# NB: Please see the other vhost_*.pp example files for further
+# examples.
+
+# Base class. Declares default vhost on port 80 and default ssl
+# vhost on port 443 listening on all interfaces and serving
+# $apache::docroot
+class { 'apache': }
+
+# Most basic vhost
+apache::vhost { 'first.example.com':
+  port    => '80',
+  docroot => '/var/www/first',
+}
+
+# Vhost with different docroot owner/group/mode
+apache::vhost { 'second.example.com':
+  port          => '80',
+  docroot       => '/var/www/second',
+  docroot_owner => 'third',
+  docroot_group => 'third',
+  docroot_mode  => '0770',
+}
+
+# Vhost with serveradmin
+apache::vhost { 'third.example.com':
+  port        => '80',
+  docroot     => '/var/www/third',
+  serveradmin => 'admin@example.com',
+}
+
+# Vhost with ssl (uses default ssl certs)
+apache::vhost { 'ssl.example.com':
+  port    => '443',
+  docroot => '/var/www/ssl',
+  ssl     => true,
+}
+
+# Vhost with ssl and specific ssl certs
+apache::vhost { 'fourth.example.com':
+  port     => '443',
+  docroot  => '/var/www/fourth',
+  ssl      => true,
+  ssl_cert => '/etc/ssl/fourth.example.com.cert',
+  ssl_key  => '/etc/ssl/fourth.example.com.key',
+}
+
+# Vhost with english title and servername parameter
+apache::vhost { 'The fifth vhost':
+  servername => 'fifth.example.com',
+  port       => '80',
+  docroot    => '/var/www/fifth',
+}
+
+# Vhost with server aliases
+apache::vhost { 'sixth.example.com':
+  serveraliases => [
+    'sixth.example.org',
+    'sixth.example.net',
+  ],
+  port          => '80',
+  docroot       => '/var/www/fifth',
+}
+
+# Vhost with alternate options
+apache::vhost { 'seventh.example.com':
+  port    => '80',
+  docroot => '/var/www/seventh',
+  options => [
+    'Indexes',
+    'MultiViews',
+  ],
+}
+
+# Vhost with AllowOverride for .htaccess
+apache::vhost { 'eighth.example.com':
+  port     => '80',
+  docroot  => '/var/www/eighth',
+  override => 'All',
+}
+
+# Vhost with access and error logs disabled
+apache::vhost { 'ninth.example.com':
+  port       => '80',
+  docroot    => '/var/www/ninth',
+  access_log => false,
+  error_log  => false,
+}
+
+# Vhost with custom access and error logs and logroot
+apache::vhost { 'tenth.example.com':
+  port            => '80',
+  docroot         => '/var/www/tenth',
+  access_log_file => 'tenth_vhost.log',
+  error_log_file  => 'tenth_vhost_error.log',
+  logroot         => '/var/log',
+}
+
+# Vhost with a cgi-bin
+apache::vhost { 'eleventh.example.com':
+  port        => '80',
+  docroot     => '/var/www/eleventh',
+  scriptalias => '/usr/lib/cgi-bin',
+}
+
+# Vhost with a proxypass configuration
+apache::vhost { 'twelfth.example.com':
+  port          => '80',
+  docroot       => '/var/www/twelfth',
+  proxy_dest    => 'http://internal.example.com:8080/twelfth',
+  no_proxy_uris => ['/login','/logout'],
+}
+
+# Vhost to redirect /login and /logout
+apache::vhost { 'thirteenth.example.com':
+  port            => '80',
+  docroot         => '/var/www/thirteenth',
+  redirect_source => [
+    '/login',
+    '/logout',
+  ],
+  redirect_dest   => [
+    'http://10.0.0.10/login',
+    'http://10.0.0.10/logout',
+  ],
+}
+
+# Vhost to permamently redirect
+apache::vhost { 'fourteenth.example.com':
+  port            => '80',
+  docroot         => '/var/www/fourteenth',
+  redirect_source => '/blog',
+  redirect_dest   => 'http://blog.example.com',
+  redirect_status => 'permanent',
+}
+
+# Vhost with a rack configuration
+apache::vhost { 'fifteenth.example.com':
+  port           => '80',
+  docroot        => '/var/www/fifteenth',
+  rack_base_uris => ['/rackapp1', '/rackapp2'],
+}
+
+
+# Vhost to redirect non-ssl to ssl
+apache::vhost { 'sixteenth.example.com non-ssl':
+  servername => 'sixteenth.example.com',
+  port       => '80',
+  docroot    => '/var/www/sixteenth',
+  rewrites   => [
+    {
+      comment      => 'redirect non-SSL traffic to SSL site',
+      rewrite_cond => ['%{HTTPS} off'],
+      rewrite_rule => ['(.*) https://%{HTTPS_HOST}%{REQUEST_URI}'],
+    }
+  ]
+}
+
+# Rewrite a URL to lower case
+apache::vhost { 'sixteenth.example.com non-ssl':
+  servername => 'sixteenth.example.com',
+  port       => '80',
+  docroot    => '/var/www/sixteenth',
+  rewrites   => [
+    { comment      => 'Rewrite to lower case',
+      rewrite_cond => ['%{REQUEST_URI} [A-Z]'],
+      rewrite_map  => ['lc int:tolower'],
+      rewrite_rule => ['(.*) ${lc:$1} [R=301,L]'],
+    }
+  ]
+}
+
+apache::vhost { 'sixteenth.example.com ssl':
+  servername => 'sixteenth.example.com',
+  port       => '443',
+  docroot    => '/var/www/sixteenth',
+  ssl        => true,
+}
+
+# Vhost to redirect non-ssl to ssl using old rewrite method
+apache::vhost { 'sixteenth.example.com non-ssl old rewrite':
+  servername   => 'sixteenth.example.com',
+  port         => '80',
+  docroot      => '/var/www/sixteenth',
+  rewrite_cond => '%{HTTPS} off',
+  rewrite_rule => '(.*) https://%{HTTPS_HOST}%{REQUEST_URI}',
+}
+apache::vhost { 'sixteenth.example.com ssl old rewrite':
+  servername => 'sixteenth.example.com',
+  port       => '443',
+  docroot    => '/var/www/sixteenth',
+  ssl        => true,
+}
+
+# Vhost to block repository files
+apache::vhost { 'seventeenth.example.com':
+  port    => '80',
+  docroot => '/var/www/seventeenth',
+  block   => 'scm',
+}
+
+# Vhost with special environment variables
+apache::vhost { 'eighteenth.example.com':
+  port    => '80',
+  docroot => '/var/www/eighteenth',
+  setenv  => ['SPECIAL_PATH /foo/bin','KILROY was_here'],
+}
+
+apache::vhost { 'nineteenth.example.com':
+  port     => '80',
+  docroot  => '/var/www/nineteenth',
+  setenvif => 'Host "^([^\.]*)\.website\.com$" CLIENT_NAME=$1',
+}
+
+# Vhost with additional include files
+apache::vhost { 'twentyieth.example.com':
+  port                => '80',
+  docroot             => '/var/www/twelfth',
+  additional_includes => ['/tmp/proxy_group_a','/tmp/proxy_group_b'],
+}
+
+# Vhost with alias for subdomain mapped to same named directory
+# http://example.com.loc => /var/www/example.com
+apache::vhost { 'subdomain.loc':
+  vhost_name      => '*',
+  port            => '80',
+  virtual_docroot => '/var/www/%-2+',
+  docroot         => '/var/www',
+  serveraliases   => ['*.loc',],
+}
+
+# Vhost with SSLProtocol,SSLCipherSuite, SSLHonorCipherOrder
+apache::vhost { 'securedomain.com':
+        priority             => '10',
+        vhost_name           => 'www.securedomain.com',
+        port                 => '443',
+        docroot              => '/var/www/secure',
+        ssl                  => true,
+        ssl_cert             => '/etc/ssl/securedomain.cert',
+        ssl_key              => '/etc/ssl/securedomain.key',
+        ssl_chain            => '/etc/ssl/securedomain.crt',
+        ssl_protocol         => '-ALL +SSLv3 +TLSv1',
+        ssl_cipher           => 'ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM',
+        ssl_honorcipherorder => 'On',
+        add_listen           => false,
+}
+
+# Vhost with access log environment variables writing control
+apache::vhost { 'twentyfirst.example.com':
+  port               => '80',
+  docroot            => '/var/www/twentyfirst',
+  access_log_env_var => 'admin',
+}
+
+# Vhost with a passenger_base configuration
+apache::vhost { 'twentysecond.example.com':
+  port           => '80',
+  docroot        => '/var/www/twentysecond',
+  rack_base_uris => ['/passengerapp1', '/passengerapp2'],
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/vhost_directories.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,44 @@
+# Base class. Declares default vhost on port 80 and default ssl
+# vhost on port 443 listening on all interfaces and serving
+# $apache::docroot
+class { 'apache': }
+
+# Example from README adapted.
+apache::vhost { 'readme.example.net':
+  docroot     => '/var/www/readme',
+  directories => [
+    {
+      'path'         => '/var/www/readme',
+      'ServerTokens' => 'prod' ,
+    },
+    {
+      'path'  => '/usr/share/empty',
+      'allow' => 'from all',
+    },
+  ],
+}
+
+# location test
+apache::vhost { 'location.example.net':
+  docroot     => '/var/www/location',
+  directories => [
+    {
+      'path'         => '/location',
+      'provider'     => 'location',
+      'ServerTokens' => 'prod'
+    },
+  ],
+}
+
+# files test, curedly disable access to accidental backup files.
+apache::vhost { 'files.example.net':
+  docroot     => '/var/www/files',
+  directories => [
+    {
+      'path'     => '(\.swp|\.bak|~)$',
+      'provider' => 'filesmatch',
+      'deny'     => 'from all'
+    },
+  ],
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/vhost_filter.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+# Base class. Declares default vhost on port 80 with filters.
+class { 'apache': }
+
+# Example from README adapted.
+apache::vhost { 'readme.example.net':
+  docroot => '/var/www/html',
+  filters => [
+    'FilterDeclare   COMPRESS',
+    'FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/html',
+    'FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/css',
+    'FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/plain',
+    'FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/xml',
+    'FilterChain     COMPRESS',
+    'FilterProtocol  COMPRESS  DEFLATE change=yes;byteranges=no',
+  ],
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/vhost_ip_based.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+## IP-based vhosts on any listen port
+# IP-based vhosts respond to requests on specific IP addresses.
+
+# Base class. Turn off the default vhosts; we will be declaring
+# all vhosts below.
+class { 'apache':
+  default_vhost => false,
+}
+
+# Listen on port 80 and 81; required because the following vhosts
+# are not declared with a port parameter.
+apache::listen { '80': }
+apache::listen { '81': }
+
+# IP-based vhosts
+apache::vhost { 'first.example.com':
+  ip       => '10.0.0.10',
+  docroot  => '/var/www/first',
+  ip_based => true,
+}
+apache::vhost { 'second.example.com':
+  ip       => '10.0.0.11',
+  docroot  => '/var/www/second',
+  ip_based => true,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/vhost_proxypass.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,66 @@
+## vhost with proxyPass directive
+# NB: Please see the other vhost_*.pp example files for further
+# examples.
+
+# Base class. Declares default vhost on port 80 and default ssl
+# vhost on port 443 listening on all interfaces and serving
+# $apache::docroot
+class { 'apache': }
+
+# Most basic vhost with proxy_pass
+apache::vhost { 'first.example.com':
+  port       => 80,
+  docroot    => '/var/www/first',
+  proxy_pass => [
+    {
+      'path' => '/first',
+      'url'  => 'http://localhost:8080/first'
+    },
+  ],
+}
+
+# vhost with proxy_pass and parameters
+apache::vhost { 'second.example.com':
+  port       => 80,
+  docroot    => '/var/www/second',
+  proxy_pass => [
+    {
+      'path'   => '/second',
+      'url'    => 'http://localhost:8080/second',
+      'params' => {
+        'retry'   => '0',
+        'timeout' => '5'
+        }
+    },
+  ],
+}
+
+# vhost with proxy_pass and keywords
+apache::vhost { 'third.example.com':
+  port       => 80,
+  docroot    => '/var/www/third',
+  proxy_pass => [
+    {
+      'path'     => '/third',
+      'url'      => 'http://localhost:8080/third',
+      'keywords' => ['noquery', 'interpolate']
+    },
+  ],
+}
+
+# vhost with proxy_pass, parameters and keywords
+apache::vhost { 'fourth.example.com':
+  port       => 80,
+  docroot    => '/var/www/fourth',
+  proxy_pass => [
+    {
+      'path'     => '/fourth',
+      'url'      => 'http://localhost:8080/fourth',
+      'params'   => {
+        'retry'   => '0',
+        'timeout' => '5'
+        },
+      'keywords' => ['noquery', 'interpolate']
+    },
+  ],
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/vhost_ssl.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+## SSL-enabled vhosts
+# SSL-enabled vhosts respond only to HTTPS queries.
+
+# Base class. Turn off the default vhosts; we will be declaring
+# all vhosts below.
+class { 'apache':
+  default_vhost => false,
+}
+
+# Non-ssl vhost
+apache::vhost { 'first.example.com non-ssl':
+  servername => 'first.example.com',
+  port       => '80',
+  docroot    => '/var/www/first',
+}
+
+# SSL vhost at the same domain
+apache::vhost { 'first.example.com ssl':
+  servername => 'first.example.com',
+  port       => '443',
+  docroot    => '/var/www/first',
+  ssl        => true,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/examples/vhosts_without_listen.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,53 @@
+## Declare ip-based and name-based vhosts
+# Mixing Name-based vhost with IP-specific vhosts requires `add_listen =>
+# 'false'` on the non-IP vhosts
+
+# Base class. Turn off the default vhosts; we will be declaring
+# all vhosts below.
+class { 'apache':
+  default_vhost => false,
+}
+
+
+# Add two an IP-based vhost on 10.0.0.10, ssl and non-ssl
+apache::vhost { 'The first IP-based vhost, non-ssl':
+  servername => 'first.example.com',
+  ip         => '10.0.0.10',
+  port       => '80',
+  ip_based   => true,
+  docroot    => '/var/www/first',
+}
+apache::vhost { 'The first IP-based vhost, ssl':
+  servername => 'first.example.com',
+  ip         => '10.0.0.10',
+  port       => '443',
+  ip_based   => true,
+  docroot    => '/var/www/first-ssl',
+  ssl        => true,
+}
+
+# Two name-based vhost listening on 10.0.0.20
+apache::vhost { 'second.example.com':
+  ip      => '10.0.0.20',
+  port    => '80',
+  docroot => '/var/www/second',
+}
+apache::vhost { 'third.example.com':
+  ip      => '10.0.0.20',
+  port    => '80',
+  docroot => '/var/www/third',
+}
+
+# Two name-based vhosts without IPs specified, so that they will answer on either 10.0.0.10 or 10.0.0.20 . It is requried to declare
+# `add_listen => 'false'` to disable declaring "Listen 80" which will conflict
+# with the IP-based preceeding vhosts.
+apache::vhost { 'fourth.example.com':
+  port       => '80',
+  docroot    => '/var/www/fourth',
+  add_listen => false,
+}
+apache::vhost { 'fifth.example.com':
+  port       => '80',
+  docroot    => '/var/www/fifth',
+  add_listen => false,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/files/httpd	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+# Configuration file for the httpd service.
+
+#
+# The default processing model (MPM) is the process-based
+# 'prefork' model.  A thread-based model, 'worker', is also
+# available, but does not work with some modules (such as PHP).
+# The service must be stopped before changing this variable.
+#
+#HTTPD=/usr/sbin/httpd.worker
+
+#
+# To pass additional options (for instance, -D definitions) to the
+# httpd binary at startup, set OPTIONS here.
+#
+#OPTIONS=
+#OPTIONS=-DDOWN
+
+#
+# By default, the httpd process is started in the C locale; to 
+# change the locale in which the server runs, the HTTPD_LANG
+# variable can be set.
+#
+#HTTPD_LANG=C
+export SHORTHOST=`hostname -s`
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/lib/puppet/parser/functions/bool2httpd.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,30 @@
+Puppet::Parser::Functions::newfunction(:bool2httpd, :type => :rvalue, :doc => <<-EOS
+Transform a supposed boolean to On or Off. Pass all other values through.
+Given a nil value (undef), bool2httpd will return 'Off'
+
+Example:
+
+    $trace_enable     = false
+    $server_signature = 'mail'
+
+    bool2httpd($trace_enable)
+    # => 'Off'
+    bool2httpd($server_signature)
+    # => 'mail'
+    bool2httpd(undef)
+    # => 'Off'
+
+EOS
+) do |args|
+  raise(Puppet::ParseError, "bool2httpd() wrong number of arguments. Given: #{args.size} for 1)") if args.size != 1
+
+  arg = args[0]
+
+  if arg.nil? or arg == false or arg =~ /false/i or arg == :undef
+    return 'Off'
+  elsif arg == true or arg =~ /true/i
+    return 'On'
+  end
+
+  return arg.to_s
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/lib/puppet/parser/functions/validate_apache_log_level.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+module Puppet::Parser::Functions
+  newfunction(:validate_apache_log_level, :doc => <<-'ENDHEREDOC') do |args|
+    Perform simple validation of a string against the list of known log
+    levels as per http://httpd.apache.org/docs/current/mod/core.html#loglevel
+        validate_apache_loglevel('info')
+
+    Modules maybe specified with their own levels like these:
+        validate_apache_loglevel('warn ssl:info')
+        validate_apache_loglevel('warn mod_ssl.c:info')
+        validate_apache_loglevel('warn ssl_module:info')
+
+    Expected to be used from the main or vhost.
+    
+    Might be used from directory too later as apaceh supports that
+
+    ENDHEREDOC
+    if (args.size != 1) then
+      raise Puppet::ParseError, ("validate_apache_loglevel(): wrong number of arguments (#{args.length}; must be 1)")
+    end
+
+    log_level = args[0]
+    msg = "Log level '${log_level}' is not one of the supported Apache HTTP Server log levels."
+
+    raise Puppet::ParseError, (msg) unless log_level =~ Regexp.compile('(emerg|alert|crit|error|warn|notice|info|debug|trace[1-8])')
+
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/lib/puppet/provider/a2mod.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+class Puppet::Provider::A2mod < Puppet::Provider
+  def self.prefetch(mods)
+    instances.each do |prov|
+      if mod = mods[prov.name]
+        mod.provider = prov
+      end
+    end
+  end
+
+  def flush
+    @property_hash.clear
+  end
+
+  def properties
+    if @property_hash.empty?
+      @property_hash = query || {:ensure => :absent}
+      @property_hash[:ensure] = :absent if @property_hash.empty?
+    end
+    @property_hash.dup
+  end
+
+  def query
+    self.class.instances.each do |mod|
+      if mod.name == self.name or mod.name.downcase == self.name
+        return mod.properties
+      end
+    end
+    nil
+  end
+
+  def exists?
+    properties[:ensure] != :absent
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/lib/puppet/provider/a2mod/a2mod.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+require 'puppet/provider/a2mod'
+
+Puppet::Type.type(:a2mod).provide(:a2mod, :parent => Puppet::Provider::A2mod) do
+    desc "Manage Apache 2 modules on Debian and Ubuntu"
+
+    optional_commands :encmd => "a2enmod"
+    optional_commands :discmd => "a2dismod"
+    commands :apache2ctl => "apache2ctl"
+
+    confine :osfamily => :debian
+    defaultfor :operatingsystem => [:debian, :ubuntu]
+
+    def self.instances
+      modules = apache2ctl("-M").lines.collect { |line|
+        m = line.match(/(\w+)_module \(shared\)$/)
+        m[1] if m
+      }.compact
+
+      modules.map do |mod|
+        new(
+          :name     => mod,
+          :ensure   => :present,
+          :provider => :a2mod
+        )
+      end
+    end
+
+    def create
+        encmd resource[:name]
+    end
+
+    def destroy
+        discmd resource[:name]
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/lib/puppet/provider/a2mod/gentoo.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,116 @@
+require 'puppet/util/filetype'
+Puppet::Type.type(:a2mod).provide(:gentoo, :parent => Puppet::Provider) do
+  desc "Manage Apache 2 modules on Gentoo"
+
+  confine :operatingsystem => :gentoo
+  defaultfor :operatingsystem => :gentoo
+
+  attr_accessor :property_hash
+
+  def create
+    @property_hash[:ensure] = :present
+  end
+
+  def exists?
+    (!(@property_hash[:ensure].nil?) and @property_hash[:ensure] == :present)
+  end
+
+  def destroy
+    @property_hash[:ensure] = :absent
+  end
+
+  def flush
+    self.class.flush
+  end
+
+  class << self
+    attr_reader :conf_file
+  end
+
+  def self.clear
+    @mod_resources = []
+    @modules       = []
+    @other_args    = ""
+  end
+
+  def self.initvars
+    @conf_file     = "/etc/conf.d/apache2"
+    @filetype      = Puppet::Util::FileType.filetype(:flat).new(conf_file)
+    @mod_resources = []
+    @modules       = []
+    @other_args    = ""
+  end
+
+  self.initvars
+
+  # Retrieve an array of all existing modules
+  def self.modules
+    if @modules.length <= 0
+      # Locate the APACHE_OPTS variable
+      records = filetype.read.split(/\n/)
+      apache2_opts = records.grep(/^\s*APACHE2_OPTS=/).first
+
+      # Extract all defines
+      while apache2_opts.sub!(/-D\s+(\w+)/, '')
+        @modules << $1.downcase
+      end
+
+      # Hang on to any remaining options.
+      if apache2_opts.match(/APACHE2_OPTS="(.+)"/)
+        @other_args = $1.strip
+      end
+
+      @modules.sort!.uniq!
+    end
+
+    @modules
+  end
+
+  def self.prefetch(resources={})
+    # Match resources with existing providers
+    instances.each do |provider|
+      if resource = resources[provider.name]
+        resource.provider = provider
+      end
+    end
+
+    # Store all resources using this provider for flushing
+    resources.each do |name, resource|
+      @mod_resources << resource
+    end
+  end
+
+  def self.instances
+    modules.map {|mod| new(:name => mod, :provider => :gentoo, :ensure => :present)}
+  end
+
+  def self.flush
+
+    mod_list       = modules
+    mods_to_remove = @mod_resources.select {|mod| mod.should(:ensure) == :absent}.map {|mod| mod[:name]}
+    mods_to_add    = @mod_resources.select {|mod| mod.should(:ensure) == :present}.map {|mod| mod[:name]}
+
+    mod_list -= mods_to_remove
+    mod_list += mods_to_add
+    mod_list.sort!.uniq!
+
+    if modules != mod_list
+      opts = @other_args + " "
+      opts << mod_list.map {|mod| "-D #{mod.upcase}"}.join(" ")
+      opts.strip!
+      opts.gsub!(/\s+/, ' ')
+
+      apache2_opts = %Q{APACHE2_OPTS="#{opts}"}
+      Puppet.debug("Writing back \"#{apache2_opts}\" to #{conf_file}")
+
+      records = filetype.read.split(/\n/)
+
+      opts_index = records.find_index {|i| i.match(/^\s*APACHE2_OPTS/)}
+      records[opts_index] = apache2_opts
+
+      filetype.backup
+      filetype.write(records.join("\n"))
+      @modules = mod_list
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/lib/puppet/provider/a2mod/modfix.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+Puppet::Type.type(:a2mod).provide :modfix do
+    desc "Dummy provider for A2mod.
+
+    Fake nil resources when there is no crontab binary available. Allows
+    puppetd to run on a bootstrapped machine before a Cron package has been
+    installed. Workaround for: http://projects.puppetlabs.com/issues/2384
+    "
+
+    def self.instances
+        []
+    end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/lib/puppet/provider/a2mod/redhat.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,60 @@
+require 'puppet/provider/a2mod'
+
+Puppet::Type.type(:a2mod).provide(:redhat, :parent => Puppet::Provider::A2mod) do
+  desc "Manage Apache 2 modules on RedHat family OSs"
+
+  commands :apachectl => "apachectl"
+
+  confine :osfamily => :redhat
+  defaultfor :osfamily => :redhat
+
+  require 'pathname'
+
+  # modpath: Path to default apache modules directory /etc/httpd/mod.d
+  # modfile: Path to module load configuration file; Default: resides under modpath directory
+  # libfile: Path to actual apache module library. Added in modfile LoadModule
+
+  attr_accessor :modfile, :libfile
+  class << self
+    attr_accessor :modpath
+    def preinit
+      @modpath = "/etc/httpd/mod.d"
+    end
+  end
+
+  self.preinit
+
+  def create
+    File.open(modfile,'w') do |f|
+      f.puts "LoadModule #{resource[:identifier]} #{libfile}"
+    end
+  end
+
+  def destroy
+    File.delete(modfile)
+  end
+
+  def self.instances
+    modules = apachectl("-M").lines.collect { |line|
+      m = line.match(/(\w+)_module \(shared\)$/)
+      m[1] if m
+    }.compact
+
+    modules.map do |mod|
+      new(
+        :name     => mod,
+        :ensure   => :present,
+        :provider => :redhat
+      )
+    end
+  end
+
+  def modfile
+    modfile ||= "#{self.class.modpath}/#{resource[:name]}.load"
+  end
+
+  # Set libfile path: If absolute path is passed, then maintain it. Else, make it default from 'modules' dir.
+  def libfile
+    libfile = Pathname.new(resource[:lib]).absolute? ? resource[:lib] : "modules/#{resource[:lib]}"
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/lib/puppet/type/a2mod.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,30 @@
+Puppet::Type.newtype(:a2mod) do
+    @doc = "Manage Apache 2 modules"
+
+    ensurable
+
+    newparam(:name) do
+       Puppet.warning "The a2mod provider is deprecated, please use apache::mod instead"
+       desc "The name of the module to be managed"
+
+       isnamevar
+
+    end
+
+    newparam(:lib) do
+      desc "The name of the .so library to be loaded"
+
+      defaultto { "mod_#{@resource[:name]}.so" }
+    end
+ 
+    newparam(:identifier) do
+      desc "Module identifier string used by LoadModule. Default: module-name_module"
+
+      # http://httpd.apache.org/docs/2.2/mod/module-dict.html#ModuleIdentifier
+
+      defaultto { "#{resource[:name]}_module" }
+    end
+
+    autorequire(:package) { catalog.resource(:package, 'httpd')}
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/balancer.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,82 @@
+# == Define Resource Type: apache::balancer
+#
+# This type will create an apache balancer cluster file inside the conf.d
+# directory. Each balancer cluster needs one or more balancer members (that can
+# be declared with the apache::balancermember defined resource type). Using
+# storeconfigs, you can export the apache::balancermember resources on all
+# balancer members, and then collect them on a single apache load balancer
+# server.
+#
+# === Requirement/Dependencies:
+#
+# Currently requires the puppetlabs/concat module on the Puppet Forge and uses
+# storeconfigs on the Puppet Master to export/collect resources from all
+# balancer members.
+#
+# === Parameters
+#
+# [*name*]
+# The namevar of the defined resource type is the balancer clusters name.
+# This name is also used in the name of the conf.d file
+#
+# [*proxy_set*]
+# Hash, default empty. If given, each key-value pair will be used as a ProxySet
+# line in the configuration.
+#
+# [*collect_exported*]
+# Boolean, default 'true'. True means 'collect exported @@balancermember
+# resources' (for the case when every balancermember node exports itself),
+# false means 'rely on the existing declared balancermember resources' (for the
+# case when you know the full set of balancermembers in advance and use
+# apache::balancermember with array arguments, which allows you to deploy
+# everything in 1 run)
+#
+#
+# === Examples
+#
+# Exporting the resource for a balancer member:
+#
+# apache::balancer { 'puppet00': }
+#
+define apache::balancer (
+  $proxy_set = {},
+  $collect_exported = true,
+) {
+  include ::apache::mod::proxy_balancer
+
+  $target = "${::apache::params::confd_dir}/balancer_${name}.conf"
+
+  concat { $target:
+    owner  => '0',
+    group  => '0',
+    mode   => '0644',
+    notify => Class['Apache::Service'],
+  }
+
+  concat::fragment { "00-${name}-header":
+    ensure  => present,
+    target  => $target,
+    order   => '01',
+    content => "<Proxy balancer://${name}>\n",
+  }
+
+  if $collect_exported {
+    Apache::Balancermember <<| balancer_cluster == $name |>>
+  }
+  # else: the resources have been created and they introduced their
+  # concat fragments. We don't have to do anything about them.
+
+  concat::fragment { "01-${name}-proxyset":
+    ensure  => present,
+    target  => $target,
+    order   => '19',
+    content => inline_template("<% @proxy_set.keys.sort.each do |key| %> Proxyset <%= key %>=<%= @proxy_set[key] %>\n<% end %>"),
+  }
+
+  concat::fragment { "01-${name}-footer":
+    ensure  => present,
+    target  => $target,
+    order   => '20',
+    content => "</Proxy>\n",
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/balancermember.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,53 @@
+# == Define Resource Type: apache::balancermember
+#
+# This type will setup a balancer member inside a listening service
+# configuration block in /etc/apache/apache.cfg on the load balancer.
+# currently it only has the ability to specify the instance name, url and an
+# array of options. More features can be added as needed. The best way to
+# implement this is to export this resource for all apache balancer member
+# servers, and then collect them on the main apache load balancer.
+#
+# === Requirement/Dependencies:
+#
+# Currently requires the puppetlabs/concat module on the Puppet Forge and
+# uses storeconfigs on the Puppet Master to export/collect resources
+# from all balancer members.
+#
+# === Parameters
+#
+# [*name*]
+# The title of the resource is arbitrary and only utilized in the concat
+# fragment name.
+#
+# [*balancer_cluster*]
+# The apache service's instance name (or, the title of the apache::balancer
+# resource). This must match up with a declared apache::balancer resource.
+#
+# [*url*]
+# The url used to contact the balancer member server.
+#
+# [*options*]
+# An array of options to be specified after the url.
+#
+# === Examples
+#
+# Exporting the resource for a balancer member:
+#
+# @@apache::balancermember { 'apache':
+#   balancer_cluster => 'puppet00',
+#   url              => "ajp://${::fqdn}:8009"
+#   options          => ['ping=5', 'disablereuse=on', 'retry=5', 'ttl=120'],
+# }
+#
+define apache::balancermember(
+  $balancer_cluster,
+  $url = "http://${::fqdn}/",
+  $options = [],
+) {
+
+  concat::fragment { "BalancerMember ${name}":
+    ensure  => present,
+    target  => "${::apache::params::confd_dir}/balancer_${balancer_cluster}.conf",
+    content => inline_template(" BalancerMember ${url} <%= @options.join ' ' %>\n"),
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/confd/no_accf.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+class apache::confd::no_accf {
+  # Template uses no variables
+  file { 'no-accf.conf':
+    ensure  => 'file',
+    path    => "${::apache::confd_dir}/no-accf.conf",
+    content => template('apache/confd/no-accf.conf.erb'),
+    require => Exec["mkdir ${::apache::confd_dir}"],
+    before  => File[$::apache::confd_dir],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/custom_config.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,68 @@
+# See README.md for usage information
+define apache::custom_config (
+  $ensure         = 'present',
+  $confdir        = $::apache::confd_dir,
+  $content        = undef,
+  $priority       = '25',
+  $source         = undef,
+  $verify_command = $::apache::params::verify_command,
+  $verify_config  = true,
+) {
+
+  if $content and $source {
+    fail('Only one of $content and $source can be specified.')
+  }
+
+  if $ensure == 'present' and ! $content and ! $source {
+    fail('One of $content and $source must be specified.')
+  }
+
+  validate_re($ensure, '^(present|absent)$',
+  "${ensure} is not supported for ensure.
+  Allowed values are 'present' and 'absent'.")
+
+  validate_bool($verify_config)
+
+  if $priority {
+    $priority_prefix = "${priority}-"
+  } else {
+    $priority_prefix = ''
+  }
+
+  ## Apache include does not always work with spaces in the filename
+  $filename_middle = regsubst($name, ' ', '_', 'G')
+  $filename = "${priority_prefix}${filename_middle}.conf"
+
+  if ! $verify_config or $ensure == 'absent' {
+    $notifies = Class['Apache::Service']
+  } else {
+    $notifies = undef
+  }
+
+  file { "apache_${name}":
+    ensure  => $ensure,
+    path    => "${confdir}/${filename}",
+    content => $content,
+    source  => $source,
+    require => Package['httpd'],
+    notify  => $notifies,
+  }
+
+  if $ensure == 'present' and $verify_config {
+    exec { "syntax verification for ${name}":
+      command     => $verify_command,
+      subscribe   => File["apache_${name}"],
+      refreshonly => true,
+      notify      => Class['Apache::Service'],
+      before      => Exec["remove ${name} if invalid"],
+      require     => Anchor['::apache::modules_set_up']
+    }
+
+    exec { "remove ${name} if invalid":
+      command     => "/bin/rm ${confdir}/${filename}",
+      unless      => $verify_command,
+      subscribe   => File["apache_${name}"],
+      refreshonly => true,
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/default_confd_files.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+class apache::default_confd_files (
+  $all = true,
+) {
+  # The rest of the conf.d/* files only get loaded if we want them
+  if $all {
+    case $::osfamily {
+      'freebsd': {
+        include ::apache::confd::no_accf
+      }
+      default: {
+        # do nothing
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/default_mods.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,179 @@
+class apache::default_mods (
+  $all            = true,
+  $mods           = undef,
+  $apache_version = $::apache::apache_version,
+  $use_systemd    = $::apache::use_systemd,
+) {
+  # These are modules required to run the default configuration.
+  # They are not configurable at this time, so we just include
+  # them to make sure it works.
+  case $::osfamily {
+    'redhat': {
+      ::apache::mod { 'log_config': }
+      if versioncmp($apache_version, '2.4') >= 0 {
+        # Lets fork it
+        # Do not try to load mod_systemd on RHEL/CentOS 6 SCL.
+        if ( !($::osfamily == 'redhat' and versioncmp($::operatingsystemrelease, '7.0') == -1) and !($::operatingsystem == 'Amazon') ) {
+          if ($use_systemd) {
+            ::apache::mod { 'systemd': }
+          }
+        }
+        ::apache::mod { 'unixd': }
+      }
+    }
+    'freebsd': {
+      ::apache::mod { 'log_config': }
+      ::apache::mod { 'unixd': }
+    }
+    'Suse': {
+      ::apache::mod { 'log_config': }
+    }
+    default: {}
+  }
+  case $::osfamily {
+    'gentoo': {}
+    default: {
+      ::apache::mod { 'authz_host': }
+    }
+  }
+  # The rest of the modules only get loaded if we want all modules enabled
+  if $all {
+    case $::osfamily {
+      'debian': {
+        include ::apache::mod::authn_core
+        include ::apache::mod::reqtimeout
+        if versioncmp($apache_version, '2.4') < 0 {
+          ::apache::mod { 'authn_alias': }
+        }
+      }
+      'redhat': {
+        include ::apache::mod::actions
+        include ::apache::mod::authn_core
+        include ::apache::mod::cache
+        include ::apache::mod::ext_filter
+        include ::apache::mod::mime
+        include ::apache::mod::mime_magic
+        include ::apache::mod::rewrite
+        include ::apache::mod::speling
+        include ::apache::mod::suexec
+        include ::apache::mod::version
+        include ::apache::mod::vhost_alias
+        ::apache::mod { 'auth_digest': }
+        ::apache::mod { 'authn_anon': }
+        ::apache::mod { 'authn_dbm': }
+        ::apache::mod { 'authz_dbm': }
+        ::apache::mod { 'authz_owner': }
+        ::apache::mod { 'expires': }
+        ::apache::mod { 'include': }
+        ::apache::mod { 'logio': }
+        ::apache::mod { 'substitute': }
+        ::apache::mod { 'usertrack': }
+
+        if versioncmp($apache_version, '2.4') < 0 {
+          ::apache::mod { 'authn_alias': }
+          ::apache::mod { 'authn_default': }
+        }
+      }
+      'freebsd': {
+        include ::apache::mod::actions
+        include ::apache::mod::authn_core
+        include ::apache::mod::cache
+        include ::apache::mod::disk_cache
+        include ::apache::mod::headers
+        include ::apache::mod::info
+        include ::apache::mod::mime_magic
+        include ::apache::mod::reqtimeout
+        include ::apache::mod::rewrite
+        include ::apache::mod::userdir
+        include ::apache::mod::version
+        include ::apache::mod::vhost_alias
+        include ::apache::mod::speling
+        include ::apache::mod::filter
+
+        ::apache::mod { 'asis': }
+        ::apache::mod { 'auth_digest': }
+        ::apache::mod { 'auth_form': }
+        ::apache::mod { 'authn_anon': }
+        ::apache::mod { 'authn_dbm': }
+        ::apache::mod { 'authn_socache': }
+        ::apache::mod { 'authz_dbd': }
+        ::apache::mod { 'authz_dbm': }
+        ::apache::mod { 'authz_owner': }
+        ::apache::mod { 'dumpio': }
+        ::apache::mod { 'expires': }
+        ::apache::mod { 'file_cache': }
+        ::apache::mod { 'imagemap':}
+        ::apache::mod { 'include': }
+        ::apache::mod { 'logio': }
+        ::apache::mod { 'request': }
+        ::apache::mod { 'session': }
+        ::apache::mod { 'unique_id': }
+      }
+      default: {}
+    }
+    case $::apache::mpm_module {
+      'prefork': {
+        include ::apache::mod::cgi
+      }
+      'worker': {
+        include ::apache::mod::cgid
+      }
+      default: {
+        # do nothing
+      }
+    }
+    include ::apache::mod::alias
+    include ::apache::mod::authn_file
+    include ::apache::mod::autoindex
+    include ::apache::mod::dav
+    include ::apache::mod::dav_fs
+    include ::apache::mod::deflate
+    include ::apache::mod::dir
+    include ::apache::mod::mime
+    include ::apache::mod::negotiation
+    include ::apache::mod::setenvif
+    ::apache::mod { 'auth_basic': }
+
+    if versioncmp($apache_version, '2.4') >= 0 {
+      # filter is needed by mod_deflate
+      include ::apache::mod::filter
+
+      # authz_core is needed for 'Require' directive
+      ::apache::mod { 'authz_core':
+        id => 'authz_core_module',
+      }
+
+      # lots of stuff seems to break without access_compat
+      ::apache::mod { 'access_compat': }
+    } else {
+      include ::apache::mod::authz_default
+    }
+
+    include ::apache::mod::authz_user
+
+    ::apache::mod { 'authz_groupfile': }
+    ::apache::mod { 'env': }
+  } elsif $mods {
+    ::apache::default_mods::load { $mods: }
+
+    if versioncmp($apache_version, '2.4') >= 0 {
+      # authz_core is needed for 'Require' directive
+      ::apache::mod { 'authz_core':
+        id => 'authz_core_module',
+      }
+
+      # filter is needed by mod_deflate
+      include ::apache::mod::filter
+    }
+  } else {
+    if versioncmp($apache_version, '2.4') >= 0 {
+      # authz_core is needed for 'Require' directive
+      ::apache::mod { 'authz_core':
+        id => 'authz_core_module',
+      }
+
+      # filter is needed by mod_deflate
+      include ::apache::mod::filter
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/default_mods/load.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+# private define
+define apache::default_mods::load ($module = $title) {
+  if defined("apache::mod::${module}") {
+    include "::apache::mod::${module}"
+  } else {
+    ::apache::mod { $module: }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/dev.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+class apache::dev {
+  include ::apache::params
+  $packages = $::apache::dev_packages
+  if $packages { # FreeBSD doesn't have dev packages to install
+    package { $packages:
+      ensure  => present,
+      require => Package['httpd'],
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/fastcgi/server.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+define apache::fastcgi::server (
+  $host          = '127.0.0.1:9000',
+  $timeout       = 15,
+  $flush         = false,
+  $faux_path     = "/var/www/${name}.fcgi",
+  $fcgi_alias    = "/${name}.fcgi",
+  $file_type     = 'application/x-httpd-php'
+) {
+  include apache::mod::fastcgi
+
+  Apache::Mod['fastcgi'] -> Apache::Fastcgi::Server[$title]
+
+  file { "fastcgi-pool-${name}.conf":
+    ensure  => present,
+    path    => "${::apache::confd_dir}/fastcgi-pool-${name}.conf",
+    owner   => 'root',
+    group   => $::apache::params::root_group,
+    mode    => '0644',
+    content => template('apache/fastcgi/server.erb'),
+    require => Exec["mkdir ${::apache::confd_dir}"],
+    before  => File[$::apache::confd_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,395 @@
+# Class: apache
+#
+# This class installs Apache
+#
+# Parameters:
+#
+# Actions:
+#   - Install Apache
+#   - Manage Apache service
+#
+# Requires:
+#
+# Sample Usage:
+#
+class apache (
+  $apache_name            = $::apache::params::apache_name,
+  $service_name           = $::apache::params::service_name,
+  $default_mods           = true,
+  $default_vhost          = true,
+  $default_charset        = undef,
+  $default_confd_files    = true,
+  $default_ssl_vhost      = false,
+  $default_ssl_cert       = $::apache::params::default_ssl_cert,
+  $default_ssl_key        = $::apache::params::default_ssl_key,
+  $default_ssl_chain      = undef,
+  $default_ssl_ca         = undef,
+  $default_ssl_crl_path   = undef,
+  $default_ssl_crl        = undef,
+  $default_ssl_crl_check  = undef,
+  $default_type           = 'none',
+  $dev_packages           = $::apache::params::dev_packages,
+  $ip                     = undef,
+  $service_enable         = true,
+  $service_manage         = true,
+  $service_ensure         = 'running',
+  $service_restart        = undef,
+  $purge_configs          = true,
+  $purge_vhost_dir        = undef,
+  $purge_vdir             = false,
+  $serveradmin            = 'root@localhost',
+  $sendfile               = 'On',
+  $error_documents        = false,
+  $timeout                = '120',
+  $httpd_dir              = $::apache::params::httpd_dir,
+  $server_root            = $::apache::params::server_root,
+  $conf_dir               = $::apache::params::conf_dir,
+  $confd_dir              = $::apache::params::confd_dir,
+  $vhost_dir              = $::apache::params::vhost_dir,
+  $vhost_enable_dir       = $::apache::params::vhost_enable_dir,
+  $vhost_include_pattern  = $::apache::params::vhost_include_pattern,
+  $mod_dir                = $::apache::params::mod_dir,
+  $mod_enable_dir         = $::apache::params::mod_enable_dir,
+  $mpm_module             = $::apache::params::mpm_module,
+  $lib_path               = $::apache::params::lib_path,
+  $conf_template          = $::apache::params::conf_template,
+  $servername             = $::apache::params::servername,
+  $pidfile                = $::apache::params::pidfile,
+  $rewrite_lock           = undef,
+  $manage_user            = true,
+  $manage_group           = true,
+  $user                   = $::apache::params::user,
+  $group                  = $::apache::params::group,
+  $keepalive              = $::apache::params::keepalive,
+  $keepalive_timeout      = $::apache::params::keepalive_timeout,
+  $max_keepalive_requests = $::apache::params::max_keepalive_requests,
+  $logroot                = $::apache::params::logroot,
+  $logroot_mode           = $::apache::params::logroot_mode,
+  $log_level              = $::apache::params::log_level,
+  $log_formats            = {},
+  $ports_file             = $::apache::params::ports_file,
+  $docroot                = $::apache::params::docroot,
+  $apache_version         = $::apache::version::default,
+  $server_tokens          = 'OS',
+  $server_signature       = 'On',
+  $trace_enable           = 'On',
+  $allow_encoded_slashes  = undef,
+  $package_ensure         = 'installed',
+  $use_optional_includes  = $::apache::params::use_optional_includes,
+  $use_systemd            = $::apache::params::use_systemd,
+) inherits ::apache::params {
+  validate_bool($default_vhost)
+  validate_bool($default_ssl_vhost)
+  validate_bool($default_confd_files)
+  # true/false is sufficient for both ensure and enable
+  validate_bool($service_enable)
+  validate_bool($service_manage)
+  validate_bool($use_optional_includes)
+
+  $valid_mpms_re = $apache_version ? {
+    '2.4'   => '(event|itk|peruser|prefork|worker)',
+    default => '(event|itk|prefork|worker)'
+  }
+
+  if $mpm_module {
+    validate_re($mpm_module, $valid_mpms_re)
+  }
+
+  if $allow_encoded_slashes {
+    validate_re($allow_encoded_slashes, '(^on$|^off$|^nodecode$)', "${allow_encoded_slashes} is not permitted for allow_encoded_slashes. Allowed values are 'on', 'off' or 'nodecode'.")
+  }
+
+  # NOTE: on FreeBSD it's mpm module's responsibility to install httpd package.
+  # NOTE: the same strategy may be introduced for other OSes. For this, you
+  # should delete the 'if' block below and modify all MPM modules' manifests
+  # such that they include apache::package class (currently event.pp, itk.pp,
+  # peruser.pp, prefork.pp, worker.pp).
+  if $::osfamily != 'FreeBSD' {
+    package { 'httpd':
+      ensure => $package_ensure,
+      name   => $apache_name,
+      notify => Class['Apache::Service'],
+    }
+  }
+  validate_re($sendfile, [ '^[oO]n$' , '^[oO]ff$' ])
+
+  # declare the web server user and group
+  # Note: requiring the package means the package ought to create them and not puppet
+  validate_bool($manage_user)
+  if $manage_user {
+    user { $user:
+      ensure  => present,
+      gid     => $group,
+      require => Package['httpd'],
+    }
+  }
+  validate_bool($manage_group)
+  if $manage_group {
+    group { $group:
+      ensure  => present,
+      require => Package['httpd']
+    }
+  }
+
+  validate_apache_log_level($log_level)
+
+  class { '::apache::service':
+    service_name    => $service_name,
+    service_enable  => $service_enable,
+    service_manage  => $service_manage,
+    service_ensure  => $service_ensure,
+    service_restart => $service_restart,
+  }
+
+  # Deprecated backwards-compatibility
+  if $purge_vdir {
+    warning('Class[\'apache\'] parameter purge_vdir is deprecated in favor of purge_configs')
+    $purge_confd = $purge_vdir
+  } else {
+    $purge_confd = $purge_configs
+  }
+
+  # Set purge vhostd appropriately
+  if $purge_vhost_dir == undef {
+    $purge_vhostd = $purge_confd
+  } else {
+    $purge_vhostd = $purge_vhost_dir
+  }
+
+  Exec {
+    path => '/bin:/sbin:/usr/bin:/usr/sbin',
+  }
+
+  exec { "mkdir ${confd_dir}":
+    creates => $confd_dir,
+    require => Package['httpd'],
+  }
+  file { $confd_dir:
+    ensure  => directory,
+    recurse => true,
+    purge   => $purge_confd,
+    notify  => Class['Apache::Service'],
+    require => Package['httpd'],
+  }
+
+  if ! defined(File[$mod_dir]) {
+    exec { "mkdir ${mod_dir}":
+      creates => $mod_dir,
+      require => Package['httpd'],
+    }
+    # Don't purge available modules if an enable dir is used
+    $purge_mod_dir = $purge_configs and !$mod_enable_dir
+    file { $mod_dir:
+      ensure  => directory,
+      recurse => true,
+      purge   => $purge_mod_dir,
+      notify  => Class['Apache::Service'],
+      require => Package['httpd'],
+    }
+  }
+
+  if $mod_enable_dir and ! defined(File[$mod_enable_dir]) {
+    $mod_load_dir = $mod_enable_dir
+    exec { "mkdir ${mod_enable_dir}":
+      creates => $mod_enable_dir,
+      require => Package['httpd'],
+    }
+    file { $mod_enable_dir:
+      ensure  => directory,
+      recurse => true,
+      purge   => $purge_configs,
+      notify  => Class['Apache::Service'],
+      require => Package['httpd'],
+    }
+  } else {
+    $mod_load_dir = $mod_dir
+  }
+
+  if ! defined(File[$vhost_dir]) {
+    exec { "mkdir ${vhost_dir}":
+      creates => $vhost_dir,
+      require => Package['httpd'],
+    }
+    file { $vhost_dir:
+      ensure  => directory,
+      recurse => true,
+      purge   => $purge_vhostd,
+      notify  => Class['Apache::Service'],
+      require => Package['httpd'],
+    }
+  }
+
+  if $vhost_enable_dir and ! defined(File[$vhost_enable_dir]) {
+    $vhost_load_dir = $vhost_enable_dir
+    exec { "mkdir ${vhost_load_dir}":
+      creates => $vhost_load_dir,
+      require => Package['httpd'],
+    }
+    file { $vhost_enable_dir:
+      ensure  => directory,
+      recurse => true,
+      purge   => $purge_vhostd,
+      notify  => Class['Apache::Service'],
+      require => Package['httpd'],
+    }
+  } else {
+    $vhost_load_dir = $vhost_dir
+  }
+
+  concat { $ports_file:
+    owner   => 'root',
+    group   => $::apache::params::root_group,
+    mode    => '0644',
+    notify  => Class['Apache::Service'],
+    require => Package['httpd'],
+  }
+  concat::fragment { 'Apache ports header':
+    ensure  => present,
+    target  => $ports_file,
+    content => template('apache/ports_header.erb')
+  }
+
+  if $::apache::conf_dir and $::apache::params::conf_file {
+    case $::osfamily {
+      'debian': {
+        $error_log            = 'error.log'
+        $scriptalias          = '/usr/lib/cgi-bin'
+        $access_log_file      = 'access.log'
+      }
+      'redhat': {
+        $error_log            = 'error_log'
+        $scriptalias          = '/var/www/cgi-bin'
+        $access_log_file      = 'access_log'
+      }
+      'freebsd': {
+        $error_log            = 'httpd-error.log'
+        $scriptalias          = '/usr/local/www/apache24/cgi-bin'
+        $access_log_file      = 'httpd-access.log'
+      } 'gentoo': {
+        $error_log            = 'error.log'
+        $error_documents_path = '/usr/share/apache2/error'
+        $scriptalias          = '/var/www/localhost/cgi-bin'
+        $access_log_file      = 'access.log'
+
+        ::portage::makeconf { 'apache2_modules':
+          content => $default_mods,
+        }
+        file { [
+          '/etc/apache2/modules.d/.keep_www-servers_apache-2',
+          '/etc/apache2/vhosts.d/.keep_www-servers_apache-2'
+        ]:
+          ensure  => absent,
+          require => Package['httpd'],
+        }
+      }
+      'Suse': {
+        $error_log            = 'error.log'
+        $scriptalias          = '/usr/lib/cgi-bin'
+        $access_log_file      = 'access.log'
+      }
+      default: {
+        fail("Unsupported osfamily ${::osfamily}")
+      }
+    }
+
+    $apxs_workaround = $::osfamily ? {
+      'freebsd' => true,
+      default   => false
+    }
+
+    if $rewrite_lock {
+      validate_absolute_path($rewrite_lock)
+    }
+
+    # Template uses:
+    # - $pidfile
+    # - $user
+    # - $group
+    # - $logroot
+    # - $error_log
+    # - $sendfile
+    # - $mod_dir
+    # - $ports_file
+    # - $confd_dir
+    # - $vhost_dir
+    # - $error_documents
+    # - $error_documents_path
+    # - $apxs_workaround
+    # - $keepalive
+    # - $keepalive_timeout
+    # - $max_keepalive_requests
+    # - $server_root
+    # - $server_tokens
+    # - $server_signature
+    # - $trace_enable
+    # - $rewrite_lock
+    file { "${::apache::conf_dir}/${::apache::params::conf_file}":
+      ensure  => file,
+      content => template($conf_template),
+      notify  => Class['Apache::Service'],
+      require => [Package['httpd'], File[$ports_file]],
+    }
+
+    # preserve back-wards compatibility to the times when default_mods was
+    # only a boolean value. Now it can be an array (too)
+    if is_array($default_mods) {
+      class { '::apache::default_mods':
+        all  => false,
+        mods => $default_mods,
+      }
+    } else {
+      class { '::apache::default_mods':
+        all => $default_mods,
+      }
+    }
+    class { '::apache::default_confd_files':
+      all => $default_confd_files
+    }
+    if $mpm_module {
+      class { "::apache::mod::${mpm_module}": }
+    }
+
+    $default_vhost_ensure = $default_vhost ? {
+      true  => 'present',
+      false => 'absent'
+    }
+    $default_ssl_vhost_ensure = $default_ssl_vhost ? {
+      true  => 'present',
+      false => 'absent'
+    }
+
+    ::apache::vhost { 'default':
+      ensure          => $default_vhost_ensure,
+      port            => 80,
+      docroot         => $docroot,
+      scriptalias     => $scriptalias,
+      serveradmin     => $serveradmin,
+      access_log_file => $access_log_file,
+      priority        => '15',
+      ip              => $ip,
+      logroot_mode    => $logroot_mode,
+      manage_docroot  => $default_vhost,
+    }
+    $ssl_access_log_file = $::osfamily ? {
+      'freebsd' => $access_log_file,
+      default   => "ssl_${access_log_file}",
+    }
+    ::apache::vhost { 'default-ssl':
+      ensure          => $default_ssl_vhost_ensure,
+      port            => 443,
+      ssl             => true,
+      docroot         => $docroot,
+      scriptalias     => $scriptalias,
+      serveradmin     => $serveradmin,
+      access_log_file => $ssl_access_log_file,
+      priority        => '15',
+      ip              => $ip,
+      logroot_mode    => $logroot_mode,
+      manage_docroot  => $default_ssl_vhost,
+    }
+  }
+
+  # This anchor can be used as a reference point for things that need to happen *after*
+  # all modules have been put in place.
+  anchor { '::apache::modules_set_up': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/listen.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+define apache::listen {
+  $listen_addr_port = $name
+
+  # Template uses: $listen_addr_port
+  concat::fragment { "Listen ${listen_addr_port}":
+    ensure  => present,
+    target  => $::apache::ports_file,
+    content => template('apache/listen.erb'),
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,167 @@
+define apache::mod (
+  $package        = undef,
+  $package_ensure = 'present',
+  $lib            = undef,
+  $lib_path       = $::apache::lib_path,
+  $id             = undef,
+  $path           = undef,
+  $loadfile_name  = undef,
+  $loadfiles      = undef,
+) {
+  if ! defined(Class['apache']) {
+    fail('You must include the apache base class before using any apache defined resources')
+  }
+
+  $mod = $name
+  #include apache #This creates duplicate resources in rspec-puppet
+  $mod_dir = $::apache::mod_dir
+
+  # Determine if we have special lib
+  $mod_libs = $::apache::params::mod_libs
+  if $lib {
+    $_lib = $lib
+  } elsif has_key($mod_libs, $mod) { # 2.6 compatibility hack
+    $_lib = $mod_libs[$mod]
+  } else {
+    $_lib = "mod_${mod}.so"
+  }
+
+  # Determine if declaration specified a path to the module
+  if $path {
+    $_path = $path
+  } else {
+    $_path = "${lib_path}/${_lib}"
+  }
+
+  if $id {
+    $_id = $id
+  } else {
+    $_id = "${mod}_module"
+  }
+
+  if $loadfile_name {
+    $_loadfile_name = $loadfile_name
+  } else {
+    $_loadfile_name = "${mod}.load"
+  }
+
+  # Determine if we have a package
+  $mod_packages = $::apache::params::mod_packages
+  if $package {
+    $_package = $package
+  } elsif has_key($mod_packages, $mod) { # 2.6 compatibility hack
+    $_package = $mod_packages[$mod]
+  } else {
+    $_package = undef
+  }
+  if $_package and ! defined(Package[$_package]) {
+    # note: FreeBSD/ports uses apxs tool to activate modules; apxs clutters
+    # httpd.conf with 'LoadModule' directives; here, by proper resource
+    # ordering, we ensure that our version of httpd.conf is reverted after
+    # the module gets installed.
+    $package_before = $::osfamily ? {
+      'freebsd' => [
+        File[$_loadfile_name],
+        File["${::apache::conf_dir}/${::apache::params::conf_file}"]
+      ],
+      default => File[$_loadfile_name],
+    }
+    # if there are any packages, they should be installed before the associated conf file
+    Package[$_package] -> File<| title == "${mod}.conf" |>
+    # $_package may be an array
+    package { $_package:
+      ensure  => $package_ensure,
+      require => Package['httpd'],
+      before  => $package_before,
+    }
+  }
+
+  file { $_loadfile_name:
+    ensure  => file,
+    path    => "${mod_dir}/${_loadfile_name}",
+    owner   => 'root',
+    group   => $::apache::params::root_group,
+    mode    => '0644',
+    content => template('apache/mod/load.erb'),
+    require => [
+      Package['httpd'],
+      Exec["mkdir ${mod_dir}"],
+    ],
+    before  => File[$mod_dir],
+    notify  => Class['apache::service'],
+  }
+
+  if $::osfamily == 'Debian' {
+    $enable_dir = $::apache::mod_enable_dir
+    file{ "${_loadfile_name} symlink":
+      ensure  => link,
+      path    => "${enable_dir}/${_loadfile_name}",
+      target  => "${mod_dir}/${_loadfile_name}",
+      owner   => 'root',
+      group   => $::apache::params::root_group,
+      mode    => '0644',
+      require => [
+        File[$_loadfile_name],
+        Exec["mkdir ${enable_dir}"],
+      ],
+      before  => File[$enable_dir],
+      notify  => Class['apache::service'],
+    }
+    # Each module may have a .conf file as well, which should be
+    # defined in the class apache::mod::module
+    # Some modules do not require this file.
+    if defined(File["${mod}.conf"]) {
+      file{ "${mod}.conf symlink":
+        ensure  => link,
+        path    => "${enable_dir}/${mod}.conf",
+        target  => "${mod_dir}/${mod}.conf",
+        owner   => 'root',
+        group   => $::apache::params::root_group,
+        mode    => '0644',
+        require => [
+          File["${mod}.conf"],
+          Exec["mkdir ${enable_dir}"],
+        ],
+        before  => File[$enable_dir],
+        notify  => Class['apache::service'],
+      }
+    }
+  } elsif $::osfamily == 'Suse' {
+    $enable_dir = $::apache::mod_enable_dir
+    file{ "${_loadfile_name} symlink":
+      ensure  => link,
+      path    => "${enable_dir}/${_loadfile_name}",
+      target  => "${mod_dir}/${_loadfile_name}",
+      owner   => 'root',
+      group   => $::apache::params::root_group,
+      mode    => '0644',
+      require => [
+        File[$_loadfile_name],
+        Exec["mkdir ${enable_dir}"],
+      ],
+      before  => File[$enable_dir],
+      notify  => Class['apache::service'],
+    }
+    # Each module may have a .conf file as well, which should be
+    # defined in the class apache::mod::module
+    # Some modules do not require this file.
+    if defined(File["${mod}.conf"]) {
+      file{ "${mod}.conf symlink":
+        ensure  => link,
+        path    => "${enable_dir}/${mod}.conf",
+        target  => "${mod_dir}/${mod}.conf",
+        owner   => 'root',
+        group   => $::apache::params::root_group,
+        mode    => '0644',
+        require => [
+          File["${mod}.conf"],
+          Exec["mkdir ${enable_dir}"],
+        ],
+        before  => File[$enable_dir],
+        notify  => Class['apache::service'],
+      }
+    }
+  }
+
+  Apache::Mod[$name] -> Anchor['::apache::modules_set_up']
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/actions.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::actions {
+  apache::mod { 'actions': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/alias.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+class apache::mod::alias(
+  $apache_version = $apache::apache_version,
+  $icons_options  = 'Indexes MultiViews',
+  # set icons_path to false to disable the alias
+  $icons_path     = $::apache::params::alias_icons_path,
+
+) {
+  apache::mod { 'alias': }
+  # Template uses $icons_path
+  if $icons_path {
+    file { 'alias.conf':
+      ensure  => file,
+      path    => "${::apache::mod_dir}/alias.conf",
+      content => template('apache/mod/alias.conf.erb'),
+      require => Exec["mkdir ${::apache::mod_dir}"],
+      before  => File[$::apache::mod_dir],
+      notify  => Class['apache::service'],
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/auth_basic.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::auth_basic {
+  ::apache::mod { 'auth_basic': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/auth_cas.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,48 @@
+class apache::mod::auth_cas (
+  $cas_login_url,
+  $cas_validate_url,
+  $cas_cookie_path          = $::apache::params::cas_cookie_path,
+  $cas_version              = 2,
+  $cas_debug                = 'Off',
+  $cas_validate_depth       = undef,
+  $cas_certificate_path     = undef,
+  $cas_proxy_validate_url   = undef,
+  $cas_root_proxied_as      = undef,
+  $cas_cookie_entropy       = undef,
+  $cas_timeout              = undef,
+  $cas_idle_timeout         = undef,
+  $cas_cache_clean_interval = undef,
+  $cas_cookie_domain        = undef,
+  $cas_cookie_http_only     = undef,
+  $cas_authoritative        = undef,
+  $suppress_warning         = false,
+) {
+
+  validate_string($cas_login_url, $cas_validate_url, $cas_cookie_path)
+
+  if $::osfamily == 'RedHat' and ! $suppress_warning {
+    warning('RedHat distributions do not have Apache mod_auth_cas in their default package repositories.')
+  }
+
+  ::apache::mod { 'auth_cas': }
+
+  file { $cas_cookie_path:
+    ensure => directory,
+    before => File['auth_cas.conf'],
+    mode   => '0750',
+    owner  => $apache::user,
+    group  => $apache::group,
+  }
+
+  # Template uses
+  # - All variables beginning with cas_
+  file { 'auth_cas.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/auth_cas.conf",
+    content => template('apache/mod/auth_cas.conf.erb'),
+    require => [ Exec["mkdir ${::apache::mod_dir}"], ],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['Apache::Service'],
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/auth_kerb.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+class apache::mod::auth_kerb {
+  ::apache::mod { 'auth_kerb': }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/auth_mellon.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+class apache::mod::auth_mellon (
+  $mellon_cache_size = $::apache::params::mellon_cache_size,
+  $mellon_lock_file  = $::apache::params::mellon_lock_file,
+  $mellon_post_directory = $::apache::params::mellon_post_directory,
+  $mellon_cache_entry_size = undef,
+  $mellon_post_ttl = undef,
+  $mellon_post_size = undef,
+  $mellon_post_count = undef
+) {
+
+  ::apache::mod { 'auth_mellon': }
+
+  # Template uses
+  # - All variables beginning with mellon_
+  file { 'auth_mellon.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/auth_mellon.conf",
+    content => template('apache/mod/auth_mellon.conf.erb'),
+    require => [ Exec["mkdir ${::apache::mod_dir}"], ],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['Apache::Service'],
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/authn_core.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+class apache::mod::authn_core(
+  $apache_version = $::apache::apache_version
+) {
+  if versioncmp($apache_version, '2.4') >= 0 {
+    ::apache::mod { 'authn_core': }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/authn_file.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::authn_file {
+  ::apache::mod { 'authn_file': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/authnz_ldap.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+class apache::mod::authnz_ldap (
+  $verifyServerCert = true,
+) {
+  include '::apache::mod::ldap'
+  ::apache::mod { 'authnz_ldap': }
+
+  validate_bool($verifyServerCert)
+
+  # Template uses:
+  # - $verifyServerCert
+  file { 'authnz_ldap.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/authnz_ldap.conf",
+    content => template('apache/mod/authnz_ldap.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/authz_default.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+class apache::mod::authz_default(
+    $apache_version = $::apache::apache_version
+) {
+  if versioncmp($apache_version, '2.4') >= 0 {
+    warning('apache::mod::authz_default has been removed in Apache 2.4')
+  } else {
+    ::apache::mod { 'authz_default': }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/authz_user.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::authz_user {
+  ::apache::mod { 'authz_user': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/autoindex.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+class apache::mod::autoindex {
+  ::apache::mod { 'autoindex': }
+  # Template uses no variables
+  file { 'autoindex.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/autoindex.conf",
+    content => template('apache/mod/autoindex.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/cache.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::cache {
+  ::apache::mod { 'cache': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/cgi.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+class apache::mod::cgi {
+  case $::osfamily {
+    'FreeBSD': {}
+    default: {
+      Class['::apache::mod::prefork'] -> Class['::apache::mod::cgi']
+    }
+  }
+
+  ::apache::mod { 'cgi': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/cgid.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+class apache::mod::cgid {
+  case $::osfamily {
+    'FreeBSD': {}
+    default: {
+      if defined(Class['::apache::mod::event']) {
+        Class['::apache::mod::event'] -> Class['::apache::mod::cgid']
+      } else {
+        Class['::apache::mod::worker'] -> Class['::apache::mod::cgid']
+      }
+    }
+  }
+
+  # Debian specifies it's cgid sock path, but RedHat uses the default value
+  # with no config file
+  $cgisock_path = $::osfamily ? {
+    'debian'  => "\${APACHE_RUN_DIR}/cgisock",
+    'freebsd' => 'cgisock',
+    default   => undef,
+  }
+  ::apache::mod { 'cgid': }
+  if $cgisock_path {
+    # Template uses $cgisock_path
+    file { 'cgid.conf':
+      ensure  => file,
+      path    => "${::apache::mod_dir}/cgid.conf",
+      content => template('apache/mod/cgid.conf.erb'),
+      require => Exec["mkdir ${::apache::mod_dir}"],
+      before  => File[$::apache::mod_dir],
+      notify  => Class['apache::service'],
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/dav.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::dav {
+  ::apache::mod { 'dav': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/dav_fs.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+class apache::mod::dav_fs {
+  $dav_lock = $::osfamily ? {
+    'debian'  => "\${APACHE_LOCK_DIR}/DAVLock",
+    'freebsd' => '/usr/local/var/DavLock',
+    default   => '/var/lib/dav/lockdb',
+  }
+
+  Class['::apache::mod::dav'] -> Class['::apache::mod::dav_fs']
+  ::apache::mod { 'dav_fs': }
+
+  # Template uses: $dav_lock
+  file { 'dav_fs.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/dav_fs.conf",
+    content => template('apache/mod/dav_fs.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/dav_svn.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+class apache::mod::dav_svn (
+  $authz_svn_enabled = false,
+) {
+  Class['::apache::mod::dav'] -> Class['::apache::mod::dav_svn']
+  include ::apache::mod::dav
+  ::apache::mod { 'dav_svn': }
+
+  if $::osfamily == 'Debian' and ($::operatingsystemmajrelease != '6' and $::operatingsystemmajrelease != '10.04' and $::operatingsystemrelease != '10.04') {
+    $loadfile_name = undef
+  } else {
+    $loadfile_name = 'dav_svn_authz_svn.load'
+  }
+
+  if $authz_svn_enabled {
+    ::apache::mod { 'authz_svn':
+      loadfile_name => $loadfile_name,
+      require       => Apache::Mod['dav_svn'],
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/deflate.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+class apache::mod::deflate (
+  $types = [
+    'text/html text/plain text/xml',
+    'text/css',
+    'application/x-javascript application/javascript application/ecmascript',
+    'application/rss+xml',
+    'application/json'
+  ],
+  $notes = {
+    'Input'  => 'instream',
+    'Output' => 'outstream',
+    'Ratio'  => 'ratio'
+  }
+) {
+  ::apache::mod { 'deflate': }
+
+  file { 'deflate.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/deflate.conf",
+    content => template('apache/mod/deflate.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/dev.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+class apache::mod::dev {
+  # Development packages are not apache modules
+  warning('apache::mod::dev is deprecated; please use apache::dev')
+  include ::apache::dev
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/dir.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+# Note: this sets the global DirectoryIndex directive, it may be necessary to consider being able to modify the apache::vhost to declare DirectoryIndex statements in a vhost configuration
+# Parameters:
+# - $indexes provides a string for the DirectoryIndex directive http://httpd.apache.org/docs/current/mod/mod_dir.html#directoryindex
+class apache::mod::dir (
+  $dir     = 'public_html',
+  $indexes = ['index.html','index.html.var','index.cgi','index.pl','index.php','index.xhtml'],
+) {
+  validate_array($indexes)
+  ::apache::mod { 'dir': }
+
+  # Template uses
+  # - $indexes
+  file { 'dir.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/dir.conf",
+    content => template('apache/mod/dir.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/disk_cache.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,40 @@
+class apache::mod::disk_cache (
+  $cache_root = undef,
+) {
+  if $cache_root {
+    $_cache_root = $cache_root
+  }
+  elsif versioncmp($::apache::apache_version, '2.4') >= 0 {
+    $_cache_root = $::osfamily ? {
+      'debian'  => '/var/cache/apache2/mod_cache_disk',
+      'redhat'  => '/var/cache/httpd/proxy',
+      'freebsd' => '/var/cache/mod_cache_disk',
+    }
+  }
+  else {
+    $_cache_root = $::osfamily ? {
+      'debian'  => '/var/cache/apache2/mod_disk_cache',
+      'redhat'  => '/var/cache/mod_proxy',
+      'freebsd' => '/var/cache/mod_disk_cache',
+    }
+  }
+
+  if versioncmp($::apache::apache_version, '2.4') >= 0 {
+    apache::mod { 'cache_disk': }
+  }
+  else {
+    apache::mod { 'disk_cache': }
+  }
+
+  Class['::apache::mod::cache'] -> Class['::apache::mod::disk_cache']
+
+  # Template uses $_cache_root
+  file { 'disk_cache.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/disk_cache.conf",
+    content => template('apache/mod/disk_cache.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/event.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,71 @@
+class apache::mod::event (
+  $startservers           = '2',
+  $maxclients             = '150',
+  $minsparethreads        = '25',
+  $maxsparethreads        = '75',
+  $threadsperchild        = '25',
+  $maxrequestsperchild    = '0',
+  $serverlimit            = '25',
+  $apache_version         = $::apache::apache_version,
+  $threadlimit            = '64',
+  $listenbacklog          = '511',
+  $maxrequestworkers      = '250',
+  $maxconnectionsperchild = '0',
+) {
+  if defined(Class['apache::mod::itk']) {
+    fail('May not include both apache::mod::event and apache::mod::itk on the same node')
+  }
+  if defined(Class['apache::mod::peruser']) {
+    fail('May not include both apache::mod::event and apache::mod::peruser on the same node')
+  }
+  if defined(Class['apache::mod::prefork']) {
+    fail('May not include both apache::mod::event and apache::mod::prefork on the same node')
+  }
+  if defined(Class['apache::mod::worker']) {
+    fail('May not include both apache::mod::event and apache::mod::worker on the same node')
+  }
+  File {
+    owner => 'root',
+    group => $::apache::params::root_group,
+    mode  => '0644',
+  }
+
+  # Template uses:
+  # - $startservers
+  # - $maxclients
+  # - $minsparethreads
+  # - $maxsparethreads
+  # - $threadsperchild
+  # - $maxrequestsperchild
+  # - $serverlimit
+  file { "${::apache::mod_dir}/event.conf":
+    ensure  => file,
+    content => template('apache/mod/event.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+
+  case $::osfamily {
+    'redhat': {
+      if versioncmp($apache_version, '2.4') >= 0 {
+        apache::mpm{ 'event':
+          apache_version => $apache_version,
+        }
+      }
+    }
+    'debian','freebsd' : {
+      apache::mpm{ 'event':
+        apache_version => $apache_version,
+      }
+    }
+    'gentoo': {
+      ::portage::makeconf { 'apache2_mpms':
+        content => 'event',
+      }
+    }
+    default: {
+      fail("Unsupported osfamily ${::osfamily}")
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/expires.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+class apache::mod::expires (
+  $expires_active  = true,
+  $expires_default = undef,
+  $expires_by_type = undef,
+) {
+  ::apache::mod { 'expires': }
+
+  # Template uses
+  # $expires_active
+  # $expires_default
+  # $expires_by_type
+  file { 'expires.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/expires.conf",
+    content => template('apache/mod/expires.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/ext_filter.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+class apache::mod::ext_filter(
+  $ext_filter_define = undef
+) {
+
+  if $ext_filter_define {
+    validate_hash($ext_filter_define)
+  }
+
+  ::apache::mod { 'ext_filter': }
+
+  # Template uses
+  # -$ext_filter_define
+
+  if $ext_filter_define {
+    file { 'ext_filter.conf':
+      ensure  => file,
+      path    => "${::apache::mod_dir}/ext_filter.conf",
+      content => template('apache/mod/ext_filter.conf.erb'),
+      require => [ Exec["mkdir ${::apache::mod_dir}"], ],
+      before  => File[$::apache::mod_dir],
+      notify  => Class['Apache::Service'],
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/fastcgi.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+class apache::mod::fastcgi {
+
+  # Debian specifies it's fastcgi lib path, but RedHat uses the default value
+  # with no config file
+  $fastcgi_lib_path = $::apache::params::fastcgi_lib_path
+
+  ::apache::mod { 'fastcgi': }
+
+  if $fastcgi_lib_path {
+    # Template uses:
+    # - $fastcgi_server
+    # - $fastcgi_socket
+    # - $fastcgi_dir
+    file { 'fastcgi.conf':
+      ensure  => file,
+      path    => "${::apache::mod_dir}/fastcgi.conf",
+      content => template('apache/mod/fastcgi.conf.erb'),
+      require => Exec["mkdir ${::apache::mod_dir}"],
+      before  => File[$::apache::mod_dir],
+      notify  => Class['apache::service'],
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/fcgid.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+class apache::mod::fcgid(
+  $options = {},
+) {
+
+  ::apache::mod { 'fcgid':
+    loadfile_name => 'unixd_fcgid.load',
+  }
+
+  # Template uses:
+  # - $options
+  file { 'unixd_fcgid.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/unixd_fcgid.conf",
+    content => template('apache/mod/unixd_fcgid.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/filter.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::filter {
+  ::apache::mod { 'filter': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/geoip.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+class apache::mod::geoip (
+  $enable                     = false,
+  $db_file                    = '/usr/share/GeoIP/GeoIP.dat',
+  $flag                       = 'Standard',
+  $output                     = 'All',
+  $enable_utf8                = undef,
+  $scan_proxy_headers         = undef,
+  $scan_proxy_header_field    = undef,
+  $use_last_xforwarededfor_ip = undef,
+) {
+  ::apache::mod { 'geoip': }
+
+  # Template uses:
+  # - enable
+  # - db_file
+  # - flag
+  # - output
+  # - enable_utf8
+  # - scan_proxy_headers
+  # - scan_proxy_header_field
+  # - use_last_xforwarededfor_ip
+  file { 'geoip.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/geoip.conf",
+    content => template('apache/mod/geoip.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/headers.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::headers {
+  ::apache::mod { 'headers': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/include.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::include {
+  ::apache::mod { 'include': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/info.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+class apache::mod::info (
+  $allow_from      = ['127.0.0.1','::1'],
+  $apache_version  = $::apache::apache_version,
+  $restrict_access = true,
+){
+  apache::mod { 'info': }
+  # Template uses
+  # $allow_from
+  # $apache_version
+  file { 'info.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/info.conf",
+    content => template('apache/mod/info.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/itk.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,60 @@
+class apache::mod::itk (
+  $startservers        = '8',
+  $minspareservers     = '5',
+  $maxspareservers     = '20',
+  $serverlimit         = '256',
+  $maxclients          = '256',
+  $maxrequestsperchild = '4000',
+  $apache_version      = $::apache::apache_version,
+) {
+  if defined(Class['apache::mod::event']) {
+    fail('May not include both apache::mod::itk and apache::mod::event on the same node')
+  }
+  if defined(Class['apache::mod::peruser']) {
+    fail('May not include both apache::mod::itk and apache::mod::peruser on the same node')
+  }
+  if versioncmp($apache_version, '2.4') < 0 {
+    if defined(Class['apache::mod::prefork']) {
+      fail('May not include both apache::mod::itk and apache::mod::prefork on the same node')
+    }
+  }
+  if defined(Class['apache::mod::worker']) {
+    fail('May not include both apache::mod::itk and apache::mod::worker on the same node')
+  }
+  File {
+    owner => 'root',
+    group => $::apache::params::root_group,
+    mode  => '0644',
+  }
+
+  # Template uses:
+  # - $startservers
+  # - $minspareservers
+  # - $maxspareservers
+  # - $serverlimit
+  # - $maxclients
+  # - $maxrequestsperchild
+  file { "${::apache::mod_dir}/itk.conf":
+    ensure  => file,
+    content => template('apache/mod/itk.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+
+  case $::osfamily {
+    'debian', 'freebsd': {
+      apache::mpm{ 'itk':
+        apache_version => $apache_version,
+      }
+    }
+    'gentoo': {
+      ::portage::makeconf { 'apache2_mpms':
+        content => 'itk',
+      }
+    }
+    default: {
+      fail("Unsupported osfamily ${::osfamily}")
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/ldap.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+class apache::mod::ldap (
+  $apache_version = $::apache::apache_version,
+){
+  ::apache::mod { 'ldap': }
+  # Template uses $apache_version
+  file { 'ldap.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/ldap.conf",
+    content => template('apache/mod/ldap.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/mime.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+class apache::mod::mime (
+  $mime_support_package = $::apache::params::mime_support_package,
+  $mime_types_config    = $::apache::params::mime_types_config,
+) {
+  apache::mod { 'mime': }
+  # Template uses $mime_types_config
+  file { 'mime.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/mime.conf",
+    content => template('apache/mod/mime.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+  if $mime_support_package {
+    package { $mime_support_package:
+      ensure => 'installed',
+      before => File['mime.conf'],
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/mime_magic.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+class apache::mod::mime_magic (
+  $magic_file = "${::apache::conf_dir}/magic"
+) {
+  apache::mod { 'mime_magic': }
+  # Template uses $magic_file
+  file { 'mime_magic.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/mime_magic.conf",
+    content => template('apache/mod/mime_magic.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/negotiation.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+class apache::mod::negotiation (
+  $force_language_priority = 'Prefer Fallback',
+  $language_priority = [ 'en', 'ca', 'cs', 'da', 'de', 'el', 'eo', 'es', 'et',
+                        'fr', 'he', 'hr', 'it', 'ja', 'ko', 'ltz', 'nl', 'nn',
+                        'no', 'pl', 'pt', 'pt-BR', 'ru', 'sv', 'zh-CN',
+                        'zh-TW' ],
+) {
+  if !is_array($force_language_priority) and !is_string($force_language_priority) {
+    fail('force_languague_priority must be a string or array of strings')
+  }
+  if !is_array($language_priority) and !is_string($language_priority) {
+    fail('force_languague_priority must be a string or array of strings')
+  }
+
+  ::apache::mod { 'negotiation': }
+  # Template uses no variables
+  file { 'negotiation.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/negotiation.conf",
+    content => template('apache/mod/negotiation.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/nss.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+class apache::mod::nss (
+  $transfer_log = "${::apache::params::logroot}/access.log",
+  $error_log    = "${::apache::params::logroot}/error.log",
+  $passwd_file  = undef
+) {
+  include ::apache::mod::mime
+
+  apache::mod { 'nss': }
+
+  $httpd_dir = $::apache::httpd_dir
+
+  # Template uses:
+  # $transfer_log
+  # $error_log
+  # $http_dir
+  # passwd_file
+  file { 'nss.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/nss.conf",
+    content => template('apache/mod/nss.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/pagespeed.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,55 @@
+class apache::mod::pagespeed (
+  $inherit_vhost_config          = 'on',
+  $filter_xhtml                  = false,
+  $cache_path                    = '/var/cache/mod_pagespeed/',
+  $log_dir                       = '/var/log/pagespeed',
+  $memcache_servers              = [],
+  $rewrite_level                 = 'CoreFilters',
+  $disable_filters               = [],
+  $enable_filters                = [],
+  $forbid_filters                = [],
+  $rewrite_deadline_per_flush_ms = 10,
+  $additional_domains            = undef,
+  $file_cache_size_kb            = 102400,
+  $file_cache_clean_interval_ms  = 3600000,
+  $lru_cache_per_process         = 1024,
+  $lru_cache_byte_limit          = 16384,
+  $css_flatten_max_bytes         = 2048,
+  $css_inline_max_bytes          = 2048,
+  $css_image_inline_max_bytes    = 2048,
+  $image_inline_max_bytes        = 2048,
+  $js_inline_max_bytes           = 2048,
+  $css_outline_min_bytes         = 3000,
+  $js_outline_min_bytes          = 3000,
+  $inode_limit                   = 500000,
+  $image_max_rewrites_at_once    = 8,
+  $num_rewrite_threads           = 4,
+  $num_expensive_rewrite_threads = 4,
+  $collect_statistics            = 'on',
+  $statistics_logging            = 'on',
+  $allow_view_stats              = [],
+  $allow_pagespeed_console       = [],
+  $allow_pagespeed_message       = [],
+  $message_buffer_size           = 100000,
+  $additional_configuration      = {},
+  $apache_version                = $::apache::apache_version,
+){
+
+  $_lib = $::apache::apache_version ? {
+    '2.4'   => 'mod_pagespeed_ap24.so',
+    default => undef
+  }
+
+  apache::mod { 'pagespeed':
+    lib => $_lib,
+  }
+
+  file { 'pagespeed.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/pagespeed.conf",
+    content => template('apache/mod/pagespeed.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/passenger.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,84 @@
+class apache::mod::passenger (
+  $passenger_conf_file            = $::apache::params::passenger_conf_file,
+  $passenger_conf_package_file    = $::apache::params::passenger_conf_package_file,
+  $passenger_high_performance     = undef,
+  $passenger_pool_idle_time       = undef,
+  $passenger_max_requests         = undef,
+  $passenger_spawn_method         = undef,
+  $passenger_stat_throttle_rate   = undef,
+  $rack_autodetect                = undef,
+  $rails_autodetect               = undef,
+  $passenger_root                 = $::apache::params::passenger_root,
+  $passenger_ruby                 = $::apache::params::passenger_ruby,
+  $passenger_default_ruby         = $::apache::params::passenger_default_ruby,
+  $passenger_max_pool_size        = undef,
+  $passenger_min_instances        = undef,
+  $passenger_use_global_queue     = undef,
+  $passenger_app_env              = undef,
+  $mod_package                    = undef,
+  $mod_package_ensure             = undef,
+  $mod_lib                        = undef,
+  $mod_lib_path                   = undef,
+  $mod_id                         = undef,
+  $mod_path                       = undef,
+) {
+
+  if $passenger_spawn_method {
+    validate_re($passenger_spawn_method, '(^smart$|^direct$|^smart-lv2$|^conservative$)', "${passenger_spawn_method} is not permitted for passenger_spawn_method. Allowed values are 'smart', 'direct', 'smart-lv2', or 'conservative'.")
+  }
+
+  # Managed by the package, but declare it to avoid purging
+  if $passenger_conf_package_file {
+    file { 'passenger_package.conf':
+      path => "${::apache::mod_dir}/${passenger_conf_package_file}",
+    }
+  }
+
+  $_package = $mod_package
+  $_package_ensure = $mod_package_ensure
+  $_lib = $mod_lib
+  if $::osfamily == 'FreeBSD' {
+    if $mod_lib_path {
+      $_lib_path = $mod_lib_path
+    } else {
+      $_lib_path = "${passenger_root}/buildout/apache2"
+    }
+  } else {
+    $_lib_path = $mod_lib_path
+  }
+
+  $_id = $mod_id
+  $_path = $mod_path
+  ::apache::mod { 'passenger':
+    package        => $_package,
+    package_ensure => $_package_ensure,
+    lib            => $_lib,
+    lib_path       => $_lib_path,
+    id             => $_id,
+    path           => $_path,
+    loadfile_name  => 'zpassenger.load',
+  }
+
+  # Template uses:
+  # - $passenger_root
+  # - $passenger_ruby
+  # - $passenger_default_ruby
+  # - $passenger_max_pool_size
+  # - $passenger_min_instances
+  # - $passenger_high_performance
+  # - $passenger_max_requests
+  # - $passenger_spawn_method
+  # - $passenger_stat_throttle_rate
+  # - $passenger_use_global_queue
+  # - $passenger_app_env
+  # - $rack_autodetect
+  # - $rails_autodetect
+  file { 'passenger.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/${passenger_conf_file}",
+    content => template('apache/mod/passenger.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/perl.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::perl {
+  ::apache::mod { 'perl': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/peruser.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,76 @@
+class apache::mod::peruser (
+  $minspareprocessors = '2',
+  $minprocessors = '2',
+  $maxprocessors = '10',
+  $maxclients = '150',
+  $maxrequestsperchild = '1000',
+  $idletimeout = '120',
+  $expiretimeout = '120',
+  $keepalive = 'Off',
+) {
+
+  case $::osfamily {
+    'freebsd' : {
+      fail("Unsupported osfamily ${::osfamily}")
+    }
+    default: {
+      if $::osfamily == 'gentoo' {
+        ::portage::makeconf { 'apache2_mpms':
+          content => 'peruser',
+        }
+      }
+
+      if defined(Class['apache::mod::event']) {
+        fail('May not include both apache::mod::peruser and apache::mod::event on the same node')
+      }
+      if defined(Class['apache::mod::itk']) {
+        fail('May not include both apache::mod::peruser and apache::mod::itk on the same node')
+      }
+      if defined(Class['apache::mod::prefork']) {
+        fail('May not include both apache::mod::peruser and apache::mod::prefork on the same node')
+      }
+      if defined(Class['apache::mod::worker']) {
+        fail('May not include both apache::mod::peruser and apache::mod::worker on the same node')
+      }
+      File {
+        owner => 'root',
+        group => $::apache::params::root_group,
+        mode  => '0644',
+      }
+
+      $mod_dir = $::apache::mod_dir
+
+      # Template uses:
+      # - $minspareprocessors
+      # - $minprocessors
+      # - $maxprocessors
+      # - $maxclients
+      # - $maxrequestsperchild
+      # - $idletimeout
+      # - $expiretimeout
+      # - $keepalive
+      # - $mod_dir
+      file { "${::apache::mod_dir}/peruser.conf":
+        ensure  => file,
+        content => template('apache/mod/peruser.conf.erb'),
+        require => Exec["mkdir ${::apache::mod_dir}"],
+        before  => File[$::apache::mod_dir],
+        notify  => Class['apache::service'],
+      }
+      file { "${::apache::mod_dir}/peruser":
+        ensure  => directory,
+        require => File[$::apache::mod_dir],
+      }
+      file { "${::apache::mod_dir}/peruser/multiplexers":
+        ensure  => directory,
+        require => File["${::apache::mod_dir}/peruser"],
+      }
+      file { "${::apache::mod_dir}/peruser/processors":
+        ensure  => directory,
+        require => File["${::apache::mod_dir}/peruser"],
+      }
+
+      ::apache::peruser::multiplexer { '01-default': }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/php.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,62 @@
+class apache::mod::php (
+  $package_name   = undef,
+  $package_ensure = 'present',
+  $path           = undef,
+  $extensions     = ['.php'],
+  $content        = undef,
+  $template       = 'apache/mod/php5.conf.erb',
+  $source         = undef,
+  $root_group     = $::apache::params::root_group,
+) inherits apache::params {
+
+  if defined(Class['::apache::mod::prefork']) {
+    Class['::apache::mod::prefork']->File['php5.conf']
+  }
+  elsif defined(Class['::apache::mod::itk']) {
+    Class['::apache::mod::itk']->File['php5.conf']
+  }
+  else {
+    fail('apache::mod::php requires apache::mod::prefork or apache::mod::itk; please enable mpm_module => \'prefork\' or mpm_module => \'itk\' on Class[\'apache\']')
+  }
+  validate_array($extensions)
+
+  if $source and ($content or $template != 'apache/mod/php5.conf.erb') {
+    warning('source and content or template parameters are provided. source parameter will be used')
+  } elsif $content and $template != 'apache/mod/php5.conf.erb' {
+    warning('content and template parameters are provided. content parameter will be used')
+  }
+
+  $manage_content = $source ? {
+    undef   => $content ? {
+      undef   => template($template),
+      default => $content,
+    },
+    default => undef,
+  }
+
+  ::apache::mod { 'php5':
+    package        => $package_name,
+    package_ensure => $package_ensure,
+    path           => $path,
+  }
+
+  include ::apache::mod::mime
+  include ::apache::mod::dir
+  Class['::apache::mod::mime'] -> Class['::apache::mod::dir'] -> Class['::apache::mod::php']
+
+  # Template uses $extensions
+  file { 'php5.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/php5.conf",
+    owner   => 'root',
+    group   => $root_group,
+    mode    => '0644',
+    content => $manage_content,
+    source  => $source,
+    require => [
+      Exec["mkdir ${::apache::mod_dir}"],
+    ],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/prefork.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,77 @@
+class apache::mod::prefork (
+  $startservers        = '8',
+  $minspareservers     = '5',
+  $maxspareservers     = '20',
+  $serverlimit         = '256',
+  $maxclients          = '256',
+  $maxrequestsperchild = '4000',
+  $apache_version      = $::apache::apache_version,
+) {
+  if defined(Class['apache::mod::event']) {
+    fail('May not include both apache::mod::prefork and apache::mod::event on the same node')
+  }
+  if versioncmp($apache_version, '2.4') < 0 {
+    if defined(Class['apache::mod::itk']) {
+      fail('May not include both apache::mod::prefork and apache::mod::itk on the same node')
+    }
+  }
+  if defined(Class['apache::mod::peruser']) {
+    fail('May not include both apache::mod::prefork and apache::mod::peruser on the same node')
+  }
+  if defined(Class['apache::mod::worker']) {
+    fail('May not include both apache::mod::prefork and apache::mod::worker on the same node')
+  }
+  File {
+    owner => 'root',
+    group => $::apache::params::root_group,
+    mode  => '0644',
+  }
+
+  # Template uses:
+  # - $startservers
+  # - $minspareservers
+  # - $maxspareservers
+  # - $serverlimit
+  # - $maxclients
+  # - $maxrequestsperchild
+  file { "${::apache::mod_dir}/prefork.conf":
+    ensure  => file,
+    content => template('apache/mod/prefork.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+
+  case $::osfamily {
+    'redhat': {
+      if versioncmp($apache_version, '2.4') >= 0 {
+        ::apache::mpm{ 'prefork':
+          apache_version => $apache_version,
+        }
+      }
+      else {
+        file_line { '/etc/sysconfig/httpd prefork enable':
+          ensure  => present,
+          path    => '/etc/sysconfig/httpd',
+          line    => '#HTTPD=/usr/sbin/httpd.worker',
+          match   => '#?HTTPD=/usr/sbin/httpd.worker',
+          require => Package['httpd'],
+          notify  => Class['apache::service'],
+        }
+      }
+    }
+    'debian', 'freebsd', 'Suse' : {
+      ::apache::mpm{ 'prefork':
+        apache_version => $apache_version,
+      }
+    }
+    'gentoo': {
+      ::portage::makeconf { 'apache2_mpms':
+        content => 'prefork',
+      }
+    }
+    default: {
+      fail("Unsupported osfamily ${::osfamily}")
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/proxy.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+class apache::mod::proxy (
+  $proxy_requests = 'Off',
+  $allow_from = undef,
+  $apache_version = $::apache::apache_version,
+) {
+  ::apache::mod { 'proxy': }
+  # Template uses $proxy_requests, $apache_version
+  file { 'proxy.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/proxy.conf",
+    content => template('apache/mod/proxy.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/proxy_ajp.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+class apache::mod::proxy_ajp {
+  Class['::apache::mod::proxy'] -> Class['::apache::mod::proxy_ajp']
+  ::apache::mod { 'proxy_ajp': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/proxy_balancer.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+class apache::mod::proxy_balancer {
+
+  include ::apache::mod::proxy
+  include ::apache::mod::proxy_http
+
+  Class['::apache::mod::proxy'] -> Class['::apache::mod::proxy_balancer']
+  Class['::apache::mod::proxy_http'] -> Class['::apache::mod::proxy_balancer']
+  ::apache::mod { 'proxy_balancer': }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/proxy_connect.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+class apache::mod::proxy_connect (
+  $apache_version  = $::apache::apache_version,
+) {
+  if versioncmp($apache_version, '2.2') >= 0 {
+    Class['::apache::mod::proxy'] -> Class['::apache::mod::proxy_connect']
+    ::apache::mod { 'proxy_connect': }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/proxy_html.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+class apache::mod::proxy_html {
+  Class['::apache::mod::proxy'] -> Class['::apache::mod::proxy_html']
+  Class['::apache::mod::proxy_http'] -> Class['::apache::mod::proxy_html']
+
+  # Add libxml2
+  case $::osfamily {
+    /RedHat|FreeBSD|Gentoo/: {
+      ::apache::mod { 'xml2enc': }
+      $loadfiles = undef
+    }
+    'Debian': {
+      $gnu_path = $::hardwaremodel ? {
+        'i686'  => 'i386',
+        default => $::hardwaremodel,
+      }
+      $loadfiles = $::apache::params::distrelease ? {
+        '6'     => ['/usr/lib/libxml2.so.2'],
+        '10'    => ['/usr/lib/libxml2.so.2'],
+        default => ["/usr/lib/${gnu_path}-linux-gnu/libxml2.so.2"],
+      }
+    }
+  }
+
+  ::apache::mod { 'proxy_html':
+    loadfiles => $loadfiles,
+  }
+
+  # Template uses $icons_path
+  file { 'proxy_html.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/proxy_html.conf",
+    content => template('apache/mod/proxy_html.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/proxy_http.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+class apache::mod::proxy_http {
+  Class['::apache::mod::proxy'] -> Class['::apache::mod::proxy_http']
+  ::apache::mod { 'proxy_http': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/python.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+class apache::mod::python {
+  ::apache::mod { 'python': }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/remoteip.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+class apache::mod::remoteip (
+  $header            = 'X-Forwarded-For',
+  $proxy_ips         = [ '127.0.0.1' ],
+  $proxies_header    = undef,
+  $trusted_proxy_ips = undef,
+  $apache_version    = $::apache::apache_version
+) {
+  if versioncmp($apache_version, '2.4') < 0 {
+    fail('mod_remoteip is only available in Apache 2.4')
+  }
+
+  ::apache::mod { 'remoteip': }
+
+  # Template uses:
+  # - $header
+  # - $proxy_ips
+  # - $proxies_header
+  # - $trusted_proxy_ips
+  file { 'remoteip.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/remoteip.conf",
+    content => template('apache/mod/remoteip.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Service['httpd'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/reqtimeout.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+class apache::mod::reqtimeout (
+  $timeouts = ['header=20-40,minrate=500', 'body=10,minrate=500']
+){
+  ::apache::mod { 'reqtimeout': }
+  # Template uses no variables
+  file { 'reqtimeout.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/reqtimeout.conf",
+    content => template('apache/mod/reqtimeout.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/rewrite.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+class apache::mod::rewrite {
+  include ::apache::params
+  ::apache::mod { 'rewrite': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/rpaf.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+class apache::mod::rpaf (
+  $sethostname = true,
+  $proxy_ips   = [ '127.0.0.1' ],
+  $header      = 'X-Forwarded-For'
+) {
+  ::apache::mod { 'rpaf': }
+
+  # Template uses:
+  # - $sethostname
+  # - $proxy_ips
+  # - $header
+  file { 'rpaf.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/rpaf.conf",
+    content => template('apache/mod/rpaf.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/security.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,76 @@
+class apache::mod::security (
+  $crs_package           = $::apache::params::modsec_crs_package,
+  $activated_rules       = $::apache::params::modsec_default_rules,
+  $modsec_dir            = $::apache::params::modsec_dir,
+  $modsec_secruleengine  = $::apache::params::modsec_secruleengine,
+  $allowed_methods       = 'GET HEAD POST OPTIONS',
+  $content_types         = 'application/x-www-form-urlencoded|multipart/form-data|text/xml|application/xml|application/x-amf',
+  $restricted_extensions = '.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .resources/ .resx/ .sql/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/',
+  $restricted_headers    = '/Proxy-Connection/ /Lock-Token/ /Content-Range/ /Translate/ /via/ /if/',
+){
+
+  if $::osfamily == 'FreeBSD' {
+    fail('FreeBSD is not currently supported')
+  }
+
+  ::apache::mod { 'security':
+    id  => 'security2_module',
+    lib => 'mod_security2.so',
+  }
+
+  ::apache::mod { 'unique_id_module':
+    id  => 'unique_id_module',
+    lib => 'mod_unique_id.so',
+  }
+
+  if $crs_package  {
+    package { $crs_package:
+      ensure => 'latest',
+      before => File['security.conf'],
+    }
+  }
+
+  # Template uses:
+  # - $modsec_dir
+  file { 'security.conf':
+    ensure  => file,
+    content => template('apache/mod/security.conf.erb'),
+    path    => "${::apache::mod_dir}/security.conf",
+    owner   => $::apache::params::user,
+    group   => $::apache::params::group,
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+
+  file { $modsec_dir:
+    ensure  => directory,
+    owner   => $::apache::params::user,
+    group   => $::apache::params::group,
+    mode    => '0555',
+    purge   => true,
+    force   => true,
+    recurse => true,
+  }
+
+  file { "${modsec_dir}/activated_rules":
+    ensure  => directory,
+    owner   => $::apache::params::user,
+    group   => $::apache::params::group,
+    mode    => '0555',
+    purge   => true,
+    force   => true,
+    recurse => true,
+    notify  => Class['apache::service'],
+  }
+
+  file { "${modsec_dir}/security_crs.conf":
+    ensure  => file,
+    content => template('apache/mod/security_crs.conf.erb'),
+    require => File[$modsec_dir],
+    notify  => Class['apache::service'],
+  }
+
+  apache::security::rule_link { $activated_rules: }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/setenvif.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+class apache::mod::setenvif {
+  ::apache::mod { 'setenvif': }
+  # Template uses no variables
+  file { 'setenvif.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/setenvif.conf",
+    content => template('apache/mod/setenvif.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/shib.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+class apache::mod::shib (
+  $suppress_warning = false,
+) {
+
+  if $::osfamily == 'RedHat' and ! $suppress_warning {
+    warning('RedHat distributions do not have Apache mod_shib in their default package repositories.')
+  }
+
+  $mod_shib = 'shib2'
+
+  apache::mod {$mod_shib:
+    id => 'mod_shib',
+  }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/speling.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::speling {
+  ::apache::mod { 'speling': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/ssl.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,81 @@
+class apache::mod::ssl (
+  $ssl_compression         = false,
+  $ssl_cryptodevice        = 'builtin',
+  $ssl_options             = [ 'StdEnvVars' ],
+  $ssl_openssl_conf_cmd    = undef,
+  $ssl_cipher              = 'HIGH:MEDIUM:!aNULL:!MD5:!RC4',
+  $ssl_honorcipherorder    = 'On',
+  $ssl_protocol            = [ 'all', '-SSLv2', '-SSLv3' ],
+  $ssl_pass_phrase_dialog  = 'builtin',
+  $ssl_random_seed_bytes   = '512',
+  $ssl_sessioncachetimeout = '300',
+  $apache_version          = $::apache::apache_version,
+  $package_name            = undef,
+) {
+
+  case $::osfamily {
+    'debian': {
+      if versioncmp($apache_version, '2.4') >= 0 {
+        $ssl_mutex = 'default'
+      } elsif $::operatingsystem == 'Ubuntu' and $::operatingsystemrelease == '10.04' {
+        $ssl_mutex = 'file:/var/run/apache2/ssl_mutex'
+      } else {
+        $ssl_mutex = "file:\${APACHE_RUN_DIR}/ssl_mutex"
+      }
+    }
+    'redhat': {
+      $ssl_mutex = 'default'
+    }
+    'freebsd': {
+      $ssl_mutex = 'default'
+    }
+    'gentoo': {
+      $ssl_mutex = 'default'
+    }
+    'Suse': {
+      $ssl_mutex = 'default'
+    }
+    default: {
+      fail("Unsupported osfamily ${::osfamily}")
+    }
+  }
+
+  $session_cache = $::osfamily ? {
+    'debian'  => "\${APACHE_RUN_DIR}/ssl_scache(512000)",
+    'redhat'  => '/var/cache/mod_ssl/scache(512000)',
+    'freebsd' => '/var/run/ssl_scache(512000)',
+    'gentoo'  => '/var/run/ssl_scache(512000)',
+    'Suse'    => '/var/lib/apache2/ssl_scache(512000)'
+  }
+
+  ::apache::mod { 'ssl':
+    package => $package_name,
+  }
+
+  if versioncmp($apache_version, '2.4') >= 0 {
+    ::apache::mod { 'socache_shmcb': }
+  }
+
+  # Template uses
+  #
+  # $ssl_compression
+  # $ssl_cryptodevice
+  # $ssl_cipher
+  # $ssl_honorcipherorder
+  # $ssl_options
+  # $ssl_openssl_conf_cmd
+  # $session_cache
+  # $ssl_mutex
+  # $ssl_random_seed_bytes
+  # $ssl_sessioncachetimeout
+  # $apache_version
+  #
+  file { 'ssl.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/ssl.conf",
+    content => template('apache/mod/ssl.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/status.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+# Class: apache::mod::status
+#
+# This class enables and configures Apache mod_status
+# See: http://httpd.apache.org/docs/current/mod/mod_status.html
+#
+# Parameters:
+# - $allow_from is an array of hosts, ip addresses, partial network numbers
+#   or networks in CIDR notation specifying what hosts can view the special
+#   /server-status URL.  Defaults to ['127.0.0.1', '::1'].
+# - $extended_status track and display extended status information. Valid
+#   values are 'On' or 'Off'.  Defaults to 'On'.
+# - $status_path is the path assigned to the Location directive which
+#   defines the URL to access the server status. Defaults to '/server-status'.
+# 
+# Actions:
+# - Enable and configure Apache mod_status
+#
+# Requires:
+# - The apache class
+#
+# Sample Usage:
+#
+#  # Simple usage allowing access from localhost and a private subnet
+#  class { 'apache::mod::status':
+#    $allow_from => ['127.0.0.1', '10.10.10.10/24'],
+#  }
+#
+class apache::mod::status (
+  $allow_from      = ['127.0.0.1','::1'],
+  $extended_status = 'On',
+  $apache_version = $::apache::apache_version,
+  $status_path     = '/server-status',
+){
+  validate_array($allow_from)
+  validate_re(downcase($extended_status), '^(on|off)$', "${extended_status} is not supported for extended_status.  Allowed values are 'On' and 'Off'.")
+  ::apache::mod { 'status': }
+  # Template uses $allow_from, $extended_status, $apache_version, $status_path
+  file { 'status.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/status.conf",
+    content => template('apache/mod/status.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/suexec.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::suexec {
+  ::apache::mod { 'suexec': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/suphp.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+class apache::mod::suphp (
+){
+  ::apache::mod { 'suphp': }
+
+  file {'suphp.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/suphp.conf",
+    content => template('apache/mod/suphp.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/userdir.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+class apache::mod::userdir (
+  $home = '/home',
+  $dir = 'public_html',
+  $disable_root = true,
+  $apache_version = $::apache::apache_version,
+  $options = [ 'MultiViews', 'Indexes', 'SymLinksIfOwnerMatch', 'IncludesNoExec' ],
+) {
+  ::apache::mod { 'userdir': }
+
+  # Template uses $home, $dir, $disable_root, $apache_version
+  file { 'userdir.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/userdir.conf",
+    content => template('apache/mod/userdir.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/version.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+class apache::mod::version(
+  $apache_version = $::apache::apache_version
+) {
+
+  if ($::osfamily == 'debian' and versioncmp($apache_version, '2.4') >= 0) {
+    warning("${module_name}: module version_module is built-in and can't be loaded")
+  } else {
+    ::apache::mod { 'version': }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/vhost_alias.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class apache::mod::vhost_alias {
+  ::apache::mod { 'vhost_alias': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/worker.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,135 @@
+# == Class: apache::mod::worker
+#
+#
+# === Parameters
+#
+#  [*startservers*]
+#   (optional) The number of child server processes created on startup
+#   Defaults is '2'
+#
+#  [*maxclients*]
+#   (optional) The max number of simultaneous requests that will be served.
+#   This is the old name and is still supported. The new name is
+#   MaxRequestWorkers as of 2.3.13.
+#   Default is '150'
+#
+#  [*minsparethreads*]
+#   (optional) Minimum number of idle threads to handle request spikes.
+#   Default is '25'
+#
+#  [*maxsparethreads*]
+#   (optional) Maximum number of idle threads.
+#   Default is '75'
+#
+#  [*threadsperchild*]
+#   (optional) The number of threads created by each child process.
+#   Default is '25'
+#
+#  [*maxrequestsperchild*]
+#   (optional) Limit on the number of connectiojns an individual child server
+#   process will handle. This is the old name and is still supported. The new
+#   name is MaxConnectionsPerChild as of 2.3.9+.
+#   Default is '0'
+#
+#  [*serverlimit*]
+#   (optional) With worker, use this directive only if your MaxRequestWorkers
+#   and ThreadsPerChild settings require more than 16 server processes
+#   (default). Do not set the value of this directive any higher than the
+#   number of server processes required by what you may want for
+#   MaxRequestWorkers and ThreadsPerChild.
+#   Default is '25'
+#
+#  [*threadlimit*]
+#   (optional) This directive sets the maximum configured value for
+#   ThreadsPerChild for the lifetime of the Apache httpd process.
+#   Default is '64'
+#
+#  [*listenbacklog*]
+#    (optional) Maximum length of the queue of pending connections.
+#    Defaults is '511'
+#
+#  [*apache_version*]
+#   (optional)
+#   Default is $::apache::apache_version
+#
+class apache::mod::worker (
+  $startservers        = '2',
+  $maxclients          = '150',
+  $minsparethreads     = '25',
+  $maxsparethreads     = '75',
+  $threadsperchild     = '25',
+  $maxrequestsperchild = '0',
+  $serverlimit         = '25',
+  $threadlimit         = '64',
+  $listenbacklog       = '511',
+  $apache_version      = $::apache::apache_version,
+) {
+  if defined(Class['apache::mod::event']) {
+    fail('May not include both apache::mod::worker and apache::mod::event on the same node')
+  }
+  if defined(Class['apache::mod::itk']) {
+    fail('May not include both apache::mod::worker and apache::mod::itk on the same node')
+  }
+  if defined(Class['apache::mod::peruser']) {
+    fail('May not include both apache::mod::worker and apache::mod::peruser on the same node')
+  }
+  if defined(Class['apache::mod::prefork']) {
+    fail('May not include both apache::mod::worker and apache::mod::prefork on the same node')
+  }
+  File {
+    owner => 'root',
+    group => $::apache::params::root_group,
+    mode  => '0644',
+  }
+
+  # Template uses:
+  # - $startservers
+  # - $maxclients
+  # - $minsparethreads
+  # - $maxsparethreads
+  # - $threadsperchild
+  # - $maxrequestsperchild
+  # - $serverlimit
+  # - $threadLimit
+  # - $listenbacklog
+  file { "${::apache::mod_dir}/worker.conf":
+    ensure  => file,
+    content => template('apache/mod/worker.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+
+  case $::osfamily {
+    'redhat': {
+      if versioncmp($apache_version, '2.4') >= 0 {
+        ::apache::mpm{ 'worker':
+          apache_version => $apache_version,
+        }
+      }
+      else {
+        file_line { '/etc/sysconfig/httpd worker enable':
+          ensure  => present,
+          path    => '/etc/sysconfig/httpd',
+          line    => 'HTTPD=/usr/sbin/httpd.worker',
+          match   => '#?HTTPD=/usr/sbin/httpd.worker',
+          require => Package['httpd'],
+          notify  => Class['apache::service'],
+        }
+      }
+    }
+    'debian', 'freebsd', 'Suse': {
+      ::apache::mpm{ 'worker':
+        apache_version => $apache_version,
+      }
+    }
+    'gentoo': {
+      ::portage::makeconf { 'apache2_mpms':
+        content => 'worker',
+      }
+    }
+    default: {
+      fail("Unsupported osfamily ${::osfamily}")
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/wsgi.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,41 @@
+class apache::mod::wsgi (
+  $wsgi_socket_prefix = $::apache::params::wsgi_socket_prefix,
+  $wsgi_python_path   = undef,
+  $wsgi_python_home   = undef,
+  $package_name       = undef,
+  $mod_path           = undef,
+){
+
+  if ($package_name != undef and $mod_path == undef) or ($package_name == undef and $mod_path != undef) {
+    fail('apache::mod::wsgi - both package_name and mod_path must be specified!')
+  }
+
+  if $package_name != undef {
+    if $mod_path =~ /\// {
+      $_mod_path = $mod_path
+    } else {
+      $_mod_path = "${::apache::lib_path}/${mod_path}"
+    }
+    ::apache::mod { 'wsgi':
+      package => $package_name,
+      path    => $_mod_path,
+    }
+  }
+  else {
+    ::apache::mod { 'wsgi': }
+  }
+
+  # Template uses:
+  # - $wsgi_socket_prefix
+  # - $wsgi_python_path
+  # - $wsgi_python_home
+  file {'wsgi.conf':
+    ensure  => file,
+    path    => "${::apache::mod_dir}/wsgi.conf",
+    content => template('apache/mod/wsgi.conf.erb'),
+    require => Exec["mkdir ${::apache::mod_dir}"],
+    before  => File[$::apache::mod_dir],
+    notify  => Class['apache::service'],
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mod/xsendfile.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+class apache::mod::xsendfile {
+  include ::apache::params
+  ::apache::mod { 'xsendfile': }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/mpm.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,107 @@
+define apache::mpm (
+  $lib_path       = $::apache::lib_path,
+  $apache_version = $::apache::apache_version,
+) {
+  if ! defined(Class['apache']) {
+    fail('You must include the apache base class before using any apache defined resources')
+  }
+
+  $mpm     = $name
+  $mod_dir = $::apache::mod_dir
+
+  $_lib  = "mod_mpm_${mpm}.so"
+  $_path = "${lib_path}/${_lib}"
+  $_id   = "mpm_${mpm}_module"
+
+  if versioncmp($apache_version, '2.4') >= 0 {
+    file { "${mod_dir}/${mpm}.load":
+      ensure  => file,
+      path    => "${mod_dir}/${mpm}.load",
+      content => "LoadModule ${_id} ${_path}\n",
+      require => [
+        Package['httpd'],
+        Exec["mkdir ${mod_dir}"],
+      ],
+      before  => File[$mod_dir],
+      notify  => Class['apache::service'],
+    }
+  }
+
+  case $::osfamily {
+    'debian': {
+      file { "${::apache::mod_enable_dir}/${mpm}.conf":
+        ensure  => link,
+        target  => "${::apache::mod_dir}/${mpm}.conf",
+        require => Exec["mkdir ${::apache::mod_enable_dir}"],
+        before  => File[$::apache::mod_enable_dir],
+        notify  => Class['apache::service'],
+      }
+
+      if versioncmp($apache_version, '2.4') >= 0 {
+        file { "${::apache::mod_enable_dir}/${mpm}.load":
+          ensure  => link,
+          target  => "${::apache::mod_dir}/${mpm}.load",
+          require => Exec["mkdir ${::apache::mod_enable_dir}"],
+          before  => File[$::apache::mod_enable_dir],
+          notify  => Class['apache::service'],
+        }
+
+        if $mpm == 'itk' {
+            file { "${lib_path}/mod_mpm_itk.so":
+              ensure => link,
+              target => "${lib_path}/mpm_itk.so"
+            }
+        }
+      }
+
+      if versioncmp($apache_version, '2.4') < 0 {
+        package { "apache2-mpm-${mpm}":
+          ensure => present,
+        }
+      }
+    }
+    'freebsd': {
+      class { '::apache::package':
+        mpm_module => $mpm
+      }
+    }
+    'redhat': {
+      # so we don't fail
+    }
+    'Suse': {
+      file { "${::apache::mod_enable_dir}/${mpm}.conf":
+        ensure  => link,
+        target  => "${::apache::mod_dir}/${mpm}.conf",
+        require => Exec["mkdir ${::apache::mod_enable_dir}"],
+        before  => File[$::apache::mod_enable_dir],
+        notify  => Class['apache::service'],
+      }
+
+      if versioncmp($apache_version, '2.4') >= 0 {
+        file { "${::apache::mod_enable_dir}/${mpm}.load":
+          ensure  => link,
+          target  => "${::apache::mod_dir}/${mpm}.load",
+          require => Exec["mkdir ${::apache::mod_enable_dir}"],
+          before  => File[$::apache::mod_enable_dir],
+          notify  => Class['apache::service'],
+        }
+
+        if $mpm == 'itk' {
+            file { "${lib_path}/mod_mpm_itk.so":
+              ensure => link,
+              target => "${lib_path}/mpm_itk.so"
+            }
+        }
+      }
+
+      if versioncmp($apache_version, '2.4') < 0 {
+        package { "apache2-${mpm}":
+          ensure => present,
+        }
+      }
+    }
+    default: {
+      fail("Unsupported osfamily ${::osfamily}")
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/namevirtualhost.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+define apache::namevirtualhost {
+  $addr_port = $name
+
+  # Template uses: $addr_port
+  concat::fragment { "NameVirtualHost ${addr_port}":
+    ensure  => present,
+    target  => $::apache::ports_file,
+    content => template('apache/namevirtualhost.erb'),
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/package.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,65 @@
+class apache::package (
+  $ensure     = 'present',
+  $mpm_module = $::apache::params::mpm_module,
+) inherits ::apache::params {
+
+  # The base class must be included first because it is used by parameter defaults
+  if ! defined(Class['apache']) {
+    fail('You must include the apache base class before using any apache defined resources')
+  }
+
+  case $::osfamily {
+    'FreeBSD': {
+      case $mpm_module {
+        'prefork': {
+          $set = 'MPM_PREFORK'
+          $unset = 'MPM_WORKER MPM_EVENT'
+        }
+        'worker': {
+          $set = 'MPM_WORKER'
+          $unset = 'MPM_PREFORK MPM_EVENT'
+        }
+        'event': {
+          $set = 'MPM_EVENT'
+          $unset = 'MPM_PREFORK MPM_WORKER'
+        }
+        'itk': {
+          $set = undef
+          $unset = undef
+          package { 'www/mod_mpm_itk':
+            ensure => installed,
+          }
+        }
+        default: { fail("MPM module ${mpm_module} not supported on FreeBSD") }
+      }
+
+      # Configure ports to have apache build options set correctly
+      if $set {
+        file_line { 'apache SET options in /etc/make.conf':
+          ensure => $ensure,
+          path   => '/etc/make.conf',
+          line   => "apache24_SET_FORCE=${set}",
+          match  => '^apache24_SET_FORCE=.*',
+          before => Package['httpd'],
+        }
+        file_line { 'apache UNSET options in /etc/make.conf':
+          ensure => $ensure,
+          path   => '/etc/make.conf',
+          line   => "apache24_UNSET_FORCE=${unset}",
+          match  => '^apache24_UNSET_FORCE=.*',
+          before => Package['httpd'],
+        }
+      }
+      $apache_package = $::apache::apache_name
+    }
+    default: {
+      $apache_package = $::apache::apache_name
+    }
+  }
+
+  package { 'httpd':
+    ensure => $ensure,
+    name   => $apache_package,
+    notify => Class['Apache::Service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/params.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,518 @@
+# Class: apache::params
+#
+# This class manages Apache parameters
+#
+# Parameters:
+# - The $user that Apache runs as
+# - The $group that Apache runs as
+# - The $apache_name is the name of the package and service on the relevant
+#   distribution
+# - The $php_package is the name of the package that provided PHP
+# - The $ssl_package is the name of the Apache SSL package
+# - The $apache_dev is the name of the Apache development libraries package
+# - The $conf_contents is the contents of the Apache configuration file
+#
+# Actions:
+#
+# Requires:
+#
+# Sample Usage:
+#
+class apache::params inherits ::apache::version {
+  if($::fqdn) {
+    $servername = $::fqdn
+  } else {
+    $servername = $::hostname
+  }
+
+  # The default error log level
+  $log_level = 'warn'
+  $use_optional_includes = false
+
+  # should we use systemd module?
+  $use_systemd = true
+
+  $vhost_include_pattern = '*'
+
+  if $::operatingsystem == 'Ubuntu' and $::lsbdistrelease == '10.04' {
+    $verify_command = '/usr/sbin/apache2ctl -t'
+  } else {
+    $verify_command = '/usr/sbin/apachectl -t'
+  }
+  if $::osfamily == 'RedHat' or $::operatingsystem == 'amazon' {
+    $user                 = 'apache'
+    $group                = 'apache'
+    $root_group           = 'root'
+    $apache_name          = 'httpd'
+    $service_name         = 'httpd'
+    $httpd_dir            = '/etc/httpd'
+    $server_root          = '/etc/httpd'
+    $conf_dir             = "${httpd_dir}/conf"
+    $confd_dir            = "${httpd_dir}/conf.d"
+    $mod_dir              = "${httpd_dir}/conf.d"
+    $mod_enable_dir       = undef
+    $vhost_dir            = "${httpd_dir}/conf.d"
+    $vhost_enable_dir     = undef
+    $conf_file            = 'httpd.conf'
+    $ports_file           = "${conf_dir}/ports.conf"
+    $pidfile              = 'run/httpd.pid'
+    $logroot              = '/var/log/httpd'
+    $logroot_mode         = undef
+    $lib_path             = 'modules'
+    $mpm_module           = 'prefork'
+    $dev_packages         = 'httpd-devel'
+    $default_ssl_cert     = '/etc/pki/tls/certs/localhost.crt'
+    $default_ssl_key      = '/etc/pki/tls/private/localhost.key'
+    $ssl_certs_dir        = '/etc/pki/tls/certs'
+    $passenger_conf_file  = 'passenger_extra.conf'
+    $passenger_conf_package_file = 'passenger.conf'
+    $passenger_root       = undef
+    $passenger_ruby       = undef
+    $passenger_default_ruby = undef
+    $suphp_addhandler     = 'php5-script'
+    $suphp_engine         = 'off'
+    $suphp_configpath     = undef
+    # NOTE: The module for Shibboleth is not available to RH/CentOS without an additional repository. http://wiki.aaf.edu.au/tech-info/sp-install-guide
+    # NOTE: The auth_cas module isn't available to RH/CentOS without enabling EPEL.
+    $mod_packages         = {
+      'auth_cas'    => 'mod_auth_cas',
+      'auth_kerb'   => 'mod_auth_kerb',
+      'auth_mellon' => 'mod_auth_mellon',
+      'authnz_ldap' => $::apache::version::distrelease ? {
+        '7'     => 'mod_ldap',
+        default => 'mod_authz_ldap',
+      },
+      'fastcgi'     => 'mod_fastcgi',
+      'fcgid'       => 'mod_fcgid',
+      'geoip'       => 'mod_geoip',
+      'ldap'        => $::apache::version::distrelease ? {
+        '7'     => 'mod_ldap',
+        default => undef,
+      },
+      'pagespeed'   => 'mod-pagespeed-stable',
+      'passenger'   => 'mod_passenger',
+      'perl'        => 'mod_perl',
+      'php5'        => $::apache::version::distrelease ? {
+        '5'     => 'php53',
+        default => 'php',
+      },
+      'proxy_html'  => 'mod_proxy_html',
+      'python'      => 'mod_python',
+      'security'    => 'mod_security',
+      'shibboleth'  => 'shibboleth',
+      'ssl'         => 'mod_ssl',
+      'wsgi'        => 'mod_wsgi',
+      'dav_svn'     => 'mod_dav_svn',
+      'suphp'       => 'mod_suphp',
+      'xsendfile'   => 'mod_xsendfile',
+      'nss'         => 'mod_nss',
+      'shib2'       => 'shibboleth',
+    }
+    $mod_libs             = {
+      'php5' => 'libphp5.so',
+      'nss'  => 'libmodnss.so',
+    }
+    $conf_template        = 'apache/httpd.conf.erb'
+    $keepalive            = 'Off'
+    $keepalive_timeout    = 15
+    $max_keepalive_requests = 100
+    $fastcgi_lib_path     = undef
+    $mime_support_package = 'mailcap'
+    $mime_types_config    = '/etc/mime.types'
+    $docroot              = '/var/www/html'
+    $alias_icons_path     = $::apache::version::distrelease ? {
+      '7'     => '/usr/share/httpd/icons',
+      default => '/var/www/icons',
+    }
+    $error_documents_path = $::apache::version::distrelease ? {
+      '7'     => '/usr/share/httpd/error',
+      default => '/var/www/error'
+    }
+    if $::osfamily == 'RedHat' {
+      $wsgi_socket_prefix = '/var/run/wsgi'
+    } else {
+      $wsgi_socket_prefix = undef
+    }
+    $cas_cookie_path      = '/var/cache/mod_auth_cas/'
+    $mellon_lock_file     = '/run/mod_auth_mellon/lock'
+    $mellon_cache_size    = 100
+    $mellon_post_directory = undef
+    $modsec_crs_package   = 'mod_security_crs'
+    $modsec_crs_path      = '/usr/lib/modsecurity.d'
+    $modsec_dir           = '/etc/httpd/modsecurity.d'
+    $modsec_secruleengine = 'On'
+    $modsec_default_rules = [
+      'base_rules/modsecurity_35_bad_robots.data',
+      'base_rules/modsecurity_35_scanners.data',
+      'base_rules/modsecurity_40_generic_attacks.data',
+      'base_rules/modsecurity_41_sql_injection_attacks.data',
+      'base_rules/modsecurity_50_outbound.data',
+      'base_rules/modsecurity_50_outbound_malware.data',
+      'base_rules/modsecurity_crs_20_protocol_violations.conf',
+      'base_rules/modsecurity_crs_21_protocol_anomalies.conf',
+      'base_rules/modsecurity_crs_23_request_limits.conf',
+      'base_rules/modsecurity_crs_30_http_policy.conf',
+      'base_rules/modsecurity_crs_35_bad_robots.conf',
+      'base_rules/modsecurity_crs_40_generic_attacks.conf',
+      'base_rules/modsecurity_crs_41_sql_injection_attacks.conf',
+      'base_rules/modsecurity_crs_41_xss_attacks.conf',
+      'base_rules/modsecurity_crs_42_tight_security.conf',
+      'base_rules/modsecurity_crs_45_trojans.conf',
+      'base_rules/modsecurity_crs_47_common_exceptions.conf',
+      'base_rules/modsecurity_crs_49_inbound_blocking.conf',
+      'base_rules/modsecurity_crs_50_outbound.conf',
+      'base_rules/modsecurity_crs_59_outbound_blocking.conf',
+      'base_rules/modsecurity_crs_60_correlation.conf'
+    ]
+  } elsif $::osfamily == 'Debian' {
+    $user                = 'www-data'
+    $group               = 'www-data'
+    $root_group          = 'root'
+    $apache_name         = 'apache2'
+    $service_name        = 'apache2'
+    $httpd_dir           = '/etc/apache2'
+    $server_root         = '/etc/apache2'
+    $conf_dir            = $httpd_dir
+    $confd_dir           = "${httpd_dir}/conf.d"
+    $mod_dir             = "${httpd_dir}/mods-available"
+    $mod_enable_dir      = "${httpd_dir}/mods-enabled"
+    $vhost_dir           = "${httpd_dir}/sites-available"
+    $vhost_enable_dir    = "${httpd_dir}/sites-enabled"
+    $conf_file           = 'apache2.conf'
+    $ports_file          = "${conf_dir}/ports.conf"
+    $pidfile             = "\${APACHE_PID_FILE}"
+    $logroot             = '/var/log/apache2'
+    $logroot_mode        = undef
+    $lib_path            = '/usr/lib/apache2/modules'
+    $mpm_module          = 'worker'
+    $default_ssl_cert    = '/etc/ssl/certs/ssl-cert-snakeoil.pem'
+    $default_ssl_key     = '/etc/ssl/private/ssl-cert-snakeoil.key'
+    $ssl_certs_dir       = '/etc/ssl/certs'
+    $suphp_addhandler    = 'x-httpd-php'
+    $suphp_engine        = 'off'
+    $suphp_configpath    = '/etc/php5/apache2'
+    $mod_packages        = {
+      'auth_cas'    => 'libapache2-mod-auth-cas',
+      'auth_kerb'   => 'libapache2-mod-auth-kerb',
+      'auth_mellon' => 'libapache2-mod-auth-mellon',
+      'dav_svn'     => 'libapache2-svn',
+      'fastcgi'     => 'libapache2-mod-fastcgi',
+      'fcgid'       => 'libapache2-mod-fcgid',
+      'geoip'       => 'libapache2-mod-geoip',
+      'nss'         => 'libapache2-mod-nss',
+      'pagespeed'   => 'mod-pagespeed-stable',
+      'passenger'   => 'libapache2-mod-passenger',
+      'perl'        => 'libapache2-mod-perl2',
+      'php5'        => 'libapache2-mod-php5',
+      'proxy_html'  => 'libapache2-mod-proxy-html',
+      'python'      => 'libapache2-mod-python',
+      'rpaf'        => 'libapache2-mod-rpaf',
+      'security'    => 'libapache2-modsecurity',
+      'suphp'       => 'libapache2-mod-suphp',
+      'wsgi'        => 'libapache2-mod-wsgi',
+      'xsendfile'   => 'libapache2-mod-xsendfile',
+      'shib2'       => 'libapache2-mod-shib2',
+    }
+    $mod_libs             = {
+      'php5' => 'libphp5.so',
+    }
+    $conf_template          = 'apache/httpd.conf.erb'
+    $keepalive              = 'Off'
+    $keepalive_timeout      = 15
+    $max_keepalive_requests = 100
+    $fastcgi_lib_path       = '/var/lib/apache2/fastcgi'
+    $mime_support_package = 'mime-support'
+    $mime_types_config    = '/etc/mime.types'
+    if ($::operatingsystem == 'Ubuntu' and versioncmp($::operatingsystemrelease, '13.10') >= 0) or ($::operatingsystem == 'Debian' and versioncmp($::operatingsystemrelease, '8') >= 0) {
+      $docroot              = '/var/www/html'
+    } else {
+      $docroot              = '/var/www'
+    }
+    $cas_cookie_path      = '/var/cache/apache2/mod_auth_cas/'
+    $mellon_lock_file     = undef
+    $mellon_cache_size    = undef
+    $mellon_post_directory = '/var/cache/apache2/mod_auth_mellon/'
+    $modsec_crs_package   = 'modsecurity-crs'
+    $modsec_crs_path      = '/usr/share/modsecurity-crs'
+    $modsec_dir           = '/etc/modsecurity'
+    $modsec_secruleengine = 'On'
+    $modsec_default_rules = [
+      'base_rules/modsecurity_35_bad_robots.data',
+      'base_rules/modsecurity_35_scanners.data',
+      'base_rules/modsecurity_40_generic_attacks.data',
+      'base_rules/modsecurity_41_sql_injection_attacks.data',
+      'base_rules/modsecurity_50_outbound.data',
+      'base_rules/modsecurity_50_outbound_malware.data',
+      'base_rules/modsecurity_crs_20_protocol_violations.conf',
+      'base_rules/modsecurity_crs_21_protocol_anomalies.conf',
+      'base_rules/modsecurity_crs_23_request_limits.conf',
+      'base_rules/modsecurity_crs_30_http_policy.conf',
+      'base_rules/modsecurity_crs_35_bad_robots.conf',
+      'base_rules/modsecurity_crs_40_generic_attacks.conf',
+      'base_rules/modsecurity_crs_41_sql_injection_attacks.conf',
+      'base_rules/modsecurity_crs_41_xss_attacks.conf',
+      'base_rules/modsecurity_crs_42_tight_security.conf',
+      'base_rules/modsecurity_crs_45_trojans.conf',
+      'base_rules/modsecurity_crs_47_common_exceptions.conf',
+      'base_rules/modsecurity_crs_49_inbound_blocking.conf',
+      'base_rules/modsecurity_crs_50_outbound.conf',
+      'base_rules/modsecurity_crs_59_outbound_blocking.conf',
+      'base_rules/modsecurity_crs_60_correlation.conf'
+    ]
+    $alias_icons_path     = '/usr/share/apache2/icons'
+    $error_documents_path = '/usr/share/apache2/error'
+    if ($::operatingsystem == 'Ubuntu' and versioncmp($::operatingsystemrelease, '13.10') >= 0) or ($::operatingsystem == 'Debian' and versioncmp($::operatingsystemrelease, '8') >= 0) {
+      $dev_packages        = ['libaprutil1-dev', 'libapr1-dev', 'apache2-dev']
+    } else {
+      $dev_packages        = ['libaprutil1-dev', 'libapr1-dev', 'apache2-prefork-dev']
+    }
+
+    #
+    # Passenger-specific settings
+    #
+
+    $passenger_conf_file         = 'passenger.conf'
+    $passenger_conf_package_file = undef
+
+    case $::operatingsystem {
+      'Ubuntu': {
+        case $::lsbdistrelease {
+          '12.04': {
+            $passenger_root         = '/usr'
+            $passenger_ruby         = '/usr/bin/ruby'
+            $passenger_default_ruby = undef
+          }
+          '14.04': {
+            $passenger_root         = '/usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini'
+            $passenger_ruby         = undef
+            $passenger_default_ruby = '/usr/bin/ruby'
+          }
+          default: {
+            # The following settings may or may not work on Ubuntu releases not
+            # supported by this module.
+            $passenger_root         = '/usr'
+            $passenger_ruby         = '/usr/bin/ruby'
+            $passenger_default_ruby = undef
+          }
+        }
+      }
+      'Debian': {
+        case $::lsbdistcodename {
+          'wheezy': {
+            $passenger_root         = '/usr'
+            $passenger_ruby         = '/usr/bin/ruby'
+            $passenger_default_ruby = undef
+          }
+          'jessie': {
+            $passenger_root         = '/usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini'
+            $passenger_ruby         = undef
+            $passenger_default_ruby = '/usr/bin/ruby'
+          }
+          default: {
+            # The following settings may or may not work on Debian releases not
+            # supported by this module.
+            $passenger_root         = '/usr'
+            $passenger_ruby         = '/usr/bin/ruby'
+            $passenger_default_ruby = undef
+          }
+        }
+      }
+    }
+    $wsgi_socket_prefix = undef
+  } elsif $::osfamily == 'FreeBSD' {
+    $user             = 'www'
+    $group            = 'www'
+    $root_group       = 'wheel'
+    $apache_name      = 'apache24'
+    $service_name     = 'apache24'
+    $httpd_dir        = '/usr/local/etc/apache24'
+    $server_root      = '/usr/local'
+    $conf_dir         = $httpd_dir
+    $confd_dir        = "${httpd_dir}/Includes"
+    $mod_dir          = "${httpd_dir}/Modules"
+    $mod_enable_dir   = undef
+    $vhost_dir        = "${httpd_dir}/Vhosts"
+    $vhost_enable_dir = undef
+    $conf_file        = 'httpd.conf'
+    $ports_file       = "${conf_dir}/ports.conf"
+    $pidfile          = '/var/run/httpd.pid'
+    $logroot          = '/var/log/apache24'
+    $logroot_mode     = undef
+    $lib_path         = '/usr/local/libexec/apache24'
+    $mpm_module       = 'prefork'
+    $dev_packages     = undef
+    $default_ssl_cert = '/usr/local/etc/apache24/server.crt'
+    $default_ssl_key  = '/usr/local/etc/apache24/server.key'
+    $ssl_certs_dir    = '/usr/local/etc/apache24'
+    $passenger_conf_file = 'passenger.conf'
+    $passenger_conf_package_file = undef
+    $passenger_root   = '/usr/local/lib/ruby/gems/2.0/gems/passenger-4.0.58'
+    $passenger_ruby   = '/usr/local/bin/ruby'
+    $passenger_default_ruby = undef
+    $suphp_addhandler = 'php5-script'
+    $suphp_engine     = 'off'
+    $suphp_configpath = undef
+    $mod_packages     = {
+      # NOTE: I list here only modules that are not included in www/apache24
+      # NOTE: 'passenger' needs to enable APACHE_SUPPORT in make config
+      # NOTE: 'php' needs to enable APACHE option in make config
+      # NOTE: 'dav_svn' needs to enable MOD_DAV_SVN make config
+      # NOTE: not sure where the shibboleth should come from
+      'auth_kerb'  => 'www/mod_auth_kerb2',
+      'fcgid'      => 'www/mod_fcgid',
+      'passenger'  => 'www/rubygem-passenger',
+      'perl'       => 'www/mod_perl2',
+      'php5'       => 'www/mod_php5',
+      'proxy_html' => 'www/mod_proxy_html',
+      'python'     => 'www/mod_python3',
+      'wsgi'       => 'www/mod_wsgi',
+      'dav_svn'    => 'devel/subversion',
+      'xsendfile'  => 'www/mod_xsendfile',
+      'rpaf'       => 'www/mod_rpaf2',
+      'shib2'      => 'security/shibboleth2-sp',
+    }
+    $mod_libs         = {
+      'php5' => 'libphp5.so',
+    }
+    $conf_template        = 'apache/httpd.conf.erb'
+    $keepalive            = 'Off'
+    $keepalive_timeout    = 15
+    $max_keepalive_requests = 100
+    $fastcgi_lib_path     = undef # TODO: revisit
+    $mime_support_package = 'misc/mime-support'
+    $mime_types_config    = '/usr/local/etc/mime.types'
+    $wsgi_socket_prefix   = undef
+    $docroot              = '/usr/local/www/apache24/data'
+    $alias_icons_path     = '/usr/local/www/apache24/icons'
+    $error_documents_path = '/usr/local/www/apache24/error'
+  } elsif $::osfamily == 'Gentoo' {
+    $user             = 'apache'
+    $group            = 'apache'
+    $root_group       = 'wheel'
+    $apache_name      = 'www-servers/apache'
+    $service_name     = 'apache2'
+    $httpd_dir        = '/etc/apache2'
+    $server_root      = '/var/www'
+    $conf_dir         = $httpd_dir
+    $confd_dir        = "${httpd_dir}/conf.d"
+    $mod_dir          = "${httpd_dir}/modules.d"
+    $mod_enable_dir   = undef
+    $vhost_dir        = "${httpd_dir}/vhosts.d"
+    $vhost_enable_dir = undef
+    $conf_file        = 'httpd.conf'
+    $ports_file       = "${conf_dir}/ports.conf"
+    $logroot          = '/var/log/apache2'
+    $logroot_mode     = undef
+    $lib_path         = '/usr/lib/apache2/modules'
+    $mpm_module       = 'prefork'
+    $dev_packages     = undef
+    $default_ssl_cert = '/etc/ssl/apache2/server.crt'
+    $default_ssl_key  = '/etc/ssl/apache2/server.key'
+    $ssl_certs_dir    = '/etc/ssl/apache2'
+    $passenger_root   = '/usr'
+    $passenger_ruby   = '/usr/bin/ruby'
+    $passenger_conf_file = 'passenger.conf'
+    $passenger_conf_package_file = undef
+    $passenger_default_ruby = undef
+    $suphp_addhandler = 'x-httpd-php'
+    $suphp_engine     = 'off'
+    $suphp_configpath = '/etc/php5/apache2'
+    $mod_packages     = {
+      # NOTE: I list here only modules that are not included in www-servers/apache
+      'auth_kerb'  => 'www-apache/mod_auth_kerb',
+      'fcgid'      => 'www-apache/mod_fcgid',
+      'passenger'  => 'www-apache/passenger',
+      'perl'       => 'www-apache/mod_perl',
+      'php5'       => 'dev-lang/php',
+      'proxy_html' => 'www-apache/mod_proxy_html',
+      'proxy_fcgi' => 'www-apache/mod_proxy_fcgi',
+      'python'     => 'www-apache/mod_python',
+      'wsgi'       => 'www-apache/mod_wsgi',
+      'dav_svn'    => 'dev-vcs/subversion',
+      'xsendfile'  => 'www-apache/mod_xsendfile',
+      'rpaf'       => 'www-apache/mod_rpaf',
+      'xml2enc'    => 'www-apache/mod_xml2enc',
+    }
+    $mod_libs         = {
+      'php5' => 'libphp5.so',
+    }
+    $conf_template        = 'apache/httpd.conf.erb'
+    $keepalive            = 'Off'
+    $keepalive_timeout    = 15
+    $max_keepalive_requests = 100
+    $fastcgi_lib_path     = undef # TODO: revisit
+    $mime_support_package = 'app-misc/mime-types'
+    $mime_types_config    = '/etc/mime.types'
+    $wsgi_socket_prefix   = undef
+    $docroot              = '/var/www/localhost/htdocs'
+    $alias_icons_path     = '/usr/share/apache2/icons'
+    $error_documents_path = '/usr/share/apache2/error'
+  } elsif $::osfamily == 'Suse' {
+    $user                = 'wwwrun'
+    $group               = 'wwwrun'
+    $root_group          = 'root'
+    $apache_name         = 'apache2'
+    $service_name        = 'apache2'
+    $httpd_dir           = '/etc/apache2'
+    $server_root         = '/etc/apache2'
+    $conf_dir            = $httpd_dir
+    $confd_dir           = "${httpd_dir}/conf.d"
+    $mod_dir             = "${httpd_dir}/mods-available"
+    $mod_enable_dir      = "${httpd_dir}/mods-enabled"
+    $vhost_dir           = "${httpd_dir}/sites-available"
+    $vhost_enable_dir    = "${httpd_dir}/sites-enabled"
+    $conf_file           = 'httpd.conf'
+    $ports_file          = "${conf_dir}/ports.conf"
+    $pidfile             = '/var/run/httpd2.pid'
+    $logroot             = '/var/log/apache2'
+    $logroot_mode        = undef
+    $lib_path            = '/usr/lib64/apache2-prefork/'
+    $mpm_module          = 'prefork'
+    $default_ssl_cert    = '/etc/ssl/certs/ssl-cert-snakeoil.pem'
+    $default_ssl_key     = '/etc/ssl/private/ssl-cert-snakeoil.key'
+    $ssl_certs_dir       = '/etc/ssl/certs'
+    $suphp_addhandler    = 'x-httpd-php'
+    $suphp_engine        = 'off'
+    $suphp_configpath    = '/etc/php5/apache2'
+    $mod_packages        = {
+      'auth_kerb'   => 'apache2-mod_auth_kerb',
+      'fcgid'       => 'apache2-mod_fcgid',
+      'perl'        => 'apache2-mod_perl',
+      'php5'        => 'apache2-mod_php53',
+      'python'      => 'apache2-mod_python',
+    }
+    $mod_libs             = {
+      'php5' => 'libphp5.so',
+    }
+    $conf_template          = 'apache/httpd.conf.erb'
+    $keepalive              = 'Off'
+    $keepalive_timeout      = 15
+    $max_keepalive_requests = 100
+    $fastcgi_lib_path       = '/var/lib/apache2/fastcgi'
+    $mime_support_package = 'aaa_base'
+    $mime_types_config    = '/etc/mime.types'
+    $docroot              = '/srv/www'
+    $cas_cookie_path      = '/var/cache/apache2/mod_auth_cas/'
+    $mellon_lock_file     = undef
+    $mellon_cache_size    = undef
+    $mellon_post_directory = undef
+    $alias_icons_path     = '/usr/share/apache2/icons'
+    $error_documents_path = '/usr/share/apache2/error'
+    $dev_packages        = ['libapr-util1-devel', 'libapr1-devel']
+
+    #
+    # Passenger-specific settings
+    #
+
+    $passenger_conf_file          = 'passenger.conf'
+    $passenger_conf_package_file  = undef
+
+    $passenger_root               = '/usr'
+    $passenger_ruby               = '/usr/bin/ruby'
+    $passenger_default_ruby       = undef
+    $wsgi_socket_prefix           = undef
+
+  } else {
+    fail("Class['apache::params']: Unsupported osfamily: ${::osfamily}")
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/peruser/multiplexer.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+define apache::peruser::multiplexer (
+  $user = $::apache::user,
+  $group = $::apache::group,
+  $file = undef,
+) {
+  if ! $file {
+    $filename = "${name}.conf"
+  } else {
+    $filename = $file
+  }
+  file { "${::apache::mod_dir}/peruser/multiplexers/${filename}":
+    ensure  => file,
+    content => "Multiplexer ${user} ${group}\n",
+    require => File["${::apache::mod_dir}/peruser/multiplexers"],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/peruser/processor.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+define apache::peruser::processor (
+  $user,
+  $group,
+  $file = undef,
+) {
+  if ! $file {
+    $filename = "${name}.conf"
+  } else {
+    $filename = $file
+  }
+  file { "${::apache::mod_dir}/peruser/processors/${filename}":
+    ensure  => file,
+    content => "Processor ${user} ${group}\n",
+    require => File["${::apache::mod_dir}/peruser/processors"],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/php.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+# Class: apache::php
+#
+# This class installs PHP for Apache
+#
+# Parameters:
+# - $php_package
+#
+# Actions:
+#   - Install Apache PHP package
+#
+# Requires:
+#
+# Sample Usage:
+#
+class apache::php {
+  warning('apache::php is deprecated; please use apache::mod::php')
+  include ::apache::mod::php
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/proxy.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+# Class: apache::proxy
+#
+# This class enabled the proxy module for Apache
+#
+# Actions:
+#   - Enables Apache Proxy module
+#
+# Requires:
+#
+# Sample Usage:
+#
+class apache::proxy {
+  warning('apache::proxy is deprecated; please use apache::mod::proxy')
+  include ::apache::mod::proxy
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/python.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+# Class: apache::python
+#
+# This class installs Python for Apache
+#
+# Parameters:
+# - $php_package
+#
+# Actions:
+#   - Install Apache Python package
+#
+# Requires:
+#
+# Sample Usage:
+#
+class apache::python {
+  warning('apache::python is deprecated; please use apache::mod::python')
+  include ::apache::mod::python
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/security/rule_link.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+define apache::security::rule_link () {
+
+  $parts = split($title, '/')
+  $filename = $parts[-1]
+
+  file { $filename:
+    ensure  => 'link',
+    path    => "${::apache::mod::security::modsec_dir}/activated_rules/${filename}",
+    target  => "${::apache::params::modsec_crs_path}/${title}",
+    require => File["${::apache::mod::security::modsec_dir}/activated_rules"],
+    notify  => Class['apache::service'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/service.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,49 @@
+# Class: apache::service
+#
+# Manages the Apache daemon
+#
+# Parameters:
+#
+# Actions:
+#   - Manage Apache service
+#
+# Requires:
+#
+# Sample Usage:
+#
+#    sometype { 'foo':
+#      notify => Class['apache::service'],
+#    }
+#
+#
+class apache::service (
+  $service_name   = $::apache::params::service_name,
+  $service_enable = true,
+  $service_ensure = 'running',
+  $service_manage = true,
+  $service_restart = undef
+) {
+  # The base class must be included first because parameter defaults depend on it
+  if ! defined(Class['apache::params']) {
+    fail('You must include the apache::params class before using any apache defined resources')
+  }
+  validate_bool($service_enable)
+  validate_bool($service_manage)
+
+  case $service_ensure {
+    true, false, 'running', 'stopped': {
+      $_service_ensure = $service_ensure
+    }
+    default: {
+      $_service_ensure = undef
+    }
+  }
+  if $service_manage {
+    service { 'httpd':
+      ensure  => $_service_ensure,
+      name    => $service_name,
+      enable  => $service_enable,
+      restart => $service_restart
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/ssl.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+# Class: apache::ssl
+#
+# This class installs Apache SSL capabilities
+#
+# Parameters:
+# - The $ssl_package name from the apache::params class
+#
+# Actions:
+#   - Install Apache SSL capabilities
+#
+# Requires:
+#
+# Sample Usage:
+#
+class apache::ssl {
+  warning('apache::ssl is deprecated; please use apache::mod::ssl')
+  include ::apache::mod::ssl
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/version.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+# Class: apache::version
+#
+# Try to automatically detect the version by OS
+#
+class apache::version {
+  # This will be 5 or 6 on RedHat, 6 or wheezy on Debian, 12 or quantal on Ubuntu, etc.
+  $osr_array = split($::operatingsystemrelease,'[\/\.]')
+  $distrelease = $osr_array[0]
+  if ! $distrelease {
+    fail("Class['apache::version']: Unparsable \$::operatingsystemrelease: ${::operatingsystemrelease}")
+  }
+
+  case $::osfamily {
+    'RedHat': {
+      if ($::operatingsystem == 'Amazon') {
+        $default = '2.2'
+      } elsif ($::operatingsystem == 'Fedora' and versioncmp($distrelease, '18') >= 0) or ($::operatingsystem != 'Fedora' and versioncmp($distrelease, '7') >= 0) {
+        $default = '2.4'
+      } else {
+        $default = '2.2'
+      }
+    }
+    'Debian': {
+      if $::operatingsystem == 'Ubuntu' and versioncmp($::operatingsystemrelease, '13.10') >= 0 {
+        $default = '2.4'
+      } elsif $::operatingsystem == 'Debian' and versioncmp($distrelease, '8') >= 0 {
+        $default = '2.4'
+      } else {
+        $default = '2.2'
+      }
+    }
+    'FreeBSD': {
+      $default = '2.4'
+    }
+    'Gentoo': {
+      $default = '2.4'
+    }
+    'Suse': {
+      $default = '2.2'
+    }
+    default: {
+      fail("Class['apache::version']: Unsupported osfamily: ${::osfamily}")
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/manifests/vhost.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,978 @@
+# See README.md for usage information
+define apache::vhost(
+  $docroot,
+  $manage_docroot              = true,
+  $virtual_docroot             = false,
+  $port                        = undef,
+  $ip                          = undef,
+  $ip_based                    = false,
+  $add_listen                  = true,
+  $docroot_owner               = 'root',
+  $docroot_group               = $::apache::params::root_group,
+  $docroot_mode                = undef,
+  $serveradmin                 = undef,
+  $ssl                         = false,
+  $ssl_cert                    = $::apache::default_ssl_cert,
+  $ssl_key                     = $::apache::default_ssl_key,
+  $ssl_chain                   = $::apache::default_ssl_chain,
+  $ssl_ca                      = $::apache::default_ssl_ca,
+  $ssl_crl_path                = $::apache::default_ssl_crl_path,
+  $ssl_crl                     = $::apache::default_ssl_crl,
+  $ssl_crl_check               = $::apache::default_ssl_crl_check,
+  $ssl_certs_dir               = $::apache::params::ssl_certs_dir,
+  $ssl_protocol                = undef,
+  $ssl_cipher                  = undef,
+  $ssl_honorcipherorder        = undef,
+  $ssl_verify_client           = undef,
+  $ssl_verify_depth            = undef,
+  $ssl_proxy_machine_cert      = undef,
+  $ssl_options                 = undef,
+  $ssl_openssl_conf_cmd        = undef,
+  $ssl_proxyengine             = false,
+  $priority                    = undef,
+  $default_vhost               = false,
+  $servername                  = $name,
+  $serveraliases               = [],
+  $options                     = ['Indexes','FollowSymLinks','MultiViews'],
+  $override                    = ['None'],
+  $directoryindex              = '',
+  $vhost_name                  = '*',
+  $logroot                     = $::apache::logroot,
+  $logroot_ensure              = 'directory',
+  $logroot_mode                = undef,
+  $log_level                   = undef,
+  $access_log                  = true,
+  $access_log_file             = false,
+  $access_log_pipe             = false,
+  $access_log_syslog           = false,
+  $access_log_format           = false,
+  $access_log_env_var          = false,
+  $access_logs                 = undef,
+  $aliases                     = undef,
+  $directories                 = undef,
+  $error_log                   = true,
+  $error_log_file              = undef,
+  $error_log_pipe              = undef,
+  $error_log_syslog            = undef,
+  $error_documents             = [],
+  $fallbackresource            = undef,
+  $scriptalias                 = undef,
+  $scriptaliases               = [],
+  $proxy_dest                  = undef,
+  $proxy_dest_match            = undef,
+  $proxy_dest_reverse_match    = undef,
+  $proxy_pass                  = undef,
+  $proxy_pass_match            = undef,
+  $suphp_addhandler            = $::apache::params::suphp_addhandler,
+  $suphp_engine                = $::apache::params::suphp_engine,
+  $suphp_configpath            = $::apache::params::suphp_configpath,
+  $php_flags                   = {},
+  $php_values                  = {},
+  $php_admin_flags             = {},
+  $php_admin_values            = {},
+  $no_proxy_uris               = [],
+  $no_proxy_uris_match         = [],
+  $proxy_preserve_host         = false,
+  $proxy_error_override        = false,
+  $redirect_source             = '/',
+  $redirect_dest               = undef,
+  $redirect_status             = undef,
+  $redirectmatch_status        = undef,
+  $redirectmatch_regexp        = undef,
+  $redirectmatch_dest          = undef,
+  $rack_base_uris              = undef,
+  $passenger_base_uris         = undef,
+  $headers                     = undef,
+  $request_headers             = undef,
+  $filters                     = undef,
+  $rewrites                    = undef,
+  $rewrite_base                = undef,
+  $rewrite_rule                = undef,
+  $rewrite_cond                = undef,
+  $setenv                      = [],
+  $setenvif                    = [],
+  $block                       = [],
+  $ensure                      = 'present',
+  $wsgi_application_group      = undef,
+  $wsgi_daemon_process         = undef,
+  $wsgi_daemon_process_options = undef,
+  $wsgi_import_script          = undef,
+  $wsgi_import_script_options  = undef,
+  $wsgi_process_group          = undef,
+  $wsgi_script_aliases         = undef,
+  $wsgi_pass_authorization     = undef,
+  $wsgi_chunked_request        = undef,
+  $custom_fragment             = undef,
+  $itk                         = undef,
+  $action                      = undef,
+  $fastcgi_server              = undef,
+  $fastcgi_socket              = undef,
+  $fastcgi_dir                 = undef,
+  $additional_includes         = [],
+  $use_optional_includes       = $::apache::use_optional_includes,
+  $apache_version              = $::apache::apache_version,
+  $allow_encoded_slashes       = undef,
+  $suexec_user_group           = undef,
+  $passenger_app_root          = undef,
+  $passenger_app_env           = undef,
+  $passenger_ruby              = undef,
+  $passenger_min_instances     = undef,
+  $passenger_start_timeout     = undef,
+  $passenger_pre_start         = undef,
+  $add_default_charset         = undef,
+  $modsec_disable_vhost        = undef,
+  $modsec_disable_ids          = undef,
+  $modsec_disable_ips          = undef,
+  $modsec_body_limit           = undef,
+  $auth_kerb                   = false,
+  $krb_method_negotiate        = 'on',
+  $krb_method_k5passwd         = 'on',
+  $krb_authoritative           = 'on',
+  $krb_auth_realms             = [],
+  $krb_5keytab                 = undef,
+  $krb_local_user_mapping      = undef,
+  $limit_request_field_size    = undef,
+) {
+  # The base class must be included first because it is used by parameter defaults
+  if ! defined(Class['apache']) {
+    fail('You must include the apache base class before using any apache defined resources')
+  }
+
+  $apache_name = $::apache::apache_name
+
+  validate_re($ensure, '^(present|absent)$',
+  "${ensure} is not supported for ensure.
+  Allowed values are 'present' and 'absent'.")
+  validate_re($suphp_engine, '^(on|off)$',
+  "${suphp_engine} is not supported for suphp_engine.
+  Allowed values are 'on' and 'off'.")
+  validate_bool($ip_based)
+  validate_bool($access_log)
+  validate_bool($error_log)
+  validate_bool($ssl)
+  validate_bool($default_vhost)
+  validate_bool($ssl_proxyengine)
+  if $rewrites {
+    validate_array($rewrites)
+    validate_hash($rewrites[0])
+  }
+
+  # Input validation begins
+
+  if $suexec_user_group {
+    validate_re($suexec_user_group, '^[\w-]+ [\w-]+$',
+    "${suexec_user_group} is not supported for suexec_user_group.  Must be 'user group'.")
+  }
+
+  if $wsgi_pass_authorization {
+    validate_re(downcase($wsgi_pass_authorization), '^(on|off)$',
+    "${wsgi_pass_authorization} is not supported for wsgi_pass_authorization.
+    Allowed values are 'on' and 'off'.")
+  }
+
+  # Deprecated backwards-compatibility
+  if $rewrite_base {
+    warning('Apache::Vhost: parameter rewrite_base is deprecated in favor of rewrites')
+  }
+  if $rewrite_rule {
+    warning('Apache::Vhost: parameter rewrite_rule is deprecated in favor of rewrites')
+  }
+  if $rewrite_cond {
+    warning('Apache::Vhost parameter rewrite_cond is deprecated in favor of rewrites')
+  }
+
+  if $wsgi_script_aliases {
+    validate_hash($wsgi_script_aliases)
+  }
+  if $wsgi_daemon_process_options {
+    validate_hash($wsgi_daemon_process_options)
+  }
+  if $wsgi_import_script_options {
+    validate_hash($wsgi_import_script_options)
+  }
+  if $itk {
+    validate_hash($itk)
+  }
+
+  validate_re($logroot_ensure, '^(directory|absent)$',
+  "${logroot_ensure} is not supported for logroot_ensure.
+  Allowed values are 'directory' and 'absent'.")
+
+  if $log_level {
+    validate_apache_log_level($log_level)
+  }
+
+  if $access_log_file and $access_log_pipe {
+    fail("Apache::Vhost[${name}]: 'access_log_file' and 'access_log_pipe' cannot be defined at the same time")
+  }
+
+  if $error_log_file and $error_log_pipe {
+    fail("Apache::Vhost[${name}]: 'error_log_file' and 'error_log_pipe' cannot be defined at the same time")
+  }
+
+  if $fallbackresource {
+    validate_re($fallbackresource, '^/|disabled', 'Please make sure fallbackresource starts with a / (or is "disabled")')
+  }
+
+  if $custom_fragment {
+    validate_string($custom_fragment)
+  }
+
+  if $allow_encoded_slashes {
+    validate_re($allow_encoded_slashes, '(^on$|^off$|^nodecode$)', "${allow_encoded_slashes} is not permitted for allow_encoded_slashes. Allowed values are 'on', 'off' or 'nodecode'.")
+  }
+
+  validate_bool($auth_kerb)
+
+  if $limit_request_field_size {
+    validate_integer($limit_request_field_size)
+  }
+
+  # Validate the docroot as a string if:
+  # - $manage_docroot is true
+  if $manage_docroot {
+    validate_string($docroot)
+  }
+  # Input validation ends
+
+  if $ssl and $ensure == 'present' {
+    include ::apache::mod::ssl
+    # Required for the AddType lines.
+    include ::apache::mod::mime
+  }
+
+  if $auth_kerb and $ensure == 'present' {
+    include ::apache::mod::auth_kerb
+  }
+
+  if $virtual_docroot {
+    include ::apache::mod::vhost_alias
+  }
+
+  if $wsgi_daemon_process {
+    include ::apache::mod::wsgi
+  }
+
+  if $suexec_user_group {
+    include ::apache::mod::suexec
+  }
+
+  if $passenger_app_root or $passenger_app_env or $passenger_ruby or $passenger_min_instances or $passenger_start_timeout or $passenger_pre_start {
+    include ::apache::mod::passenger
+  }
+
+  # Configure the defaultness of a vhost
+  if $priority {
+    $priority_real = "${priority}-"
+  } elsif $priority == false {
+    $priority_real = ''
+  } elsif $default_vhost {
+    $priority_real = '10-'
+  } else {
+    $priority_real = '25-'
+  }
+
+  ## Apache include does not always work with spaces in the filename
+  $filename = regsubst($name, ' ', '_', 'G')
+
+  # This ensures that the docroot exists
+  # But enables it to be specified across multiple vhost resources
+  if $manage_docroot and $docroot and ! defined(File[$docroot]) {
+    file { $docroot:
+      ensure  => directory,
+      owner   => $docroot_owner,
+      group   => $docroot_group,
+      mode    => $docroot_mode,
+      require => Package['httpd'],
+      before  => Concat["${priority_real}${filename}.conf"],
+    }
+  }
+
+  # Same as above, but for logroot
+  if ! defined(File[$logroot]) {
+    file { $logroot:
+      ensure  => $logroot_ensure,
+      mode    => $logroot_mode,
+      require => Package['httpd'],
+      before  => Concat["${priority_real}${filename}.conf"],
+    }
+  }
+
+
+  # Is apache::mod::passenger enabled (or apache::mod['passenger'])
+  $passenger_enabled = defined(Apache::Mod['passenger'])
+
+  # Is apache::mod::shib enabled (or apache::mod['shib2'])
+  $shibboleth_enabled = defined(Apache::Mod['shib2'])
+
+  if $access_log and !$access_logs {
+    if $access_log_file {
+      $_logs_dest = "${logroot}/${access_log_file}"
+    } elsif $access_log_pipe {
+      $_logs_dest = $access_log_pipe
+    } elsif $access_log_syslog {
+      $_logs_dest = $access_log_syslog
+    } else {
+      $_logs_dest = undef
+    }
+    $_access_logs = [{
+      'file'        => $access_log_file,
+      'pipe'        => $access_log_pipe,
+      'syslog'      => $access_log_syslog,
+      'format'      => $access_log_format,
+      'env'         => $access_log_env_var
+    }]
+  } elsif $access_logs {
+    if !is_array($access_logs) {
+      fail("Apache::Vhost[${name}]: access_logs must be an array of hashes")
+    }
+    $_access_logs = $access_logs
+  }
+
+  if $error_log_file {
+    $error_log_destination = "${logroot}/${error_log_file}"
+  } elsif $error_log_pipe {
+    $error_log_destination = $error_log_pipe
+  } elsif $error_log_syslog {
+    $error_log_destination = $error_log_syslog
+  } else {
+    if $ssl {
+      $error_log_destination = "${logroot}/${name}_error_ssl.log"
+    } else {
+      $error_log_destination = "${logroot}/${name}_error.log"
+    }
+  }
+
+  if $ip {
+    if $port {
+      $listen_addr_port = suffix(any2array($ip),":${port}")
+      $nvh_addr_port = suffix(any2array($ip),":${port}")
+    } else {
+      $listen_addr_port = undef
+      $nvh_addr_port = $ip
+      if ! $servername and ! $ip_based {
+        fail("Apache::Vhost[${name}]: must pass 'ip' and/or 'port' parameters for name-based vhosts")
+      }
+    }
+  } else {
+    if $port {
+      $listen_addr_port = $port
+      $nvh_addr_port = "${vhost_name}:${port}"
+    } else {
+      $listen_addr_port = undef
+      $nvh_addr_port = $name
+      if ! $servername {
+        fail("Apache::Vhost[${name}]: must pass 'ip' and/or 'port' parameters, and/or 'servername' parameter")
+      }
+    }
+  }
+  if $add_listen {
+    if $ip and defined(Apache::Listen["${port}"]) {
+      fail("Apache::Vhost[${name}]: Mixing IP and non-IP Listen directives is not possible; check the add_listen parameter of the apache::vhost define to disable this")
+    }
+    if $listen_addr_port and $ensure == 'present' {
+      ensure_resource('apache::listen', $listen_addr_port)
+    }
+  }
+  if ! $ip_based {
+    if $ensure == 'present' and (versioncmp($apache_version, '2.4') < 0) {
+      ensure_resource('apache::namevirtualhost', $nvh_addr_port)
+    }
+  }
+
+  # Load mod_rewrite if needed and not yet loaded
+  if $rewrites or $rewrite_cond {
+    if ! defined(Class['apache::mod::rewrite']) {
+      include ::apache::mod::rewrite
+    }
+  }
+
+  # Load mod_alias if needed and not yet loaded
+  if ($scriptalias or $scriptaliases != []) or ($aliases and $aliases != []) or ($redirect_source and $redirect_dest) {
+    if ! defined(Class['apache::mod::alias'])  and ($ensure == 'present') {
+      include ::apache::mod::alias
+    }
+  }
+
+  # Load mod_proxy if needed and not yet loaded
+  if ($proxy_dest or $proxy_pass or $proxy_pass_match or $proxy_dest_match) {
+    if ! defined(Class['apache::mod::proxy']) {
+      include ::apache::mod::proxy
+    }
+    if ! defined(Class['apache::mod::proxy_http']) {
+      include ::apache::mod::proxy_http
+    }
+  }
+
+  # Load mod_passenger if needed and not yet loaded
+  if $rack_base_uris {
+    if ! defined(Class['apache::mod::passenger']) {
+      include ::apache::mod::passenger
+    }
+  }
+
+  # Load mod_passenger if needed and not yet loaded
+  if $passenger_base_uris {
+      include ::apache::mod::passenger
+  }
+
+  # Load mod_fastci if needed and not yet loaded
+  if $fastcgi_server and $fastcgi_socket {
+    if ! defined(Class['apache::mod::fastcgi']) {
+      include ::apache::mod::fastcgi
+    }
+  }
+
+  # Check if mod_headers is required to process $headers/$request_headers
+  if $headers or $request_headers {
+    if ! defined(Class['apache::mod::headers']) {
+      include ::apache::mod::headers
+    }
+  }
+
+  # Check if mod_filter is required to process $filters
+  if $filters {
+    if ! defined(Class['apache::mod::filter']) {
+      include ::apache::mod::filter
+    }
+  }
+
+  if ($setenv and ! empty($setenv)) or ($setenvif and ! empty($setenvif)) {
+    if ! defined(Class['apache::mod::setenvif']) {
+      include ::apache::mod::setenvif
+    }
+  }
+
+  ## Create a default directory list if none defined
+  if $directories {
+    if !is_hash($directories) and !(is_array($directories) and is_hash($directories[0])) {
+      fail("Apache::Vhost[${name}]: 'directories' must be either a Hash or an Array of Hashes")
+    }
+    $_directories = $directories
+  } elsif $docroot {
+    $_directory = {
+      provider       => 'directory',
+      path           => $docroot,
+      options        => $options,
+      allow_override => $override,
+      directoryindex => $directoryindex,
+    }
+
+    if versioncmp($apache_version, '2.4') >= 0 {
+      $_directory_version = {
+        require => 'all granted',
+      }
+    } else {
+      $_directory_version = {
+        order => 'allow,deny',
+        allow => 'from all',
+      }
+    }
+
+    $_directories = [ merge($_directory, $_directory_version) ]
+  }
+
+  ## Create a global LocationMatch if locations aren't defined
+  if $modsec_disable_ids {
+    if is_hash($modsec_disable_ids) {
+      $_modsec_disable_ids = $modsec_disable_ids
+    } elsif is_array($modsec_disable_ids) {
+      $_modsec_disable_ids = { '.*' => $modsec_disable_ids }
+    } else {
+      fail("Apache::Vhost[${name}]: 'modsec_disable_ids' must be either a Hash of location/IDs or an Array of IDs")
+    }
+  }
+
+  concat { "${priority_real}${filename}.conf":
+    ensure  => $ensure,
+    path    => "${::apache::vhost_dir}/${priority_real}${filename}.conf",
+    owner   => 'root',
+    group   => $::apache::params::root_group,
+    mode    => '0644',
+    order   => 'numeric',
+    require => Package['httpd'],
+    notify  => Class['apache::service'],
+  }
+  if $::apache::vhost_enable_dir {
+    $vhost_enable_dir = $::apache::vhost_enable_dir
+    $vhost_symlink_ensure = $ensure ? {
+      present => link,
+      default => $ensure,
+    }
+    file{ "${priority_real}${filename}.conf symlink":
+      ensure  => $vhost_symlink_ensure,
+      path    => "${vhost_enable_dir}/${priority_real}${filename}.conf",
+      target  => "${::apache::vhost_dir}/${priority_real}${filename}.conf",
+      owner   => 'root',
+      group   => $::apache::params::root_group,
+      mode    => '0644',
+      require => Concat["${priority_real}${filename}.conf"],
+      notify  => Class['apache::service'],
+    }
+  }
+
+  # Template uses:
+  # - $nvh_addr_port
+  # - $servername
+  # - $serveradmin
+  concat::fragment { "${name}-apache-header":
+    target  => "${priority_real}${filename}.conf",
+    order   => 0,
+    content => template('apache/vhost/_file_header.erb'),
+  }
+
+  # Template uses:
+  # - $virtual_docroot
+  # - $docroot
+  if $docroot {
+    concat::fragment { "${name}-docroot":
+      target  => "${priority_real}${filename}.conf",
+      order   => 10,
+      content => template('apache/vhost/_docroot.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $aliases
+  if $aliases and ! empty($aliases) {
+    concat::fragment { "${name}-aliases":
+      target  => "${priority_real}${filename}.conf",
+      order   => 20,
+      content => template('apache/vhost/_aliases.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $itk
+  # - $::kernelversion
+  if $itk and ! empty($itk) {
+    concat::fragment { "${name}-itk":
+      target  => "${priority_real}${filename}.conf",
+      order   => 30,
+      content => template('apache/vhost/_itk.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $fallbackresource
+  if $fallbackresource {
+    concat::fragment { "${name}-fallbackresource":
+      target  => "${priority_real}${filename}.conf",
+      order   => 40,
+      content => template('apache/vhost/_fallbackresource.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $allow_encoded_slashes
+  if $allow_encoded_slashes {
+    concat::fragment { "${name}-allow_encoded_slashes":
+      target  => "${priority_real}${filename}.conf",
+      order   => 50,
+      content => template('apache/vhost/_allow_encoded_slashes.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $_directories
+  # - $docroot
+  # - $apache_version
+  # - $suphp_engine
+  # - $shibboleth_enabled
+  if $_directories and ! empty($_directories) {
+    concat::fragment { "${name}-directories":
+      target  => "${priority_real}${filename}.conf",
+      order   => 60,
+      content => template('apache/vhost/_directories.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $additional_includes
+  if $additional_includes and ! empty($additional_includes) {
+    concat::fragment { "${name}-additional_includes":
+      target  => "${priority_real}${filename}.conf",
+      order   => 70,
+      content => template('apache/vhost/_additional_includes.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $error_log
+  # - $log_level
+  # - $error_log_destination
+  # - $log_level
+  if $error_log or $log_level {
+    concat::fragment { "${name}-logging":
+      target  => "${priority_real}${filename}.conf",
+      order   => 80,
+      content => template('apache/vhost/_logging.erb'),
+    }
+  }
+
+  # Template uses no variables
+  concat::fragment { "${name}-serversignature":
+    target  => "${priority_real}${filename}.conf",
+    order   => 90,
+    content => template('apache/vhost/_serversignature.erb'),
+  }
+
+  # Template uses:
+  # - $access_log
+  # - $_access_log_env_var
+  # - $access_log_destination
+  # - $_access_log_format
+  # - $_access_log_env_var
+  # - $access_logs
+  if $access_log or $access_logs {
+    concat::fragment { "${name}-access_log":
+      target  => "${priority_real}${filename}.conf",
+      order   => 100,
+      content => template('apache/vhost/_access_log.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $action
+  if $action {
+    concat::fragment { "${name}-action":
+      target  => "${priority_real}${filename}.conf",
+      order   => 110,
+      content => template('apache/vhost/_action.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $block
+  # - $apache_version
+  if $block and ! empty($block) {
+    concat::fragment { "${name}-block":
+      target  => "${priority_real}${filename}.conf",
+      order   => 120,
+      content => template('apache/vhost/_block.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $error_documents
+  if $error_documents and ! empty($error_documents) {
+    concat::fragment { "${name}-error_document":
+      target  => "${priority_real}${filename}.conf",
+      order   => 130,
+      content => template('apache/vhost/_error_document.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $proxy_dest
+  # - $proxy_pass
+  # - $proxy_pass_match
+  # - $proxy_preserve_host
+  # - $no_proxy_uris
+  if $proxy_dest or $proxy_pass or $proxy_pass_match or $proxy_dest_match {
+    concat::fragment { "${name}-proxy":
+      target  => "${priority_real}${filename}.conf",
+      order   => 140,
+      content => template('apache/vhost/_proxy.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $rack_base_uris
+  if $rack_base_uris {
+    concat::fragment { "${name}-rack":
+      target  => "${priority_real}${filename}.conf",
+      order   => 150,
+      content => template('apache/vhost/_rack.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $passenger_base_uris
+  if $passenger_base_uris {
+    concat::fragment { "${name}-passenger_uris":
+      target  => "${priority_real}${filename}.conf",
+      order   => 155,
+      content => template('apache/vhost/_passenger_base_uris.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $redirect_source
+  # - $redirect_dest
+  # - $redirect_status
+  # - $redirect_dest_a
+  # - $redirect_source_a
+  # - $redirect_status_a
+  # - $redirectmatch_status
+  # - $redirectmatch_regexp
+  # - $redirectmatch_dest
+  # - $redirectmatch_status_a
+  # - $redirectmatch_regexp_a
+  # - $redirectmatch_dest
+  if ($redirect_source and $redirect_dest) or ($redirectmatch_status and $redirectmatch_regexp and $redirectmatch_dest) {
+    concat::fragment { "${name}-redirect":
+      target  => "${priority_real}${filename}.conf",
+      order   => 160,
+      content => template('apache/vhost/_redirect.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $rewrites
+  # - $rewrite_base
+  # - $rewrite_rule
+  # - $rewrite_cond
+  # - $rewrite_map
+  if $rewrites or $rewrite_rule {
+    concat::fragment { "${name}-rewrite":
+      target  => "${priority_real}${filename}.conf",
+      order   => 170,
+      content => template('apache/vhost/_rewrite.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $scriptaliases
+  # - $scriptalias
+  if ( $scriptalias or $scriptaliases != [] ) {
+    concat::fragment { "${name}-scriptalias":
+      target  => "${priority_real}${filename}.conf",
+      order   => 180,
+      content => template('apache/vhost/_scriptalias.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $serveraliases
+  if $serveraliases and ! empty($serveraliases) {
+    concat::fragment { "${name}-serveralias":
+      target  => "${priority_real}${filename}.conf",
+      order   => 190,
+      content => template('apache/vhost/_serveralias.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $setenv
+  # - $setenvif
+  if ($setenv and ! empty($setenv)) or ($setenvif and ! empty($setenvif)) {
+    concat::fragment { "${name}-setenv":
+      target  => "${priority_real}${filename}.conf",
+      order   => 200,
+      content => template('apache/vhost/_setenv.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $ssl
+  # - $ssl_cert
+  # - $ssl_key
+  # - $ssl_chain
+  # - $ssl_certs_dir
+  # - $ssl_ca
+  # - $ssl_crl_path
+  # - $ssl_crl
+  # - $ssl_crl_check
+  # - $ssl_proxyengine
+  # - $ssl_protocol
+  # - $ssl_cipher
+  # - $ssl_honorcipherorder
+  # - $ssl_verify_client
+  # - $ssl_verify_depth
+  # - $ssl_proxy_machine_cert
+  # - $ssl_options
+  # - $ssl_openssl_conf_cmd
+  # - $apache_version
+  if $ssl {
+    concat::fragment { "${name}-ssl":
+      target  => "${priority_real}${filename}.conf",
+      order   => 210,
+      content => template('apache/vhost/_ssl.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $auth_kerb
+  # - $krb_method_negotiate
+  # - $krb_method_k5passwd
+  # - $krb_authoritative
+  # - $krb_auth_realms
+  # - $krb_5keytab 
+  # - $krb_local_user_mapping
+  if $auth_kerb {
+    concat::fragment { "${name}-auth_kerb":
+      target  => "${priority_real}${filename}.conf",
+      order   => 210,
+      content => template('apache/vhost/_auth_kerb.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $suphp_engine
+  # - $suphp_addhandler
+  # - $suphp_configpath
+  if $suphp_engine == 'on' {
+    concat::fragment { "${name}-suphp":
+      target  => "${priority_real}${filename}.conf",
+      order   => 220,
+      content => template('apache/vhost/_suphp.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $php_values
+  # - $php_flags
+  if ($php_values and ! empty($php_values)) or ($php_flags and ! empty($php_flags)) {
+    concat::fragment { "${name}-php":
+      target  => "${priority_real}${filename}.conf",
+      order   => 220,
+      content => template('apache/vhost/_php.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $php_admin_values
+  # - $php_admin_flags
+  if ($php_admin_values and ! empty($php_admin_values)) or ($php_admin_flags and ! empty($php_admin_flags)) {
+    concat::fragment { "${name}-php_admin":
+      target  => "${priority_real}${filename}.conf",
+      order   => 230,
+      content => template('apache/vhost/_php_admin.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $headers
+  if $headers and ! empty($headers) {
+    concat::fragment { "${name}-header":
+      target  => "${priority_real}${filename}.conf",
+      order   => 240,
+      content => template('apache/vhost/_header.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $request_headers
+  if $request_headers and ! empty($request_headers) {
+    concat::fragment { "${name}-requestheader":
+      target  => "${priority_real}${filename}.conf",
+      order   => 250,
+      content => template('apache/vhost/_requestheader.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $wsgi_application_group
+  # - $wsgi_daemon_process
+  # - $wsgi_daemon_process_options
+  # - $wsgi_import_script
+  # - $wsgi_import_script_options
+  # - $wsgi_process_group
+  # - $wsgi_script_aliases
+  # - $wsgi_pass_authorization
+  if $wsgi_application_group or $wsgi_daemon_process or ($wsgi_import_script and $wsgi_import_script_options) or $wsgi_process_group or ($wsgi_script_aliases and ! empty($wsgi_script_aliases)) or $wsgi_pass_authorization {
+    concat::fragment { "${name}-wsgi":
+      target  => "${priority_real}${filename}.conf",
+      order   => 260,
+      content => template('apache/vhost/_wsgi.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $custom_fragment
+  if $custom_fragment {
+    concat::fragment { "${name}-custom_fragment":
+      target  => "${priority_real}${filename}.conf",
+      order   => 270,
+      content => template('apache/vhost/_custom_fragment.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $fastcgi_server
+  # - $fastcgi_socket
+  # - $fastcgi_dir
+  # - $apache_version
+  if $fastcgi_server or $fastcgi_dir {
+    concat::fragment { "${name}-fastcgi":
+      target  => "${priority_real}${filename}.conf",
+      order   => 280,
+      content => template('apache/vhost/_fastcgi.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $suexec_user_group
+  if $suexec_user_group {
+    concat::fragment { "${name}-suexec":
+      target  => "${priority_real}${filename}.conf",
+      order   => 290,
+      content => template('apache/vhost/_suexec.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $passenger_app_root
+  # - $passenger_app_env
+  # - $passenger_ruby
+  # - $passenger_min_instances
+  # - $passenger_start_timeout
+  # - $passenger_pre_start
+  if $passenger_app_root or $passenger_app_env or $passenger_ruby or $passenger_min_instances or $passenger_start_timeout or $passenger_pre_start {
+    concat::fragment { "${name}-passenger":
+      target  => "${priority_real}${filename}.conf",
+      order   => 300,
+      content => template('apache/vhost/_passenger.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $add_default_charset
+  if $add_default_charset {
+    concat::fragment { "${name}-charsets":
+      target  => "${priority_real}${filename}.conf",
+      order   => 310,
+      content => template('apache/vhost/_charsets.erb'),
+    }
+  }
+
+  # Template uses:
+  # - $modsec_disable_vhost
+  # - $modsec_disable_ids
+  # - $modsec_disable_ips
+  # - $modsec_body_limit
+  if $modsec_disable_vhost or $modsec_disable_ids or $modsec_disable_ips {
+    concat::fragment { "${name}-security":
+      target  => "${priority_real}${filename}.conf",
+      order   => 320,
+      content => template('apache/vhost/_security.erb')
+    }
+  }
+
+  # Template uses:
+  # - $filters
+  if $filters and ! empty($filters) {
+    concat::fragment { "${name}-filters":
+      target  => "${priority_real}${filename}.conf",
+      order   => 330,
+      content => template('apache/vhost/_filters.erb'),
+    }
+  }
+  # Template uses:
+  # - $limit_request_field_size
+  if $limit_request_field_size {
+    concat::fragment { "${name}-limits":
+      target  => "${priority_real}${filename}.conf",
+      order   => 330,
+      content => template('apache/vhost/_limits.erb'),
+    }
+  }
+
+  # Template uses no variables
+  concat::fragment { "${name}-file_footer":
+    target  => "${priority_real}${filename}.conf",
+    order   => 999,
+    content => template('apache/vhost/_file_footer.erb'),
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/metadata.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,79 @@
+{
+  "name": "puppetlabs-apache",
+  "version": "1.7.1",
+  "author": "puppetlabs",
+  "summary": "Installs, configures, and manages Apache virtual hosts, web services, and modules.",
+  "license": "Apache-2.0",
+  "source": "git://github.com/puppetlabs/puppetlabs-apache.git",
+  "project_page": "https://github.com/puppetlabs/puppetlabs-apache",
+  "issues_url": "https://tickets.puppetlabs.com/browse/MODULES",
+  "dependencies": [
+    {"name":"puppetlabs/stdlib","version_requirement":">= 2.4.0 < 5.0.0"},
+    {"name":"puppetlabs/concat","version_requirement":">= 1.1.1 < 2.0.0"}
+  ],
+  "operatingsystem_support": [
+    {
+      "operatingsystem": "RedHat",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "CentOS",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "OracleLinux",
+      "operatingsystemrelease": [
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Scientific",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Debian",
+      "operatingsystemrelease": [
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "SLES",
+      "operatingsystemrelease": [
+        "11 SP1"
+      ]
+    },
+    {
+      "operatingsystem": "Ubuntu",
+      "operatingsystemrelease": [
+        "10.04",
+        "12.04",
+        "14.04"
+      ]
+    }
+  ],
+  "requirements": [
+    {
+      "name": "pe",
+      "version_requirement": ">= 3.7.0 < 2015.4.0"
+    },
+    {
+      "name": "puppet",
+      "version_requirement": ">= 3.0.0 < 5.0.0"
+    }
+  ],
+  "description": "Module for Apache configuration"
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/apache_parameters_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,475 @@
+require 'spec_helper_acceptance'
+require_relative './version.rb'
+
+describe 'apache parameters', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+
+  # Currently this test only does something on FreeBSD.
+  describe 'default_confd_files => false' do
+    it 'doesnt do anything' do
+      pp = "class { 'apache': default_confd_files => false }"
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    if fact('osfamily') == 'FreeBSD'
+      describe file("#{$confd_dir}/no-accf.conf.erb") do
+        it { is_expected.not_to be_file }
+      end
+    end
+  end
+  describe 'default_confd_files => true' do
+    it 'copies conf.d files' do
+      pp = "class { 'apache': default_confd_files => true }"
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    if fact('osfamily') == 'FreeBSD'
+      describe file("#{$confd_dir}/no-accf.conf.erb") do
+        it { is_expected.to be_file }
+      end
+    end
+  end
+
+  describe 'when set adds a listen statement' do
+    it 'applys cleanly' do
+      pp = "class { 'apache': ip => '10.1.1.1', service_ensure => stopped }"
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file($ports_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'Listen 10.1.1.1' }
+    end
+  end
+
+  describe 'service tests => true' do
+    it 'starts the service' do
+      pp = <<-EOS
+        class { 'apache':
+          service_enable => true,
+          service_manage => true,
+          service_ensure => running,
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service($service_name) do
+      it { is_expected.to be_running }
+      it { is_expected.to be_enabled }
+    end
+  end
+
+  describe 'service tests => false' do
+    it 'stops the service' do
+      pp = <<-EOS
+        class { 'apache':
+          service_enable => false,
+          service_ensure => stopped,
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service($service_name) do
+      it { is_expected.not_to be_running }
+      it { is_expected.not_to be_enabled }
+    end
+  end
+
+  describe 'service manage => false' do
+    it 'we dont manage the service, so it shouldnt start the service' do
+      pp = <<-EOS
+        class { 'apache':
+          service_enable => true,
+          service_manage => false,
+          service_ensure => true,
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service($service_name) do
+      it { is_expected.not_to be_running }
+      it { is_expected.not_to be_enabled }
+    end
+  end
+
+  describe 'purge parameters => false' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache':
+          purge_configs   => false,
+          purge_vhost_dir => false,
+          vhost_dir       => "#{$confd_dir}.vhosts"
+        }
+      EOS
+      shell("touch #{$confd_dir}/test.conf")
+      shell("mkdir -p #{$confd_dir}.vhosts && touch #{$confd_dir}.vhosts/test.conf")
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    # Ensure the files didn't disappear.
+    describe file("#{$confd_dir}/test.conf") do
+      it { is_expected.to be_file }
+    end
+    describe file("#{$confd_dir}.vhosts/test.conf") do
+      it { is_expected.to be_file }
+    end
+  end
+
+  if fact('osfamily') != 'Debian'
+    describe 'purge parameters => true' do
+      it 'applies cleanly' do
+        pp = <<-EOS
+          class { 'apache':
+            purge_configs   => true,
+            purge_vhost_dir => true,
+            vhost_dir       => "#{$confd_dir}.vhosts"
+          }
+        EOS
+        shell("touch #{$confd_dir}/test.conf")
+        shell("mkdir -p #{$confd_dir}.vhosts && touch #{$confd_dir}.vhosts/test.conf")
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      # File should be gone
+      describe file("#{$confd_dir}/test.conf") do
+        it { is_expected.not_to be_file }
+      end
+      describe file("#{$confd_dir}.vhosts/test.conf") do
+        it { is_expected.not_to be_file }
+      end
+    end
+  end
+
+  describe 'serveradmin' do
+    it 'applies cleanly' do
+      pp = "class { 'apache': serveradmin => 'test@example.com' }"
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file($vhost) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'ServerAdmin test@example.com' }
+    end
+  end
+
+  describe 'sendfile' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = "class { 'apache': sendfile => 'On' }"
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'EnableSendfile On' }
+    end
+
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = "class { 'apache': sendfile => 'Off' }"
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'Sendfile Off' }
+    end
+  end
+
+  describe 'error_documents' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = "class { 'apache': error_documents => true }"
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'Alias /error/' }
+    end
+  end
+
+  describe 'timeout' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = "class { 'apache': timeout => '1234' }"
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'Timeout 1234' }
+    end
+  end
+
+  describe 'httpd_dir' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = <<-EOS
+          class { 'apache': httpd_dir => '/tmp', service_ensure => stopped }
+          include 'apache::mod::mime'
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe file("#{$mod_dir}/mime.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'AddLanguage eo .eo' }
+    end
+  end
+
+  describe 'server_root' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = "class { 'apache': server_root => '/tmp/root', service_ensure => stopped }"
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'ServerRoot "/tmp/root"' }
+    end
+  end
+
+  describe 'confd_dir' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = "class { 'apache': confd_dir => '/tmp/root', service_ensure => stopped, use_optional_includes => true }"
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    if $apache_version == '2.4'
+      describe file($conf_file) do
+        it { is_expected.to be_file }
+        it { is_expected.to contain 'IncludeOptional "/tmp/root/*.conf"' }
+      end
+    else
+      describe file($conf_file) do
+        it { is_expected.to be_file }
+        it { is_expected.to contain 'Include "/tmp/root/*.conf"' }
+      end
+    end
+  end
+
+  describe 'conf_template' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = "class { 'apache': conf_template => 'another/test.conf.erb', service_ensure => stopped }"
+        shell("mkdir -p #{default['distmoduledir']}/another/templates")
+        shell("echo 'testcontent' >> #{default['distmoduledir']}/another/templates/test.conf.erb")
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'testcontent' }
+    end
+  end
+
+  describe 'servername' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = "class { 'apache': servername => 'test.server', service_ensure => stopped }"
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'ServerName "test.server"' }
+    end
+  end
+
+  describe 'user' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = <<-EOS
+          class { 'apache':
+            manage_user  => true,
+            manage_group => true,
+            user         => 'testweb',
+            group        => 'testweb',
+          }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe user('testweb') do
+      it { is_expected.to exist }
+      it { is_expected.to belong_to_group 'testweb' }
+    end
+
+    describe group('testweb') do
+      it { is_expected.to exist }
+    end
+  end
+
+  describe 'logformats' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = <<-EOS
+          class { 'apache':
+            log_formats => {
+              'vhost_common'   => '%v %h %l %u %t \\\"%r\\\" %>s %b',
+              'vhost_combined' => '%v %h %l %u %t \\\"%r\\\" %>s %b \\\"%{Referer}i\\\" \\\"%{User-agent}i\\\"',
+            }
+          }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common' }
+      it { is_expected.to contain 'LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined' }
+    end
+  end
+
+
+  describe 'keepalive' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = "class { 'apache': keepalive => 'On', keepalive_timeout => '30', max_keepalive_requests => '200' }"
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'KeepAlive On' }
+      it { is_expected.to contain 'KeepAliveTimeout 30' }
+      it { is_expected.to contain 'MaxKeepAliveRequests 200' }
+    end
+  end
+
+  describe 'logging' do
+    describe 'setup' do
+      it 'applies cleanly' do
+        pp = <<-EOS
+          if $::osfamily == 'RedHat' and "$::selinux" == "true" {
+            $semanage_package = $::operatingsystemmajrelease ? {
+              '5'     => 'policycoreutils',
+              default => 'policycoreutils-python',
+            }
+
+            package { $semanage_package: ensure => installed }
+            exec { 'set_apache_defaults':
+              command => 'semanage fcontext -a -t httpd_log_t "/apache_spec(/.*)?"',
+              path    => '/bin:/usr/bin/:/sbin:/usr/sbin',
+              require => Package[$semanage_package],
+            }
+            exec { 'restorecon_apache':
+              command => 'restorecon -Rv /apache_spec',
+              path    => '/bin:/usr/bin/:/sbin:/usr/sbin',
+              before  => Service['httpd'],
+              require => Class['apache'],
+            }
+          }
+          file { '/apache_spec': ensure => directory, }
+          class { 'apache': logroot => '/apache_spec' }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe file("/apache_spec/#{$error_log}") do
+      it { is_expected.to be_file }
+    end
+  end
+
+  describe 'ports_file' do
+    it 'applys cleanly' do
+      pp = <<-EOS
+        file { '/apache_spec': ensure => directory, }
+        class { 'apache':
+          ports_file     => '/apache_spec/ports_file',
+          ip             => '10.1.1.1',
+          service_ensure => stopped
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/apache_spec/ports_file') do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'Listen 10.1.1.1' }
+    end
+  end
+
+  describe 'server_tokens' do
+    it 'applys cleanly' do
+      pp = <<-EOS
+        class { 'apache':
+          server_tokens  => 'Minor',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'ServerTokens Minor' }
+    end
+  end
+
+  describe 'server_signature' do
+    it 'applys cleanly' do
+      pp = <<-EOS
+        class { 'apache':
+          server_signature  => 'testsig',
+          service_ensure    => stopped,
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'ServerSignature testsig' }
+    end
+  end
+
+  describe 'trace_enable' do
+    it 'applys cleanly' do
+      pp = <<-EOS
+        class { 'apache':
+          trace_enable  => 'Off',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file($conf_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'TraceEnable Off' }
+    end
+  end
+
+  describe 'package_ensure' do
+    it 'applys cleanly' do
+      pp = <<-EOS
+        class { 'apache':
+          package_ensure  => present,
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe package($package_name) do
+      it { is_expected.to be_installed }
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/apache_ssl_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,100 @@
+require 'spec_helper_acceptance'
+require_relative './version.rb'
+
+case fact('osfamily')
+when 'RedHat'
+  vhostd = '/etc/httpd/conf.d'
+when 'Debian'
+  vhostd = '/etc/apache2/sites-available'
+end
+
+describe 'apache ssl', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+
+  describe 'ssl parameters' do
+    it 'runs without error' do
+      pp = <<-EOS
+        class { 'apache':
+          service_ensure        => stopped,
+          default_ssl_vhost     => true,
+          default_ssl_cert      => '/tmp/ssl_cert',
+          default_ssl_key       => '/tmp/ssl_key',
+          default_ssl_chain     => '/tmp/ssl_chain',
+          default_ssl_ca        => '/tmp/ssl_ca',
+          default_ssl_crl_path  => '/tmp/ssl_crl_path',
+          default_ssl_crl       => '/tmp/ssl_crl',
+          default_ssl_crl_check => 'chain',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{vhostd}/15-default-ssl.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'SSLCertificateFile      "/tmp/ssl_cert"' }
+      it { is_expected.to contain 'SSLCertificateKeyFile   "/tmp/ssl_key"' }
+      it { is_expected.to contain 'SSLCertificateChainFile "/tmp/ssl_chain"' }
+      it { is_expected.to contain 'SSLCACertificateFile    "/tmp/ssl_ca"' }
+      it { is_expected.to contain 'SSLCARevocationPath     "/tmp/ssl_crl_path"' }
+      it { is_expected.to contain 'SSLCARevocationFile     "/tmp/ssl_crl"' }
+      if $apache_version == '2.4'
+        it { is_expected.to contain 'SSLCARevocationCheck    "chain"' }
+      else
+        it { is_expected.not_to contain 'SSLCARevocationCheck' }
+      end
+    end
+  end
+
+  describe 'vhost ssl parameters' do
+    it 'runs without error' do
+      pp = <<-EOS
+        class { 'apache':
+          service_ensure       => stopped,
+        }
+
+        apache::vhost { 'test_ssl':
+          docroot              => '/tmp/test',
+          ssl                  => true,
+          ssl_cert             => '/tmp/ssl_cert',
+          ssl_key              => '/tmp/ssl_key',
+          ssl_chain            => '/tmp/ssl_chain',
+          ssl_ca               => '/tmp/ssl_ca',
+          ssl_crl_path         => '/tmp/ssl_crl_path',
+          ssl_crl              => '/tmp/ssl_crl',
+          ssl_crl_check        => 'chain',
+          ssl_certs_dir        => '/tmp',
+          ssl_protocol         => 'test',
+          ssl_cipher           => 'test',
+          ssl_honorcipherorder => 'test',
+          ssl_verify_client    => 'test',
+          ssl_verify_depth     => 'test',
+          ssl_options          => ['test', 'test1'],
+          ssl_proxyengine      => true,
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{vhostd}/25-test_ssl.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'SSLCertificateFile      "/tmp/ssl_cert"' }
+      it { is_expected.to contain 'SSLCertificateKeyFile   "/tmp/ssl_key"' }
+      it { is_expected.to contain 'SSLCertificateChainFile "/tmp/ssl_chain"' }
+      it { is_expected.to contain 'SSLCACertificateFile    "/tmp/ssl_ca"' }
+      it { is_expected.to contain 'SSLCARevocationPath     "/tmp/ssl_crl_path"' }
+      it { is_expected.to contain 'SSLCARevocationFile     "/tmp/ssl_crl"' }
+      it { is_expected.to contain 'SSLProxyEngine On' }
+      it { is_expected.to contain 'SSLProtocol             test' }
+      it { is_expected.to contain 'SSLCipherSuite          test' }
+      it { is_expected.to contain 'SSLHonorCipherOrder     test' }
+      it { is_expected.to contain 'SSLVerifyClient         test' }
+      it { is_expected.to contain 'SSLVerifyDepth          test' }
+      it { is_expected.to contain 'SSLOptions test test1' }
+      if $apache_version == '2.4'
+        it { is_expected.to contain 'SSLCARevocationCheck    "chain"' }
+      else
+        it { is_expected.not_to contain 'SSLCARevocationCheck' }
+      end
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/class_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,88 @@
+require 'spec_helper_acceptance'
+
+describe 'apache class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  case fact('osfamily')
+  when 'RedHat'
+    package_name = 'httpd'
+    service_name = 'httpd'
+  when 'Debian'
+    package_name = 'apache2'
+    service_name = 'apache2'
+  when 'FreeBSD'
+    package_name = 'apache24'
+    service_name = 'apache24'
+  when 'Gentoo'
+    package_name = 'www-servers/apache'
+    service_name = 'apache2'
+  end
+
+  context 'default parameters' do
+    it 'should work with no errors' do
+      pp = <<-EOS
+      class { 'apache': }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    describe package(package_name) do
+      it { is_expected.to be_installed }
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe port(80) do
+      it { should be_listening }
+    end
+  end
+
+  context 'custom site/mod dir parameters' do
+    # Using puppet_apply as a helper
+    it 'should work with no errors' do
+      pp = <<-EOS
+      if $::osfamily == 'RedHat' and "$::selinux" == "true" {
+        $semanage_package = $::operatingsystemmajrelease ? {
+          '5'     => 'policycoreutils',
+          default => 'policycoreutils-python',
+        }
+
+        package { $semanage_package: ensure => installed }
+        exec { 'set_apache_defaults':
+          command     => 'semanage fcontext -a -t httpd_sys_content_t "/apache_spec(/.*)?"',
+          path        => '/bin:/usr/bin/:/sbin:/usr/sbin',
+          subscribe   => Package[$semanage_package],
+          refreshonly => true,
+        }
+        exec { 'restorecon_apache':
+          command     => 'restorecon -Rv /apache_spec',
+          path        => '/bin:/usr/bin/:/sbin:/usr/sbin',
+          before      => Service['httpd'],
+          require     => Class['apache'],
+          subscribe   => Exec['set_apache_defaults'],
+          refreshonly => true,
+        }
+      }
+      file { '/apache_spec': ensure => directory, }
+      file { '/apache_spec/apache_custom': ensure => directory, }
+      class { 'apache':
+        mod_dir   => '/apache_spec/apache_custom/mods',
+        vhost_dir => '/apache_spec/apache_custom/vhosts',
+      }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/custom_config_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,76 @@
+require 'spec_helper_acceptance'
+require_relative './version.rb'
+
+describe 'apache::custom_config define', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  context 'invalid config' do
+    it 'should not add the config' do
+      pp = <<-EOS
+        class { 'apache': }
+        apache::custom_config { 'acceptance_test':
+          content => 'INVALID',
+        }
+      EOS
+
+      apply_manifest(pp, :expect_failures => true)
+    end
+
+    describe file("#{$confd_dir}/25-acceptance_test.conf") do
+      it { is_expected.not_to be_file }
+    end
+  end
+
+  context 'valid config' do
+    it 'should add the config' do
+      pp = <<-EOS
+        class { 'apache': }
+        apache::custom_config { 'acceptance_test':
+          content => '# just a comment',
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$confd_dir}/25-acceptance_test.conf") do
+      it { is_expected.to contain '# just a comment' }
+    end
+  end
+
+  describe 'custom_config without priority prefix' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        apache::custom_config { 'prefix_test':
+          priority => false,
+          content => '# just a comment',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$confd_dir}/prefix_test.conf") do
+      it { is_expected.to be_file }
+    end
+  end
+
+  describe 'custom_config only applied after configs are written' do
+    it 'applies in the right order' do
+      pp = <<-EOS
+        class { 'apache': }
+
+        apache::custom_config { 'ordering_test':
+          content => '# just a comment',
+        }
+
+        # Try to wedge the apache::custom_config call between when httpd.conf is written and
+        # ports.conf is written. This should trigger a dependency cycle
+        File["#{$conf_file}"] -> Apache::Custom_config['ordering_test'] -> File["#{$ports_file}"]
+      EOS
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/Found 1 dependency cycle/i)
+    end
+
+    describe file("#{$confd_dir}/25-ordering_test.conf") do
+      it { is_expected.not_to be_file }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/default_mods_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,123 @@
+require 'spec_helper_acceptance'
+
+case fact('osfamily')
+when 'RedHat'
+  mod_dir     = '/etc/httpd/conf.d'
+  servicename = 'httpd'
+when 'Debian'
+  mod_dir     = '/etc/apache2/mods-available'
+  servicename = 'apache2'
+when 'FreeBSD'
+  mod_dir     = '/usr/local/etc/apache24/Modules'
+  servicename = 'apache24'
+when 'Gentoo'
+  mod_dir     = '/etc/apache2/modules.d'
+  servicename = 'apache2'
+end
+
+describe 'apache::default_mods class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  describe 'no default mods' do
+    # Using puppet_apply as a helper
+    it 'should apply with no errors' do
+      pp = <<-EOS
+        class { 'apache':
+          default_mods => false,
+        }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    describe service(servicename) do
+      it { is_expected.to be_running }
+    end
+  end
+
+  describe 'no default mods and failing' do
+    # Using puppet_apply as a helper
+    it 'should apply with errors' do
+      pp = <<-EOS
+        class { 'apache':
+          default_mods => false,
+        }
+        apache::vhost { 'defaults.example.com':
+          docroot => '/var/www/defaults',
+          aliases => {
+            alias => '/css',
+            path  => '/var/www/css',
+          },
+          setenv  => 'TEST1 one',
+        }
+      EOS
+
+      apply_manifest(pp, { :expect_failures => true })
+    end
+
+    # Are these the same?
+    describe service(servicename) do
+      it { is_expected.not_to be_running }
+    end
+    describe "service #{servicename}" do
+      it 'should not be running' do
+        shell("pidof #{servicename}", {:acceptable_exit_codes => 1})
+      end
+    end
+  end
+
+  describe 'alternative default mods' do
+    # Using puppet_apply as a helper
+    it 'should apply with no errors' do
+      pp = <<-EOS
+        class { 'apache':
+          default_mods => [
+            'info',
+            'alias',
+            'mime',
+            'env',
+            'expires',
+          ],
+        }
+        apache::vhost { 'defaults.example.com':
+          docroot => '/var/www/defaults',
+          aliases => {
+            alias => '/css',
+            path  => '/var/www/css',
+          },
+          setenv  => 'TEST1 one',
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+      shell('sleep 10')
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    describe service(servicename) do
+      it { is_expected.to be_running }
+    end
+  end
+
+  describe 'change loadfile name' do
+    it 'should apply with no errors' do
+      pp = <<-EOS
+        class { 'apache': default_mods => false }
+        ::apache::mod { 'auth_basic':
+          loadfile_name => 'zz_auth_basic.load',
+        }
+      EOS
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    describe service(servicename) do
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{mod_dir}/zz_auth_basic.load") do
+      it { is_expected.to be_file }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/itk_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+require 'spec_helper_acceptance'
+
+case fact('osfamily')
+when 'Debian'
+  service_name = 'apache2'
+when 'FreeBSD'
+  service_name = 'apache24'
+else
+  # Not implemented yet
+  service_name = :skip
+end
+
+describe 'apache::mod::itk class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) or service_name.equal? :skip do
+  describe 'running puppet code' do
+    # Using puppet_apply as a helper
+    it 'should work with no errors' do
+      pp = <<-EOS
+          class { 'apache':
+            mpm_module => 'itk',
+          }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+  end
+
+  describe service(service_name) do
+    it { is_expected.to be_running }
+    it { is_expected.to be_enabled }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/mod_dav_svn_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,62 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::mod::dav_svn class', :unless => (fact('operatingsystem') == 'OracleLinux' and fact('operatingsystemmajrelease') == '7') do
+  case fact('osfamily')
+  when 'Debian'
+    mod_dir             = '/etc/apache2/mods-available'
+    service_name        = 'apache2'
+    if fact('operatingsystemmajrelease') == '6' or fact('operatingsystemmajrelease') == '10.04' or fact('operatingsystemrelease') == '10.04'
+      authz_svn_load_file = 'dav_svn_authz_svn.load'
+    else
+      authz_svn_load_file = 'authz_svn.load'
+    end
+  when 'RedHat'
+    mod_dir             = '/etc/httpd/conf.d'
+    service_name        = 'httpd'
+    authz_svn_load_file = 'dav_svn_authz_svn.load'
+  when 'FreeBSD'
+    mod_dir             = '/usr/local/etc/apache24/Modules'
+    service_name        = 'apache24'
+    authz_svn_load_file = 'dav_svn_authz_svn.load'
+  end
+
+  context "default dav_svn config" do
+    it 'succeeds in puppeting dav_svn' do
+      pp= <<-EOS
+        class { 'apache': }
+        include apache::mod::dav_svn
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{mod_dir}/dav_svn.load") do
+      it { is_expected.to contain "LoadModule dav_svn_module" }
+    end
+  end
+
+  context "dav_svn with enabled authz_svn config" do
+    it 'succeeds in puppeting dav_svn' do
+      pp= <<-EOS
+        class { 'apache': }
+        class { 'apache::mod::dav_svn':
+            authz_svn_enabled => true,
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{mod_dir}/#{authz_svn_load_file}") do
+      it { is_expected.to contain "LoadModule authz_svn_module" }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/mod_deflate_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,43 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::mod::deflate class' do
+  case fact('osfamily')
+  when 'Debian'
+    mod_dir      = '/etc/apache2/mods-available'
+    service_name = 'apache2'
+  when 'RedHat'
+    mod_dir      = '/etc/httpd/conf.d'
+    service_name = 'httpd'
+  when 'FreeBSD'
+    mod_dir      = '/usr/local/etc/apache24/Modules'
+    service_name = 'apache24'
+  when 'Gentoo'
+    mod_dir      = '/etc/apache2/modules.d'
+    service_name = 'apache2'
+  end
+
+  context "default deflate config" do
+    it 'succeeds in puppeting deflate' do
+      pp= <<-EOS
+        class { 'apache': }
+        include apache::mod::deflate
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{mod_dir}/deflate.conf") do
+      it { is_expected.to contain "AddOutputFilterByType DEFLATE text/html text/plain text/xml" }
+      it { is_expected.to contain "AddOutputFilterByType DEFLATE text/css" }
+      it { is_expected.to contain "AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript" }
+      it { is_expected.to contain "AddOutputFilterByType DEFLATE application/rss+xml" }
+      it { is_expected.to contain "DeflateFilterNote Input instream" }
+      it { is_expected.to contain "DeflateFilterNote Output outstream" }
+      it { is_expected.to contain "DeflateFilterNote Ratio ratio" }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/mod_fcgid_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,57 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::mod::fcgid class', :unless => (UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) or (fact('operatingsystem') == 'OracleLinux' and fact('operatingsystemmajrelease') == '7')) do
+  context "default fcgid config", :if => (fact('osfamily') == 'RedHat' and fact('operatingsystemmajrelease') != '5') do
+    it 'succeeds in puppeting fcgid' do
+      pp = <<-EOS
+        class { 'epel': } # mod_fcgid lives in epel
+        class { 'apache': }
+        class { 'apache::mod::php': } # For /usr/bin/php-cgi
+        class { 'apache::mod::fcgid':
+          options => {
+            'FcgidIPCDir'  => '/var/run/fcgidsock',
+          },
+        }
+        apache::vhost { 'fcgid.example.com':
+          port        => '80',
+          docroot     => '/var/www/fcgid',
+          directories => {
+            path        => '/var/www/fcgid',
+            options     => '+ExecCGI',
+            addhandlers => {
+              handler    => 'fcgid-script',
+              extensions => '.php',
+            },
+            fcgiwrapper => {
+              command => '/usr/bin/php-cgi',
+              suffix  => '.php',
+            }
+          },
+        }
+        file { '/var/www/fcgid/index.php':
+          ensure  => file,
+          owner   => 'root',
+          group   => 'root',
+          content => "<?php echo 'Hello world'; ?>\\n",
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service('httpd') do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    it 'should answer to fcgid.example.com' do
+      shell("/usr/bin/curl -H 'Host: fcgid.example.com' 127.0.0.1:80") do |r|
+        expect(r.stdout).to match(/^Hello world$/)
+        expect(r.exit_code).to eq(0)
+      end
+    end
+
+    it 'should run a php-cgi process' do
+      shell("pgrep -u apache php-cgi", :acceptable_exit_codes => [0])
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/mod_mime_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::mod::mime class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  case fact('osfamily')
+  when 'Debian'
+    mod_dir      = '/etc/apache2/mods-available'
+    service_name = 'apache2'
+  when 'RedHat'
+    mod_dir      = '/etc/httpd/conf.d'
+    service_name = 'httpd'
+  when 'FreeBSD'
+    mod_dir      = '/usr/local/etc/apache24/Modules'
+    service_name = 'apache24'
+  when 'Gentoo'
+    mod_dir      = '/etc/apache2/modules.d'
+    service_name = 'apache2'
+  end
+
+  context "default mime config" do
+    it 'succeeds in puppeting mime' do
+      pp= <<-EOS
+        class { 'apache': }
+        include apache::mod::mime
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{mod_dir}/mime.conf") do
+      it { is_expected.to contain "AddType application/x-compress .Z" }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/mod_negotiation_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,84 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::mod::negotiation class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  case fact('osfamily')
+  when 'Debian'
+    vhost_dir    = '/etc/apache2/sites-enabled'
+    mod_dir      = '/etc/apache2/mods-available'
+    service_name = 'apache2'
+  when 'RedHat'
+    vhost_dir    = '/etc/httpd/conf.d'
+    mod_dir      = '/etc/httpd/conf.d'
+    service_name = 'httpd'
+  when 'FreeBSD'
+    vhost_dir    = '/usr/local/etc/apache24/Vhosts'
+    mod_dir      = '/usr/local/etc/apache24/Modules'
+    service_name = 'apache24'
+  when 'Gentoo'
+    vhost_dir    = '/etc/apache2/vhosts.d'
+    mod_dir      = '/etc/apache2/modules.d'
+    service_name = 'apache2'
+  end
+
+  context "default negotiation config" do
+    it 'succeeds in puppeting negotiation' do
+      pp= <<-EOS
+        class { '::apache': default_mods => false }
+        class { '::apache::mod::negotiation': }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{mod_dir}/negotiation.conf") do
+      it { should contain "LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW
+ForceLanguagePriority Prefer Fallback" }
+    end
+
+    describe service(service_name) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+  end
+
+  context "with alternative force_language_priority" do
+    it 'succeeds in puppeting negotiation' do
+      pp= <<-EOS
+        class { '::apache': default_mods => false }
+        class { '::apache::mod::negotiation':
+          force_language_priority => 'Prefer',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{mod_dir}/negotiation.conf") do
+      it { should contain "ForceLanguagePriority Prefer" }
+    end
+
+    describe service(service_name) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+  end
+
+  context "with alternative language_priority" do
+    it 'succeeds in puppeting negotiation' do
+      pp= <<-EOS
+        class { '::apache': default_mods => false }
+        class { '::apache::mod::negotiation':
+          language_priority => [ 'en', 'es' ],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{mod_dir}/negotiation.conf") do
+      it { should contain "LanguagePriority en es" }
+    end
+
+    describe service(service_name) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/mod_pagespeed_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,89 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::mod::pagespeed class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  case fact('osfamily')
+  when 'Debian'
+    vhost_dir    = '/etc/apache2/sites-enabled'
+    mod_dir      = '/etc/apache2/mods-available'
+    service_name = 'apache2'
+  when 'RedHat'
+    vhost_dir    = '/etc/httpd/conf.d'
+    mod_dir      = '/etc/httpd/conf.d'
+    service_name = 'httpd'
+  when 'FreeBSD'
+    vhost_dir    = '/usr/local/etc/apache24/Vhosts'
+    mod_dir      = '/usr/local/etc/apache24/Modules'
+    service_name = 'apache24'
+  when 'Gentoo'
+    vhost_dir    = '/etc/apache2/vhosts.d'
+    mod_dir      = '/etc/apache2/modules.d'
+    service_name = 'apache2'
+  end
+
+  context "default pagespeed config" do
+    it 'succeeds in puppeting pagespeed' do
+      pp= <<-EOS
+        if $::osfamily == 'Debian' {
+          class { 'apt': }
+
+          apt::source { 'mod-pagespeed':
+            key         => '7FAC5991',
+            key_server  => 'pgp.mit.edu',
+            location    => 'http://dl.google.com/linux/mod-pagespeed/deb/',
+            release     => 'stable',
+            repos       => 'main',
+            include_src => false,
+            before      => Class['apache'],
+          }
+        } elsif $::osfamily == 'RedHat' {
+         yumrepo { 'mod-pagespeed':
+          baseurl  => "http://dl.google.com/linux/mod-pagespeed/rpm/stable/$::architecture",
+            enabled  => 1,
+            gpgcheck => 1,
+            gpgkey   => 'https://dl-ssl.google.com/linux/linux_signing_key.pub',
+            before   => Class['apache'],
+          }
+        }
+
+        class { 'apache':
+          mpm_module => 'prefork',
+        }
+        class { 'apache::mod::pagespeed':
+          enable_filters  => ['remove_comments'],
+          disable_filters => ['extend_cache'],
+          forbid_filters  => ['rewrite_javascript'],
+        }
+        apache::vhost { 'pagespeed.example.com':
+          port    => '80',
+          docroot => '/var/www/pagespeed',
+        }
+        host { 'pagespeed.example.com': ip => '127.0.0.1', }
+        file { '/var/www/pagespeed/index.html':
+          ensure  => file,
+          content => "<html>\n<!-- comment -->\n<body>\n<p>Hello World!</p>\n</body>\n</html>",
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{mod_dir}/pagespeed.conf") do
+      it { is_expected.to contain "AddOutputFilterByType MOD_PAGESPEED_OUTPUT_FILTER text/html" }
+      it { is_expected.to contain "ModPagespeedEnableFilters remove_comments" }
+      it { is_expected.to contain "ModPagespeedDisableFilters extend_cache" }
+      it { is_expected.to contain "ModPagespeedForbidFilters rewrite_javascript" }
+    end
+
+    it 'should answer to pagespeed.example.com and include <head/> and be stripped of comments by mod_pagespeed' do
+      shell("/usr/bin/curl pagespeed.example.com:80") do |r|
+        expect(r.stdout).to match(/<head\/>/)
+        expect(r.stdout).not_to match(/<!-- comment -->/)
+        expect(r.exit_code).to eq(0)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/mod_passenger_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,198 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::mod::passenger class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  case fact('osfamily')
+  when 'Debian'
+    service_name = 'apache2'
+    mod_dir = '/etc/apache2/mods-available/'
+    conf_file = "#{mod_dir}passenger.conf"
+    load_file = "#{mod_dir}zpassenger.load"
+
+    case fact('operatingsystem')
+    when 'Ubuntu'
+      case fact('lsbdistrelease')
+      when '10.04'
+        passenger_root = '/usr'
+        passenger_ruby = '/usr/bin/ruby'
+      when '12.04'
+        passenger_root = '/usr'
+        passenger_ruby = '/usr/bin/ruby'
+      when '14.04'
+        passenger_root         = '/usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini'
+        passenger_ruby         = '/usr/bin/ruby'
+        passenger_default_ruby = '/usr/bin/ruby'
+      else
+        # This may or may not work on Ubuntu releases other than the above
+        passenger_root = '/usr'
+        passenger_ruby = '/usr/bin/ruby'
+      end
+    when 'Debian'
+      case fact('lsbdistcodename')
+      when 'wheezy'
+        passenger_root = '/usr'
+        passenger_ruby = '/usr/bin/ruby'
+      when 'jessie'
+        passenger_root         = '/usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini'
+        passenger_ruby         = '/usr/bin/ruby'
+        passenger_default_ruby = '/usr/bin/ruby'
+      else
+        # This may or may not work on Debian releases other than the above
+        passenger_root = '/usr'
+        passenger_ruby = '/usr/bin/ruby'
+      end
+    end
+
+    passenger_module_path = '/usr/lib/apache2/modules/mod_passenger.so'
+    rackapp_user = 'www-data'
+    rackapp_group = 'www-data'
+  when 'RedHat'
+    service_name = 'httpd'
+    mod_dir = '/etc/httpd/conf.d/'
+    conf_file = "#{mod_dir}passenger.conf"
+    load_file = "#{mod_dir}zpassenger.load"
+    # sometimes installs as 3.0.12, sometimes as 3.0.19 - so just check for the stable part
+    passenger_root = '/usr/lib/ruby/gems/1.8/gems/passenger-3.0.1'
+    passenger_ruby = '/usr/bin/ruby'
+    passenger_tempdir = '/var/run/rubygem-passenger'
+    passenger_module_path = 'modules/mod_passenger.so'
+    rackapp_user = 'apache'
+    rackapp_group = 'apache'
+  end
+
+  pp_rackapp = <<-EOS
+          /* a simple ruby rack 'hellow world' app */
+          file { '/var/www/passenger':
+            ensure  => directory,
+            owner   => '#{rackapp_user}',
+            group   => '#{rackapp_group}',
+            require => Class['apache::mod::passenger'],
+          }
+          file { '/var/www/passenger/config.ru':
+            ensure  => file,
+            owner   => '#{rackapp_user}',
+            group   => '#{rackapp_group}',
+            content => "app = proc { |env| [200, { \\"Content-Type\\" => \\"text/html\\" }, [\\"hello <b>world</b>\\"]] }\\nrun app",
+            require => File['/var/www/passenger'] ,
+          }
+          apache::vhost { 'passenger.example.com':
+            port    => '80',
+            docroot => '/var/www/passenger/public',
+            docroot_group => '#{rackapp_group}' ,
+            docroot_owner => '#{rackapp_user}' ,
+            custom_fragment => "PassengerRuby  #{passenger_ruby}\\nRailsEnv  development" ,
+            require => File['/var/www/passenger/config.ru'] ,
+          }
+          host { 'passenger.example.com': ip => '127.0.0.1', }
+  EOS
+
+  case fact('osfamily')
+  when 'Debian'
+    context "default passenger config" do
+      it 'succeeds in puppeting passenger' do
+        pp = <<-EOS
+          /* stock apache and mod_passenger */
+          class { 'apache': }
+          class { 'apache::mod::passenger': }
+          #{pp_rackapp}
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe service(service_name) do
+        it { is_expected.to be_enabled }
+        it { is_expected.to be_running }
+      end
+
+      describe file(conf_file) do
+        it { is_expected.to contain "PassengerRoot \"#{passenger_root}\"" }
+
+        case fact('operatingsystem')
+        when 'Ubuntu'
+          case fact('lsbdistrelease')
+          when '10.04'
+            it { is_expected.to contain "PassengerRuby \"#{passenger_ruby}\"" }
+            it { is_expected.not_to contain "/PassengerDefaultRuby/" }
+          when '12.04'
+            it { is_expected.to contain "PassengerRuby \"#{passenger_ruby}\"" }
+            it { is_expected.not_to contain "/PassengerDefaultRuby/" }
+          when '14.04'
+            it { is_expected.to contain "PassengerDefaultRuby \"#{passenger_ruby}\"" }
+            it { is_expected.not_to contain "/PassengerRuby/" }
+          else
+            # This may or may not work on Ubuntu releases other than the above
+            it { is_expected.to contain "PassengerRuby \"#{passenger_ruby}\"" }
+            it { is_expected.not_to contain "/PassengerDefaultRuby/" }
+          end
+        when 'Debian'
+          case fact('lsbdistcodename')
+          when 'wheezy'
+            it { is_expected.to contain "PassengerRuby \"#{passenger_ruby}\"" }
+            it { is_expected.not_to contain "/PassengerDefaultRuby/" }
+          when 'jessie'
+            it { is_expected.to contain "PassengerDefaultRuby \"#{passenger_ruby}\"" }
+            it { is_expected.not_to contain "/PassengerRuby/" }
+          else
+            # This may or may not work on Debian releases other than the above
+            it { is_expected.to contain "PassengerRuby \"#{passenger_ruby}\"" }
+            it { is_expected.not_to contain "/PassengerDefaultRuby/" }
+          end
+        end
+      end
+
+      describe file(load_file) do
+        it { is_expected.to contain "LoadModule passenger_module #{passenger_module_path}" }
+      end
+
+      it 'should output status via passenger-memory-stats' do
+        shell("PATH=/usr/bin:$PATH /usr/sbin/passenger-memory-stats") do |r|
+          expect(r.stdout).to match(/Apache processes/)
+          expect(r.stdout).to match(/Nginx processes/)
+          expect(r.stdout).to match(/Passenger processes/)
+
+          # passenger-memory-stats output on newer Debian/Ubuntu verions do not contain
+          # these two lines
+          unless ((fact('operatingsystem') == 'Ubuntu' && fact('operatingsystemrelease') == '14.04') or
+                 (fact('operatingsystem') == 'Debian' && fact('operatingsystemrelease') == '8.0'))
+            expect(r.stdout).to match(/### Processes: [0-9]+/)
+            expect(r.stdout).to match(/### Total private dirty RSS: [0-9\.]+ MB/)
+          end
+
+          expect(r.exit_code).to eq(0)
+        end
+      end
+
+      # passenger-status fails under stock ubuntu-server-12042-x64 + mod_passenger,
+      # even when the passenger process is successfully installed and running
+      unless fact('operatingsystem') == 'Ubuntu' && fact('operatingsystemrelease') == '12.04'
+        it 'should output status via passenger-status' do
+          # xml output not available on ubunutu <= 10.04, so sticking with default pool output
+          shell("PATH=/usr/bin:$PATH /usr/sbin/passenger-status") do |r|
+            # spacing may vary
+            expect(r.stdout).to match(/[\-]+ General information [\-]+/)
+            if fact('operatingsystem') == 'Ubuntu' && fact('operatingsystemrelease') == '14.04'
+              expect(r.stdout).to match(/Max pool size[ ]+: [0-9]+/)
+              expect(r.stdout).to match(/Processes[ ]+: [0-9]+/)
+              expect(r.stdout).to match(/Requests in top-level queue[ ]+: [0-9]+/)
+            else
+              expect(r.stdout).to match(/max[ ]+= [0-9]+/)
+              expect(r.stdout).to match(/count[ ]+= [0-9]+/)
+              expect(r.stdout).to match(/active[ ]+= [0-9]+/)
+              expect(r.stdout).to match(/inactive[ ]+= [0-9]+/)
+              expect(r.stdout).to match(/Waiting on global queue: [0-9]+/)
+            end
+
+            expect(r.exit_code).to eq(0)
+          end
+        end
+      end
+
+      it 'should answer to passenger.example.com' do
+        shell("/usr/bin/curl passenger.example.com:80") do |r|
+          expect(r.stdout).to match(/^hello <b>world<\/b>$/)
+          expect(r.exit_code).to eq(0)
+        end
+      end
+
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/mod_php_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,143 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::mod::php class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  case fact('osfamily')
+  when 'Debian'
+    vhost_dir    = '/etc/apache2/sites-enabled'
+    mod_dir      = '/etc/apache2/mods-available'
+    service_name = 'apache2'
+  when 'RedHat'
+    vhost_dir    = '/etc/httpd/conf.d'
+    mod_dir      = '/etc/httpd/conf.d'
+    service_name = 'httpd'
+  when 'FreeBSD'
+    vhost_dir    = '/usr/local/etc/apache24/Vhosts'
+    mod_dir      = '/usr/local/etc/apache24/Modules'
+    service_name = 'apache24'
+  when 'Gentoo'
+    vhost_dir    = '/etc/apache2/vhosts.d'
+    mod_dir      = '/etc/apache2/modules.d'
+    service_name = 'apache2'
+  end
+
+  context "default php config" do
+    it 'succeeds in puppeting php' do
+      pp= <<-EOS
+        class { 'apache':
+          mpm_module => 'prefork',
+        }
+        class { 'apache::mod::php': }
+        apache::vhost { 'php.example.com':
+          port    => '80',
+          docroot => '/var/www/php',
+        }
+        host { 'php.example.com': ip => '127.0.0.1', }
+        file { '/var/www/php/index.php':
+          ensure  => file,
+          content => "<?php phpinfo(); ?>\\n",
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{mod_dir}/php5.conf") do
+      it { is_expected.to contain "DirectoryIndex index.php" }
+    end
+
+    it 'should answer to php.example.com' do
+      shell("/usr/bin/curl php.example.com:80") do |r|
+        expect(r.stdout).to match(/PHP Version/)
+        expect(r.exit_code).to eq(0)
+      end
+    end
+  end
+
+  context "custom extensions, php_flag, php_value, php_admin_flag, and php_admin_value" do
+    it 'succeeds in puppeting php' do
+      pp= <<-EOS
+        class { 'apache':
+          mpm_module => 'prefork',
+        }
+        class { 'apache::mod::php':
+          extensions => ['.php','.php5'],
+        }
+        apache::vhost { 'php.example.com':
+          port             => '80',
+          docroot          => '/var/www/php',
+          php_values       => { 'include_path' => '.:/usr/share/pear:/usr/bin/php', },
+          php_flags        => { 'display_errors' => 'on', },
+          php_admin_values => { 'open_basedir' => '/var/www/php/:/usr/share/pear/', },
+          php_admin_flags  => { 'engine' => 'on', },
+        }
+        host { 'php.example.com': ip => '127.0.0.1', }
+        file { '/var/www/php/index.php5':
+          ensure  => file,
+          content => "<?php phpinfo(); ?>\\n",
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{vhost_dir}/25-php.example.com.conf") do
+      it { is_expected.to contain "  php_flag display_errors on" }
+      it { is_expected.to contain "  php_value include_path .:/usr/share/pear:/usr/bin/php" }
+      it { is_expected.to contain "  php_admin_flag engine on" }
+      it { is_expected.to contain "  php_admin_value open_basedir /var/www/php/:/usr/share/pear/" }
+    end
+
+    it 'should answer to php.example.com' do
+      shell("/usr/bin/curl php.example.com:80") do |r|
+        expect(r.stdout).to match(/\/usr\/share\/pear\//)
+        expect(r.exit_code).to eq(0)
+      end
+    end
+  end
+
+  context "provide custom config file" do
+    it 'succeeds in puppeting php' do
+      pp= <<-EOS
+        class {'apache':
+          mpm_module => 'prefork',
+        }
+        class {'apache::mod::php':
+          content => '# somecontent',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{mod_dir}/php5.conf") do
+      it { should contain "# somecontent" }
+    end
+  end
+
+  context "provide content and template config file" do
+    it 'succeeds in puppeting php' do
+      pp= <<-EOS
+        class {'apache':
+          mpm_module => 'prefork',
+        }
+        class {'apache::mod::php':
+          content  => '# somecontent',
+          template => 'apache/mod/php5.conf.erb',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{mod_dir}/php5.conf") do
+      it { should contain "# somecontent" }
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/mod_proxy_html_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,41 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::mod::proxy_html class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  case fact('osfamily')
+  when 'Debian'
+    service_name = 'apache2'
+  when 'RedHat'
+    service_name = 'httpd'
+  when 'FreeBSD'
+    service_name = 'apache24'
+  when 'Gentoo'
+    service_name = 'apache2'
+  end
+
+  context "default proxy_html config" do
+    if fact('osfamily') == 'RedHat' and fact('operatingsystemmajrelease') =~ /(5|6)/
+      it 'adds epel' do
+        pp = "class { 'epel': }"
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    it 'succeeds in puppeting proxy_html' do
+      pp= <<-EOS
+        class { 'apache': }
+        class { 'apache::mod::proxy': }
+        class { 'apache::mod::proxy_http': }
+        # mod_proxy_html doesn't exist in RHEL5
+        if $::osfamily == 'RedHat' and $::operatingsystemmajrelease != '5' {
+          class { 'apache::mod::proxy_html': }
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/mod_security_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,247 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::mod::security class', :unless => (UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) or (fact('osfamily') == 'Debian' and (fact('lsbdistcodename') == 'squeeze' or fact('lsbdistcodename') == 'lucid' or fact('lsbdistcodename') == 'precise' or fact('lsbdistcodename') == 'wheezy'))) do
+  case fact('osfamily')
+  when 'Debian'
+    mod_dir      = '/etc/apache2/mods-available'
+    service_name = 'apache2'
+    package_name = 'apache2'
+  when 'RedHat'
+    mod_dir      = '/etc/httpd/conf.d'
+    service_name = 'httpd'
+    package_name = 'httpd'
+  end
+
+  context "default mod_security config" do
+    if fact('osfamily') == 'RedHat' and fact('operatingsystemmajrelease') =~ /(5|6)/
+      it 'adds epel' do
+        pp = "class { 'epel': }"
+        apply_manifest(pp, :catch_failures => true)
+      end
+    elsif fact('osfamily') == 'RedHat' and fact('operatingsystemmajrelease') == '7'
+      it 'changes obsoletes, per PUP-4497' do
+        pp = <<-EOS
+          ini_setting { 'obsoletes':
+            path    => '/etc/yum.conf',
+            section => 'main',
+            setting => 'obsoletes',
+            value   => '0',
+          }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    it 'succeeds in puppeting mod_security' do
+      pp= <<-EOS
+        host { 'modsec.example.com': ip => '127.0.0.1', }
+        class { 'apache': }
+        class { 'apache::mod::security': }
+        apache::vhost { 'modsec.example.com':
+          port    => '80',
+          docroot => '/var/www/html',
+        }
+        file { '/var/www/html/index.html':
+          ensure  => file,
+          content => 'Index page',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+
+      #Need to add a short sleep here because on RHEL6 the service takes a bit longer to init
+      if fact('osfamily') == 'RedHat' and fact('operatingsystemmajrelease') =~ /(5|6)/
+        sleep 5
+      end
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe package(package_name) do
+      it { is_expected.to be_installed }
+    end
+
+    describe file("#{mod_dir}/security.conf") do
+      it { is_expected.to contain "mod_security2.c" }
+    end
+
+    describe 'should be listening on port 80' do
+      it 'should return index page' do
+        shell('/usr/bin/curl -A beaker modsec.example.com:80') do |r|
+          expect(r.stdout).to match(/Index page/)
+          expect(r.exit_code).to eq(0)
+        end
+      end
+
+      it 'should block query with SQL' do
+        shell '/usr/bin/curl -A beaker -f modsec.example.com:80?SELECT%20*FROM%20mysql.users', :acceptable_exit_codes => [22]
+      end
+    end
+
+  end #default mod_security config
+
+  context "mod_security should allow disabling by vhost" do
+    it 'succeeds in puppeting mod_security' do
+      pp= <<-EOS
+        host { 'modsec.example.com': ip => '127.0.0.1', }
+        class { 'apache': }
+        class { 'apache::mod::security': }
+        apache::vhost { 'modsec.example.com':
+          port    => '80',
+          docroot => '/var/www/html',
+        }
+        file { '/var/www/html/index.html':
+          ensure  => file,
+          content => 'Index page',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{mod_dir}/security.conf") do
+      it { is_expected.to contain "mod_security2.c" }
+    end
+
+    it 'should block query with SQL' do
+      shell '/usr/bin/curl -A beaker -f modsec.example.com:80?SELECT%20*FROM%20mysql.users', :acceptable_exit_codes => [22]
+    end
+
+    it 'should disable mod_security per vhost' do
+      pp= <<-EOS
+        class { 'apache': }
+        class { 'apache::mod::security': }
+        apache::vhost { 'modsec.example.com':
+          port                 => '80',
+          docroot              => '/var/www/html',
+          modsec_disable_vhost => true,
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should return index page' do
+      shell('/usr/bin/curl -A beaker -f modsec.example.com:80?SELECT%20*FROM%20mysql.users') do |r|
+        expect(r.stdout).to match(/Index page/)
+        expect(r.exit_code).to eq(0)
+      end
+    end
+  end #mod_security should allow disabling by vhost
+
+  context "mod_security should allow disabling by ip" do
+    it 'succeeds in puppeting mod_security' do
+      pp= <<-EOS
+        host { 'modsec.example.com': ip => '127.0.0.1', }
+        class { 'apache': }
+        class { 'apache::mod::security': }
+        apache::vhost { 'modsec.example.com':
+          port    => '80',
+          docroot => '/var/www/html',
+        }
+        file { '/var/www/html/index.html':
+          ensure  => file,
+          content => 'Index page',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{mod_dir}/security.conf") do
+      it { is_expected.to contain "mod_security2.c" }
+    end
+
+    it 'should block query with SQL' do
+      shell '/usr/bin/curl -A beaker -f modsec.example.com:80?SELECT%20*FROM%20mysql.users', :acceptable_exit_codes => [22]
+    end
+
+    it 'should disable mod_security per vhost' do
+      pp= <<-EOS
+        class { 'apache': }
+        class { 'apache::mod::security': }
+        apache::vhost { 'modsec.example.com':
+          port               => '80',
+          docroot            => '/var/www/html',
+          modsec_disable_ips => [ '127.0.0.1' ],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should return index page' do
+      shell('/usr/bin/curl -A beaker modsec.example.com:80') do |r|
+        expect(r.stdout).to match(/Index page/)
+        expect(r.exit_code).to eq(0)
+      end
+    end
+  end #mod_security should allow disabling by ip
+
+  context "mod_security should allow disabling by id" do
+    it 'succeeds in puppeting mod_security' do
+      pp= <<-EOS
+        host { 'modsec.example.com': ip => '127.0.0.1', }
+        class { 'apache': }
+        class { 'apache::mod::security': }
+        apache::vhost { 'modsec.example.com':
+          port    => '80',
+          docroot => '/var/www/html',
+        }
+        file { '/var/www/html/index.html':
+          ensure  => file,
+          content => 'Index page',
+        }
+        file { '/var/www/html/index2.html':
+          ensure  => file,
+          content => 'Page 2',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service(service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{mod_dir}/security.conf") do
+      it { is_expected.to contain "mod_security2.c" }
+    end
+
+    it 'should block query with SQL' do
+      shell '/usr/bin/curl -A beaker -f modsec.example.com:80?SELECT%20*FROM%20mysql.users', :acceptable_exit_codes => [22]
+    end
+
+    it 'should disable mod_security per vhost' do
+      pp= <<-EOS
+        class { 'apache': }
+        class { 'apache::mod::security': }
+        apache::vhost { 'modsec.example.com':
+          port               => '80',
+          docroot            => '/var/www/html',
+          modsec_disable_ids => [ '950007' ],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should return index page' do
+      shell('/usr/bin/curl -A beaker -f modsec.example.com:80?SELECT%20*FROM%20mysql.users') do |r|
+        expect(r.stdout).to match(/Index page/)
+        expect(r.exit_code).to eq(0)
+      end
+    end
+
+  end #mod_security should allow disabling by id
+
+
+end #apache::mod::security class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/mod_suphp_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,55 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::mod::suphp class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  case fact('operatingsystem')
+    when 'Ubuntu'
+      context "default suphp config" do
+        it 'succeeds in puppeting suphp' do
+          pp = <<-EOS
+class { 'apache':
+  mpm_module => 'prefork',
+}
+host { 'suphp.example.com': ip => '127.0.0.1', }
+apache::vhost { 'suphp.example.com':
+  port    => '80',
+  docroot => '/var/www/suphp',
+}
+file { '/var/www/suphp/index.php':
+  ensure  => file,
+  owner   => 'daemon',
+  group   => 'daemon',
+  content => "<?php echo get_current_user(); ?>\\n",
+  require => File['/var/www/suphp'],
+  before  => Class['apache::mod::php'],
+}
+class { 'apache::mod::php': }
+class { 'apache::mod::suphp': }
+          EOS
+          apply_manifest(pp, :catch_failures => true)
+        end
+
+        describe service('apache2') do
+          it { is_expected.to be_enabled }
+          it { is_expected.to be_running }
+        end
+
+        it 'should answer to suphp.example.com' do
+          timeout = 0
+          loop do
+            r = shell('curl suphp.example.com:80')
+            timeout += 1
+            break if r.stdout =~ /^daemon$/
+            if timeout > 40
+              expect(timeout < 40).to be true
+              break
+            end
+            sleep(1)
+          end
+          shell("/usr/bin/curl suphp.example.com:80") do |r|
+            expect(r.stdout).to match(/^daemon$/)
+            expect(r.exit_code).to eq(0)
+          end
+        end
+      end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/nodesets/centos-70-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  centos-70-x64:
+    roles:
+      - master
+    platform: el-7-x86_64
+    box : puppetlabs/centos-7.0-64-nocm
+    box_url : https://vagrantcloud.com/puppetlabs/boxes/centos-7.0-64-nocm
+    hypervisor : vagrant
+CONFIG:
+  log_level: verbose
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/nodesets/debian-607-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  debian-607-x64:
+    roles:
+      - master
+    platform: debian-6-amd64
+    box : debian-607-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  log_level: debug
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/nodesets/debian-70rc1-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  debian-70rc1-x64:
+    roles:
+      - master
+    platform: debian-7-amd64
+    box : debian-70rc1-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-70rc1-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  log_level: debug
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/nodesets/debian-73-i386.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  debian-73-i386:
+    roles:
+      - master
+    platform: debian-7-i386
+    box : debian-73-i386-virtualbox-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-73-i386-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  log_level: debug
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/nodesets/debian-73-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  debian-73-x64:
+    roles:
+      - master
+    platform: debian-7-amd64
+    box : debian-73-x64-virtualbox-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-73-x64-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  log_level: debug
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/nodesets/default.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-66-x64:
+    roles:
+      - master
+    platform: el-6-x86_64
+    box : puppetlabs/centos-6.6-64-nocm
+    hypervisor : vagrant
+CONFIG:
+  log_level: debug
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/nodesets/fedora-18-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  fedora-18-x64:
+    roles:
+      - master
+    platform: fedora-18-x86_64
+    box : fedora-18-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/fedora-18-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  log_level: debug
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-server-10044-x64:
+    roles:
+      - master
+    platform: ubuntu-10.04-amd64
+    box : ubuntu-server-10044-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-server-12042-x64:
+    roles:
+      - master
+    platform: ubuntu-12.04-amd64
+    box : ubuntu-server-12042-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  ubuntu-server-1310-x64:
+    roles:
+      - master
+    platform: ubuntu-13.10-amd64
+    box : ubuntu-server-1310-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-1310-x64-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  log_level   : debug
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  ubuntu-server-1404-x64:
+    roles:
+      - master
+    platform: ubuntu-14.04-amd64
+    box : puppetlabs/ubuntu-14.04-64-nocm
+    box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm
+    hypervisor : vagrant
+CONFIG:
+  log_level   : debug
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/prefork_worker_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,81 @@
+require 'spec_helper_acceptance'
+
+case fact('osfamily')
+when 'RedHat'
+  servicename = 'httpd'
+when 'Debian'
+  servicename = 'apache2'
+when 'FreeBSD'
+  servicename = 'apache24'
+when 'Gentoo'
+  servicename = 'apache2'
+end
+
+case fact('osfamily')
+when 'FreeBSD'
+  describe 'apache::mod::event class' do
+    describe 'running puppet code' do
+      # Using puppet_apply as a helper
+      it 'should work with no errors' do
+        pp = <<-EOS
+          class { 'apache':
+            mpm_module => 'event',
+          }
+        EOS
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+      end
+    end
+
+    describe service(servicename) do
+      it { is_expected.to be_running }
+      it { is_expected.to be_enabled }
+    end
+  end
+end
+
+describe 'apache::mod::worker class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  describe 'running puppet code' do
+    # Using puppet_apply as a helper
+    it 'should work with no errors' do
+      pp = <<-EOS
+        class { 'apache':
+          mpm_module => 'worker',
+        }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+  end
+
+  describe service(servicename) do
+    it { is_expected.to be_running }
+    it { is_expected.to be_enabled }
+  end
+end
+
+describe 'apache::mod::prefork class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  describe 'running puppet code' do
+    # Using puppet_apply as a helper
+    it 'should work with no errors' do
+      pp = <<-EOS
+        class { 'apache':
+          mpm_module => 'prefork',
+        }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+  end
+
+  describe service(servicename) do
+    it { is_expected.to be_running }
+    it { is_expected.to be_enabled }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/service_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+require 'spec_helper_acceptance'
+
+describe 'apache::service class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  describe 'adding dependencies in between the base class and service class' do
+    it 'should work with no errors' do
+      pp = <<-EOS
+      class { 'apache': }
+      file { '/tmp/test':
+        require => Class['apache'],
+        notify  => Class['apache::service'],
+      }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/unsupported_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+require 'spec_helper_acceptance'
+
+describe 'unsupported distributions and OSes', :if => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  it 'should fail' do
+    pp = <<-EOS
+      class { 'apache': }
+      apache::vhost { 'test.lan':
+        docroot => '/var/www',
+      }
+    EOS
+    expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/unsupported/i)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/version.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,75 @@
+_osfamily               = fact('osfamily')
+_operatingsystem        = fact('operatingsystem')
+_operatingsystemrelease = fact('operatingsystemrelease').to_f
+
+case _osfamily
+when 'RedHat'
+  $confd_dir        = '/etc/httpd/conf.d'
+  $mod_dir          = '/etc/httpd/conf.d'
+  $conf_file        = '/etc/httpd/conf/httpd.conf'
+  $ports_file       = '/etc/httpd/conf/ports.conf'
+  $vhost_dir        = '/etc/httpd/conf.d'
+  $vhost            = '/etc/httpd/conf.d/15-default.conf'
+  $run_dir          = '/var/run/httpd'
+  $service_name     = 'httpd'
+  $package_name     = 'httpd'
+  $error_log        = 'error_log'
+  $suphp_handler    = 'php5-script'
+  $suphp_configpath = 'undef'
+
+  if (_operatingsystem == 'Fedora' and _operatingsystemrelease >= 18) or (_operatingsystem != 'Fedora' and _operatingsystemrelease >= 7)
+    $apache_version = '2.4'
+  else
+    $apache_version = '2.2'
+  end
+when 'Debian'
+  $confd_dir        = '/etc/apache2/conf.d'
+  $mod_dir          = '/etc/apache2/mods-available'
+  $conf_file        = '/etc/apache2/apache2.conf'
+  $ports_file       = '/etc/apache2/ports.conf'
+  $vhost            = '/etc/apache2/sites-available/15-default.conf'
+  $vhost_dir        = '/etc/apache2/sites-enabled'
+  $run_dir          = '/var/run/apache2'
+  $service_name     = 'apache2'
+  $package_name     = 'apache2'
+  $error_log        = 'error.log'
+  $suphp_handler    = 'x-httpd-php'
+  $suphp_configpath = '/etc/php5/apache2'
+
+  if _operatingsystem == 'Ubuntu' and _operatingsystemrelease >= 13.10
+    $apache_version = '2.4'
+  elsif _operatingsystem == 'Debian' and _operatingsystemrelease >= 8.0
+    $apache_version = '2.4'
+  else
+    $apache_version = '2.2'
+  end
+when 'FreeBSD'
+  $confd_dir        = '/usr/local/etc/apache24/Includes'
+  $mod_dir          = '/usr/local/etc/apache24/Modules'
+  $conf_file        = '/usr/local/etc/apache24/httpd.conf'
+  $ports_file       = '/usr/local/etc/apache24/Includes/ports.conf'
+  $vhost            = '/usr/local/etc/apache24/Vhosts/15-default.conf'
+  $vhost_dir        = '/usr/local/etc/apache24/Vhosts'
+  $run_dir          = '/var/run/apache24'
+  $service_name     = 'apache24'
+  $package_name     = 'apache24'
+  $error_log        = 'http-error.log'
+
+  $apache_version = '2.2'
+when 'Gentoo'
+  $confd_dir        = '/etc/apache2/conf.d'
+  $mod_dir          = '/etc/apache2/modules.d'
+  $conf_file        = '/etc/apache2/httpd.conf'
+  $ports_file       = '/etc/apache2/ports.conf'
+  $vhost            = '/etc/apache2/vhosts.d/15-default.conf'
+  $vhost_dir        = '/etc/apache2/vhosts.d'
+  $run_dir          = '/var/run/apache2'
+  $service_name     = 'apache2'
+  $package_name     = 'www-servers/apache'
+  $error_log        = 'http-error.log'
+
+  $apache_version = '2.4'
+else
+  $apache_version = '0'
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/acceptance/vhost_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1390 @@
+require 'spec_helper_acceptance'
+require_relative './version.rb'
+
+describe 'apache::vhost define', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
+  context 'no default vhosts' do
+    it 'should create no default vhosts' do
+      pp = <<-EOS
+        class { 'apache':
+          default_vhost => false,
+          default_ssl_vhost => false,
+          service_ensure => stopped
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/15-default.conf") do
+      it { is_expected.not_to be_file }
+    end
+
+    describe file("#{$vhost_dir}/15-default-ssl.conf") do
+      it { is_expected.not_to be_file }
+    end
+  end
+
+  context "default vhost without ssl" do
+    it 'should create a default vhost config' do
+      pp = <<-EOS
+        class { 'apache': }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/15-default.conf") do
+      it { is_expected.to contain '<VirtualHost \*:80>' }
+    end
+
+    describe file("#{$vhost_dir}/15-default-ssl.conf") do
+      it { is_expected.not_to be_file }
+    end
+  end
+
+  context 'default vhost with ssl' do
+    it 'should create default vhost configs' do
+      pp = <<-EOS
+        file { '#{$run_dir}':
+          ensure  => 'directory',
+          recurse => true,
+        }
+
+        class { 'apache':
+          default_ssl_vhost => true,
+          require => File['#{$run_dir}'],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/15-default.conf") do
+      it { is_expected.to contain '<VirtualHost \*:80>' }
+    end
+
+    describe file("#{$vhost_dir}/15-default-ssl.conf") do
+      it { is_expected.to contain '<VirtualHost \*:443>' }
+      it { is_expected.to contain "SSLEngine on" }
+    end
+  end
+
+  context 'new vhost on port 80' do
+    it 'should configure an apache vhost' do
+      pp = <<-EOS
+        class { 'apache': }
+        file { '#{$run_dir}':
+          ensure  => 'directory',
+          recurse => true,
+        }
+
+        apache::vhost { 'first.example.com':
+          port    => '80',
+          docroot => '/var/www/first',
+          require => File['#{$run_dir}'],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-first.example.com.conf") do
+      it { is_expected.to contain '<VirtualHost \*:80>' }
+      it { is_expected.to contain "ServerName first.example.com" }
+    end
+  end
+
+  context 'new proxy vhost on port 80' do
+    it 'should configure an apache proxy vhost' do
+      pp = <<-EOS
+        class { 'apache': }
+        apache::vhost { 'proxy.example.com':
+          port    => '80',
+          docroot => '/var/www/proxy',
+          proxy_pass => [
+            { 'path' => '/foo', 'url' => 'http://backend-foo/'},
+          ],
+        proxy_preserve_host   => true,
+        proxy_error_override  => true,
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-proxy.example.com.conf") do
+      it { is_expected.to contain '<VirtualHost \*:80>' }
+      it { is_expected.to contain "ServerName proxy.example.com" }
+      it { is_expected.to contain "ProxyPass" }
+      it { is_expected.to contain "ProxyPreserveHost On" }
+      it { is_expected.to contain "ProxyErrorOverride On" }
+      it { is_expected.not_to contain "<Proxy \*>" }
+    end
+  end
+
+  context 'new proxy vhost on port 80' do
+    it 'should configure an apache proxy vhost' do
+      pp = <<-EOS
+        class { 'apache': }
+        apache::vhost { 'proxy.example.com':
+          port    => '80',
+          docroot => '/var/www/proxy',
+          proxy_pass_match => [
+            { 'path' => '/foo', 'url' => 'http://backend-foo/'},
+          ],
+        proxy_preserve_host   => true,
+        proxy_error_override  => true,
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-proxy.example.com.conf") do
+      it { is_expected.to contain '<VirtualHost \*:80>' }
+      it { is_expected.to contain "ServerName proxy.example.com" }
+      it { is_expected.to contain "ProxyPassMatch /foo http://backend-foo/" }
+      it { is_expected.to contain "ProxyPreserveHost On" }
+      it { is_expected.to contain "ProxyErrorOverride On" }
+      it { is_expected.not_to contain "<Proxy \*>" }
+    end
+  end
+
+  context 'new vhost on port 80' do
+    it 'should configure two apache vhosts' do
+      pp = <<-EOS
+        class { 'apache': }
+        apache::vhost { 'first.example.com':
+          port    => '80',
+          docroot => '/var/www/first',
+        }
+        host { 'first.example.com': ip => '127.0.0.1', }
+        file { '/var/www/first/index.html':
+          ensure  => file,
+          content => "Hello from first\\n",
+        }
+        apache::vhost { 'second.example.com':
+          port    => '80',
+          docroot => '/var/www/second',
+        }
+        host { 'second.example.com': ip => '127.0.0.1', }
+        file { '/var/www/second/index.html':
+          ensure  => file,
+          content => "Hello from second\\n",
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service($service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    it 'should answer to first.example.com' do
+      shell("/usr/bin/curl first.example.com:80", {:acceptable_exit_codes => 0}) do |r|
+        expect(r.stdout).to eq("Hello from first\n")
+      end
+    end
+
+    it 'should answer to second.example.com' do
+      shell("/usr/bin/curl second.example.com:80", {:acceptable_exit_codes => 0}) do |r|
+        expect(r.stdout).to eq("Hello from second\n")
+      end
+    end
+  end
+
+  context 'new vhost with multiple IP addresses on port 80' do
+    it 'should configure one apache vhost with 2 ip addresses' do
+      pp = <<-EOS
+        class { 'apache':
+          default_vhost => false,
+        }
+        apache::vhost { 'example.com':
+          port     => '80',
+          ip       => ['127.0.0.1','127.0.0.2'],
+          ip_based => true,
+          docroot  => '/var/www/html',
+        }
+        host { 'ipv4.example.com': ip => '127.0.0.1', }
+        host { 'ipv6.example.com': ip => '127.0.0.2', }
+        file { '/var/www/html/index.html':
+          ensure  => file,
+          content => "Hello from vhost\\n",
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service($service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    describe file("#{$vhost_dir}/25-example.com.conf") do
+      it { is_expected.to contain '<VirtualHost 127.0.0.1:80 127.0.0.2:80>' }
+      it { is_expected.to contain "ServerName example.com" }
+    end
+
+    describe file($ports_file) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'Listen 127.0.0.1:80' }
+      it { is_expected.to contain 'Listen 127.0.0.2:80' }
+      it { is_expected.not_to contain 'NameVirtualHost 127.0.0.1:80' }
+      it { is_expected.not_to contain 'NameVirtualHost 127.0.0.2:80' }
+    end
+
+    it 'should answer to ipv4.example.com' do
+      shell("/usr/bin/curl ipv4.example.com:80", {:acceptable_exit_codes => 0}) do |r|
+        expect(r.stdout).to eq("Hello from vhost\n")
+      end
+    end
+
+    it 'should answer to ipv6.example.com' do
+      shell("/usr/bin/curl ipv6.example.com:80", {:acceptable_exit_codes => 0}) do |r|
+        expect(r.stdout).to eq("Hello from vhost\n")
+      end
+    end
+  end
+
+  context 'apache_directories' do
+    describe 'readme example, adapted' do
+      it 'should configure a vhost with Files' do
+        pp = <<-EOS
+          class { 'apache': }
+
+          if versioncmp($apache::apache_version, '2.4') >= 0 {
+            $_files_match_directory = { 'path' => '(\.swp|\.bak|~)$', 'provider' => 'filesmatch', 'require' => 'all denied', }
+          } else {
+            $_files_match_directory = { 'path' => '(\.swp|\.bak|~)$', 'provider' => 'filesmatch', 'deny' => 'from all', }
+          }
+
+          $_directories = [
+            { 'path' => '/var/www/files', },
+            $_files_match_directory,
+          ]
+
+          apache::vhost { 'files.example.net':
+            docroot     => '/var/www/files',
+            directories => $_directories,
+          }
+          file { '/var/www/files/index.html':
+            ensure  => file,
+            content => "Hello World\\n",
+          }
+          file { '/var/www/files/index.html.bak':
+            ensure  => file,
+            content => "Hello World\\n",
+          }
+          host { 'files.example.net': ip => '127.0.0.1', }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe service($service_name) do
+        it { is_expected.to be_enabled }
+        it { is_expected.to be_running }
+      end
+
+      it 'should answer to files.example.net' do
+        expect(shell("/usr/bin/curl -sSf files.example.net:80/index.html").stdout).to eq("Hello World\n")
+        expect(shell("/usr/bin/curl -sSf files.example.net:80/index.html.bak", {:acceptable_exit_codes => 22}).stderr).to match(/curl: \(22\) The requested URL returned error: 403/)
+      end
+    end
+
+    describe 'other Directory options' do
+      it 'should configure a vhost with multiple Directory sections' do
+        pp = <<-EOS
+          class { 'apache': }
+
+          if versioncmp($apache::apache_version, '2.4') >= 0 {
+            $_files_match_directory = { 'path' => 'private.html$', 'provider' => 'filesmatch', 'require' => 'all denied' }
+          } else {
+            $_files_match_directory = [
+              { 'path' => 'private.html$', 'provider' => 'filesmatch', 'deny' => 'from all' },
+              { 'path' => '/bar/bar.html', 'provider' => 'location', allow => [ 'from 127.0.0.1', ] },
+            ]
+          }
+
+          $_directories = [
+            { 'path' => '/var/www/files', },
+            { 'path' => '/foo/', 'provider' => 'location', 'directoryindex' => 'notindex.html', },
+            $_files_match_directory,
+          ]
+
+          apache::vhost { 'files.example.net':
+            docroot     => '/var/www/files',
+            directories => $_directories,
+          }
+          file { '/var/www/files/foo':
+            ensure => directory,
+          }
+          file { '/var/www/files/foo/notindex.html':
+            ensure  => file,
+            content => "Hello Foo\\n",
+          }
+          file { '/var/www/files/private.html':
+            ensure  => file,
+            content => "Hello World\\n",
+          }
+          file { '/var/www/files/bar':
+            ensure => directory,
+          }
+          file { '/var/www/files/bar/bar.html':
+            ensure  => file,
+            content => "Hello Bar\\n",
+          }
+          host { 'files.example.net': ip => '127.0.0.1', }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe service($service_name) do
+        it { is_expected.to be_enabled }
+        it { is_expected.to be_running }
+      end
+
+      it 'should answer to files.example.net' do
+        expect(shell("/usr/bin/curl -sSf files.example.net:80/").stdout).to eq("Hello World\n")
+        expect(shell("/usr/bin/curl -sSf files.example.net:80/foo/").stdout).to eq("Hello Foo\n")
+        expect(shell("/usr/bin/curl -sSf files.example.net:80/private.html", {:acceptable_exit_codes => 22}).stderr).to match(/curl: \(22\) The requested URL returned error: 403/)
+        expect(shell("/usr/bin/curl -sSf files.example.net:80/bar/bar.html").stdout).to eq("Hello Bar\n")
+      end
+    end
+
+    describe 'SetHandler directive' do
+      it 'should configure a vhost with a SetHandler directive' do
+        pp = <<-EOS
+          class { 'apache': }
+          apache::mod { 'status': }
+          host { 'files.example.net': ip => '127.0.0.1', }
+          apache::vhost { 'files.example.net':
+            docroot     => '/var/www/files',
+            directories => [
+              { path => '/var/www/files', },
+              { path => '/server-status', provider => 'location', sethandler => 'server-status', },
+            ],
+          }
+          file { '/var/www/files/index.html':
+            ensure  => file,
+            content => "Hello World\\n",
+          }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe service($service_name) do
+        it { is_expected.to be_enabled }
+        it { is_expected.to be_running }
+      end
+
+      it 'should answer to files.example.net' do
+        expect(shell("/usr/bin/curl -sSf files.example.net:80/index.html").stdout).to eq("Hello World\n")
+        expect(shell("/usr/bin/curl -sSf files.example.net:80/server-status?auto").stdout).to match(/Scoreboard: /)
+      end
+    end
+
+    describe 'Satisfy and Auth directive', :unless => $apache_version == '2.4' do
+      it 'should configure a vhost with Satisfy and Auth directive' do
+        pp = <<-EOS
+          class { 'apache': }
+          host { 'files.example.net': ip => '127.0.0.1', }
+          apache::vhost { 'files.example.net':
+            docroot     => '/var/www/files',
+            directories => [
+              {
+                path => '/var/www/files/foo',
+                auth_type => 'Basic',
+                auth_name => 'Basic Auth',
+                auth_user_file => '/var/www/htpasswd',
+                auth_require => "valid-user",
+              },
+              {
+                path => '/var/www/files/bar',
+                auth_type => 'Basic',
+                auth_name => 'Basic Auth',
+                auth_user_file => '/var/www/htpasswd',
+                auth_require => 'valid-user',
+                satisfy => 'Any',
+              },
+              {
+                path => '/var/www/files/baz',
+                allow => 'from 10.10.10.10',
+                auth_type => 'Basic',
+                auth_name => 'Basic Auth',
+                auth_user_file => '/var/www/htpasswd',
+                auth_require => 'valid-user',
+                satisfy => 'Any',
+              },
+            ],
+          }
+          file { '/var/www/files/foo':
+            ensure => directory,
+          }
+          file { '/var/www/files/bar':
+            ensure => directory,
+          }
+          file { '/var/www/files/baz':
+            ensure => directory,
+          }
+          file { '/var/www/files/foo/index.html':
+            ensure  => file,
+            content => "Hello World\\n",
+          }
+          file { '/var/www/files/bar/index.html':
+            ensure  => file,
+            content => "Hello World\\n",
+          }
+          file { '/var/www/files/baz/index.html':
+            ensure  => file,
+            content => "Hello World\\n",
+          }
+          file { '/var/www/htpasswd':
+            ensure  => file,
+            content => "login:IZ7jMcLSx0oQk", # "password" as password
+          }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe service($service_name) do
+        it { should be_enabled }
+        it { should be_running }
+      end
+
+      it 'should answer to files.example.net' do
+        shell("/usr/bin/curl -sSf files.example.net:80/foo/index.html", {:acceptable_exit_codes => 22}).stderr.should match(/curl: \(22\) The requested URL returned error: 401/)
+        shell("/usr/bin/curl -sSf -u login:password files.example.net:80/foo/index.html").stdout.should eq("Hello World\n")
+        shell("/usr/bin/curl -sSf files.example.net:80/bar/index.html").stdout.should eq("Hello World\n")
+        shell("/usr/bin/curl -sSf -u login:password files.example.net:80/bar/index.html").stdout.should eq("Hello World\n")
+        shell("/usr/bin/curl -sSf files.example.net:80/baz/index.html", {:acceptable_exit_codes => 22}).stderr.should match(/curl: \(22\) The requested URL returned error: 401/)
+        shell("/usr/bin/curl -sSf -u login:password files.example.net:80/baz/index.html").stdout.should eq("Hello World\n")
+      end
+    end
+  end
+
+  case fact('lsbdistcodename')
+  when 'precise', 'wheezy'
+    context 'vhost fallbackresource example' do
+      it 'should configure a vhost with Fallbackresource' do
+        pp = <<-EOS
+        class { 'apache': }
+        apache::vhost { 'fallback.example.net':
+          docroot         => '/var/www/fallback',
+          fallbackresource => '/index.html'
+        }
+        file { '/var/www/fallback/index.html':
+          ensure  => file,
+          content => "Hello World\\n",
+        }
+        host { 'fallback.example.net': ip => '127.0.0.1', }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe service($service_name) do
+        it { is_expected.to be_enabled }
+        it { is_expected.to be_running }
+      end
+
+      it 'should answer to fallback.example.net' do
+        shell("/usr/bin/curl fallback.example.net:80/Does/Not/Exist") do |r|
+          expect(r.stdout).to eq("Hello World\n")
+        end
+      end
+
+    end
+  else
+    # The current stable RHEL release (6.4) comes with Apache httpd 2.2.15
+    # That was released March 6, 2010.
+    # FallbackResource was backported to 2.2.16, and released July 25, 2010.
+    # Ubuntu Lucid (10.04) comes with apache2 2.2.14, released October 3, 2009.
+    # https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x/STATUS
+  end
+
+  context 'virtual_docroot hosting separate sites' do
+    it 'should configure a vhost with VirtualDocumentRoot' do
+      pp = <<-EOS
+        class { 'apache': }
+        apache::vhost { 'virt.example.com':
+          vhost_name      => '*',
+          serveraliases   => '*virt.example.com',
+          port            => '80',
+          docroot         => '/var/www/virt',
+          virtual_docroot => '/var/www/virt/%1',
+        }
+        host { 'virt.example.com': ip => '127.0.0.1', }
+        host { 'a.virt.example.com': ip => '127.0.0.1', }
+        host { 'b.virt.example.com': ip => '127.0.0.1', }
+        file { [ '/var/www/virt/a', '/var/www/virt/b', ]: ensure => directory, }
+        file { '/var/www/virt/a/index.html': ensure  => file, content => "Hello from a.virt\\n", }
+        file { '/var/www/virt/b/index.html': ensure  => file, content => "Hello from b.virt\\n", }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe service($service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    it 'should answer to a.virt.example.com' do
+      shell("/usr/bin/curl a.virt.example.com:80", {:acceptable_exit_codes => 0}) do |r|
+        expect(r.stdout).to eq("Hello from a.virt\n")
+      end
+    end
+
+    it 'should answer to b.virt.example.com' do
+      shell("/usr/bin/curl b.virt.example.com:80", {:acceptable_exit_codes => 0}) do |r|
+        expect(r.stdout).to eq("Hello from b.virt\n")
+      end
+    end
+  end
+
+  context 'proxy_pass for alternative vhost' do
+    it 'should configure a local vhost and a proxy vhost' do
+      apply_manifest(%{
+        class { 'apache': default_vhost => false, }
+        apache::vhost { 'localhost':
+          docroot => '/var/www/local',
+          ip      => '127.0.0.1',
+          port    => '8888',
+        }
+        apache::listen { '*:80': }
+        apache::vhost { 'proxy.example.com':
+          docroot    => '/var/www',
+          port       => '80',
+          add_listen => false,
+          proxy_pass => {
+            'path' => '/',
+            'url'  => 'http://localhost:8888/subdir/',
+          },
+        }
+        host { 'proxy.example.com': ip => '127.0.0.1', }
+        file { ['/var/www/local', '/var/www/local/subdir']: ensure => directory, }
+        file { '/var/www/local/subdir/index.html':
+          ensure  => file,
+          content => "Hello from localhost\\n",
+        }
+                     }, :catch_failures => true)
+    end
+
+    describe service($service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    it 'should get a response from the back end' do
+      shell("/usr/bin/curl --max-redirs 0 proxy.example.com:80") do |r|
+        expect(r.stdout).to eq("Hello from localhost\n")
+        expect(r.exit_code).to eq(0)
+      end
+    end
+  end
+
+  context 'proxy_pass_match for alternative vhost' do
+    it 'should configure a local vhost and a proxy vhost' do
+      apply_manifest(%{
+        class { 'apache': default_vhost => false, }
+        apache::vhost { 'localhost':
+          docroot => '/var/www/local',
+          ip      => '127.0.0.1',
+          port    => '8888',
+        }
+        apache::listen { '*:80': }
+        apache::vhost { 'proxy.example.com':
+          docroot    => '/var/www',
+          port       => '80',
+          add_listen => false,
+          proxy_pass_match => {
+            'path' => '/',
+            'url'  => 'http://localhost:8888/subdir/',
+          },
+        }
+        host { 'proxy.example.com': ip => '127.0.0.1', }
+        file { ['/var/www/local', '/var/www/local/subdir']: ensure => directory, }
+        file { '/var/www/local/subdir/index.html':
+          ensure  => file,
+          content => "Hello from localhost\\n",
+        }
+                     }, :catch_failures => true)
+    end
+
+    describe service($service_name) do
+      it { is_expected.to be_enabled }
+      it { is_expected.to be_running }
+    end
+
+    it 'should get a response from the back end' do
+      shell("/usr/bin/curl --max-redirs 0 proxy.example.com:80") do |r|
+        expect(r.stdout).to eq("Hello from localhost\n")
+        expect(r.exit_code).to eq(0)
+      end
+    end
+  end
+
+  describe 'ip_based' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot    => '/tmp',
+          ip_based   => true,
+          servername => 'test.server',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file($ports_file) do
+      it { is_expected.to be_file }
+      it { is_expected.not_to contain 'NameVirtualHost test.server' }
+    end
+  end
+
+  describe 'add_listen' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': default_vhost => false }
+        host { 'testlisten.server': ip => '127.0.0.1' }
+        apache::listen { '81': }
+        apache::vhost { 'testlisten.server':
+          docroot    => '/tmp',
+          port       => '80',
+          add_listen => false,
+          servername => 'testlisten.server',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file($ports_file) do
+      it { is_expected.to be_file }
+      it { is_expected.not_to contain 'Listen 80' }
+      it { is_expected.to contain 'Listen 81' }
+    end
+  end
+
+  describe 'docroot' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        user { 'test_owner': ensure => present, }
+        group { 'test_group': ensure => present, }
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot       => '/tmp/test',
+          docroot_owner => 'test_owner',
+          docroot_group => 'test_group',
+          docroot_mode  => '0750',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/tmp/test') do
+      it { is_expected.to be_directory }
+      it { is_expected.to be_owned_by 'test_owner' }
+      it { is_expected.to be_grouped_into 'test_group' }
+      it { is_expected.to be_mode 750 }
+    end
+  end
+
+  describe 'default_vhost' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot    => '/tmp',
+          default_vhost => true,
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file($ports_file) do
+      it { is_expected.to be_file }
+      if fact('osfamily') == 'RedHat' and fact('operatingsystemmajrelease') == '7'
+        it { is_expected.not_to contain 'NameVirtualHost test.server' }
+      elsif fact('operatingsystem') == 'Ubuntu' and fact('operatingsystemrelease') =~ /(14\.04|13\.10)/
+        it { is_expected.not_to contain 'NameVirtualHost test.server' }
+      else
+        it { is_expected.to contain 'NameVirtualHost test.server' }
+      end
+    end
+
+    describe file("#{$vhost_dir}/10-test.server.conf") do
+      it { is_expected.to be_file }
+    end
+  end
+
+  describe 'options' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot    => '/tmp',
+          options    => ['Indexes','FollowSymLinks', 'ExecCGI'],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'Options Indexes FollowSymLinks ExecCGI' }
+    end
+  end
+
+  describe 'override' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot    => '/tmp',
+          override   => ['All'],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'AllowOverride All' }
+    end
+  end
+
+  describe 'logroot' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot    => '/tmp',
+          logroot    => '/tmp',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain '  CustomLog "/tmp' }
+    end
+  end
+
+  ['access', 'error'].each do |logtype|
+    case logtype
+    when 'access'
+      logname = 'CustomLog'
+    when 'error'
+      logname = 'ErrorLog'
+    end
+
+    describe "#{logtype}_log" do
+      it 'applies cleanly' do
+        pp = <<-EOS
+          class { 'apache': }
+          host { 'test.server': ip => '127.0.0.1' }
+          apache::vhost { 'test.server':
+            docroot    => '/tmp',
+            logroot    => '/tmp',
+        #{logtype}_log => false,
+          }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe file("#{$vhost_dir}/25-test.server.conf") do
+        it { is_expected.to be_file }
+        it { is_expected.not_to contain "  #{logname} \"/tmp" }
+      end
+    end
+
+    describe "#{logtype}_log_pipe" do
+      it 'applies cleanly' do
+        pp = <<-EOS
+          class { 'apache': }
+          host { 'test.server': ip => '127.0.0.1' }
+          apache::vhost { 'test.server':
+            docroot    => '/tmp',
+            logroot    => '/tmp',
+        #{logtype}_log_pipe => '|/bin/sh',
+          }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe file("#{$vhost_dir}/25-test.server.conf") do
+        it { is_expected.to be_file }
+        it { is_expected.to contain "  #{logname} \"|/bin/sh" }
+      end
+    end
+
+    describe "#{logtype}_log_syslog" do
+      it 'applies cleanly' do
+        pp = <<-EOS
+          class { 'apache': }
+          host { 'test.server': ip => '127.0.0.1' }
+          apache::vhost { 'test.server':
+            docroot    => '/tmp',
+            logroot    => '/tmp',
+        #{logtype}_log_syslog => 'syslog',
+          }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe file("#{$vhost_dir}/25-test.server.conf") do
+        it { is_expected.to be_file }
+        it { is_expected.to contain "  #{logname} \"syslog\"" }
+      end
+    end
+  end
+
+  describe 'access_log_format' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot    => '/tmp',
+          logroot    => '/tmp',
+          access_log_syslog => 'syslog',
+          access_log_format => '%h %l',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'CustomLog "syslog" "%h %l"' }
+    end
+  end
+
+  describe 'access_log_env_var' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot            => '/tmp',
+          logroot            => '/tmp',
+          access_log_syslog  => 'syslog',
+          access_log_env_var => 'admin',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'CustomLog "syslog" combined env=admin' }
+    end
+  end
+
+  describe 'multiple access_logs' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot            => '/tmp',
+          logroot            => '/tmp',
+          access_logs => [
+            {'file' => 'log1'},
+            {'file' => 'log2', 'env' => 'admin' },
+            {'file' => '/var/tmp/log3', 'format' => '%h %l'},
+            {'syslog' => 'syslog' }
+          ]
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'CustomLog "/tmp/log1" combined' }
+      it { is_expected.to contain 'CustomLog "/tmp/log2" combined env=admin' }
+      it { is_expected.to contain 'CustomLog "/var/tmp/log3" "%h %l"' }
+      it { is_expected.to contain 'CustomLog "syslog" combined' }
+    end
+  end
+
+  describe 'aliases' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot    => '/tmp',
+          aliases => [
+            { alias       => '/image'    , path => '/ftp/pub/image' }   ,
+            { scriptalias => '/myscript' , path => '/usr/share/myscript' }
+          ],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'Alias /image "/ftp/pub/image"' }
+      it { is_expected.to contain 'ScriptAlias /myscript "/usr/share/myscript"' }
+    end
+  end
+
+  describe 'scriptaliases' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot    => '/tmp',
+          scriptaliases => [{ alias => '/myscript', path  => '/usr/share/myscript', }],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'ScriptAlias /myscript "/usr/share/myscript"' }
+    end
+  end
+
+  describe 'proxy' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': service_ensure => stopped, }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot    => '/tmp',
+          proxy_dest => 'test2',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'ProxyPass          / test2/' }
+    end
+  end
+
+  describe 'actions' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot => '/tmp',
+          action  => 'php-fastcgi',
+        }
+      EOS
+      pp = pp + "\nclass { 'apache::mod::actions': }" if fact('osfamily') == 'Debian'
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'Action php-fastcgi /cgi-bin virtual' }
+    end
+  end
+
+  describe 'suphp' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': service_ensure => stopped, }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot          => '/tmp',
+          suphp_addhandler => '#{$suphp_handler}',
+          suphp_engine     => 'on',
+          suphp_configpath => '#{$suphp_configpath}',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain "suPHP_AddHandler #{$suphp_handler}" }
+      it { is_expected.to contain 'suPHP_Engine on' }
+      it { is_expected.to contain "suPHP_ConfigPath \"#{$suphp_configpath}\"" }
+    end
+  end
+
+  describe 'no_proxy_uris' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': service_ensure => stopped, }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot          => '/tmp',
+          proxy_dest       => 'http://test2',
+          no_proxy_uris    => [ 'http://test2/test' ],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'ProxyPass          / http://test2/' }
+      it { is_expected.to contain 'ProxyPass        http://test2/test !' }
+    end
+  end
+
+  describe 'redirect' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot          => '/tmp',
+          redirect_source  => ['/images'],
+          redirect_dest    => ['http://test.server/'],
+          redirect_status  => ['permanent'],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'Redirect permanent /images http://test.server/' }
+    end
+  end
+
+  describe 'request_headers' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot          => '/tmp',
+          request_headers  => ['append MirrorID "mirror 12"'],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'append MirrorID "mirror 12"' }
+    end
+  end
+
+  describe 'rewrite rules' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot          => '/tmp',
+          rewrites => [
+            { comment => 'test',
+              rewrite_cond => '%{HTTP_USER_AGENT} ^Lynx/ [OR]',
+              rewrite_rule => ['^index\.html$ welcome.html'],
+              rewrite_map  => ['lc int:tolower'],
+            }
+          ],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain '#test' }
+      it { is_expected.to contain 'RewriteCond %{HTTP_USER_AGENT} ^Lynx/ [OR]' }
+      it { is_expected.to contain 'RewriteRule ^index.html$ welcome.html' }
+      it { is_expected.to contain 'RewriteMap lc int:tolower' }
+    end
+  end
+
+  describe 'directory rewrite rules' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        if ! defined(Class['apache::mod::rewrite']) {
+          include ::apache::mod::rewrite
+        }
+        apache::vhost { 'test.server':
+          docroot      => '/tmp',
+          directories  => [
+            {
+            path => '/tmp',
+            rewrites => [
+              {
+              comment => 'Permalink Rewrites',
+              rewrite_base => '/',
+              },
+              { rewrite_rule => [ '^index\\.php$ - [L]' ] },
+              { rewrite_cond => [
+                '%{REQUEST_FILENAME} !-f',
+                '%{REQUEST_FILENAME} !-d',                                                                                             ],                                                                                                                     rewrite_rule => [ '. /index.php [L]' ],                                                                              }
+              ],
+            },
+            ],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { should be_file }
+      it { should contain '#Permalink Rewrites' }
+      it { should contain 'RewriteEngine On' }
+      it { should contain 'RewriteBase /' }
+      it { should contain 'RewriteRule ^index\.php$ - [L]' }
+      it { should contain 'RewriteCond %{REQUEST_FILENAME} !-f' }
+      it { should contain 'RewriteCond %{REQUEST_FILENAME} !-d' }
+      it { should contain 'RewriteRule . /index.php [L]' }
+    end
+  end
+
+  describe 'setenv/setenvif' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot  => '/tmp',
+          setenv   => ['TEST /test'],
+          setenvif => ['Request_URI "\.gif$" object_is_image=gif']
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'SetEnv TEST /test' }
+      it { is_expected.to contain 'SetEnvIf Request_URI "\.gif$" object_is_image=gif' }
+    end
+  end
+
+  describe 'block' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot  => '/tmp',
+          block    => 'scm',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain '<DirectoryMatch .*\.(svn|git|bzr)/.*>' }
+    end
+  end
+
+  describe 'wsgi' do
+    it 'import_script applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        class { 'apache::mod::wsgi': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot                     => '/tmp',
+          wsgi_application_group      => '%{GLOBAL}',
+          wsgi_daemon_process         => 'wsgi',
+          wsgi_daemon_process_options => {processes => '2'},
+          wsgi_process_group          => 'nobody',
+          wsgi_script_aliases         => { '/test' => '/test1' },
+          wsgi_pass_authorization     => 'On',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'import_script applies cleanly', :unless => (fact('lsbdistcodename') == 'lucid' or UNSUPPORTED_PLATFORMS.include?(fact('osfamily'))) do
+      pp = <<-EOS
+        class { 'apache': }
+        class { 'apache::mod::wsgi': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot                     => '/tmp',
+          wsgi_application_group      => '%{GLOBAL}',
+          wsgi_daemon_process         => 'wsgi',
+          wsgi_daemon_process_options => {processes => '2'},
+          wsgi_import_script          => '/test1',
+          wsgi_import_script_options  => { application-group => '%{GLOBAL}', process-group => 'wsgi' },
+          wsgi_process_group          => 'nobody',
+          wsgi_script_aliases         => { '/test' => '/test1' },
+          wsgi_pass_authorization     => 'On',
+          wsgi_chunked_request        => 'On',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf"), :unless => (fact('lsbdistcodename') == 'lucid' or UNSUPPORTED_PLATFORMS.include?(fact('osfamily'))) do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'WSGIApplicationGroup %{GLOBAL}' }
+      it { is_expected.to contain 'WSGIDaemonProcess wsgi processes=2' }
+      it { is_expected.to contain 'WSGIImportScript /test1 application-group=%{GLOBAL} process-group=wsgi' }
+      it { is_expected.to contain 'WSGIProcessGroup nobody' }
+      it { is_expected.to contain 'WSGIScriptAlias /test "/test1"' }
+      it { is_expected.to contain 'WSGIPassAuthorization On' }
+      it { is_expected.to contain 'WSGIChunkedRequest On' }
+    end
+  end
+
+  describe 'custom_fragment' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot  => '/tmp',
+          custom_fragment => inline_template('#weird test string'),
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain '#weird test string' }
+    end
+  end
+
+  describe 'itk' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        apache::vhost { 'test.server':
+          docroot  => '/tmp',
+          itk      => { user => 'nobody', group => 'nobody' }
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'AssignUserId nobody nobody' }
+    end
+  end
+
+  # So what does this work on?
+  if default['platform'] !~ /^(debian-(6|7)|el-(5|6|7))/
+    describe 'fastcgi' do
+      it 'applies cleanly' do
+        pp = <<-EOS
+          class { 'apache': }
+          class { 'apache::mod::fastcgi': }
+          host { 'test.server': ip => '127.0.0.1' }
+          apache::vhost { 'test.server':
+            docroot        => '/tmp',
+            fastcgi_server => 'localhost',
+            fastcgi_socket => '/tmp/fast/1234',
+            fastcgi_dir    => '/tmp/fast',
+          }
+        EOS
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe file("#{$vhost_dir}/25-test.server.conf") do
+        it { is_expected.to be_file }
+        it { is_expected.to contain 'FastCgiExternalServer localhost -socket /tmp/fast/1234' }
+        it { is_expected.to contain '<Directory "/tmp/fast">' }
+      end
+    end
+  end
+
+  describe 'additional_includes' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        if $::osfamily == 'RedHat' and "$::selinux" == "true" {
+          $semanage_package = $::operatingsystemmajrelease ? {
+            '5'     => 'policycoreutils',
+            default => 'policycoreutils-python',
+          }
+          exec { 'set_apache_defaults':
+            command => 'semanage fcontext -a -t httpd_sys_content_t "/apache_spec(/.*)?"',
+            path    => '/bin:/usr/bin/:/sbin:/usr/sbin',
+            require => Package[$semanage_package],
+          }
+          package { $semanage_package: ensure => installed }
+          exec { 'restorecon_apache':
+            command => 'restorecon -Rv /apache_spec',
+            path    => '/bin:/usr/bin/:/sbin:/usr/sbin',
+            before  => Service['httpd'],
+            require => Class['apache'],
+          }
+        }
+        class { 'apache': }
+        host { 'test.server': ip => '127.0.0.1' }
+        file { '/apache_spec': ensure => directory, }
+        file { '/apache_spec/include': ensure => present, content => '#additional_includes' }
+        apache::vhost { 'test.server':
+          docroot             => '/apache_spec',
+          additional_includes => '/apache_spec/include',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'Include "/apache_spec/include"' }
+    end
+  end
+
+  describe 'virtualhost without priority prefix' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        apache::vhost { 'test.server':
+          priority => false,
+          docroot => '/tmp'
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/test.server.conf") do
+      it { is_expected.to be_file }
+    end
+  end
+
+  describe 'SSLProtocol directive' do
+    it 'applies cleanly' do
+      pp = <<-EOS
+        class { 'apache': }
+        apache::vhost { 'test.server':
+          docroot      => '/tmp',
+          ssl          => true,
+          ssl_protocol => ['All', '-SSLv2'],
+        }
+        apache::vhost { 'test2.server':
+          docroot      => '/tmp',
+          ssl          => true,
+          ssl_protocol => 'All -SSLv2',
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file("#{$vhost_dir}/25-test.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'SSLProtocol  *All -SSLv2' }
+    end
+
+    describe file("#{$vhost_dir}/25-test2.server.conf") do
+      it { is_expected.to be_file }
+      it { is_expected.to contain 'SSLProtocol  *All -SSLv2' }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/apache_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,874 @@
+require 'spec_helper'
+
+describe 'apache', :type => :class do
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :lsbdistcodename        => 'squeeze',
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_package("httpd").with(
+      'notify' => 'Class[Apache::Service]',
+      'ensure' => 'installed'
+      )
+    }
+    it { is_expected.to contain_user("www-data") }
+    it { is_expected.to contain_group("www-data") }
+    it { is_expected.to contain_class("apache::service") }
+    it { is_expected.to contain_file("/var/www").with(
+      'ensure'  => 'directory'
+      )
+    }
+    it { is_expected.to contain_file("/etc/apache2/sites-enabled").with(
+      'ensure'  => 'directory',
+      'recurse' => 'true',
+      'purge'   => 'true',
+      'notify'  => 'Class[Apache::Service]',
+      'require' => 'Package[httpd]'
+      )
+    }
+    it { is_expected.to contain_file("/etc/apache2/mods-enabled").with(
+      'ensure'  => 'directory',
+      'recurse' => 'true',
+      'purge'   => 'true',
+      'notify'  => 'Class[Apache::Service]',
+      'require' => 'Package[httpd]'
+      )
+    }
+    it { is_expected.to contain_file("/etc/apache2/mods-available").with(
+      'ensure'  => 'directory',
+      'recurse' => 'true',
+      'purge'   => 'false',
+      'notify'  => 'Class[Apache::Service]',
+      'require' => 'Package[httpd]'
+      )
+    }
+    it { is_expected.to contain_concat("/etc/apache2/ports.conf").with(
+      'owner'   => 'root',
+      'group'   => 'root',
+      'mode'    => '0644',
+      'notify'  => 'Class[Apache::Service]'
+      )
+    }
+    # Assert that load files are placed and symlinked for these mods, but no conf file.
+    [
+      'auth_basic',
+      'authn_file',
+      'authz_default',
+      'authz_groupfile',
+      'authz_host',
+      'authz_user',
+      'dav',
+      'env'
+    ].each do |modname|
+      it { is_expected.to contain_file("#{modname}.load").with(
+        'path'   => "/etc/apache2/mods-available/#{modname}.load",
+        'ensure' => 'file'
+      ) }
+      it { is_expected.to contain_file("#{modname}.load symlink").with(
+        'path'   => "/etc/apache2/mods-enabled/#{modname}.load",
+        'ensure' => 'link',
+        'target' => "/etc/apache2/mods-available/#{modname}.load"
+      ) }
+      it { is_expected.not_to contain_file("#{modname}.conf") }
+      it { is_expected.not_to contain_file("#{modname}.conf symlink") }
+    end
+
+    context "with Apache version < 2.4" do
+      let :params do
+        { :apache_version => '2.2' }
+      end
+
+      it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^Include "/etc/apache2/conf\.d/\*\.conf"$} }
+    end
+
+    context "with Apache version >= 2.4" do
+      let :params do
+        {
+          :apache_version => '2.4',
+          :use_optional_includes => true
+        }
+      end
+
+      it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^IncludeOptional "/etc/apache2/conf\.d/\*\.conf"$} }
+    end
+
+    context "when specifying slash encoding behaviour" do
+      let :params do
+        { :allow_encoded_slashes => 'nodecode' }
+      end
+
+      it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^AllowEncodedSlashes nodecode$} }
+    end
+
+    context "when specifying default character set" do
+      let :params do
+        { :default_charset => 'none' }
+      end
+
+      it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^AddDefaultCharset none$} }
+    end
+
+    # Assert that both load files and conf files are placed and symlinked for these mods
+    [
+      'alias',
+      'autoindex',
+      'dav_fs',
+      'deflate',
+      'dir',
+      'mime',
+      'negotiation',
+      'setenvif',
+    ].each do |modname|
+      it { is_expected.to contain_file("#{modname}.load").with(
+        'path'   => "/etc/apache2/mods-available/#{modname}.load",
+        'ensure' => 'file'
+      ) }
+      it { is_expected.to contain_file("#{modname}.load symlink").with(
+        'path'   => "/etc/apache2/mods-enabled/#{modname}.load",
+        'ensure' => 'link',
+        'target' => "/etc/apache2/mods-available/#{modname}.load"
+      ) }
+      it { is_expected.to contain_file("#{modname}.conf").with(
+        'path'   => "/etc/apache2/mods-available/#{modname}.conf",
+        'ensure' => 'file'
+      ) }
+      it { is_expected.to contain_file("#{modname}.conf symlink").with(
+        'path'   => "/etc/apache2/mods-enabled/#{modname}.conf",
+        'ensure' => 'link',
+        'target' => "/etc/apache2/mods-available/#{modname}.conf"
+      ) }
+    end
+
+    describe "Check default type" do
+      context "with Apache version < 2.4" do
+        let :params do
+          {
+            :apache_version => '2.2',
+          }
+        end
+
+       context "when default_type => 'none'" do
+          let :params do
+            { :default_type => 'none' }
+          end
+
+          it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^DefaultType none$} }
+        end
+        context "when default_type => 'text/plain'" do
+          let :params do
+            { :default_type => 'text/plain' }
+          end
+
+          it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^DefaultType text/plain$} }
+        end
+      end
+
+      context "with Apache version >= 2.4" do
+        let :params do
+          {
+            :apache_version => '2.4',
+          }
+        end
+        it { is_expected.to contain_file("/etc/apache2/apache2.conf").without_content %r{^DefaultType [.]*$} }
+      end
+    end
+
+    describe "Don't create user resource" do
+      context "when parameter manage_user is false" do
+        let :params do
+          { :manage_user => false }
+        end
+
+        it { is_expected.not_to contain_user('www-data') }
+        it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^User www-data\n} }
+      end
+    end
+    describe "Don't create group resource" do
+      context "when parameter manage_group is false" do
+        let :params do
+          { :manage_group => false }
+        end
+
+        it { is_expected.not_to contain_group('www-data') }
+        it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^Group www-data\n} }
+      end
+    end
+
+    describe "Add extra LogFormats" do
+      context "When parameter log_formats is a hash" do
+        let :params do
+          { :log_formats => {
+            'vhost_common'   => "%v %h %l %u %t \"%r\" %>s %b",
+            'vhost_combined' => "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
+          } }
+        end
+
+        it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common\n} }
+        it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%\{Referer\}i\" \"%\{User-agent\}i\"" vhost_combined\n} }
+      end
+    end
+
+    describe "Override existing LogFormats" do
+      context "When parameter log_formats is a hash" do
+        let :params do
+          { :log_formats => {
+            'common'   => "%v %h %l %u %t \"%r\" %>s %b",
+            'combined' => "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
+          } }
+        end
+
+        it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^LogFormat "%v %h %l %u %t \"%r\" %>s %b" common\n} }
+        it { is_expected.to contain_file("/etc/apache2/apache2.conf").without_content %r{^LogFormat "%h %l %u %t \"%r\" %>s %b \"%\{Referer\}i\" \"%\{User-agent\}i\"" combined\n} }
+        it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^LogFormat "%v %h %l %u %t \"%r\" %>s %b" common\n} }
+        it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%\{Referer\}i\" \"%\{User-agent\}i\"" combined\n} }
+        it { is_expected.to contain_file("/etc/apache2/apache2.conf").without_content %r{^LogFormat "%h %l %u %t \"%r\" %>s %b \"%\{Referer\}i\" \"%\{User-agent\}i\"" combined\n} }
+      end
+    end
+
+    context "8" do
+      let :facts do
+        super().merge({
+          :lsbdistcodename        => 'jessie',
+          :operatingsystemrelease => '8'
+        })
+      end
+      it { is_expected.to contain_file("/var/www/html").with(
+        'ensure'  => 'directory'
+         )
+        }
+      end
+    context "on Ubuntu" do
+      let :facts do
+        super().merge({
+          :operatingsystem => 'Ubuntu'
+        })
+      end
+
+      context "14.04" do
+        let :facts do
+          super().merge({
+            :lsbdistrelease         => '14.04',
+            :operatingsystemrelease => '14.04'
+          })
+        end
+        it { is_expected.to contain_file("/var/www/html").with(
+          'ensure'  => 'directory'
+          )
+        }
+      end
+      context "13.10" do
+        let :facts do
+          super().merge({
+            :lsbdistrelease         => '13.10',
+            :operatingsystemrelease => '13.10'
+          })
+        end
+        it { is_expected.to contain_class('apache').with_apache_version('2.4') }
+      end
+      context "12.04" do
+        let :facts do
+          super().merge({
+            :lsbdistrelease         => '12.04',
+            :operatingsystemrelease => '12.04'
+          })
+        end
+        it { is_expected.to contain_class('apache').with_apache_version('2.2') }
+      end
+      context "13.04" do
+        let :facts do
+          super().merge({
+            :lsbdistrelease         => '13.04',
+            :operatingsystemrelease => '13.04'
+          })
+        end
+        it { is_expected.to contain_class('apache').with_apache_version('2.2') }
+      end
+    end
+  end
+  context "on a RedHat 5 OS" do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '5',
+        :concat_basedir         => '/dne',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_package("httpd").with(
+      'notify' => 'Class[Apache::Service]',
+      'ensure' => 'installed'
+      )
+    }
+    it { is_expected.to contain_user("apache") }
+    it { is_expected.to contain_group("apache") }
+    it { is_expected.to contain_class("apache::service") }
+    it { is_expected.to contain_file("/var/www/html").with(
+      'ensure'  => 'directory'
+      )
+    }
+    it { is_expected.to contain_file("/etc/httpd/conf.d").with(
+      'ensure'  => 'directory',
+      'recurse' => 'true',
+      'purge'   => 'true',
+      'notify'  => 'Class[Apache::Service]',
+      'require' => 'Package[httpd]'
+      )
+    }
+    it { is_expected.to contain_concat("/etc/httpd/conf/ports.conf").with(
+      'owner'   => 'root',
+      'group'   => 'root',
+      'mode'    => '0644',
+      'notify'  => 'Class[Apache::Service]'
+      )
+    }
+    describe "Alternate confd/mod/vhosts directory" do
+      let :params do
+        {
+          :vhost_dir => '/etc/httpd/site.d',
+          :confd_dir => '/etc/httpd/conf.d',
+          :mod_dir   => '/etc/httpd/mod.d',
+        }
+      end
+
+      ['mod.d','site.d','conf.d'].each do |dir|
+        it { is_expected.to contain_file("/etc/httpd/#{dir}").with(
+          'ensure'  => 'directory',
+          'recurse' => 'true',
+          'purge'   => 'true',
+          'notify'  => 'Class[Apache::Service]',
+          'require' => 'Package[httpd]'
+        ) }
+      end
+
+      # Assert that load files are placed for these mods, but no conf file.
+      [
+        'auth_basic',
+        'authn_file',
+        'authz_default',
+        'authz_groupfile',
+        'authz_host',
+        'authz_user',
+        'dav',
+        'env',
+      ].each do |modname|
+        it { is_expected.to contain_file("#{modname}.load").with_path(
+          "/etc/httpd/mod.d/#{modname}.load"
+        ) }
+        it { is_expected.not_to contain_file("#{modname}.conf").with_path(
+          "/etc/httpd/mod.d/#{modname}.conf"
+        ) }
+      end
+
+      # Assert that both load files and conf files are placed for these mods
+      [
+        'alias',
+        'autoindex',
+        'dav_fs',
+        'deflate',
+        'dir',
+        'mime',
+        'negotiation',
+        'setenvif',
+      ].each do |modname|
+        it { is_expected.to contain_file("#{modname}.load").with_path(
+          "/etc/httpd/mod.d/#{modname}.load"
+        ) }
+        it { is_expected.to contain_file("#{modname}.conf").with_path(
+          "/etc/httpd/mod.d/#{modname}.conf"
+        ) }
+      end
+
+      context "with Apache version < 2.4" do
+        let :params do
+          { :apache_version => '2.2' }
+        end
+
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^Include "/etc/httpd/conf\.d/\*\.conf"$} }
+      end
+
+      context "with Apache version >= 2.4" do
+        let :params do
+          {
+            :apache_version => '2.4',
+            :use_optional_includes => true
+          }
+        end
+
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^IncludeOptional "/etc/httpd/conf\.d/\*\.conf"$} }
+      end
+
+      context "with Apache version < 2.4" do
+        let :params do
+          {
+            :apache_version => '2.2',
+            :rewrite_lock => '/var/lock/subsys/rewrite-lock'
+          }
+        end
+
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^RewriteLock /var/lock/subsys/rewrite-lock$} }
+      end
+
+      context "with Apache version < 2.4" do
+        let :params do
+          {
+            :apache_version => '2.2'
+          }
+        end
+
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").without_content %r{^RewriteLock [.]*$} }
+      end
+
+      context "with Apache version >= 2.4" do
+        let :params do
+          {
+            :apache_version => '2.4',
+            :rewrite_lock => '/var/lock/subsys/rewrite-lock'
+          }
+        end
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").without_content %r{^RewriteLock [.]*$} }
+      end
+
+      context "when specifying slash encoding behaviour" do
+        let :params do
+          { :allow_encoded_slashes => 'nodecode' }
+        end
+
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^AllowEncodedSlashes nodecode$} }
+      end
+
+      context "when specifying default character set" do
+        let :params do
+          { :default_charset => 'none' }
+        end
+
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^AddDefaultCharset none$} }
+      end
+
+      context "with Apache version < 2.4" do
+        let :params do
+          {
+            :apache_version => '2.2',
+          }
+        end
+
+       context "when default_type => 'none'" do
+          let :params do
+            { :default_type => 'none' }
+          end
+
+          it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^DefaultType none$} }
+        end
+        context "when default_type => 'text/plain'" do
+          let :params do
+            { :default_type => 'text/plain' }
+          end
+
+          it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^DefaultType text/plain$} }
+        end
+      end
+
+      context "with Apache version >= 2.4" do
+        let :params do
+          {
+            :apache_version => '2.4',
+          }
+        end
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").without_content %r{^DefaultType [.]*$} }
+      end
+
+      it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^Include "/etc/httpd/site\.d/\*"$} }
+      it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^Include "/etc/httpd/mod\.d/\*\.conf"$} }
+      it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^Include "/etc/httpd/mod\.d/\*\.load"$} }
+    end
+
+    describe "Alternate conf directory" do
+      let :params do
+        { :conf_dir => '/opt/rh/root/etc/httpd/conf' }
+      end
+
+      it { is_expected.to contain_file("/opt/rh/root/etc/httpd/conf/httpd.conf").with(
+        'ensure'  => 'file',
+        'notify'  => 'Class[Apache::Service]',
+        'require' => ['Package[httpd]', 'File[/etc/httpd/conf/ports.conf]'],
+      ) }
+    end
+
+    describe "Alternate conf.d directory" do
+      let :params do
+        { :confd_dir => '/etc/httpd/special_conf.d' }
+      end
+
+      it { is_expected.to contain_file("/etc/httpd/special_conf.d").with(
+        'ensure'  => 'directory',
+        'recurse' => 'true',
+        'purge'   => 'true',
+        'notify'  => 'Class[Apache::Service]',
+        'require' => 'Package[httpd]'
+      ) }
+    end
+
+    describe "Alternate mpm_modules" do
+      context "when declaring mpm_module is false" do
+        let :params do
+          { :mpm_module => false }
+        end
+        it 'should not declare mpm modules' do
+          is_expected.not_to contain_class('apache::mod::event')
+          is_expected.not_to contain_class('apache::mod::itk')
+          is_expected.not_to contain_class('apache::mod::peruser')
+          is_expected.not_to contain_class('apache::mod::prefork')
+          is_expected.not_to contain_class('apache::mod::worker')
+        end
+      end
+      context "when declaring mpm_module => prefork" do
+        let :params do
+          { :mpm_module => 'prefork' }
+        end
+        it { is_expected.to contain_class('apache::mod::prefork') }
+        it { is_expected.not_to contain_class('apache::mod::event') }
+        it { is_expected.not_to contain_class('apache::mod::itk') }
+        it { is_expected.not_to contain_class('apache::mod::peruser') }
+        it { is_expected.not_to contain_class('apache::mod::worker') }
+      end
+      context "when declaring mpm_module => worker" do
+        let :params do
+          { :mpm_module => 'worker' }
+        end
+        it { is_expected.to contain_class('apache::mod::worker') }
+        it { is_expected.not_to contain_class('apache::mod::event') }
+        it { is_expected.not_to contain_class('apache::mod::itk') }
+        it { is_expected.not_to contain_class('apache::mod::peruser') }
+        it { is_expected.not_to contain_class('apache::mod::prefork') }
+      end
+      context "when declaring mpm_module => breakme" do
+        let :params do
+          { :mpm_module => 'breakme' }
+        end
+        it { expect { catalogue }.to raise_error Puppet::Error, /does not match/ }
+      end
+    end
+
+    describe "different templates for httpd.conf" do
+      context "with default" do
+        let :params do
+          { :conf_template => 'apache/httpd.conf.erb' }
+        end
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^# Security\n} }
+      end
+      context "with non-default" do
+        let :params do
+          { :conf_template => 'site_apache/fake.conf.erb' }
+        end
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^Fake template for rspec.$} }
+      end
+    end
+
+    describe "default mods" do
+      context "without" do
+        let :params do
+          { :default_mods => false }
+        end
+
+        it { is_expected.to contain_apache__mod('authz_host') }
+        it { is_expected.not_to contain_apache__mod('env') }
+      end
+      context "custom" do
+        let :params do
+          { :default_mods => [
+            'info',
+            'alias',
+            'mime',
+            'env',
+            'setenv',
+            'expires',
+          ]}
+        end
+
+        it { is_expected.to contain_apache__mod('authz_host') }
+        it { is_expected.to contain_apache__mod('env') }
+        it { is_expected.to contain_class('apache::mod::info') }
+        it { is_expected.to contain_class('apache::mod::mime') }
+      end
+    end
+    describe "Don't create user resource" do
+      context "when parameter manage_user is false" do
+        let :params do
+          { :manage_user => false }
+        end
+
+        it { is_expected.not_to contain_user('apache') }
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^User apache\n} }
+      end
+    end
+    describe "Don't create group resource" do
+      context "when parameter manage_group is false" do
+        let :params do
+          { :manage_group => false }
+        end
+
+        it { is_expected.not_to contain_group('apache') }
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^Group apache\n} }
+
+      end
+    end
+    describe "sendfile" do
+      context "with invalid value" do
+        let :params do
+          { :sendfile => 'foo' }
+        end
+        it "should fail" do
+          expect do
+            catalogue
+          end.to raise_error(Puppet::Error, /"foo" does not match/)
+        end
+      end
+      context "On" do
+        let :params do
+          { :sendfile => 'On' }
+        end
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^EnableSendfile On\n} }
+      end
+      context "Off" do
+        let :params do
+          { :sendfile => 'Off' }
+        end
+        it { is_expected.to contain_file("/etc/httpd/conf/httpd.conf").with_content %r{^EnableSendfile Off\n} }
+      end
+    end
+    context "on Fedora" do
+      let :facts do
+        super().merge({
+          :operatingsystem => 'Fedora'
+        })
+      end
+
+      context "21" do
+        let :facts do
+          super().merge({
+            :lsbdistrelease         => '21',
+            :operatingsystemrelease => '21'
+          })
+        end
+        it { is_expected.to contain_class('apache').with_apache_version('2.4') }
+      end
+      context "Rawhide" do
+        let :facts do
+          super().merge({
+            :lsbdistrelease         => 'Rawhide',
+            :operatingsystemrelease => 'Rawhide'
+          })
+        end
+        it { is_expected.to contain_class('apache').with_apache_version('2.4') }
+      end
+      # kinda obsolete
+      context "17" do
+        let :facts do
+          super().merge({
+            :lsbdistrelease         => '17',
+            :operatingsystemrelease => '17'
+          })
+        end
+        it { is_expected.to contain_class('apache').with_apache_version('2.2') }
+      end
+    end
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :osfamily               => 'FreeBSD',
+        :operatingsystem        => 'FreeBSD',
+        :operatingsystemrelease => '10',
+        :concat_basedir         => '/dne',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_class("apache::package").with({'ensure' => 'present'}) }
+    it { is_expected.to contain_user("www") }
+    it { is_expected.to contain_group("www") }
+    it { is_expected.to contain_class("apache::service") }
+    it { is_expected.to contain_file("/usr/local/www/apache24/data").with(
+      'ensure'  => 'directory'
+      )
+    }
+    it { is_expected.to contain_file("/usr/local/etc/apache24/Vhosts").with(
+      'ensure'  => 'directory',
+      'recurse' => 'true',
+      'purge'   => 'true',
+      'notify'  => 'Class[Apache::Service]',
+      'require' => 'Package[httpd]'
+    ) }
+    it { is_expected.to contain_file("/usr/local/etc/apache24/Modules").with(
+      'ensure'  => 'directory',
+      'recurse' => 'true',
+      'purge'   => 'true',
+      'notify'  => 'Class[Apache::Service]',
+      'require' => 'Package[httpd]'
+    ) }
+    it { is_expected.to contain_concat("/usr/local/etc/apache24/ports.conf").with(
+      'owner'   => 'root',
+      'group'   => 'wheel',
+      'mode'    => '0644',
+      'notify'  => 'Class[Apache::Service]'
+    ) }
+    # Assert that load files are placed for these mods, but no conf file.
+    [
+      'auth_basic',
+      'authn_core',
+      'authn_file',
+      'authz_groupfile',
+      'authz_host',
+      'authz_user',
+      'dav',
+      'env'
+    ].each do |modname|
+      it { is_expected.to contain_file("#{modname}.load").with(
+        'path'   => "/usr/local/etc/apache24/Modules/#{modname}.load",
+        'ensure' => 'file'
+      ) }
+      it { is_expected.not_to contain_file("#{modname}.conf") }
+    end
+
+    # Assert that both load files and conf files are placed for these mods
+    [
+      'alias',
+      'autoindex',
+      'dav_fs',
+      'deflate',
+      'dir',
+      'mime',
+      'negotiation',
+      'setenvif',
+    ].each do |modname|
+      it { is_expected.to contain_file("#{modname}.load").with(
+        'path'   => "/usr/local/etc/apache24/Modules/#{modname}.load",
+        'ensure' => 'file'
+      ) }
+      it { is_expected.to contain_file("#{modname}.conf").with(
+        'path'   => "/usr/local/etc/apache24/Modules/#{modname}.conf",
+        'ensure' => 'file'
+      ) }
+    end
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_user("apache") }
+    it { is_expected.to contain_group("apache") }
+    it { is_expected.to contain_class("apache::service") }
+    it { is_expected.to contain_file("/var/www/localhost/htdocs").with(
+      'ensure'  => 'directory'
+      )
+    }
+    it { is_expected.to contain_file("/etc/apache2/vhosts.d").with(
+      'ensure'  => 'directory',
+      'recurse' => 'true',
+      'purge'   => 'true',
+      'notify'  => 'Class[Apache::Service]',
+      'require' => 'Package[httpd]'
+    ) }
+    it { is_expected.to contain_file("/etc/apache2/modules.d").with(
+      'ensure'  => 'directory',
+      'recurse' => 'true',
+      'purge'   => 'true',
+      'notify'  => 'Class[Apache::Service]',
+      'require' => 'Package[httpd]'
+    ) }
+    it { is_expected.to contain_concat("/etc/apache2/ports.conf").with(
+      'owner'   => 'root',
+      'group'   => 'wheel',
+      'mode'    => '0644',
+      'notify'  => 'Class[Apache::Service]'
+    ) }
+  end
+  context 'on all OSes' do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    context 'with a custom apache_name parameter' do
+      let :params do {
+        :apache_name => 'httpd24-httpd'
+      }
+      end
+      it { is_expected.to contain_package("httpd").with(
+        'notify' => 'Class[Apache::Service]',
+        'ensure' => 'installed',
+        'name'   => 'httpd24-httpd'
+        )
+      }
+    end
+    context 'default vhost defaults' do
+      it { is_expected.to contain_apache__vhost('default').with_ensure('present') }
+      it { is_expected.to contain_apache__vhost('default-ssl').with_ensure('absent') }
+    end
+    context 'without default non-ssl vhost' do
+      let :params do {
+        :default_vhost  => false
+      }
+      end
+      it { is_expected.to contain_apache__vhost('default').with_ensure('absent') }
+      it { is_expected.not_to contain_file('/var/www/html') }
+    end
+    context 'with default ssl vhost' do
+      let :params do {
+          :default_ssl_vhost  => true
+        }
+      end
+      it { is_expected.to contain_apache__vhost('default-ssl').with_ensure('present') }
+      it { is_expected.to contain_file('/var/www/html') }
+    end
+  end
+  context 'with unsupported osfamily' do
+    let :facts do
+      { :osfamily        => 'Darwin',
+        :operatingsystemrelease => '13.1.0',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+
+    it do
+      expect {
+       catalogue
+      }.to raise_error(Puppet::Error, /Unsupported osfamily/)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/dev_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,90 @@
+require 'spec_helper'
+
+describe 'apache::dev', :type => :class do
+  let(:pre_condition) {[
+    'include apache'
+  ]}
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :lsbdistcodename        => 'squeeze',
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :is_pe                  => false,
+        :concat_basedir         => '/foo',
+        :id                     => 'root',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin',
+        :kernel                 => 'Linux'
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_package("libaprutil1-dev") }
+    it { is_expected.to contain_package("libapr1-dev") }
+    it { is_expected.to contain_package("apache2-prefork-dev") }
+  end
+  context "on an Ubuntu 14 OS" do
+    let :facts do
+      {
+        :lsbdistrelease         => '14.04',
+        :lsbdistcodename        => 'trusty',
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Ubuntu',
+        :operatingsystemrelease => '14.04',
+        :is_pe                  => false,
+        :concat_basedir         => '/foo',
+        :id                     => 'root',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin',
+        :kernel                 => 'Linux'
+      }
+    end
+    it { is_expected.to contain_package("apache2-dev") }
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '6',
+        :is_pe                  => false,
+        :concat_basedir         => '/foo',
+        :id                     => 'root',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin',
+        :kernel                 => 'Linux'
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_package("httpd-devel") }
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystem        => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :is_pe                  => false,
+        :concat_basedir         => '/foo',
+        :id                     => 'root',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin',
+        :kernel                 => 'FreeBSD'
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+        :concat_basedir         => '/foo',
+        :id                     => 'root',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin',
+        :kernel                 => 'Linux'
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/alias_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,96 @@
+require 'spec_helper'
+
+describe 'apache::mod::alias', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :lsbdistcodename        => 'squeeze',
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_apache__mod("alias") }
+    it { is_expected.to contain_file("alias.conf").with(:content => /Alias \/icons\/ "\/usr\/share\/apache2\/icons\/"/) }
+  end
+  context "on a RedHat 6-based OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_apache__mod("alias") }
+    it { is_expected.to contain_file("alias.conf").with(:content => /Alias \/icons\/ "\/var\/www\/icons\/"/) }
+  end
+  context "on a RedHat 7-based OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '7',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_apache__mod("alias") }
+    it { is_expected.to contain_file("alias.conf").with(:content => /Alias \/icons\/ "\/usr\/share\/httpd\/icons\/"/) }
+  end
+  context "with icons options", :compile do
+    let :pre_condition do
+      'class { apache: default_mods => false }'
+    end
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '7',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    let :params do
+      {
+        'icons_options' => 'foo'
+      }
+    end
+    it { is_expected.to contain_apache__mod("alias") }
+    it { is_expected.to contain_file("alias.conf").with(:content => /Options foo/) }
+  end
+  context "on a FreeBSD OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :osfamily               => 'FreeBSD',
+        :operatingsystem        => 'FreeBSD',
+        :operatingsystemrelease => '10',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_apache__mod("alias") }
+    it { is_expected.to contain_file("alias.conf").with(:content => /Alias \/icons\/ "\/usr\/local\/www\/apache24\/icons\/"/) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/auth_cas_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+describe 'apache::mod::auth_cas', :type => :class do
+  let :params do
+    {
+      :cas_login_url    => 'https://cas.example.com/login',
+      :cas_validate_url => 'https://cas.example.com/validate',
+    }
+  end
+
+  let :pre_condition do
+    'include ::apache'
+  end
+
+  context "on a Debian OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :lsbdistcodename        => 'squeeze',
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod("auth_cas") }
+    it { is_expected.to contain_package("libapache2-mod-auth-cas") }
+    it { is_expected.to contain_file("auth_cas.conf").with_path('/etc/apache2/mods-available/auth_cas.conf') }
+    it { is_expected.to contain_file("/var/cache/apache2/mod_auth_cas/").with_owner('www-data') }
+  end
+  context "on a RedHat OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod("auth_cas") }
+    it { is_expected.to contain_package("mod_auth_cas") }
+    it { is_expected.to contain_file("auth_cas.conf").with_path('/etc/httpd/conf.d/auth_cas.conf') }
+    it { is_expected.to contain_file("/var/cache/mod_auth_cas/").with_owner('apache') }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/auth_kerb_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,76 @@
+require 'spec_helper'
+
+describe 'apache::mod::auth_kerb', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :lsbdistcodename        => 'squeeze',
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod("auth_kerb") }
+    it { is_expected.to contain_package("libapache2-mod-auth-kerb") }
+  end
+  context "on a RedHat OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod("auth_kerb") }
+    it { is_expected.to contain_package("mod_auth_kerb") }
+  end
+  context "on a FreeBSD OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :osfamily               => 'FreeBSD',
+        :operatingsystem        => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod("auth_kerb") }
+    it { is_expected.to contain_package("www/mod_auth_kerb2") }
+  end
+  context "on a Gentoo OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod("auth_kerb") }
+    it { is_expected.to contain_package("www-apache/mod_auth_kerb") }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/auth_mellon_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,87 @@
+describe 'apache::mod::auth_mellon', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :fqdn                   => 'test.example.com',
+        :is_pe                  => false,
+      }
+    end
+    describe 'with no parameters' do
+      it { should contain_apache__mod('auth_mellon') }
+      it { should contain_package('libapache2-mod-auth-mellon') }
+      it { should contain_file('auth_mellon.conf').with_path('/etc/apache2/mods-available/auth_mellon.conf') }
+      it { should contain_file('auth_mellon.conf').with_content("MellonPostDirectory \"\/var\/cache\/apache2\/mod_auth_mellon\/\"\n") }
+    end
+    describe 'with parameters' do
+      let :params do
+        { :mellon_cache_size => '200',
+          :mellon_cache_entry_size => '2010',
+          :mellon_lock_file => '/tmp/junk',
+          :mellon_post_directory => '/tmp/post',
+          :mellon_post_ttl => '5',
+          :mellon_post_size => '8',
+          :mellon_post_count => '10'
+        }
+      end
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonCacheSize\s+200$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonCacheEntrySize\s+2010$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonLockFile\s+"\/tmp\/junk"$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonPostDirectory\s+"\/tmp\/post"$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonPostTTL\s+5$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonPostSize\s+8$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonPostCount\s+10$/) }
+    end
+
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :fqdn                   => 'test.example.com',
+        :is_pe                  => false,
+      }
+    end
+    describe 'with no parameters' do
+      it { should contain_apache__mod('auth_mellon') }
+      it { should contain_package('mod_auth_mellon') }
+      it { should contain_file('auth_mellon.conf').with_path('/etc/httpd/conf.d/auth_mellon.conf') }
+      it { should contain_file('auth_mellon.conf').with_content("MellonCacheSize 100\nMellonLockFile \"/run/mod_auth_mellon/lock\"\n") }
+    end
+    describe 'with parameters' do
+      let :params do
+        { :mellon_cache_size => '200',
+          :mellon_cache_entry_size => '2010',
+          :mellon_lock_file => '/tmp/junk',
+          :mellon_post_directory => '/tmp/post',
+          :mellon_post_ttl => '5',
+          :mellon_post_size => '8',
+          :mellon_post_count => '10'
+        }
+      end
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonCacheSize\s+200$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonCacheEntrySize\s+2010$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonLockFile\s+"\/tmp\/junk"$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonPostDirectory\s+"\/tmp\/post"$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonPostTTL\s+5$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonPostSize\s+8$/) }
+      it { should contain_file('auth_mellon.conf').with_content(/^MellonPostCount\s+10$/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/authnz_ldap_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,78 @@
+require 'spec_helper'
+
+describe 'apache::mod::authnz_ldap', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :lsbdistcodename        => 'squeeze',
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :operatingsystem        => 'Debian',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_class("apache::mod::ldap") }
+    it { is_expected.to contain_apache__mod('authnz_ldap') }
+
+    context 'default verifyServerCert' do
+      it { is_expected.to contain_file('authnz_ldap.conf').with_content(/^LDAPVerifyServerCert On$/) }
+    end
+
+    context 'verifyServerCert = false' do
+      let(:params) { { :verifyServerCert => false } }
+      it { is_expected.to contain_file('authnz_ldap.conf').with_content(/^LDAPVerifyServerCert Off$/) }
+    end
+
+    context 'verifyServerCert = wrong' do
+      let(:params) { { :verifyServerCert => 'wrong' } }
+      it 'should raise an error' do
+        expect { is_expected.to raise_error Puppet::Error }
+      end
+    end
+  end #Debian
+
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :operatingsystem        => 'RedHat',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_class("apache::mod::ldap") }
+    it { is_expected.to contain_apache__mod('authnz_ldap') }
+
+    context 'default verifyServerCert' do
+      it { is_expected.to contain_file('authnz_ldap.conf').with_content(/^LDAPVerifyServerCert On$/) }
+    end
+
+    context 'verifyServerCert = false' do
+      let(:params) { { :verifyServerCert => false } }
+      it { is_expected.to contain_file('authnz_ldap.conf').with_content(/^LDAPVerifyServerCert Off$/) }
+    end
+
+    context 'verifyServerCert = wrong' do
+      let(:params) { { :verifyServerCert => 'wrong' } }
+      it 'should raise an error' do
+        expect { is_expected.to raise_error Puppet::Error }
+      end
+    end
+  end # Redhat
+
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/dav_svn_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,79 @@
+require 'spec_helper'
+
+describe 'apache::mod::dav_svn', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :lsbdistcodename           => 'squeeze',
+        :osfamily                  => 'Debian',
+        :operatingsystemrelease    => '6',
+        :operatingsystemmajrelease => '6',
+        :concat_basedir            => '/dne',
+        :operatingsystem           => 'Debian',
+        :id                        => 'root',
+        :kernel                    => 'Linux',
+        :path                      => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('dav_svn') }
+    it { is_expected.to contain_package("libapache2-svn") }
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily                  => 'RedHat',
+        :operatingsystemrelease    => '6',
+        :operatingsystemmajrelease => '6',
+        :concat_basedir            => '/dne',
+        :operatingsystem           => 'RedHat',
+        :id                        => 'root',
+        :kernel                    => 'Linux',
+        :path                      => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('dav_svn') }
+    it { is_expected.to contain_package("mod_dav_svn") }
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily                  => 'FreeBSD',
+        :operatingsystemrelease    => '9',
+        :operatingsystemmajrelease => '9',
+        :concat_basedir            => '/dne',
+        :operatingsystem           => 'FreeBSD',
+        :id                        => 'root',
+        :kernel                    => 'Linux',
+        :path                      => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('dav_svn') }
+    it { is_expected.to contain_package("devel/subversion") }
+  end
+  context "on a Gentoo OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :kernel                 => 'Linux',
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('dav_svn') }
+    it { is_expected.to contain_package("dev-vcs/subversion") }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/deflate_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,126 @@
+require 'spec_helper'
+
+# This function is called inside the OS specific contexts
+def general_deflate_specs
+  it { is_expected.to contain_apache__mod("deflate") }
+
+  it do
+    is_expected.to contain_file("deflate.conf").with_content(
+      "AddOutputFilterByType DEFLATE text/css\n"\
+      "AddOutputFilterByType DEFLATE text/html\n"\
+      "\n"\
+      "DeflateFilterNote Input instream\n"\
+      "DeflateFilterNote Ratio ratio\n"
+    )
+  end
+end
+
+describe 'apache::mod::deflate', :type => :class do
+  let :pre_condition do
+    'class { "apache":
+      default_mods => false,
+    }
+    class { "apache::mod::deflate":
+      types => [ "text/html", "text/css" ],
+      notes => {
+        "Input" => "instream",
+        "Ratio" => "ratio",
+      }
+    }
+    '
+  end
+
+  context "On a Debian OS with default params" do
+    let :facts do
+      {
+        :id                     => 'root',
+        :lsbdistcodename        => 'squeeze',
+        :kernel                 => 'Linux',
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+
+    # Load the more generic tests for this context
+    general_deflate_specs()
+
+    it { is_expected.to contain_file("deflate.conf").with({
+      :ensure => 'file',
+      :path   => '/etc/apache2/mods-available/deflate.conf',
+    } ) }
+    it { is_expected.to contain_file("deflate.conf symlink").with({
+      :ensure => 'link',
+      :path   => '/etc/apache2/mods-enabled/deflate.conf',
+    } ) }
+  end
+
+  context "on a RedHat OS with default params" do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+
+    # Load the more generic tests for this context
+    general_deflate_specs()
+
+    it { is_expected.to contain_file("deflate.conf").with_path("/etc/httpd/conf.d/deflate.conf") }
+  end
+
+  context "On a FreeBSD OS with default params" do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :osfamily               => 'FreeBSD',
+        :operatingsystem        => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+
+    # Load the more generic tests for this context
+    general_deflate_specs()
+
+    it { is_expected.to contain_file("deflate.conf").with({
+      :ensure => 'file',
+      :path   => '/usr/local/etc/apache24/Modules/deflate.conf',
+    } ) }
+  end
+
+  context "On a Gentoo OS with default params" do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+
+    # Load the more generic tests for this context
+    general_deflate_specs()
+
+    it { is_expected.to contain_file("deflate.conf").with({
+      :ensure => 'file',
+      :path   => '/etc/apache2/modules.d/deflate.conf',
+    } ) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/dev_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,29 @@
+require 'spec_helper'
+
+describe 'apache::mod::dev', :type => :class do
+  let(:pre_condition) {[
+    'include apache'
+  ]}
+  [
+    ['RedHat',  '6', 'Santiago', 'Linux'],
+    ['Debian',  '6', 'squeeze', 'Linux'],
+    ['FreeBSD', '9', 'FreeBSD', 'FreeBSD'],
+  ].each do |osfamily, operatingsystemrelease, lsbdistcodename, kernel|
+    context "on a #{osfamily} OS" do
+      let :facts do
+        {
+          :lsbdistcodename        => lsbdistcodename,
+          :osfamily               => osfamily,
+          :operatingsystem        => osfamily,
+          :operatingsystemrelease => operatingsystemrelease,
+          :is_pe                  => false,
+          :concat_basedir         => '/foo',
+          :id                     => 'root',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin',
+          :kernel                 => kernel
+        }
+      end
+      it { is_expected.to contain_class('apache::dev') }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/dir_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,138 @@
+require 'spec_helper'
+
+describe 'apache::mod::dir', :type => :class do
+  let :pre_condition do
+    'class { "apache":
+      default_mods => false,
+    }'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :lsbdistcodename        => 'squeeze',
+        :is_pe                  => false,
+      }
+    end
+    context "passing no parameters" do
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('dir') }
+      it { is_expected.to contain_file('dir.conf').with_content(/^DirectoryIndex /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.html /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.html\.var /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.cgi /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.pl /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.php /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.xhtml$/) }
+    end
+    context "passing indexes => ['example.txt','fearsome.aspx']" do
+      let :params do
+        {:indexes => ['example.txt','fearsome.aspx']}
+      end
+      it { is_expected.to contain_file('dir.conf').with_content(/ example\.txt /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ fearsome\.aspx$/) }
+    end
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'Redhat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    context "passing no parameters" do
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('dir') }
+      it { is_expected.to contain_file('dir.conf').with_content(/^DirectoryIndex /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.html /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.html\.var /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.cgi /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.pl /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.php /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.xhtml$/) }
+    end
+    context "passing indexes => ['example.txt','fearsome.aspx']" do
+      let :params do
+        {:indexes => ['example.txt','fearsome.aspx']}
+      end
+      it { is_expected.to contain_file('dir.conf').with_content(/ example\.txt /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ fearsome\.aspx$/) }
+    end
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    context "passing no parameters" do
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('dir') }
+      it { is_expected.to contain_file('dir.conf').with_content(/^DirectoryIndex /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.html /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.html\.var /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.cgi /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.pl /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.php /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.xhtml$/) }
+    end
+    context "passing indexes => ['example.txt','fearsome.aspx']" do
+      let :params do
+        {:indexes => ['example.txt','fearsome.aspx']}
+      end
+      it { is_expected.to contain_file('dir.conf').with_content(/ example\.txt /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ fearsome\.aspx$/) }
+    end
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    context "passing no parameters" do
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('dir') }
+      it { is_expected.to contain_file('dir.conf').with_content(/^DirectoryIndex /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.html /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.html\.var /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.cgi /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.pl /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.php /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ index\.xhtml$/) }
+    end
+    context "passing indexes => ['example.txt','fearsome.aspx']" do
+      let :params do
+        {:indexes => ['example.txt','fearsome.aspx']}
+      end
+      it { is_expected.to contain_file('dir.conf').with_content(/ example\.txt /) }
+      it { is_expected.to contain_file('dir.conf').with_content(/ fearsome\.aspx$/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/disk_cache.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,111 @@
+require 'spec_helper'
+
+describe 'apache::mod::disk_cache', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :lsbdistcodename        => 'squeeze',
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    context "with Apache version < 2.4" do
+      let :params do
+        {
+          :apache_version => '2.2',
+        }
+      end
+
+      it { is_expected.to contain_apache__mod("disk_cache") }
+      it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/apache2\/mod_disk_cache\"\nCacheDirLevels 2\nCacheDirLength 1/) }
+    end
+    context "with Apache version >= 2.4" do
+      let :params do
+        {
+          :apache_version => '2.4',
+        }
+      end
+
+      it { is_expected.to contain_apache__mod("cache_disk") }
+      it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/apache2\/mod_cache_disk\"\nCacheDirLevels 2\nCacheDirLength 1/) }
+    end
+  end
+
+  context "on a RedHat 6-based OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    context "with Apache version < 2.4" do
+      let :params do
+        {
+          :apache_version => '2.2',
+        }
+      end
+
+      it { is_expected.to contain_apache__mod("disk_cache") }
+      it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/httpd\/proxy\"\nCacheDirLevels 2\nCacheDirLength 1/) }
+    end
+    context "with Apache version >= 2.4" do
+      let :params do
+        {
+          :apache_version => '2.4',
+        }
+      end
+
+      it { is_expected.to contain_apache__mod("cache_disk") }
+      it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/httpd\/proxy\"\nCacheDirLevels 2\nCacheDirLength 1/) }
+    end
+  end
+  context "on a FreeBSD OS", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :osfamily               => 'FreeBSD',
+        :operatingsystem        => 'FreeBSD',
+        :operatingsystemrelease => '10',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    context "with Apache version < 2.4" do
+      let :params do
+        {
+          :apache_version => '2.2',
+        }
+      end
+
+      it { is_expected.to contain_apache__mod("disk_cache") }
+      it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/mod_cache_disk\"\nCacheDirLevels 2\nCacheDirLength 1/) }
+    end
+    context "with Apache version >= 2.4" do
+      let :params do
+        {
+          :apache_version => '2.4',
+        }
+      end
+
+      it { is_expected.to contain_apache__mod("cache_disk") }
+      it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/mod_cache_disk\"\nCacheDirLevels 2\nCacheDirLength 1/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/event_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,154 @@
+require 'spec_helper'
+
+describe 'apache::mod::event', :type => :class do
+  let :pre_condition do
+    'class { "apache": mpm_module => false, }'
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('event') }
+    it { is_expected.to contain_file("/usr/local/etc/apache24/Modules/event.conf").with_ensure('file') }
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('event') }
+    it { is_expected.to contain_file("/etc/apache2/modules.d/event.conf").with_ensure('file') }
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :lsbdistcodename        => 'squeeze',
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('event') }
+    it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file') }
+    it { is_expected.to contain_file("/etc/apache2/mods-enabled/event.conf").with_ensure('link') }
+
+    context "Test mpm_event params" do
+      let :params do
+        {
+          :serverlimit            => '0',
+          :startservers           => '1',
+          :maxclients             => '2',
+          :minsparethreads        => '3',
+          :maxsparethreads        => '4',
+          :threadsperchild        => '5',
+          :maxrequestsperchild    => '6',
+          :threadlimit            => '7',
+          :listenbacklog          => '8',
+          :maxrequestworkers      => '9',
+          :maxconnectionsperchild => '10',
+        }
+      end
+
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file').with_content(/^\s*ServerLimit\s*0/) }
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file').with_content(/^\s*StartServers\s*1/) }
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file').with_content(/^\s*MaxClients\s*2/) }
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file').with_content(/^\s*MinSpareThreads\s*3/) }
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file').with_content(/^\s*MaxSpareThreads\s*4/) }
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file').with_content(/^\s*ThreadsPerChild\s*5/) }
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file').with_content(/^\s*MaxRequestsPerChild\s*6/) }
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file').with_content(/^\s*ThreadLimit\s*7/) }
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file').with_content(/^\s*ListenBacklog\s*8/) }
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file').with_content(/^\s*MaxRequestWorkers\s*9/) }
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.conf").with_ensure('file').with_content(/^\s*MaxConnectionsPerChild\s*10/) }
+    end
+
+    context "with Apache version < 2.4" do
+      let :params do
+        {
+          :apache_version => '2.2',
+        }
+      end
+
+      it { is_expected.not_to contain_file("/etc/apache2/mods-available/event.load") }
+      it { is_expected.not_to contain_file("/etc/apache2/mods-enabled/event.load") }
+
+      it { is_expected.to contain_package("apache2-mpm-event") }
+    end
+
+    context "with Apache version >= 2.4" do
+      let :params do
+        {
+          :apache_version => '2.4',
+        }
+      end
+
+      it { is_expected.to contain_file("/etc/apache2/mods-available/event.load").with({
+        'ensure'  => 'file',
+        'content' => "LoadModule mpm_event_module /usr/lib/apache2/modules/mod_mpm_event.so\n"
+        })
+      }
+      it { is_expected.to contain_file("/etc/apache2/mods-enabled/event.load").with_ensure('link') }
+    end
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    context "with Apache version >= 2.4" do
+      let :params do
+        {
+          :apache_version => '2.4',
+        }
+      end
+
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.not_to contain_apache__mod('worker') }
+      it { is_expected.not_to contain_apache__mod('prefork') }
+
+      it { is_expected.to contain_file("/etc/httpd/conf.d/event.conf").with_ensure('file') }
+
+      it { is_expected.to contain_file("/etc/httpd/conf.d/event.load").with({
+        'ensure'  => 'file',
+        'content' => "LoadModule mpm_event_module modules/mod_mpm_event.so\n",
+        })
+      }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/expires_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,84 @@
+require 'spec_helper'
+
+describe 'apache::mod::expires', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "with expires active", :compile do
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :lsbdistcodename        => 'squeeze',
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_apache__mod("expires") }
+    it { is_expected.to contain_file("expires.conf").with(:content => /ExpiresActive On\n/) }
+  end
+  context "with expires default", :compile do
+    let :pre_condition do
+      'class { apache: default_mods => false }'
+    end
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '7',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    let :params do
+      {
+        'expires_default' => 'access plus 1 month'
+      }
+    end
+    it { is_expected.to contain_apache__mod("expires") }
+    it { is_expected.to contain_file("expires.conf").with_content(
+        "ExpiresActive On\n" \
+        "ExpiresDefault \"access plus 1 month\"\n"
+      )
+    }
+  end
+  context "with expires by type", :compile do
+    let :pre_condition do
+      'class { apache: default_mods => false }'
+    end
+    let :facts do
+      {
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'RedHat',
+        :operatingsystemrelease => '7',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :concat_basedir         => '/dne',
+        :is_pe                  => false,
+      }
+    end
+    let :params do
+      {
+        'expires_by_type' => [
+          { 'text/json' => 'mod plus 1 day' },
+          { 'text/html' => 'access plus 1 year' },
+        ]
+      }
+    end
+    it { is_expected.to contain_apache__mod("expires") }
+    it { is_expected.to contain_file("expires.conf").with_content(
+        "ExpiresActive On\n" \
+        "ExpiresByType text/json \"mod plus 1 day\"\n" \
+        "ExpiresByType text/html \"access plus 1 year\"\n"
+      )
+    }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/ext_filter_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,66 @@
+describe 'apache::mod::ext_filter', :type => :class do
+  let :pre_condition do
+    'class { "apache":
+      default_mods => false,
+    }'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :fqdn                   => 'test.example.com',
+        :is_pe                  => false,
+      }
+    end
+    describe 'with no parameters' do
+      it { is_expected.to contain_apache__mod('ext_filter') }
+      it { is_expected.not_to contain_file('ext_filter.conf') }
+    end
+    describe 'with parameters' do
+      let :params do
+        { :ext_filter_define =>  {'filtA' => 'input=A output=B',
+                                  'filtB' => 'input=C cmd="C"' },
+        }
+      end
+      it { is_expected.to contain_file('ext_filter.conf').with_content(/^ExtFilterDefine\s+filtA\s+input=A output=B$/) }
+      it { is_expected.to contain_file('ext_filter.conf').with_content(/^ExtFilterDefine\s+filtB\s+input=C cmd="C"$/) }
+    end
+
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :fqdn                   => 'test.example.com',
+        :is_pe                  => false,
+      }
+    end
+    describe 'with no parameters' do
+      it { is_expected.to contain_apache__mod('ext_filter') }
+      it { is_expected.not_to contain_file('ext_filter.conf') }
+    end
+    describe 'with parameters' do
+      let :params do
+        { :ext_filter_define =>  {'filtA' => 'input=A output=B',
+                                  'filtB' => 'input=C cmd="C"' },
+        }
+      end
+      it { is_expected.to contain_file('ext_filter.conf').with_path('/etc/httpd/conf.d/ext_filter.conf') }
+      it { is_expected.to contain_file('ext_filter.conf').with_content(/^ExtFilterDefine\s+filtA\s+input=A output=B$/) }
+      it { is_expected.to contain_file('ext_filter.conf').with_content(/^ExtFilterDefine\s+filtB\s+input=C cmd="C"$/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/fastcgi_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+require 'spec_helper'
+
+describe 'apache::mod::fastcgi', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('fastcgi') }
+    it { is_expected.to contain_package("libapache2-mod-fastcgi") }
+    it { is_expected.to contain_file('fastcgi.conf') }
+  end
+
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('fastcgi') }
+    it { is_expected.to contain_package("mod_fastcgi") }
+    it { is_expected.not_to contain_file('fastcgi.conf') }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/fcgid_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,143 @@
+require 'spec_helper'
+
+describe 'apache::mod::fcgid', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily                  => 'Debian',
+        :operatingsystemrelease    => '6',
+        :operatingsystemmajrelease => '6',
+        :concat_basedir            => '/dne',
+        :lsbdistcodename           => 'squeeze',
+        :operatingsystem           => 'Debian',
+        :id                        => 'root',
+        :kernel                    => 'Linux',
+        :path                      => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('fcgid').with({
+      'loadfile_name' => 'unixd_fcgid.load'
+    }) }
+    it { is_expected.to contain_package("libapache2-mod-fcgid") }
+  end
+
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily                  => 'RedHat',
+        :operatingsystemrelease    => '6',
+        :operatingsystemmajrelease => '6',
+        :concat_basedir            => '/dne',
+        :operatingsystem           => 'RedHat',
+        :id                        => 'root',
+        :kernel                    => 'Linux',
+        :path                      => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                     => false,
+      }
+    end
+
+    describe 'without parameters' do
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('fcgid').with({
+        'loadfile_name' => 'unixd_fcgid.load'
+      }) }
+      it { is_expected.to contain_package("mod_fcgid") }
+    end
+
+    describe 'with parameters' do
+      let :params do {
+        :options                     => {
+          'FcgidIPCDir'               => '/var/run/fcgidsock',
+          'SharememPath'              => '/var/run/fcgid_shm',
+          'FcgidMinProcessesPerClass' => '0',
+          'AddHandler'                => 'fcgid-script .fcgi',
+        }
+      } end
+
+      it 'should contain the correct config' do
+        content = catalogue.resource('file', 'unixd_fcgid.conf').send(:parameters)[:content]
+        expect(content.split("\n").reject { |c| c =~ /(^#|^$)/ }).to eq([
+          '<IfModule mod_fcgid.c>',
+          '  AddHandler fcgid-script .fcgi',
+          '  FcgidIPCDir /var/run/fcgidsock',
+          '  FcgidMinProcessesPerClass 0',
+          '  SharememPath /var/run/fcgid_shm',
+          '</IfModule>',
+        ])
+      end
+    end
+  end
+
+  context "on RHEL7" do
+    let :facts do
+      {
+        :osfamily                  => 'RedHat',
+        :operatingsystemrelease    => '7',
+        :operatingsystemmajrelease => '7',
+        :concat_basedir            => '/dne',
+        :operatingsystem           => 'RedHat',
+        :id                        => 'root',
+        :kernel                    => 'Linux',
+        :path                      => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    describe 'without parameters' do
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('fcgid').with({
+        'loadfile_name' => 'unixd_fcgid.load'
+      }) }
+      it { is_expected.to contain_package("mod_fcgid") }
+    end
+  end
+
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily                  => 'FreeBSD',
+        :operatingsystemrelease    => '10',
+        :operatingsystemmajrelease => '10',
+        :concat_basedir            => '/dne',
+        :operatingsystem           => 'FreeBSD',
+        :id                        => 'root',
+        :kernel                    => 'FreeBSD',
+        :path                      => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('fcgid').with({
+      'loadfile_name' => 'unixd_fcgid.load'
+    }) }
+    it { is_expected.to contain_package("www/mod_fcgid") }
+  end
+
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily                  => 'Gentoo',
+        :operatingsystem           => 'Gentoo',
+        :operatingsystemrelease    => '3.16.1-gentoo',
+        :concat_basedir            => '/dne',
+        :id                        => 'root',
+        :kernel                    => 'Linux',
+        :path                      => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('fcgid').with({
+      'loadfile_name' => 'unixd_fcgid.load'
+    }) }
+    it { is_expected.to contain_package("www-apache/mod_fcgid") }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/info_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,222 @@
+# This function is called inside the OS specific contexts
+def general_info_specs_22
+  it { is_expected.to contain_apache__mod('info') }
+
+  context 'passing no parameters' do
+    it {
+      is_expected.to contain_file('info.conf').with_content(
+        "<Location /server-info>\n"\
+        "    SetHandler server-info\n"\
+        "    Order deny,allow\n"\
+        "    Deny from all\n"\
+        "    Allow from 127.0.0.1\n"\
+        "    Allow from ::1\n"\
+        "</Location>\n"
+      )
+    }
+  end
+  context 'passing restrict_access => false' do
+    let :params do {
+      :restrict_access => false
+    }
+    end
+    it {
+      is_expected.to contain_file('info.conf').with_content(
+        "<Location /server-info>\n"\
+        "    SetHandler server-info\n"\
+        "</Location>\n"
+      )
+    }
+  end
+  context "passing allow_from => ['10.10.1.2', '192.168.1.2', '127.0.0.1']" do
+    let :params do
+      {:allow_from => ['10.10.1.2', '192.168.1.2', '127.0.0.1']}
+    end
+    it {
+      is_expected.to contain_file('info.conf').with_content(
+        "<Location /server-info>\n"\
+        "    SetHandler server-info\n"\
+        "    Order deny,allow\n"\
+        "    Deny from all\n"\
+        "    Allow from 10.10.1.2\n"\
+        "    Allow from 192.168.1.2\n"\
+        "    Allow from 127.0.0.1\n"\
+        "</Location>\n"
+      )
+    }
+  end
+  context 'passing both restrict_access and allow_from' do
+    let :params do
+      {
+        :restrict_access => false,
+        :allow_from      => ['10.10.1.2', '192.168.1.2', '127.0.0.1']
+      }
+    end
+    it {
+      is_expected.to contain_file('info.conf').with_content(
+        "<Location /server-info>\n"\
+        "    SetHandler server-info\n"\
+        "</Location>\n"
+      )
+    }
+  end
+end
+
+def general_info_specs_24
+  it { is_expected.to contain_apache__mod('info') }
+
+  context 'passing no parameters' do
+    it {
+      is_expected.to contain_file('info.conf').with_content(
+        "<Location /server-info>\n"\
+        "    SetHandler server-info\n"\
+        "    Require ip 127.0.0.1 ::1\n"\
+        "</Location>\n"
+      )
+    }
+  end
+  context 'passing restrict_access => false' do
+    let :params do {
+      :restrict_access => false
+    }
+    end
+    it {
+      is_expected.to contain_file('info.conf').with_content(
+        "<Location /server-info>\n"\
+        "    SetHandler server-info\n"\
+        "</Location>\n"
+      )
+    }
+  end
+  context "passing allow_from => ['10.10.1.2', '192.168.1.2', '127.0.0.1']" do
+    let :params do
+      {:allow_from => ['10.10.1.2', '192.168.1.2', '127.0.0.1']}
+    end
+    it {
+      is_expected.to contain_file('info.conf').with_content(
+        "<Location /server-info>\n"\
+        "    SetHandler server-info\n"\
+        "    Require ip 10.10.1.2 192.168.1.2 127.0.0.1\n"\
+        "</Location>\n"
+      )
+    }
+  end
+  context 'passing both restrict_access and allow_from' do
+    let :params do
+      {
+        :restrict_access => false,
+        :allow_from      => ['10.10.1.2', '192.168.1.2', '127.0.0.1']
+      }
+    end
+    it {
+      is_expected.to contain_file('info.conf').with_content(
+        "<Location /server-info>\n"\
+        "    SetHandler server-info\n"\
+        "</Location>\n"
+      )
+    }
+  end
+end
+
+describe 'apache::mod::info', :type => :class do
+  let :pre_condition do
+    "class { 'apache': default_mods => false, }"
+  end
+
+  context 'On a Debian OS' do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    # Load the more generic tests for this context
+    general_info_specs_22()
+
+    it { is_expected.to contain_file('info.conf').with({
+      :ensure => 'file',
+      :path   => '/etc/apache2/mods-available/info.conf',
+    } ) }
+    it { is_expected.to contain_file('info.conf symlink').with({
+      :ensure => 'link',
+      :path   => '/etc/apache2/mods-enabled/info.conf',
+    } ) }
+  end
+
+  context 'on a RedHat OS' do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    # Load the more generic tests for this context
+    general_info_specs_22()
+
+    it { is_expected.to contain_file('info.conf').with({
+      :ensure => 'file',
+      :path   => '/etc/httpd/conf.d/info.conf',
+      } ) }
+  end
+
+  context 'on a FreeBSD OS' do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '10',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    # Load the more generic tests for this context
+    general_info_specs_24()
+
+    it { is_expected.to contain_file('info.conf').with({
+      :ensure => 'file',
+      :path   => '/usr/local/etc/apache24/Modules/info.conf',
+    } ) }
+  end
+
+  context 'on a Gentoo OS' do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    # Load the more generic tests for this context
+    general_info_specs_24()
+
+    it { is_expected.to contain_file('info.conf').with({
+      :ensure => 'file',
+      :path   => '/etc/apache2/modules.d/info.conf',
+    } ) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/itk_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+describe 'apache::mod::itk', :type => :class do
+  let :pre_condition do
+    'class { "apache": mpm_module => false, }'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('itk') }
+    it { is_expected.to contain_file("/etc/apache2/mods-available/itk.conf").with_ensure('file') }
+    it { is_expected.to contain_file("/etc/apache2/mods-enabled/itk.conf").with_ensure('link') }
+
+    context "with Apache version < 2.4" do
+      let :params do
+        {
+          :apache_version => '2.2',
+        }
+      end
+
+      it { is_expected.not_to contain_file("/etc/apache2/mods-available/itk.load") }
+      it { is_expected.not_to contain_file("/etc/apache2/mods-enabled/itk.load") }
+
+      it { is_expected.to contain_package("apache2-mpm-itk") }
+    end
+
+    context "with Apache version >= 2.4" do
+      let :params do
+        {
+          :apache_version => '2.4',
+        }
+      end
+
+      it { is_expected.to contain_file("/etc/apache2/mods-available/itk.load").with({
+        'ensure'  => 'file',
+        'content' => "LoadModule mpm_itk_module /usr/lib/apache2/modules/mod_mpm_itk.so\n"
+        })
+      }
+      it { is_expected.to contain_file("/etc/apache2/mods-enabled/itk.load").with_ensure('link') }
+    end
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '10',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+        :mpm_module             => 'itk',
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('itk') }
+    it { is_expected.to contain_file("/usr/local/etc/apache24/Modules/itk.conf").with_ensure('file') }
+    it { is_expected.to contain_package("www/mod_mpm_itk") }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/mime_magic_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,112 @@
+require 'spec_helper'
+
+# This function is called inside the OS specific contexts
+def general_mime_magic_specs
+  it { is_expected.to contain_apache__mod("mime_magic") }
+end
+
+describe 'apache::mod::mime_magic', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+
+  context "On a Debian OS with default params" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    general_mime_magic_specs()
+
+    it do
+      is_expected.to contain_file("mime_magic.conf").with_content(
+        "MIMEMagicFile \"/etc/apache2/magic\"\n"
+      )
+    end
+
+    it { is_expected.to contain_file("mime_magic.conf").with({
+      :ensure => 'file',
+      :path   => '/etc/apache2/mods-available/mime_magic.conf',
+    } ) }
+    it { is_expected.to contain_file("mime_magic.conf symlink").with({
+      :ensure => 'link',
+      :path   => '/etc/apache2/mods-enabled/mime_magic.conf',
+    } ) }
+
+    context "with magic_file => /tmp/Debian_magic" do
+      let :params do
+        { :magic_file => "/tmp/Debian_magic" }
+      end
+
+      it do
+        is_expected.to contain_file("mime_magic.conf").with_content(
+          "MIMEMagicFile \"/tmp/Debian_magic\"\n"
+        )
+      end
+    end
+
+  end
+
+  context "on a RedHat OS with default params" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    general_mime_magic_specs()
+
+    it do
+      is_expected.to contain_file("mime_magic.conf").with_content(
+        "MIMEMagicFile \"/etc/httpd/conf/magic\"\n"
+      )
+    end
+
+    it { is_expected.to contain_file("mime_magic.conf").with_path("/etc/httpd/conf.d/mime_magic.conf") }
+
+  end
+
+  context "with magic_file => /tmp/magic" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    let :params do
+      { :magic_file => "/tmp/magic" }
+    end
+
+    it do
+      is_expected.to contain_file("mime_magic.conf").with_content(
+        "MIMEMagicFile \"/tmp/magic\"\n"
+      )
+    end
+  end
+
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/mime_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+# This function is called inside the OS specific conte, :compilexts
+def general_mime_specs
+  it { is_expected.to contain_apache__mod("mime") }
+end
+
+describe 'apache::mod::mime', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+
+  context "On a Debian OS with default params", :compile do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    general_mime_specs()
+
+    it { is_expected.to contain_file("mime.conf").with_path('/etc/apache2/mods-available/mime.conf') }
+
+  end
+
+  context "on a RedHat OS with default params", :compile do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    general_mime_specs()
+
+    it { is_expected.to contain_file("mime.conf").with_path("/etc/httpd/conf.d/mime.conf") }
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/negotiation_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,65 @@
+require 'spec_helper'
+
+describe 'apache::mod::negotiation', :type => :class do
+  describe "OS independent tests" do
+
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :kernel                 => 'Linux',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    context "default params" do
+      let :pre_condition do
+        'class {"::apache": }'
+      end
+      it { should contain_class("apache") }
+      it do
+        should contain_file('negotiation.conf').with( {
+          :ensure  => 'file',
+          :content => 'LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW
+ForceLanguagePriority Prefer Fallback
+',
+        } )
+      end
+    end
+
+    context 'with force_language_priority parameter' do
+      let :pre_condition do
+        'class {"::apache": default_mods => ["negotiation"]}'
+      end
+      let :params do
+        { :force_language_priority => 'Prefer' }
+      end
+      it do
+        should contain_file('negotiation.conf').with( {
+          :ensure  => 'file',
+          :content => /^ForceLanguagePriority Prefer$/,
+        } )
+      end
+    end
+
+    context 'with language_priority parameter' do
+      let :pre_condition do
+        'class {"::apache": default_mods => ["negotiation"]}'
+      end
+      let :params do
+        { :language_priority => [ 'en', 'es' ] }
+      end
+      it do
+        should contain_file('negotiation.conf').with( {
+          :ensure  => 'file',
+          :content => /^LanguagePriority en es$/,
+        } )
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/pagespeed_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+require 'spec_helper'
+
+describe 'apache::mod::pagespeed', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('pagespeed') }
+    it { is_expected.to contain_package("mod-pagespeed-stable") }
+    it { is_expected.to contain_file('pagespeed.conf') }
+  end
+
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('pagespeed') }
+    it { is_expected.to contain_package("mod-pagespeed-stable") }
+    it { is_expected.to contain_file('pagespeed.conf') }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/passenger_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,300 @@
+require 'spec_helper'
+
+describe 'apache::mod::passenger', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :kernel                 => 'Linux',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('passenger') }
+    it { is_expected.to contain_package("libapache2-mod-passenger") }
+    it { is_expected.to contain_file('zpassenger.load').with({
+      'path' => '/etc/apache2/mods-available/zpassenger.load',
+    }) }
+    it { is_expected.to contain_file('passenger.conf').with({
+      'path' => '/etc/apache2/mods-available/passenger.conf',
+    }) }
+    describe "with passenger_root => '/usr/lib/example'" do
+      let :params do
+        { :passenger_root => '/usr/lib/example' }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(%r{PassengerRoot "/usr/lib/example"}) }
+    end
+    describe "with passenger_ruby => /usr/lib/example/ruby" do
+      let :params do
+        { :passenger_ruby => '/usr/lib/example/ruby' }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(%r{PassengerRuby "/usr/lib/example/ruby"}) }
+    end
+    describe "with passenger_default_ruby => /usr/lib/example/ruby1.9.3" do
+      let :params do
+        { :passenger_ruby => '/usr/lib/example/ruby1.9.3' }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(%r{PassengerRuby "/usr/lib/example/ruby1.9.3"}) }
+    end
+    describe "with passenger_high_performance => on" do
+      let :params do
+        { :passenger_high_performance => 'on' }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  PassengerHighPerformance on$/) }
+    end
+    describe "with passenger_pool_idle_time => 1200" do
+      let :params do
+        { :passenger_pool_idle_time => 1200 }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  PassengerPoolIdleTime 1200$/) }
+    end
+    describe "with passenger_max_requests => 20" do
+      let :params do
+        { :passenger_max_requests => 20 }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  PassengerMaxRequests 20$/) }
+    end
+    describe "with passenger_spawn_method => bogus" do
+      let :params do
+        { :passenger_spawn_method => 'bogus' }
+      end
+      it { is_expected.to raise_error(Puppet::Error, /not permitted for passenger_spawn_method/) }
+    end
+    describe "with passenger_spawn_method => direct" do
+      let :params do
+        { :passenger_spawn_method => 'direct' }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  PassengerSpawnMethod direct$/) }
+    end
+    describe "with passenger_stat_throttle_rate => 10" do
+      let :params do
+        { :passenger_stat_throttle_rate => 10 }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  PassengerStatThrottleRate 10$/) }
+    end
+    describe "with passenger_max_pool_size => 16" do
+      let :params do
+        { :passenger_max_pool_size => 16 }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  PassengerMaxPoolSize 16$/) }
+    end
+    describe "with passenger_min_instances => 5" do
+      let :params do
+        { :passenger_min_instances => 5 }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  PassengerMinInstances 5$/) }
+    end
+    describe "with rack_autodetect => on" do
+      let :params do
+        { :rack_autodetect => 'on' }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  RackAutoDetect on$/) }
+    end
+    describe "with rails_autodetect => on" do
+      let :params do
+        { :rails_autodetect => 'on' }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  RailsAutoDetect on$/) }
+    end
+    describe "with passenger_use_global_queue => on" do
+      let :params do
+        { :passenger_use_global_queue => 'on' }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  PassengerUseGlobalQueue on$/) }
+    end
+    describe "with passenger_app_env => 'foo'" do
+      let :params do
+        { :passenger_app_env => 'foo' }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  PassengerAppEnv foo$/) }
+    end
+    describe "with mod_path => '/usr/lib/foo/mod_foo.so'" do
+      let :params do
+        { :mod_path => '/usr/lib/foo/mod_foo.so' }
+      end
+      it { is_expected.to contain_file('zpassenger.load').with_content(/^LoadModule passenger_module \/usr\/lib\/foo\/mod_foo\.so$/) }
+    end
+    describe "with mod_lib_path => '/usr/lib/foo'" do
+      let :params do
+        { :mod_lib_path => '/usr/lib/foo' }
+      end
+      it { is_expected.to contain_file('zpassenger.load').with_content(/^LoadModule passenger_module \/usr\/lib\/foo\/mod_passenger\.so$/) }
+    end
+    describe "with mod_lib => 'mod_foo.so'" do
+      let :params do
+        { :mod_lib => 'mod_foo.so' }
+      end
+      it { is_expected.to contain_file('zpassenger.load').with_content(/^LoadModule passenger_module \/usr\/lib\/apache2\/modules\/mod_foo\.so$/) }
+    end
+    describe "with mod_id => 'mod_foo'" do
+      let :params do
+        { :mod_id => 'mod_foo' }
+      end
+      it { is_expected.to contain_file('zpassenger.load').with_content(/^LoadModule mod_foo \/usr\/lib\/apache2\/modules\/mod_passenger\.so$/) }
+    end
+
+    context "with Ubuntu 12.04 defaults" do
+      let :facts do
+        {
+          :osfamily               => 'Debian',
+          :operatingsystemrelease => '12.04',
+          :kernel                 => 'Linux',
+          :operatingsystem        => 'Ubuntu',
+          :lsbdistrelease         => '12.04',
+          :concat_basedir         => '/dne',
+          :id                     => 'root',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+
+      it { is_expected.to contain_file('passenger.conf').with_content(%r{PassengerRoot "/usr"}) }
+      it { is_expected.to contain_file('passenger.conf').with_content(%r{PassengerRuby "/usr/bin/ruby"}) }
+      it { is_expected.to contain_file('passenger.conf').without_content(/PassengerDefaultRuby/) }
+    end
+
+    context "with Ubuntu 14.04 defaults" do
+      let :facts do
+        {
+          :osfamily               => 'Debian',
+          :operatingsystemrelease => '14.04',
+          :operatingsystem        => 'Ubuntu',
+          :kernel                 => 'Linux',
+          :lsbdistrelease         => '14.04',
+          :concat_basedir         => '/dne',
+          :id                     => 'root',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+
+      it { is_expected.to contain_file('passenger.conf').with_content(%r{PassengerRoot "/usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini"}) }
+      it { is_expected.to contain_file('passenger.conf').without_content(/PassengerRuby/) }
+      it { is_expected.to contain_file('passenger.conf').with_content(%r{PassengerDefaultRuby "/usr/bin/ruby"}) }
+    end
+
+    context "with Debian 7 defaults" do
+      let :facts do
+        {
+          :osfamily               => 'Debian',
+          :operatingsystemrelease => '7.3',
+          :operatingsystem        => 'Debian',
+          :kernel                 => 'Linux',
+          :lsbdistcodename        => 'wheezy',
+          :concat_basedir         => '/dne',
+          :id                     => 'root',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+
+      it { is_expected.to contain_file('passenger.conf').with_content(%r{PassengerRoot "/usr"}) }
+      it { is_expected.to contain_file('passenger.conf').with_content(%r{PassengerRuby "/usr/bin/ruby"}) }
+      it { is_expected.to contain_file('passenger.conf').without_content(/PassengerDefaultRuby/) }
+    end
+
+    context "with Debian 8 defaults" do
+      let :facts do
+        {
+          :osfamily               => 'Debian',
+          :operatingsystemrelease => '8.0',
+          :operatingsystem        => 'Debian',
+          :kernel                 => 'Linux',
+          :lsbdistcodename        => 'jessie',
+          :concat_basedir         => '/dne',
+          :id                     => 'root',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+
+      it { is_expected.to contain_file('passenger.conf').with_content(%r{PassengerRoot "/usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini"}) }
+      it { is_expected.to contain_file('passenger.conf').without_content(/PassengerRuby/) }
+      it { is_expected.to contain_file('passenger.conf').with_content(%r{PassengerDefaultRuby "/usr/bin/ruby"}) }
+    end
+  end
+
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('passenger') }
+    it { is_expected.to contain_package("mod_passenger") }
+    it { is_expected.to contain_file('passenger_package.conf').with({
+      'path' => '/etc/httpd/conf.d/passenger.conf',
+    }) }
+    it { is_expected.to contain_file('passenger_package.conf').without_content }
+    it { is_expected.to contain_file('passenger_package.conf').without_source }
+    it { is_expected.to contain_file('zpassenger.load').with({
+      'path' => '/etc/httpd/conf.d/zpassenger.load',
+    }) }
+    it { is_expected.to contain_file('passenger.conf').without_content(/PassengerRoot/) }
+    it { is_expected.to contain_file('passenger.conf').without_content(/PassengerRuby/) }
+    describe "with passenger_root => '/usr/lib/example'" do
+      let :params do
+        { :passenger_root => '/usr/lib/example' }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  PassengerRoot "\/usr\/lib\/example"$/) }
+    end
+    describe "with passenger_ruby => /usr/lib/example/ruby" do
+      let :params do
+        { :passenger_ruby => '/usr/lib/example/ruby' }
+      end
+      it { is_expected.to contain_file('passenger.conf').with_content(/^  PassengerRuby "\/usr\/lib\/example\/ruby"$/) }
+    end
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('passenger') }
+    it { is_expected.to contain_package("www/rubygem-passenger") }
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('passenger') }
+    it { is_expected.to contain_package("www-apache/passenger") }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/perl_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,76 @@
+require 'spec_helper'
+
+describe 'apache::mod::perl', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('perl') }
+    it { is_expected.to contain_package("libapache2-mod-perl2") }
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('perl') }
+    it { is_expected.to contain_package("mod_perl") }
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('perl') }
+    it { is_expected.to contain_package("www/mod_perl2") }
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'Gentoo',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('perl') }
+    it { is_expected.to contain_package("www-apache/mod_perl") }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/peruser_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe 'apache::mod::peruser', :type => :class do
+  let :pre_condition do
+    'class { "apache": mpm_module => false, }'
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '10',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it do
+      expect {
+        catalogue
+      }.to raise_error(Puppet::Error, /Unsupported osfamily FreeBSD/)
+    end
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('peruser') }
+    it { is_expected.to contain_file("/etc/apache2/modules.d/peruser.conf").with_ensure('file') }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/php_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,289 @@
+require 'spec_helper'
+
+describe 'apache::mod::php', :type => :class do
+  describe "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    context "with mpm_module => prefork" do
+      let :pre_condition do
+        'class { "apache": mpm_module => prefork, }'
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_class("apache::mod::prefork") }
+      it { is_expected.to contain_apache__mod('php5') }
+      it { is_expected.to contain_package("libapache2-mod-php5") }
+      it { is_expected.to contain_file("php5.load").with(
+        :content => "LoadModule php5_module /usr/lib/apache2/modules/libphp5.so\n"
+      ) }
+    end
+    context "with mpm_module => itk" do
+      let :pre_condition do
+        'class { "apache": mpm_module => itk, }'
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_class("apache::mod::itk") }
+      it { is_expected.to contain_apache__mod('php5') }
+      it { is_expected.to contain_package("libapache2-mod-php5") }
+      it { is_expected.to contain_file("php5.load").with(
+        :content => "LoadModule php5_module /usr/lib/apache2/modules/libphp5.so\n"
+      ) }
+    end
+  end
+  describe "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    context "with default params" do
+      let :pre_condition do
+        'class { "apache": }'
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('php5') }
+      it { is_expected.to contain_package("php") }
+      it { is_expected.to contain_file("php5.load").with(
+        :content => "LoadModule php5_module modules/libphp5.so\n"
+      ) }
+    end
+    context "with alternative package name" do let :pre_condition do
+        'class { "apache": }'
+      end
+      let :params do
+        { :package_name => 'php54'}
+      end
+      it { is_expected.to contain_package("php54") }
+    end
+    context "with alternative path" do let :pre_condition do
+        'class { "apache": }'
+      end
+      let :params do
+        { :path => 'alternative-path'}
+      end
+      it { is_expected.to contain_file("php5.load").with(
+        :content => "LoadModule php5_module alternative-path\n"
+      ) }
+    end
+    context "with alternative extensions" do let :pre_condition do
+        'class { "apache": }'
+      end
+      let :params do
+        { :extensions => ['.php','.php5']}
+      end
+      it { is_expected.to contain_file("php5.conf").with_content(/AddHandler php5-script .php .php5\n/) }
+    end
+    context "with specific version" do
+      let :pre_condition do
+        'class { "apache": }'
+      end
+      let :params do
+        { :package_ensure => '5.3.13'}
+      end
+      it { is_expected.to contain_package("php").with(
+        :ensure => '5.3.13'
+      ) }
+    end
+    context "with mpm_module => prefork" do
+      let :pre_condition do
+        'class { "apache": mpm_module => prefork, }'
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_class("apache::mod::prefork") }
+      it { is_expected.to contain_apache__mod('php5') }
+      it { is_expected.to contain_package("php") }
+      it { is_expected.to contain_file("php5.load").with(
+        :content => "LoadModule php5_module modules/libphp5.so\n"
+      ) }
+    end
+    context "with mpm_module => itk" do
+      let :pre_condition do
+        'class { "apache": mpm_module => itk, }'
+      end
+      it 'should raise an error' do
+        expect { expect(subject).to contain_class("apache::mod::itk") }.to raise_error Puppet::Error, /Unsupported osfamily RedHat/
+      end
+    end
+  end
+  describe "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '10',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    context "with mpm_module => prefork" do
+      let :pre_condition do
+        'class { "apache": mpm_module => prefork, }'
+      end
+      it { is_expected.to contain_class('apache::params') }
+      it { is_expected.to contain_apache__mod('php5') }
+      it { is_expected.to contain_package("www/mod_php5") }
+      it { is_expected.to contain_file('php5.load') }
+    end
+    context "with mpm_module => itk" do
+      let :pre_condition do
+        'class { "apache": mpm_module => itk, }'
+      end
+      it { is_expected.to contain_class('apache::params') }
+      it { is_expected.to contain_class('apache::mod::itk') }
+      it { is_expected.to contain_apache__mod('php5') }
+      it { is_expected.to contain_package("www/mod_php5") }
+      it { is_expected.to contain_file('php5.load') }
+    end
+  end
+  describe "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    context "with mpm_module => prefork" do
+      let :pre_condition do
+        'class { "apache": mpm_module => prefork, }'
+      end
+      it { is_expected.to contain_class('apache::params') }
+      it { is_expected.to contain_apache__mod('php5') }
+      it { is_expected.to contain_package("dev-lang/php") }
+      it { is_expected.to contain_file('php5.load') }
+    end
+    context "with mpm_module => itk" do
+      let :pre_condition do
+        'class { "apache": mpm_module => itk, }'
+      end
+      it { is_expected.to contain_class('apache::params') }
+      it { is_expected.to contain_class('apache::mod::itk') }
+      it { is_expected.to contain_apache__mod('php5') }
+      it { is_expected.to contain_package("dev-lang/php") }
+      it { is_expected.to contain_file('php5.load') }
+    end
+  end
+  describe "OS independent tests" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :kernel                 => 'Linux',
+        :lsbdistcodename        => 'squeeze',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    context 'with content param' do
+      let :pre_condition do
+        'class { "apache": mpm_module => prefork, }'
+      end
+      let :params do
+        { :content => 'somecontent' }
+      end
+      it { should contain_file('php5.conf').with(
+        :content => 'somecontent'
+      ) }
+    end
+    context 'with template param' do
+      let :pre_condition do
+        'class { "apache": mpm_module => prefork, }'
+      end
+      let :params do
+        { :template => 'apache/mod/php5.conf.erb' }
+      end
+      it { should contain_file('php5.conf').with(
+        :content => /^# PHP is an HTML-embedded scripting language which attempts to make it/
+      ) }
+    end
+    context 'with source param' do
+      let :pre_condition do
+        'class { "apache": mpm_module => prefork, }'
+      end
+      let :params do
+        { :source => 'some-path' }
+      end
+      it { should contain_file('php5.conf').with(
+        :source => 'some-path'
+      ) }
+    end
+    context 'content has priority over template' do
+      let :pre_condition do
+        'class { "apache": mpm_module => prefork, }'
+      end
+      let :params do
+        {
+          :template => 'apache/mod/php5.conf.erb',
+          :content  => 'somecontent'
+        }
+      end
+      it { should contain_file('php5.conf').with(
+        :content => 'somecontent'
+      ) }
+    end
+    context 'source has priority over template' do
+      let :pre_condition do
+        'class { "apache": mpm_module => prefork, }'
+      end
+      let :params do
+        {
+          :template => 'apache/mod/php5.conf.erb',
+          :source   => 'some-path'
+        }
+      end
+      it { should contain_file('php5.conf').with(
+        :source => 'some-path'
+      ) }
+    end
+    context 'source has priority over content' do
+      let :pre_condition do
+        'class { "apache": mpm_module => prefork, }'
+      end
+      let :params do
+        {
+          :content => 'somecontent',
+          :source  => 'some-path'
+        }
+      end
+      it { should contain_file('php5.conf').with(
+        :source => 'some-path'
+      ) }
+    end
+    context 'with mpm_module => worker' do
+      let :pre_condition do
+        'class { "apache": mpm_module => worker, }'
+      end
+      it 'should raise an error' do
+        expect { expect(subject).to contain_apache__mod('php5') }.to raise_error Puppet::Error, /mpm_module => 'prefork' or mpm_module => 'itk'/
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/prefork_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,134 @@
+require 'spec_helper'
+
+describe 'apache::mod::prefork', :type => :class do
+  let :pre_condition do
+    'class { "apache": mpm_module => false, }'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('prefork') }
+    it { is_expected.to contain_file("/etc/apache2/mods-available/prefork.conf").with_ensure('file') }
+    it { is_expected.to contain_file("/etc/apache2/mods-enabled/prefork.conf").with_ensure('link') }
+
+    context "with Apache version < 2.4" do
+      let :params do
+        {
+          :apache_version => '2.2',
+        }
+      end
+
+      it { is_expected.not_to contain_file("/etc/apache2/mods-available/prefork.load") }
+      it { is_expected.not_to contain_file("/etc/apache2/mods-enabled/prefork.load") }
+
+      it { is_expected.to contain_package("apache2-mpm-prefork") }
+    end
+
+    context "with Apache version >= 2.4" do
+      let :params do
+        {
+          :apache_version => '2.4',
+        }
+      end
+
+      it { is_expected.to contain_file("/etc/apache2/mods-available/prefork.load").with({
+        'ensure'  => 'file',
+        'content' => "LoadModule mpm_prefork_module /usr/lib/apache2/modules/mod_mpm_prefork.so\n"
+        })
+      }
+      it { is_expected.to contain_file("/etc/apache2/mods-enabled/prefork.load").with_ensure('link') }
+    end
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('prefork') }
+    it { is_expected.to contain_file("/etc/httpd/conf.d/prefork.conf").with_ensure('file') }
+
+    context "with Apache version < 2.4" do
+      let :params do
+        {
+          :apache_version => '2.2',
+        }
+      end
+
+      it { is_expected.to contain_file_line("/etc/sysconfig/httpd prefork enable").with({
+        'require' => 'Package[httpd]',
+        })
+      }
+    end
+
+    context "with Apache version >= 2.4" do
+      let :params do
+        {
+          :apache_version => '2.4',
+        }
+      end
+
+      it { is_expected.not_to contain_apache__mod('event') }
+
+      it { is_expected.to contain_file("/etc/httpd/conf.d/prefork.load").with({
+        'ensure'  => 'file',
+        'content' => "LoadModule mpm_prefork_module modules/mod_mpm_prefork.so\n",
+        })
+      }
+    end
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('prefork') }
+    it { is_expected.to contain_file("/usr/local/etc/apache24/Modules/prefork.conf").with_ensure('file') }
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('prefork') }
+    it { is_expected.to contain_file("/etc/apache2/modules.d/prefork.conf").with_ensure('file') }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/proxy_connect_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,65 @@
+require 'spec_helper'
+
+describe 'apache::mod::proxy_connect', :type => :class do
+  let :pre_condition do
+    [
+      'include apache',
+      'include apache::mod::proxy',
+    ]
+  end
+  context 'on a Debian OS' do
+    let :facts do
+      {
+        :osfamily        => 'Debian',
+        :concat_basedir  => '/dne',
+        :operatingsystem => 'Debian',
+        :id              => 'root',
+        :kernel          => 'Linux',
+        :path            => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    context 'with Apache version < 2.2' do
+      let :facts do
+        super().merge({
+          :operatingsystemrelease => '7.0',
+          :lsbdistcodename        => 'wheezy',
+        })
+      end
+      let :params do
+        {
+          :apache_version => '2.1',
+        }
+      end
+      it { is_expected.not_to contain_apache__mod('proxy_connect') }
+    end
+    context 'with Apache version = 2.2' do
+      let :facts do
+        super().merge({
+          :operatingsystemrelease => '7.0',
+          :lsbdistcodename        => 'wheezy',
+        })
+      end
+      let :params do
+        {
+          :apache_version => '2.2',
+        }
+      end
+      it { is_expected.to contain_apache__mod('proxy_connect') }
+    end
+    context 'with Apache version >= 2.4' do
+      let :facts do
+        super().merge({
+          :operatingsystemrelease => '8.0',
+          :lsbdistcodename        => 'jessie',
+        })
+      end
+      let :params do
+        {
+          :apache_version => '2.4',
+        }
+      end
+      it { is_expected.to contain_apache__mod('proxy_connect') }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/proxy_html_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,105 @@
+require 'spec_helper'
+
+describe 'apache::mod::proxy_html', :type => :class do
+  let :pre_condition do
+    [
+      'include apache',
+      'include apache::mod::proxy',
+      'include apache::mod::proxy_http',
+    ]
+  end
+  context "on a Debian OS" do
+    shared_examples "debian" do |loadfiles|
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('proxy_html').with(:loadfiles => loadfiles) }
+      it { is_expected.to contain_package("libapache2-mod-proxy-html") }
+    end
+    let :facts do
+      {
+        :osfamily        => 'Debian',
+        :concat_basedir  => '/dne',
+        :architecture    => 'i386',
+        :lsbdistcodename => 'squeeze',
+        :operatingsystem => 'Debian',
+        :id              => 'root',
+        :kernel          => 'Linux',
+        :path            => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :hardwaremodel   => 'i386',
+        :is_pe                  => false,
+      }
+    end
+
+    context "on squeeze" do
+      let(:facts) { super().merge({ :operatingsystemrelease => '6' }) }
+      it_behaves_like "debian", ['/usr/lib/libxml2.so.2']
+    end
+    context "on wheezy" do
+      let(:facts) { super().merge({ :operatingsystemrelease => '7' }) }
+      context "i386" do
+        let(:facts) { super().merge({
+          :hardwaremodel => 'i686',
+          :architecture  => 'i386'
+        })}
+        it_behaves_like "debian", ["/usr/lib/i386-linux-gnu/libxml2.so.2"]
+      end
+      context "x64" do
+        let(:facts) { super().merge({
+          :hardwaremodel => 'x86_64',
+          :architecture  => 'amd64'
+        })}
+        it_behaves_like "debian", ["/usr/lib/x86_64-linux-gnu/libxml2.so.2"]
+      end
+    end
+  end
+  context "on a RedHat OS", :compile do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('proxy_html').with(:loadfiles => nil) }
+    it { is_expected.to contain_package("mod_proxy_html") }
+  end
+  context "on a FreeBSD OS", :compile do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('proxy_html').with(:loadfiles => nil) }
+    it { is_expected.to contain_package("www/mod_proxy_html") }
+  end
+  context "on a Gentoo OS", :compile do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('proxy_html').with(:loadfiles => nil) }
+    it { is_expected.to contain_package("www-apache/mod_proxy_html") }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/python_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,76 @@
+require 'spec_helper'
+
+describe 'apache::mod::python', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod("python") }
+    it { is_expected.to contain_package("libapache2-mod-python") }
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod("python") }
+    it { is_expected.to contain_package("mod_python") }
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod("python") }
+    it { is_expected.to contain_package("www/mod_python3") }
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod("python") }
+    it { is_expected.to contain_package("www-apache/mod_python") }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/remoteip_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,53 @@
+require 'spec_helper'
+
+describe 'apache::mod::remoteip', :type => :class do
+  let :pre_condition do
+    [
+      'include apache',
+    ]
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '8',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'jessie',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+      }
+    end
+    let :params do
+      { :apache_version => '2.4' }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('remoteip') }
+    it { is_expected.to contain_file('remoteip.conf').with({
+      'path' => '/etc/apache2/mods-available/remoteip.conf',
+    }) }
+
+    describe "with header X-Forwarded-For" do
+      let :params do
+        { :header => 'X-Forwarded-For' }
+      end
+      it { is_expected.to contain_file('remoteip.conf').with_content(/^RemoteIPHeader X-Forwarded-For$/) }
+    end
+    describe "with proxy_ips => [ 10.42.17.8, 10.42.18.99 ]" do
+      let :params do
+        { :proxy_ips => [ '10.42.17.8', '10.42.18.99' ] }
+      end
+      it { is_expected.to contain_file('remoteip.conf').with_content(/^RemoteIPInternalProxy 10.42.17.8$/) }
+      it { is_expected.to contain_file('remoteip.conf').with_content(/^RemoteIPInternalProxy 10.42.18.99$/) }
+    end
+    describe "with Apache version < 2.4" do
+      let :params do
+        { :apache_version => '2.2' }
+      end
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /mod_remoteip is only available in Apache 2.4/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/reqtimeout_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,150 @@
+require 'spec_helper'
+
+describe 'apache::mod::reqtimeout', :type => :class do
+  let :pre_condition do
+    'class { "apache":
+      default_mods => false,
+    }'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :lsbdistcodename        => 'squeeze',
+        :is_pe                  => false,
+      }
+    end
+    context "passing no parameters" do
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-40,minrate=500\nRequestReadTimeout body=10,minrate=500$/) }
+    end
+    context "passing timeouts => ['header=20-60,minrate=600', 'body=60,minrate=600']" do
+      let :params do
+        {:timeouts => ['header=20-60,minrate=600', 'body=60,minrate=600']}
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-60,minrate=600\nRequestReadTimeout body=60,minrate=600$/) }
+    end
+    context "passing timeouts => 'header=20-60,minrate=600'" do
+      let :params do
+        {:timeouts => 'header=20-60,minrate=600'}
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-60,minrate=600$/) }
+    end
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'Redhat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    context "passing no parameters" do
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-40,minrate=500\nRequestReadTimeout body=10,minrate=500$/) }
+    end
+    context "passing timeouts => ['header=20-60,minrate=600', 'body=60,minrate=600']" do
+      let :params do
+        {:timeouts => ['header=20-60,minrate=600', 'body=60,minrate=600']}
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-60,minrate=600\nRequestReadTimeout body=60,minrate=600$/) }
+    end
+    context "passing timeouts => 'header=20-60,minrate=600'" do
+      let :params do
+        {:timeouts => 'header=20-60,minrate=600'}
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-60,minrate=600$/) }
+    end
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    context "passing no parameters" do
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-40,minrate=500\nRequestReadTimeout body=10,minrate=500$/) }
+    end
+    context "passing timeouts => ['header=20-60,minrate=600', 'body=60,minrate=600']" do
+      let :params do
+        {:timeouts => ['header=20-60,minrate=600', 'body=60,minrate=600']}
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-60,minrate=600\nRequestReadTimeout body=60,minrate=600$/) }
+    end
+    context "passing timeouts => 'header=20-60,minrate=600'" do
+      let :params do
+        {:timeouts => 'header=20-60,minrate=600'}
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-60,minrate=600$/) }
+    end
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    context "passing no parameters" do
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-40,minrate=500\nRequestReadTimeout body=10,minrate=500$/) }
+    end
+    context "passing timeouts => ['header=20-60,minrate=600', 'body=60,minrate=600']" do
+      let :params do
+        {:timeouts => ['header=20-60,minrate=600', 'body=60,minrate=600']}
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-60,minrate=600\nRequestReadTimeout body=60,minrate=600$/) }
+    end
+    context "passing timeouts => 'header=20-60,minrate=600'" do
+      let :params do
+        {:timeouts => 'header=20-60,minrate=600'}
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__mod('reqtimeout') }
+      it { is_expected.to contain_file('reqtimeout.conf').with_content(/^RequestReadTimeout header=20-60,minrate=600$/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/rpaf_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,130 @@
+require 'spec_helper'
+
+describe 'apache::mod::rpaf', :type => :class do
+  let :pre_condition do
+    [
+      'include apache',
+    ]
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('rpaf') }
+    it { is_expected.to contain_package("libapache2-mod-rpaf") }
+    it { is_expected.to contain_file('rpaf.conf').with({
+      'path' => '/etc/apache2/mods-available/rpaf.conf',
+    }) }
+    it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFenable On$/) }
+
+    describe "with sethostname => true" do
+      let :params do
+        { :sethostname => 'true' }
+      end
+      it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFsethostname On$/) }
+    end
+    describe "with proxy_ips => [ 10.42.17.8, 10.42.18.99 ]" do
+      let :params do
+        { :proxy_ips => [ '10.42.17.8', '10.42.18.99' ] }
+      end
+      it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFproxy_ips 10.42.17.8 10.42.18.99$/) }
+    end
+    describe "with header => X-Real-IP" do
+      let :params do
+        { :header => 'X-Real-IP' }
+      end
+      it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFheader X-Real-IP$/) }
+    end
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('rpaf') }
+    it { is_expected.to contain_package("www/mod_rpaf2") }
+    it { is_expected.to contain_file('rpaf.conf').with({
+      'path' => '/usr/local/etc/apache24/Modules/rpaf.conf',
+    }) }
+    it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFenable On$/) }
+
+    describe "with sethostname => true" do
+      let :params do
+        { :sethostname => 'true' }
+      end
+      it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFsethostname On$/) }
+    end
+    describe "with proxy_ips => [ 10.42.17.8, 10.42.18.99 ]" do
+      let :params do
+        { :proxy_ips => [ '10.42.17.8', '10.42.18.99' ] }
+      end
+      it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFproxy_ips 10.42.17.8 10.42.18.99$/) }
+    end
+    describe "with header => X-Real-IP" do
+      let :params do
+        { :header => 'X-Real-IP' }
+      end
+      it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFheader X-Real-IP$/) }
+    end
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_apache__mod('rpaf') }
+    it { is_expected.to contain_package("www-apache/mod_rpaf") }
+    it { is_expected.to contain_file('rpaf.conf').with({
+      'path' => '/etc/apache2/modules.d/rpaf.conf',
+    }) }
+    it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFenable On$/) }
+
+    describe "with sethostname => true" do
+      let :params do
+        { :sethostname => 'true' }
+      end
+      it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFsethostname On$/) }
+    end
+    describe "with proxy_ips => [ 10.42.17.8, 10.42.18.99 ]" do
+      let :params do
+        { :proxy_ips => [ '10.42.17.8', '10.42.18.99' ] }
+      end
+      it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFproxy_ips 10.42.17.8 10.42.18.99$/) }
+    end
+    describe "with header => X-Real-IP" do
+      let :params do
+        { :header => 'X-Real-IP' }
+      end
+      it { is_expected.to contain_file('rpaf.conf').with_content(/^RPAFheader X-Real-IP$/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/security_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,95 @@
+require 'spec_helper'
+
+describe 'apache::mod::security', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+
+  context "on RedHat based systems" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'CentOS',
+        :operatingsystemrelease => '7',
+        :kernel                 => 'Linux',
+        :id                     => 'root',
+        :concat_basedir         => '/',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { should contain_apache__mod('security').with(
+      :id => 'security2_module',
+      :lib => 'mod_security2.so'
+    ) }
+    it { should contain_apache__mod('unique_id_module').with(
+      :id => 'unique_id_module',
+      :lib => 'mod_unique_id.so'
+    ) }
+    it { should contain_package('mod_security_crs') }
+    it { should contain_file('security.conf').with(
+      :path => '/etc/httpd/conf.d/security.conf'
+    ) }
+    it { should contain_file('/etc/httpd/modsecurity.d').with(
+      :ensure => 'directory',
+      :path => '/etc/httpd/modsecurity.d',
+      :owner => 'apache',
+      :group => 'apache'
+    ) }
+    it { should contain_file('/etc/httpd/modsecurity.d/activated_rules').with(
+      :ensure => 'directory',
+      :path => '/etc/httpd/modsecurity.d/activated_rules',
+      :owner => 'apache',
+      :group => 'apache'
+    ) }
+    it { should contain_file('/etc/httpd/modsecurity.d/security_crs.conf').with(
+      :path => '/etc/httpd/modsecurity.d/security_crs.conf'
+    ) }
+    it { should contain_apache__security__rule_link('base_rules/modsecurity_35_bad_robots.data') }
+  end
+
+  context "on Debian based systems" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/',
+        :lsbdistcodename        => 'squeeze',
+        :id                     => 'root',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :kernel                 => 'Linux',
+        :is_pe                  => false,
+      }
+    end
+    it { should contain_apache__mod('security').with(
+      :id => 'security2_module',
+      :lib => 'mod_security2.so'
+    ) }
+    it { should contain_apache__mod('unique_id_module').with(
+      :id => 'unique_id_module',
+      :lib => 'mod_unique_id.so'
+    ) }
+    it { should contain_package('modsecurity-crs') }
+    it { should contain_file('security.conf').with(
+      :path => '/etc/apache2/mods-available/security.conf'
+    ) }
+    it { should contain_file('/etc/modsecurity').with(
+      :ensure => 'directory',
+      :path => '/etc/modsecurity',
+      :owner => 'www-data',
+      :group => 'www-data'
+    ) }
+    it { should contain_file('/etc/modsecurity/activated_rules').with(
+      :ensure => 'directory',
+      :path => '/etc/modsecurity/activated_rules',
+      :owner => 'www-data',
+      :group => 'www-data'
+    ) }
+    it { should contain_file('/etc/modsecurity/security_crs.conf').with(
+      :path => '/etc/modsecurity/security_crs.conf'
+    ) }
+    it { should contain_apache__security__rule_link('base_rules/modsecurity_35_bad_robots.data') }
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/shib_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+describe 'apache::mod::shib', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :fqdn                   => 'test.example.com',
+        :is_pe                  => false,
+      }
+    end
+    describe 'with no parameters' do
+      it { should contain_apache__mod('shib2').with_id('mod_shib') }
+    end
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :fqdn                   => 'test.example.com',
+        :is_pe                  => false,
+      }
+    end
+    describe 'with no parameters' do
+      it { should contain_apache__mod('shib2').with_id('mod_shib') }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/speling_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe 'apache::mod::speling', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_apache__mod('speling') }
+  end
+
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_apache__mod('speling') }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/ssl_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,165 @@
+require 'spec_helper'
+
+describe 'apache::mod::ssl', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context 'on an unsupported OS' do
+    let :facts do
+      {
+        :osfamily               => 'Magic',
+        :operatingsystemrelease => '0',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'Magic',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { expect { catalogue }.to raise_error(Puppet::Error, /Unsupported osfamily:/) }
+  end
+
+  context 'on a RedHat OS' do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class('apache::params') }
+    it { is_expected.to contain_apache__mod('ssl') }
+    it { is_expected.to contain_package('mod_ssl') }
+    context 'with a custom package_name parameter' do
+      let :params do
+        { :package_name => 'httpd24-mod_ssl' }
+      end
+      it { is_expected.to contain_class('apache::params') }
+      it { is_expected.to contain_apache__mod('ssl') }
+      it { is_expected.to contain_package('httpd24-mod_ssl') }
+      it { is_expected.not_to contain_package('mod_ssl') }
+    end
+  end
+
+  context 'on a Debian OS' do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class('apache::params') }
+    it { is_expected.to contain_apache__mod('ssl') }
+    it { is_expected.not_to contain_package('libapache2-mod-ssl') }
+  end
+
+  context 'on a FreeBSD OS' do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class('apache::params') }
+    it { is_expected.to contain_apache__mod('ssl') }
+  end
+
+  context 'on a Gentoo OS' do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class('apache::params') }
+    it { is_expected.to contain_apache__mod('ssl') }
+  end
+
+  context 'on a Suse OS' do
+    let :facts do
+      {
+        :osfamily               => 'Suse',
+        :operatingsystem        => 'SLES',
+        :operatingsystemrelease => '11.2',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class('apache::params') }
+    it { is_expected.to contain_apache__mod('ssl') }
+  end
+  # Template config doesn't vary by distro
+  context "on all distros" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'CentOS',
+        :operatingsystemrelease => '6',
+        :kernel                 => 'Linux',
+        :id                     => 'root',
+        :concat_basedir         => '/dne',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    context 'not setting ssl_pass_phrase_dialog' do
+      it { is_expected.to contain_file('ssl.conf').with_content(/^  SSLPassPhraseDialog builtin$/)}
+    end
+
+    context 'setting ssl_pass_phrase_dialog' do
+      let :params do
+        {
+          :ssl_pass_phrase_dialog => 'exec:/path/to/program',
+        }
+      end
+      it { is_expected.to contain_file('ssl.conf').with_content(/^  SSLPassPhraseDialog exec:\/path\/to\/program$/)}
+    end
+
+    context 'setting ssl_random_seed_bytes' do
+      let :params do
+        {
+          :ssl_random_seed_bytes => '1024',
+        }
+      end
+      it { is_expected.to contain_file('ssl.conf').with_content(%r{^  SSLRandomSeed startup file:/dev/urandom 1024$})}
+    end
+
+    context 'setting ssl_openssl_conf_cmd' do
+      let :params do
+        {
+          :ssl_openssl_conf_cmd => 'DHParameters "foo.pem"',
+        }
+      end
+      it { is_expected.to contain_file('ssl.conf').with_content(/^\s+SSLOpenSSLConfCmd DHParameters "foo.pem"$/)}
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/status_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,206 @@
+require 'spec_helper'
+
+# Helper function for testing the contents of `status.conf`
+def status_conf_spec(allow_from, extended_status, status_path)
+  it do
+    is_expected.to contain_file("status.conf").with_content(
+      "<Location #{status_path}>\n"\
+      "    SetHandler server-status\n"\
+      "    Order deny,allow\n"\
+      "    Deny from all\n"\
+      "    Allow from #{Array(allow_from).join(' ')}\n"\
+      "</Location>\n"\
+      "ExtendedStatus #{extended_status}\n"\
+      "\n"\
+      "<IfModule mod_proxy.c>\n"\
+      "    # Show Proxy LoadBalancer status in mod_status\n"\
+      "    ProxyStatus On\n"\
+      "</IfModule>\n"
+    )
+  end
+end
+
+describe 'apache::mod::status', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+
+  context "on a Debian OS with default params" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    it { is_expected.to contain_apache__mod("status") }
+
+    status_conf_spec(["127.0.0.1", "::1"], "On", "/server-status")
+
+    it { is_expected.to contain_file("status.conf").with({
+      :ensure => 'file',
+      :path   => '/etc/apache2/mods-available/status.conf',
+    } ) }
+
+    it { is_expected.to contain_file("status.conf symlink").with({
+      :ensure => 'link',
+      :path   => '/etc/apache2/mods-enabled/status.conf',
+    } ) }
+
+  end
+
+  context "on a RedHat OS with default params" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    it { is_expected.to contain_apache__mod("status") }
+
+    status_conf_spec(["127.0.0.1", "::1"], "On", "/server-status")
+
+    it { is_expected.to contain_file("status.conf").with_path("/etc/httpd/conf.d/status.conf") }
+
+  end
+
+  context "with custom parameters $allow_from => ['10.10.10.10','11.11.11.11'], $extended_status => 'Off', $status_path => '/custom-status'" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    let :params do
+      {
+        :allow_from => ['10.10.10.10','11.11.11.11'],
+        :extended_status => 'Off',
+        :status_path => '/custom-status',
+      }
+    end
+
+    status_conf_spec(["10.10.10.10", "11.11.11.11"], "Off", "/custom-status")
+
+  end
+
+  context "with valid parameter type $allow_from => ['10.10.10.10']" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    let :params do
+      { :allow_from => ['10.10.10.10'] }
+    end
+    it 'should expect to succeed array validation' do
+      expect {
+        is_expected.to contain_file("status.conf")
+      }.not_to raise_error()
+    end
+  end
+
+  context "with invalid parameter type $allow_from => '10.10.10.10'" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    let :params do
+      { :allow_from => '10.10.10.10' }
+    end
+    it 'should expect to fail array validation' do
+      expect {
+        is_expected.to contain_file("status.conf")
+      }.to raise_error(Puppet::Error)
+    end
+  end
+
+  # Only On or Off are valid options
+  ['On', 'Off'].each do |valid_param|
+    context "with valid value $extended_status => '#{valid_param}'" do
+      let :facts do
+        {
+          :osfamily               => 'Debian',
+          :operatingsystemrelease => '6',
+          :concat_basedir         => '/dne',
+          :lsbdistcodename        => 'squeeze',
+          :operatingsystem        => 'Debian',
+          :id                     => 'root',
+          :kernel                 => 'Linux',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+      let :params do
+        { :extended_status => valid_param }
+      end
+      it 'should expect to succeed regular expression validation' do
+        expect {
+          is_expected.to contain_file("status.conf")
+        }.not_to raise_error()
+      end
+    end
+  end
+
+  ['Yes', 'No'].each do |invalid_param|
+    context "with invalid value $extended_status => '#{invalid_param}'" do
+      let :facts do
+        {
+          :osfamily               => 'Debian',
+          :operatingsystemrelease => '6',
+          :concat_basedir         => '/dne',
+          :operatingsystem        => 'Debian',
+          :id                     => 'root',
+          :kernel                 => 'Linux',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+      let :params do
+        { :extended_status => invalid_param }
+      end
+      it 'should expect to fail regular expression validation' do
+        expect {
+          is_expected.to contain_file("status.conf")
+        }.to raise_error(Puppet::Error)
+      end
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/suphp_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe 'apache::mod::suphp', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_package("libapache2-mod-suphp") }
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_package("mod_suphp") }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/worker_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,189 @@
+require 'spec_helper'
+
+describe 'apache::mod::worker', :type => :class do
+  let :pre_condition do
+    'class { "apache": mpm_module => false, }'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('worker') }
+    it { is_expected.to contain_file("/etc/apache2/mods-available/worker.conf").with_ensure('file') }
+    it { is_expected.to contain_file("/etc/apache2/mods-enabled/worker.conf").with_ensure('link') }
+
+    context "with Apache version < 2.4" do
+      let :params do
+        {
+          :apache_version => '2.2',
+        }
+      end
+
+      it { is_expected.not_to contain_file("/etc/apache2/mods-available/worker.load") }
+      it { is_expected.not_to contain_file("/etc/apache2/mods-enabled/worker.load") }
+
+      it { is_expected.to contain_package("apache2-mpm-worker") }
+    end
+
+    context "with Apache version >= 2.4" do
+      let :params do
+        {
+          :apache_version => '2.4',
+        }
+      end
+
+      it { is_expected.to contain_file("/etc/apache2/mods-available/worker.load").with({
+        'ensure'  => 'file',
+        'content' => "LoadModule mpm_worker_module /usr/lib/apache2/modules/mod_mpm_worker.so\n"
+        })
+      }
+      it { is_expected.to contain_file("/etc/apache2/mods-enabled/worker.load").with_ensure('link') }
+    end
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('worker') }
+    it { is_expected.to contain_file("/etc/httpd/conf.d/worker.conf").with_ensure('file') }
+
+    context "with Apache version < 2.4" do
+      let :params do
+        {
+          :apache_version => '2.2',
+        }
+      end
+
+      it { is_expected.to contain_file_line("/etc/sysconfig/httpd worker enable").with({
+        'require' => 'Package[httpd]',
+        })
+      }
+    end
+
+    context "with Apache version >= 2.4" do
+      let :params do
+        {
+          :apache_version => '2.4',
+        }
+      end
+
+      it { is_expected.not_to contain_apache__mod('event') }
+
+      it { is_expected.to contain_file("/etc/httpd/conf.d/worker.load").with({
+        'ensure'  => 'file',
+        'content' => "LoadModule mpm_worker_module modules/mod_mpm_worker.so\n",
+        })
+      }
+    end
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('worker') }
+    it { is_expected.to contain_file("/usr/local/etc/apache24/Modules/worker.conf").with_ensure('file') }
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.not_to contain_apache__mod('worker') }
+    it { is_expected.to contain_file("/etc/apache2/modules.d/worker.conf").with_ensure('file') }
+  end
+
+  # Template config doesn't vary by distro
+  context "on all distros" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'CentOS',
+        :operatingsystemrelease => '6',
+        :kernel                 => 'Linux',
+        :id                     => 'root',
+        :concat_basedir         => '/dne',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    context 'defaults' do
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^<IfModule mpm_worker_module>$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+ServerLimit\s+25$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+StartServers\s+2$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+MaxClients\s+150$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+MinSpareThreads\s+25$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+MaxSpareThreads\s+75$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+ThreadsPerChild\s+25$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+MaxRequestsPerChild\s+0$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+ThreadLimit\s+64$/) }
+      it { should contain_file("/etc/httpd/conf.d/worker.conf").with(:content => /^\s*ListenBacklog\s*511/) }
+    end
+
+    context 'setting params' do
+      let :params do
+        {
+          :serverlimit          => 10,
+          :startservers         => 11,
+          :maxclients           => 12,
+          :minsparethreads      => 13,
+          :maxsparethreads      => 14,
+          :threadsperchild      => 15,
+          :maxrequestsperchild  => 16,
+          :threadlimit          => 17,
+          :listenbacklog        => 8,
+        }
+      end
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^<IfModule mpm_worker_module>$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+ServerLimit\s+10$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+StartServers\s+11$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+MaxClients\s+12$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+MinSpareThreads\s+13$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+MaxSpareThreads\s+14$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+ThreadsPerChild\s+15$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+MaxRequestsPerChild\s+16$/) }
+      it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^\s+ThreadLimit\s+17$/) }
+      it { should contain_file("/etc/httpd/conf.d/worker.conf").with(:content => /^\s*ListenBacklog\s*8/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/mod/wsgi_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,147 @@
+require 'spec_helper'
+
+describe 'apache::mod::wsgi', :type => :class do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_class('apache::mod::wsgi').with(
+        'wsgi_socket_prefix' => nil
+      )
+    }
+    it { is_expected.to contain_package("libapache2-mod-wsgi") }
+  end
+  context "on a RedHat OS" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_class('apache::mod::wsgi').with(
+        'wsgi_socket_prefix' => '/var/run/wsgi'
+      )
+    }
+    it { is_expected.to contain_package("mod_wsgi") }
+
+    describe "with custom WSGISocketPrefix" do
+      let :params do
+        { :wsgi_socket_prefix => 'run/wsgi' }
+      end
+      it {is_expected.to contain_file('wsgi.conf').with_content(/^  WSGISocketPrefix run\/wsgi$/)}
+    end
+    describe "with custom WSGIPythonHome" do
+      let :params do
+        { :wsgi_python_home => '/path/to/virtenv' }
+      end
+      it {is_expected.to contain_file('wsgi.conf').with_content(/^  WSGIPythonHome "\/path\/to\/virtenv"$/)}
+    end
+    describe "with custom package_name and mod_path" do
+      let :params do
+        {
+          :package_name => 'mod_wsgi_package',
+          :mod_path     => '/foo/bar/baz',
+        }
+      end
+      it { is_expected.to contain_apache__mod('wsgi').with({
+          'package' => 'mod_wsgi_package',
+          'path'    => '/foo/bar/baz',
+        })
+      }
+      it { is_expected.to contain_package("mod_wsgi_package") }
+      it { is_expected.to contain_file('wsgi.load').with_content(%r"LoadModule wsgi_module /foo/bar/baz") }
+    end
+    describe "with custom mod_path not containing /" do
+      let :params do
+        {
+          :package_name => 'mod_wsgi_package',
+          :mod_path     => 'wsgi_mod_name.so',
+        }
+      end
+      it { is_expected.to contain_apache__mod('wsgi').with({
+          'path'     => 'modules/wsgi_mod_name.so',
+          'package'  => 'mod_wsgi_package',
+        })
+      }
+      it { is_expected.to contain_file('wsgi.load').with_content(%r"LoadModule wsgi_module modules/wsgi_mod_name.so") }
+
+    end
+    describe "with package_name but no mod_path" do
+      let :params do
+        {
+          :mod_path => '/foo/bar/baz',
+        }
+      end
+      it { expect { catalogue }.to raise_error Puppet::Error, /apache::mod::wsgi - both package_name and mod_path must be specified!/ }
+    end
+    describe "with mod_path but no package_name" do
+      let :params do
+        {
+          :package_name => '/foo/bar/baz',
+        }
+      end
+      it { expect { catalogue }.to raise_error Puppet::Error, /apache::mod::wsgi - both package_name and mod_path must be specified!/ }
+    end
+  end
+  context "on a FreeBSD OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_class('apache::mod::wsgi').with(
+        'wsgi_socket_prefix' => nil
+      )
+    }
+    it { is_expected.to contain_package("www/mod_wsgi") }
+  end
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_class("apache::params") }
+    it { is_expected.to contain_class('apache::mod::wsgi').with(
+        'wsgi_socket_prefix' => nil
+      )
+    }
+    it { is_expected.to contain_package("www-apache/mod_wsgi") }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/params_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'apache::params', :type => :class do
+  context "On a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_apache__params }
+
+    it "Should not contain any resources" do
+      should have_resource_count(0)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/classes/service_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,175 @@
+require 'spec_helper'
+
+describe 'apache::service', :type => :class do
+  let :pre_condition do
+    'include apache::params'
+  end
+  context "on a Debian OS" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_service("httpd").with(
+      'name'      => 'apache2',
+      'ensure'    => 'running',
+      'enable'    => 'true'
+      )
+    }
+
+    context "with $service_name => 'foo'" do
+      let (:params) {{ :service_name => 'foo' }}
+      it { is_expected.to contain_service("httpd").with(
+        'name'      => 'foo'
+        )
+      }
+    end
+
+    context "with $service_enable => true" do
+      let (:params) {{ :service_enable => true }}
+      it { is_expected.to contain_service("httpd").with(
+        'name'      => 'apache2',
+        'ensure'    => 'running',
+        'enable'    => 'true'
+        )
+      }
+    end
+
+    context "with $service_enable => false" do
+      let (:params) {{ :service_enable => false }}
+      it { is_expected.to contain_service("httpd").with(
+        'name'      => 'apache2',
+        'ensure'    => 'running',
+        'enable'    => 'false'
+        )
+      }
+    end
+
+    context "$service_enable must be a bool" do
+      let (:params) {{ :service_enable => 'not-a-boolean' }}
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a boolean/)
+      end
+    end
+
+    context "$service_manage must be a bool" do
+      let (:params) {{ :service_manage => 'not-a-boolean' }}
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a boolean/)
+      end
+    end
+
+    context "with $service_ensure => 'running'" do
+      let (:params) {{ :service_ensure => 'running', }}
+      it { is_expected.to contain_service("httpd").with(
+        'ensure'    => 'running',
+        'enable'    => 'true'
+        )
+      }
+    end
+
+    context "with $service_ensure => 'stopped'" do
+      let (:params) {{ :service_ensure => 'stopped', }}
+      it { is_expected.to contain_service("httpd").with(
+        'ensure'    => 'stopped',
+        'enable'    => 'true'
+        )
+      }
+    end
+
+    context "with $service_ensure => 'UNDEF'" do
+      let (:params) {{ :service_ensure => 'UNDEF' }}
+      it { is_expected.to contain_service("httpd").without_ensure }
+    end
+
+    context "with $service_restart unset" do
+      it { is_expected.to contain_service("httpd").without_restart }
+    end
+
+    context "with $service_restart => '/usr/sbin/apachectl graceful'" do
+     let (:params) {{ :service_restart => '/usr/sbin/apachectl graceful' }}
+     it { is_expected.to contain_service("httpd").with(
+        'restart' => '/usr/sbin/apachectl graceful'
+      )
+     }
+    end
+  end
+
+
+  context "on a RedHat 5 OS, do not manage service" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '5',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    let(:params) do
+      {
+        'service_ensure' => 'running',
+        'service_name'   => 'httpd',
+        'service_manage' => false
+      }
+    end
+    it 'should not manage the httpd service' do
+      subject.should_not contain_service('httpd')
+    end
+  end
+
+  context "on a FreeBSD 5 OS" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_service("httpd").with(
+      'name'      => 'apache24',
+      'ensure'    => 'running',
+      'enable'    => 'true'
+      )
+    }
+  end
+
+  context "on a Gentoo OS" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { is_expected.to contain_service("httpd").with(
+      'name'      => 'apache2',
+      'ensure'    => 'running',
+      'enable'    => 'true'
+      )
+    }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/defines/balancermember_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe 'apache::balancermember', :type => :define do
+  let :pre_condition do
+    'include apache
+    apache::balancer {"balancer":}
+    apache::balancer {"balancer-external":}
+    apache::balancermember {"http://127.0.0.1:8080-external": url => "http://127.0.0.1:8080/", balancer_cluster => "balancer-external"}
+    '
+  end
+  let :title do
+    'http://127.0.0.1:8080/'
+  end
+  let :params do
+    {
+      :options          => [],
+      :url              => 'http://127.0.0.1:8080/',
+      :balancer_cluster => 'balancer-internal'
+    }
+  end
+  let :facts do
+    {
+      :osfamily               => 'Debian',
+      :operatingsystem        => 'Debian',
+      :operatingsystemrelease => '6',
+      :lsbdistcodename        => 'squeeze',
+      :id                     => 'root',
+      :concat_basedir         => '/dne',
+      :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+      :kernel                 => 'Linux',
+      :is_pe                  => false,
+    }
+  end
+  describe "allows multiple balancermembers with the same url" do
+    it { should contain_concat__fragment('BalancerMember http://127.0.0.1:8080/') }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/defines/custom_config_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,138 @@
+require 'spec_helper'
+
+describe 'apache::custom_config', :type => :define do
+  let :pre_condition do
+    'class { "apache": }'
+  end
+  let :title do
+    'rspec'
+  end
+  let :facts do
+    {
+      :osfamily               => 'Debian',
+      :operatingsystemrelease => '6',
+      :concat_basedir         => '/',
+      :lsbdistcodename        => 'squeeze',
+      :operatingsystem        => 'Debian',
+      :id                     => 'root',
+      :kernel                 => 'Linux',
+      :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+      :is_pe                  => false,
+    }
+  end
+  context 'defaults with content' do
+    let :params do
+      {
+        'content' => '# Test',
+      }
+    end
+    it { is_expected.to contain_exec("syntax verification for rspec").with({
+      'refreshonly' => 'true',
+      'subscribe'   => 'File[apache_rspec]',
+      'command'     => '/usr/sbin/apachectl -t',
+      'notify'      => 'Class[Apache::Service]',
+      'before'      => 'Exec[remove rspec if invalid]',
+    })
+    }
+    it { is_expected.to contain_exec("remove rspec if invalid").with({
+      'unless'      => '/usr/sbin/apachectl -t',
+      'subscribe'   => 'File[apache_rspec]',
+      'refreshonly' => 'true',
+    })
+    }
+    it { is_expected.to contain_file("apache_rspec").with({
+      'ensure'  => 'present',
+      'content' => '# Test',
+      'require' => 'Package[httpd]',
+    })
+    }
+  end
+  context 'set everything with source' do
+    let :params do
+      {
+        'confdir'        => '/dne',
+        'priority'       => '30',
+        'source'         => 'puppet:///modules/apache/test',
+        'verify_command' => '/bin/true',
+      }
+    end
+    it { is_expected.to contain_exec("syntax verification for rspec").with({
+      'command'     => '/bin/true',
+    })
+    }
+    it { is_expected.to contain_exec("remove rspec if invalid").with({
+      'command'     => '/bin/rm /dne/30-rspec.conf',
+      'unless'      => '/bin/true',
+    })
+    }
+    it { is_expected.to contain_file("apache_rspec").with({
+      'path'   => '/dne/30-rspec.conf',
+      'ensure'  => 'present',
+      'source' => 'puppet:///modules/apache/test',
+      'require' => 'Package[httpd]',
+    })
+    }
+  end
+  context 'verify_config => false' do
+    let :params do
+      {
+        'content'       => '# test',
+        'verify_config' => false,
+      }
+    end
+    it { is_expected.to_not contain_exec('syntax verification for rspec') }
+    it { is_expected.to_not contain_exec('remove rspec if invalid') }
+    it { is_expected.to contain_file('apache_rspec').with({
+      'notify' => 'Class[Apache::Service]'
+    })
+    }
+  end
+  context 'ensure => absent' do
+    let :params do
+      {
+        'ensure' => 'absent'
+      }
+    end
+    it { is_expected.to_not contain_exec('syntax verification for rspec') }
+    it { is_expected.to_not contain_exec('remove rspec if invalid') }
+    it { is_expected.to contain_file('apache_rspec').with({
+      'ensure' => 'absent',
+    })
+    }
+  end
+  describe 'validation' do
+    context 'both content and source' do
+      let :params do
+        {
+          'content' => 'foo',
+          'source'  => 'bar',
+        }
+      end
+      it do
+        expect {
+          catalogue
+        }.to raise_error(Puppet::Error, /Only one of \$content and \$source can be specified\./)
+      end
+    end
+    context 'neither content nor source' do
+      it do
+        expect {
+          catalogue
+        }.to raise_error(Puppet::Error, /One of \$content and \$source must be specified\./)
+      end
+    end
+    context 'bad ensure' do
+      let :params do
+        {
+          'content' => 'foo',
+          'ensure'  => 'foo',
+        }
+      end
+      it do
+        expect {
+          catalogue
+        }.to raise_error(Puppet::Error, /is not supported for ensure/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/defines/fastcgi_server_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,133 @@
+require 'spec_helper'
+
+describe 'apache::fastcgi::server', :type => :define do
+  let :pre_condition do
+    'include apache'
+  end
+  let :title do
+    'www'
+  end
+  describe 'os-dependent items' do
+    context "on RedHat based systems" do
+      let :default_facts do
+        {
+          :osfamily               => 'RedHat',
+          :operatingsystem        => 'CentOS',
+          :operatingsystemrelease => '6',
+          :kernel                 => 'Linux',
+          :id                     => 'root',
+          :concat_basedir         => '/dne',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+      let :facts do default_facts end
+      it { should contain_class("apache") }
+      it { should contain_class("apache::mod::fastcgi") }
+      it { should contain_file("fastcgi-pool-#{title}.conf").with(
+        :ensure => 'present',
+        :path => "/etc/httpd/conf.d/fastcgi-pool-#{title}.conf"
+      ) }
+    end
+    context "on Debian based systems" do
+      let :default_facts do
+        {
+          :osfamily               => 'Debian',
+          :operatingsystem        => 'Debian',
+          :operatingsystemrelease => '6',
+          :lsbdistcodename        => 'squeeze',
+          :kernel                 => 'Linux',
+          :id                     => 'root',
+          :concat_basedir         => '/dne',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+      let :facts do default_facts end
+      it { should contain_class("apache") }
+      it { should contain_class("apache::mod::fastcgi") }
+      it { should contain_file("fastcgi-pool-#{title}.conf").with(
+        :ensure => 'present',
+        :path   => "/etc/apache2/conf.d/fastcgi-pool-#{title}.conf"
+      ) }
+    end
+    context "on FreeBSD systems" do
+      let :default_facts do
+        {
+          :osfamily               => 'FreeBSD',
+          :operatingsystem        => 'FreeBSD',
+          :operatingsystemrelease => '9',
+          :kernel                 => 'FreeBSD',
+          :id                     => 'root',
+          :concat_basedir         => '/dne',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+      let :facts do default_facts end
+      it { should contain_class("apache") }
+      it { should contain_class("apache::mod::fastcgi") }
+      it { should contain_file("fastcgi-pool-#{title}.conf").with(
+        :ensure => 'present',
+        :path   => "/usr/local/etc/apache24/Includes/fastcgi-pool-#{title}.conf"
+      ) }
+    end
+    context "on Gentoo systems" do
+      let :default_facts do
+        {
+          :osfamily               => 'Gentoo',
+          :operatingsystem        => 'Gentoo',
+          :operatingsystemrelease => '3.16.1-gentoo',
+          :concat_basedir         => '/dne',
+          :kernel                 => 'Linux',
+          :id                     => 'root',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+          :is_pe                  => false,
+        }
+      end
+      let :facts do default_facts end
+      it { should contain_class("apache") }
+      it { should contain_class("apache::mod::fastcgi") }
+      it { should contain_file("fastcgi-pool-#{title}.conf").with(
+        :ensure => 'present',
+        :path   => "/etc/apache2/conf.d/fastcgi-pool-#{title}.conf"
+      ) }
+    end
+  end
+  describe 'os-independent items' do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :lsbdistcodename        => 'squeeze',
+        :kernel                 => 'Linux',
+        :id                     => 'root',
+        :concat_basedir         => '/dne',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    describe ".conf content" do
+      let :params do
+        {
+          :host       => '127.0.0.1:9001',
+          :timeout    => 30,
+          :flush      => true,
+          :faux_path  => '/var/www/php-www.fcgi',
+          :fcgi_alias => '/php-www.fcgi',
+          :file_type  => 'application/x-httpd-php'
+        }
+      end
+      let :expected do
+'FastCGIExternalServer /var/www/php-www.fcgi -idle-timeout 30 -flush -host 127.0.0.1:9001
+Alias /php-www.fcgi /var/www/php-www.fcgi
+Action application/x-httpd-php /php-www.fcgi
+'
+      end
+      it do
+        should contain_file("fastcgi-pool-www.conf").with_content(expected)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/defines/mod_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,152 @@
+require 'spec_helper'
+
+describe 'apache::mod', :type => :define do
+  let :pre_condition do
+    'include apache'
+  end
+  context "on a RedHat osfamily" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    describe "for non-special modules" do
+      let :title do
+        'spec_m'
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it "should manage the module load file" do
+        is_expected.to contain_file('spec_m.load').with({
+          :path    => '/etc/httpd/conf.d/spec_m.load',
+          :content => "LoadModule spec_m_module modules/mod_spec_m.so\n",
+          :owner   => 'root',
+          :group   => 'root',
+          :mode    => '0644',
+        } )
+      end
+    end
+
+    describe "with shibboleth module and package param passed" do
+      # name/title for the apache::mod define
+      let :title do
+        'xsendfile'
+      end
+      # parameters
+      let(:params) { {:package => 'mod_xsendfile'} }
+
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_package('mod_xsendfile') }
+    end
+  end
+
+  context "on a Debian osfamily" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    describe "for non-special modules" do
+      let :title do
+        'spec_m'
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it "should manage the module load file" do
+        is_expected.to contain_file('spec_m.load').with({
+          :path    => '/etc/apache2/mods-available/spec_m.load',
+          :content => "LoadModule spec_m_module /usr/lib/apache2/modules/mod_spec_m.so\n",
+          :owner   => 'root',
+          :group   => 'root',
+          :mode    => '0644',
+        } )
+      end
+      it "should link the module load file" do
+        is_expected.to contain_file('spec_m.load symlink').with({
+          :path   => '/etc/apache2/mods-enabled/spec_m.load',
+          :target => '/etc/apache2/mods-available/spec_m.load',
+          :owner   => 'root',
+          :group   => 'root',
+          :mode    => '0644',
+        } )
+      end
+    end
+  end
+
+  context "on a FreeBSD osfamily" do
+    let :facts do
+      {
+        :osfamily               => 'FreeBSD',
+        :operatingsystemrelease => '9',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'FreeBSD',
+        :id                     => 'root',
+        :kernel                 => 'FreeBSD',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    describe "for non-special modules" do
+      let :title do
+        'spec_m'
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it "should manage the module load file" do
+        is_expected.to contain_file('spec_m.load').with({
+          :path    => '/usr/local/etc/apache24/Modules/spec_m.load',
+          :content => "LoadModule spec_m_module /usr/local/libexec/apache24/mod_spec_m.so\n",
+          :owner   => 'root',
+          :group   => 'wheel',
+          :mode    => '0644',
+        } )
+      end
+    end
+  end
+
+  context "on a Gentoo osfamily" do
+    let :facts do
+      {
+        :osfamily               => 'Gentoo',
+        :operatingsystem        => 'Gentoo',
+        :operatingsystemrelease => '3.16.1-gentoo',
+        :concat_basedir         => '/dne',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+        :is_pe                  => false,
+      }
+    end
+
+    describe "for non-special modules" do
+      let :title do
+        'spec_m'
+      end
+      it { is_expected.to contain_class("apache::params") }
+      it "should manage the module load file" do
+        is_expected.to contain_file('spec_m.load').with({
+          :path    => '/etc/apache2/modules.d/spec_m.load',
+          :content => "LoadModule spec_m_module /usr/lib/apache2/modules/mod_spec_m.so\n",
+          :owner   => 'root',
+          :group   => 'wheel',
+          :mode    => '0644',
+        } )
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/defines/modsec_link_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,53 @@
+require 'spec_helper'
+
+describe 'apache::security::rule_link', :type => :define do
+  let :pre_condition do
+    'class { "apache": }
+    class { "apache::mod::security": activated_rules => [] }
+    '
+  end
+
+  let :title do
+    'base_rules/modsecurity_35_bad_robots.data'
+  end
+
+  context "on RedHat based systems" do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystem        => 'CentOS',
+        :operatingsystemrelease => '7',
+        :kernel                 => 'Linux',
+        :id                     => 'root',
+        :concat_basedir         => '/',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    it { should contain_file('modsecurity_35_bad_robots.data').with(
+      :path => '/etc/httpd/modsecurity.d/activated_rules/modsecurity_35_bad_robots.data',
+      :target => '/usr/lib/modsecurity.d/base_rules/modsecurity_35_bad_robots.data'
+    ) }
+  end
+
+  context "on Debian based systems" do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystem        => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/',
+        :lsbdistcodename        => 'squeeze',
+        :id                     => 'root',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :kernel                 => 'Linux',
+        :is_pe                  => false,
+      }
+    end
+    it { should contain_file('modsecurity_35_bad_robots.data').with(
+      :path => '/etc/modsecurity/activated_rules/modsecurity_35_bad_robots.data',
+      :target => '/usr/share/modsecurity-crs/base_rules/modsecurity_35_bad_robots.data'
+    ) }
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/defines/vhost_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,942 @@
+require 'spec_helper'
+
+describe 'apache::vhost', :type => :define do
+  let :pre_condition do
+    'class { "apache": default_vhost => false, default_mods => false, vhost_enable_dir => "/etc/apache2/sites-enabled"}'
+  end
+  let :title do
+    'rspec.example.com'
+  end
+  let :default_params do
+    {
+      :docroot => '/rspec/docroot',
+      :port    => '84',
+    }
+  end
+  describe 'os-dependent items' do
+    context "on RedHat based systems" do
+      let :default_facts do
+        {
+          :osfamily               => 'RedHat',
+          :operatingsystemrelease => '6',
+          :concat_basedir         => '/dne',
+          :operatingsystem        => 'RedHat',
+          :id                     => 'root',
+          :kernel                 => 'Linux',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+      let :params do default_params end
+      let :facts do default_facts end
+      it { is_expected.to contain_class("apache") }
+      it { is_expected.to contain_class("apache::params") }
+    end
+    context "on Debian based systems" do
+      let :default_facts do
+        {
+          :osfamily               => 'Debian',
+          :operatingsystemrelease => '6',
+          :concat_basedir         => '/dne',
+          :lsbdistcodename        => 'squeeze',
+          :operatingsystem        => 'Debian',
+          :id                     => 'root',
+          :kernel                 => 'Linux',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+      let :params do default_params end
+      let :facts do default_facts end
+      it { is_expected.to contain_class("apache") }
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_file("25-rspec.example.com.conf").with(
+        :ensure => 'present',
+        :path   => '/etc/apache2/sites-available/25-rspec.example.com.conf'
+      ) }
+      it { is_expected.to contain_file("25-rspec.example.com.conf symlink").with(
+        :ensure => 'link',
+        :path   => '/etc/apache2/sites-enabled/25-rspec.example.com.conf',
+        :target => '/etc/apache2/sites-available/25-rspec.example.com.conf'
+      ) }
+    end
+    context "on FreeBSD systems" do
+      let :default_facts do
+        {
+          :osfamily               => 'FreeBSD',
+          :operatingsystemrelease => '9',
+          :concat_basedir         => '/dne',
+          :operatingsystem        => 'FreeBSD',
+          :id                     => 'root',
+          :kernel                 => 'FreeBSD',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :is_pe                  => false,
+        }
+      end
+      let :params do default_params end
+      let :facts do default_facts end
+      it { is_expected.to contain_class("apache") }
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_file("25-rspec.example.com.conf").with(
+        :ensure => 'present',
+        :path   => '/usr/local/etc/apache24/Vhosts/25-rspec.example.com.conf'
+      ) }
+    end
+    context "on Gentoo systems" do
+      let :default_facts do
+        {
+          :osfamily               => 'Gentoo',
+          :operatingsystem        => 'Gentoo',
+          :operatingsystemrelease => '3.16.1-gentoo',
+          :concat_basedir         => '/dne',
+          :id                     => 'root',
+          :kernel                 => 'Linux',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin',
+          :is_pe                  => false,
+        }
+      end
+      let :params do default_params end
+      let :facts do default_facts end
+      it { is_expected.to contain_class("apache") }
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_file("25-rspec.example.com.conf").with(
+        :ensure => 'present',
+        :path   => '/etc/apache2/vhosts.d/25-rspec.example.com.conf'
+      ) }
+    end
+  end
+  describe 'os-independent items' do
+    let :facts do
+      {
+        :osfamily               => 'Debian',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :lsbdistcodename        => 'squeeze',
+        :operatingsystem        => 'Debian',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    describe 'basic assumptions' do
+      let :params do default_params end
+      it { is_expected.to contain_class("apache") }
+      it { is_expected.to contain_class("apache::params") }
+      it { is_expected.to contain_apache__listen(params[:port]) }
+      it { is_expected.to contain_apache__namevirtualhost("*:#{params[:port]}") }
+    end
+    context 'set everything!' do
+      let :params do
+        {
+          'docroot'                     => '/var/www/foo',
+          'manage_docroot'              => false,
+          'virtual_docroot'             => true,
+          'port'                        => '8080',
+          'ip'                          => '127.0.0.1',
+          'ip_based'                    => true,
+          'add_listen'                  => false,
+          'docroot_owner'               => 'user',
+          'docroot_group'               => 'wheel',
+          'docroot_mode'                => '0664',
+          'serveradmin'                 => 'foo@localhost',
+          'ssl'                         => true,
+          'ssl_cert'                    => '/ssl/cert',
+          'ssl_key'                     => '/ssl/key',
+          'ssl_chain'                   => '/ssl/chain',
+          'ssl_crl_path'                => '/ssl/crl',
+          'ssl_crl'                     => 'foo.crl',
+          'ssl_certs_dir'               => '/ssl/certs',
+          'ssl_protocol'                => 'SSLv2',
+          'ssl_cipher'                  => 'HIGH',
+          'ssl_honorcipherorder'        => 'Off',
+          'ssl_verify_client'           => 'optional',
+          'ssl_verify_depth'            => '3',
+          'ssl_options'                 => '+ExportCertData',
+          'ssl_openssl_conf_cmd'        => 'DHParameters "foo.pem"',
+          'ssl_proxyengine'             => true,
+          'priority'                    => '30',
+          'default_vhost'               => true,
+          'servername'                  => 'example.com',
+          'serveraliases'               => ['test-example.com'],
+          'options'                     => ['MultiView'],
+          'override'                    => ['All'],
+          'directoryindex'              => 'index.html',
+          'vhost_name'                  => 'test',
+          'logroot'                     => '/var/www/logs',
+          'logroot_ensure'              => 'directory',
+          'logroot_mode'                => '0600',
+          'log_level'                   => 'crit',
+          'access_log'                  => false,
+          'access_log_file'             => 'httpd_access_log',
+          'access_log_syslog'           => true,
+          'access_log_format'           => '%h %l %u %t \"%r\" %>s %b',
+          'access_log_env_var'          => '',
+          'aliases'                     => '/image',
+          'directories'                 => [
+            {
+              'path'     => '/var/www/files',
+              'provider' => 'files',
+              'require'  => [ 'valid-user', 'all denied', ],
+            },
+            {
+              'path'     => '/var/www/files',
+              'provider' => 'files',
+              'require'  => 'all granted',
+            },
+            { 'path'              => '/var/www/files/indexed_directory',
+              'directoryindex'    => 'disabled',
+              'options'           => ['Indexes','FollowSymLinks','MultiViews'],
+              'index_options'     => ['FancyIndexing'],
+              'index_style_sheet' => '/styles/style.css',
+            },
+            { 'path'              => '/var/www/files/output_filtered',
+              'set_output_filter' => 'output_filter',
+            },
+          ],
+          'error_log'                   => false,
+          'error_log_file'              => 'httpd_error_log',
+          'error_log_syslog'            => true,
+          'error_documents'             => 'true',
+          'fallbackresource'            => '/index.php',
+          'scriptalias'                 => '/usr/lib/cgi-bin',
+          'scriptaliases'               => [
+            {
+              'alias' => '/myscript',
+              'path'  => '/usr/share/myscript',
+            },
+            {
+              'aliasmatch' => '^/foo(.*)',
+              'path'       => '/usr/share/fooscripts$1',
+            },
+          ],
+          'proxy_dest'                  => '/',
+          'proxy_pass'                  => [
+            {
+              'path'            => '/a',
+              'url'             => 'http://backend-a/',
+              'keywords'        => ['noquery', 'interpolate'],
+              'reverse_cookies' => [{
+                'path'          => '/a',
+                'url'           => 'http://backend-a/',
+              }],
+              'params'          => {
+                      'retry'   => '0',
+                      'timeout' => '5'
+              },
+              'setenv'   => ['proxy-nokeepalive 1','force-proxy-request-1.0 1'],
+            }
+          ],
+          'proxy_pass_match'            => [
+            {
+              'path'     => '/a',
+              'url'      => 'http://backend-a/',
+              'keywords' => ['noquery', 'interpolate'],
+              'params'   => {
+                      'retry'   => '0',
+                      'timeout' => '5'
+              },
+              'setenv'   => ['proxy-nokeepalive 1','force-proxy-request-1.0 1'],
+            }
+          ],
+          'suphp_addhandler'            => 'foo',
+          'suphp_engine'                => 'on',
+          'suphp_configpath'            => '/var/www/html',
+          'php_admin_flags'             => ['foo', 'bar'],
+          'php_admin_values'            => ['true', 'false'],
+          'no_proxy_uris'               => '/foo',
+          'no_proxy_uris_match'         => '/foomatch',
+          'proxy_preserve_host'         => true,
+          'proxy_error_override'        => true,
+          'redirect_source'             => '/bar',
+          'redirect_dest'               => '/',
+          'redirect_status'             => 'temp',
+          'redirectmatch_status'        => ['404'],
+          'redirectmatch_regexp'        => ['\.git$'],
+          'redirectmatch_dest'          => ['http://www.example.com'],
+          'rack_base_uris'              => ['/rackapp1'],
+          'passenger_base_uris'         => ['/passengerapp1'],
+          'headers'                     => 'Set X-Robots-Tag "noindex, noarchive, nosnippet"',
+          'request_headers'             => ['append MirrorID "mirror 12"'],
+          'rewrites'                    => [
+            {
+              'rewrite_rule' => ['^index\.html$ welcome.html']
+            }
+          ],
+          'filters'                     => [
+            'FilterDeclare COMPRESS',
+            'FilterProvider COMPRESS  DEFLATE resp=Content-Type $text/html',
+            'FilterProvider COMPRESS  DEFLATE resp=Content-Type $text/css',
+            'FilterProvider COMPRESS  DEFLATE resp=Content-Type $text/plain',
+            'FilterProvider COMPRESS  DEFLATE resp=Content-Type $text/xml',
+            'FilterChain COMPRESS',
+            'FilterProtocol COMPRESS  DEFLATE change=yes;byteranges=no',
+          ],
+          'rewrite_base'                => '/',
+          'rewrite_rule'                => '^index\.html$ welcome.html',
+          'rewrite_cond'                => '%{HTTP_USER_AGENT} ^MSIE',
+          'setenv'                      => ['FOO=/bin/true'],
+          'setenvif'                    => 'Request_URI "\.gif$" object_is_image=gif',
+          'block'                       => 'scm',
+          'wsgi_application_group'      => '%{GLOBAL}',
+          'wsgi_daemon_process'         => 'wsgi',
+          'wsgi_daemon_process_options' => {
+            'processes'    => '2',
+            'threads'      => '15',
+            'display-name' => '%{GROUP}',
+          },
+          'wsgi_import_script'          => '/var/www/demo.wsgi',
+          'wsgi_import_script_options'  => {
+            'process-group'     => 'wsgi',
+            'application-group' => '%{GLOBAL}'
+          },
+          'wsgi_process_group'          => 'wsgi',
+          'wsgi_script_aliases'         => {
+            '/' => '/var/www/demo.wsgi'
+          },
+          'wsgi_pass_authorization'     => 'On',
+          'custom_fragment'             => '#custom string',
+          'itk'                         => {
+            'user'  => 'someuser',
+            'group' => 'somegroup'
+          },
+          'wsgi_chunked_request'        => 'On',
+          'action'                      => 'foo',
+          'fastcgi_server'              => 'localhost',
+          'fastcgi_socket'              => '/tmp/fastcgi.socket',
+          'fastcgi_dir'                 => '/tmp',
+          'additional_includes'         => '/custom/path/includes',
+          'apache_version'              => '2.4',
+          'use_optional_includes'       => true,
+          'suexec_user_group'           => 'root root',
+          'allow_encoded_slashes'       => 'nodecode',
+          'passenger_app_root'          => '/usr/share/myapp',
+          'passenger_app_env'           => 'test',
+          'passenger_ruby'              => '/usr/bin/ruby1.9.1',
+          'passenger_min_instances'     => '1',
+          'passenger_start_timeout'     => '600',
+          'passenger_pre_start'         => 'http://localhost/myapp',
+          'add_default_charset'         => 'UTF-8',
+          'auth_kerb'                   => true,
+          'krb_method_negotiate'        => 'off',
+          'krb_method_k5passwd'         => 'off',
+          'krb_authoritative'           => 'off',
+          'krb_auth_realms'             => ['EXAMPLE.ORG','EXAMPLE.NET'],
+          'krb_5keytab'                 => '/tmp/keytab5',
+          'krb_local_user_mapping'      => 'off',
+          'limit_request_field_size'    => '54321',
+        }
+      end
+      let :facts do
+        {
+          :osfamily               => 'RedHat',
+          :operatingsystemrelease => '7',
+          :concat_basedir         => '/dne',
+          :operatingsystem        => 'RedHat',
+          :id                     => 'root',
+          :kernel                 => 'Linux',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :kernelversion          => '3.6.2',
+          :is_pe                  => false,
+        }
+      end
+
+      it { is_expected.to compile }
+      it { is_expected.to_not contain_file('/var/www/foo') }
+      it { is_expected.to contain_class('apache::mod::ssl') }
+      it { is_expected.to contain_file('ssl.conf').with(
+        :content => /^\s+SSLHonorCipherOrder On$/ ) }
+      it { is_expected.to contain_file('ssl.conf').with(
+        :content => /^\s+SSLPassPhraseDialog builtin$/ ) }
+      it { is_expected.to contain_file('ssl.conf').with(
+        :content => /^\s+SSLSessionCacheTimeout 300$/ ) }
+      it { is_expected.to contain_class('apache::mod::mime') }
+      it { is_expected.to contain_class('apache::mod::vhost_alias') }
+      it { is_expected.to contain_class('apache::mod::wsgi') }
+      it { is_expected.to contain_class('apache::mod::suexec') }
+      it { is_expected.to contain_class('apache::mod::passenger') }
+      it { is_expected.to contain_file('/var/www/logs').with({
+        'ensure' => 'directory',
+        'mode'   => '0600',
+      })
+      }
+      it { is_expected.to contain_class('apache::mod::rewrite') }
+      it { is_expected.to contain_class('apache::mod::alias') }
+      it { is_expected.to contain_class('apache::mod::proxy') }
+      it { is_expected.to contain_class('apache::mod::proxy_http') }
+      it { is_expected.to contain_class('apache::mod::passenger') }
+      it { is_expected.to contain_class('apache::mod::passenger') }
+      it { is_expected.to contain_class('apache::mod::fastcgi') }
+      it { is_expected.to contain_class('apache::mod::headers') }
+      it { is_expected.to contain_class('apache::mod::filter') }
+      it { is_expected.to contain_class('apache::mod::setenvif') }
+      it { is_expected.to contain_concat('30-rspec.example.com.conf').with({
+        'owner'   => 'root',
+        'mode'    => '0644',
+        'require' => 'Package[httpd]',
+        'notify'  => 'Class[Apache::Service]',
+      })
+      }
+      it { is_expected.to contain_file('30-rspec.example.com.conf symlink').with({
+        'ensure' => 'link',
+        'path'   => '/etc/apache2/sites-enabled/30-rspec.example.com.conf',
+      })
+      }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-apache-header') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-docroot') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-aliases') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-itk') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-fallbackresource') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Require valid-user$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Require all denied$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Require all granted$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Options\sIndexes\sFollowSymLinks\sMultiViews$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+IndexOptions\sFancyIndexing$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+IndexStyleSheet\s'\/styles\/style\.css'$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+DirectoryIndex\sdisabled$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+SetOutputFilter\soutput_filter$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-additional_includes') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-logging') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-serversignature') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-access_log') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-action') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-block') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-error_document') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-proxy').with_content(
+              /retry=0/) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-proxy').with_content(
+              /timeout=5/) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-proxy').with_content(
+              /SetEnv force-proxy-request-1.0 1/) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-proxy').with_content(
+              /SetEnv proxy-nokeepalive 1/) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-proxy').with_content(
+              /noquery interpolate/) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-proxy').with_content(
+              /ProxyPassReverseCookiePath\s+\/a\s+http:\/\//) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-rack') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-redirect') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-rewrite') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-scriptalias') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-serveralias') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-setenv') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-ssl') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-ssl').with(
+        :content => /^\s+SSLOpenSSLConfCmd\s+DHParameters "foo.pem"$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-suphp') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-php_admin') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-header') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-filters').with(
+        :content => /^\s+FilterDeclare COMPRESS$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-requestheader') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-wsgi') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-custom_fragment') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-fastcgi') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-suexec') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-allow_encoded_slashes') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-passenger') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-charsets') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-file_footer') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-auth_kerb').with(
+        :content => /^\s+KrbMethodNegotiate\soff$/)}
+      it { is_expected.to contain_concat__fragment('rspec.example.com-auth_kerb').with(
+        :content => /^\s+KrbAuthoritative\soff$/)}
+      it { is_expected.to contain_concat__fragment('rspec.example.com-auth_kerb').with(
+        :content => /^\s+KrbAuthRealms\sEXAMPLE.ORG\sEXAMPLE.NET$/)}
+      it { is_expected.to contain_concat__fragment('rspec.example.com-auth_kerb').with(
+        :content => /^\s+Krb5Keytab\s\/tmp\/keytab5$/)}
+      it { is_expected.to contain_concat__fragment('rspec.example.com-auth_kerb').with(
+        :content => /^\s+KrbLocalUserMapping\soff$/)}
+      it { is_expected.to contain_concat__fragment('rspec.example.com-limits').with(
+        :content => /^\s+LimitRequestFieldSize\s54321$/)}
+    end
+    context 'vhost with multiple ip addresses' do
+      let :params do
+        {
+          'port'                        => '80',
+          'ip'                          => ['127.0.0.1','::1'],
+          'ip_based'                    => true,
+          'servername'                  => 'example.com',
+          'docroot'                     => '/var/www/html',
+          'add_listen'                  => true,
+          'ensure'                      => 'present'
+        }
+      end
+      let :facts do
+        {
+          :osfamily               => 'RedHat',
+          :operatingsystemrelease => '7',
+          :concat_basedir         => '/dne',
+          :operatingsystem        => 'RedHat',
+          :id                     => 'root',
+          :kernel                 => 'Linux',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :kernelversion          => '3.6.2',
+          :is_pe                  => false,
+        }
+      end
+
+      it { is_expected.to compile }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-apache-header').with(
+        :content => /[.\/m]*<VirtualHost 127.0.0.1:80 ::1:80>[.\/m]*$/ ) }
+      it { is_expected.to contain_concat__fragment('Listen 127.0.0.1:80') }
+      it { is_expected.to contain_concat__fragment('Listen ::1:80') }
+      it { is_expected.to_not contain_concat__fragment('NameVirtualHost 127.0.0.1:80') }
+      it { is_expected.to_not contain_concat__fragment('NameVirtualHost ::1:80') }
+    end
+    context 'set only aliases' do
+      let :params do
+        {
+          'docroot' => '/rspec/docroot',
+          'aliases' => [
+            {
+              'alias' => '/alias',
+              'path'  => '/rspec/docroot',
+            },
+          ]
+        }
+      end
+      it { is_expected.to contain_class('apache::mod::alias')}
+    end
+    context 'proxy_pass_match' do
+      let :params do
+        {
+          'docroot'          => '/rspec/docroot',
+          'proxy_pass_match'            => [
+            {
+              'path'     => '.*',
+              'url'      => 'http://backend-a/',
+              'params'   => { 'timeout' => 300 },
+            }
+          ],
+        }
+      end
+      it { is_expected.to contain_concat__fragment('rspec.example.com-proxy').with_content(
+              /ProxyPassMatch .* http:\/\/backend-a\/ timeout=300/).with_content(/## Proxy rules/) }
+    end
+    context 'proxy_dest_match' do
+      let :params do
+        {
+          'docroot'          => '/rspec/docroot',
+          'proxy_dest_match' => '/'
+        }
+      end
+      it { is_expected.to contain_concat__fragment('rspec.example.com-proxy').with_content(/## Proxy rules/) }
+    end
+    context 'not everything can be set together...' do
+      let :params do
+        {
+          'access_log_pipe' => '/dev/null',
+          'error_log_pipe'  => '/dev/null',
+          'docroot'         => '/var/www/foo',
+          'ensure'          => 'absent',
+          'manage_docroot'  => true,
+          'logroot'         => '/tmp/logroot',
+          'logroot_ensure'  => 'absent',
+          'directories'     => [
+            {
+              'path'     => '/var/www/files',
+              'provider' => 'files',
+              'allow'    => [ 'from 127.0.0.1', 'from 127.0.0.2', ],
+              'deny'     => [ 'from 127.0.0.3', 'from 127.0.0.4', ],
+              'satisfy'  => 'any',
+            },
+            {
+              'path'     => '/var/www/foo',
+              'provider' => 'files',
+              'allow'    => 'from 127.0.0.5',
+              'deny'     => 'from all',
+              'order'    => 'deny,allow',
+            },
+          ],
+
+        }
+      end
+      let :facts do
+        {
+          :osfamily               => 'RedHat',
+          :operatingsystemrelease => '6',
+          :concat_basedir         => '/dne',
+          :operatingsystem        => 'RedHat',
+          :id                     => 'root',
+          :kernel                 => 'Linux',
+          :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+          :kernelversion          => '3.6.2',
+          :is_pe                  => false,
+        }
+      end
+
+      it { is_expected.to compile }
+      it { is_expected.to_not contain_class('apache::mod::ssl') }
+      it { is_expected.to_not contain_class('apache::mod::mime') }
+      it { is_expected.to_not contain_class('apache::mod::vhost_alias') }
+      it { is_expected.to_not contain_class('apache::mod::wsgi') }
+      it { is_expected.to_not contain_class('apache::mod::passenger') }
+      it { is_expected.to_not contain_class('apache::mod::suexec') }
+      it { is_expected.to_not contain_class('apache::mod::rewrite') }
+      it { is_expected.to_not contain_class('apache::mod::alias') }
+      it { is_expected.to_not contain_class('apache::mod::proxy') }
+      it { is_expected.to_not contain_class('apache::mod::proxy_http') }
+      it { is_expected.to_not contain_class('apache::mod::passenger') }
+      it { is_expected.to_not contain_class('apache::mod::headers') }
+      it { is_expected.to contain_file('/var/www/foo') }
+      it { is_expected.to contain_file('/tmp/logroot').with({
+        'ensure' => 'absent',
+      })
+      }
+      it { is_expected.to contain_concat('25-rspec.example.com.conf').with({
+        'ensure' => 'absent',
+      })
+      }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-apache-header') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-docroot') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-aliases') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-itk') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-fallbackresource') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Allow from 127\.0\.0\.1$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Allow from 127\.0\.0\.2$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Allow from 127\.0\.0\.5$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Deny from 127\.0\.0\.3$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Deny from 127\.0\.0\.4$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Deny from all$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Satisfy any$/ ) }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with(
+        :content => /^\s+Order deny,allow$/ ) }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-additional_includes') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-logging') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-serversignature') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-access_log') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-action') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-block') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-error_document') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-proxy') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-rack') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-redirect') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-rewrite') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-scriptalias') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-serveralias') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-setenv') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-ssl') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-suphp') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-php_admin') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-header') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-requestheader') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-wsgi') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-custom_fragment') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-fastcgi') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-suexec') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-charsets') }
+      it { is_expected.to_not contain_concat__fragment('rspec.example.com-limits') }
+      it { is_expected.to contain_concat__fragment('rspec.example.com-file_footer') }
+    end
+    context 'when not setting nor managing the docroot' do
+      let :params do
+        {
+          'docroot'                     => false,
+          'manage_docroot'              => false,
+        }
+      end
+      it { is_expected.to compile }
+      it { is_expected.not_to contain_concat__fragment('rspec.example.com-docroot') }
+    end
+  end
+  describe 'access logs' do
+    let :facts do
+      {
+        :osfamily               => 'RedHat',
+        :operatingsystemrelease => '6',
+        :concat_basedir         => '/dne',
+        :operatingsystem        => 'RedHat',
+        :id                     => 'root',
+        :kernel                 => 'Linux',
+        :path                   => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe                  => false,
+      }
+    end
+    context 'single log file' do
+      let(:params) do
+        {
+          'docroot'         => '/rspec/docroot',
+          'access_log_file' => 'my_log_file',
+        }
+      end
+      it { is_expected.to contain_concat__fragment('rspec.example.com-access_log').with(
+        :content => /^\s+CustomLog.*my_log_file" combined\s*$/
+      )}
+    end
+    context 'single log file with environment' do
+      let(:params) do
+        {
+          'docroot'            => '/rspec/docroot',
+          'access_log_file'    => 'my_log_file',
+          'access_log_env_var' => 'prod'
+        }
+      end
+      it { is_expected.to contain_concat__fragment('rspec.example.com-access_log').with(
+        :content => /^\s+CustomLog.*my_log_file" combined\s+env=prod$/
+      )}
+    end
+    context 'multiple log files' do
+      let(:params) do
+        {
+          'docroot'     => '/rspec/docroot',
+          'access_logs' => [
+            { 'file' => '/tmp/log1', 'env' => 'dev' },
+            { 'file' => 'log2' },
+            { 'syslog' => 'syslog', 'format' => '%h %l' }
+          ],
+        }
+      end
+      it { is_expected.to contain_concat__fragment('rspec.example.com-access_log').with(
+        :content => /^\s+CustomLog "\/tmp\/log1"\s+combined\s+env=dev$/
+      )}
+      it { is_expected.to contain_concat__fragment('rspec.example.com-access_log').with(
+        :content => /^\s+CustomLog "\/var\/log\/httpd\/log2"\s+combined\s*$/
+      )}
+      it { is_expected.to contain_concat__fragment('rspec.example.com-access_log').with(
+        :content => /^\s+CustomLog "syslog" "%h %l"\s*$/
+      )}
+    end
+  end # access logs
+  describe 'validation' do
+    context 'bad ensure' do
+      let :params do
+        {
+          'docroot' => '/rspec/docroot',
+          'ensure'  => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad suphp_engine' do
+      let :params do
+        {
+          'docroot'      => '/rspec/docroot',
+          'suphp_engine' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad ip_based' do
+      let :params do
+        {
+          'docroot'  => '/rspec/docroot',
+          'ip_based' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad access_log' do
+      let :params do
+        {
+          'docroot'    => '/rspec/docroot',
+          'access_log' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad error_log' do
+      let :params do
+        {
+          'docroot'   => '/rspec/docroot',
+          'error_log' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad_ssl' do
+      let :params do
+        {
+          'docroot' => '/rspec/docroot',
+          'ssl'     => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad default_vhost' do
+      let :params do
+        {
+          'docroot'       => '/rspec/docroot',
+          'default_vhost' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad ssl_proxyengine' do
+      let :params do
+        {
+          'docroot'         => '/rspec/docroot',
+          'ssl_proxyengine' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad rewrites' do
+      let :params do
+        {
+          'docroot'  => '/rspec/docroot',
+          'rewrites' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad rewrites 2' do
+      let :params do
+        {
+          'docroot'  => '/rspec/docroot',
+          'rewrites' => ['bogus'],
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad suexec_user_group' do
+      let :params do
+        {
+          'docroot'           => '/rspec/docroot',
+          'suexec_user_group' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad wsgi_script_alias' do
+      let :params do
+        {
+          'docroot'           => '/rspec/docroot',
+          'wsgi_script_alias' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad wsgi_daemon_process_options' do
+      let :params do
+        {
+          'docroot'                     => '/rspec/docroot',
+          'wsgi_daemon_process_options' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad wsgi_import_script_alias' do
+      let :params do
+        {
+          'docroot'                  => '/rspec/docroot',
+          'wsgi_import_script_alias' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad itk' do
+      let :params do
+        {
+          'docroot' => '/rspec/docroot',
+          'itk'     => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad logroot_ensure' do
+      let :params do
+        {
+          'docroot'   => '/rspec/docroot',
+          'log_level' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad log_level' do
+      let :params do
+        {
+          'docroot'   => '/rspec/docroot',
+          'log_level' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'access_log_file and access_log_pipe' do
+      let :params do
+        {
+          'docroot'         => '/rspec/docroot',
+          'access_log_file' => 'bogus',
+          'access_log_pipe' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'error_log_file and error_log_pipe' do
+      let :params do
+        {
+          'docroot'        => '/rspec/docroot',
+          'error_log_file' => 'bogus',
+          'error_log_pipe' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad fallbackresource' do
+      let :params do
+        {
+          'docroot'          => '/rspec/docroot',
+          'fallbackresource' => 'bogus',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad custom_fragment' do
+      let :params do
+        {
+          'docroot'         => '/rspec/docroot',
+          'custom_fragment' => true,
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+    context 'bad access_logs' do
+      let :params do
+        {
+          'docroot'     => '/rspec/docroot',
+          'access_logs' => '/var/log/somewhere',
+        }
+      end
+      let :facts do default_facts end
+      it { expect { is_expected.to compile }.to raise_error }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/spec.opts	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+--format
+s
+--colour
+--loadby
+mtime
+--backtrace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/spec_helper.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+require 'puppetlabs_spec_helper/module_spec_helper'
+
+RSpec.configure do |c|
+  c.treat_symbols_as_metadata_keys_with_true_values = true
+
+  c.before :each do
+    # Ensure that we don't accidentally cache facts and environment
+    # between test cases.
+    Facter::Util::Loader.any_instance.stubs(:load_all)
+    Facter.clear
+    Facter.clear_messages
+
+    # Store any environment variables away to be restored later
+    @old_env = {}
+    ENV.each_key {|k| @old_env[k] = ENV[k]}
+
+    if ENV['STRICT_VARIABLES'] == 'yes'
+      Puppet.settings[:strict_variables]=true
+    end
+  end
+end
+
+shared_examples :compile, :compile => true do
+  it { should compile.with_all_deps }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/spec_helper_acceptance.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,50 @@
+require 'beaker-rspec/spec_helper'
+require 'beaker-rspec/helpers/serverspec'
+require 'beaker/puppet_install_helper'
+
+run_puppet_install_helper
+
+UNSUPPORTED_PLATFORMS = ['Suse','windows','AIX','Solaris']
+
+RSpec.configure do |c|
+  # Project root
+  proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+  # Readable test descriptions
+  c.formatter = :documentation
+
+  # Configure all nodes in nodeset
+  c.before :suite do
+    # net-tools required for netstat utility being used by be_listening
+    if fact('osfamily') == 'RedHat' && fact('operatingsystemmajrelease') == '7'
+      pp = <<-EOS
+        package { 'net-tools': ensure => installed }
+      EOS
+
+      apply_manifest_on(agents, pp, :catch_failures => false)
+    end
+
+    # Install module and dependencies
+    hosts.each do |host|
+      copy_module_to(host, :source => proj_root, :module_name => 'apache')
+      # Required for mod_passenger tests.
+      if fact('osfamily') == 'RedHat'
+        on host, puppet('module','install','stahnma/epel'), { :acceptable_exit_codes => [0,1] }
+        on host, puppet('module','install','puppetlabs/inifile'), { :acceptable_exit_codes => [0,1] }
+      end
+      # Required for manifest to make mod_pagespeed repository available
+      if fact('osfamily') == 'Debian'
+        on host, puppet('module','install','puppetlabs-apt', '--version 1.8.0', '--force'), { :acceptable_exit_codes => [0,1] }
+      end
+      on host, puppet('module','install','puppetlabs-stdlib'), { :acceptable_exit_codes => [0,1] }
+      on host, puppet('module','install','puppetlabs-concat', '--version 1.1.1', '--force'), { :acceptable_exit_codes => [0,1] }
+
+      # Make sure selinux is disabled before each test or apache won't work.
+      if ! UNSUPPORTED_PLATFORMS.include?(fact('osfamily'))
+        on host, puppet('apply', '-e',
+                          %{"exec { 'setenforce 0': path   => '/bin:/sbin:/usr/bin:/usr/sbin', onlyif => 'which setenforce && getenforce | grep Enforcing', }"}),
+                          { :acceptable_exit_codes => [0] }
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/unit/provider/a2mod/gentoo_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,184 @@
+#!/usr/bin/env rspec
+
+require 'spec_helper'
+
+provider_class = Puppet::Type.type(:a2mod).provider(:gentoo)
+
+describe provider_class do
+  before :each do
+    provider_class.clear
+  end
+
+  [:conf_file, :instances, :modules, :initvars, :conf_file, :clear].each do |method|
+    it "should respond to the class method #{method}" do
+      expect(provider_class).to respond_to(method)
+    end
+  end
+
+  describe "when fetching modules" do
+    before do
+      @filetype = mock()
+    end
+
+    it "should return a sorted array of the defined parameters" do
+      @filetype.expects(:read).returns(%Q{APACHE2_OPTS="-D FOO -D BAR -D BAZ"\n})
+      provider_class.expects(:filetype).returns(@filetype)
+
+      expect(provider_class.modules).to eq(%w{bar baz foo})
+    end
+
+    it "should cache the module list" do
+      @filetype.expects(:read).once.returns(%Q{APACHE2_OPTS="-D FOO -D BAR -D BAZ"\n})
+      provider_class.expects(:filetype).once.returns(@filetype)
+
+      2.times { expect(provider_class.modules).to eq(%w{bar baz foo}) }
+    end
+
+    it "should normalize parameters" do
+      @filetype.expects(:read).returns(%Q{APACHE2_OPTS="-D FOO -D BAR -D BAR"\n})
+      provider_class.expects(:filetype).returns(@filetype)
+
+      expect(provider_class.modules).to eq(%w{bar foo})
+    end
+  end
+
+  describe "when prefetching" do
+    it "should match providers to resources" do
+      provider = mock("ssl_provider", :name => "ssl")
+      resource = mock("ssl_resource")
+      resource.expects(:provider=).with(provider)
+
+      provider_class.expects(:instances).returns([provider])
+      provider_class.prefetch("ssl" => resource)
+    end
+  end
+
+  describe "when flushing" do
+    before :each do
+      @filetype = mock()
+      @filetype.stubs(:backup)
+      provider_class.expects(:filetype).at_least_once.returns(@filetype)
+
+      @info = mock()
+      @info.stubs(:[]).with(:name).returns("info")
+      @info.stubs(:provider=)
+
+      @mpm = mock()
+      @mpm.stubs(:[]).with(:name).returns("mpm")
+      @mpm.stubs(:provider=)
+
+      @ssl = mock()
+      @ssl.stubs(:[]).with(:name).returns("ssl")
+      @ssl.stubs(:provider=)
+    end
+
+    it "should add modules whose ensure is present" do
+      @filetype.expects(:read).at_least_once.returns(%Q{APACHE2_OPTS=""})
+      @filetype.expects(:write).with(%Q{APACHE2_OPTS="-D INFO"})
+
+      @info.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("info" => @info)
+
+      provider_class.flush
+    end
+
+    it "should remove modules whose ensure is present" do
+      @filetype.expects(:read).at_least_once.returns(%Q{APACHE2_OPTS="-D INFO"})
+      @filetype.expects(:write).with(%Q{APACHE2_OPTS=""})
+
+      @info.stubs(:should).with(:ensure).returns(:absent)
+      @info.stubs(:provider=)
+      provider_class.prefetch("info" => @info)
+
+      provider_class.flush
+    end
+
+    it "should not modify providers without resources" do
+      @filetype.expects(:read).at_least_once.returns(%Q{APACHE2_OPTS="-D INFO -D MPM"})
+      @filetype.expects(:write).with(%Q{APACHE2_OPTS="-D MPM -D SSL"})
+
+      @info.stubs(:should).with(:ensure).returns(:absent)
+      provider_class.prefetch("info" => @info)
+
+      @ssl.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("ssl" => @ssl)
+
+      provider_class.flush
+    end
+
+    it "should write the modules in sorted order" do
+      @filetype.expects(:read).at_least_once.returns(%Q{APACHE2_OPTS=""})
+      @filetype.expects(:write).with(%Q{APACHE2_OPTS="-D INFO -D MPM -D SSL"})
+
+      @mpm.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("mpm" => @mpm)
+      @info.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("info" => @info)
+      @ssl.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("ssl" => @ssl)
+
+      provider_class.flush
+    end
+
+    it "should write the records back once" do
+      @filetype.expects(:read).at_least_once.returns(%Q{APACHE2_OPTS=""})
+      @filetype.expects(:write).once.with(%Q{APACHE2_OPTS="-D INFO -D SSL"})
+
+      @info.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("info" => @info)
+
+      @ssl.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("ssl" => @ssl)
+
+      provider_class.flush
+    end
+
+    it "should only modify the line containing APACHE2_OPTS" do
+      @filetype.expects(:read).at_least_once.returns(%Q{# Comment\nAPACHE2_OPTS=""\n# Another comment})
+      @filetype.expects(:write).once.with(%Q{# Comment\nAPACHE2_OPTS="-D INFO"\n# Another comment})
+
+      @info.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("info" => @info)
+      provider_class.flush
+    end
+
+    it "should restore any arbitrary arguments" do
+      @filetype.expects(:read).at_least_once.returns(%Q{APACHE2_OPTS="-Y -D MPM -X"})
+      @filetype.expects(:write).once.with(%Q{APACHE2_OPTS="-Y -X -D INFO -D MPM"})
+
+      @info.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("info" => @info)
+      provider_class.flush
+    end
+
+    it "should backup the file once if changes were made" do
+      @filetype.expects(:read).at_least_once.returns(%Q{APACHE2_OPTS=""})
+      @filetype.expects(:write).once.with(%Q{APACHE2_OPTS="-D INFO -D SSL"})
+
+      @info.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("info" => @info)
+
+      @ssl.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("ssl" => @ssl)
+
+      @filetype.unstub(:backup)
+      @filetype.expects(:backup)
+      provider_class.flush
+    end
+
+    it "should not write the file or run backups if no changes were made" do
+      @filetype.expects(:read).at_least_once.returns(%Q{APACHE2_OPTS="-X -D INFO -D SSL -Y"})
+      @filetype.expects(:write).never
+
+      @info.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("info" => @info)
+
+      @ssl.stubs(:should).with(:ensure).returns(:present)
+      provider_class.prefetch("ssl" => @ssl)
+
+      @filetype.unstub(:backup)
+      @filetype.expects(:backup).never
+      provider_class.flush
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/unit/puppet/parser/functions/bool2httpd_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,54 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe "the bool2httpd function" do
+  let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+  it "should exist" do
+    expect(Puppet::Parser::Functions.function("bool2httpd")).to eq("function_bool2httpd")
+  end
+
+  it "should raise a ParseError if there is less than 1 arguments" do
+    expect { scope.function_bool2httpd([]) }.to( raise_error(Puppet::ParseError))
+  end
+
+  it "should convert true to 'On'" do
+    result = scope.function_bool2httpd([true])
+    expect(result).to(eq('On'))
+  end
+
+  it "should convert true to a string" do
+    result = scope.function_bool2httpd([true])
+    expect(result.class).to(eq(String))
+  end
+
+  it "should convert false to 'Off'" do
+    result = scope.function_bool2httpd([false])
+    expect(result).to(eq('Off'))
+  end
+
+  it "should convert false to a string" do
+    result = scope.function_bool2httpd([false])
+    expect(result.class).to(eq(String))
+  end
+
+  it "should accept (and return) any string" do
+    result = scope.function_bool2httpd(["mail"])
+    expect(result).to(eq('mail'))
+  end
+
+  it "should accept a nil value (and return Off)" do
+    result = scope.function_bool2httpd([nil])
+    expect(result).to(eq('Off'))
+  end
+
+  it "should accept an undef value (and return 'Off')" do
+    result = scope.function_bool2httpd([:undef])
+    expect(result).to(eq('Off'))
+  end
+
+  it "should return a default value on non-matches" do
+    result = scope.function_bool2httpd(['foo'])
+    expect(result).to(eq('foo'))
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/spec/unit/puppet/parser/functions/validate_apache_log_level.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe "the validate_apache_log_level function" do
+  let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+  it "should exist" do
+    expect(Puppet::Parser::Functions.function("validate_apache_log_level")).to eq("function_validate_apache_log_level")
+  end
+
+  it "should raise a ParseError if there is less than 1 arguments" do
+    expect { scope.function_validate_apache_log_level([]) }.to( raise_error(Puppet::ParseError) )
+  end
+
+  it "should raise a ParseError when given garbage" do
+    expect { scope.function_validate_apache_log_level(['garbage']) }.to( raise_error(Puppet::ParseError) )
+  end
+
+  it "should not raise a ParseError when given a plain log level" do
+    expect { scope.function_validate_apache_log_level(['info']) }.to_not raise_error 
+  end
+
+  it "should not raise a ParseError when given a log level and module log level" do
+    expect { scope.function_validate_apache_log_level(['warn ssl:info']) }.to_not raise_error 
+  end
+
+  it "should not raise a ParseError when given a log level and module log level" do
+    expect { scope.function_validate_apache_log_level(['warn mod_ssl.c:info']) }.to_not raise_error 
+  end
+
+  it "should not raise a ParseError when given a log level and module log level" do
+    expect { scope.function_validate_apache_log_level(['warn ssl_module:info']) }.to_not raise_error 
+  end
+
+  it "should not raise a ParseError when given a trace level" do
+    expect { scope.function_validate_apache_log_level(['trace4']) }.to_not raise_error 
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/confd/no-accf.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+<IfDefine NOHTTPACCEPT>
+   AcceptFilter http none
+   AcceptFilter https none
+</IfDefine>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/fastcgi/server.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+FastCGIExternalServer <%= @faux_path %> -idle-timeout <%= @timeout %> <%= if @flush then '-flush' end %> -host <%= @host %>
+Alias <%= @fcgi_alias %> <%= @faux_path %>
+Action <%= @file_type %> <%= @fcgi_alias %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/httpd.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,134 @@
+# Security
+ServerTokens <%= @server_tokens %>
+ServerSignature <%= scope.function_bool2httpd([@server_signature]) %>
+TraceEnable <%= scope.function_bool2httpd([@trace_enable]) %>
+
+ServerName "<%= @servername %>"
+ServerRoot "<%= @server_root %>"
+PidFile <%= @pidfile %>
+Timeout <%= @timeout %>
+KeepAlive <%= @keepalive %>
+MaxKeepAliveRequests <%= @max_keepalive_requests %>
+KeepAliveTimeout <%= @keepalive_timeout %>
+
+<%- if @rewrite_lock and scope.function_versioncmp([@apache_version, '2.2']) <= 0 -%>
+RewriteLock <%= @rewrite_lock %>
+<%- end -%>
+
+User <%= @user %>
+Group <%= @group %>
+
+AccessFileName .htaccess
+<FilesMatch "^\.ht">
+<%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+    Require all denied
+<%- else -%>
+     Order allow,deny
+     Deny from all
+     Satisfy all
+<%- end -%>
+</FilesMatch>
+
+<Directory />
+  Options FollowSymLinks
+  AllowOverride None
+</Directory>
+
+<% if @default_charset -%>
+AddDefaultCharset <%= @default_charset %>
+<% end -%>
+
+<%- if scope.function_versioncmp([@apache_version, '2.4']) < 0 -%>
+DefaultType <%= @default_type %>
+<%- end -%>
+HostnameLookups Off
+ErrorLog "<%= @logroot %>/<%= @error_log %>"
+LogLevel <%= @log_level %>
+EnableSendfile <%= @sendfile %>
+<%- if @allow_encoded_slashes -%>
+AllowEncodedSlashes <%= @allow_encoded_slashes %>
+<%- end -%>
+
+#Listen 80
+
+<% if @apxs_workaround -%>
+# Workaround: without this hack apxs would be confused about where to put
+# LoadModule directives and fail entire procedure of apache package
+# installation/reinstallation. This problem was observed on FreeBSD (apache22).
+#LoadModule fake_module libexec/apache22/mod_fake.so
+<% end -%>
+
+Include "<%= @mod_load_dir %>/*.load"
+<% if @mod_load_dir != @confd_dir and @mod_load_dir != @vhost_load_dir -%>
+Include "<%= @mod_load_dir %>/*.conf"
+<% end -%>
+Include "<%= @ports_file %>"
+
+<% unless @log_formats.has_key?('combined') -%>
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+<% end -%>
+<% unless @log_formats.has_key?('common') -%>
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+<% end -%>
+<% unless @log_formats.has_key?('referer') -%>
+LogFormat "%{Referer}i -> %U" referer
+<% end -%>
+<% unless @log_formats.has_key?('agent') -%>
+LogFormat "%{User-agent}i" agent
+<% end -%>
+<% if @log_formats and !@log_formats.empty? -%>
+  <%- @log_formats.sort.each do |nickname,format| -%>
+LogFormat "<%= format -%>" <%= nickname %>
+  <%- end -%>
+<% end -%>
+
+<%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+IncludeOptional "<%= @confd_dir %>/*.conf"
+<%- else -%>
+Include "<%= @confd_dir %>/*.conf"
+<%- end -%>
+<% if @vhost_load_dir != @confd_dir -%>
+<%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+IncludeOptional "<%= @vhost_load_dir %>/<%= @vhost_include_pattern %>"
+<%- else -%>
+Include "<%= @vhost_load_dir %>/<%= @vhost_include_pattern %>"
+<%- end -%>
+<% end -%>
+
+<% if @error_documents -%>
+# /usr/share/apache2/error on debian
+Alias /error/ "<%= @error_documents_path %>/"
+
+<Directory "<%= @error_documents_path %>">
+  AllowOverride None
+  Options IncludesNoExec
+  AddOutputFilter Includes html
+  AddHandler type-map var
+<%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+  Require all granted
+<%- else -%>
+  Order allow,deny
+  Allow from all
+<%- end -%>
+  LanguagePriority en cs de es fr it nl sv pt-br ro
+  ForceLanguagePriority Prefer Fallback
+</Directory>
+
+ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
+ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
+ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
+ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
+ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
+ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
+ErrorDocument 410 /error/HTTP_GONE.html.var
+ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
+ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
+ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
+ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
+ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var
+ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
+ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
+ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
+ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
+ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/listen.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+<%# Listen should always be one of:
+  - <port>
+  - <ipv4>:<port>
+  - [<ipv6]:<port>
+-%>
+Listen <%= @listen_addr_port %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/alias.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+<IfModule alias_module>
+Alias /icons/ "<%= @icons_path %>/"
+<Directory "<%= @icons_path %>">
+    Options <%= @icons_options %>
+    AllowOverride None
+<%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+    Require all granted
+<%- else -%>
+     Order allow,deny
+     Allow from all
+<%- end -%>
+</Directory>
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/auth_cas.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,40 @@
+CASCookiePath <%= @cas_cookie_path %>
+CASLoginURL <%= @cas_login_url %>
+CASValidateURL <%= @cas_validate_url %>
+
+CASVersion <%= @cas_version %>
+CASDebug <%= @cas_debug %>
+
+<% if @cas_certificate_path -%>
+CASCertificatePath <%= @cas_certificate_path %>
+<% end -%>
+<% if @cas_proxy_validate_url -%>
+CASProxyValidateURL <%= @cas_proxy_validate_url %>
+<% end -%>
+<% if @cas_validate_depth -%>
+CASValidateDepth <%= @cas_validate_depth %>
+<% end -%>
+<% if @cas_root_proxied_as -%>
+CASRootProxiedAs <%= @cas_root_proxied_as %>
+<% end -%>
+<% if @cas_cookie_entropy -%>
+CASCookieEntropy <%= @cas_cookie_entropy %>
+<% end -%>
+<% if @cas_timeout -%>
+CASTimeout <%= @cas_timeout %>
+<% end -%>
+<% if @cas_idle_timeout -%>
+CASIdleTimeout <%= @cas_idle_timeout %>
+<% end -%>
+<% if @cas_cache_clean_interval -%>
+CASCacheCleanInterval <%= @cas_cache_clean_interval %>
+<% end -%>
+<% if @cas_cookie_domain -%>
+CASCookieDomain <%= @cas_cookie_domain %>
+<% end -%>
+<% if @cas_cookie_http_only -%>
+CASCookieHttpOnly <%= @cas_cookie_http_only %>
+<% end -%>
+<% if @cas_authoritative -%>
+CASAuthoritative <%= @cas_authoritative %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/auth_mellon.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+<%- if @mellon_cache_size -%>
+MellonCacheSize <%= @mellon_cache_size %>
+<%- end -%>
+<%- if @mellon_cache_entry_size -%>
+MellonCacheEntrySize <%= @mellon_cache_entry_size %>
+<%- end -%>
+<%- if @mellon_lock_file -%>
+MellonLockFile "<%= @mellon_lock_file %>"
+<%- end -%>
+<%- if @mellon_post_directory -%>
+MellonPostDirectory "<%= @mellon_post_directory %>"
+<%- end -%>
+<%- if @mellon_post_ttl -%>
+MellonPostTTL <%= @mellon_post_ttl %>
+<%- end -%>
+<%- if @mellon_post_size -%>
+MellonPostSize <%= @mellon_post_size %>
+<%- end -%>
+<%- if @mellon_post_count -%>
+MellonPostCount <%= @mellon_post_count %>
+<%- end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/authnz_ldap.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+<% if @verifyServerCert == true -%>
+LDAPVerifyServerCert On
+<% else -%>
+LDAPVerifyServerCert Off
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/autoindex.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,56 @@
+IndexOptions FancyIndexing VersionSort HTMLTable NameWidth=* DescriptionWidth=* Charset=UTF-8
+AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip x-bzip2
+
+AddIconByType (TXT,/icons/text.gif) text/*
+AddIconByType (IMG,/icons/image2.gif) image/*
+AddIconByType (SND,/icons/sound2.gif) audio/*
+AddIconByType (VID,/icons/movie.gif) video/*
+
+AddIcon /icons/binary.gif .bin .exe
+AddIcon /icons/binhex.gif .hqx
+AddIcon /icons/tar.gif .tar
+AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
+AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
+AddIcon /icons/a.gif .ps .ai .eps
+AddIcon /icons/layout.gif .html .shtml .htm .pdf
+AddIcon /icons/text.gif .txt
+AddIcon /icons/c.gif .c
+AddIcon /icons/p.gif .pl .py
+AddIcon /icons/f.gif .for
+AddIcon /icons/dvi.gif .dvi
+AddIcon /icons/uuencoded.gif .uu
+AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
+AddIcon /icons/tex.gif .tex
+AddIcon /icons/bomb.gif /core
+AddIcon (SND,/icons/sound2.gif) .ogg
+AddIcon (VID,/icons/movie.gif) .ogm
+
+AddIcon /icons/back.gif ..
+AddIcon /icons/hand.right.gif README
+AddIcon /icons/folder.gif ^^DIRECTORY^^
+AddIcon /icons/blank.gif ^^BLANKICON^^
+
+AddIcon /icons/odf6odt-20x22.png .odt
+AddIcon /icons/odf6ods-20x22.png .ods
+AddIcon /icons/odf6odp-20x22.png .odp
+AddIcon /icons/odf6odg-20x22.png .odg
+AddIcon /icons/odf6odc-20x22.png .odc
+AddIcon /icons/odf6odf-20x22.png .odf
+AddIcon /icons/odf6odb-20x22.png .odb
+AddIcon /icons/odf6odi-20x22.png .odi
+AddIcon /icons/odf6odm-20x22.png .odm
+
+AddIcon /icons/odf6ott-20x22.png .ott
+AddIcon /icons/odf6ots-20x22.png .ots
+AddIcon /icons/odf6otp-20x22.png .otp
+AddIcon /icons/odf6otg-20x22.png .otg
+AddIcon /icons/odf6otc-20x22.png .otc
+AddIcon /icons/odf6otf-20x22.png .otf
+AddIcon /icons/odf6oti-20x22.png .oti
+AddIcon /icons/odf6oth-20x22.png .oth
+
+DefaultIcon /icons/unknown.gif
+ReadmeName README.html
+HeaderName HEADER.html
+
+IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/cgid.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+ScriptSock "<%= @cgisock_path %>"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/dav_fs.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+DAVLockDB "<%= @dav_lock %>"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/deflate.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+<%- @types.sort.each do |type| -%>
+AddOutputFilterByType DEFLATE <%= type %>
+<%- end -%>
+
+<%- @notes.sort.each do |type,note| -%>
+DeflateFilterNote <%= type %> <%=note %>
+<%- end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/dir.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+DirectoryIndex <%= @indexes.join(' ') %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/disk_cache.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+CacheEnable disk /
+CacheRoot "<%= @_cache_root %>"
+CacheDirLevels 2
+CacheDirLength 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/event.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+<IfModule mpm_event_module>
+  ServerLimit            <%= @serverlimit %>
+  StartServers           <%= @startservers %>
+  MaxClients             <%= @maxclients %>
+  MinSpareThreads        <%= @minsparethreads %>
+  MaxSpareThreads        <%= @maxsparethreads %>
+  ThreadsPerChild        <%= @threadsperchild %>
+  MaxRequestsPerChild    <%= @maxrequestsperchild %>
+  ThreadLimit            <%= @threadlimit %>
+  ListenBacklog          <%= @listenbacklog %>
+  MaxRequestWorkers      <%= @maxrequestworkers %>
+  MaxConnectionsPerChild <%= @maxconnectionsperchild %>
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/expires.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+ExpiresActive <%= scope.function_bool2httpd([@expires_active]) %>
+<%- if ! @expires_default.nil? and ! @expires_default.empty? -%>
+ExpiresDefault "<%= @expires_default %>"
+<%- end -%>
+<%- if ! @expires_by_type.nil? and ! @expires_by_type.empty? -%>
+<%-   [@expires_by_type].flatten.each do |line| -%>
+<%-     line.map do |type, seconds| -%>
+ExpiresByType <%= type %> "<%= seconds -%>"
+<%-     end -%>
+<%-   end -%>
+<%- end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/ext_filter.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+# mod_ext_filter definitions
+<%- if @ext_filter_define.length >= 1 -%>
+<%- @ext_filter_define.keys.sort.each do |name| -%>
+ExtFilterDefine <%= name %> <%= @ext_filter_define[name] %>
+<%- end -%>
+<%- end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/fastcgi.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+# The Fastcgi Apache module configuration file is being
+# managed by Puppet and changes will be overwritten.
+<IfModule mod_fastcgi.c>
+  AddHandler fastcgi-script .fcgi
+  FastCgiIpcDir "<%= @fastcgi_lib_path %>"
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/geoip.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+GeoIPEnable <%= scope.function_bool2httpd([@enable]) %>
+
+<%- if @db_file and ! [ false, 'false', '' ].include?(@db_file) -%>
+    <%- if @db_file.kind_of?(Array) -%>
+      <%- Array(@db_file).each do |file| -%>
+GeoIPDBFile <%= file %> <%= @flag %>
+      <%- end -%>
+    <%- else -%>
+GeoIPDBFile <%= @db_file %> <%= @flag %>
+    <%- end -%>
+<%- end -%>
+GeoIPOutput <%= @output %>
+<% if ! @enable_utf8.nil? -%>
+GeoIPEnableUTF8 <%= scope.function_bool2httpd([@enable_utf8]) %>
+<% end -%>
+<% if ! @scan_proxy_headers.nil? -%>
+GeoIPScanProxyHeaders <%= scope.function_bool2httpd([@scan_proxy_headers]) %>
+<% end -%>
+<% if ! @scan_proxy_header_field.nil? -%>
+GeoIPScanProxyHeaderField <%= @scan_proxy_header_field %>
+<% end -%>
+<% if ! @use_last_xforwarededfor_ip.nil? -%>
+GeoIPUseLastXForwardedForIP <%= scope.function_bool2httpd([@use_last_xforwarededfor_ip]) %>
+<% end -%>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/info.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+<Location /server-info>
+    SetHandler server-info
+<%- if @restrict_access -%>
+  <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+    Require ip <%= Array(@allow_from).join(" ") %>
+  <%- else -%>
+    Order deny,allow
+    Deny from all
+    <%- if @allow_from and ! @allow_from.empty? -%>
+      <%- @allow_from.each do |allowed| -%>
+    Allow from <%= allowed %>
+      <%- end -%>
+    <%- else -%>
+    Allow from 127.0.0.1
+    Allow from ::1
+    <%- end -%>
+  <%- end -%>
+<%- end -%>
+</Location>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/itk.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+<IfModule mpm_itk_module>
+  StartServers        <%= @startservers %>
+  MinSpareServers     <%= @minspareservers %>
+  MaxSpareServers     <%= @maxspareservers %>
+  ServerLimit         <%= @serverlimit %>
+  MaxClients          <%= @maxclients %>
+  MaxRequestsPerChild <%= @maxrequestsperchild %>
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/ldap.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+<Location /ldap-status>
+    SetHandler ldap-status
+    <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+    Require ip 127.0.0.1 ::1
+    <%- else -%>
+    Order deny,allow
+    Deny from all
+    Allow from 127.0.0.1 ::1
+    Satisfy all
+    <%- end -%>
+</Location>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/load.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+<% if @loadfiles -%>
+<% Array(@loadfiles).each do |loadfile| -%>
+LoadFile <%= loadfile %>
+<% end -%>
+
+<% end -%>
+LoadModule <%= @_id %> <%= @_path %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/mime.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+TypesConfig <%= @mime_types_config %>
+
+AddType application/x-compress .Z
+AddType application/x-gzip .gz .tgz
+AddType application/x-bzip2 .bz2
+
+AddLanguage ca .ca
+AddLanguage cs .cz .cs
+AddLanguage da .dk
+AddLanguage de .de
+AddLanguage el .el
+AddLanguage en .en
+AddLanguage eo .eo
+AddLanguage es .es
+AddLanguage et .et
+AddLanguage fr .fr
+AddLanguage he .he
+AddLanguage hr .hr
+AddLanguage it .it
+AddLanguage ja .ja
+AddLanguage ko .ko
+AddLanguage ltz .ltz
+AddLanguage nl .nl
+AddLanguage nn .nn
+AddLanguage no .no
+AddLanguage pl .po
+AddLanguage pt .pt
+AddLanguage pt-BR .pt-br
+AddLanguage ru .ru
+AddLanguage sv .sv
+AddLanguage zh-CN .zh-cn
+AddLanguage zh-TW .zh-tw
+
+AddHandler type-map var
+AddType text/html .shtml
+AddOutputFilter INCLUDES .shtml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/mime_magic.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+MIMEMagicFile "<%= @magic_file %>"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/mpm_event.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+<IfModule mpm_event_module>
+  StartServers          2
+  MinSpareThreads      25
+  MaxSpareThreads      75
+  ThreadLimit          64
+  ThreadsPerChild      25
+  MaxClients          150
+  MaxRequestsPerChild   0
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/negotiation.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,2 @@
+LanguagePriority <%= Array(@language_priority).join(' ') %>
+ForceLanguagePriority <%= Array(@force_language_priority).join(' ') %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/nss.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,228 @@
+#
+# This is the Apache server configuration file providing SSL support using.
+# the mod_nss plugin.  It contains the configuration directives to instruct
+# the server how to serve pages over an https connection.
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do.  They're here only as hints or reminders.  If you are unsure
+# consult the online docs. You have been warned.
+#
+
+#LoadModule nss_module modules/libmodnss.so
+
+#
+# When we also provide SSL we have to listen to the
+# standard HTTP port (see above) and to the HTTPS port
+#
+# Note: Configurations that use IPv6 but not IPv4-mapped addresses need two
+#       Listen directives: "Listen [::]:8443" and "Listen 0.0.0.0:443"
+#
+Listen 8443
+
+##
+##  SSL Global Context
+##
+##  All SSL configuration in this context applies both to
+##  the main server and all SSL-enabled virtual hosts.
+##
+
+#
+#   Some MIME-types for downloading Certificates and CRLs
+#
+AddType application/x-x509-ca-cert .crt
+AddType application/x-pkcs7-crl    .crl
+
+#   Pass Phrase Dialog:
+#   Configure the pass phrase gathering process.
+#   The filtering dialog program (`builtin' is a internal
+#   terminal dialog) has to provide the pass phrase on stdout.
+<% if @passwd_file -%>
+NSSPassPhraseDialog  "file:<%= @passwd_file %>"
+<% else -%>
+NSSPassPhraseDialog  builtin
+<% end -%>
+
+#   Pass Phrase Helper:
+#   This helper program stores the token password pins between
+#   restarts of Apache.
+NSSPassPhraseHelper /usr/sbin/nss_pcache
+
+#   Configure the SSL Session Cache.
+#   NSSSessionCacheSize is the number of entries in the cache.
+#   NSSSessionCacheTimeout is the SSL2 session timeout (in seconds).
+#   NSSSession3CacheTimeout is the SSL3/TLS session timeout (in seconds).
+NSSSessionCacheSize 10000
+NSSSessionCacheTimeout 100
+NSSSession3CacheTimeout 86400
+
+#
+# Pseudo Random Number Generator (PRNG):
+# Configure one or more sources to seed the PRNG of the SSL library.
+# The seed data should be of good random quality.
+# WARNING! On some platforms /dev/random blocks if not enough entropy
+# is available. Those platforms usually also provide a non-blocking
+# device, /dev/urandom, which may be used instead.
+#
+# This does not support seeding the RNG with each connection.
+
+NSSRandomSeed startup builtin
+#NSSRandomSeed startup file:/dev/random  512
+#NSSRandomSeed startup file:/dev/urandom 512
+
+#
+# TLS Negotiation configuration under RFC 5746
+#
+# Only renegotiate if the peer's hello bears the TLS renegotiation_info
+# extension. Default off.
+NSSRenegotiation off
+
+# Peer must send Signaling Cipher Suite Value (SCSV) or
+# Renegotiation Info (RI) extension in ALL handshakes.  Default: off
+NSSRequireSafeNegotiation off
+
+##
+## SSL Virtual Host Context
+##
+
+<VirtualHost _default_:8443>
+
+#   General setup for the virtual host
+#DocumentRoot "/etc/httpd/htdocs"
+#ServerName www.example.com:8443
+#ServerAdmin you@example.com
+
+# mod_nss can log to separate log files, you can choose to do that if you'd like
+# LogLevel is not inherited from httpd.conf.
+ErrorLog "<%= @error_log %>"
+TransferLog "<%= @transfer_log %>"
+LogLevel warn
+
+#   SSL Engine Switch:
+#   Enable/Disable SSL for this virtual host.
+NSSEngine on
+
+#   SSL Cipher Suite:
+#   List the ciphers that the client is permitted to negotiate.
+#   See the mod_nss documentation for a complete list.
+
+# SSL 3 ciphers. SSL 2 is disabled by default.
+NSSCipherSuite +rsa_rc4_128_md5,+rsa_rc4_128_sha,+rsa_3des_sha,-rsa_des_sha,-rsa_rc4_40_md5,-rsa_rc2_40_md5,-rsa_null_md5,-rsa_null_sha,+fips_3des_sha,-fips_des_sha,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,-rsa_des_56_sha,-rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha
+
+# SSL 3 ciphers + ECC ciphers. SSL 2 is disabled by default.
+#
+# Comment out the NSSCipherSuite line above and use the one below if you have
+# ECC enabled NSS and mod_nss and want to use Elliptical Curve Cryptography
+#NSSCipherSuite +rsa_rc4_128_md5,+rsa_rc4_128_sha,+rsa_3des_sha,-rsa_des_sha,-rsa_rc4_40_md5,-rsa_rc2_40_md5,-rsa_null_md5,-rsa_null_sha,+fips_3des_sha,-fips_des_sha,-fortezza,-fortezza_rc4_128_sha,-fortezza_null,-rsa_des_56_sha,-rsa_rc4_56_sha,+rsa_aes_128_sha,+rsa_aes_256_sha,-ecdh_ecdsa_null_sha,+ecdh_ecdsa_rc4_128_sha,+ecdh_ecdsa_3des_sha,+ecdh_ecdsa_aes_128_sha,+ecdh_ecdsa_aes_256_sha,-ecdhe_ecdsa_null_sha,+ecdhe_ecdsa_rc4_128_sha,+ecdhe_ecdsa_3des_sha,+ecdhe_ecdsa_aes_128_sha,+ecdhe_ecdsa_aes_256_sha,-ecdh_rsa_null_sha,+ecdh_rsa_128_sha,+ecdh_rsa_3des_sha,+ecdh_rsa_aes_128_sha,+ecdh_rsa_aes_256_sha,-echde_rsa_null,+ecdhe_rsa_rc4_128_sha,+ecdhe_rsa_3des_sha,+ecdhe_rsa_aes_128_sha,+ecdhe_rsa_aes_256_sha
+
+#   SSL Protocol:
+#   Cryptographic protocols that provide communication security.
+#   NSS handles the specified protocols as "ranges", and automatically
+#   negotiates the use of the strongest protocol for a connection starting
+#   with the maximum specified protocol and downgrading as necessary to the
+#   minimum specified protocol that can be used between two processes.
+#   Since all protocol ranges are completely inclusive, and no protocol in the
+#   middle of a range may be excluded, the entry "NSSProtocol SSLv3,TLSv1.1"
+#   is identical to the entry "NSSProtocol SSLv3,TLSv1.0,TLSv1.1".
+NSSProtocol SSLv3,TLSv1.0,TLSv1.1
+
+#   SSL Certificate Nickname:
+#   The nickname of the RSA server certificate you are going to use.
+NSSNickname Server-Cert
+
+#   SSL Certificate Nickname:
+#   The nickname of the ECC server certificate you are going to use, if you
+#   have an ECC-enabled version of NSS and mod_nss
+#NSSECCNickname Server-Cert-ecc
+
+#   Server Certificate Database:
+#   The NSS security database directory that holds the certificates and
+#   keys. The database consists of 3 files: cert8.db, key3.db and secmod.db.
+#   Provide the directory that these files exist.
+NSSCertificateDatabase "<%= @httpd_dir -%>/alias"
+
+#   Database Prefix:
+#   In order to be able to store multiple NSS databases in one directory
+#   they need unique names. This option sets the database prefix used for
+#   cert8.db and key3.db.
+#NSSDBPrefix my-prefix-
+
+#   Client Authentication (Type):
+#   Client certificate verification type.  Types are none, optional and
+#   require.
+#NSSVerifyClient none
+
+#
+#   Online Certificate Status Protocol (OCSP).
+#   Verify that certificates have not been revoked before accepting them.
+#NSSOCSP off
+
+#
+#   Use a default OCSP responder. If enabled this will be used regardless
+#   of whether one is included in a client certificate. Note that the
+#   server certificate is verified during startup.
+#
+#   NSSOCSPDefaultURL defines the service URL of the OCSP responder
+#   NSSOCSPDefaultName is the nickname of the certificate to trust to
+#       sign the OCSP responses.
+#NSSOCSPDefaultResponder on
+#NSSOCSPDefaultURL http://example.com/ocsp/status
+#NSSOCSPDefaultName ocsp-nickname
+
+#   Access Control:
+#   With SSLRequire you can do per-directory access control based
+#   on arbitrary complex boolean expressions containing server
+#   variable checks and other lookup directives.  The syntax is a
+#   mixture between C and Perl.  See the mod_nss documentation
+#   for more details.
+#<Location />
+#NSSRequire (    %{SSL_CIPHER} !~ m/^(EXP|NULL)/ \
+#            and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
+#            and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
+#            and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
+#            and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20       ) \
+#           or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/
+#</Location>
+
+#   SSL Engine Options:
+#   Set various options for the SSL engine.
+#   o FakeBasicAuth:
+#     Translate the client X.509 into a Basic Authorisation.  This means that
+#     the standard Auth/DBMAuth methods can be used for access control.  The
+#     user name is the `one line' version of the client's X.509 certificate.
+#     Note that no password is obtained from the user. Every entry in the user
+#     file needs this password: `xxj31ZMTZzkVA'.
+#   o ExportCertData:
+#     This exports two additional environment variables: SSL_CLIENT_CERT and
+#     SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
+#     server (always existing) and the client (only existing when client
+#     authentication is used). This can be used to import the certificates
+#     into CGI scripts.
+#   o StdEnvVars:
+#     This exports the standard SSL/TLS related `SSL_*' environment variables.
+#     Per default this exportation is switched off for performance reasons,
+#     because the extraction step is an expensive operation and is usually
+#     useless for serving static content. So one usually enables the
+#     exportation for CGI and SSI requests only.
+#   o StrictRequire:
+#     This denies access when "NSSRequireSSL" or "NSSRequire" applied even
+#     under a "Satisfy any" situation, i.e. when it applies access is denied
+#     and no other module can change it.
+#   o OptRenegotiate:
+#     This enables optimized SSL connection renegotiation handling when SSL
+#     directives are used in per-directory context.
+#NSSOptions +FakeBasicAuth +ExportCertData +CompatEnvVars +StrictRequire
+<FilesMatch "\.(cgi|shtml|phtml|php3?)$">
+    NSSOptions +StdEnvVars
+</FilesMatch>
+<Directory "/var/www/cgi-bin">
+    NSSOptions +StdEnvVars
+</Directory>
+
+#   Per-Server Logging:
+#   The home of a custom SSL log file. Use this when you want a
+#   compact non-error SSL logfile on a virtual host basis.
+#CustomLog /home/rcrit/redhat/apache/logs/ssl_request_log \
+#          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
+
+</VirtualHost>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/pagespeed.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,98 @@
+ModPagespeed on
+
+ModPagespeedInheritVHostConfig <%= @inherit_vhost_config %>
+AddOutputFilterByType MOD_PAGESPEED_OUTPUT_FILTER text/html
+<% if @filter_xhtml -%>
+AddOutputFilterByType MOD_PAGESPEED_OUTPUT_FILTER application/xhtml+xml
+<% end -%>
+ModPagespeedFileCachePath "<%= @cache_path %>"
+ModPagespeedLogDir "<%= @log_dir %>"
+    
+<% @memcache_servers.each do |server| -%>
+ModPagespeedMemcachedServers <%= server %>
+<% end -%>
+
+ModPagespeedRewriteLevel <%= @rewrite_level -%>
+
+<% @disable_filters.each do |filter| -%>
+ModPagespeedDisableFilters <%= filter %>
+<% end -%>
+    
+<% @enable_filters.each do |filter| -%>
+ModPagespeedEnableFilters <%= filter %>
+<% end -%>
+
+<% @forbid_filters.each do |filter| -%>
+ModPagespeedForbidFilters <%= filter %>
+<% end -%>
+
+ModPagespeedRewriteDeadlinePerFlushMs <%= @rewrite_deadline_per_flush_ms %>
+
+<% if @additional_domains -%>
+ModPagespeedDomain <%= @additional_domains -%>
+<% end -%>
+
+ModPagespeedFileCacheSizeKb          <%= @file_cache_size_kb %>
+ModPagespeedFileCacheCleanIntervalMs <%= @file_cache_clean_interval_ms %>
+ModPagespeedLRUCacheKbPerProcess     <%= @lru_cache_per_process %>
+ModPagespeedLRUCacheByteLimit        <%= @lru_cache_byte_limit %>
+ModPagespeedCssFlattenMaxBytes       <%= @css_flatten_max_bytes %>
+ModPagespeedCssInlineMaxBytes        <%= @css_inline_max_bytes %>
+ModPagespeedCssImageInlineMaxBytes   <%= @css_image_inline_max_bytes %>
+ModPagespeedImageInlineMaxBytes      <%= @image_inline_max_bytes %>
+ModPagespeedJsInlineMaxBytes         <%= @js_inline_max_bytes %>
+ModPagespeedCssOutlineMinBytes       <%= @css_outline_min_bytes %>
+ModPagespeedJsOutlineMinBytes        <%= @js_outline_min_bytes %>
+
+
+ModPagespeedFileCacheInodeLimit <%= @inode_limit %>
+ModPagespeedImageMaxRewritesAtOnce <%= @image_max_rewrites_at_once %>
+
+ModPagespeedNumRewriteThreads <%= @num_rewrite_threads %>
+ModPagespeedNumExpensiveRewriteThreads <%= @num_expensive_rewrite_threads %>
+
+ModPagespeedStatistics <%= @collect_statistics %>
+
+<Location /mod_pagespeed_statistics>
+    # You may insert other "Allow from" lines to add hosts you want to
+    # allow to look at generated statistics.  Another possibility is
+    # to comment out the "Order" and "Allow" options from the config
+    # file, to allow any client that can reach your server to examine
+    # statistics.  This might be appropriate in an experimental setup or
+    # if the Apache server is protected by a reverse proxy that will
+    # filter URLs in some fashion.
+    <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+    Require ip 127.0.0.1 ::1 <%= Array(@allow_view_stats).join(" ") %>
+    <%- else -%>
+    Order allow,deny
+    Allow from 127.0.0.1 ::1 <%= Array(@allow_view_stats).join(" ") %>
+    <%- end -%>
+    SetHandler mod_pagespeed_statistics
+</Location>
+
+ModPagespeedStatisticsLogging <%= @statistics_logging %>
+<Location /pagespeed_console>
+    <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+    Require ip 127.0.0.1 ::1 <%= Array(@allow_pagespeed_console).join(" ") %>
+    <%- else -%>
+    Order allow,deny
+    Allow from 127.0.0.1 ::1 <%= Array(@allow_pagespeed_console).join(" ") %>
+    <%- end -%>
+    SetHandler pagespeed_console
+</Location>
+
+ModPagespeedMessageBufferSize <%= @message_buffer_size %>
+
+<Location /mod_pagespeed_message>
+    <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+    Require ip 127.0.0.1 ::1 <%= Array(@allow_pagespeed_message).join(" ") %>
+    <%- else -%>
+    Order allow,deny
+    Allow from 127.0.0.1 ::1 <%= Array(@allow_pagespeed_message).join(" ") %>
+    <%- end -%>
+    SetHandler mod_pagespeed_message
+</Location>
+
+<% @additional_configuration.each_pair do |key, value| -%>
+<%= key %> <%= value %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/passenger.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+# The Passenger Apache module configuration file is being
+# managed by Puppet and changes will be overwritten.
+<IfModule mod_passenger.c>
+  <%- if @passenger_root -%>
+  PassengerRoot "<%= @passenger_root %>"
+  <%- end -%>
+  <%- if @passenger_ruby -%>
+  PassengerRuby "<%= @passenger_ruby %>"
+  <%- end -%>
+  <%- if @passenger_default_ruby -%>
+  PassengerDefaultRuby "<%= @passenger_default_ruby %>"
+  <%- end -%>
+  <%- if @passenger_high_performance -%>
+  PassengerHighPerformance <%= @passenger_high_performance %>
+  <%- end -%>
+  <%- if @passenger_max_pool_size -%>
+  PassengerMaxPoolSize <%= @passenger_max_pool_size %>
+  <%- end -%>
+  <%- if @passenger_min_instances -%>
+  PassengerMinInstances <%= @passenger_min_instances %>
+  <%- end -%>
+  <%- if @passenger_pool_idle_time -%>
+  PassengerPoolIdleTime <%= @passenger_pool_idle_time %>
+  <%- end -%>
+  <%- if @passenger_max_requests -%>
+  PassengerMaxRequests <%= @passenger_max_requests %>
+  <%- end -%>
+  <%- if @passenger_spawn_method -%>
+  PassengerSpawnMethod <%= @passenger_spawn_method %>
+  <%- end -%>
+  <%- if @passenger_stat_throttle_rate -%>
+  PassengerStatThrottleRate <%= @passenger_stat_throttle_rate %>
+  <%- end -%>
+  <%- if @rack_autodetect -%>
+  RackAutoDetect <%= @rack_autodetect %>
+  <%- end -%>
+  <%- if @rails_autodetect -%>
+  RailsAutoDetect <%= @rails_autodetect %>
+  <%- end -%>
+  <%- if @passenger_use_global_queue -%>
+  PassengerUseGlobalQueue <%= @passenger_use_global_queue %>
+  <%- end -%>
+  <%- if @passenger_app_env -%>
+  PassengerAppEnv <%= @passenger_app_env %>
+  <%- end -%>
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/peruser.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+<IfModule mpm_peruser_module>
+  MinSpareProcessors  <%= @minspareprocessors %>
+  MinProcessors       <%= @minprocessors %>
+  MaxProcessors       <%= @maxprocessors %>
+  MaxClients          <%= @maxclients %>
+  MaxRequestsPerChild <%= @maxrequestsperchild %>
+  IdleTimeout         <%= @idletimeout %>
+  ExpireTimeout       <%= @expiretimeout %>
+  KeepAlive           <%= @keepalive %>
+  Include             "<%= @mod_dir %>/peruser/multiplexers/*.conf"
+  Include             "<%= @mod_dir %>/peruser/processors/*.conf"
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/php5.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,30 @@
+#
+# PHP is an HTML-embedded scripting language which attempts to make it
+# easy for developers to write dynamically generated webpages.
+#
+#<IfModule prefork.c>
+#  LoadModule php5_module modules/libphp5.so
+#</IfModule>
+#<IfModule worker.c>
+#  # Use of the "ZTS" build with worker is experimental, and no shared
+#  # modules are supported.
+#  LoadModule php5_module modules/libphp5-zts.so
+#</IfModule>
+
+#
+# Cause the PHP interpreter to handle files with a .php extension.
+#
+AddHandler php5-script <%= @extensions.flatten.compact.join(' ') %>
+AddType text/html .php
+
+#
+# Add index.php to the list of files that will be served as directory
+# indexes.
+#
+DirectoryIndex index.php
+
+#
+# Uncomment the following line to allow PHP to pretty-print .phps
+# files as PHP source code:
+#
+#AddType application/x-httpd-php-source .phps
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/prefork.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+<IfModule mpm_prefork_module>
+  StartServers        <%= @startservers %>
+  MinSpareServers     <%= @minspareservers %>
+  MaxSpareServers     <%= @maxspareservers %>
+  ServerLimit         <%= @serverlimit %>
+  MaxClients          <%= @maxclients %>
+  MaxRequestsPerChild <%= @maxrequestsperchild %>
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/proxy.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+#
+# Proxy Server directives. Uncomment the following lines to
+# enable the proxy server:
+#
+<IfModule mod_proxy.c>
+  # Do not enable proxying with ProxyRequests until you have secured your
+  # server.  Open proxy servers are dangerous both to your network and to the
+  # Internet at large.
+  ProxyRequests <%= @proxy_requests %>
+
+  <% if @proxy_requests != 'Off' or ( @allow_from and ! @allow_from.empty? ) -%>
+  <Proxy *>
+    <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+    Require ip <%= Array(@allow_from).join(" ") %>
+    <%- else -%>
+    Order deny,allow
+    Deny from all
+    Allow from <%= Array(@allow_from).join(" ") %>
+    <%- end -%>
+  </Proxy>
+  <% end -%>
+
+  # Enable/disable the handling of HTTP/1.1 "Via:" headers.
+  # ("Full" adds the server version; "Block" removes all outgoing Via: headers)
+  # Set to one of: Off | On | Full | Block
+  ProxyVia On
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/proxy_html.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+ProxyHTMLLinks  a               href
+ProxyHTMLLinks  area            href
+ProxyHTMLLinks  link            href
+ProxyHTMLLinks  img             src longdesc usemap
+ProxyHTMLLinks  object          classid codebase data usemap
+ProxyHTMLLinks  q               cite
+ProxyHTMLLinks  blockquote      cite
+ProxyHTMLLinks  ins             cite
+ProxyHTMLLinks  del             cite
+ProxyHTMLLinks  form            action
+ProxyHTMLLinks  input           src usemap
+ProxyHTMLLinks  head            profileProxyHTMLLinks  base            href
+ProxyHTMLLinks  script          src for
+
+ProxyHTMLEvents onclick ondblclick onmousedown onmouseup \
+                onmouseover onmousemove onmouseout onkeypress \
+                onkeydown onkeyup onfocus onblur onload \
+                onunload onsubmit onreset onselect onchange
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/remoteip.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+# Declare the header field which should be parsed for useragent IP addresses
+RemoteIPHeader <%= @header %>
+
+<%- if @proxy_ips -%>
+# Declare client intranet IP addresses trusted to present
+# the RemoteIPHeader value
+<%-   [@proxy_ips].flatten.each do |proxy| -%>
+RemoteIPInternalProxy <%= proxy %>
+<%-   end -%>
+<%- end -%>
+
+<%- if @proxies_header -%>
+# Declare the header field which will record all intermediate IP addresses
+RemoteIPProxiesHeader <%= @proxies_header %>
+<%- end -%>
+
+<%- if @trusted_proxy_ips -%>
+# Declare client intranet IP addresses trusted to present
+# the RemoteIPHeader value
+  <%- [@trusted_proxy_ips].flatten.each do |proxy| -%>
+RemoteIPTrustedProxy <%= proxy %>
+  <%- end -%>
+<%- end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/reqtimeout.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+<% Array(@timeouts).each do |timeout| -%>
+RequestReadTimeout <%= timeout %>
+<%- end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/rpaf.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+# Enable reverse proxy add forward
+RPAFenable On
+# RPAFsethostname will, when enabled, take the incoming X-Host header and
+# update the virtual host settings accordingly. This allows to have the same
+# hostnames as in the "real" configuration for the forwarding proxy.
+<% if @sethostname -%>
+RPAFsethostname On
+<% else -%>
+RPAFsethostname Off
+<% end -%>
+# Which IPs are forwarding requests to us
+RPAFproxy_ips <%= Array(@proxy_ips).join(" ") %>
+# Setting RPAFheader allows you to change the header name to parse from the
+# default X-Forwarded-For to something of your choice.
+RPAFheader <%= @header %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/security.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,71 @@
+<IfModule mod_security2.c>
+    # ModSecurity Core Rules Set configuration
+<%- if scope.function_versioncmp([scope.lookupvar('::apache::apache_version'), '2.4']) >= 0 -%>
+    IncludeOptional <%= @modsec_dir %>/*.conf
+    IncludeOptional <%= @modsec_dir %>/activated_rules/*.conf
+<%- else -%>
+    Include <%= @modsec_dir %>/*.conf
+    Include <%= @modsec_dir %>/activated_rules/*.conf
+<%- end -%>
+
+    # Default recommended configuration
+    SecRuleEngine <%= @modsec_secruleengine %>
+    SecRequestBodyAccess On
+    SecRule REQUEST_HEADERS:Content-Type "text/xml" \
+      "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
+    SecRequestBodyLimit 13107200
+    SecRequestBodyNoFilesLimit 131072
+    SecRequestBodyInMemoryLimit 131072
+    SecRequestBodyLimitAction Reject
+    SecRule REQBODY_ERROR "!@eq 0" \
+      "id:'200001', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
+    SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
+      "id:'200002',phase:2,t:none,log,deny,status:44,msg:'Multipart request body failed strict validation: \
+      PE %{REQBODY_PROCESSOR_ERROR}, \
+      BQ %{MULTIPART_BOUNDARY_QUOTED}, \
+      BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
+      DB %{MULTIPART_DATA_BEFORE}, \
+      DA %{MULTIPART_DATA_AFTER}, \
+      HF %{MULTIPART_HEADER_FOLDING}, \
+      LF %{MULTIPART_LF_LINE}, \
+      SM %{MULTIPART_MISSING_SEMICOLON}, \
+      IQ %{MULTIPART_INVALID_QUOTING}, \
+      IP %{MULTIPART_INVALID_PART}, \
+      IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
+      FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
+
+    SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \
+      "id:'200003',phase:2,t:none,log,deny,status:44,msg:'Multipart parser detected a possible unmatched boundary.'"
+
+    SecPcreMatchLimit 1000
+    SecPcreMatchLimitRecursion 1000
+
+    SecRule TX:/^MSC_/ "!@streq 0" \
+      "id:'200004',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
+
+    SecResponseBodyAccess Off
+    SecResponseBodyMimeType text/plain text/html text/xml
+    SecResponseBodyLimit 524288
+    SecResponseBodyLimitAction ProcessPartial
+    SecDebugLogLevel 0
+    SecAuditEngine RelevantOnly
+    SecAuditLogRelevantStatus "^(?:5|4(?!04))"
+    SecAuditLogParts ABIJDEFHZ
+    SecAuditLogType Serial
+    SecArgumentSeparator &
+    SecCookieFormat 0
+<%- if scope.lookupvar('::osfamily') == 'Debian' -%>
+    SecDebugLog /var/log/apache2/modsec_debug.log
+    SecAuditLog /var/log/apache2/modsec_audit.log
+    SecTmpDir /var/cache/modsecurity
+    SecDataDir /var/cache/modsecurity
+    SecUploadDir /var/cache/modsecurity
+<% else -%>
+    SecDebugLog /var/log/httpd/modsec_debug.log
+    SecAuditLog /var/log/httpd/modsec_audit.log
+    SecTmpDir /var/lib/mod_security
+    SecDataDir /var/lib/mod_security
+    SecUploadDir /var/lib/mod_security
+<% end -%>
+    SecUploadKeepFiles Off
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/security_crs.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,428 @@
+# ---------------------------------------------------------------
+# Core ModSecurity Rule Set ver.2.2.6
+# Copyright (C) 2006-2012 Trustwave All rights reserved.
+#
+# The OWASP ModSecurity Core Rule Set is distributed under
+# Apache Software License (ASL) version 2
+# Please see the enclosed LICENCE file for full details.
+# ---------------------------------------------------------------
+
+
+#
+# -- [[ Recommended Base Configuration ]] -------------------------------------------------
+#
+# The configuration directives/settings in this file are used to control
+# the OWASP ModSecurity CRS. These settings do **NOT** configure the main
+# ModSecurity settings such as:
+#
+# - SecRuleEngine
+# - SecRequestBodyAccess
+# - SecAuditEngine
+# - SecDebugLog
+#
+# You should use the modsecurity.conf-recommended file that comes with the
+# ModSecurity source code archive.
+#
+# Ref: http://mod-security.svn.sourceforge.net/viewvc/mod-security/m2/trunk/modsecurity.conf-recommended
+#
+
+
+#
+# -- [[ Rule Version ]] -------------------------------------------------------------------
+#
+# Rule version data is added to the "Producer" line of Section H of the Audit log:
+#
+# - Producer: ModSecurity for Apache/2.7.0-rc1 (http://www.modsecurity.org/); OWASP_CRS/2.2.4.
+#
+# Ref: https://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Reference_Manual#SecComponentSignature
+#
+SecComponentSignature "OWASP_CRS/2.2.6"
+
+
+#
+# -- [[ Modes of Operation: Self-Contained vs. Collaborative Detection ]] -----------------
+#
+# Each detection rule uses the "block" action which will inherit the SecDefaultAction
+# specified below.  Your settings here will determine which mode of operation you use.
+#
+# -- [[ Self-Contained Mode ]] --
+# Rules inherit the "deny" disruptive action.  The first rule that matches will block.
+#
+# -- [[ Collaborative Detection Mode ]] --
+# This is a "delayed blocking" mode of operation where each matching rule will inherit
+# the "pass" action and will only contribute to anomaly scores.  Transactional blocking
+# can be applied
+#
+# -- [[ Alert Logging Control ]] --
+# You have three options -
+#
+# - To log to both the Apache error_log and ModSecurity audit_log file use: "log"
+# - To log *only* to the ModSecurity audit_log file use: "nolog,auditlog"
+# - To log *only* to the Apache error_log file use: "log,noauditlog"
+#
+# Ref: http://blog.spiderlabs.com/2010/11/advanced-topic-of-the-week-traditional-vs-anomaly-scoring-detection-modes.html
+# Ref: https://sourceforge.net/apps/mediawiki/mod-security/index.php?title=Reference_Manual#SecDefaultAction
+#
+SecDefaultAction "phase:1,deny,log"
+
+
+#
+# -- [[ Collaborative Detection Severity Levels ]] ----------------------------------------
+#
+# These are the default scoring points for each severity level.  You may
+# adjust these to you liking.  These settings will be used in macro expansion
+# in the rules to increment the anomaly scores when rules match.
+#
+# These are the default Severity ratings (with anomaly scores) of the individual rules -
+#
+#    - 2: Critical - Anomaly Score of 5.
+#         Is the highest severity level possible without correlation.  It is
+#         normally generated by the web attack rules (40 level files).
+#    - 3: Error - Anomaly Score of 4.
+#         Is generated mostly from outbound leakage rules (50 level files).
+#    - 4: Warning - Anomaly Score of 3.
+#         Is generated by malicious client rules (35 level files).
+#    - 5: Notice - Anomaly Score of 2.
+#         Is generated by the Protocol policy and anomaly files.
+#
+SecAction \
+  "id:'900001', \
+  phase:1, \
+  t:none, \
+  setvar:tx.critical_anomaly_score=5, \
+  setvar:tx.error_anomaly_score=4, \
+  setvar:tx.warning_anomaly_score=3, \
+  setvar:tx.notice_anomaly_score=2, \
+  nolog, \
+  pass"
+
+
+#
+# -- [[ Collaborative Detection Scoring Threshold Levels ]] ------------------------------
+#
+# These variables are used in macro expansion in the 49 inbound blocking and 59
+# outbound blocking files.
+#
+# **MUST HAVE** ModSecurity v2.5.12 or higher to use macro expansion in numeric
+# operators.  If you have an earlier version, edit the 49/59 files directly to
+# set the appropriate anomaly score levels.
+#
+# You should set the score to the proper threshold you would prefer. If set to "5"
+# it will work similarly to previous Mod CRS rules and will create an event in the error_log
+# file if there are any rules that match.  If you would like to lessen the number of events
+# generated in the error_log file, you should increase the anomaly score threshold to
+# something like "20".  This would only generate an event in the error_log file if
+# there are multiple lower severity rule matches or if any 1 higher severity item matches.
+#
+SecAction \
+  "id:'900002', \
+  phase:1, \
+  t:none, \
+  setvar:tx.inbound_anomaly_score_level=5, \
+  nolog, \
+  pass"
+
+
+SecAction \
+  "id:'900003', \
+  phase:1, \
+  t:none, \
+  setvar:tx.outbound_anomaly_score_level=4, \
+  nolog, \
+  pass"
+
+
+#
+# -- [[ Collaborative Detection Blocking ]] -----------------------------------------------
+#
+# This is a collaborative detection mode where each rule will increment an overall
+# anomaly score for the transaction. The scores are then evaluated in the following files:
+#
+# Inbound anomaly score - checked in the modsecurity_crs_49_inbound_blocking.conf file
+# Outbound anomaly score - checked in the modsecurity_crs_59_outbound_blocking.conf file
+#
+# If you want to use anomaly scoring mode, then uncomment this line.
+#
+#SecAction \
+  "id:'900004', \
+  phase:1, \
+  t:none, \
+  setvar:tx.anomaly_score_blocking=on, \
+  nolog, \
+  pass"
+
+
+#
+# -- [[ GeoIP Database ]] -----------------------------------------------------------------
+#
+# There are some rulesets that need to inspect the GEO data of the REMOTE_ADDR data.
+#
+# You must first download the MaxMind GeoIP Lite City DB -
+#
+#       http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
+#
+# You then need to define the proper path for the SecGeoLookupDb directive
+#
+# Ref: http://blog.spiderlabs.com/2010/10/detecting-malice-with-modsecurity-geolocation-data.html
+# Ref: http://blog.spiderlabs.com/2010/11/detecting-malice-with-modsecurity-ip-forensics.html
+#
+#SecGeoLookupDb /opt/modsecurity/lib/GeoLiteCity.dat
+
+#
+# -- [[ Regression Testing Mode ]] --------------------------------------------------------
+#
+# If you are going to run the regression testing mode, you should uncomment the
+# following rule. It will enable DetectionOnly mode for the SecRuleEngine and
+# will enable Response Header tagging so that the client testing script can see
+# which rule IDs have matched.
+#
+# You must specify the your source IP address where you will be running the tests
+# from.
+#
+#SecRule REMOTE_ADDR "@ipMatch 192.168.1.100" \
+  "id:'900005', \
+  phase:1, \
+  t:none, \
+  ctl:ruleEngine=DetectionOnly, \
+  setvar:tx.regression_testing=1, \
+  nolog, \
+  pass"
+
+
+#
+# -- [[ HTTP Policy Settings ]] ----------------------------------------------------------
+#
+# Set the following policy settings here and they will be propagated to the 23 rules
+# file (modsecurity_common_23_request_limits.conf) by using macro expansion.
+# If you run into false positives, you can adjust the settings here.
+#
+# Only the max number of args is uncommented by default as there are a high rate
+# of false positives.  Uncomment the items you wish to set.
+#
+#
+# -- Maximum number of arguments in request limited
+SecAction \
+  "id:'900006', \
+  phase:1, \
+  t:none, \
+  setvar:tx.max_num_args=255, \
+  nolog, \
+  pass"
+
+#
+# -- Limit argument name length
+#SecAction \
+  "id:'900007', \
+  phase:1, \
+  t:none, \
+  setvar:tx.arg_name_length=100, \
+  nolog, \
+  pass"
+
+#
+# -- Limit value name length
+#SecAction \
+  "id:'900008', \
+  phase:1, \
+  t:none, \
+  setvar:tx.arg_length=400, \
+  nolog, \
+  pass"
+
+#
+# -- Limit arguments total length
+#SecAction \
+  "id:'900009', \
+  phase:1, \
+  t:none, \
+  setvar:tx.total_arg_length=64000, \
+  nolog, \
+  pass"
+
+#
+# -- Individual file size is limited
+#SecAction \
+  "id:'900010', \
+  phase:1, \
+  t:none, \
+  setvar:tx.max_file_size=1048576, \
+  nolog, \
+  pass"
+
+#
+# -- Combined file size is limited
+#SecAction \
+  "id:'900011', \
+  phase:1, \
+  t:none, \
+  setvar:tx.combined_file_sizes=1048576, \
+  nolog, \
+  pass"
+
+
+#
+# Set the following policy settings here and they will be propagated to the 30 rules
+# file (modsecurity_crs_30_http_policy.conf) by using macro expansion.
+# If you run into false positves, you can adjust the settings here.
+#
+SecAction \
+  "id:'900012', \
+  phase:1, \
+  t:none, \
+  setvar:'tx.allowed_methods=<%= @allowed_methods -%>', \
+  setvar:'tx.allowed_request_content_type=<%= @content_types -%>', \
+  setvar:'tx.allowed_http_versions=HTTP/0.9 HTTP/1.0 HTTP/1.1', \
+  setvar:'tx.restricted_extensions=<%= @restricted_extensions -%>', \
+  setvar:'tx.restricted_headers=<%= @restricted_headers -%>', \
+  nolog, \
+  pass"
+
+
+#
+# -- [[ Content Security Policy (CSP) Settings ]] -----------------------------------------
+#
+# The purpose of these settings is to send CSP response headers to
+# Mozilla FireFox users so that you can enforce how dynamic content
+# is used. CSP usage helps to prevent XSS attacks against your users.
+#
+# Reference Link:
+#
+#	https://developer.mozilla.org/en/Security/CSP
+#
+# Uncomment this SecAction line if you want use CSP enforcement.
+# You need to set the appropriate directives and settings for your site/domain and
+# and activate the CSP file in the experimental_rules directory.
+#
+# Ref: http://blog.spiderlabs.com/2011/04/modsecurity-advanced-topic-of-the-week-integrating-content-security-policy-csp.html
+#
+#SecAction \
+  "id:'900013', \
+  phase:1, \
+  t:none, \
+  setvar:tx.csp_report_only=1, \
+  setvar:tx.csp_report_uri=/csp_violation_report, \
+  setenv:'csp_policy=allow \'self\'; img-src *.yoursite.com; media-src *.yoursite.com; style-src *.yoursite.com; frame-ancestors *.yoursite.com; script-src *.yoursite.com; report-uri %{tx.csp_report_uri}', \
+  nolog, \
+  pass"
+
+
+#
+# -- [[ Brute Force Protection ]] ---------------------------------------------------------
+#
+# If you are using the Brute Force Protection rule set, then uncomment the following
+# lines and set the following variables:
+# - Protected URLs: resources to protect (e.g. login pages) - set to your login page
+# - Burst Time Slice Interval: time interval window to monitor for bursts
+# - Request Threshold: request # threshold to trigger a burst
+# - Block Period: temporary block timeout
+#
+#SecAction \
+  "id:'900014', \
+  phase:1, \
+  t:none, \
+  setvar:'tx.brute_force_protected_urls=/login.jsp /partner_login.php', \
+  setvar:'tx.brute_force_burst_time_slice=60', \
+  setvar:'tx.brute_force_counter_threshold=10', \
+  setvar:'tx.brute_force_block_timeout=300', \
+  nolog, \
+  pass"
+
+
+#
+# -- [[ DoS Protection ]] ----------------------------------------------------------------
+#
+# If you are using the DoS Protection rule set, then uncomment the following
+# lines and set the following variables:
+# - Burst Time Slice Interval: time interval window to monitor for bursts
+# - Request Threshold: request # threshold to trigger a burst
+# - Block Period: temporary block timeout
+#
+#SecAction \
+  "id:'900015', \
+  phase:1, \
+  t:none, \
+  setvar:'tx.dos_burst_time_slice=60', \
+  setvar:'tx.dos_counter_threshold=100', \
+  setvar:'tx.dos_block_timeout=600', \
+  nolog, \
+  pass"
+
+
+#
+# -- [[ Check UTF enconding ]] -----------------------------------------------------------
+#
+# We only want to apply this check if UTF-8 encoding is actually used by the site, otherwise
+# it will result in false positives.
+#
+# Uncomment this line if your site uses UTF8 encoding
+#SecAction \
+  "id:'900016', \
+  phase:1, \
+  t:none, \
+  setvar:tx.crs_validate_utf8_encoding=1, \
+  nolog, \
+  pass"
+
+
+#
+# -- [[ Enable XML Body Parsing ]] -------------------------------------------------------
+#
+# The rules in this file will trigger the XML parser upon an XML request
+#
+# Initiate XML Processor in case of xml content-type
+#
+SecRule REQUEST_HEADERS:Content-Type "text/xml" \
+  "id:'900017', \
+  phase:1, \
+  t:none,t:lowercase, \
+  nolog, \
+  pass, \
+  chain"
+	SecRule REQBODY_PROCESSOR "!@streq XML" \
+	  "ctl:requestBodyProcessor=XML"
+
+
+#
+# -- [[ Global and IP Collections ]] -----------------------------------------------------
+#
+# Create both Global and IP collections for rules to use
+# There are some CRS rules that assume that these two collections
+# have already been initiated.
+#
+SecRule REQUEST_HEADERS:User-Agent "^(.*)$" \
+  "id:'900018', \
+  phase:1, \
+  t:none,t:sha1,t:hexEncode, \
+  setvar:tx.ua_hash=%{matched_var}, \
+  nolog, \
+  pass"
+
+
+SecRule REQUEST_HEADERS:x-forwarded-for "^\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b" \
+  "id:'900019', \
+  phase:1, \
+  t:none, \
+  capture, \
+  setvar:tx.real_ip=%{tx.1}, \
+  nolog, \
+  pass"
+
+
+SecRule &TX:REAL_IP "!@eq 0" \
+  "id:'900020', \
+  phase:1, \
+  t:none, \
+  initcol:global=global, \
+  initcol:ip=%{tx.real_ip}_%{tx.ua_hash}, \
+  nolog, \
+  pass"
+
+
+SecRule &TX:REAL_IP "@eq 0" \
+  "id:'900021', \
+  phase:1, \
+  t:none, \
+  initcol:global=global, \
+  initcol:ip=%{remote_addr}_%{tx.ua_hash}, \
+  nolog, \
+  pass"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/setenvif.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#
+# The following directives modify normal HTTP response behavior to
+# handle known problems with browser implementations.
+#
+BrowserMatch "Mozilla/2" nokeepalive
+BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
+BrowserMatch "RealPlayer 4\.0" force-response-1.0
+BrowserMatch "Java/1\.0" force-response-1.0
+BrowserMatch "JDK/1\.0" force-response-1.0
+
+#
+# The following directive disables redirects on non-GET requests for
+# a directory that does not include the trailing slash.  This fixes a 
+# problem with Microsoft WebFolders which does not appropriately handle 
+# redirects for folders with DAV methods.
+# Same deal with Apple's DAV filesystem and Gnome VFS support for DAV.
+#
+BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
+BrowserMatch "MS FrontPage" redirect-carefully
+BrowserMatch "^WebDrive" redirect-carefully
+BrowserMatch "^WebDAVFS/1.[0123]" redirect-carefully
+BrowserMatch "^gnome-vfs/1.0" redirect-carefully
+BrowserMatch "^gvfs/1" redirect-carefully
+BrowserMatch "^XML Spy" redirect-carefully
+BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
+BrowserMatch " Konqueror/4" redirect-carefully
+
+<IfModule mod_ssl.c>
+  BrowserMatch "MSIE [2-6]" \
+    nokeepalive ssl-unclean-shutdown \
+    downgrade-1.0 force-response-1.0
+  # MSIE 7 and newer should be able to use keepalive
+  BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/ssl.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+<IfModule mod_ssl.c>
+  SSLRandomSeed startup builtin
+  SSLRandomSeed startup file:/dev/urandom <%= @ssl_random_seed_bytes %>
+  SSLRandomSeed connect builtin
+  SSLRandomSeed connect file:/dev/urandom <%= @ssl_random_seed_bytes %>
+
+  AddType application/x-x509-ca-cert .crt
+  AddType application/x-pkcs7-crl    .crl
+
+  SSLPassPhraseDialog <%= @ssl_pass_phrase_dialog %>
+  SSLSessionCache "shmcb:<%= @session_cache %>"
+  SSLSessionCacheTimeout <%= @ssl_sessioncachetimeout %>
+<% if @ssl_compression -%>
+  SSLCompression On
+<% end -%>
+  <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+  Mutex <%= @ssl_mutex %>
+  <%- else -%>
+  SSLMutex <%= @ssl_mutex %>
+  <%- end -%>
+  SSLCryptoDevice <%= @ssl_cryptodevice %>
+  SSLHonorCipherOrder <%= @ssl_honorcipherorder %>
+  SSLCipherSuite <%= @ssl_cipher %>
+  SSLProtocol <%= @ssl_protocol.compact.join(' ') %>
+<% if @ssl_options -%>
+  SSLOptions <%= @ssl_options.compact.join(' ') %>
+<% end -%>
+<%- if @ssl_openssl_conf_cmd -%>
+  SSLOpenSSLConfCmd <%= @ssl_openssl_conf_cmd %>
+<%- end -%>
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/status.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+<Location <%= @status_path %>>
+    SetHandler server-status
+    <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+    Require ip <%= Array(@allow_from).join(" ") %>
+    <%- else -%>
+    Order deny,allow
+    Deny from all
+    Allow from <%= Array(@allow_from).join(" ") %>
+    <%- end -%>
+</Location>
+ExtendedStatus <%= @extended_status %>
+
+<IfModule mod_proxy.c>
+    # Show Proxy LoadBalancer status in mod_status
+    ProxyStatus On
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/suphp.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+<IfModule mod_suphp.c>
+    AddType application/x-httpd-suphp .php .php3 .php4 .php5 .phtml
+    suPHP_AddHandler application/x-httpd-suphp
+
+    <Directory />
+        suPHP_Engine on
+    </Directory>
+
+    # By default, disable suPHP for debian packaged web applications as files
+    # are owned by root and cannot be executed by suPHP because of min_uid.
+    <Directory /usr/share>
+        suPHP_Engine off
+    </Directory>
+
+# # Use a specific php config file (a dir which contains a php.ini file)
+#       suPHP_ConfigPath /etc/php4/cgi/suphp/
+# # Tells mod_suphp NOT to handle requests with the type <mime-type>.
+#       suPHP_RemoveHandler <mime-type>
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/unixd_fcgid.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+<IfModule mod_fcgid.c>
+<% @options.sort_by {|key, value| key}.each do |key, value| -%>
+  <%= key %> <%= value %>
+<% end -%>
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/userdir.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+<IfModule mod_userdir.c>
+<% if @disable_root -%>
+  UserDir disabled root
+<% end -%>
+  UserDir <%= @home %>/*/<%= @dir %>
+
+  <Directory "<%= @home %>/*/<%= @dir %>">
+    AllowOverride FileInfo AuthConfig Limit Indexes
+    Options <%= @options.join(' ') %>
+    <Limit GET POST OPTIONS>
+      <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+      Require all granted
+      <%- else -%>
+      Order allow,deny
+      Allow from all
+      <%- end -%>
+    </Limit>
+    <LimitExcept GET POST OPTIONS>
+      <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+      Require all granted
+      <%- else -%>
+      Order allow,deny
+      Allow from all
+      <%- end -%>
+    </LimitExcept>
+  </Directory>
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/worker.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+<IfModule mpm_worker_module>
+  ServerLimit         <%= @serverlimit %>
+  StartServers        <%= @startservers %>
+  MaxClients          <%= @maxclients %>
+  MinSpareThreads     <%= @minsparethreads %>
+  MaxSpareThreads     <%= @maxsparethreads %>
+  ThreadsPerChild     <%= @threadsperchild %>
+  MaxRequestsPerChild <%= @maxrequestsperchild %>
+  ThreadLimit         <%= @threadlimit %>
+  ListenBacklog       <%= @listenbacklog %>
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/mod/wsgi.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+# The WSGI Apache module configuration file is being
+# managed by Puppet an changes will be overwritten.
+<IfModule mod_wsgi.c>
+  <%- if @wsgi_socket_prefix -%>
+  WSGISocketPrefix <%= @wsgi_socket_prefix %>
+  <%- end -%>
+  <%- if @wsgi_python_home -%>
+  WSGIPythonHome "<%= @wsgi_python_home %>"
+  <%- end -%>
+  <%- if @wsgi_python_path -%>
+  WSGIPythonPath "<%= @wsgi_python_path %>"
+  <%- end -%>
+</IfModule>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/namevirtualhost.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+<%# NameVirtualHost should always be one of:
+  - *
+  - *:<port>
+  - _default_:<port>
+  - <ip>
+  - <ip>:<port>
+-%>
+NameVirtualHost <%= @addr_port %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/ports_header.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+# ************************************
+# Listen & NameVirtualHost resources in module puppetlabs-apache
+# Managed by Puppet
+# ************************************
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_access_log.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+<% @_access_logs.each do |log| -%>
+<%   env ||= "env=#{log['env']}" if log['env'] -%>
+<%   env ||= '' -%>
+<%   format ||= "\"#{log['format']}\"" if log['format'] -%>
+<%   format ||= 'combined' -%>
+<%   if log['file'] -%>
+<%     if log['file'].chars.first == '/' -%>
+<%       destination = "#{log['file']}" -%>
+<%     else -%>
+<%       destination = "#{@logroot}/#{log['file']}" -%>
+<%     end -%>
+<%   elsif log['syslog'] -%>
+<%     destination = "syslog" -%>
+<%   elsif log['pipe'] -%>
+<%     destination = log['pipe'] -%>
+<%   else -%>
+<%     destination ||= "#{@logroot}/#{@name}_access_ssl.log" if @ssl -%>
+<%     destination ||= "#{@logroot}/#{@name}_access.log" -%>
+<%   end -%>
+  CustomLog "<%= destination %>" <%= format %> <%= env %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_action.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+<% if @action -%>
+
+  Action <%= @action %> /cgi-bin virtual
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_additional_includes.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+<% Array(@additional_includes).each do |include| -%>
+
+  ## Load additional static includes
+<%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 && @use_optional_includes -%>
+  IncludeOptional "<%= include %>"
+<%- else -%>
+  Include "<%= include %>"
+<%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_aliases.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+<% if @aliases and ! @aliases.empty? -%>
+  ## Alias declarations for resources outside the DocumentRoot
+  <%- [@aliases].flatten.compact.each do |alias_statement| -%>
+    <%- if alias_statement["path"] != '' -%>
+      <%- if alias_statement["alias"] and alias_statement["alias"] != '' -%>
+  Alias <%= alias_statement["alias"] %> "<%= alias_statement["path"] %>"
+      <%- elsif alias_statement["aliasmatch"] and alias_statement["aliasmatch"] != '' -%>
+  AliasMatch <%= alias_statement["aliasmatch"] %> "<%= alias_statement["path"] %>"
+      <%- elsif alias_statement["scriptalias"] and alias_statement["scriptalias"] != '' -%>
+  ScriptAlias <%= alias_statement["scriptalias"] %> "<%= alias_statement["path"] %>"
+      <%- elsif alias_statement["scriptaliasmatch"] and alias_statement["scriptaliasmatch"] != '' -%>
+  ScriptAliasMatch <%= alias_statement["scriptaliasmatch"] %> "<%= alias_statement["path"] %>"
+      <%- end -%>
+    <%- end -%>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_allow_encoded_slashes.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+<%- if @allow_encoded_slashes -%>
+
+  AllowEncodedSlashes <%= @allow_encoded_slashes %>
+<%- end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_auth_kerb.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+<% if @auth_kerb -%>
+
+  ## Kerberos directives
+  <%- if @krb_method_negotiate -%>
+  KrbMethodNegotiate <%= @krb_method_negotiate %>
+  <%- end -%>
+  <%- if @krb_method_k5passwd -%>
+  KrbMethodK5Passwd <%= @krb_method_k5passwd %>
+  <%- end -%>
+  <%- if @krb_authoritative -%>
+  KrbAuthoritative <%= @krb_authoritative %>
+  <%- end -%>
+  <%- if @krb_auth_realms and @krb_auth_realms.length >= 1 -%>
+  KrbAuthRealms <%= @krb_auth_realms.join(' ') %>
+  <%- end -%>
+  <%- if @krb_5keytab -%>
+  Krb5Keytab <%= @krb_5keytab %>
+  <%- end -%>
+  <%- if @krb_local_user_mapping -%>
+  KrbLocalUserMapping <%= @krb_local_user_mapping -%>
+  <%- end -%>
+
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_block.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+<% if @block and ! @block.empty? -%>
+
+  ## Block access statements
+<% if @block.include? 'scm' -%>
+  # Block access to SCM directories.
+  <DirectoryMatch .*\.(svn|git|bzr)/.*>
+  <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+    Require all denied
+  <%- else -%>
+    Deny From All
+  <%- end -%>
+  </DirectoryMatch>
+<% end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_charsets.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+<% if @add_default_charset -%>
+
+  AddDefaultCharset <%= @add_default_charset %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_custom_fragment.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+<% if @custom_fragment -%>
+
+  ## Custom fragment
+<%= @custom_fragment %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_directories.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,298 @@
+<% if @_directories and ! @_directories.empty? -%>
+
+  ## Directories, there should at least be a declaration for <%= @docroot %>
+  <%- [@_directories].flatten.compact.each do |directory| -%>
+    <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+      <%- if directory['allow'] and ! [ false, 'false', '' ].include?(directory['allow']) -%>
+        <%- scope.function_warning(["Apache::Vhost: Using allow is deprecated in your Apache version"]) -%>
+      <%- end -%>
+      <%- if directory['deny'] and ! [ false, 'false', '' ].include?(directory['deny']) -%>
+        <%- scope.function_warning(["Apache::Vhost: Using deny is deprecated in your Apache version"]) -%>
+      <%- end -%>
+      <%- if directory['order'] and ! [ false, 'false', '' ].include?(directory['order']) -%>
+        <%- scope.function_warning(["Apache::Vhost: Using order is deprecated in your Apache version"]) -%>
+      <%- end -%>
+      <%- if directory['satisfy'] and ! [ false, 'false', '' ].include?(directory['satisfy']) -%>
+        <%- scope.function_warning(["Apache::Vhost: Using satisfy is deprecated in your Apache version"]) -%>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['path'] and directory['path'] != '' -%>
+      <%- if directory['provider'] and directory['provider'].match('(directory|location|files)') -%>
+        <%- if /^(.*)match$/ =~ directory['provider'] -%>
+          <%- provider = $1.capitalize + 'Match' -%>
+        <%- else -%>
+          <%- provider = directory['provider'].capitalize -%>
+        <%- end -%>
+      <%- else -%>
+        <%- provider = 'Directory' -%>
+      <%- end -%>
+      <%- path = directory['path'] -%>
+
+  <<%= provider %> "<%= path %>">
+      <%- if directory['headers'] -%>
+        <%- Array(directory['headers']).each do |header| -%>
+    Header <%= header %>
+      <%- end -%>
+    <%- end -%>
+    <%- if ! directory['geoip_enable'].nil? -%>
+    GeoIPEnable <%= scope.function_bool2httpd([directory['geoip_enable']]) %>
+    <%- end -%>
+    <%- if directory['options'] -%>
+    Options <%= Array(directory['options']).join(' ') %>
+    <%- end -%>
+    <%- if provider == 'Directory' -%>
+      <%- if directory['index_options'] -%>
+    IndexOptions <%= Array(directory['index_options']).join(' ') %>
+      <%- end -%>
+      <%- if directory['index_order_default'] -%>
+    IndexOrderDefault <%= Array(directory['index_order_default']).join(' ') %>
+      <%- end -%>
+      <%- if directory['index_style_sheet'] -%>
+    IndexStyleSheet '<%= directory['index_style_sheet'] %>'
+      <%- end -%>
+      <%- if directory['allow_override'] -%>
+    AllowOverride <%= Array(directory['allow_override']).join(' ') %>
+      <%- elsif provider == 'Directory' -%>
+    AllowOverride None
+      <%- end -%>
+    <%- end -%>
+    <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+      <%- if directory['require'] and directory['require'] != '' -%>
+        <%- Array(directory['require']).each do |req| -%>
+    Require <%= req %>
+        <%- end -%>
+      <%- end -%>
+      <%- if directory['auth_require'] -%>
+    Require <%= directory['auth_require'] %>
+      <%- end -%>
+      <%- if !(directory['require'] and directory['require'] != '') && !(directory['auth_require']) -%>
+    Require all granted
+      <%- end -%>
+    <%- else -%>
+      <%- if directory['auth_require'] -%>
+    Require <%= directory['auth_require'] %>
+      <%- end -%>
+      <%- if directory['order'] and directory['order'] != '' -%>
+    Order <%= Array(directory['order']).join(',') %>
+      <%- else -%>
+    Order allow,deny
+      <%- end -%>
+      <%- if directory['deny'] and ! [ false, 'false', '' ].include?(directory['deny']) -%>
+        <%- if directory['deny'].kind_of?(Array) -%>
+          <%- Array(directory['deny']).each do |restrict| -%>
+    Deny <%=  restrict %>
+          <%- end -%>
+        <%- else -%>
+    Deny <%= directory['deny'] %>
+        <%- end -%>
+      <%- end -%>
+      <%- if directory['allow'] and ! [ false, 'false', '' ].include?(directory['allow']) -%>
+        <%- if directory['allow'].kind_of?(Array) -%>
+          <%- Array(directory['allow']).each do |access| -%>
+    Allow <%=  access %>
+        <%- end -%>
+      <%- else -%>
+    Allow <%= directory['allow'] %>
+      <%- end -%>
+      <%- elsif [ 'from all', 'from All' ].include?(directory['deny']) -%>
+      <%- elsif ! directory['deny'] and [ false, 'false', '' ].include?(directory['allow']) -%>
+    Deny from all
+      <%- else -%>
+    Allow from all
+      <%- end -%>
+      <%- if directory['satisfy'] and directory['satisfy'] != '' -%>
+    Satisfy <%= directory['satisfy'] %>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['addhandlers'] and ! directory['addhandlers'].empty? -%>
+      <%- [directory['addhandlers']].flatten.compact.each do |addhandler| -%>
+    AddHandler <%= addhandler['handler'] %> <%= Array(addhandler['extensions']).join(' ') %>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['sethandler'] and directory['sethandler'] != '' -%>
+    SetHandler <%= directory['sethandler'] %>
+    <%- end -%>
+    <%- if directory['passenger_enabled'] and directory['passenger_enabled'] != '' -%>
+    PassengerEnabled <%= directory['passenger_enabled'] %>
+    <%- end -%>
+    <%- if directory['php_flags'] and ! directory['php_flags'].empty? -%>
+      <%- directory['php_flags'].sort.each do |flag,value| -%>
+        <%- value = if value =~ /true|yes|on|1/i then 'on' else 'off' end -%>
+    php_flag <%= "#{flag} #{value}" %>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['php_values'] and ! directory['php_values'].empty? -%>
+      <%- directory['php_values'].sort.each do |key,value| -%>
+    php_value <%= "#{key} #{value}" %>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['php_admin_flags'] and ! directory['php_admin_flags'].empty? -%>
+      <%- directory['php_admin_flags'].sort.each do |flag,value| -%>
+        <%- value = if value =~ /true|yes|on|1/i then 'on' else 'off' end -%>
+    php_admin_flag <%= "#{flag} #{value}" %>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['php_admin_values'] and ! directory['php_admin_values'].empty? -%>
+      <%- directory['php_admin_values'].sort.each do |key,value| -%>
+    php_admin_value <%= "#{key} #{value}" %>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['directoryindex'] and directory['directoryindex'] != '' -%>
+    DirectoryIndex <%= directory['directoryindex'] %>
+    <%- end -%>
+    <%- if directory['error_documents'] and ! directory['error_documents'].empty? -%>
+      <%- [directory['error_documents']].flatten.compact.each do |error_document| -%>
+    ErrorDocument <%= error_document['error_code'] %> <%= error_document['document'] %>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['auth_type'] -%>
+    AuthType <%= directory['auth_type'] %>
+    <%- end -%>
+    <%- if directory['auth_name'] -%>
+    AuthName "<%= directory['auth_name'] %>"
+    <%- end -%>
+    <%- if directory['auth_digest_algorithm'] -%>
+    AuthDigestAlgorithm <%= directory['auth_digest_algorithm'] %>
+    <%- end -%>
+    <%- if directory['auth_digest_domain'] -%>
+    AuthDigestDomain <%= Array(directory['auth_digest_domain']).join(' ') %>
+    <%- end -%>
+    <%- if directory['auth_digest_nonce_lifetime'] -%>
+    AuthDigestNonceLifetime <%= directory['auth_digest_nonce_lifetime'] %>
+    <%- end -%>
+    <%- if directory['auth_digest_provider'] -%>
+    AuthDigestProvider <%= directory['auth_digest_provider'] %>
+    <%- end -%>
+    <%- if directory['auth_digest_qop'] -%>
+    AuthDigestQop <%= directory['auth_digest_qop'] %>
+    <%- end -%>
+    <%- if directory['auth_digest_shmem_size'] -%>
+    AuthDigestShmemSize <%= directory['auth_digest_shmem_size'] %>
+    <%- end -%>
+    <%- if directory['auth_basic_authoritative'] -%>
+    AuthBasicAuthoritative <%= directory['auth_basic_authoritative'] %>
+    <%- end -%>
+    <%- if directory['auth_basic_fake'] -%>
+    AuthBasicFake <%= directory['auth_basic_fake'] %>
+    <%- end -%>
+    <%- if directory['auth_basic_provider'] -%>
+    AuthBasicProvider <%= directory['auth_basic_provider'] %>
+    <%- end -%>
+    <%- if directory['auth_user_file'] -%>
+    AuthUserFile <%= directory['auth_user_file'] %>
+    <%- end -%>
+    <%- if directory['auth_group_file'] -%>
+    AuthGroupFile <%= directory['auth_group_file'] %>
+    <%- end -%>
+    <%- if directory['fallbackresource'] -%>
+    FallbackResource <%= directory['fallbackresource'] %>
+    <%- end -%>
+    <%- if directory['expires_active'] -%>
+    ExpiresActive <%= directory['expires_active'] %>
+    <%- end -%>
+    <%- if directory['expires_default'] -%>
+    ExpiresDefault <%= directory['expires_default'] %>
+    <%- end -%>
+    <%- if directory['expires_by_type'] -%>
+    <%- Array(directory['expires_by_type']).each do |rule| -%>
+    ExpiresByType <%= rule %>
+    <%- end -%>
+    <%- end -%>
+    <%- if directory['ext_filter_options'] -%>
+    ExtFilterOptions <%= directory['ext_filter_options'] %>
+    <%- end -%>
+    <%- if directory['force_type'] -%>
+    ForceType <%= directory['force_type'] %>
+    <%- end -%>
+    <%- if directory['ssl_options'] -%>
+    SSLOptions <%= Array(directory['ssl_options']).join(' ') %>
+    <%- end -%>
+    <%- if directory['suphp'] and @suphp_engine == 'on' -%>
+    suPHP_UserGroup <%= directory['suphp']['user'] %> <%= directory['suphp']['group'] %>
+    <%- end -%>
+    <%- if directory['fcgiwrapper'] -%>
+    FcgidWrapper <%= directory['fcgiwrapper']['command'] %> <%= directory['fcgiwrapper']['suffix'] %> <%= directory['fcgiwrapper']['virtual'] %>
+    <%- end -%>
+    <%- if directory['rewrites'] -%>
+    # Rewrite rules
+    RewriteEngine On
+      <%- directory['rewrites'].flatten.compact.each do |rewrite_details| -%>
+        <%- if rewrite_details['comment'] -%>
+    #<%= rewrite_details['comment'] %>
+        <%- end -%>
+        <%- if rewrite_details['rewrite_base'] -%>
+    RewriteBase <%= rewrite_details['rewrite_base'] %>
+        <%- end -%>
+        <%- if rewrite_details['rewrite_cond'] -%>
+          <%- Array(rewrite_details['rewrite_cond']).each do |commands| -%>
+            <%- Array(commands).each do |command| -%>
+    RewriteCond <%= command %>
+            <%- end -%>
+          <%- end -%>
+        <%- end -%>
+        <%- Array(rewrite_details['rewrite_rule']).each do |commands| -%>
+          <%- Array(commands).each do |command| -%>
+    RewriteRule <%= command %>
+          <%- end -%>
+        <%- end -%>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['setenv'] -%>
+      <%- Array(directory['setenv']).each do |setenv| -%>
+    SetEnv <%= setenv %>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['set_output_filter'] -%>
+    SetOutputFilter <%= directory['set_output_filter'] %>
+    <%- end -%>
+    <%- if @shibboleth_enabled -%>
+      <%- if directory['shib_require_session'] and ! directory['shib_require_session'].empty? -%>
+    ShibRequireSession <%= directory['shib_require_session'] %>
+      <%- end -%>
+      <%- if directory['shib_request_settings'] and ! directory['shib_request_settings'].empty? -%>
+        <%- directory['shib_request_settings'].each do |key,value| -%>
+    ShibRequestSetting <%= key %> <%= value %>
+        <%- end -%>
+      <%- end -%>
+      <%- if directory['shib_use_headers'] and ! directory['shib_use_headers'].empty? -%>
+    ShibUseHeaders <%= directory['shib_use_headers'] %>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['mellon_enable'] -%>
+    MellonEnable "<%= directory['mellon_enable'] %>"
+      <%- if directory['mellon_endpoint_path'] -%>
+    MellonEndpointPath "<%= directory['mellon_endpoint_path'] %>"
+      <%- end -%>
+      <%- if directory['mellon_sp_private_key_file'] -%>
+    MellonSPPrivateKeyFile "<%= directory['mellon_sp_private_key_file'] %>"
+      <%- end -%>
+      <%- if directory['mellon_sp_cert_file'] -%>
+    MellonSPCertFile "<%= directory['mellon_sp_cert_file'] %>"
+      <%- end -%>
+      <%- if directory['mellon_idp_metadata_file'] -%>
+    MellonIDPMetadataFile "<%= directory['mellon_idp_metadata_file'] %>"
+      <%- end -%>
+      <%- if directory['mellon_set_env_no_prefix'] -%>
+        <%- directory['mellon_set_env_no_prefix'].each do |key, value| -%>
+    MellonSetEnvNoPrefix "<%= key %>" "<%= value %>"
+        <%- end -%>
+      <%- end -%>
+      <%- if directory['mellon_user'] -%>
+    MellonUser "<%= directory['mellon_user'] %>"
+      <%- end -%>
+      <%- if directory['mellon_saml_response_dump'] -%>
+    MellonSamlResponseDump "<%= directory['mellon_saml_response_dump'] %>"
+      <%- end -%>
+      <%- if directory['mellon_cond'] -%>
+        <%- Array(directory['mellon_cond']).each do |cond| -%>
+    MellonCond <%= cond %>
+         <%- end -%>
+      <%- end -%>
+    <%- end -%>
+    <%- if directory['custom_fragment'] -%>
+    <%= directory['custom_fragment'] %>
+    <%- end -%>
+  </<%= provider %>>
+    <%- end -%>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_docroot.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+
+  ## Vhost docroot
+<% if @virtual_docroot -%>
+  VirtualDocumentRoot "<%= @virtual_docroot %>"
+<% elsif @docroot -%>
+  DocumentRoot "<%= @docroot %>"
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_error_document.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+<% if @error_documents and ! @error_documents.empty? -%>
+  <%- [@error_documents].flatten.compact.each do |error_document| -%>
+    <%- if error_document["error_code"] != '' and error_document["document"] != '' -%>
+  ErrorDocument <%= error_document["error_code"] %> <%= error_document["document"] %>
+    <%- end -%>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_fallbackresource.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+<% if @fallbackresource -%>
+
+  FallbackResource <%= @fallbackresource %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_fastcgi.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+<% if @fastcgi_server -%>
+
+  FastCgiExternalServer <%= @fastcgi_server %> -socket <%= @fastcgi_socket %>
+<% end -%>
+<% if @fastcgi_dir -%>
+
+  <Directory "<%= @fastcgi_dir %>">
+    Options +ExecCGI
+    AllowOverride All
+    SetHandler fastcgi-script
+  <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+    Require all granted
+  <%- else -%>
+    Order allow,deny
+    Allow From All
+  <%- end -%>
+    AuthBasicAuthoritative Off
+  </Directory>
+
+  AllowEncodedSlashes On
+  ServerSignature Off
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_file_footer.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+</VirtualHost>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_file_header.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+# ************************************
+# Vhost template in module puppetlabs-apache
+# Managed by Puppet
+# ************************************
+
+<VirtualHost <%= [@nvh_addr_port].flatten.compact.join(' ') %>>
+  ServerName <%= @servername %>
+<% if @serveradmin -%>
+  ServerAdmin <%= @serveradmin %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_filters.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+<% if @filters and ! @filters.empty? -%>
+
+  ## Filter module rules
+  ## as per http://httpd.apache.org/docs/2.2/mod/mod_filter.html
+  <%- Array(@filters).each do |filter| -%>
+    <%- if filter != '' -%>
+  <%= filter %>
+    <%- end -%>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_header.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+<% if @headers and ! @headers.empty? -%>
+
+  ## Header rules
+  ## as per http://httpd.apache.org/docs/2.2/mod/mod_headers.html#header
+  <%- Array(@headers).each do |header_statement| -%>
+    <%- if header_statement != '' -%>
+  Header <%= header_statement %>
+    <%- end -%>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_itk.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,29 @@
+<% if @itk and ! @itk.empty? -%>
+
+  ## ITK statement
+  <IfModule mpm_itk_module>
+     <%- if @itk["user"] and @itk["group"] -%>
+     AssignUserId <%= @itk["user"] %> <%= @itk["group"] %>
+     <%- end -%>
+     <%- if @itk["assignuseridexpr"] -%>
+     AssignUserIdExpr <%= @itk["assignuseridexpr"] %>
+     <%- end -%>
+     <%- if @itk["assigngroupidexpr"] -%>
+     AssignGroupIdExpr <%= @itk["assigngroupidexpr"] %>
+     <%- end -%>
+     <%- if @itk["maxclientvhost"] -%>
+     MaxClientsVHost <%= @itk["maxclientvhost"] %>
+     <%- end -%>
+     <%- if @itk["nice"] -%>
+     NiceValue <%= @itk["nice"] %>
+     <%- end -%>
+     <%- if @kernelversion >= '3.5.0' -%>
+       <%- if @itk["limituidrange"] -%>
+     LimitUIDRange <%= @itk["limituidrange"] %>
+       <%- end -%>
+       <%- if @itk["limitgidrange"] -%>
+     LimitGIDRange <%= @itk["limitgidrange"] %>
+       <%- end -%>
+     <%- end -%>
+  </IfModule>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_limits.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+
+  ## Limit Request Values
+<% if @limit_request_field_size -%>
+  LimitRequestFieldSize <%= @limit_request_field_size %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_logging.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+<% if @error_log or @log_level -%>
+
+  ## Logging
+<% end -%>
+<% if @error_log -%>
+  ErrorLog "<%= @error_log_destination %>"
+<% end -%>
+<% if @log_level -%>
+  LogLevel <%= @log_level %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_passenger.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+<% if @passenger_app_root -%>
+  PassengerAppRoot <%= @passenger_app_root %>
+<% end -%>
+<% if @passenger_app_env -%>
+  PassengerAppEnv <%= @passenger_app_env %>
+<% end -%>
+<% if @passenger_ruby -%>
+  PassengerRuby <%= @passenger_ruby %>
+<% end -%>
+<% if @passenger_min_instances -%>
+  PassengerMinInstances <%= @passenger_min_instances %>
+<% end -%>
+<% if @passenger_start_timeout -%>
+  PassengerStartTimeout <%= @passenger_start_timeout %>
+<% end -%>
+<% if @passenger_pre_start -%>
+  PassengerPreStart <%= @passenger_pre_start %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_passenger_base_uris.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+<% if @passenger_base_uris -%>
+
+  ## Enable passenger base uris
+<% Array(@passenger_base_uris).each do |uri| -%>
+  PassengerBaseURI <%= uri %>
+<% end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_php.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+<% if @php_values and not @php_values.empty? -%>
+  <%- @php_values.sort.each do |key,value| -%>
+  php_value <%= key %> <%= value %>
+  <%- end -%>
+<% end -%>
+<% if @php_flags and not @php_flags.empty? -%>
+  <%- @php_flags.sort.each do |key,flag| -%>
+    <%-# normalize flag -%>
+    <%- if flag =~ /true|yes|on|1/i then flag = 'on' else flag = 'off' end -%>
+  php_flag <%= key %> <%= flag %>
+  <%- end -%>
+<% end -%>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_php_admin.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+<% if @php_admin_values and not @php_admin_values.empty? -%>
+  <%- @php_admin_values.sort.each do |key,value| -%>
+  php_admin_value <%= key %> <%= value %>
+  <%- end -%>
+<% end -%>
+<% if @php_admin_flags and not @php_admin_flags.empty? -%>
+  <%- @php_admin_flags.sort.each do |key,flag| -%>
+    <%-# normalize flag -%>
+    <%- if flag =~ /true|yes|on|1/i then flag = 'on' else flag = 'off' end -%>
+  php_admin_flag <%= key %> <%= flag %>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_proxy.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,80 @@
+<% if @proxy_dest or @proxy_pass or @proxy_pass_match or @proxy_dest_match -%>
+
+  ## Proxy rules
+  ProxyRequests Off
+<%- end -%>
+<% if @proxy_preserve_host -%>
+  ProxyPreserveHost On
+<%- end -%>
+<% if @proxy_error_override -%>
+  ProxyErrorOverride On
+<%- end -%>
+<%- [@proxy_pass].flatten.compact.each do |proxy| -%>
+  ProxyPass <%= proxy['path'] %> <%= proxy['url'] -%>
+  <%- if proxy['params'] -%>
+    <%- proxy['params'].each_pair do |key, value| -%> <%= key %>=<%= value -%>
+    <%- end -%>
+  <%- end -%>
+  <%- if proxy['keywords'] %> <%= proxy['keywords'].join(' ') -%>
+  <%- end %>
+  <Location <%= proxy['path']%>>
+  <%- if not proxy['reverse_cookies'].nil? -%>
+    <%- Array(proxy['reverse_cookies']).each do |reverse_cookies| -%>
+    ProxyPassReverseCookiePath <%= reverse_cookies['path'] %> <%= reverse_cookies['url'] %>
+    <%- end -%>
+  <%- end -%>
+  <%- if proxy['reverse_urls'].nil? -%>
+    ProxyPassReverse <%= proxy['url'] %>
+  <%- else -%>
+    <%- Array(proxy['reverse_urls']).each do |reverse_url| -%>
+    ProxyPassReverse <%= reverse_url %>
+    <%- end -%>
+  <%- end -%>
+  <%- if proxy['setenv'] -%>
+    <%- Array(proxy['setenv']).each do |setenv_var| -%>
+    SetEnv <%= setenv_var %>
+    <%- end -%>
+  <%- end -%>
+  </Location>
+<% end -%>
+<% [@proxy_pass_match].flatten.compact.each do |proxy| %>
+  ProxyPassMatch <%= proxy['path'] %> <%= proxy['url'] -%>
+  <%- if proxy['params'] -%>
+    <%- proxy['params'].each_pair do |key, value| -%> <%= key %>=<%= value -%>
+    <%- end -%>
+  <%- end -%>
+  <%- if proxy['keywords'] %> <%= proxy['keywords'].join(' ') -%>
+  <%- end %>
+  <Location <%= proxy['path']%>>
+  <%- if proxy['reverse_urls'].nil? -%>
+    ProxyPassReverse <%= proxy['url'] %>
+  <%- else -%>
+    <%- Array(proxy['reverse_urls']).each do |reverse_url| -%>
+    ProxyPassReverse <%= reverse_url %>
+    <%- end -%>
+  <%- end -%>
+  <%- if proxy['setenv'] -%>
+    <%- Array(proxy['setenv']).each do |setenv_var| -%>
+    SetEnv <%= setenv_var %>
+    <%- end -%>
+  <%- end -%>
+  </Location>
+<% end -%>
+<% if @proxy_dest -%>
+<%- Array(@no_proxy_uris).each do |uri| -%>
+  ProxyPass        <%= uri %> !
+<% end -%>
+  ProxyPass          / <%= @proxy_dest %>/
+  <Location          />
+    ProxyPassReverse <%= @proxy_dest %>/
+  </Location>
+<% end -%>
+<% if @proxy_dest_match -%>
+<%- Array(@no_proxy_uris_match).each do |uri| -%>
+  ProxyPassMatch        <%= uri %> !
+<% end -%>
+  ProxyPassMatch          / <%= @proxy_dest_match %>/
+  <Location          />
+    ProxyPassReverse <%= @proxy_dest_reverse_match %>/
+  </Location>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_rack.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+<% if @rack_base_uris -%>
+
+  ## Enable rack
+<% Array(@rack_base_uris).each do |uri| -%>
+  RackBaseURI <%= uri %>
+<% end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_redirect.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+<% if @redirect_source and @redirect_dest -%>
+<% @redirect_dest_a   = Array(@redirect_dest) -%>
+<% @redirect_source_a = Array(@redirect_source) -%>
+<% @redirect_status_a = Array(@redirect_status) -%>
+
+  ## Redirect rules
+  <%- @redirect_source_a.each_with_index do |source, i| -%>
+<% @redirect_dest_a[i] ||= @redirect_dest_a[0] -%>
+<% @redirect_status_a[i] ||= @redirect_status_a[0] -%>
+  Redirect <%= "#{@redirect_status_a[i]} " %><%= source %> <%= @redirect_dest_a[i] %>
+  <%- end -%>
+<% end -%>
+<%- if @redirectmatch_status and @redirectmatch_regexp and @redirectmatch_dest -%>
+<% @redirectmatch_status_a = Array(@redirectmatch_status) -%>
+<% @redirectmatch_regexp_a = Array(@redirectmatch_regexp) -%>
+<% @redirectmatch_dest_a = Array(@redirectmatch_dest) -%>
+
+  ## RedirectMatch rules
+  <%- @redirectmatch_status_a.each_with_index do |status, i| -%>
+<% @redirectmatch_status_a[i] ||= @redirectmatch_status_a[0] -%>
+<% @redirectmatch_regexp_a[i] ||= @redirectmatch_regexp_a[0] -%>
+<% @redirectmatch_dest_a[i] ||= @redirectmatch_dest_a[0] -%>
+  RedirectMatch <%= "#{@redirectmatch_status_a[i]} " %> <%= @redirectmatch_regexp_a[i] %> <%= @redirectmatch_dest_a[i] %>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_requestheader.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+<% if @request_headers and ! @request_headers.empty? -%>
+
+  ## Request header rules
+  ## as per http://httpd.apache.org/docs/2.2/mod/mod_headers.html#requestheader
+  <%- Array(@request_headers).each do |request_statement| -%>
+    <%- if request_statement != '' -%>
+  RequestHeader <%= request_statement %>
+    <%- end -%>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_rewrite.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,50 @@
+<%- if @rewrites -%>
+  ## Rewrite rules
+  RewriteEngine On
+  <%- if @rewrite_base -%>
+  RewriteBase <%= @rewrite_base %>
+  <%- end -%>
+
+  <%- [@rewrites].flatten.compact.each do |rewrite_details| -%>
+    <%- if rewrite_details['comment'] -%>
+  #<%= rewrite_details['comment'] %>
+    <%- end -%>
+    <%- if rewrite_details['rewrite_base'] -%>
+  RewriteBase <%= rewrite_details['rewrite_base'] %>
+    <%- end -%>
+    <%- if rewrite_details['rewrite_cond'] -%>
+      <%- Array(rewrite_details['rewrite_cond']).each do |commands| -%>
+        <%- Array(commands).each do |command| -%>
+  RewriteCond <%= command %>
+        <%- end -%>
+      <%- end -%>
+    <%- end -%>
+    <%- if rewrite_details['rewrite_map'] -%>
+      <%- Array(rewrite_details['rewrite_map']).each do |commands| -%>
+        <%- Array(commands).each do |command| -%>
+  RewriteMap <%= command %>
+        <%- end -%>
+      <%- end -%>
+    <%- end -%>
+    <%- Array(rewrite_details['rewrite_rule']).each do |commands| -%>
+      <%- Array(commands).each do |command| -%>
+  RewriteRule <%= command %>
+      <%- end -%>
+
+    <%- end -%>
+  <%- end -%>
+<%- end -%>
+<%# reverse compatibility -%>
+<% if @rewrite_rule and !@rewrites -%>
+  ## Rewrite rules
+  RewriteEngine On
+  <%- if @rewrite_base -%>
+  RewriteBase <%= @rewrite_base %>
+  <%- end -%>
+  <%- if @rewrite_cond -%>
+    <%- Array(@rewrite_cond).each do |cond| -%>
+  RewriteCond <%= cond %>
+    <%- end -%>
+  <%- end -%>
+  RewriteRule <%= @rewrite_rule %>
+<%- end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_scriptalias.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+<%- if @scriptaliases.is_a?(Array) -%>
+<%-  aliases = @scriptaliases -%>
+<%- elsif @scriptaliases.is_a?(Hash) -%>
+<%-  aliases = [@scriptaliases] -%>
+<%- else -%>
+<%-  # Nothing to do with any other data type -%>
+<%-  aliases = [] -%>
+<%- end -%>
+<%- if @scriptalias or !aliases.empty? -%>
+  ## Script alias directives
+<%# Combine scriptalais and scriptaliases into a single data structure -%>
+<%# for backward compatibility and ease of implementation -%>
+<%- aliases << { 'alias' => '/cgi-bin', 'path' => @scriptalias } if @scriptalias -%>
+<%- aliases.flatten.compact! -%>
+<%- aliases.each do |salias| -%>
+  <%- if salias["path"] != '' -%>
+    <%- if salias["alias"] and salias["alias"] != '' -%>
+  ScriptAlias <%= salias['alias'] %> "<%= salias['path'] %>"
+    <%- elsif salias["aliasmatch"] and salias["aliasmatch"] != '' -%>
+  ScriptAliasMatch <%= salias['aliasmatch'] %> "<%= salias['path'] %>"
+    <%- end -%>
+  <%- end -%>
+<%- end -%>
+<%- end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_security.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+<% if @modsec_disable_vhost -%>
+  SecRuleEngine Off
+<% end -%>
+<% if @_modsec_disable_ids.is_a?(Hash) -%>
+<%   @_modsec_disable_ids.each do |location,rules| -%>
+  <LocationMatch <%= location %>>
+<%     Array(rules).each do |rule| -%>
+    SecRuleRemoveById <%= rule %>
+<%     end -%>
+  </LocationMatch>
+<%   end -%>
+<% end -%>
+<% ips = Array(@modsec_disable_ips).join(',') %>
+<% if ips != '' %>
+  SecRule REMOTE_ADDR "<%= ips %>" "nolog,allow,id:1234123455"
+  SecAction  "phase:2,pass,nolog,id:1234123456"
+<% end -%>
+<% if @modsec_body_limit -%>
+  SecRequestBodyLimit <%= @modsec_body_limit %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_serveralias.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+<% if @serveraliases and ! @serveraliases.empty? -%>
+
+  ## Server aliases
+  <%- Array(@serveraliases).each do |serveralias| -%>
+  ServerAlias <%= serveralias %>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_serversignature.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+  ServerSignature Off
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_setenv.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+<% if @setenv and ! @setenv.empty? -%>
+
+  ## SetEnv/SetEnvIf for environment variables
+  <%- Array(@setenv).each do |envvar| -%>
+  SetEnv <%= envvar %>
+  <%- end -%>
+<% end -%>
+<% if @setenvif and ! @setenvif.empty? -%>
+  <%- Array(@setenvif).each do |envifvar| -%>
+  SetEnvIf <%= envifvar %>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_ssl.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,52 @@
+<% if @ssl -%>
+
+  ## SSL directives
+  SSLEngine on
+  SSLCertificateFile      "<%= @ssl_cert %>"
+  SSLCertificateKeyFile   "<%= @ssl_key %>"
+  <%- if @ssl_chain -%>
+  SSLCertificateChainFile "<%= @ssl_chain %>"
+  <%- end -%>
+  <%- if @ssl_certs_dir && @ssl_certs_dir != '' -%>
+  SSLCACertificatePath    "<%= @ssl_certs_dir %>"
+  <%- end -%>
+  <%- if @ssl_ca -%>
+  SSLCACertificateFile    "<%= @ssl_ca %>"
+  <%- end -%>
+  <%- if @ssl_crl_path -%>
+  SSLCARevocationPath     "<%= @ssl_crl_path %>"
+  <%- end -%>
+  <%- if @ssl_crl -%>
+  SSLCARevocationFile     "<%= @ssl_crl %>"
+  <%- end -%>
+  <%- if @ssl_crl_check && scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
+  SSLCARevocationCheck    "<%= @ssl_crl_check %>"
+  <%- end -%>
+  <%- if @ssl_proxyengine -%>
+  SSLProxyEngine On
+  <%- end -%>
+  <%- if @ssl_protocol -%>
+  SSLProtocol             <%= [@ssl_protocol].flatten.compact.join(' ') %>
+  <%- end -%>
+  <%- if @ssl_cipher -%>
+  SSLCipherSuite          <%= @ssl_cipher %>
+  <%- end -%>
+  <%- if @ssl_honorcipherorder -%>
+  SSLHonorCipherOrder     <%= @ssl_honorcipherorder %>
+  <%- end -%>
+  <%- if @ssl_verify_client -%>
+  SSLVerifyClient         <%= @ssl_verify_client %>
+  <%- end -%>
+  <%- if @ssl_verify_depth -%>
+  SSLVerifyDepth          <%= @ssl_verify_depth %>
+  <%- end -%>
+  <%- if @ssl_proxy_machine_cert -%>
+  SSLProxyMachineCertificateFile "<%= @ssl_proxy_machine_cert %>"
+  <%- end -%>
+  <%- if @ssl_options -%>
+  SSLOptions <%= Array(@ssl_options).join(' ') %>
+  <%- end -%>
+  <%- if @ssl_openssl_conf_cmd -%>
+  SSLOpenSSLConfCmd       <%= @ssl_openssl_conf_cmd %>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_suexec.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+<% if @suexec_user_group -%>
+
+  SuexecUserGroup <%= @suexec_user_group %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_suphp.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+<% if @suphp_engine == 'on' -%>
+  <%- if @suphp_addhandler -%>
+  suPHP_AddHandler <%= @suphp_addhandler %>
+  <%- end -%>
+  <%- if @suphp_engine -%>
+  suPHP_Engine <%= @suphp_engine %>
+  <%- end -%>
+  <%- if @suphp_configpath -%>
+  suPHP_ConfigPath "<%= @suphp_configpath %>"
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/apache/templates/vhost/_wsgi.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+<% if @wsgi_application_group -%>
+  WSGIApplicationGroup <%= @wsgi_application_group %>
+<% end -%>
+<% if @wsgi_daemon_process and @wsgi_daemon_process_options -%>
+  WSGIDaemonProcess <%= @wsgi_daemon_process %> <%= @wsgi_daemon_process_options.collect { |k,v| "#{k}=#{v}"}.sort.join(' ') %>
+<% elsif @wsgi_daemon_process and !@wsgi_daemon_process_options -%>
+  WSGIDaemonProcess <%= @wsgi_daemon_process %>
+<% end -%>
+<% if @wsgi_import_script and @wsgi_import_script_options -%>
+  WSGIImportScript <%= @wsgi_import_script %> <%= @wsgi_import_script_options.collect { |k,v| "#{k}=#{v}"}.sort.join(' ') %>
+<% end -%>
+<% if @wsgi_process_group -%>
+  WSGIProcessGroup <%= @wsgi_process_group %>
+<% end -%>
+<% if @wsgi_script_aliases and ! @wsgi_script_aliases.empty? -%>
+  <%- @wsgi_script_aliases.keys.sort.each do |key| -%>
+    <%- if key != '' and @wsgi_script_aliases[key] != ''-%>
+  WSGIScriptAlias <%= key %> "<%= @wsgi_script_aliases[key] %>"
+    <%- end -%>
+  <%- end -%>
+<% end -%>
+<% if @wsgi_pass_authorization -%>
+  WSGIPassAuthorization <%= @wsgi_pass_authorization %>
+<% end -%>
+<% if @wsgi_chunked_request -%>
+  WSGIChunkedRequest <%= @wsgi_chunked_request %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/CHANGELOG.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,115 @@
+## 2015-08-21 - Release 0.8.1
+
+Use docker for acceptance tests
+
+## 2015-06-29 - Release 0.8.0
+
+allow to specify a user for the archive extraction and the archive download
+
+## 2015-06-26 - Release 0.7.5
+
+Fix strict_variables activation with rspec-puppet 2.2
+
+## 2015-05-28 - Release 0.7.4
+
+Add beaker_spec_helper to Gemfile
+
+## 2015-05-26 - Release 0.7.3
+
+Use random application order in nodeset
+
+## 2015-05-26 - Release 0.7.2
+
+add utopic & vivid nodesets
+
+## 2015-05-25 - Release 0.7.1
+
+Don't allow failure on Puppet 4
+
+## 2015-05-18 - Release 0.7.0
+
+Support tar.xz format
+
+## 2015-05-13 - Release 0.6.2
+
+Add puppet-lint-file_source_rights-check gem
+
+## 2015-05-12 - Release 0.6.1
+
+Don't pin beaker
+
+## 2015-05-12 - Release 0.6.0
+
+Support the purging of target directories
+
+## 2015-04-27 - Release 0.5.3
+
+Add nodeset ubuntu-12.04-x86_64-openstack
+
+## 2015-04-17 - Release 0.5.2
+
+Add beaker nodesets
+
+## 2015-04-03 - Release 0.5.1
+
+Confine rspec pinning to ruby 1.8
+Fix when not using digest_url
+
+## 2015-03-24 - Release 0.5.0
+
+Add a proxy_server parameter
+
+## 2015-03-24 - Release 0.4.1
+
+Add unit tests
+
+## 2015-03-06 - Release 0.4.0
+
+Add --strip-components support
+
+## 2015-01-07 - Release 0.3.6
+
+Fix unquoted strings in cases
+
+## 2015-01-05 - Release 0.3.5
+
+Simplify bundler cache in Travis CI
+Fix license name in metadata.json
+
+## 2014-11-18 Release 0.3.2
+
+Linting metadata
+
+## 2014-11-04 Release 0.3.1
+
+Fix missing comma
+
+## 2014-11-04 Release 0.3.0
+
+Add path to execs
+
+## 2014-11-04 Release 0.2.1
+
+Drop Puppet 2.7 support
+
+## 2014-10-20 Release 0.2.0
+
+Setup automatic Forge releases
+
+## 2014-09-24 Release 0.1.3
+
+Bug fix
+
+## 2014-09-23 Release 0.1.2
+
+Quote url to get the data from
+
+## 2014-09-05 Release 0.1.1
+
+Allow disabling of no-checksum notices in puppetmaster logs
+
+## 2014-07-02 Release 0.1.0
+
+Make curl silent, #21
+Add documentation
+Fix strict variables
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/Gemfile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,47 @@
+source ENV['GEM_SOURCE'] || "https://rubygems.org"
+
+group :development, :unit_tests do
+  gem 'rake',                                              :require => false
+  gem 'rspec', '< 3.2',                                    :require => false if RUBY_VERSION =~ /^1.8/
+  gem 'rspec-puppet',                                      :require => false
+  gem 'puppetlabs_spec_helper',                            :require => false
+  gem 'metadata-json-lint',                                :require => false
+  gem 'puppet-lint',                                       :require => false
+  gem 'puppet-lint-unquoted_string-check',                 :require => false
+  gem 'puppet-lint-empty_string-check',                    :require => false
+  gem 'puppet-lint-spaceship_operator_without_tag-check',  :require => false
+  gem 'puppet-lint-variable_contains_upcase',              :require => false
+  gem 'puppet-lint-absolute_classname-check',              :require => false
+  gem 'puppet-lint-undef_in_function-check',               :require => false
+  gem 'puppet-lint-leading_zero-check',                    :require => false
+  gem 'puppet-lint-trailing_comma-check',                  :require => false
+  gem 'puppet-lint-file_ensure-check',                     :require => false
+  gem 'puppet-lint-version_comparison-check',              :require => false
+  gem 'puppet-lint-fileserver-check',                      :require => false
+  gem 'puppet-lint-file_source_rights-check',              :require => false
+  gem 'puppet-lint-alias-check',                           :require => false
+  gem 'rspec-puppet-facts',                                :require => false
+  gem 'github_changelog_generator',                        :require => false, :git => 'https://github.com/raphink/github-changelog-generator.git', :branch => 'dev/all_patches' if RUBY_VERSION !~ /^1.8/
+  gem 'puppet-blacksmith',                                 :require => false if RUBY_VERSION !~ /^1.8/
+end
+
+group :system_tests do
+  gem 'beaker',              :require => false
+  gem 'beaker-rspec',        :require => false
+  gem 'beaker_spec_helper',  :require => false
+  gem 'serverspec',          :require => false
+end
+
+if facterversion = ENV['FACTER_GEM_VERSION']
+  gem 'facter', facterversion, :require => false
+else
+  gem 'facter', :require => false
+end
+
+if puppetversion = ENV['PUPPET_GEM_VERSION']
+  gem 'puppet', puppetversion, :require => false
+else
+  gem 'puppet', :require => false
+end
+
+# vim:ft=ruby
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/LICENSE	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/README.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,112 @@
+Archive Puppet Module
+====================
+
+[![Puppet Forge Version](http://img.shields.io/puppetforge/v/camptocamp/archive.svg)](https://forge.puppetlabs.com/camptocamp/archive)
+[![Puppet Forge Downloads](http://img.shields.io/puppetforge/dt/camptocamp/archive.svg)](https://forge.puppetlabs.com/camptocamp/archive)
+[![Build Status](https://img.shields.io/travis/camptocamp/puppet-archive/master.svg)](https://travis-ci.org/camptocamp/puppet-archive)
+[![Gemnasium](https://img.shields.io/gemnasium/camptocamp/puppet-archive.svg)](https://gemnasium.com/camptocamp/puppet-archive)
+[![By Camptocamp](https://img.shields.io/badge/by-camptocamp-fb7047.svg)](http://www.camptocamp.com)
+
+Overview
+--------
+
+Puppet Module to download and extract tar and zip archives based on [camptocamp/puppet-archive](https://github.com/camptocamp/puppet-archive).
+
+Supported archive types are:
+
+- `tar.gz`, `tgz`
+- `tar.bz2`, `tbz2`
+- `tar.xz`, `txz`
+- `zip`
+
+Features:
+
+- Ability to follow redirects
+- Supports checksum matching
+
+Usage
+-----
+
+Example:
+
+    archive { 'apache-tomcat-6.0.26':
+      ensure => present,
+      url    => 'http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.26/bin/apache-tomcat-6.0.26.tar.gz',
+      target => '/opt',
+    }
+
+You can have archive follow redirects by setting:
+
+```
+follow_redirects => true
+````
+
+The default archive format is ```tar.gz```. To use another supported format you must specify the extenstion:
+
+```
+extension => "zip"
+```
+
+By default archive will try and find a matching checksum file to verify the download. To disable this behavior set the ```checksum``` option to ```false```:
+
+```
+checksum => false
+```
+
+You can specify a ```digest_url```, ```digest_string``` and ```digest_type``` to verify archive integrity.
+
+For `.tar.gz` and `tar.bz2` archives, the extract step's `--strip-components=n` flag can be accessed. This can be used to [change the name of the extracted directory](http://unix.stackexchange.com/questions/11018/how-to-choose-directory-name-during-untarring).
+
+```
+strip_components => 1
+```
+
+```
+purge_target => false
+```
+
+By default the target directory is left intact, this option can be used to `rm -rf` the target directory prior to extraction.
+
+This full example will download the [packer](packer.io) tool to ```/usr/local/bin```:
+
+```
+archive { '0.5.1_linux_amd64':
+   ensure => present,
+   url => 'https://dl.bintray.com/mitchellh/packer/0.5.1_linux_amd64.zip',
+   target => '/usr/local/bin',
+   follow_redirects => true,
+   extension => 'zip',
+   checksum => false,
+   src_target => '/tmp'
+}
+```
+
+You can also specifiy a global user to be used for the whole download and extract operation. Note that the module doesn't handle the right of the specified user on the src_target directory.
+```
+
+archive { '0.5.1_linux_amd64':
+   ensure => present,
+   url => 'https://dl.bintray.com/mitchellh/packer/0.5.1_linux_amd64.zip',
+   target => '/usr/local/bin',
+   follow_redirects => true,
+   extension => 'zip',
+   checksum => false,
+   user       => 'camptocamp',
+   src_target => '/home/camptocamp'
+}
+```
+
+License
+-------
+
+Copyright (c) 2012 Camptocamp SA
+
+This script is licensed under the Apache License, Version 2.0.
+
+See http://www.apache.org/licenses/LICENSE-2.0.html for the full license text.
+
+
+Support
+-------
+
+Please log tickets and issues at our [project site](https://github.com/camptocamp/puppet-archive/issues).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/Rakefile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+require 'puppetlabs_spec_helper/rake_tasks'
+require 'puppet-lint/tasks/puppet-lint'
+
+Rake::Task[:lint].clear
+PuppetLint::RakeTask.new :lint do |config|
+  config.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp", "vendor/**/*.pp"]
+  config.disable_checks = ['80chars']
+  config.fail_on_warnings = true
+end
+
+PuppetSyntax.exclude_paths = ["spec/fixtures/**/*.pp", "vendor/**/*"]
+
+# Publishing tasks
+unless RUBY_VERSION =~ /^1\.8/
+  require 'puppet_blacksmith'
+  require 'puppet_blacksmith/rake_tasks'
+  require 'github_changelog_generator/task'
+  GitHubChangelogGenerator::RakeTask.new :changelog do |config|
+    m = Blacksmith::Modulefile.new
+    config.future_release = m.version
+    config.release_url = "https://forge.puppetlabs.com/#{m.author}/#{m.name}/%s"
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/checksums.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+{
+  "CHANGELOG.md": "a270fbc0eb53304a62eb8fb978a5d499",
+  "Gemfile": "fd6a01b07d9008b04417c33e02b4c931",
+  "LICENSE": "3b83ef96387f14655fc854ddc3c6bd57",
+  "README.md": "90d767333b620a8d037bf4282565028e",
+  "Rakefile": "2ca51e1c85d1459ea347efd2213afe73",
+  "manifests/download.pp": "116b320a8a1807f30930b836fbf766bf",
+  "manifests/extract.pp": "1d0a1db6fc107f28576e69199303b040",
+  "manifests/init.pp": "af167aa777f83c05e8c4b5adfde4fe5e",
+  "manifests/tar_gz.pp": "0cf28ed9d33375b7d0addf4190fe6b3c",
+  "manifests/zip.pp": "151b78d9eae3310881690e5c00123c7a",
+  "metadata.json": "6184f3b55064035518567f9193c52b47",
+  "spec/acceptance/nodesets/centos-5-x86_64-docker.yml": "916223adf56a5eae28fc4dbc8d3d5d09",
+  "spec/acceptance/nodesets/centos-6-x86_64-docker.yml": "79ee475e5497307c173a1aba59e1a206",
+  "spec/acceptance/nodesets/centos-6-x86_64-openstack.yml": "5509e2ebb2bee49bec7905141d91535b",
+  "spec/acceptance/nodesets/centos-6-x86_64-vagrant.yml": "f973bde1c355b0af3ba5c08e02311580",
+  "spec/acceptance/nodesets/centos-7-x86_64-docker.yml": "1d4713c4b0788eaaed0a5767ba0268d4",
+  "spec/acceptance/nodesets/centos-7-x86_64-openstack.yml": "554374fca1889b858d90a81226578b82",
+  "spec/acceptance/nodesets/centos-7-x86_64-vagrant.yml": "82b8ada243c70d9a2d8c9a3a4385416c",
+  "spec/acceptance/nodesets/debian-6-x86_64-docker.yml": "d6cb2154bf149715439b5bc64ef627bc",
+  "spec/acceptance/nodesets/debian-6-x86_64-openstack.yml": "83b0b0ecb7212b45179546ac6b6b83b7",
+  "spec/acceptance/nodesets/debian-6-x86_64-vagrant.yml": "d6356946a61858342d0be2b6b670eb55",
+  "spec/acceptance/nodesets/debian-7-x86_64-docker.yml": "2d68216014870420714f306fb3aaa601",
+  "spec/acceptance/nodesets/debian-7-x86_64-openstack.yml": "47f0b02b2d6ea2134574f045e9a315af",
+  "spec/acceptance/nodesets/debian-7-x86_64-vagrant.yml": "2dacc8c1cce7bc4fa8e3b13267df9ecd",
+  "spec/acceptance/nodesets/debian-8-x86_64-docker.yml": "d7fb01335b3273723b8b418faef51538",
+  "spec/acceptance/nodesets/debian-8-x86_64-openstack.yml": "075a6d6389a6b6cbe3b11f7a6e160059",
+  "spec/acceptance/nodesets/debian-8-x86_64-vagrant.yml": "9c33b450b4aa17476acc86d839d79dd2",
+  "spec/acceptance/nodesets/ubuntu-10.04-x86_64-docker.yml": "11480a9d30e9c4daee140dd420176723",
+  "spec/acceptance/nodesets/ubuntu-12.04-x86_64-docker.yml": "46cc4eceef33f04818ce74855630e05b",
+  "spec/acceptance/nodesets/ubuntu-12.04-x86_64-openstack.yml": "d1619ba4430c1a61cd9407533ac91de2",
+  "spec/acceptance/nodesets/ubuntu-14.04-x86_64-docker.yml": "5390c092066afa65780816b162dfb4aa",
+  "spec/acceptance/nodesets/ubuntu-14.04-x86_64-openstack.yml": "535b98aa7c5d0df88817675af991d2b6",
+  "spec/acceptance/nodesets/ubuntu-14.04-x86_64-vagrant.yml": "8622e2d9cae7a0923b8510561f1daf5a",
+  "spec/acceptance/nodesets/ubuntu-14.10-x86_64-docker.yml": "df4b8f4bd33f38e0053a806d739db819",
+  "spec/acceptance/nodesets/ubuntu-14.10-x86_64-openstack.yml": "cdfa94d70efdcbb4ae0e9caea474c4b1",
+  "spec/acceptance/nodesets/ubuntu-15.04-x86_64-docker.yml": "cefdea8d6ead29b5f492adb971019a81",
+  "spec/acceptance/nodesets/ubuntu-15.04-x86_64-openstack.yml": "60a9ce9983e881df4b83c2720dc014ed",
+  "spec/defines/archive_spec.rb": "d1925af41a0f6c20fbb0cad1db4173a2",
+  "spec/spec.opts": "a600ded995d948e393fbe2320ba8e51c",
+  "spec/spec_helper.rb": "706ea71a4048b1f9e6c650d71b5fb331"
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/manifests/download.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,190 @@
+# == Definition: archive::download
+#
+# Archive downloader with integrity verification.
+#
+# Parameters:
+#
+# - *$url:
+# - *$digest_url:
+# - *$digest_string: Default value undef
+# - *$digest_type: Default value "md5".
+# - *$timeout: Default value 120.
+# - *$src_target: Default value "/usr/src".
+# - *$allow_insecure: Default value false.
+# - *$follow_redirects: Default value false.
+# - *$verbose: Default value true.
+# - *$proxy_server: Default value undef.
+# - *$user: The user used to download the archive
+#
+# Example usage:
+#
+#  archive::download {"apache-tomcat-6.0.26.tar.gz":
+#    ensure => present,
+#    url    => "http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.26/bin/apache-tomcat-6.0.26.tar.gz",
+#  }
+#
+#  archive::download {"apache-tomcat-6.0.26.tar.gz":
+#    ensure        => present,
+#    digest_string => "f9eafa9bfd620324d1270ae8f09a8c89",
+#    url           => "http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.26/bin/apache-tomcat-6.0.26.tar.gz",
+#  }
+#
+define archive::download (
+  $url,
+  $ensure=present,
+  $checksum=true,
+  $digest_url=undef,
+  $digest_string=undef,
+  $digest_type='md5',
+  $timeout=120,
+  $src_target='/usr/src',
+  $allow_insecure=false,
+  $follow_redirects=false,
+  $verbose=true,
+  $path=$::path,
+  $proxy_server=undef,
+  $user=undef,
+) {
+
+  $insecure_arg = $allow_insecure ? {
+    true    => '-k',
+    default => '',
+  }
+
+  $redirect_arg = $follow_redirects ? {
+    true    => '-L',
+    default => '',
+  }
+
+  if !defined(Package['curl']) {
+    package{'curl':
+      ensure => present,
+    }
+  }
+
+  if $proxy_server {
+    $proxy_option = "--proxy ${proxy_server}"
+  } else {
+    $proxy_option = undef
+  }
+
+  case $checksum {
+    true : {
+      case $digest_type {
+        'md5','sha1','sha224','sha256','sha384','sha512' : {
+          $checksum_cmd = "${digest_type}sum -c ${name}.${digest_type}"
+        }
+        default: { fail 'Unimplemented digest type' }
+      }
+
+      if $digest_url and $digest_string {
+        fail 'digest_url and digest_string should not be used together !'
+      }
+
+      if $digest_string {
+        case $ensure {
+          'present': {
+            file {"${src_target}/${name}.${digest_type}":
+              ensure  => $ensure,
+              content => "${digest_string} *${name}",
+              owner   => $user,
+              notify  => Exec["download archive ${name} and check sum"],
+            }
+          }
+          'absent': {
+            file {"${src_target}/${name}.${digest_type}":
+              ensure => absent,
+              purge  => true,
+              owner  => $user,
+              force  => true,
+            }
+          }
+          default: {
+            fail('$ensure can only be present or absent.')
+          }
+        }
+      } else {
+        case $ensure {
+          'present': {
+
+            if !$digest_url {
+              $digest_src = "${url}.${digest_type}"
+            } else {
+              $digest_src = $digest_url
+            }
+
+
+            exec {"download digest of archive ${name}":
+              command => "curl ${proxy_option} -s -S ${insecure_arg} ${redirect_arg} -o ${src_target}/${name}.${digest_type} '${digest_src}'",
+              creates => "${src_target}/${name}.${digest_type}",
+              timeout => $timeout,
+              path    => $path,
+              notify  => Exec["download archive ${name} and check sum"],
+              user    => $user,
+              require => Package['curl'],
+            }
+
+          }
+          'absent': {
+            file{"${src_target}/${name}.${digest_type}":
+              ensure => absent,
+              purge  => true,
+              owner  => $user,
+              force  => true,
+            }
+          }
+          default: {
+            fail('$ensure can only be present or absent.')
+          }
+        }
+      }
+    }
+    false :  {
+      $checksum_cmd = undef # Fix for strict_variables
+      if $verbose {
+        notice 'No checksum for this archive'
+      }
+    }
+    default: { fail ( "Unknown checksum value: '${checksum}'" ) }
+  }
+
+  case $ensure {
+    'present': {
+      $_notify     = $checksum ? {
+        true    => Exec["rm-on-error-${name}"],
+        default => undef,
+      }
+      $refreshonly = $checksum ? {
+        true    => true,
+        default => undef,
+      }
+      exec {"download archive ${name} and check sum":
+        command     => "curl ${proxy_option} -s -S ${insecure_arg} ${redirect_arg} -o ${src_target}/${name} '${url}'",
+        creates     => "${src_target}/${name}",
+        logoutput   => true,
+        timeout     => $timeout,
+        path        => $path,
+        require     => Package['curl'],
+        notify      => $_notify,
+        user        => $user,
+        refreshonly => $refreshonly,
+      }
+
+      exec {"rm-on-error-${name}":
+        command     => "rm -f ${src_target}/${name} ${src_target}/${name}.${digest_type} && exit 1",
+        unless      => $checksum_cmd,
+        cwd         => $src_target,
+        path        => $path,
+        refreshonly => true,
+      }
+    }
+    'absent': {
+      file {"${src_target}/${name}":
+        ensure => absent,
+        purge  => true,
+        force  => true,
+      }
+    }
+    default: { fail ( "Unknown ensure value: '${ensure}'" ) }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/manifests/extract.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,93 @@
+# == Definition: archive::extract
+#
+# Archive extractor.
+#
+# Parameters:
+#
+# - *$target: Destination directory
+# - *$src_target: Default value "/usr/src".
+# - *$root_dir: Default value "".
+# - *$extension: Default value ".tar.gz".
+# - *$timeout: Default value 120.
+# - *$strip_components: Default value 0.
+# - *$user: The user used to do the extraction.
+#
+# Example usage:
+#
+#   archive::extract {"apache-tomcat-6.0.26":
+#     ensure => present,
+#     target => "/opt",
+#   }
+#
+# This means we want to extract the local archive
+# (maybe downloaded with archive::download)
+# '/usr/src/apache-tomcat-6.0.26.tar.gz' in '/src/apache-tomcat-6.0.26'
+#
+# Warning:
+#
+# The parameter *$root_dir* must be used if the root directory of the archive
+# is different from the name of the archive *$name*. To extract the name of
+# the root directory use the commands "tar tf archive.tar.gz" or
+# "unzip -l archive.zip"
+#
+define archive::extract (
+  $target,
+  $ensure=present,
+  $src_target='/usr/src',
+  $root_dir=undef,
+  $extension='tar.gz',
+  $timeout=120,
+  $path=$::path,
+  $strip_components=0,
+  $purge=false,
+  $user=undef,
+) {
+
+  if $root_dir {
+    $extract_dir = "${target}/${root_dir}"
+  } else {
+    $extract_dir = "${target}/${name}"
+  }
+
+  case $ensure {
+    'present': {
+
+      $extract_zip    = "unzip -o ${src_target}/${name}.${extension} -d ${target}"
+      $extract_targz  = "tar --no-same-owner --no-same-permissions --strip-components=${strip_components} -xzf ${src_target}/${name}.${extension} -C ${target}"
+      $extract_tarbz2 = "tar --no-same-owner --no-same-permissions --strip-components=${strip_components} -xjf ${src_target}/${name}.${extension} -C ${target}"
+      $extract_tarxz  = "tar --no-same-owner --no-same-permissions --strip-components=${strip_components} -xpf ${src_target}/${name}.${extension} -C ${target}"
+
+      $purge_command = $purge ? {
+        true    => "rm -rf ${target} && ",
+        default => '',
+      }
+
+      $command = $extension ? {
+        'zip'     => "${purge_command}mkdir -p ${target} && ${extract_zip}",
+        'tar.gz'  => "${purge_command}mkdir -p ${target} && ${extract_targz}",
+        'tgz'     => "${purge_command}mkdir -p ${target} && ${extract_targz}",
+        'tar.bz2' => "${purge_command}mkdir -p ${target} && ${extract_tarbz2}",
+        'tgz2'    => "${purge_command}mkdir -p ${target} && ${extract_tarbz2}",
+        'tar.xz'  => "${purge_command}mkdir -p ${target} && ${extract_tarxz}",
+        'txz'     => "${purge_command}mkdir -p ${target} && ${extract_tarxz}",
+        default   => fail ( "Unknown extension value '${extension}'" ),
+      }
+      exec {"${name} unpack":
+        command => $command,
+        creates => $extract_dir,
+        timeout => $timeout,
+        user    => $user,
+        path    => $path,
+      }
+    }
+    'absent': {
+      file {$extract_dir:
+        ensure  => absent,
+        recurse => true,
+        purge   => true,
+        force   => true,
+      }
+    }
+    default: { err ( "Unknown ensure value: '${ensure}'" ) }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,82 @@
+# == Definition: archive
+#
+# Download and extract an archive.
+#
+# Parameters:
+#
+# - *$url:
+# - *$target: Destination directory
+# - *$purge_target: Purge Destination prior to extraction. Default false
+# - *$checksum: Default value "true"
+# - *$digest_url: Default value undef
+# - *$digest_string: Default value undef
+# - *$digest_type: Default value "md5"
+# - *$src_target: Default value "/usr/src"
+# - *$root_dir: Default value undef
+# - *$extension: Default value ".tar.gz"
+# - *$timeout: Default value 120
+# - *$allow_insecure: Default value false
+# - *$follow_redirects: Default value false
+# - *$verbose: Default value true
+# - *$strip_components: Default value 0
+# - *$proxy_server: Default value undef
+# - *$user: User used to do the download and the extraction. The final directory will be used by him/her.
+#
+# Example usage:
+#
+#   archive {"apache-tomcat-6.0.26":
+#     ensure => present,
+#     url    => "http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.26/bin/apache-tomcat-6.0.26.tar.gz",
+#     target => "/opt",
+#   }
+#
+define archive (
+  $url,
+  $target,
+  $ensure=present,
+  $checksum=true,
+  $digest_url=undef,
+  $digest_string=undef,
+  $digest_type='md5',
+  $timeout=120,
+  $root_dir=undef,
+  $extension='tar.gz',
+  $src_target='/usr/src',
+  $allow_insecure=false,
+  $follow_redirects=false,
+  $verbose=true,
+  $strip_components=0,
+  $proxy_server=undef,
+  $purge_target=false,
+  $user=undef,
+) {
+
+  archive::download {"${name}.${extension}":
+    ensure           => $ensure,
+    url              => $url,
+    checksum         => $checksum,
+    digest_url       => $digest_url,
+    digest_string    => $digest_string,
+    digest_type      => $digest_type,
+    timeout          => $timeout,
+    src_target       => $src_target,
+    allow_insecure   => $allow_insecure,
+    follow_redirects => $follow_redirects,
+    verbose          => $verbose,
+    proxy_server     => $proxy_server,
+    user             => $user,
+  }
+
+  archive::extract {$name:
+    ensure           => $ensure,
+    target           => $target,
+    purge            => $purge_target,
+    src_target       => $src_target,
+    root_dir         => $root_dir,
+    extension        => $extension,
+    timeout          => $timeout,
+    strip_components => $strip_components,
+    require          => Archive::Download["${name}.${extension}"],
+    user             => $user,
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/manifests/tar_gz.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+# See README.md for details.
+define archive::tar_gz($source, $target, $path=$::path) {
+  exec {"${name} unpack":
+    command => "curl -s -S ${source} | tar -xzf - -C ${target} && touch ${name}",
+    creates => $name,
+    path    => $path,
+    require => Package[curl],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/manifests/zip.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+# See README.md for details.
+define archive::zip($source, $target, $path = $::path) {
+  exec {"${name} unpack":
+    command => "TMPFILE=\$(mktemp); curl -s -S -o \${TMPFILE}.zip ${source} && unzip \${TMPFILE}.zip -d ${target} && rm \$TMPFILE && rm \${TMPFILE}.zip && touch ${name}",
+    creates => $name,
+    path    => $::path,
+    require => Package['unzip'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/metadata.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+{
+  "name": "camptocamp-archive",
+  "version": "0.8.1",
+  "author": "Camptocamp",
+  "summary": "Camptocamp Archive Module",
+  "license": "Apache-2.0",
+  "source": "https://github.com/camptocamp/puppet-archive",
+  "project_page": "https://github.com/camptocamp/puppet-archive",
+  "issues_url": "https://github.com/camptocamp/puppet-archive/issues",
+  "dependencies": [
+  
+  ],
+  "description": "Archive Module for Puppet",
+  "operatingsystem_support": [
+    {
+      "operatingsystem": "Debian",
+      "operatingsystemrelease": [
+        "6",
+        "7",
+        "8"
+      ]
+    },
+    {
+      "operatingsystem": "RedHat",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    }
+  ]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-5-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  centos-5-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-5-x86_64
+    hypervisor : docker
+    image: centos:5
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'yum install -y crontabs tar wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-6-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  centos-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-6-x86_64
+    hypervisor : docker
+    image: centos:6
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'yum install -y crontabs tar wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-6-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  centos-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-6-x86_64
+    hypervisor : openstack
+    flavor: m1.small
+    image: centos-6-latest
+    user: root
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-6-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  centos-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-6-x86_64
+    hypervisor : vagrant
+    box : camptocamp/centos-6-x86_64
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-7-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  centos-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-7-x86_64
+    hypervisor : docker
+    image: centos:7
+    docker_preserve_image: true
+    docker_cmd: '["/usr/sbin/init"]'
+    docker_image_commands:
+      - 'yum install -y crontabs tar wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-7-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  centos-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-7-x86_64
+    hypervisor : openstack
+    flavor: m1.small
+    image: centos-7-latest
+    user: centos
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/centos-7-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  centos-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-7-x86_64
+    hypervisor : vagrant
+    box : camptocamp/centos-7-x86_64
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-6-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  debian-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-6-amd64
+    hypervisor : docker
+    image: debian:6
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-6-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  debian-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-6-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: debian-6-latest
+    user: debian
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-6-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  debian-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-6-amd64
+    hypervisor : vagrant
+    box : puppetlabs/debian-6.0.10-64-nocm
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-7-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  debian-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-7-amd64
+    hypervisor : docker
+    image: debian:7
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y cron wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-7-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  debian-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-7-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: debian-7-latest
+    user: debian
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-7-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  debian-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-7-amd64
+    hypervisor : vagrant
+    box : camptocamp/debian-7-amd64
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-8-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  debian-8-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-8-amd64
+    hypervisor : docker
+    image: debian:8
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y cron wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-8-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  debian-8-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-8-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: debian-8-latest
+    user: debian
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/debian-8-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  debian-8-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-8-amd64
+    hypervisor : vagrant
+    box : camptocamp/debian-8-amd64
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-10.04-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+HOSTS:
+  ubuntu-1004-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-10.04-amd64
+    hypervisor : docker
+    image: ubuntu:10.04
+    # This stops the image from being deleted on completion, speeding up the process.
+    docker_preserve_image: true
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-12.04-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-1204-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-12.04-amd64
+    hypervisor : docker
+    image: ubuntu:12.04
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-12.04-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  ubuntu-1204-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-12.04-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: ubuntu-1204-latest
+    user: ubuntu
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-14.04-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-1404-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-14.04-amd64
+    hypervisor : docker
+    image: ubuntu:14.04
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-14.04-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  ubuntu-1404-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-14.04-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: ubuntu-1404-latest
+    user: ubuntu
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-14.04-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  ubuntu-1404-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-14.04-amd64
+    hypervisor : vagrant
+    box : puppetlabs/ubuntu-14.04-64-nocm
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-14.10-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-1410-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-14.10-amd64
+    hypervisor : docker
+    image: ubuntu:14.10
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-14.10-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  ubuntu-1410-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-14.10-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: ubuntu-1410-latest
+    user: ubuntu
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-15.04-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-1504-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-15.04-amd64
+    hypervisor : docker
+    image: ubuntu:15.04
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/acceptance/nodesets/ubuntu-15.04-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  ubuntu-1504-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-15.04-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: ubuntu-1504-latest
+    user: ubuntu
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/defines/archive_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,72 @@
+require 'spec_helper'
+
+describe 'archive' do
+  let(:title) { 'apache-tomcat-6.0.26' }
+
+  on_supported_os.each do |os, facts|
+    context "on #{os}" do
+      let(:facts) do
+        facts
+      end
+
+      context 'without parameters' do
+        it { expect { is_expected.to compile.with_all_deps }.to raise_error(/Must pass/) }
+      end
+
+      context 'with url, without target' do
+        let(:params) do
+          {
+            :url => 'http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.26/bin/apache-tomcat-6.0.26.tar.gz',
+          }
+        end
+
+        it { expect { is_expected.to compile.with_all_deps }.to raise_error(/Must pass target/) }
+      end
+
+      context 'with target, without url' do
+        let(:params) do
+          {
+            :target => '/opt',
+          }
+        end
+        
+        it { expect { is_expected.to compile.with_all_deps }.to raise_error(/Must pass url/) }
+      end
+
+      context 'with url and target' do
+        let(:params) do
+          {
+            :url => 'http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.26/bin/apache-tomcat-6.0.26.tar.gz',
+            :target => '/opt',
+          }
+        end
+
+        it { is_expected.to compile.with_all_deps }
+      end
+
+      context 'with url and purge target' do
+        let(:params) do
+          {
+            :url => 'http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.26/bin/apache-tomcat-6.0.26.tar.gz',
+            :target => '/opt/tc6',
+            :purge_target => true,
+          }
+        end
+
+        it { is_expected.to compile.with_all_deps }
+      end
+
+      context 'with url, target and user' do
+        let(:params) do
+          {
+            :url    => 'http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.26/bin/apache-tomcat-6.0.26.tar.gz',
+            :target => '/opt',
+            :user   => 'root',
+          }
+        end
+
+        it { is_expected.to compile.with_all_deps }
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/spec.opts	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+--format
+s
+--colour
+--loadby
+mtime
+--backtrace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/archive/spec/spec_helper.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+require 'puppetlabs_spec_helper/module_spec_helper'
+require 'rspec-puppet-facts'
+include RspecPuppetFacts
+
+
+RSpec.configure do |c|
+  c.include PuppetlabsSpec::Files
+
+  c.before :each do
+    # Store any environment variables away to be restored later
+    @old_env = {}
+    ENV.each_key {|k| @old_env[k] = ENV[k]}
+
+    c.strict_variables = Gem::Version.new(Puppet.version) >= Gem::Version.new('3.5')
+    Puppet.features.stubs(:root?).returns(true)
+  end
+
+  c.after :each do
+    PuppetlabsSpec::Files.cleanup
+  end
+end
+
+require 'pathname'
+dir = Pathname.new(__FILE__).parent
+Puppet[:modulepath] = File.join(dir, 'fixtures', 'modules')
+
+# There's no real need to make this version dependent, but it helps find
+# regressions in Puppet
+#
+# 1. Workaround for issue #16277 where default settings aren't initialised from
+# a spec and so the libdir is never initialised (3.0.x)
+# 2. Workaround for 2.7.20 that now only loads types for the current node
+# environment (#13858) so Puppet[:modulepath] seems to get ignored
+# 3. Workaround for 3.5 where context hasn't been configured yet,
+# ticket https://tickets.puppetlabs.com/browse/MODULES-823
+#
+ver = Gem::Version.new(Puppet.version.split('-').first)
+if Gem::Requirement.new("~> 2.7.20") =~ ver || Gem::Requirement.new("~> 3.0.0") =~ ver || Gem::Requirement.new("~> 3.5") =~ ver || Gem::Requirement.new("~> 4.0")
+  puts "augeasproviders: setting Puppet[:libdir] to work around broken type autoloading"
+  # libdir is only a single dir, so it can only workaround loading of one external module
+  Puppet[:libdir] = "#{Puppet[:modulepath]}/augeasproviders_core/lib"
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/.fixtures.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+fixtures:
+  repositories:
+    "stdlib": "git://github.com/puppetlabs/puppetlabs-stdlib.git"
+  symlinks:
+    "augeas": "#{source_dir}"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/.gitignore	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+pkg/
+Gemfile.lock
+vendor/
+spec/fixtures/
+.vagrant/
+.bundle/
+coverage/
+log/
+.*.swp
+*~
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/.puppet-lint.rc	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+--fail-on-warnings
+--relative
+--no-80chars
+--no-documentation
+--no-class_inherits_from_params_class-check
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/.sync.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+---
+.travis.yml:
+  forge_password: "GYBg84VC7Mx8BhAJ/56VjPU8tctatVVafGjuM9rJVmvJpbHkTz+XORHkvdVxCCkAkiq0/NZjwWpbxkQGMz0MxnXT5V/H90+h6YRHnWIEEqlW+5dR76uKZ9mO65cqk+l8UA+GUr5ZWKTS0fEJzjNR8aFM56DaM1u+SWIfjBXfE0k="
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/.travis.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+---
+language: ruby
+sudo: false
+cache: bundler
+bundler_args: --without system_tests
+script: ["bundle exec rake validate", "bundle exec rake lint", "bundle exec rake spec SPEC_OPTS='--format documentation'", "bundle exec rake metadata"]
+matrix:
+  fast_finish: true
+  include:
+  - rvm: 1.8.7
+    env: PUPPET_GEM_VERSION="~> 3.0" FACTER_GEM_VERSION="~> 1.7.0"
+  - rvm: 1.9.3
+    env: PUPPET_GEM_VERSION="~> 3.0"
+  - rvm: 2.0.0
+    env: PUPPET_GEM_VERSION="~> 3.0"
+  - rvm: 2.0.0
+    env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes"
+  - rvm: 2.1.6
+    env: PUPPET_GEM_VERSION="~> 4.0"
+notifications:
+  email: false
+deploy:
+  provider: puppetforge
+  user: camptocamp
+  password:
+    secure: "GYBg84VC7Mx8BhAJ/56VjPU8tctatVVafGjuM9rJVmvJpbHkTz+XORHkvdVxCCkAkiq0/NZjwWpbxkQGMz0MxnXT5V/H90+h6YRHnWIEEqlW+5dR76uKZ9mO65cqk+l8UA+GUr5ZWKTS0fEJzjNR8aFM56DaM1u+SWIfjBXfE0k="
+  on:
+    tags: true
+    # all_branches is required to use tags
+    all_branches: true
+    # Only publish if our main Ruby target builds
+    rvm: 1.9.3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/CHANGELOG.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,128 @@
+## 2015-09-09 - Release 1.4.2
+
+Fix for puppet AIO packaging
+
+## 2015-08-31 - Release 1.4.1
+
+Fix use of is_pe fact for Puppet open-source
+
+## 2015-08-31 - Release 1.4.0
+
+Add support for Puppet Enterprise paths
+
+## 2015-08-21 - Release 1.3.1
+
+Use docker for acceptance tests
+
+## 2015-08-12 - Release 1.3.0
+
+Add puppet AIO packaging support
+Allow setting package name of ruby augeas bindings
+Add support for Amazon Linux AMI
+
+## 2015-06-26 - Release 1.2.13
+
+Fix strict_variables activation with rspec-puppet 2.2
+
+## 2015-06-24 - Release 1.2.12
+
+fix the ruby-augeas gem installation on SLES and openSUSE
+
+## 2015-05-28 - Release 1.2.11
+
+Add beaker_spec_helper to Gemfile
+
+## 2015-05-26 - Release 1.2.10
+
+Use random application order in nodeset
+
+## 2015-05-26 - Release 1.2.9
+
+add utopic & vivid nodesets
+
+## 2015-05-25 - Release 1.2.8
+
+Don't allow failure on Puppet 4
+
+## 2015-05-13 - Release 1.2.7
+
+Fix source_without_rights warning
+
+## 2015-05-13 - Release 1.2.6
+
+Add puppet-lint-file_source_rights-check gem
+
+## 2015-05-12 - Release 1.2.5
+
+Don't pin beaker
+
+## 2015-04-27 - Release 1.2.4
+
+Add nodeset ubuntu-12.04-x86_64-openstack
+
+## 2015-04-17 - Release 1.2.3
+
+- Add beaker nodesets
+
+## 2015-04-14 - Release 1.2.2
+
+- Fix lens test with content but no source
+
+## 2015-04-03 - Release 1.2.1
+
+- Confine rspec pinning to ruby 1.8
+
+## 2015-03-24 - Release 1.2.0
+
+- Add lens_content and test_content to augeas::lens
+- Fix augeas() function
+
+## 2015-03-24 - Release 1.1.7
+
+- Fix for SUSE
+
+## 2015-01-19 - Release 1.1.6
+
+- Add puppet-ling plugins
+
+##2015-01-12 - Release 1.1.5
+
+- Fix LICENSE file
+- Add some puppet-lint plugins to Gemfile
+
+##2015-01-07 - Release 1.1.4
+
+- Manage unit tests with rspec-puppet-facts
+
+##2014-12-09 - Release 1.1.0
+
+- Add future parser tests
+- Convert specs to rspec3 syntax
+- Fix metadata.json
+
+##2014-11-17 - Release 1.0.3
+
+- Lint metadata.json
+
+##2014-11-04 - Release 1.0.2
+
+- Fix path in unit tests
+- Drop Puppet 2.7 support
+
+##2014-10-28 - Release 1.0.1
+- Add path to exec in augeas::lens
+
+##2014-10-20 - Release 1.0.0
+- Linting
+- Setup automatic Forge releases
+
+##2014-10-06 - Release 0.3.2
+- Remove symlink in spec/ directory (Fix #40)
+
+##2014-09-23 - Release 0.3.1
+- Centralize metadata files
+
+##2014-07-02 - Release 0.3.0
+###Summary
+- Add purge parameter
+- Cleanup unscoped variables
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/Gemfile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,47 @@
+source ENV['GEM_SOURCE'] || "https://rubygems.org"
+
+group :development, :unit_tests do
+  gem 'rake',                                              :require => false
+  gem 'rspec', '< 3.2',                                    :require => false if RUBY_VERSION =~ /^1.8/
+  gem 'rspec-puppet',                                      :require => false
+  gem 'puppetlabs_spec_helper',                            :require => false
+  gem 'metadata-json-lint',                                :require => false
+  gem 'puppet-lint',                                       :require => false
+  gem 'puppet-lint-unquoted_string-check',                 :require => false
+  gem 'puppet-lint-empty_string-check',                    :require => false
+  gem 'puppet-lint-spaceship_operator_without_tag-check',  :require => false
+  gem 'puppet-lint-variable_contains_upcase',              :require => false
+  gem 'puppet-lint-absolute_classname-check',              :require => false
+  gem 'puppet-lint-undef_in_function-check',               :require => false
+  gem 'puppet-lint-leading_zero-check',                    :require => false
+  gem 'puppet-lint-trailing_comma-check',                  :require => false
+  gem 'puppet-lint-file_ensure-check',                     :require => false
+  gem 'puppet-lint-version_comparison-check',              :require => false
+  gem 'puppet-lint-fileserver-check',                      :require => false
+  gem 'puppet-lint-file_source_rights-check',              :require => false
+  gem 'puppet-lint-alias-check',                           :require => false
+  gem 'rspec-puppet-facts',                                :require => false
+  gem 'github_changelog_generator',                        :require => false, :git => 'https://github.com/raphink/github-changelog-generator.git', :branch => 'dev/all_patches' if RUBY_VERSION !~ /^1.8/
+  gem 'puppet-blacksmith',                                 :require => false if RUBY_VERSION !~ /^1.8/
+end
+
+group :system_tests do
+  gem 'beaker',              :require => false
+  gem 'beaker-rspec',        :require => false
+  gem 'beaker_spec_helper',  :require => false
+  gem 'serverspec',          :require => false
+end
+
+if facterversion = ENV['FACTER_GEM_VERSION']
+  gem 'facter', facterversion, :require => false
+else
+  gem 'facter', :require => false
+end
+
+if puppetversion = ENV['PUPPET_GEM_VERSION']
+  gem 'puppet', puppetversion, :require => false
+else
+  gem 'puppet', :require => false
+end
+
+# vim:ft=ruby
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/LICENSE	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!) The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/README.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,83 @@
+# Augeas Puppet module
+
+[![Puppet Forge Version](http://img.shields.io/puppetforge/v/camptocamp/augeas.svg)](https://forge.puppetlabs.com/camptocamp/augeas)
+[![Puppet Forge Downloads](http://img.shields.io/puppetforge/dt/camptocamp/augeas.svg)](https://forge.puppetlabs.com/camptocamp/augeas)
+[![Build Status](https://img.shields.io/travis/camptocamp/puppet-augeas/master.svg)](https://travis-ci.org/camptocamp/puppet-augeas)
+[![Gemnasium](https://img.shields.io/gemnasium/camptocamp/puppet-augeas.svg)](https://gemnasium.com/camptocamp/puppet-augeas)
+[![By Camptocamp](https://img.shields.io/badge/by-camptocamp-fb7047.svg)](http://www.camptocamp.com)
+
+**Install and configure Augeas.**
+
+This module is provided by [Camptocamp](http://www.camptocamp.com/)
+
+## Usage
+
+Simple usage:
+
+    include augeas
+
+### Classes
+
+The module provides an `augeas` class which installs and configures Augeas.
+
+
+* lets you force the augeas version by defining `$augeas_version`, otherwise puppet will
+   only ensure the packages are present;
+* lets you force the ruby library version by defining `$augeas_ruby_version`, otherwise puppet will
+   only ensure the libaugeas-ruby version will be installed according to internal critera;
+* provides an `augeas()` master-side function to manipulate strings using Augeas;
+
+Note: the `augeas` class realizes all `augeas` resources in order to ensure they are managed after the required Augeas packages.
+
+
+### Definitions
+
+#### `augeas::lens`
+
+The `augeas::lens` definition allows you to deploy an Augeas lens and any associated test files, running unit tests and not installing if they fail:
+
+Parameters:
+
+- *ensure*: present/absent
+- *lens_content*: the content of the lens
+- *lens_source*: deprecated, the source for the lens
+- *test_content*: optionally, the content of the test file
+- *test_source*: deprecated, the source for the test file.
+- *stock_since*: optionally, indicate in which version of Augeas
+  the lens became stock, so it will not be deployed above that version.
+
+Example usage:
+
+```puppet
+augeas::lens { 'networkmanager':
+  lens_content => file('networkmanager/lenses/networkmanager.aug'),
+  test_content => file('networkmanager/lenses/test_networkmanager.aug'),
+  stock_since  => '1.0.0',
+}
+```
+
+### Functions
+
+#### `augeas()`
+
+Modifies a string using Augeas.
+
+*Example:*
+
+    augeas("proc        /proc   proc    nodev,noexec,nosuid     0       0\n", 'Fstab.lns', ['rm ./1/opt[3]'])
+
+Would result in:
+
+    "proc        /proc   proc    nodev,noexec     0       0\n"
+
+
+- *Type*: rvalue
+
+## Contributing
+
+Please report bugs and feature request using [GitHub issue
+tracker](https://github.com/camptocamp/puppet-augeas/issues).
+
+For pull requests, it is very much appreciated to check your Puppet manifest
+with [puppet-lint](https://github.com/camptocamp/puppet-augeas/issues) to follow the recommended Puppet style guidelines from the
+[Puppet Labs style guide](http://docs.puppetlabs.com/guides/style_guide.html).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/Rakefile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+require 'puppetlabs_spec_helper/rake_tasks'
+require 'puppet-lint/tasks/puppet-lint'
+
+Rake::Task[:lint].clear
+PuppetLint::RakeTask.new :lint do |config|
+  config.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp", "vendor/**/*.pp"]
+  config.disable_checks = ['80chars']
+  config.fail_on_warnings = true
+end
+
+PuppetSyntax.exclude_paths = ["spec/fixtures/**/*.pp", "vendor/**/*"]
+
+# Publishing tasks
+unless RUBY_VERSION =~ /^1\.8/
+  require 'puppet_blacksmith'
+  require 'puppet_blacksmith/rake_tasks'
+  require 'github_changelog_generator/task'
+  GitHubChangelogGenerator::RakeTask.new :changelog do |config|
+    m = Blacksmith::Modulefile.new
+    config.future_release = m.version
+    config.release_url = "https://forge.puppetlabs.com/#{m.author}/#{m.name}/%s"
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/lib/puppet/parser/functions/augeas.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,68 @@
+#
+# augeas.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:augeas, :type => :rvalue, :doc => <<-EOS
+Modifies a string using Augeas.
+
+*Example:*
+
+    augeas("proc        /proc   proc    nodev,noexec,nosuid     0       0\n", 'Fstab.lns', ['rm ./1/opt[3]'])
+
+Would result in:
+
+    "proc        /proc   proc    nodev,noexec     0       0\n"
+    EOS
+  ) do |arguments|
+    unless Puppet.features.augeas?
+      raise Puppet::ParseError, ('augeas(): this function requires the augeas feature. See http://projects.puppetlabs.com/projects/puppet/wiki/Puppet_Augeas#Pre-requisites for how to activate it.')
+    end
+
+    # Check that 2 arguments have been given ...
+    raise(Puppet::ParseError, 'augeas(): Wrong number of arguments ' +
+      "given (#{arguments.size} for 3)") if arguments.size != 3
+
+    content = arguments[0]
+    lens = arguments[1]
+    changes = arguments[2]
+
+    # Check arguments
+    raise(Puppet::ParseError, 'augeas(): content must be a string') unless content.is_a?(String)
+    raise(Puppet::ParseError, 'augeas(): lens must be a string') unless lens.is_a?(String)
+    raise(Puppet::ParseError, 'augeas(): changes must be an array') unless changes.is_a?(Array)
+
+    require 'augeas'
+    aug = Augeas::open(nil, nil, Augeas::NO_MODL_AUTOLOAD)
+    augeas_version = aug.get('/augeas/version')
+    raise(Puppet::ParseError, 'augeas(): requires Augeas 1.0.0 or greater') unless Puppet::Util::Package.versioncmp(augeas_version, '1.0.0') >= 0
+    raise(Puppet::ParseError, 'augeas(): requires ruby-augeas 0.5.0 or greater') unless aug.methods.include?(:text_store)
+
+    result = nil
+    begin
+      aug.set('/input', content)
+      aug.text_store(lens, '/input', '/store')
+      unless aug.match("/augeas/text/store//error").empty?
+          error = aug.get("/augeas/text/store//error/message")
+          raise Puppet::ParseError, "augeas(): Failed to parse string with lens #{lens}: #{error}"
+      end
+
+      # Apply changes
+      aug.context = '/store'
+      changes.each do |c|
+        r = aug.srun(c)
+        raise Puppet::ParseError, "augeas(): Failed to apply change to tree" unless r and r[0] >= 0
+      end
+      unless aug.text_retrieve(lens, '/input', '/store', '/output')
+        error = aug.get("/augeas/text/store//error/message")
+        raise Puppet::ParseError, "augeas(): Failed to apply changes with lens #{lens}: #{error}"
+      end
+      result = aug.get("/output")
+    ensure
+      aug.close
+    end
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/manifests/files.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+# Class: augeas::files
+#
+# Sets up directories and files for Augeas
+#
+class augeas::files {
+  $lens_dir = $augeas::lens_dir
+
+  # ensure no file not managed by puppet ends up in there.
+  file { $lens_dir:
+    ensure       => directory,
+    purge        => $::augeas::purge,
+    force        => true,
+    recurse      => true,
+    recurselimit => 1,
+    mode         => '0644',
+    owner        => 'root',
+    group        => 'root',
+  }
+
+  file { "${lens_dir}/dist":
+    ensure => directory,
+    purge  => false,
+    mode   => '0644',
+    owner  => 'root',
+    group  => 'root',
+  }
+
+  file { "${lens_dir}/tests":
+    ensure => directory,
+    purge  => $::augeas::purge,
+    force  => true,
+    mode   => '0644',
+    owner  => 'root',
+    group  => 'root',
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+# Class: augeas
+#
+# Install and configure Augeas
+#
+# Parameters:
+#   ['version']      - the desired version of Augeas
+#   ['ruby_package'] - the desired package name of the Ruby bindings for Augeas
+#   ['ruby_version'] - the desired version of the Ruby bindings for Augeas
+#   ['lens_dir']     - the lens directory to use
+#   ['purge']        - whether to purge lens directories
+class augeas (
+  $version      = present,
+  $ruby_package = $::augeas::params::ruby_pkg,
+  $ruby_version = present,
+  $lens_dir     = $::augeas::params::lens_dir,
+  $purge        = true,
+) inherits augeas::params {
+
+  if versioncmp($::puppetversion, '4.0.0') >= 0 {
+    anchor { 'augeas::begin': } ->
+    class {'::augeas::files': } ->
+    anchor { 'augeas::end': }
+  } else {
+    anchor { 'augeas::begin': } ->
+    class {'::augeas::packages': } ->
+    class {'::augeas::files': } ->
+    anchor { 'augeas::end': }
+
+    # lint:ignore:spaceship_operator_without_tag
+    Package['ruby-augeas', $augeas::params::augeas_pkgs] -> Augeas <| |>
+    # lint:endignore
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/manifests/lens.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,107 @@
+# Definition: augeas::lens
+#
+# Deploy an Augeas lens (and its test file).
+# Check the lens (and run the unit tests) automatically and remove the files if
+# the checks fail.
+#
+# Parameters:
+#   ['ensure']       - present/absent
+#   ['lens_content'] - the content of the lens
+#   ['lens_source']  - the source for the lens
+#   ['test_content'] - optionally, the content of the test
+#   ['test_source']  - optionally, the source for the test file.
+#   ['stock_since']  - optionally, indicate in which version of Augeas
+#                      the lens became stock, so it will not be deployed
+#                      above that version.
+#
+# Example usage:
+#
+#   augeas::lens { 'networkmanager':
+#     lens_content => file('networkmanager/lenses/networkmanager.aug'),
+#     test_content => file('networkmanager/lenses/test_networkmanager.aug'),
+#     stock_since  => '1.0.0',
+#   }
+#
+define augeas::lens (
+  $ensure       = present,
+  $lens_content = undef,
+  $lens_source  = undef,
+  $test_content = undef,
+  $test_source  = undef,
+  $stock_since  = false,
+) {
+  if !defined(Class['augeas']) {
+    fail('You must declare the augeas class before using augeas::lens')
+  }
+
+  if $lens_source != undef {
+    if $lens_content != undef {
+      fail "You can't set both \$lens_source and \$lens_content"
+    } else {
+      warning 'Passing "lens_source" is deprecated; please use "lens_content"'
+    }
+  } else {
+    if $lens_content == undef {
+      fail "You must set either \$lens_source or \$lens_content"
+    }
+  }
+
+  if $test_source != undef {
+    if $test_content != undef {
+      fail "You can't set both \$test_source and \$test_content"
+    } else {
+      warning 'Passing "test_source" is deprecated; please use "test_content"'
+    }
+  }
+
+  File {
+    owner => 'root',
+    group => 'root',
+    mode => '0644',
+  }
+
+  if (!$stock_since or versioncmp($::augeasversion, $stock_since) < 0) {
+
+    validate_re(
+      $augeas::lens_dir,
+      '/.*',
+      "'${augeas::lens_dir}' is not a valid path for lens ${name}"
+    )
+
+    $lens_dest = "${augeas::lens_dir}/${name}.aug"
+    $test_dest = "${augeas::lens_dir}/tests/test_${name}.aug"
+
+    # lint:ignore:source_without_rights
+    file { $lens_dest:
+      ensure  => $ensure,
+      source  => $lens_source,
+      content => $lens_content,
+    }
+    # lint:endignore
+
+    exec { "Typecheck lens ${name}":
+      command     => "augparse -I ${augeas::lens_dir} ${lens_dest} || (rm -f ${lens_dest} && exit 1)",
+      path        => "/opt/puppetlabs/puppet/bin:${::path}",
+      refreshonly => true,
+      subscribe   => File[$lens_dest],
+    }
+
+    if $test_source or $test_content {
+      # lint:ignore:source_without_rights
+      file { $test_dest:
+        ensure  => $ensure,
+        source  => $test_source,
+        content => $test_content,
+        notify  => Exec["Test lens ${name}"],
+      }
+      # lint:endignore
+
+      exec { "Test lens ${name}":
+        command     => "augparse -I ${augeas::lens_dir} ${test_dest} || (rm -f ${lens_dest} && rm -f ${test_dest} && exit 1)",
+        path        => "/opt/puppetlabs/puppet/bin:${::path}",
+        refreshonly => true,
+        subscribe   => File[$lens_dest, $test_dest],
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/manifests/packages.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+# Class: augeas::packages
+#
+# Sets up packages for Augeas
+#
+class augeas::packages {
+  package { $::augeas::params::augeas_pkgs:
+    ensure => $::augeas::version,
+  }
+
+  package { 'ruby-augeas':
+    ensure => $::augeas::ruby_version,
+    name   => $::augeas::ruby_package,
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/manifests/params.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,49 @@
+# Class: augeas::params
+#
+# Default parameters for the Augeas module
+#
+class augeas::params {
+
+  if versioncmp($::puppetversion, '4.0.0') >= 0 {
+    $lens_dir = '/opt/puppetlabs/puppet/share/augeas/lenses'
+  } elsif (defined('$is_pe') and str2bool("${::is_pe}")) { # lint:ignore:only_variable_string
+    # puppet enterpise has a different lens location
+    $lens_dir = '/opt/puppet/share/augeas/lenses'
+  } else {
+    $lens_dir = '/usr/share/augeas/lenses'
+  }
+
+  case $::osfamily {
+    'RedHat': {
+      $ruby_pkg = $::operatingsystem ? {
+        # Amazon Linux AMI (2014.09 and 2015.03) uses ruby 2.0
+        'Amazon' => 'ruby20-augeas',
+        default => 'ruby-augeas'
+      }
+      $augeas_pkgs = ['augeas', 'augeas-libs']
+    }
+
+    'Suse': {
+      # RPM Sources: https://build.opensuse.org/project/show/systemsmanagement:puppet
+      if versioncmp($::rubyversion, '2.1.2') >= 0 {
+        # SLES 12 / openSUSE
+        $ruby_pkg = 'ruby2.1-rubygem-ruby-augeas'
+      } else {
+        # SLES 11 SP3
+        $ruby_pkg = 'ruby1.8-rubygem-ruby-augeas'
+      }
+      $augeas_pkgs = ['augeas', 'augeas-lenses', 'libaugeas0' ]
+    }
+
+    'Debian': {
+      if versioncmp($::rubyversion, '1.9.1') >= 0 {
+        $ruby_pkg = 'libaugeas-ruby1.9.1'
+      } else {
+        $ruby_pkg = 'libaugeas-ruby1.8'
+      }
+      $augeas_pkgs = ['augeas-lenses', 'libaugeas0', 'augeas-tools']
+    }
+
+    default:  { fail("Unsupported OS family: ${::osfamily}") }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/metadata.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,69 @@
+{
+  "name": "camptocamp-augeas",
+  "version": "1.4.2",
+  "author": "camptocamp",
+  "summary": "Camptocamp Augeas module",
+  "license": "Apache-2.0",
+  "source": "https://github.com/camptocamp/puppet-augeas",
+  "project_page": "https://github.com/camptocamp/puppet-augeas",
+  "issues_url": "https://github.com/camptocamp/puppet-augeas/issues",
+  "description": "Augeas Module for Puppet",
+  "dependencies": [
+    {
+      "name": "puppetlabs/stdlib",
+      "version_requirement": ">= 3.2.0 <5.0.0"
+    }
+  ],
+  "requirements": [
+    {
+      "name": "pe",
+      "version_requirement": "3.x"
+    },
+    {
+      "name": "puppet",
+      "version_requirement": "3.x"
+    }
+  ],
+  "operatingsystem_support": [
+    {
+      "operatingsystem": "Debian",
+      "operatingsystemrelease": [
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Ubuntu",
+      "operatingsystemrelease": [
+        "10.04",
+        "12.04",
+        "14.04"
+      ]
+    },
+    {
+      "operatingsystem": "RedHat",
+      "operatingsystemrelease": [
+        "5",
+        "6"
+      ]
+    },
+    {
+      "operatingsystem": "Amazon",
+      "operatingsystemrelease": [
+        "2014.09",
+        "2015.03"
+      ]
+    }
+  ],
+  "puppet_version": [
+    "2.7",
+    "3.0",
+    "3.1",
+    "3.2",
+    "3.3",
+    "3.4",
+    "3.5",
+    "3.6",
+    "3.7"
+  ]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/.rspec	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+--format
+s
+--colour
+--loadby
+mtime
+--backtrace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-5-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  centos-5-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-5-x86_64
+    hypervisor : docker
+    image: centos:5
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'yum install -y crontabs tar wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-6-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  centos-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-6-x86_64
+    hypervisor : docker
+    image: centos:6
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'yum install -y crontabs tar wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-6-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  centos-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-6-x86_64
+    hypervisor : openstack
+    flavor: m1.small
+    image: centos-6-latest
+    user: root
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-6-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  centos-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-6-x86_64
+    hypervisor : vagrant
+    box : camptocamp/centos-6-x86_64
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-7-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  centos-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-7-x86_64
+    hypervisor : docker
+    image: centos:7
+    docker_preserve_image: true
+    docker_cmd: '["/usr/sbin/init"]'
+    docker_image_commands:
+      - 'yum install -y crontabs tar wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-7-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  centos-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-7-x86_64
+    hypervisor : openstack
+    flavor: m1.small
+    image: centos-7-latest
+    user: centos
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/centos-7-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  centos-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: el-7-x86_64
+    hypervisor : vagrant
+    box : camptocamp/centos-7-x86_64
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-6-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  debian-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-6-amd64
+    hypervisor : docker
+    image: debian:6
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-6-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  debian-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-6-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: debian-6-latest
+    user: debian
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-6-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  debian-6-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-6-amd64
+    hypervisor : vagrant
+    box : puppetlabs/debian-6.0.10-64-nocm
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-7-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  debian-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-7-amd64
+    hypervisor : docker
+    image: debian:7
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y cron wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-7-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  debian-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-7-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: debian-7-latest
+    user: debian
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-7-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  debian-7-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-7-amd64
+    hypervisor : vagrant
+    box : camptocamp/debian-7-amd64
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-8-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  debian-8-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-8-amd64
+    hypervisor : docker
+    image: debian:8
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y cron wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-8-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  debian-8-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-8-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: debian-8-latest
+    user: debian
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/debian-8-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  debian-8-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: debian-8-amd64
+    hypervisor : vagrant
+    box : camptocamp/debian-8-amd64
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-10.04-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+HOSTS:
+  ubuntu-1004-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-10.04-amd64
+    hypervisor : docker
+    image: ubuntu:10.04
+    # This stops the image from being deleted on completion, speeding up the process.
+    docker_preserve_image: true
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-12.04-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-1204-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-12.04-amd64
+    hypervisor : docker
+    image: ubuntu:12.04
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-12.04-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  ubuntu-1204-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-12.04-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: ubuntu-1204-latest
+    user: ubuntu
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-14.04-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-1404-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-14.04-amd64
+    hypervisor : docker
+    image: ubuntu:14.04
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-14.04-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  ubuntu-1404-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-14.04-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: ubuntu-1404-latest
+    user: ubuntu
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-14.04-x86_64-vagrant.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  ubuntu-1404-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-14.04-amd64
+    hypervisor : vagrant
+    box : puppetlabs/ubuntu-14.04-64-nocm
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-14.10-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-1410-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-14.10-amd64
+    hypervisor : docker
+    image: ubuntu:14.10
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-14.10-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  ubuntu-1410-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-14.10-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: ubuntu-1410-latest
+    user: ubuntu
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-15.04-x86_64-docker.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-1504-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-15.04-amd64
+    hypervisor : docker
+    image: ubuntu:15.04
+    docker_preserve_image: true
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -y wget'
+CONFIG:
+  type: foss
+  log_level: debug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/acceptance/nodesets/ubuntu-15.04-x86_64-openstack.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+HOSTS:
+  ubuntu-1504-x64:
+    default_apply_opts:
+      order: random
+      strict_variables:
+    platform: ubuntu-15.04-amd64
+    hypervisor : openstack
+    flavor: m1.small
+    image: ubuntu-1504-latest
+    user: ubuntu
+CONFIG:
+  type: foss
+  log_level: debug
+  openstack_network: default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/classes/augeas_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,210 @@
+require 'spec_helper'
+
+describe 'augeas' do
+
+  context 'when on an unsupported Operating System' do
+    let (:facts) do
+      {
+        :osfamily      => 'MS-DOS',
+        :puppetversion => Puppet.version,
+      }
+    end
+
+    it 'should fail' do
+      expect { is_expected.to compile }.to raise_error(/Unsupported OS family/)
+    end
+  end
+
+  lens_dir = Puppet.version < '4.0.0' ? '/usr/share/augeas/lenses' : '/opt/puppetlabs/puppet/share/augeas/lenses'
+
+  on_supported_os.each do |os, facts|
+    context "on #{os}" do
+      let(:facts) do
+        facts.merge({
+          :puppetversion => Puppet.version,
+        })
+      end
+
+      context 'without params' do
+        if Puppet.version < '4.0.0'
+          case facts[:osfamily]
+          when 'Debian'
+            it { is_expected.to contain_package('libaugeas0').with(
+              :ensure => 'present'
+            ) }
+            it { is_expected.to contain_package('augeas-tools').with(
+              :ensure => 'present'
+            ) }
+            it { is_expected.to contain_package('augeas-lenses').with(
+              :ensure => 'present'
+            ) }
+            case facts[:lsbdistcodename]
+            when 'squeeze', 'lucid', 'precise'
+              let(:facts) do
+                super().merge({
+                  :rubyversion => '1.8.7',
+                })
+              end
+              it { is_expected.to contain_package('ruby-augeas').with(
+                :ensure => 'present',
+                :name   => 'libaugeas-ruby1.8'
+              ) }
+            else
+              let(:facts) do
+                super().merge({
+                  :rubyversion => '1.9.3',
+                })
+              end
+              it { is_expected.to contain_package('ruby-augeas').with(
+                :ensure => 'present',
+                :name   => 'libaugeas-ruby1.9.1'
+              ) }
+            end
+          when 'RedHat'
+            it { is_expected.to contain_package('augeas').with(
+              :ensure => 'present'
+            ) }
+            it { is_expected.to contain_package('augeas-libs').with(
+              :ensure => 'present'
+            ) }
+            it { is_expected.to contain_package('ruby-augeas').with(
+              :ensure => 'present',
+              :name   => 'ruby-augeas'
+            ) }
+          end
+        end
+        it { is_expected.to contain_file(lens_dir).with(
+          :ensure       => 'directory',
+          :purge        => 'true',
+          :force        => 'true',
+          :recurse      => 'true',
+          :recurselimit => 1
+        ) }
+        it { is_expected.to contain_file("#{lens_dir}/dist").with(
+          :ensure       => 'directory',
+          :purge        => 'false'
+        ) }
+        it { is_expected.to contain_file("#{lens_dir}/tests").with(
+          :ensure       => 'directory',
+          :purge        => 'true',
+          :force        => 'true'
+        ).without(:recurse) }
+      end
+
+      context 'when versions are specified' do
+        let (:params) do
+          {
+            :version      => '1.2.3',
+            :ruby_version => '3.2.1',
+          }
+        end
+
+        if Puppet.version < '4.0.0'
+          case facts[:osfamily]
+          when 'Debian'
+            it { is_expected.to contain_package('libaugeas0').with(
+              :ensure => '1.2.3'
+            ) }
+            it { is_expected.to contain_package('augeas-tools').with(
+              :ensure => '1.2.3'
+            ) }
+            it { is_expected.to contain_package('augeas-lenses').with(
+              :ensure => '1.2.3'
+            ) }
+            case facts[:lsbdistcodename]
+            when 'squeeze', 'lucid', 'precise'
+              let(:facts) do
+                super().merge({
+                  :rubyversion => '1.8.7',
+                })
+              end
+              it { is_expected.to contain_package('ruby-augeas').with(
+                :ensure => '3.2.1',
+                :name   => 'libaugeas-ruby1.8'
+              ) }
+            else
+              let(:facts) do
+                super().merge({
+                  :rubyversion => '1.9.3',
+                })
+              end
+              it { is_expected.to contain_package('ruby-augeas').with(
+                :ensure => '3.2.1',
+                :name   => 'libaugeas-ruby1.9.1'
+              ) }
+            end
+          when 'RedHat'
+            it { is_expected.to contain_package('augeas').with(
+              :ensure => '1.2.3'
+            ) }
+            it { is_expected.to contain_package('augeas-libs').with(
+              :ensure => '1.2.3'
+            ) }
+            it { is_expected.to contain_package('ruby-augeas').with(
+              :ensure => '3.2.1',
+              :name   => 'ruby-augeas'
+            ) }
+          end
+        end
+      end
+
+      context 'with a non standard lens_dir' do
+        let (:params) do
+          {
+            :lens_dir => '/opt/augeas/lenses',
+          }
+        end
+
+        it { is_expected.to contain_file('/opt/augeas/lenses').with(
+          :ensure       => 'directory',
+          :purge        => 'true',
+          :force        => 'true',
+          :recurse      => 'true',
+          :recurselimit => 1
+        ) }
+        it { is_expected.to contain_file('/opt/augeas/lenses/dist').with(
+          :ensure       => 'directory',
+          :purge        => 'false'
+        ) }
+        it { is_expected.to contain_file('/opt/augeas/lenses/tests').with(
+          :ensure       => 'directory',
+          :purge        => 'true',
+          :force        => 'true'
+        ).without(:recurse) }
+      end
+
+      context 'with Puppet Enterprise' do
+        let (:facts) do
+          facts.merge({
+            :puppetversion => Puppet.version,
+            :is_pe         => true,
+          })
+        end
+
+        if Puppet::Util::Package.versioncmp(Puppet.version, '4.0.0') >= 0
+            # the enterprise lens dir is the same in 4
+            pe_lens_dir = lens_dir
+        else
+            pe_lens_dir = '/opt/puppet/share/augeas/lenses'
+        end
+
+        it { is_expected.to contain_file(pe_lens_dir).with(
+          :ensure       => 'directory',
+          :force        => 'true',
+          :recurse      => 'true',
+          :recurselimit => 1
+        ) }
+        it { is_expected.to contain_file("#{pe_lens_dir}/dist").with(
+          :ensure  => 'directory',
+          :purge   => 'false'
+        ) }
+        it { is_expected.to contain_file("#{pe_lens_dir}/tests").with(
+          :ensure => 'directory',
+          :force  => 'true',
+          :purge  => 'true'
+        ).without(:recurse) }
+      end
+
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/defines/augeas_lens_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,111 @@
+require 'spec_helper'
+
+describe 'augeas::lens' do
+  let (:title) { 'foo' }
+
+  context 'when not declaring augeas class first' do
+    let (:params) do
+      {
+        :lens_source => '/tmp/foo.aug',
+      }
+    end
+
+    it 'should error' do
+      expect { is_expected.to compile }.to raise_error(/You must declare the augeas class/)
+    end
+  end
+
+  lens_dir = Puppet.version < '4.0.0' ? '/usr/share/augeas/lenses' : '/opt/puppetlabs/puppet/share/augeas/lenses'
+
+  context 'when declaring augeas class first' do
+
+    on_supported_os.each do |os, facts|
+      context "on #{os}" do
+        let(:facts) do
+          facts.merge({
+            :augeasversion => :undef,
+            :puppetversion => Puppet.version,
+          })
+        end
+
+        context 'With standard augeas version' do
+
+          let(:pre_condition) do
+            "class { '::augeas': }"
+          end
+
+          context 'when no lens_source is passed' do
+            it 'should error' do
+              expect { is_expected.to compile }.to raise_error(/You must set either \$lens_source or \$lens_content/)
+            end
+          end
+
+          context 'when lens_source is passed' do
+            let (:params) do
+              {
+                :lens_source => '/tmp/foo.aug',
+              }
+            end
+
+            it { is_expected.to contain_file("#{lens_dir}/foo.aug") }
+            it { is_expected.to contain_exec('Typecheck lens foo') }
+            it { is_expected.not_to contain_file("#{lens_dir}/tests/test_foo.aug") }
+            it { is_expected.not_to contain_exec('Test lens foo') }
+          end
+
+          context 'when lens_source and test_source are passed' do
+            let (:params) do
+              {
+                :lens_source => '/tmp/foo.aug',
+                :test_source => '/tmp/test_foo.aug',
+              }
+            end
+
+            it { is_expected.to contain_file("#{lens_dir}/foo.aug") }
+            it { is_expected.to contain_file("#{lens_dir}/tests/test_foo.aug") }
+            it { is_expected.to contain_exec('Typecheck lens foo') }
+            it { is_expected.to contain_exec('Test lens foo') }
+          end
+        end
+
+        context 'when stock_since is passed and augeas is older' do
+          let (:params) do
+            {
+              :lens_source => '/tmp/foo.aug',
+              :stock_since => '1.2.3',
+            }
+          end
+
+          let(:pre_condition) do
+            "class { '::augeas': version => '1.0.0' }"
+          end
+
+          it { is_expected.to contain_file("#{lens_dir}/foo.aug") }
+          it { is_expected.to contain_exec('Typecheck lens foo') }
+        end
+
+        context 'when stock_since is passed and augeas is newer' do
+          let (:params) do
+            {
+              :lens_source => '/tmp/foo.aug',
+              :stock_since => '1.2.3',
+            }
+          end
+
+          let(:pre_condition) do
+            "class { '::augeas': version => '1.3.0' }"
+          end
+
+          it do
+            pending "undefined method `negative_failure_message'"
+            is_expected.not_to contain_file("#{lens_dir}/foo.aug")
+          end
+          it do
+            pending "undefined method `negative_failure_message'"
+            is_expected.not_to contain_exec('Typecheck lens foo')
+          end
+        end
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/spec.opts	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+--format
+s
+--colour
+--loadby
+mtime
+--backtrace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/spec_helper.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+require 'puppetlabs_spec_helper/module_spec_helper'
+require 'rspec-puppet-facts'
+include RspecPuppetFacts
+
+
+RSpec.configure do |c|
+  c.include PuppetlabsSpec::Files
+
+  c.before :each do
+    # Store any environment variables away to be restored later
+    @old_env = {}
+    ENV.each_key {|k| @old_env[k] = ENV[k]}
+
+    c.strict_variables = Gem::Version.new(Puppet.version) >= Gem::Version.new('3.5')
+    Puppet.features.stubs(:root?).returns(true)
+  end
+
+  c.after :each do
+    PuppetlabsSpec::Files.cleanup
+  end
+end
+
+require 'pathname'
+dir = Pathname.new(__FILE__).parent
+Puppet[:modulepath] = File.join(dir, 'fixtures', 'modules')
+
+# There's no real need to make this version dependent, but it helps find
+# regressions in Puppet
+#
+# 1. Workaround for issue #16277 where default settings aren't initialised from
+# a spec and so the libdir is never initialised (3.0.x)
+# 2. Workaround for 2.7.20 that now only loads types for the current node
+# environment (#13858) so Puppet[:modulepath] seems to get ignored
+# 3. Workaround for 3.5 where context hasn't been configured yet,
+# ticket https://tickets.puppetlabs.com/browse/MODULES-823
+#
+ver = Gem::Version.new(Puppet.version.split('-').first)
+if Gem::Requirement.new("~> 2.7.20") =~ ver || Gem::Requirement.new("~> 3.0.0") =~ ver || Gem::Requirement.new("~> 3.5") =~ ver || Gem::Requirement.new("~> 4.0")
+  puts "augeasproviders: setting Puppet[:libdir] to work around broken type autoloading"
+  # libdir is only a single dir, so it can only workaround loading of one external module
+  Puppet[:libdir] = "#{Puppet[:modulepath]}/augeasproviders_core/lib"
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/augeas/spec/unit/puppet/parser/functions/augeas_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,83 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe 'the augeas function' do
+  let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+  it "should fail if the augeas feature is not present" do
+    Puppet.features.expects(:augeas?).returns(false)
+    expect { scope.function_augeas([]) }.to raise_error(Puppet::ParseError, /requires the augeas feature/)
+  end
+
+  it "should exist" do
+    expect(Puppet::Parser::Functions.function("augeas")).to eq("function_augeas")
+  end
+
+  context "when passing wrong arguments" do
+    before :each do
+      Puppet.features.stubs(:augeas?).returns(true)
+    end
+
+    it "should raise a ParseError if there are no arguments" do
+      expect { scope.function_augeas([]) }.to raise_error(Puppet::ParseError, /Wrong number of arguments/)
+    end
+
+    it "should raise a ParseError if content is not a string" do
+      expect { scope.function_augeas([['foo'], 'Fstab.lns', []]) }.to raise_error(Puppet::ParseError, /content must be a string/)
+    end
+
+    it "should raise a ParseError if lens is not a string" do
+      expect { scope.function_augeas(['foo', ['Fstab.lns'], []]) }.to raise_error(Puppet::ParseError, /lens must be a string/)
+    end
+
+    it "should raise a ParseError if changes is not an array" do
+      expect { scope.function_augeas(['foo', 'Fstab.lns', 'changes']) }.to raise_error(Puppet::ParseError, /changes must be an array/)
+    end
+  end
+
+  if Puppet.features.augeas?
+    context "when passing invalid input" do
+      it "should fail to parse input with lens" do
+        expect { scope.function_augeas(['foo', 'Fstab.lns', []]) }.to raise_error(Puppet::ParseError, /Failed to parse string with lens Fstab.lns:/)
+      end
+    end
+
+    context "when passing illegal changes" do
+      it "should fail to apply illegal change" do
+        expect { scope.function_augeas(["\n", 'Fstab.lns', ['foo bar']]) }.to raise_error(Puppet::ParseError, /Failed to apply change to tree/)
+      end
+    end
+
+    context "when generating an invalid tree" do
+      it "should fail to apply changes with wrong tree" do
+        expect { scope.function_augeas(["\n", 'Fstab.lns', ['set ./1/opt 3']]) }.to raise_error(Puppet::ParseError, /Failed to apply changes with lens Fstab.lns:/)
+      end
+    end
+
+    context "when applying valid changes" do
+      it "should remove the 3rd option" do
+        result = scope.function_augeas(["proc        /proc   proc    nodev,noexec,nosuid     0       0\n", 'Fstab.lns', ['rm ./1/opt[3]']])
+        expect(result.class).to eq(String)
+        #result.should == "proc       /proc   proc    nodev,noexec     0       0\n"
+      end
+
+      it "should set a 4th option" do
+        result = scope.function_augeas(["proc        /proc   proc    nodev,noexec,nosuid     0       0\n", 'Fstab.lns', ['ins opt after ./1/opt[last()]', 'set ./1/opt[last()] nofoo']])
+        expect(result.class).to eq(String)
+        #result.should == "proc       /proc   proc    nodev,noexec,nosuid,nofoo     0       0\n"
+      end
+    end
+
+    context "when using old libs" do
+      it "should not work with Augeas prior to 1.0.0" do
+        Augeas.any_instance.expects(:get).with('/augeas/version').returns('0.10.0')
+        expect { scope.function_augeas(["\n", 'Fstab.lns', []]) }.to raise_error(Puppet::ParseError, /requires Augeas 1\.0\.0/)
+      end
+
+      it "should not work with ruby-augeas prior to 0.5.0" do
+        Augeas.any_instance.expects(:methods).returns([])
+        expect { scope.function_augeas(["\n", 'Fstab.lns', []]) }.to raise_error(Puppet::ParseError, /requires ruby-augeas 0\.5\.0/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/CHANGELOG.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,293 @@
+##Supported Release 1.2.5
+###Summary
+
+Small release for support of newer PE versions. This increments the version of PE in the metadata.json file.
+
+##2015-07-21 - Supported Release 1.2.4
+###Summary
+
+This release includes some ruby path and lint fixes.
+
+####Bugfixes
+- Use correct ruby path with PE and AIO
+- Lint fixes
+- Use correct ruby path on FreeBSD
+- Test fixes
+
+##2015-06-02 - Supported Release 2.0.1 [YANKED]
+###Summary
+
+This is a bugfix release. 
+
+####Bugfixes
+- Fixes dependency graphing with concurrent modification of the same file.
+- Fixes handling fragment target.
+- Fixes the defaulted force behavior to handle empty concats correctly.
+
+##2015-06-02 - Supported Release 1.2.3
+###Summary
+
+This release includes a README fix to document correct behavior of fragment target parameter.
+
+####Bugfixes
+- README Fix to correctly document how a fragment $target param should work.
+
+##2015-05-12 - Supported Release 2.0.0 [YANKED]
+###Summary
+
+This is a major release. Includes re-implementation of concat to use native Type and Providers, resulting in significantly improved performance and testability. Also includes a bugfix to alpha ordering of fragments.
+
+####Features
+- Re-implementation of concat to use native Type and Providers.
+
+####Bugfixes
+- Fixes a bug in alpha ordering of fragments.
+
+##2015-05-12 - Supported Release 1.2.2
+###Summary
+
+This release includes a bugfix.
+
+####Bugfixes
+- Fixes a bug introduced by MODULES-1700, in handling default retrieval of fragment backup parameter.
+
+##2015-04-14 - Supported Release 1.2.1
+###Summary
+
+This release includes bugfixes, test improvements, and a rewritten README.
+
+####Bugfixes
+
+- Verifies existence of $is_pe before using it.
+- Adds validation for $order param to not allow restricted characters.
+- Sets the group id on Fragments for versions of Facter that contain the $gid fact.
+- Sets the script group to 0 if the script is owned by root.
+- Explicitly sets script and concat directories to the same owner and group.
+- Re-adds support for fragment backup, so that static compiler can work with filebucket (MODULES-1700).
+
+##2015-02-17 - Supported Release 1.2.0
+###Summary
+
+This release includes a number of bugfixes and adds support for running a validation command when using puppet >= 3.5.0.
+
+####Features
+- Support running a validation command for Puppet >= 3.5.0
+
+####Bugfixes
+- Reset poisoned defaults from Exec
+- Use concatfragments.rb on AIX since it doesn't support print0
+- Make sure ruby is in the path for PE (MODULES-1456)
+- Fix missing method for check_is_owned_by for windows (MODULES-1764)
+- Fix sort by numeric
+
+##2014-10-28 - Supported Release 1.1.2
+###Summary
+
+This release includes bugfixes and test improvements. The module was tested against SLES10 and SLES12 and found to work against those platforms with no module improvements. Metadata was updated to include those as supported platforms.
+
+####Bugfixes
+- newline didn't work for Windows and Solaris. This has been fixed.
+- Install certs on Windows for acceptance tests
+- Update tests to work with strict variables (no module updates were required)
+- Update tests to work on Windows
+- Fix typo in CHANGELOG.md
+
+##2014-09-10 - Supported Release 1.1.1
+###Summary
+
+This is a bugfix release, and the first supported release of the 1.1.x series.
+
+####Bugfixes
+- Make the `$order` parameter default to a string and be validated as an integer
+  or a string
+- Use the ruby script on Solaris to not break Sol10 support
+- Add quotes to the ruby script location for Windows
+- Fix typos in README.md
+- Make regex in concat::setup case-insensitive to make it work on Windows
+- Make sure concat fragments are always replaced
+- Fix validation to allow `$backup` to be a boolean
+- Remove dependency on stdlib 4.x
+- Fix for lack of idempotency with `ensure => 'absent'`
+- Fix tests and spec_helper
+- Synchronized files for more consistency across modules via modulesync
+
+##2014-05-14 - Release 1.1.0
+###Summary
+
+This release is primarily a bugfix release since 1.1.0-rc1.
+
+####Features
+- Improved testing, with tests moved to beaker
+
+####Bugfixes
+- No longer attempts to set fragment owner and mode on Windows
+- Fix numeric sorting
+- Fix incorrect quoting
+- Fix newlines
+
+##2014-01-03 - Release 1.1.0-rc1
+###Summary
+
+This release of concat was 90% written by Joshua Hoblitt, and the module team
+would like to thank him for the huge amount of work he put into this release.
+
+This module deprecates a bunch of old parameters and usage patterns, modernizes
+much of the manifest code, simplifies a whole bunch of logic and makes
+improvements to almost all parts of the module.
+
+The other major feature is windows support, courtesy of luisfdez, with an
+alternative version of the concat bash script in ruby.  We've attempted to
+ensure that there are no backwards incompatible changes, all users of 1.0.0
+should be able to use 1.1.0 without any failures, but you may find deprecation
+warnings and we'll be aggressively moving for a 2.0 to remove those too.
+
+For further information on deprecations, please read:
+https://github.com/puppetlabs/puppetlabs-concat/blob/master/README.md#api-deprecations
+
+####Removed
+- Puppet 0.24 support.
+- Filebucket backup of all file resources except the target concatenated file.
+- Default owner/user/group values.
+- Purging of long unused /usr/local/bin/concatfragments.sh
+
+###Features
+- Windows support via a ruby version of the concat bash script.
+- Huge amount of acceptance testing work added.
+- Documentation (README) completely rewritten.
+- New parameters in concat:
+ - `ensure`: Controls if the file should be present/absent at all.
+ - Remove requirement to include concat::setup in manifests.
+ - Made `gnu` parameter deprecated.
+ - Added parameter validation.
+
+###Bugfixes
+ - Ensure concat::setup runs before concat::fragment in all cases.
+ - Pluginsync references updated for modern Puppet.
+ - Fix incorrect group parameter.
+ - Use $owner instead of $id to avoid confusion with $::id
+ - Compatibility fixes for Puppet 2.7/ruby 1.8.7
+ - Use LC_ALL=C instead of LANG=C
+ - Always exec the concatfragments script as root when running as root.
+ - Syntax and other cleanup changes.
+
+##2014-06-25 - Supported Release 1.0.4
+###Summary
+
+This release has test fixes.
+
+####Features
+- Added test support for OSX.
+
+####Bugfixes
+
+####Known bugs
+
+* Not supported on Windows.
+
+##2014-06-04 - Release 1.0.3
+###Summary
+
+This release adds compatibility for PE3.3 and fixes tests.
+
+####Features
+- Added test support for Ubuntu Trusty.
+
+####Bugfixes
+
+####Known bugs
+
+*Not supported on Windows.
+
+##2014-03-04 - Supported Release 1.0.2
+###Summary
+
+This is a supported release. No functional changes were made from 1.0.1.
+
+####Features
+- Huge amount of tests backported from 1.1.
+- Documentation rewrite.
+
+####Bugfixes
+
+####Known Bugs
+
+* Not supported on Windows.
+
+
+##2014-02-12 - 1.0.1
+###Summary
+
+Minor bugfixes for sorting of fragments and ordering of resources.
+
+####Bugfixes
+- LANG => C replaced with LC_ALL => C to reduce spurious recreation of
+fragments.
+- Corrected pluginsync documentation.
+- Ensure concat::setup always runs before fragments.
+
+
+##2013-08-09 - 1.0.0
+###Summary
+
+Many new features and bugfixes in this release, and if you're a heavy concat
+user you should test carefully before upgrading.  The features should all be
+backwards compatible but only light testing has been done from our side before
+this release.
+
+####Features
+- New parameters in concat:
+ - `replace`: specify if concat should replace existing files.
+ - `ensure_newline`: controls if fragments should contain a newline at the end.
+- Improved README documentation.
+- Add rspec:system tests (rake spec:system to test concat)
+
+####Bugfixes
+- Gracefully handle \n in a fragment resource name.
+- Adding more helpful message for 'pluginsync = true'
+- Allow passing `source` and `content` directly to file resource, rather than
+defining resource defaults.
+- Added -r flag to read so that filenames with \ will be read correctly.
+- sort always uses LANG=C.
+- Allow WARNMSG to contain/start with '#'.
+- Replace while-read pattern with for-do in order to support Solaris.
+
+####CHANGELOG:
+- 2010/02/19 - initial release
+- 2010/03/12 - add support for 0.24.8 and newer
+             - make the location of sort configurable
+             - add the ability to add shell comment based warnings to
+               top of files
+             - add the ablity to create empty files
+- 2010/04/05 - fix parsing of WARN and change code style to match rest
+               of the code
+             - Better and safer boolean handling for warn and force
+             - Don't use hard coded paths in the shell script, set PATH
+               top of the script
+             - Use file{} to copy the result and make all fragments owned
+               by root.  This means we can chnage the ownership/group of the
+               resulting file at any time.
+             - You can specify ensure => "/some/other/file" in concat::fragment
+               to include the contents of a symlink into the final file.
+- 2010/04/16 - Add more cleaning of the fragment name - removing / from the $name
+- 2010/05/22 - Improve documentation and show the use of ensure =>
+- 2010/07/14 - Add support for setting the filebucket behavior of files
+- 2010/10/04 - Make the warning message configurable
+- 2010/12/03 - Add flags to make concat work better on Solaris - thanks Jonathan Boyett
+- 2011/02/03 - Make the shell script more portable and add a config option for root group
+- 2011/06/21 - Make base dir root readable only for security
+- 2011/06/23 - Set base directory using a fact instead of hardcoding it
+- 2011/06/23 - Support operating as non privileged user
+- 2011/06/23 - Support dash instead of bash or sh
+- 2011/07/11 - Better solaris support
+- 2011/12/05 - Use fully qualified variables
+- 2011/12/13 - Improve Nexenta support
+- 2012/04/11 - Do not use any GNU specific extensions in the shell script
+- 2012/03/24 - Comply to community style guides
+- 2012/05/23 - Better errors when basedir isnt set
+- 2012/05/31 - Add spec tests
+- 2012/07/11 - Include concat::setup in concat improving UX
+- 2012/08/14 - Puppet Lint improvements
+- 2012/08/30 - The target path can be different from the $name
+- 2012/08/30 - More Puppet Lint cleanup
+- 2012/09/04 - RELEASE 0.2.0
+- 2012/12/12 - Added (file) $replace parameter to concat
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/CONTRIBUTING.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,220 @@
+Checklist (and a short version for the impatient)
+=================================================
+
+  * Commits:
+
+    - Make commits of logical units.
+
+    - Check for unnecessary whitespace with "git diff --check" before
+      committing.
+
+    - Commit using Unix line endings (check the settings around "crlf" in
+      git-config(1)).
+
+    - Do not check in commented out code or unneeded files.
+
+    - The first line of the commit message should be a short
+      description (50 characters is the soft limit, excluding ticket
+      number(s)), and should skip the full stop.
+
+    - Associate the issue in the message. The first line should include
+      the issue number in the form "(#XXXX) Rest of message".
+
+    - The body should provide a meaningful commit message, which:
+
+      - uses the imperative, present tense: "change", not "changed" or
+        "changes".
+
+      - includes motivation for the change, and contrasts its
+        implementation with the previous behavior.
+
+    - Make sure that you have tests for the bug you are fixing, or
+      feature you are adding.
+
+    - Make sure the test suites passes after your commit:
+      `bundle exec rspec spec/acceptance` More information on [testing](#Testing) below
+
+    - When introducing a new feature, make sure it is properly
+      documented in the README.md
+
+  * Submission:
+
+    * Pre-requisites:
+
+      - Make sure you have a [GitHub account](https://github.com/join)
+
+      - [Create a ticket](https://tickets.puppetlabs.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppetlabs.com/browse/) you are patching for.
+
+    * Preferred method:
+
+      - Fork the repository on GitHub.
+
+      - Push your changes to a topic branch in your fork of the
+        repository. (the format ticket/1234-short_description_of_change is
+        usually preferred for this project).
+
+      - Submit a pull request to the repository in the puppetlabs
+        organization.
+
+The long version
+================
+
+  1.  Make separate commits for logically separate changes.
+
+      Please break your commits down into logically consistent units
+      which include new or changed tests relevant to the rest of the
+      change.  The goal of doing this is to make the diff easier to
+      read for whoever is reviewing your code.  In general, the easier
+      your diff is to read, the more likely someone will be happy to
+      review it and get it into the code base.
+
+      If you are going to refactor a piece of code, please do so as a
+      separate commit from your feature or bug fix changes.
+
+      We also really appreciate changes that include tests to make
+      sure the bug is not re-introduced, and that the feature is not
+      accidentally broken.
+
+      Describe the technical detail of the change(s).  If your
+      description starts to get too long, that is a good sign that you
+      probably need to split up your commit into more finely grained
+      pieces.
+
+      Commits which plainly describe the things which help
+      reviewers check the patch and future developers understand the
+      code are much more likely to be merged in with a minimum of
+      bike-shedding or requested changes.  Ideally, the commit message
+      would include information, and be in a form suitable for
+      inclusion in the release notes for the version of Puppet that
+      includes them.
+
+      Please also check that you are not introducing any trailing
+      whitespace or other "whitespace errors".  You can do this by
+      running "git diff --check" on your changes before you commit.
+
+  2.  Sending your patches
+
+      To submit your changes via a GitHub pull request, we _highly_
+      recommend that you have them on a topic branch, instead of
+      directly on "master".
+      It makes things much easier to keep track of, especially if
+      you decide to work on another thing before your first change
+      is merged in.
+
+      GitHub has some pretty good
+      [general documentation](http://help.github.com/) on using
+      their site.  They also have documentation on
+      [creating pull requests](http://help.github.com/send-pull-requests/).
+
+      In general, after pushing your topic branch up to your
+      repository on GitHub, you can switch to the branch in the
+      GitHub UI and click "Pull Request" towards the top of the page
+      in order to open a pull request.
+
+
+  3.  Update the related GitHub issue.
+
+      If there is a GitHub issue associated with the change you
+      submitted, then you should update the ticket to include the
+      location of your branch, along with any other commentary you
+      may wish to make.
+
+Testing
+=======
+
+Getting Started
+---------------
+
+Our puppet modules provide [`Gemfile`](./Gemfile)s which can tell a ruby
+package manager such as [bundler](http://bundler.io/) what Ruby packages,
+or Gems, are required to build, develop, and test this software.
+
+Please make sure you have [bundler installed](http://bundler.io/#getting-started)
+on your system, then use it to install all dependencies needed for this project,
+by running
+
+```shell
+% bundle install
+Fetching gem metadata from https://rubygems.org/........
+Fetching gem metadata from https://rubygems.org/..
+Using rake (10.1.0)
+Using builder (3.2.2)
+-- 8><-- many more --><8 --
+Using rspec-system-puppet (2.2.0)
+Using serverspec (0.6.3)
+Using rspec-system-serverspec (1.0.0)
+Using bundler (1.3.5)
+Your bundle is complete!
+Use `bundle show [gemname]` to see where a bundled gem is installed.
+```
+
+NOTE some systems may require you to run this command with sudo.
+
+If you already have those gems installed, make sure they are up-to-date:
+
+```shell
+% bundle update
+```
+
+With all dependencies in place and up-to-date we can now run the tests:
+
+```shell
+% rake spec
+```
+
+This will execute all the [rspec tests](http://rspec-puppet.com/) tests
+under [spec/defines](./spec/defines), [spec/classes](./spec/classes),
+and so on. rspec tests may have the same kind of dependencies as the
+module they are testing. While the module defines in its [Modulefile](./Modulefile),
+rspec tests define them in [.fixtures.yml](./fixtures.yml).
+
+Some puppet modules also come with [beaker](https://github.com/puppetlabs/beaker)
+tests. These tests spin up a virtual machine under
+[VirtualBox](https://www.virtualbox.org/)) with, controlling it with
+[Vagrant](http://www.vagrantup.com/) to actually simulate scripted test
+scenarios. In order to run these, you will need both of those tools
+installed on your system.
+
+You can run them by issuing the following command
+
+```shell
+% rake spec_clean
+% rspec spec/acceptance
+```
+
+This will now download a pre-fabricated image configured in the [default node-set](./spec/acceptance/nodesets/default.yml),
+install puppet, copy this module and install its dependencies per [spec/spec_helper_acceptance.rb](./spec/spec_helper_acceptance.rb)
+and then run all the tests under [spec/acceptance](./spec/acceptance).
+
+Writing Tests
+-------------
+
+XXX getting started writing tests.
+
+If you have commit access to the repository
+===========================================
+
+Even if you have commit access to the repository, you will still need to
+go through the process above, and have someone else review and merge
+in your changes.  The rule is that all changes must be reviewed by a
+developer on the project (that did not write the code) to ensure that
+all changes go through a code review process.
+
+Having someone other than the author of the topic branch recorded as
+performing the merge is the record that they performed the code
+review.
+
+
+Additional Resources
+====================
+
+* [Getting additional help](http://puppetlabs.com/community/get-help)
+
+* [Writing tests](http://projects.puppetlabs.com/projects/puppet/wiki/Development_Writing_Tests)
+
+* [Patchwork](https://patchwork.puppetlabs.com)
+
+* [General GitHub documentation](http://help.github.com/)
+
+* [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/Gemfile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,48 @@
+source ENV['GEM_SOURCE'] || "https://rubygems.org"
+
+def location_for(place, fake_version = nil)
+  if place =~ /^(git:[^#]*)#(.*)/
+    [fake_version, { :git => $1, :branch => $2, :require => false }].compact
+  elsif place =~ /^file:\/\/(.*)/
+    ['>= 0', { :path => File.expand_path($1), :require => false }]
+  else
+    [place, { :require => false }]
+  end
+end
+
+group :development, :unit_tests do
+  gem 'rspec-core', '3.1.7',     :require => false
+  gem 'puppetlabs_spec_helper',  :require => false
+  gem 'simplecov',               :require => false
+  gem 'puppet_facts',            :require => false
+  gem 'json',                    :require => false
+end
+
+group :system_tests do
+  if beaker_version = ENV['BEAKER_VERSION']
+    gem 'beaker', *location_for(beaker_version)
+  end
+  if beaker_rspec_version = ENV['BEAKER_RSPEC_VERSION']
+    gem 'beaker-rspec', *location_for(beaker_rspec_version)
+  else
+    gem 'beaker-rspec',  :require => false
+  end
+  gem 'serverspec',    :require => false
+  gem 'beaker-puppet_install_helper', :require => false
+end
+
+
+
+if facterversion = ENV['FACTER_GEM_VERSION']
+  gem 'facter', facterversion, :require => false
+else
+  gem 'facter', :require => false
+end
+
+if puppetversion = ENV['PUPPET_GEM_VERSION']
+  gem 'puppet', puppetversion, :require => false
+else
+  gem 'puppet', :require => false
+end
+
+# vim:ft=ruby
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/LICENSE	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+   Copyright 2012 R.I.Pienaar
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/README.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,283 @@
+#concat
+
+####Table of Contents
+
+1. [Overview](#overview)
+2. [Module Description - What the module does and why it is useful](#module-description)
+3. [Setup - The basics of getting started with concat](#setup)
+    * [What concat affects](#what-concat-affects)
+    * [Beginning with concat](#beginning-with-concat)
+4. [Usage - Configuration options and additional functionality](#usage)
+5. [Reference - An under-the-hood peek at what the module is doing and how](#reference)
+    * [Public Defines](#public-defines)
+    * [Parameters](#parameters)
+    * [Deprecations](#deprecations)
+6. [Limitations - OS compatibility, etc.](#limitations)
+7. [Development - Guide for contributing to the module](#development)
+
+##Overview
+
+The concat module lets you construct files from multiple ordered fragments of text.
+
+##Module Description
+
+The concat module lets you gather `concat::fragment` resources from your other modules and order them through a single `concat` resource into a coherent file. It does this through a Ruby script and a temporary holding space for the fragments.
+
+##Setup
+
+###What concat affects
+
+* Installs `concatfragments.rb`.
+* Adds a `concat/` directory into Puppet's `vardir`.
+
+###Beginning with concat
+
+To start using concat you need to create:
+
+* A concat{} resource for the final file.
+* One or more concat::fragment{}s.
+
+A minimal example might be:
+
+~~~
+concat { '/tmp/file':
+  ensure => present,
+}
+
+concat::fragment { 'tmpfile':
+  target  => '/tmp/file',
+  content => 'test contents',
+  order   => '01'
+}
+~~~
+
+##Usage
+
+###Maintain a list of the major modules on a node
+
+To maintain an motd file that lists the modules on one of your nodes, first create a class to frame up the file:
+
+~~~
+class motd {
+  $motd = '/etc/motd'
+
+  concat { $motd:
+    owner => 'root',
+    group => 'root',
+    mode  => '0644'
+  }
+
+  concat::fragment{ 'motd_header':
+    target  => $motd,
+    content => "\nPuppet modules on this server:\n\n",
+    order   => '01'
+  }
+
+  # let local users add to the motd by creating a file called
+  # /etc/motd.local
+  concat::fragment{ 'motd_local':
+    target => $motd,
+    source => '/etc/motd.local',
+    order  => '15'
+  }
+}
+
+# let other modules register themselves in the motd
+define motd::register($content="", $order='10') {
+  if $content == "" {
+    $body = $name
+  } else {
+    $body = $content
+  }
+
+  concat::fragment{ "motd_fragment_$name":
+    target  => '/etc/motd',
+    order   => $order,
+    content => "    -- $body\n"
+  }
+}
+~~~
+
+Then, in the declarations for each module on the node, add `motd::register{ 'Apache': }` to register the module in the motd.
+
+~~~
+class apache {
+  include apache::install, apache::config, apache::service
+
+  motd::register{ 'Apache': }
+}
+~~~
+
+These two steps populate the /etc/motd file with a list of the installed and registered modules, which stays updated even if you just remove the registered modules' `include` lines. System administrators can append text to the list by writing to /etc/motd.local.
+
+When you're finished, the motd file will look something like this:
+
+~~~
+  Puppet modules on this server:
+
+    -- Apache
+    -- MySQL
+
+  <contents of /etc/motd.local>
+~~~
+
+##Reference
+
+**Note**: Several of this module's parameters and features have been deprecated. See the [Deprecations](#deprecations) section below.
+
+###Public defines
+* `concat`: Manages a file, compiled from one or more text fragments.
+* `concat::fragment`: Manages a fragment of text to be compiled into a file.
+
+###Parameters
+
+####`concat`
+
+All the parameters listed below are optional.
+
+#####`backup`
+
+Specifies whether (and how) to back up the destination file before overwriting it. Your value gets passed on to Puppet's [native `file` resource](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-backup) for execution. Valid options: 'true', 'false', or a string representing either a target filebucket or a filename extension beginning with ".". Default value: 'puppet'.
+
+#####`ensure`
+
+Specifies whether the destination file should exist. Setting to 'absent' tells Puppet to delete the destination file if it exists, and negates the effect of any other parameters. Valid options: 'present' and 'absent'. Default value: 'present'.
+
+
+#####`ensure_newline`
+
+Specifies whether to ensure there's a new line at the end of each fragment. Valid options: 'true' and 'false'. Default value: 'false'.
+
+#####`force`
+
+In case no fragments have been added, this parameter specifies whether to go ahead and create a potentially empty file. Valid options: 'true' and 'false'. Default value: 'false'.
+
+#####`group`
+
+Specifies a permissions group for the destination file. Valid options: a string containing a group name. Default value: undefined.
+
+#####`mode`
+
+Specifies the permissions mode of the destination file. Valid options: a string containing a permission mode value in octal notation. Default value: '0644'.
+
+#####`order`
+
+Specifies a method for sorting your fragments by name within the destination file. Valid options: 'alpha' (e.g., '1, 10, 2') or 'numeric' (e.g., '1, 2, 10'). Default value: 'alpha'.
+
+You can override this setting for individual fragments by adjusting the `order` parameter in their `concat::fragment` declarations.
+
+#####`owner`
+
+
+Specifies the owner of the destination file. Valid options: a string containing a username. Default value: undefined.
+
+#####`path`
+
+
+Specifies a destination file for the combined fragments. Valid options: a string containing an absolute path. Default value: the title of your declared resource.
+
+#####`replace`
+
+Specifies whether to overwrite the destination file if it already exists. Valid options: 'true' and 'false'. Default value: 'true'.
+
+#####`validate_cmd`
+
+Specifies a validation command to apply to the destination file. Requires Puppet version 3.5 or newer. Valid options: a string to be passed to a file resource. Default value: undefined.
+
+#####`warn`
+
+Specifies whether to add a warning message at the top of the destination file so users know it was autogenerated by Puppet. Valid options: 'true', 'false', or a string to be delivered as a warning message. Default value: 'false'.
+
+
+If you set this parameter to 'true', Puppet adds the following message:
+
+~~~
+# This file is managed by Puppet. DO NOT EDIT.
+~~~
+
+####`concat::fragment`
+
+
+Except where noted, all the below parameters are optional.
+
+#####`content`
+
+Supplies the content of the fragment. **Note**: You must supply either a `content` parameter or a `source` parameter. Valid options: a string. Default value: undef.
+
+#####`ensure`
+
+Specifies whether the fragment should be included in the destination file or discarded. Valid options: 'present' and 'absent'. Default value: 'present'.
+
+#####`order`
+
+Reorders your fragments within the destination file. Fragments that share the same order number are ordered by name. Valid options: a string (recommended) or an integer. Default value: '10'.
+
+#####`source`
+
+Specifies a file to read into the content of the fragment. **Note**: You must supply either a `content` parameter or a `source` parameter. Valid options: a string or an array, containing one or more Puppet URLs. Default value: undefined.
+
+#####`target`
+
+*Required.* Specifies the destination file of the fragment. Valid options: a string containing the title of the parent `concat` resource.
+
+###Deprecations
+
+**`concat` has the following deprecations**
+
+#####`gnu`
+
+Generates a catalog compile time warning and has no effect. This parameter was silently ignored in version `1.0.0` and will be removed in a future release.
+
+#####stringified 'true'/'false' values deprecated in `warn`
+
+Passing stringified boolean values (strings of 'true' and 'false') to the `warn` parameter of `concat` is deprecated. Generates a catalog compile time warning, and will be silently treated as the concatenated file header/warning message in a future release.
+
+Please migrate to using the Puppet DSL's native [Boolean data
+type](http://docs.puppetlabs.com/puppet/3/reference/lang_datatypes.html#booleans).
+
+
+**`concat::fragment` has the following deprecations**
+
+#####`backup`
+
+Generates a catalog compile time warning and has no effect. In the `1.0.0` release this parameter controlled file bucketing of the file fragment. Bucketing the fragment(s) is redundant with bucketing the final concatenated file and this feature has been removed.
+
+
+#####`group`
+
+Generates a catalog compile time warning and has no effect. Had no user-visible effect in version `1.0.0` and will be removed in a future release.
+
+#####`mode`
+
+Generates a catalog compile time warning and has no effect. Had no user-visible effect in version `1.0.0` and will be removed in a future release.
+
+
+#####`owner`
+
+Generates a catalog compile time warning and has no effect. Had no user-visible effect in version `1.0.0` and will be removed in a future release.
+
+#####file paths are deprecated in `ensure`
+
+Passing a value other than 'present' or 'absent' in the `ensure` parameter of `concat::fragment` is **deprecated**, and generates a catalog compile time warning. The warning will become a catalog compilation failure in a future release.
+
+If you want to use the content of a file as a fragment please use the [`source`](#source) parameter.
+
+####`concat::setup`
+
+The `concat::setup` class should no longer be directly included in the manifest. It will be removed in a future release.
+
+##Limitations
+
+This module has been tested on [all PE-supported platforms](https://forge.puppetlabs.com/supported#compat-matrix), and no issues have been identified.
+
+##Development
+
+Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can't access the huge number of platforms and myriad of hardware, software, and deployment configurations that Puppet is intended to serve.
+
+We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.
+
+For more information, see our [module contribution guide.](https://docs.puppetlabs.com/forge/contributing.html)
+
+###Contributors
+
+To see who's already involved, see the [list of contributors.](https://github.com/puppetlabs/puppetlabs-concat/graphs/contributors)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/Rakefile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+require 'puppetlabs_spec_helper/rake_tasks'
+require 'puppet-lint/tasks/puppet-lint'
+
+PuppetLint.configuration.fail_on_warnings = true
+PuppetLint.configuration.send('relative')
+PuppetLint.configuration.send('disable_80chars')
+PuppetLint.configuration.send('disable_class_inherits_from_params_class')
+PuppetLint.configuration.send('disable_documentation')
+PuppetLint.configuration.send('disable_single_quote_string_with_variables')
+PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/checksums.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,54 @@
+{
+  "CHANGELOG.md": "33617b0da25c794eaa08e1aa1543ab75",
+  "CONTRIBUTING.md": "e2b8e8e433fc76b3798b7fe435f49375",
+  "Gemfile": "e6e6eb07f0bfc9bb1e328895ca49b3f5",
+  "LICENSE": "f5a76685d453424cd63dde1535811cf0",
+  "README.md": "bb505179d3251a6158104c29c98a8c19",
+  "Rakefile": "d953eb985f82600dc3b9ac6e1f2cfe64",
+  "files/concatfragments.rb": "b684db0eac243553a6a79365119a363d",
+  "lib/facter/concat_basedir.rb": "ff080677e7f192b9b96911698b0b9b3d",
+  "lib/puppet/parser/functions/concat_getparam.rb": "7654b44a87a05b2f2e9de2eaadf1ff8f",
+  "lib/puppet/parser/functions/concat_is_bool.rb": "a5dc6980d7f27d1b858e791964682756",
+  "manifests/fragment.pp": "6261ad7c56847a13f0718eaac4b4d1a6",
+  "manifests/init.pp": "024d3917f709b25fdf43a78f4cf115a0",
+  "manifests/setup.pp": "fc1fe8d6093ecfd17be1350f9341543b",
+  "metadata.json": "bd7eef56dc5c5b4887a1781f06b61df9",
+  "spec/acceptance/backup_spec.rb": "1d60ad406485b47b42547f24a0b68dce",
+  "spec/acceptance/concat_spec.rb": "397be6dbd46d2bd59d97c004c622081c",
+  "spec/acceptance/deprecation_warnings_spec.rb": "c52721536ea53cd3e2a0aff897951e72",
+  "spec/acceptance/empty_spec.rb": "c787d7f36b3ba142f2592db3d1b59439",
+  "spec/acceptance/fragment_source_spec.rb": "594cef5172b52aa65dc16ebd34fad9c6",
+  "spec/acceptance/fragments_are_always_replaced_spec.rb": "be39ed9ed30e7bb48aaccda2d7f730ac",
+  "spec/acceptance/newline_spec.rb": "5aaf65972c4f8ed4fd1592cd863583f5",
+  "spec/acceptance/nodesets/aix-71-vcloud.yml": "de6cc5bf18be2be8d50e62503652cb32",
+  "spec/acceptance/nodesets/centos-59-x64.yml": "57eb3e471b9042a8ea40978c467f8151",
+  "spec/acceptance/nodesets/centos-64-x64-pe.yml": "ec075d95760df3d4702abea1ce0a829b",
+  "spec/acceptance/nodesets/centos-64-x64.yml": "9cde7b5d2ab6a42366d2344c264d6bdc",
+  "spec/acceptance/nodesets/centos-65-x64.yml": "3e5c36e6aa5a690229e720f4048bb8af",
+  "spec/acceptance/nodesets/debian-607-x64.yml": "d566bf76f534e2af7c9a4605316d232c",
+  "spec/acceptance/nodesets/debian-70rc1-x64.yml": "31ccca73af7b74e1cc2fb0035c230b2c",
+  "spec/acceptance/nodesets/debian-73-x64.yml": "bd3ea8245ce691c2b234529d62d043eb",
+  "spec/acceptance/nodesets/default.yml": "efd15b1780bb8e68000a7a4e9e09a132",
+  "spec/acceptance/nodesets/fedora-18-x64.yml": "acc126fa764c39a3b1df36e9224a21d9",
+  "spec/acceptance/nodesets/sles-11-x64.yml": "44e4c6c15c018333bfa9840a5e702f66",
+  "spec/acceptance/nodesets/sles-11sp1-x64.yml": "fa0046bd89c1ab4ba9521ad79db234cd",
+  "spec/acceptance/nodesets/ubuntu-server-10044-x64.yml": "75e86400b7889888dc0781c0ae1a1297",
+  "spec/acceptance/nodesets/ubuntu-server-12042-x64.yml": "d30d73e34cd50b043c7d14e305955269",
+  "spec/acceptance/nodesets/ubuntu-server-1404-x64.yml": "5f0aed10098ac5b78e4217bb27c7aaf0",
+  "spec/acceptance/order_spec.rb": "76679ada1cd77b8b0663d0a65a4c7a25",
+  "spec/acceptance/quoted_paths_spec.rb": "a7810ac24a913bbc0d733f9b1d263748",
+  "spec/acceptance/replace_spec.rb": "48f4bb04e8f471cbaba0d9b53a8ab0f0",
+  "spec/acceptance/specinfra_stubs.rb": "27839261403d8bbccf506552f9d8ef38",
+  "spec/acceptance/symbolic_name_spec.rb": "b40452adbfebb0ea9d56547d9daee700",
+  "spec/acceptance/validation_spec.rb": "e54226b10f46cfa9e89e57398eddbbd2",
+  "spec/acceptance/warn_spec.rb": "cbf24bb8d9d5e9930e33632afb1d7647",
+  "spec/spec.opts": "a600ded995d948e393fbe2320ba8e51c",
+  "spec/spec_helper.rb": "0db89c9a486df193c0e40095422e19dc",
+  "spec/spec_helper_acceptance.rb": "9e41650d04d448cbf42616abbd028a2c",
+  "spec/unit/classes/concat_setup_spec.rb": "fccc98ce6dee37e2d5824424ce473645",
+  "spec/unit/defines/concat_fragment_spec.rb": "cbeea175e9661edbb4602ebe0b069a0f",
+  "spec/unit/defines/concat_spec.rb": "a1db6d53e4d77515e08a867df26d9ccb",
+  "spec/unit/facts/concat_basedir_spec.rb": "cf00f5a07948436fa0a84d00fc098539",
+  "tests/fragment.pp": "9adc3d9ba61676066072e1b949a37dbb",
+  "tests/init.pp": "bd3ce7d2ee146744b5dbbaae8a927043"
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/files/concatfragments.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,153 @@
+#!/usr/bin/env ruby
+# Script to concat files to a config file.
+#
+# Given a directory like this:
+# /path/to/conf.d
+# |-- fragments
+# |   |-- 00_named.conf
+# |   |-- 10_domain.net
+# |   `-- zz_footer
+#
+# The script supports a test option that will build the concat file to a temp location and
+# use /usr/bin/cmp to verify if it should be run or not.  This would result in the concat happening
+# twice on each run but gives you the option to have an unless option in your execs to inhibit rebuilds.
+#
+# Without the test option and the unless combo your services that depend on the final file would end up
+# restarting on each run, or in other manifest models some changes might get missed.
+#
+# OPTIONS:
+#  -o	The file to create from the sources
+#  -d	The directory where the fragments are kept
+#  -t	Test to find out if a build is needed, basically concats the files to a temp
+#       location and compare with what's in the final location, return codes are designed
+#       for use with unless on an exec resource
+#  -w   Add a shell style comment at the top of the created file to warn users that it
+#       is generated by puppet
+#  -f   Enables the creation of empty output files when no fragments are found
+#  -n	Sort the output numerically rather than the default alpha sort
+#
+# the command:
+#
+#   concatfragments.rb -o /path/to/conffile.cfg -d /path/to/conf.d
+#
+# creates /path/to/conf.d/fragments.concat and copies the resulting
+# file to /path/to/conffile.cfg.  The files will be sorted alphabetically
+# pass the -n switch to sort numerically.
+#
+# The script does error checking on the various dirs and files to make
+# sure things don't fail.
+require 'optparse'
+require 'fileutils'
+
+settings = {
+    :outfile => "",
+    :workdir => "",
+    :test => false,
+    :force => false,
+    :warn => "",
+    :sortarg => "",
+    :newline => false
+}
+
+OptionParser.new do |opts|
+  opts.banner = "Usage: #{$0} [options]"
+  opts.separator "Specific options:"
+
+  opts.on("-o", "--outfile OUTFILE", String, "The file to create from the sources") do |o|
+    settings[:outfile] = o
+  end
+
+  opts.on("-d", "--workdir WORKDIR", String, "The directory where the fragments are kept") do |d|
+    settings[:workdir] = d
+  end
+
+  opts.on("-t", "--test", "Test to find out if a build is needed") do
+    settings[:test] = true
+  end
+
+  opts.separator "Other options:"
+  opts.on("-w", "--warn WARNMSG", String,
+          "Add a shell style comment at the top of the created file to warn users that it is generated by puppet") do |w|
+    settings[:warn] = w
+  end
+
+  opts.on("-f", "--force", "Enables the creation of empty output files when no fragments are found") do
+    settings[:force] = true
+  end
+
+  opts.on("-n", "--sort", "Sort the output numerically rather than the default alpha sort") do
+    settings[:sortarg] = "-n"
+  end
+
+  opts.on("-l", "--line", "Append a newline") do
+    settings[:newline] = true
+  end
+end.parse!
+
+# do we have -o?
+raise 'Please specify an output file with -o' unless !settings[:outfile].empty?
+
+# do we have -d?
+raise 'Please specify fragments directory with -d' unless !settings[:workdir].empty?
+
+# can we write to -o?
+if File.file?(settings[:outfile])
+  if !File.writable?(settings[:outfile])
+    raise "Cannot write to #{settings[:outfile]}"
+  end
+else
+  if !File.writable?(File.dirname(settings[:outfile]))
+    raise "Cannot write to dirname #{File.dirname(settings[:outfile])} to create #{settings[:outfile]}"
+  end
+end
+
+# do we have a fragments subdir inside the work dir?
+if !File.directory?(File.join(settings[:workdir], "fragments")) && !File.executable?(File.join(settings[:workdir], "fragments"))
+  raise "Cannot access the fragments directory"
+end
+
+# are there actually any fragments?
+if (Dir.entries(File.join(settings[:workdir], "fragments")) - %w{ . .. }).empty?
+  if !settings[:force]
+    raise "The fragments directory is empty, cowardly refusing to make empty config files"
+  end
+end
+
+Dir.chdir(settings[:workdir])
+
+if settings[:warn].empty?
+  File.open("fragments.concat", 'w') { |f| f.write("") }
+else
+  File.open("fragments.concat", 'w') { |f| f.write("#{settings[:warn]}\n") }
+end
+
+# find all the files in the fragments directory, sort them numerically and concat to fragments.concat in the working dir
+open('fragments.concat', 'a') do |f|
+  fragments = Dir.entries("fragments").sort
+  if settings[:sortarg] == '-n'
+    fragments = fragments.sort_by { |v| v.split('_').map(&:to_i) }
+  end
+  fragments.each { |entry|
+    if File.file?(File.join("fragments", entry))
+      f << File.read(File.join("fragments", entry))
+
+      # append a newline if we were asked to (invoked with -l)
+      if settings[:newline]
+        f << "\n"
+      end
+
+    end
+  }
+end
+
+if !settings[:test]
+  # This is a real run, copy the file to outfile
+  FileUtils.cp 'fragments.concat', settings[:outfile]
+else
+  # Just compare the result to outfile to help the exec decide
+  if FileUtils.cmp 'fragments.concat', settings[:outfile]
+    exit 0
+  else
+    exit 1
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/lib/facter/concat_basedir.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+# == Fact: concat_basedir
+#
+# A custom fact that sets the default location for fragments
+#
+# "${::vardir}/concat/"
+#
+Facter.add("concat_basedir") do
+  setcode do
+    File.join(Puppet[:vardir],"concat")
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/lib/puppet/parser/functions/concat_getparam.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+# Test whether a given class or definition is defined
+require 'puppet/parser/functions'
+
+Puppet::Parser::Functions.newfunction(:concat_getparam,
+                                      :type => :rvalue,
+                                      :doc => <<-'ENDOFDOC'
+Takes a resource reference and name of the parameter and
+returns value of resource's parameter.
+
+*Examples:*
+
+    define example_resource($param) {
+    }
+
+    example_resource { "example_resource_instance":
+        param => "param_value"
+    }
+
+    concat_getparam(Example_resource["example_resource_instance"], "param")
+
+Would return: param_value
+ENDOFDOC
+) do |vals|
+  reference, param = vals
+  raise(ArgumentError, 'Must specify a reference') unless reference
+  raise(ArgumentError, 'Must specify name of a parameter') unless param and param.instance_of? String
+
+  return '' if param.empty?
+
+  if resource = findresource(reference.to_s)
+    return resource[param] if resource[param]
+  end
+
+  return ''
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/lib/puppet/parser/functions/concat_is_bool.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#
+# concat_is_bool.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:concat_is_bool, :type => :rvalue, :doc => <<-EOS
+Returns true if the variable passed to this function is a boolean.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "concat_is_bool(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size != 1
+
+    type = arguments[0]
+
+    result = type.is_a?(TrueClass) || type.is_a?(FalseClass)
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/manifests/fragment.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,133 @@
+# == Define: concat::fragment
+#
+# Puts a file fragment into a directory previous setup using concat
+#
+# === Options:
+#
+# [*target*]
+#   The file that these fragments belong to
+# [*content*]
+#   If present puts the content into the file
+# [*source*]
+#   If content was not specified, use the source
+# [*order*]
+#   By default all files gets a 10_ prefix in the directory you can set it to
+#   anything else using this to influence the order of the content in the file
+# [*ensure*]
+#   Present/Absent or destination to a file to include another file
+# [*mode*]
+#   Deprecated
+# [*owner*]
+#   Deprecated
+# [*group*]
+#   Deprecated
+# [*backup*]
+#   Deprecated
+#
+define concat::fragment(
+    $target,
+    $content = undef,
+    $source  = undef,
+    $order   = '10',
+    $ensure  = undef,
+    $mode    = undef,
+    $owner   = undef,
+    $group   = undef,
+    $backup  = undef
+) {
+  validate_string($target)
+  validate_string($content)
+  if !(is_string($source) or is_array($source)) {
+    fail('$source is not a string or an Array.')
+  }
+  if !(is_string($order) or is_integer($order)) {
+    fail('$order is not a string or integer.')
+  } elsif (is_string($order) and $order =~ /[:\n\/]/) {
+    fail("Order cannot contain '/', ':', or '\n'.")
+  }
+  if $mode {
+    warning('The $mode parameter to concat::fragment is deprecated and has no effect')
+  }
+  if $owner {
+    warning('The $owner parameter to concat::fragment is deprecated and has no effect')
+  }
+  if $group {
+    warning('The $group parameter to concat::fragment is deprecated and has no effect')
+  }
+  if $backup {
+    warning('The $backup parameter to concat::fragment is deprecated and has no effect')
+  }
+
+  $my_backup = concat_getparam(Concat[$target], 'backup')
+  $_backup = $my_backup ? {
+    ''      => undef,
+    default => $my_backup
+  }
+
+  if $ensure == undef {
+    $my_ensure = concat_getparam(Concat[$target], 'ensure')
+  } else {
+    if ! ($ensure in [ 'present', 'absent' ]) {
+      warning('Passing a value other than \'present\' or \'absent\' as the $ensure parameter to concat::fragment is deprecated.  If you want to use the content of a file as a fragment please use the $source parameter.')
+    }
+    $my_ensure = $ensure
+  }
+
+  include concat::setup
+
+  $safe_name        = regsubst($name, '[/:\n]', '_', 'GM')
+  $safe_target_name = regsubst($target, '[/:\n]', '_', 'GM')
+  $concatdir        = $concat::setup::concatdir
+  $fragdir          = "${concatdir}/${safe_target_name}"
+  $fragowner        = $concat::setup::fragment_owner
+  $fraggroup        = $concat::setup::fragment_group
+  $fragmode         = $concat::setup::fragment_mode
+
+  # The file type's semantics are problematic in that ensure => present will
+  # not over write a pre-existing symlink.  We are attempting to provide
+  # backwards compatiblity with previous concat::fragment versions that
+  # supported the file type's ensure => /target syntax
+
+  # be paranoid and only allow the fragment's file resource's ensure param to
+  # be file, absent, or a file target
+  $safe_ensure = $my_ensure ? {
+    ''        => 'file',
+    undef     => 'file',
+    'file'    => 'file',
+    'present' => 'file',
+    'absent'  => 'absent',
+    default   => $my_ensure,
+  }
+
+  # if it looks line ensure => /target syntax was used, fish that out
+  if ! ($my_ensure in ['', 'present', 'absent', 'file' ]) {
+    $ensure_target = $my_ensure
+  } else {
+    $ensure_target = undef
+  }
+
+  # the file type's semantics only allows one of: ensure => /target, content,
+  # or source
+  if ($ensure_target and $source) or
+    ($ensure_target and $content) or
+    ($source and $content) {
+    fail('You cannot specify more than one of $content, $source, $ensure => /target')
+  }
+
+  if ! ($content or $source or $ensure_target) {
+    crit('No content, source or symlink specified')
+  }
+
+  file { "${fragdir}/fragments/${order}_${safe_name}":
+    ensure  => $safe_ensure,
+    owner   => $fragowner,
+    group   => $fraggroup,
+    mode    => $fragmode,
+    source  => $source,
+    content => $content,
+    backup  => $_backup,
+    replace => true,
+    alias   => "concat_fragment_${name}",
+    notify  => Exec["concat_${target}"]
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,276 @@
+# == Define: concat
+#
+# Sets up so that you can use fragments to build a final config file,
+#
+# === Options:
+#
+# [*ensure*]
+#   Present/Absent
+# [*path*]
+#   The path to the final file. Use this in case you want to differentiate
+#   between the name of a resource and the file path.  Note: Use the name you
+#   provided in the target of your fragments.
+# [*owner*]
+#   Who will own the file
+# [*group*]
+#   Who will own the file
+# [*mode*]
+#   The mode of the final file
+# [*force*]
+#   Enables creating empty files if no fragments are present
+# [*warn*]
+#   Adds a normal shell style comment top of the file indicating that it is
+#   built by puppet
+# [*force*]
+# [*backup*]
+#   Controls the filebucketing behavior of the final file and see File type
+#   reference for its use.  Defaults to 'puppet'
+# [*replace*]
+#   Whether to replace a file that already exists on the local system
+# [*order*]
+# [*ensure_newline*]
+# [*gnu*]
+#   Deprecated
+#
+# === Actions:
+# * Creates fragment directories if it didn't exist already
+# * Executes the concatfragments.rb script to build the final file, this
+#   script will create directory/fragments.concat.   Execution happens only
+#   when:
+#   * The directory changes
+#   * fragments.concat != final destination, this means rebuilds will happen
+#     whenever someone changes or deletes the final file.  Checking is done
+#     using /usr/bin/cmp.
+#   * The Exec gets notified by something else - like the concat::fragment
+#     define
+# * Copies the file over to the final destination using a file resource
+#
+# === Aliases:
+#
+# * The exec can notified using Exec["concat_/path/to/file"] or
+#   Exec["concat_/path/to/directory"]
+# * The final file can be referenced as File["/path/to/file"] or
+#   File["concat_/path/to/file"]
+#
+define concat(
+  $ensure         = 'present',
+  $path           = $name,
+  $owner          = undef,
+  $group          = undef,
+  $mode           = '0644',
+  $warn           = false,
+  $force          = false,
+  $backup         = 'puppet',
+  $replace        = true,
+  $order          = 'alpha',
+  $ensure_newline = false,
+  $validate_cmd   = undef,
+  $gnu            = undef
+) {
+  validate_re($ensure, '^present$|^absent$')
+  validate_absolute_path($path)
+  validate_string($owner)
+  validate_string($group)
+  validate_string($mode)
+  if ! (is_string($warn) or $warn == true or $warn == false) {
+    fail('$warn is not a string or boolean')
+  }
+  validate_bool($force)
+  if ! concat_is_bool($backup) and ! is_string($backup) {
+    fail('$backup must be string or bool!')
+  }
+  validate_bool($replace)
+  validate_re($order, '^alpha$|^numeric$')
+  validate_bool($ensure_newline)
+  if $validate_cmd and ! is_string($validate_cmd) {
+    fail('$validate_cmd must be a string')
+  }
+  if $gnu {
+    warning('The $gnu parameter to concat is deprecated and has no effect')
+  }
+
+  include concat::setup
+
+  $safe_name            = regsubst($name, '[/:]', '_', 'G')
+  $concatdir            = $concat::setup::concatdir
+  $fragdir              = "${concatdir}/${safe_name}"
+  $concat_name          = 'fragments.concat.out'
+  $script_command       = $concat::setup::script_command
+  $default_warn_message = '# This file is managed by Puppet. DO NOT EDIT.'
+  $bool_warn_message    = 'Using stringified boolean values (\'true\', \'yes\', \'on\', \'false\', \'no\', \'off\') to represent boolean true/false as the $warn parameter to concat is deprecated and will be treated as the warning message in a future release'
+
+  # lint:ignore:quoted_booleans
+  case $warn {
+    true: {
+      $warn_message = $default_warn_message
+    }
+    # lint:ignore:quoted_booleans
+    'true', 'yes', 'on': {
+    # lint:endignore
+      warning($bool_warn_message)
+      $warn_message = $default_warn_message
+    }
+    false: {
+      $warn_message = ''
+    }
+    # lint:ignore:quoted_booleans
+    'false', 'no', 'off': {
+    # lint:endignore
+      warning($bool_warn_message)
+      $warn_message = ''
+    }
+    default: {
+      $warn_message = $warn
+    }
+  }
+  # lint:endignore
+
+  $warnmsg_escaped = regsubst($warn_message, '\'', '\'\\\'\'', 'G')
+  $warnflag = $warnmsg_escaped ? {
+    ''      => '',
+    default => "-w '${warnmsg_escaped}'"
+  }
+
+  $forceflag = $force ? {
+    true  => '-f',
+    false => '',
+  }
+
+  $orderflag = $order ? {
+    'numeric' => '-n',
+    'alpha'   => '',
+  }
+
+  $newlineflag = $ensure_newline ? {
+    true  => '-l',
+    false => '',
+  }
+
+  File {
+    backup  => $backup,
+  }
+
+  # reset poisoned Exec defaults
+  Exec {
+    user  => undef,
+    group => undef,
+  }
+
+  if $ensure == 'present' {
+    file { $fragdir:
+      ensure => directory,
+      mode   => '0750',
+    }
+
+    file { "${fragdir}/fragments":
+      ensure  => directory,
+      mode    => '0750',
+      force   => true,
+      ignore  => ['.svn', '.git', '.gitignore'],
+      notify  => Exec["concat_${name}"],
+      purge   => true,
+      recurse => true,
+    }
+
+    file { "${fragdir}/fragments.concat":
+      ensure => present,
+      mode   => '0640',
+    }
+
+    file { "${fragdir}/${concat_name}":
+      ensure => present,
+      mode   => '0640',
+    }
+
+    file { $name:
+      ensure  => present,
+      owner   => $owner,
+      group   => $group,
+      mode    => $mode,
+      replace => $replace,
+      path    => $path,
+      alias   => "concat_${name}",
+      source  => "${fragdir}/${concat_name}",
+      backup  => $backup,
+    }
+
+    # Only newer versions of puppet 3.x support the validate_cmd parameter
+    if $validate_cmd {
+      File[$name] {
+        validate_cmd => $validate_cmd,
+      }
+    }
+
+    # remove extra whitespace from string interpolation to make testing easier
+    $command = strip(regsubst("${script_command} -o \"${fragdir}/${concat_name}\" -d \"${fragdir}\" ${warnflag} ${forceflag} ${orderflag} ${newlineflag}", '\s+', ' ', 'G'))
+
+    # make sure ruby is in the path for PE
+    if defined('$is_pe') and str2bool("${::is_pe}") { # lint:ignore:only_variable_string
+      if $::kernel == 'windows' {
+        $command_path = "${::env_windows_installdir}/bin:${::path}"
+      } else {
+        $command_path = "/opt/puppetlabs/puppet/bin:/opt/puppet/bin:${::path}"
+      }
+    } elsif $::kernel == 'windows' {
+      $command_path = $::path
+    } else {
+      $command_path = "/opt/puppetlabs/puppet/bin:${::path}"
+    }
+
+    # if puppet is running as root, this exec should also run as root to allow
+    # the concatfragments.rb script to potentially be installed in path that
+    # may not be accessible by a target non-root owner.
+    exec { "concat_${name}":
+      alias     => "concat_${fragdir}",
+      command   => $command,
+      notify    => File[$name],
+      subscribe => File[$fragdir],
+      unless    => "${command} -t",
+      path      => $command_path,
+      require   => [
+        File[$fragdir],
+        File["${fragdir}/fragments"],
+        File["${fragdir}/fragments.concat"],
+      ],
+    }
+  } else {
+    file { [
+      $fragdir,
+      "${fragdir}/fragments",
+      "${fragdir}/fragments.concat",
+      "${fragdir}/${concat_name}"
+    ]:
+      ensure => absent,
+      force  => true,
+    }
+
+    file { $path:
+      ensure => absent,
+      backup => $backup,
+    }
+
+    # lint:ignore:quoted_booleans
+    $absent_exec_command = $::kernel ? {
+      'windows' => 'cmd.exe /c exit 0',
+    # lint:ignore:quoted_booleans
+      default   => 'true',
+    # lint:endignore
+    }
+    # lint:endignore
+
+    $absent_exec_path = $::kernel ? {
+      'windows' => $::path,
+      default   => '/bin:/usr/bin',
+    }
+
+    # Need to have an unless here for idempotency.
+    exec { "concat_${name}":
+      alias   => "concat_${fragdir}",
+      command => $absent_exec_command,
+      unless  => $absent_exec_command,
+      path    => $absent_exec_path,
+    }
+  }
+}
+
+# vim:sw=2:ts=2:expandtab:textwidth=79
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/manifests/setup.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,65 @@
+# === Class: concat::setup
+#
+# Sets up the concat system. This is a private class.
+#
+# [$concatdir]
+#   is where the fragments live and is set on the fact concat_basedir.
+#   Since puppet should always manage files in $concatdir and they should
+#   not be deleted ever, /tmp is not an option.
+#
+# It also copies out the concatfragments.{sh,rb} file to ${concatdir}/bin
+#
+class concat::setup {
+  if $caller_module_name != $module_name {
+    warning("${name} is deprecated as a public API of the ${module_name} module and should no longer be directly included in the manifest.")
+  }
+
+  if $::concat_basedir {
+    $concatdir = $::concat_basedir
+  } else {
+    fail ('$concat_basedir not defined. Try running again with pluginsync=true on the [master] and/or [main] section of your node\'s \'/etc/puppet/puppet.conf\'.')
+  }
+
+  # owner,group and mode of fragment files (on windows owner and access rights should
+  # be inherited from concatdir and not explicitly set to avoid problems)
+  $fragment_owner = $::osfamily ? { 'windows' => undef, default => $::id }
+  $fragment_mode  = $::osfamily ? { 'windows' => undef, default => '0640' }
+  # test on gid fact availability to support older facter versions
+  if defined('$gid') and $::gid and $::osfamily != 'Windows' {
+    $fragment_group = $::gid
+  } else {
+    $fragment_group = undef
+  }
+
+  $script_name = 'concatfragments.rb'
+
+  $script_path = "${concatdir}/bin/${script_name}"
+
+  $default_owner = $::osfamily ? { 'windows' => undef, default => $::id }
+
+  $default_group = $default_owner ? { 'root' => '0', default => undef }
+
+  $script_mode = $::osfamily ? { 'windows' => undef, default => '0755' }
+
+  $script_command = $::osfamily? {
+    'windows' => "ruby.exe '${script_path}'",
+    'openbsd' => "/usr/local/bin/ruby21 '${script_path}'",
+    'freebsd' => "/usr/local/bin/ruby '${script_path}'",
+    default   => $script_path
+  }
+
+  file { $script_path:
+    ensure => file,
+    owner  => $default_owner,
+    group  => $default_group,
+    mode   => $script_mode,
+    source => "puppet:///modules/concat/${script_name}",
+  }
+
+  file { [ $concatdir, "${concatdir}/bin" ]:
+    ensure => directory,
+    owner  => $default_owner,
+    group  => $default_group,
+    mode   => '0755',
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/metadata.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,110 @@
+{
+  "name": "puppetlabs-concat",
+  "version": "1.2.5",
+  "author": "Puppet Labs",
+  "summary": "Construct files from multiple fragments.",
+  "license": "Apache-2.0",
+  "source": "https://github.com/puppetlabs/puppetlabs-concat",
+  "project_page": "https://github.com/puppetlabs/puppetlabs-concat",
+  "issues_url": "https://tickets.puppetlabs.com/browse/MODULES",
+  "dependencies": [
+    {"name":"puppetlabs/stdlib","version_requirement":">= 3.2.0 < 5.0.0"}
+  ],
+  "operatingsystem_support": [
+    {
+      "operatingsystem": "RedHat",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "CentOS",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "OracleLinux",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Scientific",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "SLES",
+      "operatingsystemrelease": [
+        "10 SP4",
+        "11 SP1",
+        "12"
+      ]
+    },
+    {
+      "operatingsystem": "Debian",
+      "operatingsystemrelease": [
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Ubuntu",
+      "operatingsystemrelease": [
+        "10.04",
+        "12.04",
+        "14.04"
+      ]
+    },
+    {
+      "operatingsystem": "Solaris",
+      "operatingsystemrelease": [
+        "10",
+        "11"
+      ]
+    },
+    {
+      "operatingsystem": "Windows",
+      "operatingsystemrelease": [
+        "Server 2003 R2",
+        "Server 2008 R2",
+        "Server 2012",
+        "Server 2012 R2"
+      ]
+    },
+    {
+      "operatingsystem": "AIX",
+      "operatingsystemrelease": [
+        "5.3",
+        "6.1",
+        "7.1"
+      ]
+    },
+    {
+      "operatingsystem": "OSX",
+      "operatingsystemrelease": [
+        "10.9"
+      ]
+    }
+  ],
+  "requirements": [
+    {
+      "name": "pe",
+      "version_requirement": ">= 3.0.0 < 2015.4.0"
+    },
+    {
+      "name": "puppet",
+      "version_requirement": ">= 3.0.0 < 5.0.0"
+    }
+  ]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/backup_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,115 @@
+require 'spec_helper_acceptance'
+
+describe 'concat backup parameter' do
+  basedir = default.tmpdir('concat')
+  context '=> puppet' do
+    before(:all) do
+      pp = <<-EOS
+        file { '#{basedir}':
+          ensure => directory,
+        }
+        file { '#{basedir}/file':
+          content => "old contents\n",
+        }
+      EOS
+      apply_manifest(pp)
+    end
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        backup => 'puppet',
+      }
+      concat::fragment { 'new file':
+        target  => '#{basedir}/file',
+        content => 'new contents',
+      }
+    EOS
+
+    it 'applies the manifest twice with "Filebucketed" stdout and no stderr' do
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Filebucketed #{basedir}\/file to puppet with sum 0140c31db86293a1a1e080ce9b91305f/) # sum is for file contents of 'old contents'
+      end
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/file") do
+      it { should be_file }
+      its(:content) { should match /new contents/ }
+    end
+  end
+
+  context '=> .backup' do
+    before(:all) do
+      pp = <<-EOS
+        file { '#{basedir}':
+          ensure => directory,
+        }
+        file { '#{basedir}/file':
+          content => "old contents\n",
+        }
+      EOS
+      apply_manifest(pp)
+    end
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        backup => '.backup',
+      }
+      concat::fragment { 'new file':
+        target  => '#{basedir}/file',
+        content => 'new contents',
+      }
+    EOS
+
+    # XXX Puppet doesn't mention anything about filebucketing with a given
+    # extension like .backup
+    it 'applies the manifest twice  no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/file") do
+      it { should be_file }
+      its(:content) { should match /new contents/ }
+    end
+    describe file("#{basedir}/file.backup") do
+      it { should be_file }
+      its(:content) { should match /old contents/ }
+    end
+  end
+
+  # XXX The backup parameter uses validate_string() and thus can't be the
+  # boolean false value, but the string 'false' has the same effect in Puppet 3
+  context "=> 'false'" do
+    before(:all) do
+      pp = <<-EOS
+        file { '#{basedir}':
+          ensure => directory,
+        }
+        file { '#{basedir}/file':
+          content => "old contents\n",
+        }
+      EOS
+      apply_manifest(pp)
+    end
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        backup => '.backup',
+      }
+      concat::fragment { 'new file':
+        target  => '#{basedir}/file',
+        content => 'new contents',
+      }
+    EOS
+
+    it 'applies the manifest twice with no "Filebucketed" stdout and no stderr' do
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to_not match(/Filebucketed/)
+      end
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/file") do
+      it { should be_file }
+      its(:content) { should match /new contents/ }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/concat_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,229 @@
+require 'spec_helper_acceptance'
+
+case fact('osfamily')
+  when 'AIX'
+    username = 'root'
+    groupname = 'system'
+    scriptname = 'concatfragments.rb'
+    vardir = default.puppet['vardir']
+    if vardir.nil? or vardir == ''
+      vardir = '/opt/puppetlabs/puppet/cache'
+    end
+  when 'Darwin'
+    username = 'root'
+    groupname = 'wheel'
+    scriptname = 'concatfragments.rb'
+    vardir = default.puppet['vardir']
+    if vardir.nil? or vardir == ''
+      vardir = '/opt/puppetlabs/puppet/cache'
+    end
+  when 'windows'
+    username = 'Administrator'
+    groupname = 'Administrators'
+    scriptname = 'concatfragments.rb'
+    result = on default, "echo #{default.puppet['vardir']}"
+    vardir = result.raw_output.chomp
+  when 'Solaris'
+    username = 'root'
+    groupname = 'root'
+    scriptname = 'concatfragments.rb'
+    vardir = default.puppet['vardir']
+    if vardir.nil? or vardir == ''
+      vardir = '/opt/puppetlabs/puppet/cache'
+    end
+  else
+    username = 'root'
+    groupname = 'root'
+    scriptname = 'concatfragments.rb'
+    vardir = default.puppet['vardir']
+    if vardir.nil? or vardir == ''
+      vardir = '/opt/puppetlabs/puppet/cache'
+    end
+end
+
+describe 'basic concat test' do
+  basedir = default.tmpdir('concat')
+  safe_basedir = basedir.gsub(/[\/:]/, '_')
+
+  shared_examples 'successfully_applied' do |pp|
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{vardir}/concat") do
+      it { should be_directory }
+      it { should be_owned_by username }
+      it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) {
+        should be_mode 755
+      }
+    end
+    describe file("#{vardir}/concat/bin") do
+      it { should be_directory }
+      it { should be_owned_by username }
+      it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) {
+        should be_mode 755
+      }
+    end
+    describe file("#{vardir}/concat/bin/#{scriptname}") do
+      it { should be_file }
+      it { should be_owned_by username }
+      it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) {
+        should be_mode 755
+      }
+    end
+    describe file("#{vardir}/concat/#{safe_basedir}_file") do
+      it { should be_directory }
+      it { should be_owned_by username }
+      it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) {
+        should be_mode 750
+      }
+    end
+    describe file("#{vardir}/concat/#{safe_basedir}_file/fragments") do
+      it { should be_directory }
+      it { should be_owned_by username }
+      it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) {
+        should be_mode 750
+      }
+    end
+    describe file("#{vardir}/concat/#{safe_basedir}_file/fragments.concat") do
+      it { should be_file }
+      it { should be_owned_by username }
+      it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) {
+        should be_mode 640
+      }
+    end
+    describe file("#{vardir}/concat/#{safe_basedir}_file/fragments.concat.out") do
+      it { should be_file }
+      it { should be_owned_by username }
+      it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) {
+        should be_mode 640
+      }
+    end
+  end
+
+  context 'owner/group root' do
+    before(:all) do
+      pp = <<-EOS
+        file { '#{basedir}':
+          ensure => directory,
+        }
+      EOS
+      apply_manifest(pp)
+    end
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        owner => '#{username}',
+        group => '#{groupname}',
+        mode  => '0644',
+      }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/file',
+        content => '1',
+        order   => '01',
+      }
+
+      concat::fragment { '2':
+        target  => '#{basedir}/file',
+        content => '2',
+        order   => '02',
+      }
+    EOS
+
+    it_behaves_like 'successfully_applied', pp
+
+    describe file("#{basedir}/file") do
+      it { should be_file }
+      it { should be_owned_by username }
+      it("should be group", :unless => (fact('osfamily') == 'windows')) { should be_grouped_into groupname }
+      it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) {
+        should be_mode 644
+      }
+      its(:content) {
+        should match '1'
+        should match '2'
+      }
+    end
+    describe file("#{vardir}/concat/#{safe_basedir}_file/fragments/01_1") do
+      it { should be_file }
+      it { should be_owned_by username }
+      it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) {
+        should be_mode 640
+      }
+    end
+    describe file("#{vardir}/concat/#{safe_basedir}_file/fragments/02_2") do
+      it { should be_file }
+      it { should be_owned_by username }
+      it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) {
+        should be_mode 640
+      }
+    end
+  end
+
+  context 'ensure' do
+    context 'works when set to present with path set' do
+      before(:all) do
+        pp = <<-EOS
+        file { '#{basedir}':
+          ensure => directory,
+        }
+        EOS
+        apply_manifest(pp)
+      end
+      pp="
+        concat { 'file':
+          ensure => present,
+          path   => '#{basedir}/file',
+          mode   => '0644',
+        }
+        concat::fragment { '1':
+          target  => 'file',
+          content => '1',
+          order   => '01',
+        }
+      "
+
+      it_behaves_like 'successfully_applied', pp
+
+      describe file("#{basedir}/file") do
+        it { should be_file }
+        it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) {
+          should be_mode 644
+        }
+        its(:content) { should match '1' }
+      end
+    end
+    context 'works when set to absent with path set' do
+      before(:all) do
+        pp = <<-EOS
+        file { '#{basedir}':
+          ensure => directory,
+        }
+        EOS
+        apply_manifest(pp)
+      end
+      pp="
+        concat { 'file':
+          ensure => absent,
+          path   => '#{basedir}/file',
+          mode   => '0644',
+        }
+        concat::fragment { '1':
+          target  => 'file',
+          content => '1',
+          order   => '01',
+        }
+      "
+
+      it 'applies the manifest twice with no stderr' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      describe file("#{basedir}/file") do
+        it { should_not be_file }
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/deprecation_warnings_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,238 @@
+require 'spec_helper_acceptance'
+
+describe 'deprecation warnings' do
+  basedir = default.tmpdir('concat')
+
+  shared_examples 'has_warning' do |pp, w|
+    it 'applies the manifest twice with a stderr regex' do
+      expect(apply_manifest(pp, :catch_failures => true).stderr).to match(/#{Regexp.escape(w)}/m)
+      expect(apply_manifest(pp, :catch_changes => true).stderr).to match(/#{Regexp.escape(w)}/m)
+    end
+  end
+
+  context 'concat gnu parameter' do
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        gnu => 'foo',
+      }
+      concat::fragment { 'foo':
+        target  => '#{basedir}/file',
+        content => 'bar',
+      }
+    EOS
+    w = 'The $gnu parameter to concat is deprecated and has no effect'
+
+    it_behaves_like 'has_warning', pp, w
+  end
+
+  context 'concat warn parameter =>' do
+    ['true', 'yes', 'on'].each do |warn|
+      context warn do
+        pp = <<-EOS
+          concat { '#{basedir}/file':
+            warn => '#{warn}',
+          }
+          concat::fragment { 'foo':
+            target  => '#{basedir}/file',
+            content => 'bar',
+          }
+        EOS
+        w = 'Using stringified boolean values (\'true\', \'yes\', \'on\', \'false\', \'no\', \'off\') to represent boolean true/false as the $warn parameter to concat is deprecated and will be treated as the warning message in a future release'
+
+        it_behaves_like 'has_warning', pp, w
+
+        describe file("#{basedir}/file") do
+          it { should be_file }
+          its(:content) {
+            should match '# This file is managed by Puppet. DO NOT EDIT.'
+            should match 'bar'
+          }
+        end
+      end
+    end
+
+    ['false', 'no', 'off'].each do |warn|
+      context warn do
+        pp = <<-EOS
+          concat { '#{basedir}/file':
+            warn => '#{warn}',
+          }
+          concat::fragment { 'foo':
+            target  => '#{basedir}/file',
+            content => 'bar',
+          }
+        EOS
+        w = 'Using stringified boolean values (\'true\', \'yes\', \'on\', \'false\', \'no\', \'off\') to represent boolean true/false as the $warn parameter to concat is deprecated and will be treated as the warning message in a future release'
+
+        it_behaves_like 'has_warning', pp, w
+
+        describe file("#{basedir}/file") do
+          it { should be_file }
+          its(:content) {
+            should_not match '# This file is managed by Puppet. DO NOT EDIT.'
+            should match 'bar'
+          }
+        end
+      end
+    end
+  end
+
+  context 'concat::fragment ensure parameter', :unless => fact('osfamily') == 'windows' do
+    context 'target file exists' do
+      before(:all) do
+        pp = <<-EOS
+          file { '#{basedir}':
+            ensure => directory,
+          }
+          file { '#{basedir}/file1':
+            content => "file1 contents\n",
+          }
+        EOS
+        apply_manifest(pp)
+      end
+
+      pp = <<-EOS
+        concat { '#{basedir}/file': }
+        concat::fragment { 'foo':
+          target => '#{basedir}/file',
+          ensure => '#{basedir}/file1',
+        }
+      EOS
+      w = 'Passing a value other than \'present\' or \'absent\' as the $ensure parameter to concat::fragment is deprecated.  If you want to use the content of a file as a fragment please use the $source parameter.'
+
+      it_behaves_like 'has_warning', pp, w
+
+      describe file("#{basedir}/file") do
+        it { should be_file }
+        its(:content) { should match 'file1 contents' }
+      end
+
+      describe 'the fragment can be changed from a symlink to a plain file', :unless => (fact("osfamily") == "windows") do
+        pp = <<-EOS
+          concat { '#{basedir}/file': }
+          concat::fragment { 'foo':
+            target  => '#{basedir}/file',
+            content => 'new content',
+          }
+        EOS
+
+        it 'applies the manifest twice with no stderr' do
+          apply_manifest(pp, :catch_failures => true)
+          apply_manifest(pp, :catch_changes => true)
+        end
+
+        describe file("#{basedir}/file") do
+          it { should be_file }
+          its(:content) {
+            should match 'new content'
+            should_not match 'file1 contents'
+          }
+        end
+      end
+    end # target file exists
+
+    context 'target does not exist', :unless => fact('osfamily') == 'windows' do
+      pp = <<-EOS
+        concat { '#{basedir}/file': }
+        concat::fragment { 'foo':
+          target => '#{basedir}/file',
+          ensure => '#{basedir}/file1',
+        }
+      EOS
+      w = 'Passing a value other than \'present\' or \'absent\' as the $ensure parameter to concat::fragment is deprecated.  If you want to use the content of a file as a fragment please use the $source parameter.'
+
+      it_behaves_like 'has_warning', pp, w
+
+      describe file("#{basedir}/file") do
+        it { should be_file }
+      end
+
+      describe 'the fragment can be changed from a symlink to a plain file', :unless => (fact('osfamily') == 'windows') do
+        pp = <<-EOS
+          concat { '#{basedir}/file': }
+          concat::fragment { 'foo':
+            target  => '#{basedir}/file',
+            content => 'new content',
+          }
+        EOS
+
+        it 'applies the manifest twice with no stderr' do
+          apply_manifest(pp, :catch_failures => true)
+          apply_manifest(pp, :catch_changes => true)
+        end
+
+        describe file("#{basedir}/file") do
+          it { should be_file }
+          its(:content) { should match 'new content' }
+        end
+      end
+    end # target file exists
+
+  end # concat::fragment ensure parameter
+
+  context 'concat::fragment mode parameter' do
+    pp = <<-EOS
+      concat { '#{basedir}/file': }
+      concat::fragment { 'foo':
+        target  => '#{basedir}/file',
+        content => 'bar',
+        mode    => 'bar',
+      }
+    EOS
+    w = 'The $mode parameter to concat::fragment is deprecated and has no effect'
+
+    it_behaves_like 'has_warning', pp, w
+  end
+
+  context 'concat::fragment owner parameter' do
+    pp = <<-EOS
+      concat { '#{basedir}/file': }
+      concat::fragment { 'foo':
+        target  => '#{basedir}/file',
+        content => 'bar',
+        owner   => 'bar',
+      }
+    EOS
+    w = 'The $owner parameter to concat::fragment is deprecated and has no effect'
+
+    it_behaves_like 'has_warning', pp, w
+  end
+
+  context 'concat::fragment group parameter' do
+    pp = <<-EOS
+      concat { '#{basedir}/file': }
+      concat::fragment { 'foo':
+        target  => '#{basedir}/file',
+        content => 'bar',
+        group   => 'bar',
+      }
+    EOS
+    w = 'The $group parameter to concat::fragment is deprecated and has no effect'
+
+    it_behaves_like 'has_warning', pp, w
+  end
+
+  context 'concat::fragment backup parameter' do
+    pp = <<-EOS
+      concat { '#{basedir}/file': }
+      concat::fragment { 'foo':
+        target  => '#{basedir}/file',
+        content => 'bar',
+        backup  => 'bar',
+      }
+    EOS
+    w = 'The $backup parameter to concat::fragment is deprecated and has no effect'
+
+    it_behaves_like 'has_warning', pp, w
+  end
+
+  context 'include concat::setup' do
+    pp = <<-EOS
+      include concat::setup
+    EOS
+    w = 'concat::setup is deprecated as a public API of the concat module and should no longer be directly included in the manifest.'
+
+    it_behaves_like 'has_warning', pp, w
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/empty_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+require 'spec_helper_acceptance'
+
+describe 'concat force empty parameter' do
+  basedir = default.tmpdir('concat')
+  context 'should run successfully' do
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        mode  => '0644',
+        force => true,
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/file") do
+      it { should be_file }
+      its(:content) { should_not match /1\n2/ }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/fragment_source_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,157 @@
+require 'spec_helper_acceptance'
+
+case fact('osfamily')
+  when 'AIX'
+    username = 'root'
+    groupname = 'system'
+  when 'Darwin'
+    username = 'root'
+    groupname = 'wheel'
+  when 'windows'
+    username = 'Administrator'
+    groupname = 'Administrators'
+  else
+    username = 'root'
+    groupname = 'root'
+end
+
+describe 'concat::fragment source' do
+  basedir = default.tmpdir('concat')
+  context 'should read file fragments from local system' do
+    pp = <<-EOS
+      file { '#{basedir}/file1':
+        content => "file1 contents\n"
+      }
+      file { '#{basedir}/file2':
+        content => "file2 contents\n"
+      }
+      concat { '#{basedir}/foo': }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/foo',
+        source  => '#{basedir}/file1',
+        require => File['#{basedir}/file1'],
+      }
+      concat::fragment { '2':
+        target  => '#{basedir}/foo',
+        content => 'string1 contents',
+      }
+      concat::fragment { '3':
+        target  => '#{basedir}/foo',
+        source  => '#{basedir}/file2',
+        require => File['#{basedir}/file2'],
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/foo") do
+      it { should be_file }
+      its(:content) {
+        should match 'file1 contents'
+        should match 'string1 contents'
+        should match 'file2 contents'
+      }
+    end
+  end # should read file fragments from local system
+
+  context 'should create files containing first match only.' do
+    pp = <<-EOS
+      file { '#{basedir}/file1':
+        content => "file1 contents\n"
+      }
+      file { '#{basedir}/file2':
+        content => "file2 contents\n"
+      }
+      concat { '#{basedir}/result_file1':
+        owner   => '#{username}',
+        group   => '#{groupname}',
+        mode    => '0644',
+      }
+      concat { '#{basedir}/result_file2':
+        owner   => '#{username}',
+        group   => '#{groupname}',
+        mode    => '0644',
+      }
+      concat { '#{basedir}/result_file3':
+        owner   => '#{username}',
+        group   => '#{groupname}',
+        mode    => '0644',
+      }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/result_file1',
+        source  => [ '#{basedir}/file1', '#{basedir}/file2' ],
+        require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ],
+        order   => '01',
+      }
+      concat::fragment { '2':
+        target  => '#{basedir}/result_file2',
+        source  => [ '#{basedir}/file2', '#{basedir}/file1' ],
+        require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ],
+        order   => '01',
+      }
+      concat::fragment { '3':
+        target  => '#{basedir}/result_file3',
+        source  => [ '#{basedir}/file1', '#{basedir}/file2' ],
+        require => [ File['#{basedir}/file1'], File['#{basedir}/file2'] ],
+        order   => '01',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+    describe file("#{basedir}/result_file1") do
+      it { should be_file }
+      its(:content) {
+        should match 'file1 contents'
+        should_not match 'file2 contents'
+      }
+    end
+    describe file("#{basedir}/result_file2") do
+      it { should be_file }
+      its(:content) {
+        should match 'file2 contents'
+        should_not match 'file1 contents'
+      }
+    end
+    describe file("#{basedir}/result_file3") do
+      it { should be_file }
+      its(:content) {
+        should match 'file1 contents'
+        should_not match 'file2 contents'
+      }
+    end
+  end
+
+  context 'should fail if no match on source.' do
+    pp = <<-EOS
+      concat { '#{basedir}/fail_no_source':
+        owner   => '#{username}',
+        group   => '#{groupname}',
+        mode    => '0644',
+      }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/fail_no_source',
+        source => [ '#{basedir}/nofilehere', '#{basedir}/nothereeither' ],
+        order   => '01',
+      }
+    EOS
+
+    it 'applies the manifest with resource failures' do
+      apply_manifest(pp, :expect_failures => true)
+    end
+    describe file("#{basedir}/fail_no_source") do
+      #FIXME: Serverspec::Type::File doesn't support exists? for some reason. so... hack.
+      it { should_not be_file }
+      it { should_not be_directory }
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/fragments_are_always_replaced_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,139 @@
+require 'spec_helper_acceptance'
+
+describe 'concat::fragment replace' do
+  basedir = default.tmpdir('concat')
+
+  context 'should create fragment files' do
+    before(:all) do
+      pp = <<-EOS
+        file { '#{basedir}':
+          ensure => directory,
+        }
+      EOS
+      apply_manifest(pp)
+    end
+
+    pp1 = <<-EOS
+      concat { '#{basedir}/foo': }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/foo',
+        content => 'caller has replace unset run 1',
+      }
+    EOS
+    pp2 = <<-EOS
+      concat { '#{basedir}/foo': }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/foo',
+        content => 'caller has replace unset run 2',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp1, :catch_failures => true)
+      apply_manifest(pp1, :catch_changes => true)
+      apply_manifest(pp2, :catch_failures => true)
+      apply_manifest(pp2, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/foo") do
+      it { should be_file }
+      its(:content) {
+        should_not match 'caller has replace unset run 1'
+        should match 'caller has replace unset run 2'
+      }
+    end
+  end # should create fragment files
+
+  context 'should replace its own fragment files when caller has File { replace=>true } set' do
+    before(:all) do
+      pp = <<-EOS
+        file { '#{basedir}':
+          ensure => directory,
+        }
+      EOS
+      apply_manifest(pp)
+    end
+
+    pp1 = <<-EOS
+      File { replace=>true }
+      concat { '#{basedir}/foo': }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/foo',
+        content => 'caller has replace true set run 1',
+      }
+    EOS
+    pp2 = <<-EOS
+      File { replace=>true }
+      concat { '#{basedir}/foo': }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/foo',
+        content => 'caller has replace true set run 2',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp1, :catch_failures => true)
+      apply_manifest(pp1, :catch_changes => true)
+      apply_manifest(pp2, :catch_failures => true)
+      apply_manifest(pp2, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/foo") do
+      it { should be_file }
+      its(:content) {
+        should_not match 'caller has replace true set run 1'
+        should match 'caller has replace true set run 2'
+      }
+    end
+  end # should replace its own fragment files when caller has File(replace=>true) set
+
+  context 'should replace its own fragment files even when caller has File { replace=>false } set' do
+    before(:all) do
+      pp = <<-EOS
+        file { '#{basedir}':
+          ensure => directory,
+        }
+      EOS
+      apply_manifest(pp)
+    end
+
+    pp1 = <<-EOS
+      File { replace=>false }
+      concat { '#{basedir}/foo': }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/foo',
+        content => 'caller has replace false set run 1',
+      }
+    EOS
+    pp2 = <<-EOS
+      File { replace=>false }
+      concat { '#{basedir}/foo': }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/foo',
+        content => 'caller has replace false set run 2',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp1, :catch_failures => true)
+      apply_manifest(pp1, :catch_changes => true)
+      apply_manifest(pp2, :catch_failures => true)
+      apply_manifest(pp2, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/foo") do
+      it { should be_file }
+      its(:content) {
+        should_not match 'caller has replace false set run 1'
+        should match 'caller has replace false set run 2'
+      }
+    end
+  end # should replace its own fragment files even when caller has File(replace=>false) set
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/newline_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,67 @@
+require 'spec_helper_acceptance'
+
+describe 'concat ensure_newline parameter' do
+  basedir = default.tmpdir('concat')
+  context '=> false' do
+    before(:all) do
+      pp = <<-EOS
+        file { '#{basedir}':
+          ensure => directory
+        }
+      EOS
+
+      apply_manifest(pp)
+    end
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        ensure_newline => false,
+      }
+      concat::fragment { '1':
+        target  => '#{basedir}/file',
+        content => '1',
+      }
+      concat::fragment { '2':
+        target  => '#{basedir}/file',
+        content => '2',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/file") do
+      it { should be_file }
+      its(:content) { should match '12' }
+    end
+  end
+
+  context '=> true' do
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        ensure_newline => true,
+      }
+      concat::fragment { '1':
+        target  => '#{basedir}/file',
+        content => '1',
+      }
+      concat::fragment { '2':
+        target  => '#{basedir}/file',
+        content => '2',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/file") do
+      it { should be_file }
+      its(:content) {
+        should match /1\n2\n/
+      }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/aix-71-vcloud.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+HOSTS:
+  pe-aix-71-acceptance:
+    roles:
+      - master
+      - dashboard
+      - database
+      - agent
+      - default
+    platform: aix-7.1-power
+    hypervisor: aix
+    ip: pe-aix-71-acceptance.delivery.puppetlabs.net
+CONFIG:
+  type: pe
+  nfs_server: NONE
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/centos-59-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-59-x64:
+    roles:
+      - master
+    platform: el-5-x86_64
+    box : centos-59-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/centos-64-x64-pe.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+HOSTS:
+  centos-64-x64:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: el-6-x86_64
+    box : centos-64-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: pe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/centos-64-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-64-x64:
+    roles:
+      - master
+    platform: el-6-x86_64
+    box : centos-64-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/centos-65-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-65-x64:
+    roles:
+      - master
+    platform: el-6-x86_64
+    box : centos-65-x64-vbox436-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/debian-607-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  debian-607-x64:
+    roles:
+      - master
+    platform: debian-6-amd64
+    box : debian-607-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/debian-70rc1-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  debian-70rc1-x64:
+    roles:
+      - master
+    platform: debian-7-amd64
+    box : debian-70rc1-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-70rc1-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/debian-73-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  debian-73-x64.localhost:
+    roles:
+      - master
+    platform: debian-7-amd64
+    box : debian-73-x64-virtualbox-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-73-x64-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  log_level: debug
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/default.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-66-x64:
+    roles:
+      - master
+    platform: el-6-x86_64
+    box : puppetlabs/centos-6.6-64-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-6.6-64-nocm
+    hypervisor : vagrant
+CONFIG:
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/fedora-18-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  fedora-18-x64:
+    roles:
+      - master
+    platform: fedora-18-x86_64
+    box : fedora-18-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/fedora-18-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/sles-11-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  sles-11-x64.local:
+    roles:
+      - master
+    platform: sles-11-x64
+    box : sles-11sp1-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/sles-11sp1-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+    type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/sles-11sp1-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  sles-11sp1-x64:
+    roles:
+      - master
+    platform: sles-11-x86_64
+    box : sles-11sp1-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/sles-11sp1-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-server-10044-x64:
+    roles:
+      - master
+    platform: ubuntu-10.04-amd64
+    box : ubuntu-server-10044-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-server-12042-x64:
+    roles:
+      - master
+    platform: ubuntu-12.04-amd64
+    box : ubuntu-server-12042-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  ubuntu-server-1404-x64:
+    roles:
+      - master
+    platform: ubuntu-14.04-amd64
+    box : puppetlabs/ubuntu-14.04-64-nocm
+    box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm
+    hypervisor : vagrant
+CONFIG:
+  log_level   : debug
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/order_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,123 @@
+require 'spec_helper_acceptance'
+
+describe 'concat order' do
+  basedir = default.tmpdir('concat')
+
+  context '=> ' do
+    shared_examples 'sortby' do |order_by, match_output|
+      pp = <<-EOS
+      concat { '#{basedir}/foo':
+        order => '#{order_by}'
+      }
+      concat::fragment { '1':
+        target  => '#{basedir}/foo',
+        content => 'string1',
+        order   => '1',
+      }
+      concat::fragment { '2':
+        target  => '#{basedir}/foo',
+        content => 'string2',
+        order   => '2',
+      }
+      concat::fragment { '10':
+        target  => '#{basedir}/foo',
+        content => 'string10',
+      }
+      EOS
+
+      it 'applies the manifest twice with no stderr' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      describe file("#{basedir}/foo") do
+        it { should be_file }
+        its(:content) { should match match_output }
+      end
+    end
+
+    describe 'alpha' do
+      it_behaves_like 'sortby', 'alpha', /string10string1string2/
+    end
+
+    describe 'numeric' do
+      it_behaves_like 'sortby', 'numeric', /string1string2string10/
+    end
+  end
+end # concat order
+
+describe 'concat::fragment order' do
+  basedir = default.tmpdir('concat')
+
+  context '=> reverse order' do
+    shared_examples 'order_by' do |order_by, match_output|
+      pp = <<-EOS
+      concat { '#{basedir}/foo':
+          order => '#{order_by}'
+      }
+      concat::fragment { '1':
+        target  => '#{basedir}/foo',
+        content => 'string1',
+        order   => '15',
+      }
+      concat::fragment { '2':
+        target  => '#{basedir}/foo',
+        content => 'string2',
+        # default order 10
+      }
+      concat::fragment { '3':
+        target  => '#{basedir}/foo',
+        content => 'string3',
+        order   => '1',
+      }
+      EOS
+
+      it 'applies the manifest twice with no stderr' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      describe file("#{basedir}/foo") do
+        it { should be_file }
+        its(:content) { should match match_output }
+      end
+    end
+    describe 'alpha' do
+      it_should_behave_like 'order_by', 'alpha', /string2string1string3/
+    end
+    describe 'numeric' do
+      it_should_behave_like 'order_by', 'numeric', /string3string2string1/
+    end
+  end
+
+  context '=> normal order' do
+    pp = <<-EOS
+      concat { '#{basedir}/foo': }
+      concat::fragment { '1':
+        target  => '#{basedir}/foo',
+        content => 'string1',
+        order   => '01',
+      }
+      concat::fragment { '2':
+        target  => '#{basedir}/foo',
+        content => 'string2',
+        order   => '02'
+      }
+      concat::fragment { '3':
+        target  => '#{basedir}/foo',
+        content => 'string3',
+        order   => '03',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/foo") do
+      it { should be_file }
+      its(:content) { should match /string1string2string3/ }
+    end
+  end
+end # concat::fragment order
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/quoted_paths_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+require 'spec_helper_acceptance'
+
+describe 'quoted paths' do
+  basedir = default.tmpdir('concat')
+
+  before(:all) do
+    pp = <<-EOS
+      file { '#{basedir}':
+        ensure => directory,
+      }
+      file { '#{basedir}/concat test':
+        ensure => directory,
+      }
+    EOS
+    apply_manifest(pp)
+  end
+
+  context 'path with blanks' do
+    pp = <<-EOS
+      concat { '#{basedir}/concat test/foo':
+      }
+      concat::fragment { '1':
+        target  => '#{basedir}/concat test/foo',
+        content => 'string1',
+      }
+      concat::fragment { '2':
+        target  => '#{basedir}/concat test/foo',
+        content => 'string2',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/concat test/foo") do
+      it { should be_file }
+      its(:content) { should match /string1string2/ }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/replace_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,262 @@
+require 'spec_helper_acceptance'
+
+describe 'replacement of' do
+  basedir = default.tmpdir('concat')
+  context 'file' do
+    context 'should not succeed' do
+      before(:all) do
+        pp = <<-EOS
+          file { '#{basedir}':
+            ensure => directory,
+          }
+          file { '#{basedir}/file':
+            content => "file exists\n"
+          }
+        EOS
+        apply_manifest(pp)
+      end
+      pp = <<-EOS
+        concat { '#{basedir}/file':
+          replace => false,
+        }
+
+        concat::fragment { '1':
+          target  => '#{basedir}/file',
+          content => '1',
+        }
+
+        concat::fragment { '2':
+          target  => '#{basedir}/file',
+          content => '2',
+        }
+      EOS
+
+      it 'applies the manifest twice with no stderr' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      describe file("#{basedir}/file") do
+        it { should be_file }
+        its(:content) {
+          should match 'file exists'
+          should_not match '1'
+          should_not match '2'
+        }
+      end
+    end
+
+    context 'should succeed' do
+      before(:all) do
+        pp = <<-EOS
+          file { '#{basedir}':
+            ensure => directory,
+          }
+          file { '#{basedir}/file':
+            content => "file exists\n"
+          }
+        EOS
+        apply_manifest(pp)
+      end
+      pp = <<-EOS
+        concat { '#{basedir}/file':
+          replace => true,
+        }
+
+        concat::fragment { '1':
+          target  => '#{basedir}/file',
+          content => '1',
+        }
+
+        concat::fragment { '2':
+          target  => '#{basedir}/file',
+          content => '2',
+        }
+      EOS
+
+      it 'applies the manifest twice with no stderr' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      describe file("#{basedir}/file") do
+        it { should be_file }
+        its(:content) {
+          should_not match 'file exists'
+          should match '1'
+          should match '2'
+        }
+      end
+    end
+  end # file
+
+  context 'symlink', :unless => (fact("osfamily") == "windows") do
+    context 'should not succeed' do
+      # XXX the core puppet file type will replace a symlink with a plain file
+      # when using ensure => present and source => ... but it will not when using
+      # ensure => present and content => ...; this is somewhat confusing behavior
+      before(:all) do
+        pp = <<-EOS
+          file { '#{basedir}':
+            ensure => directory,
+          }
+          file { '#{basedir}/file':
+            ensure => link,
+            target => '#{basedir}/dangling',
+          }
+        EOS
+        apply_manifest(pp)
+      end
+
+      pp = <<-EOS
+        concat { '#{basedir}/file':
+          replace => false,
+        }
+
+        concat::fragment { '1':
+          target  => '#{basedir}/file',
+          content => '1',
+        }
+
+        concat::fragment { '2':
+          target  => '#{basedir}/file',
+          content => '2',
+        }
+      EOS
+
+      it 'applies the manifest twice with no stderr' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      # XXX specinfra doesn't support be_linked_to on AIX
+      describe file("#{basedir}/file"), :unless => (fact("osfamily") == "AIX" or fact("osfamily") == "windows") do
+        it { should be_linked_to "#{basedir}/dangling" }
+      end
+
+      describe file("#{basedir}/dangling") do
+        # XXX serverspec does not have a matcher for 'exists'
+        it { should_not be_file }
+        it { should_not be_directory }
+      end
+    end
+
+    context 'should succeed' do
+      # XXX the core puppet file type will replace a symlink with a plain file
+      # when using ensure => present and source => ... but it will not when using
+      # ensure => present and content => ...; this is somewhat confusing behavior
+      before(:all) do
+        pp = <<-EOS
+          file { '#{basedir}':
+            ensure => directory,
+          }
+          file { '#{basedir}/file':
+            ensure => link,
+            target => '#{basedir}/dangling',
+          }
+        EOS
+        apply_manifest(pp)
+      end
+
+      pp = <<-EOS
+        concat { '#{basedir}/file':
+          replace => true,
+        }
+
+        concat::fragment { '1':
+          target  => '#{basedir}/file',
+          content => '1',
+        }
+
+        concat::fragment { '2':
+          target  => '#{basedir}/file',
+          content => '2',
+        }
+      EOS
+
+      it 'applies the manifest twice with no stderr' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      describe file("#{basedir}/file") do
+        it { should be_file }
+        its(:content) {
+          should match '1'
+          should match '2'
+        }
+      end
+    end
+  end # symlink
+
+  context 'directory' do
+    context 'should not succeed' do
+      before(:all) do
+        pp = <<-EOS
+          file { '#{basedir}':
+            ensure => directory,
+          }
+          file { '#{basedir}/file':
+            ensure => directory,
+          }
+        EOS
+        apply_manifest(pp)
+      end
+      pp = <<-EOS
+        concat { '#{basedir}/file': }
+
+        concat::fragment { '1':
+          target  => '#{basedir}/file',
+          content => '1',
+        }
+
+        concat::fragment { '2':
+          target  => '#{basedir}/file',
+          content => '2',
+        }
+      EOS
+
+      it 'applies the manifest twice with stderr for changing to file' do
+        expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/change from directory to file failed/)
+        expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/change from directory to file failed/)
+      end
+
+      describe file("#{basedir}/file") do
+        it { should be_directory }
+      end
+    end
+
+    # XXX concat's force param currently enables the creation of empty files
+    # when there are no fragments, and the replace param will only replace
+    # files and symlinks, not directories.  The semantics either need to be
+    # changed, extended, or a new param introduced to control directory
+    # replacement.
+    context 'should succeed', :pending => 'not yet implemented' do
+      pp = <<-EOS
+        concat { '#{basedir}/file':
+          force => true,
+        }
+
+        concat::fragment { '1':
+          target  => '#{basedir}/file',
+          content => '1',
+        }
+
+        concat::fragment { '2':
+          target  => '#{basedir}/file',
+          content => '2',
+        }
+      EOS
+
+      it 'applies the manifest twice with no stderr' do
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_changes => true)
+      end
+
+      describe file("#{basedir}/file") do
+        it { should be_file }
+        its(:content) { should match '1' }
+      end
+    end
+  end # directory
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/specinfra_stubs.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+class Specinfra::Command::Windows::Base::File < Specinfra::Command::Windows::Base
+  class << self
+    def check_is_owned_by(file, owner)
+      Backend::PowerShell::Command.new do
+        exec "if((Get-Item '#{file}').GetAccessControl().Owner -match '#{owner}'
+          -or ((Get-Item '#{file}').GetAccessControl().Owner -match '#{owner}').Length -gt 0){ exit 0 } else { exit 1 }"
+      end
+    end
+  end
+end
+
+
+class Specinfra::Command::Base::File < Specinfra::Command::Base
+  class << self
+    def get_content(file)
+      "cat '#{file}' 2> /dev/null || echo -n"
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/symbolic_name_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+require 'spec_helper_acceptance'
+
+describe 'symbolic name' do
+  basedir = default.tmpdir('concat')
+  pp = <<-EOS
+    concat { 'not_abs_path':
+      path => '#{basedir}/file',
+    }
+
+    concat::fragment { '1':
+      target  => 'not_abs_path',
+      content => '1',
+      order   => '01',
+    }
+
+    concat::fragment { '2':
+      target  => 'not_abs_path',
+      content => '2',
+      order   => '02',
+    }
+  EOS
+
+  it 'applies the manifest twice with no stderr' do
+    apply_manifest(pp, :catch_failures => true)
+    apply_manifest(pp, :catch_changes => true)
+  end
+
+  describe file("#{basedir}/file") do
+    it { should be_file }
+    its(:content) {
+      should match '1'
+      should match '2'
+    }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/validation_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+require 'spec_helper_acceptance'
+
+describe 'concat validate_cmd parameter', :unless => (fact('kernel') != 'Linux') do
+  basedir = default.tmpdir('concat')
+  context '=> "/usr/bin/test -e %"' do
+    before(:all) do
+      pp = <<-EOS
+        file { '#{basedir}':
+          ensure => directory
+        }
+      EOS
+
+      apply_manifest(pp)
+    end
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        validate_cmd => '/usr/bin/test -e %',
+      }
+      concat::fragment { 'content':
+        target  => '#{basedir}/file',
+        content => 'content',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/file") do
+      it { should be_file }
+      it { should contain 'content' }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/acceptance/warn_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,104 @@
+require 'spec_helper_acceptance'
+
+describe 'concat warn =>' do
+  basedir = default.tmpdir('concat')
+  context 'true should enable default warning message' do
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        warn  => true,
+      }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/file',
+        content => '1',
+        order   => '01',
+      }
+
+      concat::fragment { '2':
+        target  => '#{basedir}/file',
+        content => '2',
+        order   => '02',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/file") do
+      it { should be_file }
+      its(:content) {
+        should match /# This file is managed by Puppet\. DO NOT EDIT\./
+        should match /1/
+        should match /2/
+      }
+    end
+  end
+  context 'false should not enable default warning message' do
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        warn  => false,
+      }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/file',
+        content => '1',
+        order   => '01',
+      }
+
+      concat::fragment { '2':
+        target  => '#{basedir}/file',
+        content => '2',
+        order   => '02',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/file") do
+      it { should be_file }
+      its(:content) {
+        should_not match /# This file is managed by Puppet\. DO NOT EDIT\./
+        should match /1/
+        should match /2/
+      }
+    end
+  end
+  context '# foo should overide default warning message' do
+    pp = <<-EOS
+      concat { '#{basedir}/file':
+        warn  => '# foo',
+      }
+
+      concat::fragment { '1':
+        target  => '#{basedir}/file',
+        content => '1',
+        order   => '01',
+      }
+
+      concat::fragment { '2':
+        target  => '#{basedir}/file',
+        content => '2',
+        order   => '02',
+      }
+    EOS
+
+    it 'applies the manifest twice with no stderr' do
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    describe file("#{basedir}/file") do
+      it { should be_file }
+      its(:content) {
+        should match /# foo/
+        should match /1/
+        should match /2/
+      }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/spec.opts	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+--format
+s
+--colour
+--loadby
+mtime
+--backtrace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/spec_helper.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+require 'puppetlabs_spec_helper/module_spec_helper'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/spec_helper_acceptance.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,53 @@
+require 'beaker-rspec/spec_helper'
+require 'beaker-rspec/helpers/serverspec'
+require 'acceptance/specinfra_stubs'
+require 'beaker/puppet_install_helper'
+
+run_puppet_install_helper
+
+unless ENV['RS_PROVISION'] == 'no' or ENV['BEAKER_provision'] == 'no'
+  hosts.each do |host|
+    if host['platform'] =~ /sles-1/i || host['platform'] =~ /solaris-1/i
+      get_stdlib = <<-EOS
+      package{'wget':}
+      exec{'download':
+        command => "wget -P /root/ https://forgeapi.puppetlabs.com/v3/files/puppetlabs-stdlib-4.5.1.tar.gz --no-check-certificate",
+        path    => ['/opt/csw/bin/','/usr/bin/']
+      }
+      EOS
+      apply_manifest_on(host, get_stdlib)
+      # have to use force otherwise it checks ssl cert even though it is a local file
+      on host, puppet('module install /root/puppetlabs-stdlib-4.5.1.tar.gz --force --ignore-dependencies'), {:acceptable_exit_codes => [0, 1]}
+    elsif host['platform'] =~ /windows/i
+      on host, shell('curl -k -o c:/puppetlabs-stdlib-4.5.1.tar.gz https://forgeapi.puppetlabs.com/v3/files/puppetlabs-stdlib-4.5.1.tar.gz')
+      on host, puppet('module install c:/puppetlabs-stdlib-4.5.1.tar.gz --force --ignore-dependencies'), {:acceptable_exit_codes => [0, 1]}
+    else
+      on host, puppet('module install puppetlabs-stdlib'), {:acceptable_exit_codes => [0, 1]}
+    end
+  end
+end
+
+RSpec.configure do |c|
+  # Project root
+  proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+  # Readable test descriptions
+  c.formatter = :documentation
+
+  # Configure all nodes in nodeset
+  c.before :suite do
+    hosts.each do |host|
+      copy_module_to(host, :source => proj_root, :module_name => 'concat')
+    end
+  end
+
+  c.before(:all) do
+    shell('mkdir -p /tmp/concat')
+  end
+  c.after(:all) do
+    shell('rm -rf /tmp/concat /var/lib/puppet/concat')
+  end
+
+  c.treat_symbols_as_metadata_keys_with_true_values = true
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/unit/classes/concat_setup_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,98 @@
+require 'spec_helper'
+
+describe 'concat::setup', :type => :class do
+
+  shared_examples 'setup' do |concatdir|
+    concatdir = '/foo' if concatdir.nil?
+
+    let(:facts) do
+      {
+        :concat_basedir     => concatdir,
+        :caller_module_name => 'Test',
+        :osfamily           => 'Debian',
+        :id                 => 'root',
+        :is_pe              => false,
+      }
+    end
+
+    it do
+      should contain_file("#{concatdir}/bin/concatfragments.rb").with({
+        :mode   => '0755',
+        :owner  => 'root',
+        :group  => 0,
+        :source => 'puppet:///modules/concat/concatfragments.rb',
+      })
+    end
+
+    [concatdir, "#{concatdir}/bin"].each do |file|
+      it do
+        should contain_file(file).with({
+          :ensure => 'directory',
+          :mode   => '0755',
+          :owner  => 'root',
+          :group  => 0,
+        })
+      end
+    end
+  end
+
+  context 'facts' do
+    context 'concat_basedir =>' do
+      context '/foo' do
+        it_behaves_like 'setup', '/foo'
+      end
+    end
+  end # facts
+
+  context 'deprecated as a public class' do
+    it 'should create a warning' do
+      skip('rspec-puppet support for testing warning()')
+    end
+  end
+
+  context "on osfamily Solaris" do
+    concatdir = '/foo'
+    let(:facts) do
+      {
+        :concat_basedir     => concatdir,
+        :caller_module_name => 'Test',
+        :osfamily           => 'Solaris',
+        :id                 => 'root',
+        :is_pe              => false,
+      }
+    end
+
+    it do
+      should contain_file("#{concatdir}/bin/concatfragments.rb").with({
+        :ensure => 'file',
+        :owner  => 'root',
+        :group  => 0,
+        :mode   => '0755',
+        :source => 'puppet:///modules/concat/concatfragments.rb',
+      })
+    end
+  end # on osfamily Solaris
+
+  context "on osfamily windows" do
+    concatdir = '/foo'
+    let(:facts) do
+      {
+        :concat_basedir     => concatdir,
+        :caller_module_name => 'Test',
+        :osfamily           => 'windows',
+        :id                 => 'batman',
+        :is_pe              => false,
+      }
+    end
+
+    it do
+      should contain_file("#{concatdir}/bin/concatfragments.rb").with({
+        :ensure => 'file',
+        :owner  => nil,
+        :group  => nil,
+        :mode   => nil,
+        :source => 'puppet:///modules/concat/concatfragments.rb',
+      })
+    end
+  end # on osfamily windows
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/unit/defines/concat_fragment_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,338 @@
+require 'spec_helper'
+
+describe 'concat::fragment', :type => :define do
+
+  shared_examples 'fragment' do |title, params|
+    params = {} if params.nil?
+
+    p = {
+      :content => nil,
+      :source  => nil,
+      :order   => 10,
+      :ensure  => 'present',
+    }.merge(params)
+
+    safe_name        = title.gsub(/[\/\n]/, '_')
+    safe_target_name = p[:target].gsub(/[\/\n]/, '_')
+    concatdir        = '/var/lib/puppet/concat'
+    fragdir          = "#{concatdir}/#{safe_target_name}"
+    id               = 'root'
+    gid              = 'root'
+    if p[:ensure] == 'absent'
+      safe_ensure = p[:ensure] 
+    else
+      safe_ensure = 'file'
+    end
+
+    let(:title) { title }
+    let(:facts) do
+      {
+        :concat_basedir => concatdir,
+        :id             => id,
+        :gid            => gid,
+        :osfamily       => 'Debian',
+        :path           => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :is_pe          => false,
+      }
+    end
+    let(:params) { params }
+    let(:pre_condition) do
+      "concat{ '#{p[:target]}': }"
+    end
+
+    it do
+      should contain_class('concat::setup')
+      should contain_concat(p[:target])
+      should contain_file("#{fragdir}/fragments/#{p[:order]}_#{safe_name}").with({
+        :ensure  => safe_ensure,
+        :owner   => id,
+        :mode    => '0640',
+        :source  => p[:source],
+        :content => p[:content],
+        :alias   => "concat_fragment_#{title}",
+        :backup  => 'puppet',
+      })
+      # The defined() function doesn't seem to work properly with puppet 3.4 and rspec.
+      # defined() works on its own, rspec works on its own, but together they
+      # determine that $gid is not defined and cause errors here. Work around
+      # it by ignoring this check for older puppet version.
+      if Puppet::Util::Package.versioncmp(Puppet.version, '3.5.0') >= 0
+        should contain_file("#{fragdir}/fragments/#{p[:order]}_#{safe_name}").with({
+          :group   => gid,
+        })
+      end
+    end
+  end
+
+  context 'title' do
+    ['0', '1', 'a', 'z'].each do |title|
+      it_behaves_like 'fragment', title, {
+        :target  => '/etc/motd',
+      }
+    end
+  end # title
+
+  context 'target =>' do
+    ['./etc/motd', 'etc/motd', 'motd_header'].each do |target|
+      context target do
+        it_behaves_like 'fragment', target, {
+          :target  => '/etc/motd',
+        }
+      end
+    end
+
+    context 'false' do
+      let(:title) { 'motd_header' }
+      let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }}
+      let(:params) {{ :target => false }}
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a string/)
+      end
+    end
+  end # target =>
+
+  context 'ensure =>' do
+    ['present', 'absent'].each do |ens|
+      context ens do
+        it_behaves_like 'fragment', 'motd_header', {
+          :ensure => ens,
+          :target => '/etc/motd',
+        }
+      end
+    end
+
+    context 'any value other than \'present\' or \'absent\'' do
+      let(:title) { 'motd_header' }
+      let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }}
+      let(:params) {{ :ensure => 'invalid', :target => '/etc/motd' }}
+
+      it 'should create a warning' do
+        skip('rspec-puppet support for testing warning()')
+      end
+    end
+  end # ensure =>
+
+  context 'content =>' do
+    ['', 'ashp is our hero'].each do |content|
+      context content do
+        it_behaves_like 'fragment', 'motd_header', {
+          :content => content,
+          :target  => '/etc/motd',
+        }
+      end
+    end
+
+    context 'false' do
+      let(:title) { 'motd_header' }
+      let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }}
+      let(:params) {{ :content => false, :target => '/etc/motd' }}
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a string/)
+      end
+    end
+  end # content =>
+
+  context 'source =>' do
+    ['', '/foo/bar', ['/foo/bar', '/foo/baz']].each do |source|
+      context source do
+        it_behaves_like 'fragment', 'motd_header', {
+          :source => source,
+          :target => '/etc/motd',
+        }
+      end
+    end
+
+    context 'false' do
+      let(:title) { 'motd_header' }
+      let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }}
+      let(:params) {{ :source => false, :target => '/etc/motd' }}
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a string or an Array/)
+      end
+    end
+  end # source =>
+
+  context 'order =>' do
+    ['', '42', 'a', 'z'].each do |order|
+      context '\'\'' do
+        it_behaves_like 'fragment', 'motd_header', {
+          :order  => order,
+          :target => '/etc/motd',
+        }
+      end
+    end
+
+    context 'false' do
+      let(:title) { 'motd_header' }
+      let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }}
+      let(:params) {{ :order => false, :target => '/etc/motd' }}
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a string or integer/)
+      end
+    end
+
+    context '123:456' do
+      let(:title) { 'motd_header' }
+      let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }}
+      let(:params) {{ :order => '123:456', :target => '/etc/motd' }}
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /cannot contain/)
+      end
+    end
+    context '123/456' do
+      let(:title) { 'motd_header' }
+      let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }}
+      let(:params) {{ :order => '123/456', :target => '/etc/motd' }}
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /cannot contain/)
+      end
+    end
+    context '123\n456' do
+      let(:title) { 'motd_header' }
+      let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }}
+      let(:params) {{ :order => "123\n456", :target => '/etc/motd' }}
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /cannot contain/)
+      end
+    end
+  end # order =>
+
+  context 'more than one content source' do
+    error_msg = 'You cannot specify more than one of $content, $source, $ensure => /target'
+
+    context 'ensure => target and source' do
+      let(:title) { 'motd_header' }
+      let(:facts) do
+        {
+          :concat_basedir => '/tmp',
+          :osfamily       => 'Debian',
+          :id             => 'root',
+          :is_pe          => false,
+          :gid            => 'root',
+        }
+      end
+      let(:params) do
+        {
+          :target  => '/etc/motd',
+          :ensure  => '/foo',
+          :source  => '/bar',
+        }
+      end
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /#{Regexp.escape(error_msg)}/m)
+      end
+    end
+
+    context 'ensure => target and content' do
+      let(:title) { 'motd_header' }
+      let(:facts) do
+        {
+          :concat_basedir => '/tmp',
+          :osfamily       => 'Debian',
+          :id             => 'root',
+          :is_pe          => false,
+          :gid            => 'root',
+        }
+      end
+      let(:params) do
+        {
+          :target  => '/etc/motd',
+          :ensure  => '/foo',
+          :content => 'bar',
+        }
+      end
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /#{Regexp.escape(error_msg)}/m)
+      end
+    end
+
+    context 'source and content' do
+      let(:title) { 'motd_header' }
+      let(:facts) do
+        {
+          :concat_basedir => '/tmp',
+          :osfamily       => 'Debian',
+          :id             => 'root',
+          :is_pe          => false,
+          :gid            => 'root',
+        }
+      end
+      let(:params) do
+        {
+          :target => '/etc/motd',
+          :source => '/foo',
+          :content => 'bar',
+        }
+      end
+
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /#{Regexp.escape(error_msg)}/m)
+      end
+    end
+
+  end # more than one content source
+
+  describe 'deprecated parameter' do
+    context 'mode =>' do
+      context '1755' do
+        it_behaves_like 'fragment', 'motd_header', {
+          :mode   => '1755',
+          :target => '/etc/motd',
+        }
+
+        it 'should create a warning' do
+          skip('rspec-puppet support for testing warning()')
+        end
+      end
+    end # mode =>
+
+    context 'owner =>' do
+      context 'apenny' do
+        it_behaves_like 'fragment', 'motd_header', {
+          :owner  => 'apenny',
+          :target => '/etc/motd',
+        }
+
+        it 'should create a warning' do
+          skip('rspec-puppet support for testing warning()')
+        end
+      end
+    end # owner =>
+
+    context 'group =>' do
+      context 'apenny' do
+        it_behaves_like 'fragment', 'motd_header', {
+          :group  => 'apenny',
+          :target => '/etc/motd',
+        }
+
+        it 'should create a warning' do
+          skip('rspec-puppet support for testing warning()')
+        end
+      end
+    end # group =>
+
+    context 'backup =>' do
+      context 'foo' do
+        it_behaves_like 'fragment', 'motd_header', {
+          :backup => 'foo',
+          :target => '/etc/motd',
+        }
+
+        it 'should create a warning' do
+          skip('rspec-puppet support for testing warning()')
+        end
+      end
+    end # backup =>
+  end # deprecated params
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/unit/defines/concat_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,417 @@
+require 'spec_helper'
+
+describe 'concat', :type => :define do
+
+  shared_examples 'concat' do |title, params, id| 
+    params = {} if params.nil?
+    id = 'root' if id.nil?
+
+    # default param values
+    p = {
+      :ensure         => 'present',
+      :path           => title,
+      :owner          => nil,
+      :group          => nil,
+      :mode           => '0644',
+      :warn           => false,
+      :force          => false,
+      :backup         => 'puppet',
+      :replace        => true,
+      :order          => 'alpha',
+      :ensure_newline => false,
+      :validate_cmd   => nil,
+    }.merge(params)
+
+    safe_name            = title.gsub('/', '_')
+    concatdir            = '/var/lib/puppet/concat'
+    fragdir              = "#{concatdir}/#{safe_name}"
+    concat_name          = 'fragments.concat.out'
+    default_warn_message = '# This file is managed by Puppet. DO NOT EDIT.'
+
+    file_defaults = {
+      :backup  => p[:backup],
+    }
+
+    let(:title) { title }
+    let(:params) { params }
+    let(:facts) do
+      {
+        :concat_basedir => concatdir,
+        :id             => id,
+        :osfamily       => 'Debian',
+        :path           => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
+        :kernel         => 'Linux',
+        :is_pe          => false,
+      }
+    end
+
+    if p[:ensure] == 'present'
+      it do
+        should contain_file(fragdir).with(file_defaults.merge({
+          :ensure => 'directory',
+          :mode   => '0750',
+        }))
+      end
+
+      it do
+        should contain_file("#{fragdir}/fragments").with(file_defaults.merge({
+          :ensure  => 'directory',
+          :mode    => '0750',
+          :force   => true,
+          :ignore  => ['.svn', '.git', '.gitignore'],
+          :purge   => true,
+          :recurse => true,
+        }))
+      end
+
+      [
+        "#{fragdir}/fragments.concat",
+        "#{fragdir}/#{concat_name}",
+      ].each do |file|
+        it do
+          should contain_file(file).with(file_defaults.merge({
+            :ensure => 'present',
+            :mode   => '0640',
+          }))
+        end
+      end
+
+      it do
+        should contain_file(title).with(file_defaults.merge({
+          :ensure       => 'present',
+          :owner        => p[:owner],
+          :group        => p[:group],
+          :mode         => p[:mode],
+          :replace      => p[:replace],
+          :path         => p[:path],
+          :alias        => "concat_#{title}",
+          :source       => "#{fragdir}/#{concat_name}",
+          :validate_cmd => p[:validate_cmd],
+          :backup       => p[:backup],
+        }))
+      end
+
+      cmd = "#{concatdir}/bin/concatfragments.rb " +
+            "-o \"#{concatdir}/#{safe_name}/fragments.concat.out\" " +
+            "-d \"#{concatdir}/#{safe_name}\""
+
+      # flag order: fragdir, warnflag, forceflag, orderflag, newlineflag 
+      if p.has_key?(:warn)
+        case p[:warn]
+        when TrueClass
+          message = default_warn_message
+        when 'true', 'yes', 'on'
+          # should generate a stringified boolean warning
+          message = default_warn_message
+        when FalseClass
+          message = nil
+        when 'false', 'no', 'off'
+          # should generate a stringified boolean warning
+          message = nil
+        else
+          message = p[:warn]
+        end
+
+        unless message.nil?
+          cmd += " -w \'#{message}\'"
+        end
+      end
+
+      cmd += " -f" if p[:force]
+      cmd += " -n" if p[:order] == 'numeric'
+      cmd += " -l" if p[:ensure_newline] == true
+
+      it do
+        should contain_exec("concat_#{title}").with({
+          :alias   => "concat_#{fragdir}",
+          :command => cmd,
+          :unless  => "#{cmd} -t",
+        })
+      end
+    else
+      [
+        fragdir,
+        "#{fragdir}/fragments",
+        "#{fragdir}/fragments.concat",
+        "#{fragdir}/#{concat_name}",
+      ].each do |file|
+        it do
+          should contain_file(file).with(file_defaults.merge({
+            :ensure => 'absent',
+            :force  => true,
+          }))
+        end
+      end
+
+      it do
+        should contain_file(title).with(file_defaults.merge({
+          :ensure => 'absent',
+          :backup => p[:backup],
+        }))
+      end
+
+      it do
+        should contain_exec("concat_#{title}").with({
+          :alias   => "concat_#{fragdir}",
+          :command => 'true',
+          :unless  => 'true',
+          :path    => '/bin:/usr/bin',
+        })
+      end
+    end
+  end
+
+  context 'title' do
+    context 'without path param' do
+      # title/name is the default value for the path param. therefore, the
+      # title must be an absolute path unless path is specified
+      ['/foo', '/foo/bar', '/foo/bar/baz'].each do |title|
+        context title do
+          it_behaves_like 'concat', '/etc/foo.bar'
+        end
+      end
+
+      ['./foo', 'foo', 'foo/bar'].each do |title|
+        context title do
+          let(:title) { title }
+          it 'should fail' do
+            expect { catalogue }.to raise_error(Puppet::Error, /is not an absolute path/)
+          end
+        end
+      end
+    end
+
+    context 'with path param' do
+      ['./foo', 'foo', 'foo/bar'].each do |title|
+        context title do
+          it_behaves_like 'concat', title, { :path => '/etc/foo.bar' }
+        end
+      end
+    end
+  end # title =>
+
+  context 'as non-root user' do
+    it_behaves_like 'concat', '/etc/foo.bar', {}, 'bob'
+  end
+
+  context 'ensure =>' do
+    ['present', 'absent'].each do |ens|
+      context ens do
+        it_behaves_like 'concat', '/etc/foo.bar', { :ensure => ens }
+      end
+    end
+
+    context 'invalid' do
+      let(:title) { '/etc/foo.bar' }
+      let(:params) {{ :ensure => 'invalid' }}
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /#{Regexp.escape('does not match "^present$|^absent$"')}/)
+      end
+    end
+  end # ensure =>
+
+  context 'path =>' do
+    context '/foo' do
+      it_behaves_like 'concat', '/etc/foo.bar', { :path => '/foo' }
+    end
+
+    ['./foo', 'foo', 'foo/bar', false].each do |path|
+      context path do
+        let(:title) { '/etc/foo.bar' }
+        let(:params) {{ :path => path }}
+        it 'should fail' do
+          expect { catalogue }.to raise_error(Puppet::Error, /is not an absolute path/)
+        end
+      end
+    end
+  end # path =>
+
+  context 'owner =>' do
+    context 'apenney' do
+      it_behaves_like 'concat', '/etc/foo.bar', { :owner => 'apenny' }
+    end
+
+    context 'false' do
+      let(:title) { '/etc/foo.bar' }
+      let(:params) {{ :owner => false }}
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a string/)
+      end
+    end
+  end # owner =>
+
+  context 'group =>' do
+    context 'apenney' do
+      it_behaves_like 'concat', '/etc/foo.bar', { :group => 'apenny' }
+    end
+
+    context 'false' do
+      let(:title) { '/etc/foo.bar' }
+      let(:params) {{ :group => false }}
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a string/)
+      end
+    end
+  end # group =>
+
+  context 'mode =>' do
+    context '1755' do
+      it_behaves_like 'concat', '/etc/foo.bar', { :mode => '1755' }
+    end
+
+    context 'false' do
+      let(:title) { '/etc/foo.bar' }
+      let(:params) {{ :mode => false }}
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a string/)
+      end
+    end
+  end # mode =>
+
+  context 'warn =>' do
+    [true, false, '# foo'].each do |warn|
+      context warn do
+        it_behaves_like 'concat', '/etc/foo.bar', { :warn => warn }
+      end
+    end
+
+    context '(stringified boolean)' do
+      ['true', 'yes', 'on', 'false', 'no', 'off'].each do |warn|
+        context warn do
+          it_behaves_like 'concat', '/etc/foo.bar', { :warn => warn }
+
+          it 'should create a warning' do
+            skip('rspec-puppet support for testing warning()')
+          end
+        end
+      end
+    end
+
+    context '123' do
+      let(:title) { '/etc/foo.bar' }
+      let(:params) {{ :warn => 123 }}
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a string or boolean/)
+      end
+    end
+  end # warn =>
+
+  context 'force =>' do
+    [true, false].each do |force|
+      context force do
+        it_behaves_like 'concat', '/etc/foo.bar', { :force => force }
+      end
+    end
+
+    context '123' do
+      let(:title) { '/etc/foo.bar' }
+      let(:params) {{ :force => 123 }}
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a boolean/)
+      end
+    end
+  end # force =>
+
+  context 'backup =>' do
+    context 'reverse' do
+      it_behaves_like 'concat', '/etc/foo.bar', { :backup => 'reverse' }
+    end
+
+    context 'false' do
+      it_behaves_like 'concat', '/etc/foo.bar', { :backup => false }
+    end
+
+    context 'true' do
+      it_behaves_like 'concat', '/etc/foo.bar', { :backup => true }
+    end
+
+    context 'true' do
+      let(:title) { '/etc/foo.bar' }
+      let(:params) {{ :backup => [] }}
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /backup must be string or bool/)
+      end
+    end
+  end # backup =>
+
+  context 'replace =>' do
+    [true, false].each do |replace|
+      context replace do
+        it_behaves_like 'concat', '/etc/foo.bar', { :replace => replace }
+      end
+    end
+
+    context '123' do
+      let(:title) { '/etc/foo.bar' }
+      let(:params) {{ :replace => 123 }}
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a boolean/)
+      end
+    end
+  end # replace =>
+
+  context 'order =>' do
+    ['alpha', 'numeric'].each do |order|
+      context order do
+        it_behaves_like 'concat', '/etc/foo.bar', { :order => order }
+      end
+    end
+
+    context 'invalid' do
+      let(:title) { '/etc/foo.bar' }
+      let(:params) {{ :order => 'invalid' }}
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /#{Regexp.escape('does not match "^alpha$|^numeric$"')}/)
+      end
+    end
+  end # order =>
+
+  context 'ensure_newline =>' do
+    [true, false].each do |ensure_newline|
+      context 'true' do
+        it_behaves_like 'concat', '/etc/foo.bar', { :ensure_newline => ensure_newline}
+      end
+    end
+
+    context '123' do
+      let(:title) { '/etc/foo.bar' }
+      let(:params) {{ :ensure_newline => 123 }}
+      it 'should fail' do
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a boolean/)
+      end
+    end
+  end # ensure_newline =>
+
+  context 'validate_cmd =>' do
+    if Puppet::Util::Package::versioncmp(Puppet::version, '3.5.0') > 0
+      context '/usr/bin/test -e %' do
+        it_behaves_like 'concat', '/etc/foo.bar', { :validate_cmd => '/usr/bin/test -e %' }
+      end
+
+      [ 1234, true ].each do |cmd|
+        context cmd do
+          let(:title) { '/etc/foo.bar' }
+          let(:params) {{ :validate_cmd => cmd }}
+          it 'should fail' do
+            expect { catalogue }.to raise_error(Puppet::Error, /\$validate_cmd must be a string/)
+          end
+        end
+      end
+    end
+  end # validate_cmd =>
+
+  describe 'deprecated parameter' do
+    context 'gnu =>' do
+      context 'foo' do
+        it_behaves_like 'concat', '/etc/foo.bar', { :gnu => 'foo'}
+
+        it 'should create a warning' do
+          skip('rspec-puppet support for testing warning()')
+        end
+      end
+    end
+  end
+
+end
+
+# vim:sw=2:ts=2:expandtab:textwidth=79
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/spec/unit/facts/concat_basedir_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+describe 'concat_basedir', :type => :fact do
+  before(:each) { Facter.clear }
+
+  context 'Puppet[:vardir] ==' do
+    it '/var/lib/puppet' do
+      Puppet.stubs(:[]).with(:vardir).returns('/var/lib/puppet')
+      Facter.fact(:concat_basedir).value.should == '/var/lib/puppet/concat'
+    end
+
+    it '/home/apenny/.puppet/var' do
+      Puppet.stubs(:[]).with(:vardir).returns('/home/apenny/.puppet/var')
+      Facter.fact(:concat_basedir).value.should == '/home/apenny/.puppet/var/concat'
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/tests/fragment.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+concat { 'testconcat':
+  ensure => present,
+  path   => '/tmp/concat',
+  owner  => 'root',
+  group  => 'root',
+  mode   => '0664',
+}
+
+concat::fragment { '1':
+  target  => 'testconcat',
+  content => '1',
+  order   => '01',
+}
+
+concat::fragment { '2':
+  target  => 'testconcat',
+  content => '2',
+  order   => '02',
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/concat/tests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+concat { '/tmp/concat':
+  ensure => present,
+  force  => true,
+  owner  => 'root',
+  group  => 'root',
+  mode   => '0644',
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/Changes	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,61 @@
+0.6.2 Sunday 16th August, 2015
+    Corrected `template_body` error message when template is missing
+    (Github #26 - Robin Bowes)
+    Converted Metadata to metadata.json (Github #23 - Bram Vogelaar)
+
+0.6.1 Tuesday 23rd September, 2014
+    Fix usage with the future parser (Github #16 - Oscar Ferrer)
+
+0.6.0 Monday 16th June, 2014
+    Add ensure to the datacat define (Github #13 - Igor Galić)
+
+0.5.0 Saturday 10th May, 2014
+    Add show_diff to the datacat define for parity with the file
+    type in puppet 3.2 and onwards (Github #10 - Sebastian Schmidt)
+
+0.4.3 Saturday 5th April, 2014
+    Change the README.md back to github-flavoured markdown as the forge
+    supports this now (Github #6 - Igor Galić)
+    Fix for compatibilty with puppet 3.5.0 (Github #7 - Daniel Beyer)
+
+0.4.2 Thursday 26th September, 2013
+    Fix for catalog changes in 3.3.0 when using master/agent (Github #4)
+
+0.4.1 Thursday 8th August, 2013
+    Changes `datacat` define to name the wrapped `file` resource with the
+    $title of the resource itself.
+
+0.4.0 Thursday 25th July, 2013
+    Added `source_key` parameter to datacat_collector, to allow bypassing the
+    templating step.
+
+0.3.0 Tuesday 9th July, 2013
+    Add collects parameter to the datacat_collector type, for acts-as
+    relationships.
+
+0.2.1 Monday 8th July, 2013
+    Bugfix - when modifying the datacat_collector map on path the File should
+    still match to $path
+
+0.2.0 Monday 8th July, 2013
+    Allow the target parameter of a datacat_fragment to be an array to target
+    multiple collectors.
+    The datacat_collector wrapped by the datacat type will now be named for the
+    resource rather than the file path.
+
+0.1.0 Friday 5th July, 2013
+    Add a order parameter to the datacat_fragment type for relative ordering
+    of fragment merging.
+    Exposed the datacat_collector type and allow it to be used for updating
+    more than just the file type's content parameter.
+
+0.0.3 Wednesday 26th June, 2013
+    Reworked the behaviour of datacat_collector to only refresh the resource
+    when the output from the template evaluation changes. (Github #3)
+
+0.0.2 Tuesday 16th April, 2013
+    Changed README.md from Github flavored markup to standard markdown to make
+    the forge happier.
+
+0.0.1 Tuesday 16th April, 2013
+    Initial forge release
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/Gemfile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#!ruby
+source 'https://rubygems.org'
+
+group :development, :test do
+  gem 'rake'
+  gem 'puppetlabs_spec_helper', :require => false
+  gem 'rspec-system-puppet', '~>2.0'
+  gem 'puppet-lint'
+end
+
+group :development do
+  gem 'pry'
+  gem 'pry-debugger'
+  gem 'rb-readline'
+  gem 'awesome_print'
+end
+
+if puppetversion = ENV['PUPPET_GEM_VERSION']
+  gem 'puppet', puppetversion, :require => false
+else
+  gem 'puppet', :require => false
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/NOTES.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+As we're using the rspec fixtures structure, we can run them quite simply
+
+    rake spec_prep
+    puppet apply --modulepath spec/fixtures/modules -e 'include demo1'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/README.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,125 @@
+Puppet types for concatenating data via a template
+==================================================
+
+The `datacat` and `datacat_fragment` types allow you to build up a data
+structure which is rendered using a template.  This is similar to some of the
+common concatenation patterns though the intent should be clearer as it pushes
+the boilerplate down into the type.
+
+[![Build Status](https://travis-ci.org/richardc/puppet-datacat.png)](https://travis-ci.org/richardc/puppet-datacat)
+
+Sample Usage
+------------
+
+```puppet
+datacat { '/etc/nagios/objects/hostgroups.cfg':
+  template => "${module_name}/hostgroups.cfg.erb",
+}
+
+datacat_fragment { "${::fqdn} in device hostgroup":
+  target => '/etc/nagios/objects/hostgroups.cfg',
+  data   => {
+    device => [ $::fqdn ],
+  },
+}
+
+# fred.dc1.notreal has an ilo fred-ilo.dc1.notreal
+$ilo_fqdn = regsubst($::fqdn, '\.', '-ilo.')
+datacat_fragment { "${ilo_fqdn} in device hostgroup":
+  target => '/etc/nagios/objects/hostgroups.cfg',
+  data   => {
+    device => [ $ilo_fqdn ],
+  },
+}
+```
+
+And then in your `hostgroups.cfg.erb`
+
+```erb
+# hostgroups.cfg.erb
+<% @data.keys.sort.each do |hostgroup| %>
+define hostgroup {
+    name <%= hostgroup %>
+    members <%= @data[hostgroup].sort.join(',') %>
+}
+<% end %>
+```
+
+Will produce something like:
+
+```
+# /etc/nagios/objects/hostgroups.cfg
+define hostgroup {
+    name device
+    members fred.dc1.notreal,fred-ilo.dc1.notreal
+}
+```
+
+There are additional samples in a blog post I wrote to describe the approach,
+http://richardc.unixbeard.net/2013/02/puppet-concat-patterns/
+
+Types and Definitions
+---------------------
+
+## Defined Type: `datacat`
+
+Wraps the `datacat_collector` and `file` types to cover the most common
+use-case, collecting data for and templating an entire file.
+
+The `ensure` parameter defaults to `file` (an alias for `present`). `ensure`
+can be set to `absent`. In that case `datacat` will make sure the file *does
+not exist* and will not collect anything with `datacat_collector`.
+
+## Type: `datacat_collector`
+
+The `datacat_collector` type deeply merges a data hash from
+the `datacat_fragment` resources that target it.
+
+These fragments are then rendered via an erb template specified by the
+`template_body` parameter and used to update the `target_field` property
+of the related `target_resource`.
+
+Sample usage:
+
+```puppet
+datacat_collector { 'open_ports':
+  template_body   => '<%= @data["ports"].sort.join(",") %>',
+  target_resource => File_line['open_ports'],
+  target_field    => 'line',
+}
+
+datacat_fragment { 'open webserver':
+  target => 'open_ports',
+  data   => { ports => [ 80, 443 ] },
+}
+
+datacat_fragment { 'open ssh':
+  target => 'open_ports',
+  data   => { ports => [ 22 ] },
+}
+```
+
+Caveats
+-------
+
+The template is evaluated by the agent at the point of catalog evaluation,
+this means you cannot call out to puppet parser functions as you would when
+using the usual `template()` function.
+
+
+Copyright and License
+---------------------
+
+Copyright (C) 2013 Richard Clamp
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/Rakefile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+require 'rubygems'
+require 'bundler/setup'
+
+Bundler.require :default
+
+require 'rspec/core/rake_task'
+require 'puppetlabs_spec_helper/rake_tasks'
+require 'rspec-system/rake_task'
+
+task :default do
+  sh %{rake -T}
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/TODO.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+# Docs
+README.md
+
+# Add the ability for datacat_fragment to load data from files on agent
+
+    # No reason why the datacat_fragment can't load it's data_from a
+    # file on the agents disk
+    datacat_fragment { "hostgroups from yaml file":
+        target => '/etc/nagios/objects/hostgroups.cfg',
+        data_from => '/etc/nagios/build/hostgroups.yaml',
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/checksums.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+{
+  "Changes": "5e97b79bb4cc9a23069a8fcd9f873f59",
+  "Gemfile": "ef832aa81eac5835c29f9cd738b4e8e6",
+  "NOTES.md": "6f1c193c69da469ad266897eb1229982",
+  "README.md": "934ad4d56d867e031c65f8eb03fb11ed",
+  "Rakefile": "790f004b3a18453229b93c23935a4681",
+  "TODO.md": "05bafe2e4d2e1f01bac2c63722e835df",
+  "lib/puppet/parser/functions/template_body.rb": "484e311c79680cd5ab2c608d6c7ef54e",
+  "lib/puppet/provider/datacat_collector/datacat_collector.rb": "6924b9d5a8acab2b07e6a7e9c2107e4a",
+  "lib/puppet/provider/datacat_fragment/datacat_fragment.rb": "785579d50687391eb3a7f12ca396eec3",
+  "lib/puppet/type/datacat_collector.rb": "b08eb6bd3a5096b1fa58d7b88edcb59b",
+  "lib/puppet/type/datacat_fragment.rb": "75f2ee264dcdca35630cc183a594dc8b",
+  "lib/puppet_x/richardc/datacat.rb": "9d577821d01c82e6cbf544cab6650742",
+  "manifests/init.pp": "71c97d31a5c05f4478324d97a952489b",
+  "metadata.json": "67554c5ccc926b277adfb134897d9778",
+  "spec/classes/demo1_spec.rb": "86c043c0769b04015e21655339fafef5",
+  "spec/defines/datacat_spec.rb": "a34f68c0d6926fa5dd4f0b2606ff823d",
+  "spec/fixtures/modules/demo1/manifests/init.pp": "4afa5d2233c0f2c676b6eab8b993e3aa",
+  "spec/fixtures/modules/demo1/templates/sheeps.erb": "31a9e6dc4566ab5277dd36330e9eab30",
+  "spec/fixtures/modules/demo2/manifests/init.pp": "7060abe9b0df5561ca31751c8ad774c8",
+  "spec/fixtures/modules/demo2/templates/merging.erb": "7ed80a01e3df2bfd98d996fcb0a40b3c",
+  "spec/fixtures/modules/demo3/manifests/init.pp": "0a9cf6a8d6fefef9ab8797cdd78e0b9f",
+  "spec/fixtures/modules/demo3/templates/hostgroups.cfg.erb": "5c44ae094f4c401c5a91e98f09c65d65",
+  "spec/fixtures/modules/issue1/manifests/init.pp": "5c1157fc79d7b382148efba3dbd217ee",
+  "spec/fixtures/modules/issue1/templates/refers_to_scope.erb": "67046031e74f04985a15911d0554ba2b",
+  "spec/fixtures/modules/template_body/templates/test1.erb": "9f5a4e389b94ff84426684d87954d47a",
+  "spec/functions/template_body_spec.rb": "956621eeda84fc5e5dd681a889d440fa",
+  "spec/spec_helper.rb": "0db89c9a486df193c0e40095422e19dc",
+  "spec/spec_helper_system.rb": "531394a55dde543ab804c092cb8d00c0",
+  "spec/system/basic_spec.rb": "aaa9c0f55cab9acade54d4394fa7a655",
+  "spec/unit/type/datacat_collector_spec.rb": "d1fd62eb48d4cd93965d8fe6bb1c7dd5"
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/lib/puppet/parser/functions/template_body.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+Puppet::Parser::Functions::newfunction(:template_body, :type => :rvalue) do |args|
+  args.collect do |file|
+    unless filename = Puppet::Parser::Files.find_template(file, self.compiler.environment)
+      raise Puppet::ParseError, "Could not find template '#{file}'"
+    end
+    File.read(filename)
+  end.join('')
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/lib/puppet/provider/datacat_collector/datacat_collector.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,74 @@
+require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'puppet_x', 'richardc', 'datacat.rb'))
+
+Puppet::Type.type(:datacat_collector).provide(:datacat_collector) do
+  def exists?
+    # Find the datacat_fragments that point at this collector
+    our_names = [ resource[:path], resource[:collects] ].flatten.compact
+
+    fragments = resource.catalog.resources.find_all do |r|
+      r.is_a?(Puppet::Type.type(:datacat_fragment)) && ((our_names & [ r[:target] ].flatten).size > 0)
+    end
+
+    # order fragments on their :order property
+    fragments = fragments.sort { |a,b| a[:order] <=> b[:order] }
+
+    # deep merge their data chunks
+    deep_merge = Puppet_X::Richardc::Datacat.deep_merge
+    data = {}
+    fragments.each do |fragment|
+      data.merge!(fragment[:data], &deep_merge)
+    end
+
+    debug "Collected #{data.inspect}"
+
+    if @resource[:source_key]
+      debug "Selecting source_key #{@resource[:source_key]}"
+      content = data[@resource[:source_key]]
+    else
+      vars = Puppet_X::Richardc::Datacat_Binding.new(data, resource[:template])
+
+      debug "Applying template #{@resource[:template]}"
+      template = ERB.new(@resource[:template_body] || '', 0, '-')
+      template.filename = @resource[:template]
+      content = template.result(vars.get_binding)
+    end
+
+    # Find the resource to modify
+    target_resource = resolve_resource(@resource[:target_resource])
+    target_field    = @resource[:target_field].to_sym
+
+    unless target_resource.is_a?(Puppet::Type)
+      raise "Failed to map #{@resource[:target_resource]} into a resource, got to #{target_resource.inspect} of class #{target_resource.class}"
+    end
+
+    debug "Now setting field #{target_field.inspect}"
+    target_resource[target_field] = content
+
+    # and claim there's nothing to change about *this* resource
+    true
+  end
+
+  private
+
+  def resolve_resource(reference)
+    if reference.is_a?(Puppet::Type)
+      # Probably from a unit test, use the resource as-is
+      return reference
+    end
+
+    if reference.is_a?(Puppet::Resource)
+      # Already part resolved - puppet apply?
+      # join it to the catalog where we live and ask it to resolve
+      reference.catalog = resource.catalog
+      return reference.resolve
+    end
+
+    if reference.is_a?(String)
+      # 3.3.0 catalogs you need to resolve like so
+      return resource.catalog.resource(reference)
+    end
+
+    # If we got here, panic
+    raise "Don't know how to convert '#{reference.inspect}' of class #{reference.class} into a resource"
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/lib/puppet/provider/datacat_fragment/datacat_fragment.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+Puppet::Type.type(:datacat_fragment).provide(:datacat_fragment) do
+  mk_resource_methods
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/lib/puppet/type/datacat_collector.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,62 @@
+Puppet::Type.newtype(:datacat_collector) do
+  desc %q{Manages the merging of data and updating a related resource parameter.
+
+  The `datacat_collector` type deeply merges a data hash from
+  the `datacat_fragment` resources that target it.
+
+  These fragments are then rendered via an erb template specified by the
+  `template_body` parameter and used to update the `target_field` property
+  of the related `target_resource`.
+
+  Sample usage:
+
+    datacat_collector { 'open_ports':
+      template_body => '<%= @data["ports"].sort.join(",") %>',
+      target_resource => File_line['open_ports'],
+      target_field    => 'line',
+    }
+
+    datacat_fragment { 'open webserver':
+      target => 'open_ports',
+      data   => { ports => [ 80, 443 ] },
+    }
+
+    datacat_fragment { 'open ssh':
+      target => 'open_ports',
+      data   => { ports => [ 22 ] },
+    }
+
+
+  For convenience the common use case of targeting a file is wrapped in the
+  datacat defined type.}
+
+  ensurable
+
+  newparam(:path, :namevar => true) do
+    desc "An identifier (typically a file path) that can be used by datacat_fragments so they know where to target the data."
+  end
+
+  newparam(:collects) do
+    desc "Other resources we want to collect data from.  Allows for many-many datacats."
+  end
+
+  newparam(:target_resource) do
+    desc "The resource that we're going to set the field (eg File['/tmp/demo']) set theto set data tor"
+  end
+
+  newparam(:target_field) do
+    desc 'The field of the resource to put the results in'
+  end
+
+  newparam(:source_key) do
+    desc 'If specified, the key from @data to copy across to the target_field (bypasses template evaluation)'
+  end
+
+  newparam(:template) do
+    desc 'Path to the template to render.  Used in error reporting.'
+  end
+
+  newparam(:template_body) do
+    desc 'The slurped body of the template to render.'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/lib/puppet/type/datacat_fragment.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+Puppet::Type.newtype(:datacat_fragment) do
+  desc 'A fragment of data for a datacat resource.'
+
+  newparam(:name, :namevar => true) do
+    desc 'The name of this fragment.'
+  end
+
+  newparam(:target) do
+    desc 'The title of the datacat resource that the data should be considered part of.  May be an array to indicate multiple targetted collectors.'
+  end
+
+  newparam(:order) do
+    desc 'The order in which to merge this fragment into the datacat resource.  Defaults to the string "50"'
+    defaultto "50"
+  end
+
+  newparam(:data) do
+    desc 'A hash of data to be merged for this resource.'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/lib/puppet_x/richardc/datacat.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+module Puppet_X
+  module Richardc
+    class Datacat
+      def self.deep_merge
+        deep_merge = Proc.new do |key,oldval,newval|
+          newval.is_a?(Hash) && oldval.is_a?(Hash) ?
+            oldval.merge(newval, &deep_merge) :
+              newval.is_a?(Array) && oldval.is_a?(Array) ?
+                oldval + newval :
+                newval
+        end
+      end
+    end
+
+    # Our much simpler version of Puppet::Parser::TemplateWrapper
+    class Datacat_Binding
+      def initialize(d, template)
+        @data = d
+        @__file__ = template
+      end
+
+      def file
+        @__file__
+      end
+
+      # Find which line in the template (if any) we were called from.
+      # @return [String] the line number
+      # @api private
+      def script_line
+        identifier = Regexp.escape(@__file__ || "(erb)")
+        (caller.find { |l| l =~ /#{identifier}:/ }||"")[/:(\d+):/,1]
+      end
+      private :script_line
+
+      def method_missing(name, *args)
+        line_number = script_line
+        raise "Could not find value for '#{name}' #{@__file__}:#{line_number}"
+      end
+
+      def get_binding
+        binding()
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,95 @@
+# Definition: datacat
+#
+# This definition allows you to declare datacat managed files.
+#
+# Parameters:
+# All parameters are as for the file type, with the addition of a $template
+# parameter which is a path to a template to be used as the content of the
+# file.
+#
+# Sample Usage:
+#  datacat { '/etc/motd':
+#    owner => 'root',
+#    group => 'root,
+#    template => 'motd/motd.erb',
+#  }
+#
+define datacat(
+  $ensure                  = 'file',
+  $template                = undef,
+  $template_body           = undef,
+  $collects                = [],
+  $backup                  = undef,
+  $checksum                = undef,
+  $force                   = undef,
+  $group                   = undef,
+  $owner                   = undef,
+  $mode                    = undef,
+  $path                    = $title,
+  $replace                 = undef,
+  $selinux_ignore_defaults = undef,
+  $selrange                = undef,
+  $selrole                 = undef,
+  $seltype                 = undef,
+  $seluser                 = undef,
+  $show_diff               = 'UNSET'
+) {
+  if $show_diff != 'UNSET' {
+    if versioncmp($settings::puppetversion, '3.2.0') >= 0 {
+      File { show_diff => $show_diff }
+    } else {
+      warning('show_diff not supported in puppet prior to 3.2, ignoring')
+    }
+  }
+
+  # we could validate ensure by simply passing it to file, but unfortunately
+  # someone could try to be smart and pass 'directory', so we only allow a limited range
+  if $ensure != 'absent' and $ensure != 'present' and $ensure != 'file' {
+    fail("Datacat[${title}] invalid value for ensure")
+  }
+
+  if $ensure == 'absent' {
+    file { $title:
+      ensure                  => $ensure,
+      path                    => $path,
+      backup                  => $backup,
+      force                   => $force,
+    }
+  } else {
+    file { $title:
+      path                    => $path,
+      backup                  => $backup,
+      checksum                => $checksum,
+      content                 => "To be replaced by datacat_collector[${title}]\n",
+      force                   => $force,
+      group                   => $group,
+      mode                    => $mode,
+      owner                   => $owner,
+      replace                 => $replace,
+      selinux_ignore_defaults => $selinux_ignore_defaults,
+      selrange                => $selrange,
+      selrole                 => $selrole,
+      seltype                 => $seltype,
+      seluser                 => $seluser,
+    }
+
+    $template_real = $template ? {
+      undef   => 'inline',
+      default => $template,
+    }
+
+    $template_body_real = $template_body ? {
+      undef   => template_body($template_real),
+      default => $template_body,
+    }
+
+    datacat_collector { $title:
+      template        => $template_real,
+      template_body   => $template_body_real,
+      target_resource => File[$title], # when we evaluate we modify the private data of this resource
+      target_field    => 'content',
+      collects        => $collects,
+      before          => File[$title], # we want to evaluate before that resource so it can do the work
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/metadata.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+{
+  "name": "richardc-datacat",
+  "version": "0.6.2",
+  "author": "Richard Clamp",
+  "summary": "Puppet type for handling data fragments",
+  "license": "Apache-2.0",
+  "source": "https://github.com/richardc/puppet-datacat",
+  "project_page": "https://github.com/richardc/puppet-datacat",
+  "issues_url": "https://github.com/richardc/puppet-datacat/issues",
+  "description": "A pair of types for handling data fragments and templating",
+  "dependencies": [
+  
+  ]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/classes/demo1_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+require 'spec_helper'
+
+describe 'demo1' do
+  it { should create_notify('demo1') }
+  it { should create_datacat('/tmp/demo1').with_template('demo1/sheeps.erb') }
+  it { should create_datacat_fragment('data foo => 1').with_data({'foo'=>'1'}) }
+  it { should create_datacat_fragment('data bar => 2').with_data({'bar'=>'2'}) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/defines/datacat_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe "datacat" do
+  context "specifying template by path" do
+    let(:title) { 'test' }
+    let(:params) { { :template => "demo1/sheeps.erb" } }
+    it { should contain_datacat_collector('test') }
+    it { should contain_datacat_collector('test').with_template('demo1/sheeps.erb') }
+    it { should contain_datacat_collector('test').with_template_body(/baah/) }
+  end
+
+  context "specifying template by body" do
+    let(:title) { 'test' }
+    let(:params) { { :template_body => "# Baah!" } }
+    it { should contain_datacat_collector('test') }
+    it { should contain_datacat_collector('test').with_template('inline') }
+    it { should contain_datacat_collector('test').with_template_body(/Baah/) }
+  end
+
+  context "specifying ensure absent" do
+    let(:title) { 'no-file' }
+    let(:params) { { :ensure => "absent" } }
+    it { should_not contain_datacat_collector('no-file') }
+    it { should contain_file('no-file') }
+    it { should contain_file('no-file').with_ensure('absent') }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/fixtures/modules/demo1/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+class demo1 {
+  notify { 'demo1': }
+
+  datacat { '/tmp/demo1':
+    template => 'demo1/sheeps.erb',
+  }
+
+  datacat_fragment { 'data foo => 1':
+    target => '/tmp/demo1',
+    data   => { foo => 1 },
+  }
+
+  datacat_fragment { 'data bar => 2':
+    target => '/tmp/demo1',
+    data   => { bar => 2 },
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/fixtures/modules/demo1/templates/sheeps.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+# This is a super simple demonstration - baah!
+
+<%= @data.to_yaml %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/fixtures/modules/demo2/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+class demo2 {
+  notify { 'demo2': }
+
+  datacat { '/tmp/demo2':
+    template => 'demo2/merging.erb',
+  }
+
+  datacat_fragment { 'data foo => 1, 2':
+    target => '/tmp/demo2',
+    data   => { foo => [ 1, 2 ] },
+  }
+
+  datacat_fragment { 'data foo => 2, 3':
+    target => '/tmp/demo2',
+    data   => { foo => [ 2, 3 ] },
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/fixtures/modules/demo2/templates/merging.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,2 @@
+data.foo should be a merged array <%= @data['foo'].join(', ') %>
+and we can uniq it <%= @data['foo'].uniq.join(', ') %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/fixtures/modules/demo3/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#
+class demo3 {
+  datacat { '/tmp/demo3':
+    template => 'demo3/hostgroups.cfg.erb',
+  }
+
+  $host1 = 'foo.example.com'
+  datacat_fragment { 'foo host':
+    target => '/tmp/demo3',
+    data   => {
+      device => [ $host1 ],
+    },
+  }
+
+  $ilo_fqdn = 'foo-ilo.example.com'
+  datacat_fragment { 'foo ilo':
+    target => '/tmp/demo3',
+    data   => {
+      device => [ $ilo_fqdn ],
+    },
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/fixtures/modules/demo3/templates/hostgroups.cfg.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+# hostgroups.cfg.erb
+<% @data.keys.sort.each do |hostgroup| %>
+define hostgroup {
+    name <%= hostgroup %>
+    members <%= @data[hostgroup].sort.join(',') %>
+}
+<% end %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/fixtures/modules/issue1/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+# This should repo the scope error from github issue #1
+class issue1 {
+  datacat { "/tmp/issue1.1":
+    template => "issue1/refers_to_scope.erb",
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/fixtures/modules/issue1/templates/refers_to_scope.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+We don't expect this to actually work as scope is only avilable to
+templates evaluated by the template() function.
+
+It should however say that it's line 7 of refers_to_scope.erb in the error
+that is raised.
+
+<%= scope.lookupvar("pies") %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/fixtures/modules/template_body/templates/test1.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+Goodbye cruel world
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/functions/template_body_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+require 'spec_helper'
+
+describe 'template_body' do
+  it { should run.with_params('template_body/really_should_never_exist.erb').and_raise_error(Puppet::ParseError, /Could not find template 'template_body\/really_should_never_exist.erb'/) }
+  it { should run.with_params('template_body/test1.erb').and_return("Goodbye cruel world\n") }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/spec_helper.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+require 'puppetlabs_spec_helper/module_spec_helper'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/spec_helper_system.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+require 'rspec-system/spec_helper'
+require 'rspec-system-puppet/helpers'
+
+include RSpecSystemPuppet::Helpers
+
+RSpec.configure do |c|
+  proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+  # Enable colour in Jenkins
+  c.tty = true
+
+  c.include RSpecSystemPuppet::Helpers
+
+  c.before :suite do
+    puppet_install
+    puppet_master_install
+
+    puppet_module_install(:source => proj_root, :module_name => 'datacat')
+    puppet_module_install(:source => proj_root + '/spec/fixtures/modules/demo1', :module_name => 'demo1')
+    puppet_module_install(:source => proj_root + '/spec/fixtures/modules/demo2', :module_name => 'demo2')
+    puppet_module_install(:source => proj_root + '/spec/fixtures/modules/demo3', :module_name => 'demo3')
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/system/basic_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,58 @@
+require 'spec_helper_system'
+
+describe 'basic tests:' do
+  # Using puppet_apply as a subject
+  context puppet_apply 'notice("foo")' do
+    its(:stdout) { should =~ /foo/ }
+    its(:stderr) { should be_empty }
+    its(:exit_code) { should be_zero }
+  end
+
+  # Using puppet_apply as a helper
+  it 'my class should work with no errors' do
+    pp = <<-EOS
+      datacat { "/tmp/demo1":
+        template_body => "<% @data.keys.sort.each do |k| %><%= k %>: <%= @data[k] %>, <% end %>",
+      }
+
+      datacat_fragment { "foo":
+        target => '/tmp/demo1',
+        data => { foo => "one" },
+      }
+
+      datacat_fragment { "bar":
+        target => '/tmp/demo1',
+        data => { bar => "two" },
+      }
+
+      exec { '/bin/echo I have changed':
+         refreshonly => true,
+         subscribe => Datacat["/tmp/demo1"],
+      }
+    EOS
+
+    # Run it twice and test for idempotency
+    puppet_apply(pp) do |r|
+      r.exit_code.should_not == 1
+      r.refresh
+      r.exit_code.should be_zero
+    end
+
+    shell('cat /tmp/demo1') do |r|
+      r.stdout.should =~ /^bar: two, foo: one/
+    end
+  end
+
+  it 'should run the example from the documentation via a master' do
+    shell 'sudo sh -c "echo include demo3 > /etc/puppet/manifests/site.pp"'
+    puppet_agent(:debug => true) do |r|
+      r.exit_code.should_not == 1
+      r.refresh
+      r.exit_code.should be_zero
+    end
+
+    shell('cat /tmp/demo3') do |r|
+      r.stdout.should =~ /\s+name device\n\s+members foo-ilo.example.com,foo.example.com/
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/datacat/spec/unit/type/datacat_collector_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,163 @@
+require 'spec_helper'
+
+describe Puppet::Type.type(:datacat_collector) do
+  context "simple merging" do
+    before :each do
+      @catalog = Puppet::Resource::Catalog.new
+      @file = Puppet::Type.type(:file).new(:path => '/test')
+      @catalog.add_resource @file
+
+      @collector = Puppet::Type.type(:datacat_collector).new({
+        :title => "/test",
+        :template_body => '<%= @data.keys.sort.map { |x| "#{x}=#{@data[x]}" }.join(",") %>',
+        :target_resource => @file,
+        :target_field => :content,
+        :collects => [ '/secret-name' ],
+      })
+      @catalog.add_resource @collector
+    end
+
+    it "should do work when exists?" do
+      @file.expects(:[]=).with(:content, "")
+      @collector.provider.exists?
+    end
+
+    it "should combine one hash" do
+      @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+        :title => "hash one",
+        :target => '/test',
+        :data => { "foo" => "one" },
+      })
+
+      @file.expects(:[]=).with(:content, "foo=one")
+      @collector.provider.exists?
+    end
+
+    it "should combine two hashes, disjunct keys" do
+      @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+        :title => "hash one",
+        :target => '/test',
+        :data => { "alpha" => "one" },
+      })
+      @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+        :title => "hash two",
+        :target => '/test',
+        :data => { "bravo" => "two" },
+      })
+
+      @file.expects(:[]=).with(:content, "alpha=one,bravo=two")
+      @collector.provider.exists?
+    end
+
+    describe "ordering" do
+      it "should support explicit orderings 10 20" do
+        @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+          :title => "hash one",
+          :order => "10",
+          :target => '/test',
+          :data => { "alpha" => "one" },
+        })
+        @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+          :title => "hash two",
+          :order => "20",
+          :target => '/test',
+          :data => { "alpha" => "two" },
+        })
+
+        @file.expects(:[]=).with(:content, "alpha=two")
+        @collector.provider.exists?
+      end
+
+      it "should support explicit orderings 30 10" do
+        @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+          :title => "hash one",
+          :order => "30",
+          :target => '/test',
+          :data => { "alpha" => "one" },
+        })
+        @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+          :title => "hash two",
+          :order => "10",
+          :target => '/test',
+          :data => { "alpha" => "two" },
+        })
+
+        @file.expects(:[]=).with(:content, "alpha=one")
+        @collector.provider.exists?
+      end
+
+      it "should support implicit ordering '50' 10" do
+        @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+          :title => "hash one",
+          :target => '/test',
+          :data => { "alpha" => "one" },
+        })
+        @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+          :title => "hash two",
+          :order => "10",
+          :target => '/test',
+          :data => { "alpha" => "two" },
+        })
+
+        @file.expects(:[]=).with(:content, "alpha=one")
+        @collector.provider.exists?
+      end
+    end
+
+    describe "targeting multiple collectors" do
+      it "should support an array in the target attribute" do
+        @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+          :title => "target two",
+          :target => [ "/test", "/othertest" ],
+          :data => { "alpha" => "one" },
+        })
+
+        @file.expects(:[]=).with(:content, "alpha=one")
+        @collector.provider.exists?
+      end
+    end
+
+    describe "collects parameter" do
+      it "should be able to collect for things targeted via the collects parameter" do
+        @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+          :title => "target two",
+          :target => "/secret-name",
+          :data => { "alpha" => "one" },
+        })
+
+        @file.expects(:[]=).with(:content, "alpha=one")
+        @collector.provider.exists?
+      end
+    end
+
+    describe "source_key parameter" do
+      before :each do
+        @source_key_collector = Puppet::Type.type(:datacat_collector).new({
+          :title => "/source_key",
+          :target_resource => @file,
+          :target_field => :source,
+          :source_key => 'source_path',
+        })
+        @catalog.add_resource @source_key_collector
+      end
+
+      it "should set an array when asked" do
+        @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+          :title => "target one",
+          :order => "10",
+          :target => "/source_key",
+          :data => { "source_path" => [ "one" ] },
+        })
+        @catalog.add_resource Puppet::Type.type(:datacat_fragment).new({
+          :title => "target two",
+          :order => "20",
+          :target => "/source_key",
+          :data => { "source_path" => [ "two" ] },
+        })
+
+        @file.expects(:[]=).with(:source, [ 'one', 'two' ])
+        @source_key_collector.provider.exists?
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/.fixtures.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+fixtures:
+  repositories:
+    stdlib:
+      repo: https://github.com/puppetlabs/puppetlabs-stdlib.git
+      branch: '4.7.x'
+    apt:
+      repo: 'https://github.com/puppetlabs/puppetlabs-apt.git'
+      branch: '2.2.x'
+    zypprepo: https://github.com/deadpoint/puppet-zypprepo.git
+    yum: https://github.com/CERIT-SC/puppet-yum.git
+    datacat: https://github.com/richardc/puppet-datacat.git
+  symlinks:
+    elasticsearch: "#{source_dir}"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/.gitignore	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+.swp
+spec/fixtures/manifests
+spec/fixtures/modules
+.bundle
+.vendor
+.vagrant
+.ruby-version
+pkg/
+spec/reports/
+spec/logs
+log
+*.lock
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/.pmtignore	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+spec/
+Rakefile
+junit/
+logs/
+Gemfile
+Gemfile.lock
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/CHANGELOG.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,446 @@
+##0.10.1 ( Dec 17, 2015 )
+
+###Summary
+Bugfix release for proxy functionality in plugin installation
+
+####Features
+
+####Bugfixes
+* Proxy settings were not passed on correctly
+
+####Changes
+* Cleanup .pmtignore to exclude more files
+
+####Testing changes
+
+####Known bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+
+##0.10.0 ( Dec 14, 2015 )
+
+###Summary
+Module now works with ES 2.x completely
+
+####Features
+* Work with ES 2.x new plugin system and remain to work with 1.x
+* Implemented datacat module from Richard Clamp so other modules can hook into it for adding configuration options
+* Fixed init and systemd files to work with 1.x and 2.x
+* Made the module work with newer pl-apt module versions
+* Export es_include so it is passed on to ES
+* Ability to supply long gpg key for apt repo
+
+####Bugfixes
+* Documentation and typographical fixes
+* Do not force puppet:/// schema resource
+* Use package resource defaults rather than setting provider and source
+
+####Changes
+
+####Testing changes
+* Improve unit testing and shorten the runtime
+
+####Known bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+
+##0.9.9 ( Sep 01, 2015 )
+
+###Summary
+Bugfix release and extra features
+
+####Features
+* Work with ES 2.x
+* Add Java 8 detection in debian init script
+* Improve offline plugin installation
+
+####Bugfixes
+* Fix a bug with new ruby versions but older puppet versions causing type error
+* Fix config tempate to use correct ruby scoping
+* Fix regex retrieving proxy port while downloading plugin
+* Fix systemd template for better variable handling
+* Template define was using wrong pathing for removal
+
+
+####Changes
+
+####Testing changes
+
+####Known bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+
+##0.9.8 ( Jul 07, 2015 )
+
+###Summary
+
+
+####Features
+* Work with ES 2.x
+
+####Bugfixes
+* Fix plugin to maintain backwards compatibility
+
+####Changes
+
+####Testing changes
+* ensure testing works with Puppet 4.x ( Rspec and Acceptance )
+
+####Known bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+
+##0.9.7 ( Jun 24, 2015 )
+
+###Summary
+This releases adds several important features and fixes an important plugin installation issue with ES 1.6 and higher.
+
+####Features
+* Automate plugin dir extraction
+* use init service provider for Amazon Linux
+* Add Puppetlabs/apt and ceritsc/yum as required modules
+* Added Timeout to fetching facts in case ES does not respond
+* Add proxy settings for package download
+
+####Bugfixes
+* Fixed systemd template to fix issue with LimitMEMLOCK setting
+* Improve package version handling when specifying a version
+* Add tmpfiles.d file to manage sub dir in /var/run path
+* Fix plugin installations for ES 1.6 and higher
+
+####Changes
+* Removed Modulefile, only maintaining metadata.json file
+
+####Testing changes
+* Added unit testing for package pinning feature
+* Added integration testing with Elasticsearch to find issues earlier
+* Fix OpenSuse 13 testing
+
+####Known bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+
+##0.9.6 ( May 28, 2015 )
+
+###Summary
+Bugfix release 0.9.6
+
+####Features
+* Implemented package version pinning to avoid accidental upgrading
+* Added support for Debian 8
+* Added support for upgrading plugins
+* Managing LimitNOFILE and LimitMEMLOCK settings in systemd
+
+####Bugfixes
+
+####Changes
+* Dropped official support for PE 3.1.x and 3.2.x
+
+####Testing changes
+* Several testing changes implemented to increase coverage
+
+####Known bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+
+##0.9.5( Apr 16, 2015 )
+
+###Summary
+Bugfix release 0.9.5
+
+We reverted the change that implemented the full 40 character for the apt repo key.
+This caused issues with some older versions of the puppetlabs-apt module
+
+####Features
+
+####Bugfixes
+* Revert using the full 40 character for the apt repo key.
+
+####Changes
+
+####Testing changes
+
+####Known bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+
+##0.9.4( Apr 14, 2015 )
+
+###Summary
+Bugfix release 0.9.4
+
+####Features
+* Add the ability to create and populate scripts
+
+####Bugfixes
+* add support for init_defaults_file to elasticsearch::instance
+* Update apt key to full 40characters
+
+####Changes
+* Fix readme regarding module_dir with plugins
+
+####Testing changes
+* Adding staged removal test
+* Convert git urls to https
+* Add centos7 node config
+
+####Known bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+
+##0.9.3( Mar 24, 2015 )
+
+###Summary
+Bugfix release 0.9.3
+
+####Features
+
+####Bugfixes
+* Not setting repo_version did not give the correct error
+* Systemd file did not contain User/Group values
+
+####Changes
+* Brand rename from Elasticsearch to Elastic
+
+####Testing changes
+* Moved from multiple Gemfiles to single Gemfile
+
+####Known bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+##0.9.2( Mar 06, 2015 )
+
+###Summary
+Bugfix release 0.9.2
+
+####Features
+* Introducing es_instance_conn_validator resource to verify instance availability
+
+####Bugfixes
+* Fix missing data path when using the path config setting but not setting the data path
+
+####Changes
+None
+
+####Testing changes
+None
+
+####Known bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+##0.9.1 ( Feb 23, 2015 )
+
+###Summary
+This is the first bug fix release for 0.9 version.
+A bug was reported with the recursive file management.
+
+####Features
+None
+
+####Bugfixes
+* Fix recursive file management
+* Set undefined variables to work with strict_variables
+
+####Changes
+None
+
+####Testing changes
+None
+
+####Known bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+##0.9.0 ( Feb 02, 2015 )
+
+###Summary
+This release is the first one towards 1.0 release.
+Our planning is to provide LTS releases with the puppet module
+
+####Features
+* Support for using hiera to define instances and plugins.
+* Support for OpenSuSE 13.x
+* Custom facts about the installed Elasticsearch instance(s)
+* Proxy host/port support for the plugin installation
+* Ability to supply a custom logging.yml template
+
+####Bugfixes
+* Ensure file owners are correct accross all related files
+* Fix of possible service name conflict
+* Empty main config would fail with instances
+* Removal of standard files from packages we dont use
+* Ensuring correct sequence of plugin and template defines
+* Added ES_CLASSPATH export to init scripts
+
+####Changes
+* Java installation to use puppetlabs-java module
+* Added Support and testing for Puppet 3.7 and PE 3.7
+* Improve metadata.json based on scoring from Forge
+
+
+####Testing changes
+* Added testing against Puppet 3.7 and PE 3.7
+* Using rspec3
+* Using rspec-puppet-facts gem simplifies rspec testing
+
+####Known Bugs
+* Possible package conflicts when using ruby/python defines with main package name
+
+##0.4.0 ( Jun 18, 2014 ) - Backwards compatible breaking release
+
+###Summary
+This release introduces instances to facilitate the option to have more then a single instance running on the host system.
+
+####Features
+* Rewrite module to incorperate multi instance support
+* New readme layout
+
+####Bugfixes
+* None
+
+####Changes
+* Adding ec2-linux osfamily for repo management
+* Retry behaviour for plugin installation
+
+####Testing changes
+* Adding Puppet 3.6.x testing
+* Ubuntu 14.04 testing
+* Using new docker images
+* Pin rspec to 2.14.x
+
+####Known Bugs
+* No known bugs
+
+##0.3.2 ( May 15, 2014 )
+*  Add support for SLC/Scientific Linux CERN ( PR #121 )
+*  Add support for custom package names ( PR #122 )
+*  Fix python and ruby client defines to avoid name clashes.
+*  Add ability to use stage instead of anchor for repo class
+*  Minor fixes to system tests
+
+##0.3.1 ( April 22, 2014 )
+*  Ensure we create the plugin directory before installing plugins
+*  Added Puppet 3.5.x to rspec and system tests
+
+##0.3.0 ( April 2, 2014 )
+*  Fix minor issue with yumrepo in repo class ( PR #92 )
+*  Implement OpenSuse support
+*  Implement Junit reporting for tests
+*  Adding more system tests and convert to Docker images
+*  Use Augeas for managing the defaults file
+*  Add retry to package download exec
+*  Add management to manage the logging.yml file
+*  Improve inline documentation
+*  Improve support for Debian 6
+*  Improve augeas for values with spaces
+*  Run plugin install as ES user ( PR #108 )
+*  Fix rights for the plugin directory
+*  Pin Rake for Ruby 1.8.7
+*  Adding new metadata for Forge.
+*  Increase time for retry to insert the template
+
+##0.2.4 ( Feb 21, 2014 )
+*  Set puppetlabs-stdlib dependency version from 3.0.0 to 3.2.0 to be inline with other modules
+*  Let puppet run fail when template insert fails
+*  Documentation improvements ( PR #77, #78, #83 )
+*  Added beaker system tests
+*  Fixed template define after failing system tests
+*  Some fixes so variables are more inline with intended structure
+
+##0.2.3 ( Feb 06, 2014 )
+*  Add repository management feature
+*  Improve testing coverage and implement basic resource coverage reporting
+*  Add puppet 3.4.x testing
+*  Fix dependency in template define ( PR #72 )
+*  For apt repo change from key server to key file
+
+##0.2.2 ( Jan 23, 2014 )
+*  Ensure exec names are unique. This caused issues when using our logstash module
+*  Add spec tests for plugin define
+
+##0.2.1 ( Jan 22, 2014 )
+*  Simplify the management of the defaults file ( PR #64 )
+*  Doc improvements for the plugin define ( PR #66 )
+*  Allow creation of data directory ( PR #68 )
+*  Fail early when package version and package_url are defined
+
+##0.2.0 ( Nov 19, 2013 )
+*  Large rewrite of the entire module described below
+*  Make the core more dynamic for different service providers and multi instance capable
+*  Add better testing and devided into different files
+*  Fix template function. Replace of template is now only done when the file is changed
+*  Add different ways to install the package except from the repository ( puppet/http/https/ftp/file )
+*  Update java class to install openjdk 1.7
+*  Add tests for python function
+*  Update config file template to fix scoping issue ( from PR #57 )
+*  Add validation of templates
+*  Small changes for preperation for system tests
+*  Update readme for new functionality
+*  Added more test scenario's
+*  Added puppet parser validate task for added checking
+*  Ensure we don't add stuff when removing the module
+*  Update python client define
+*  Add ruby client define
+*  Add tests for ruby clients and update python client tests
+
+##0.1.3 ( Sep 06, 2013 )
+*  Exec path settings has been updated to fix warnings ( PR #37, #47 )
+*  Adding define to install python bindings ( PR #43 )
+*  Scope deprecation fixes ( PR #41 )
+*  feature to install plugins ( PR #40 )
+
+##0.1.2 ( Jun 21, 2013 )
+*  Update rake file to ignore the param inherit
+*  Added missing documentation to the template define
+*  Fix for template define to allow multiple templates ( PR #36 by Bruce Morrison )
+
+##0.1.1 ( Jun 14, 2013 )
+*  Add Oracle Linux to the OS list ( PR #25 by Stas Alekseev )
+*  Respect the restart_on_change on the defaults ( PR #29 by Simon Effenberg )
+*  Make sure the config can be empty as advertised in the readme
+*  Remove dependency cycle when the defaults file is updated ( PR #31 by Bruce Morrison )
+*  Enable retry on the template insert in case ES isn't started yet ( PR #32 by Bruce Morrison )
+*  Update templates to avoid deprecation notice with Puppet 3.2.x
+*  Update template define to avoid auto insert issue with ES
+*  Update spec tests to reflect changes to template define
+
+##0.1.0 ( May 09, 2013 )
+*  Populate .gitignore ( PR #19 by Igor Galić )
+*  Add ability to install initfile ( PR #20 by Justin Lambert )
+*  Add ability to manage default file service parameters ( PR #21 by Mathieu Bornoz )
+*  Providing complete containment of the module ( PR #24 by Brian Lalor )
+*  Add ability to specify package version ( PR #25 by Justin Lambert )
+*  Adding license file
+
+##0.0.7 ( Mar 23, 2013 )
+*  Ensure config directory is created and managed ( PR #13 by Martin Seener )
+*  Dont backup package if it changes
+*  Create explicit dependency on template directory ( PR #16 by Igor Galić )
+*  Make the config directory variable ( PR #17 by Igor Galić and PR #18 by Vincent Janelle )
+*  Fixing template define
+
+##0.0.6 ( Mar 05, 2013 )
+*  Fixing issue with configuration not printing out arrays
+*  New feature to write the config hash shorter
+*  Updated readme to reflect the new feature
+*  Adding spec tests for config file generation
+
+##0.0.5 ( Mar 03, 2013 )
+*  Option to disable restart on config file change ( PR #10 by Chris Boulton )
+
+##0.0.4 ( Mar 02, 2013 )
+*  Fixed a major issue with the config template ( Issue #9 )
+
+##0.0.3 ( Mar 02, 2013 )
+*  Adding spec tests
+*  Fixed init issue on Ubuntu ( Issue #6 by Marcus Furlong )
+*  Fixed config template problem ( Issue #8 by surfchris )
+*  New feature to manage templates
+
+##0.0.2 ( Feb 16, 2013 )
+*  Feature to supply a package instead of being dependent on the repository
+*  Feature to install java in case one doesn't manage it externally
+*  Adding RedHat and Amazon as Operating systems
+*  fixed a typo - its a shard not a shared :) ( PR #5 by Martin Seener )
+
+##0.0.1 ( Jan 13, 2013 )
+*  Initial release of the module
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/CONTRIBUTING.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+If you have a bugfix or new feature that you would like to contribute to this puppet module, please find or open an issue about it first. Talk about what you would like to do. It may be that somebody is already working on it, or that there are particular issues that you should know about before implementing the change.
+
+We enjoy working with contributors to get their code accepted. There are many approaches to fixing a problem and it is important to find the best approach before writing too much code.
+
+The process for contributing to any of the Elastic repositories is similar.
+
+1. Sign the contributor license agreement
+Please make sure you have signed the [Contributor License Agreement](http://www.elastic.co/contributor-agreement/). We are not asking you to assign copyright to us, but to give us the right to distribute your code without restriction. We ask this of all contributors in order to assure our users of the origin and continuing existence of the code. You only need to sign the CLA once.
+
+2. Run the rspec tests and ensure it completes without errors with your changes.
+
+3. Run the acceptance tests
+
+These instructions are for Ubuntu 14.04
+
+* install docker 0.11.1 
+ * wget https://get.docker.io/ubuntu/pool/main/l/lxc-docker/lxc-docker_0.11.1_amd64.deb
+ * wget https://get.docker.io/ubuntu/pool/main/l/lxc-docker-0.11.1/lxc-docker-0.11.1_0.11.1_amd64.deb
+ * sudo dpkg -i lxc-docker_0.11.1_amd64.deb lxc-docker-0.11.1_0.11.1_amd64.deb
+ * sudo usermod -a -G docker $USER
+* export RS_SET='ubuntu-server-1404-x64' # see spec/acceptance/nodesets for more
+* export VM_PUPPET_VERSION='3.7.0'
+* wget https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.1.0.deb
+* wget https://forgeapi.puppetlabs.com/v3/files/puppetlabs-stdlib-3.2.0.tar.gz
+* wget https://forgeapi.puppetlabs.com/v3/files/puppetlabs-apt-1.4.2.tar.gz
+* export files_dir=$(pwd)
+* bundle install
+* bundle exec rspec --require ci/reporter/rspec --format CI::Reporter::RSpecFormatter spec/acceptance/*_spec.rb
+
+```
+    Hypervisor for ubuntu-14-04 is docker
+    Beaker::Hypervisor, found some docker boxes to create
+    Provisioning docker
+    provisioning ubuntu-14-04
+    ...
+    Finished in 18 minutes 6 seconds
+    224 examples, 0 failures, 3 pending
+```
+
+4. Rebase your changes
+Update your local repository with the most recent code from the main this puppet module repository, and rebase your branch on top of the latest master branch. We prefer your changes to be squashed into a single commit.
+
+5. Submit a pull request
+Push your local changes to your forked copy of the repository and submit a pull request. In the pull request, describe what your changes do and mention the number of the issue where discussion has taken place, eg “Closes #123″.
+
+Then sit back and wait. There will probably be discussion about the pull request and, if any changes are needed, we would love to work with you to get your pull request merged into this puppet module.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/CONTRIBUTORS	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+The following is a list of people who have contributed ideas, code, bug
+reports, or in general have helped this puppet module along its way.
+
+Project Owner
+* Richard Pijnenburg (electrical)
+
+Contributors:
+Martin Seener (martinseener)
+Marcus Furlong (furlongm)
+Chris Boulton (chrisboulton)
+Igor Galić (igalic)
+Vincent Janelle (vjanelle)
+Mathieu Bornoz (mbornoz)
+Justin Lambert (jlambert121)
+Brian Lalor (blalor)
+Stas Alekseev (salekseev)
+Simon Effenberg (Savar)
+Bruce Morrison (brucem)
+deanmalmgren
+Matteo Sessa (msessa-cotd)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/Gemfile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+source 'https://rubygems.org'
+
+puppetversion = ENV['PUPPET_VERSION'] || '~> 3.8.0'
+gem 'puppet', puppetversion, :require => false
+
+gem 'beaker'
+gem 'beaker-rspec'
+gem 'metadata-json-lint'
+gem 'rspec-puppet', '2.2.0'
+
+gem 'pry'
+gem 'docker-api', '~> 1.0'
+gem 'rubysl-securerandom'
+gem 'ci_reporter_rspec'
+gem 'rspec', '~> 3.0'
+gem 'rake'
+gem 'puppet-doc-lint'
+gem 'puppet-lint'
+gem 'puppetlabs_spec_helper'
+gem 'puppet-syntax'
+gem 'rspec-puppet-facts'
+gem 'webmock'
+
+# Extra Puppet-lint gems
+gem 'puppet-lint-appends-check', :require => false
+gem 'puppet-lint-version_comparison-check', :require => false
+gem 'puppet-lint-unquoted_string-check', :require => false
+gem 'puppet-lint-undef_in_function-check', :require => false
+gem 'puppet-lint-trailing_comma-check', :require => false
+gem 'puppet-lint-leading_zero-check', :require => false
+gem 'puppet-lint-file_ensure-check', :require => false
+gem 'puppet-lint-empty_string-check', :require => false
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/LICENSE	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+Copyright (c) 2012-2015 Elasticsearch <http://www.elastic.co>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/README.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,534 @@
+#Elasticsearch Puppet module
+
+####Table of Contents
+
+1. [Overview](#overview)
+2. [Module description - What the module does and why it is useful](#module-description)
+3. [Setup - The basics of getting started with Elasticsearch](#setup)
+  * [The module manages the following](#the-module-manages-the-following)
+  * [Requirements](#requirements)
+4. [Usage - Configuration options and additional functionality](#usage)
+5. [Advanced features - Extra information on advanced usage](#advanced-features)
+6. [Limitations - OS compatibility, etc.](#limitations)
+7. [Development - Guide for contributing to the module](#development)
+8. [Support - When you need help with this module](#support)
+
+
+
+##Overview
+
+This module manages Elasticsearch (http://www.elasticsearch.org/overview/elasticsearch/)
+
+##Module description
+
+The elasticsearch module sets up Elasticsearch instances and can manage plugins and templates.
+
+This module has been tested against all versions of ES 1.x and 2.x
+
+##Setup
+
+###The module manages the following
+
+* Elasticsearch repository files.
+* Elasticsearch package.
+* Elasticsearch configuration file.
+* Elasticsearch service.
+* Elasticsearch plugins.
+* Elasticsearch templates.
+
+###Requirements
+
+* The [stdlib](https://forge.puppetlabs.com/puppetlabs/stdlib) Puppet library.
+* [ceritsc/yum](https://forge.puppetlabs.com/ceritsc/yum) For yum version lock.
+* [richardc/datacat](https://forge.puppetlabs.com/richardc/datacat)
+* [Augeas](http://augeas.net/)
+
+#### Repository management
+When using the repository management you will need the following dependency modules:
+
+* Debian/Ubuntu: [Puppetlabs/apt](http://forge.puppetlabs.com/puppetlabs/apt)
+* OpenSuSE: [Darin/zypprepo](https://forge.puppetlabs.com/darin/zypprepo)
+
+##Usage
+
+###Main class
+
+####Install a specific version
+
+```puppet
+class { 'elasticsearch':
+  version => '1.4.2'
+}
+```
+
+Note: This will only work when using the repository.
+
+####Automatic upgrade of the software ( default set to false )
+```puppet
+class { 'elasticsearch':
+  autoupgrade => true
+}
+```
+
+####Removal/decommissioning
+```puppet
+class { 'elasticsearch':
+  ensure => 'absent'
+}
+```
+
+####Install everything but disable service(s) afterwards
+```puppet
+class { 'elasticsearch':
+  status => 'disabled'
+}
+```
+
+###Instances
+
+This module works with the concept of instances. For service to start you need to specify at least one instance.
+
+####Quick setup
+```puppet
+elasticsearch::instance { 'es-01': }
+```
+
+This will set up its own data directory and set the node name to `$hostname-$instance_name`
+
+####Advanced options
+
+Instance specific options can be given:
+
+```puppet
+elasticsearch::instance { 'es-01':
+  config => { },        # Configuration hash
+  init_defaults => { }, # Init defaults hash
+  datadir => [ ],       # Data directory
+}
+```
+
+See [Advanced features](#advanced-features) for more information
+
+###Plug-ins
+
+Install [a variety of plugins](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-plugins.html#known-plugins). Note that `module_dir` is where the plugin will install itself to and must match that published by the plugin author; it is not where you would like to install it yourself.
+
+####From official repository
+```puppet
+elasticsearch::plugin{'lmenezes/elasticsearch-kopf':
+  instances  => 'instance_name'
+}
+```
+####From custom url
+```puppet
+elasticsearch::plugin{ 'jetty':
+  url        => 'https://oss-es-plugins.s3.amazonaws.com/elasticsearch-jetty/elasticsearch-jetty-1.2.1.zip',
+  instances  => 'instance_name'
+}
+```
+
+
+####Using a proxy
+You can also use a proxy if required by setting the `proxy_host` and `proxy_port` options:
+```puppet
+elasticsearch::plugin { 'lmenezes/elasticsearch-kopf',
+  instances  => 'instance_name',
+  proxy_host => 'proxy.host.com',
+  proxy_port => 3128
+}
+```
+
+#####Plugin name could be:
+* `elasticsearch/plugin/version` for official elasticsearch plugins (download from download.elasticsearch.org)
+* `groupId/artifactId/version`   for community plugins (download from maven central or oss sonatype)
+* `username/repository`          for site plugins (download from github master)
+
+####Upgrading plugins
+When you specify a certain plugin version, you can upgrade that plugin by specifying the new version.
+
+```puppet
+elasticsearch::plugin { 'elasticsearch/elasticsearch-cloud-aws/2.1.1':
+}
+```
+
+And to upgrade, you would simply change it to
+
+```puppet
+elasticsearch::plugin { 'elasticsearch/elasticsearch-cloud-aws/2.4.1':
+}
+```
+
+Please note that this does not work when you specify 'latest' as a version number.
+
+####ES 2.x official plugins
+For the Elasticsearch commercial plugins you can refer them to the simple name.
+
+See the [Plugin installation](https://www.elastic.co/guide/en/elasticsearch/plugins/current/installation.html) for more details.
+
+###Scripts
+
+Install [scripts](http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting.html) to be used by Elasticsearch.
+These scripts are shared across all defined instances on the same host.
+
+```puppet
+elasticsearch::script { 'myscript':
+  ensure => 'present',
+  source => 'puppet:///path/to/my/script.groovy'
+}
+```
+
+###Templates
+
+#### Add a new template using a file
+
+This will install and/or replace the template in Elasticsearch:
+
+```puppet
+elasticsearch::template { 'templatename':
+  file => 'puppet:///path/to/template.json'
+}
+```
+
+#### Add a new template using content
+
+This will install and/or replace the template in Elasticsearch:
+
+```puppet
+elasticsearch::template { 'templatename':
+  content => '{"template":"*","settings":{"number_of_replicas":0}}'
+}
+```
+
+#### Delete a template
+
+```puppet
+elasticsearch::template { 'templatename':
+  ensure => 'absent'
+}
+```
+
+#### Host
+
+By default it uses localhost:9200 as host. you can change this with the `host` and `port` variables
+
+```puppet
+elasticsearch::template { 'templatename':
+  host => $::ipaddress,
+  port => 9200
+}
+```
+
+###Bindings / Clients
+
+Install a variety of [clients/bindings](http://www.elasticsearch.org/guide/en/elasticsearch/client/community/current/clients.html):
+
+####Python
+
+```puppet
+elasticsearch::python { 'rawes': }
+```
+
+####Ruby
+```puppet
+elasticsearch::ruby { 'elasticsearch': }
+```
+
+###Connection Validator
+
+This module offers a way to make sure an instance has been started and is up and running before
+doing a next action. This is done via the use of the `es_instance_conn_validator` resource.
+```puppet
+es_instance_conn_validator { 'myinstance' :
+  server => 'es.example.com',
+  port   => '9200',
+}
+```
+
+A common use would be for example :
+
+```puppet
+class { 'kibana4' :
+  require => Es_Instance_Conn_Validator['myinstance'],
+}
+```
+
+###Package installation
+
+There are 2 different ways of installing the software
+
+####Repository
+
+This option allows you to use an existing repository for package installation.
+The `repo_version` corresponds with the major version of Elasticsearch.
+
+```puppet
+class { 'elasticsearch':
+  manage_repo  => true,
+  repo_version => '1.4',
+}
+```
+
+####Remote package source
+
+When a repository is not available or preferred you can install the packages from a remote source:
+
+#####http/https/ftp
+```puppet
+class { 'elasticsearch':
+  package_url       => 'https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.4.2.deb',
+  proxy_url         => 'http://proxy.example.com:8080/',
+}
+```
+Setting proxy_url to a location will enable download using the provided proxy
+server. This parameter is also used by elasticsearch::plugin. Setting the port
+in the proxy_url is mandatory. proxy_url defaults to undef (proxy disabled). 
+
+#####puppet://
+```puppet
+class { 'elasticsearch':
+  package_url => 'puppet:///path/to/elasticsearch-1.4.2.deb'
+}
+```
+
+#####Local file
+```puppet
+class { 'elasticsearch':
+  package_url => 'file:/path/to/elasticsearch-1.4.2.deb'
+}
+```
+
+###Java installation
+
+Most sites will manage Java separately; however, this module can attempt to install Java as well.
+This is done by using the [puppetlabs-java](https://forge.puppetlabs.com/puppetlabs/java) module.
+
+```puppet
+class { 'elasticsearch':
+  java_install => true
+}
+```
+
+Specify a particular Java package/version to be installed:
+
+```puppet
+class { 'elasticsearch':
+  java_install => true,
+  java_package => 'packagename'
+}
+```
+
+###Service management
+
+Currently only the basic SysV-style [init](https://en.wikipedia.org/wiki/Init) and [Systemd](http://en.wikipedia.org/wiki/Systemd) service providers are supported, but other systems could be implemented as necessary (pull requests welcome).
+
+
+####Defaults File
+
+The *defaults* file (`/etc/defaults/elasticsearch` or `/etc/sysconfig/elasticsearch`) for the Elasticsearch service can be populated as necessary. This can either be a static file resource or a simple key value-style  [hash](http://docs.puppetlabs.com/puppet/latest/reference/lang_datatypes.html#hashes) object, the latter being particularly well-suited to pulling out of a data source such as Hiera.
+
+#####file source
+```puppet
+class { 'elasticsearch':
+  init_defaults_file => 'puppet:///path/to/defaults'
+}
+```
+#####hash representation
+```puppet
+$config_hash = {
+  'ES_USER' => 'elasticsearch',
+  'ES_GROUP' => 'elasticsearch',
+}
+
+class { 'elasticsearch':
+  init_defaults => $config_hash
+}
+```
+
+Note: `init_defaults` hash can be passed to the main class and to the instance.
+
+##Advanced features
+
+###Package version pinning
+
+The module supports pinning the package version to avoid accidental upgrades that are not done by Puppet.
+To enable this feature:
+
+```puppet
+class { 'elasticsearch':
+  package_pin => true,
+  version     => '1.5.2',
+}
+```
+
+In this example we pin the package version to 1.5.2.
+
+
+###Data directories
+
+There are 4 different ways of setting data directories for Elasticsearch.
+In every case the required configuration options are placed in the `elasticsearch.yml` file.
+
+####Default
+By default we use:
+
+`/usr/share/elasticsearch/data/$instance_name`
+
+Which provides a data directory per instance.
+
+
+####Single global data directory
+
+```puppet
+class { 'elasticsearch':
+  datadir => '/var/lib/elasticsearch-data'
+}
+```
+Creates the following for each instance:
+
+`/var/lib/elasticsearch-data/$instance_name`
+
+####Multiple Global data directories
+
+```puppet
+class { 'elasticsearch':
+  datadir => [ '/var/lib/es-data1', '/var/lib/es-data2']
+}
+```
+Creates the following for each instance:
+`/var/lib/es-data1/$instance_name`
+and
+`/var/lib/es-data2/$instance_name`
+
+
+####Single instance data directory
+
+```puppet
+class { 'elasticsearch': }
+
+elasticsearch::instance { 'es-01':
+  datadir => '/var/lib/es-data-es01'
+}
+```
+Creates the following for this instance:
+`/var/lib/es-data-es01`
+
+####Multiple instance data directories
+
+```puppet
+class { 'elasticsearch': }
+
+elasticsearch::instance { 'es-01':
+  datadir => ['/var/lib/es-data1-es01', '/var/lib/es-data2-es01']
+}
+```
+Creates the following for this instance:
+`/var/lib/es-data1-es01`
+and
+`/var/lib/es-data2-es01`
+
+
+###Main and instance configurations
+
+The `config` option in both the main class and the instances can be configured to work together.
+
+The options in the `instance` config hash will merged with the ones from the main class and override any duplicates.
+
+#### Simple merging
+
+```puppet
+class { 'elasticsearch':
+  config => { 'cluster.name' => 'clustername' }
+}
+
+elasticsearch::instance { 'es-01':
+  config => { 'node.name' => 'nodename' }
+}
+elasticsearch::instance { 'es-02':
+  config => { 'node.name' => 'nodename2' }
+}
+
+```
+
+This example merges the `cluster.name` together with the `node.name` option.
+
+#### Overriding
+
+When duplicate options are provided, the option in the instance config overrides the ones from the main class.
+
+```puppet
+class { 'elasticsearch':
+  config => { 'cluster.name' => 'clustername' }
+}
+
+elasticsearch::instance { 'es-01':
+  config => { 'node.name' => 'nodename', 'cluster.name' => 'otherclustername' }
+}
+
+elasticsearch::instance { 'es-02':
+  config => { 'node.name' => 'nodename2' }
+}
+```
+
+This will set the cluster name to `otherclustername` for the instance `es-01` but will keep it to `clustername` for instance `es-02`
+
+####Configuration writeup
+
+The `config` hash can be written in 2 different ways:
+
+##### Full hash writeup
+
+Instead of writing the full hash representation:
+```puppet
+class { 'elasticsearch':
+  config                 => {
+   'cluster'             => {
+     'name'              => 'ClusterName',
+     'routing'           => {
+        'allocation'     => {
+          'awareness'    => {
+            'attributes' => 'rack'
+          }
+        }
+      }
+    }
+  }
+}
+```
+##### Short hash writeup
+```puppet
+class { 'elasticsearch':
+  config => {
+    'cluster' => {
+      'name' => 'ClusterName',
+      'routing.allocation.awareness.attributes' => 'rack'
+    }
+  }
+}
+```
+
+
+##Limitations
+
+This module has been built on and tested against Puppet 3.2 and higher.
+
+The module has been tested on:
+
+* Debian 6/7/8
+* CentOS 6/7
+* Ubuntu 12.04, 14.04
+* OpenSuSE 13.x
+
+Other distro's that have been reported to work:
+
+* RHEL 6
+* OracleLinux 6
+* Scientific 6
+
+Testing on other platforms has been light and cannot be guaranteed.
+
+##Development
+
+
+##Support
+
+Need help? Join us in [#elasticsearch](https://webchat.freenode.net?channels=%23elasticsearch) on Freenode IRC or on the [discussion forum](https://discuss.elastic.co/).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/Rakefile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,28 @@
+require 'rubygems'
+require 'puppetlabs_spec_helper/rake_tasks'
+
+exclude_paths = [
+  "pkg/**/*",
+  "vendor/**/*",
+  "spec/**/*",
+]
+
+require 'puppet-doc-lint/rake_task'
+PuppetDocLint.configuration.ignore_paths = exclude_paths
+
+require 'puppet-lint/tasks/puppet-lint'
+require 'puppet-syntax/tasks/puppet-syntax'
+
+PuppetSyntax.exclude_paths = exclude_paths
+PuppetSyntax.future_parser = true if ENV['FUTURE_PARSER'] == 'true'
+
+disable_checks = [
+  '80chars',
+  'class_inherits_from_params_class',
+  'class_parameter_defaults',
+  'documentation',
+  'single_quote_string_with_variables'
+].each { |check| PuppetLint.configuration.send("disable_#{check}") }
+
+PuppetLint.configuration.ignore_paths = exclude_paths
+PuppetLint.configuration.log_format = "%{path}:%{linenumber}:%{check}:%{KIND}:%{message}"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/lib/facter/es_facts.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,99 @@
+require 'net/http'
+require 'json'
+require 'yaml'
+
+module EsFacts
+
+  def self.add_fact(prefix, key, value)
+    key = "#{prefix}_#{key}".to_sym
+    ::Facter.add(key) do
+      setcode { value }
+    end
+  end
+
+  def self.run
+
+    dir_prefix = '/etc/elasticsearch'
+    ports = []
+
+    # only when the directory exists we need to process the stuff
+    if File.directory?(dir_prefix)
+
+      Dir.foreach(dir_prefix) { |dir| 
+        next if dir == '.'
+        if File.exists?("#{dir_prefix}/#{dir}/elasticsearch.yml")
+          config_data = YAML.load_file("#{dir_prefix}/#{dir}/elasticsearch.yml")
+          unless config_data['http'].nil?
+            next if config_data['http']['enabled'] == 'false'
+            if config_data['http']['port'].nil?
+              port = "9200"
+            else
+              port = config_data['http']['port']
+            end
+          else
+            port = "9200"
+          end
+          ports << port
+        end
+      }
+
+      begin
+        if ports.count > 0
+
+          add_fact('elasticsearch', 'ports', ports.join(",") )
+          ports.each do |port|
+
+            key_prefix = "elasticsearch_#{port}"
+
+            uri = URI("http://localhost:#{port}")
+            http = Net::HTTP.new(uri.host, uri.port)
+            http.read_timeout = 10
+            response = http.get("/")
+            json_data = JSON.parse(response.body)
+            next if json_data['status'] && json_data['status'] != 200
+
+            add_fact(key_prefix, 'name', json_data['name'])
+            add_fact(key_prefix, 'version', json_data['version']['number'])
+
+            uri2 = URI("http://localhost:#{port}/_nodes/#{json_data['name']}")
+            http2 = Net::HTTP.new(uri2.host, uri2.port)
+            http2.read_timeout = 10
+            response2 = http2.get(uri2.path)
+            json_data_node = JSON.parse(response2.body)
+
+            add_fact(key_prefix, 'cluster_name', json_data_node['cluster_name'])
+            node_data = json_data_node['nodes'].first
+
+            add_fact(key_prefix, 'node_id', node_data[0])
+
+            nodes_data = json_data_node['nodes'][node_data[0]]
+
+            process = nodes_data['process']
+            add_fact(key_prefix, 'mlockall', process['mlockall'])
+
+            plugins = nodes_data['plugins']
+
+            plugin_names = []
+            plugins.each do |plugin|
+              plugin_names << plugin['name']
+
+             plugin.each do |key, value|
+                prefix = "#{key_prefix}_plugin_#{plugin['name']}"
+                add_fact(prefix, key, value) unless key == 'name'
+              end
+            end
+            add_fact(key_prefix, 'plugins', plugin_names.join(","))
+
+          end
+
+        end
+      rescue
+      end
+
+    end
+
+  end
+
+end
+
+EsFacts.run
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/lib/puppet/parser/functions/array_suffix.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+#
+# suffix.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:array_suffix, :type => :rvalue, :doc => <<-EOS
+This function applies a suffix to all elements in an array.
+
+*Examples:*
+
+    array_suffix(['a','b','c'], 'p')
+
+Will return: ['ap','bp','cp']
+    EOS
+  ) do |arguments|
+
+    # Technically we support two arguments but only first is mandatory ...
+    raise(Puppet::ParseError, "array_suffix(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    array = arguments[0]
+
+    unless array.is_a?(Array)
+      raise Puppet::ParseError, "array_suffix(): expected first argument to be an Array, got #{array.inspect}"
+    end
+
+    suffix = arguments[1] if arguments[1]
+
+    if suffix
+      unless suffix.is_a? String
+        raise Puppet::ParseError, "array_suffix(): expected second argument to be a String, got #{suffix.inspect}"
+      end
+    end
+
+    # Turn everything into string same as join would do ...
+    result = array.collect do |i|
+      i = i.to_s
+      suffix ? i + suffix : i
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/lib/puppet/parser/functions/plugin_dir.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,43 @@
+module Puppet::Parser::Functions
+  newfunction(:plugin_dir, :type => :rvalue, :doc => <<-EOS
+    Extracts the end plugin directory of the name
+    EOS
+  ) do |arguments|
+
+    if arguments.size < 1 then
+      raise(Puppet::ParseError, "plugin_dir(): No arguments given")
+    elsif arguments.size > 2 then
+      raise(Puppet::ParseError, "plugin_dir(): Too many arguments given (#{arguments.size})")
+    else
+
+      unless arguments[0].is_a?(String)
+        raise(Puppet::ParseError, 'plugin_dir(): Requires string as first argument')
+      end
+
+      plugin_name = arguments[0]
+      items = plugin_name.split("/")
+
+      if items.count == 1
+        endname = items[0]
+      elsif items.count > 1
+        plugin = items[1]
+        if plugin.include?('-') # example elasticsearch-head
+          if plugin.start_with?('elasticsearch-')
+            endname = plugin.gsub('elasticsearch-', '')
+          elsif plugin.start_with?('es-')
+            endname = plugin.gsub('es-', '')
+          else
+            endname = plugin
+          end
+        else
+          endname = plugin
+        end
+      else
+        raise(Puppet::ParseError, "Unable to parse plugin name: #{plugin_name}")
+      end
+
+      return endname
+
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/lib/puppet/provider/elasticsearch_plugin/plugin.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,131 @@
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__),"..","..",".."))
+
+Puppet::Type.type(:elasticsearch_plugin).provide(:plugin) do
+  desc "A provider for the resource type `elasticsearch_plugin`,
+        which handles plugin installation"
+
+  commands :plugin => '/usr/share/elasticsearch/bin/plugin'
+  commands :es => '/usr/share/elasticsearch/bin/elasticsearch'
+
+  def exists?
+    es_version
+    if !File.exists?(pluginfile)
+      debug "Plugin file #{pluginfile} does not exist"
+      return false
+    elsif File.exists?(pluginfile) && readpluginfile != pluginfile_content
+      debug "Got #{readpluginfile} Expected #{pluginfile_content}. Removing for reinstall"
+      self.destroy
+      return false
+    else
+      debug "Plugin exists"
+      return true
+    end
+  end
+
+  def pluginfile_content
+    return @resource[:name] if is1x?
+
+    if @resource[:name].split("/").count == 1 # Official plugin
+      version = plugin_version(@resource[:name])
+      return "#{@resource[:name]}/#{version}"
+    else
+      return @resource[:name]
+    end
+  end
+
+  def pluginfile
+    File.join(@resource[:plugin_dir], plugin_name(@resource[:name]), '.name')
+  end
+
+  def writepluginfile
+    File.open(pluginfile, 'w') do |file|
+      file.write pluginfile_content
+    end
+  end
+
+  def readpluginfile
+    f = File.open(pluginfile)
+    f.readline
+  end
+
+  def install1x
+    if !@resource[:url].nil?
+      commands = [ plugin_name(@resource[:name]), '--url', @resource[:url] ]
+    elsif !@resource[:source].nil?
+      commands = [ plugin_name(@resource[:name]), '--url', "file://#{@resource[:source]}" ]
+    else
+      commands = [ @resource[:name] ]
+    end
+    commands
+  end
+
+  def install2x
+    if !@resource[:url].nil?
+      commands = [ @resource[:url] ]
+    elsif !@resource[:source].nil?
+      commands = [ "file://#{@resource[:source]}" ]
+    else
+      commands = [ @resource[:name] ]
+    end
+    commands
+  end
+
+  def create
+    es_version
+    commands = []
+    commands << @resource[:proxy_args].split(' ') if @resource[:proxy_args]
+    commands << 'install'
+    commands << install1x if is1x?
+    commands << install2x if is2x?
+    debug("Commands: #{commands.inspect}")
+    
+    plugin(commands)
+    writepluginfile
+  end
+
+  def destroy
+    plugin(['remove', @resource[:name]])
+  end
+
+  def es_version
+    return @es_version if @es_version
+    begin
+      version = es('-v') # ES 1.x
+    rescue
+      version = es('--version') # ES 2.x
+    rescue
+      raise "Unknown ES version. Got #{version.inspect}"
+    ensure
+      @es_version = version.scan(/\d+\.\d+\.\d+(?:\-\S+)?/).first
+      debug "Found ES version #{@es_version}"
+    end
+  end
+
+  def is1x?
+    Puppet::Util::Package.versioncmp(@es_version, '2.0.0') < 0
+  end
+
+  def is2x?
+    (Puppet::Util::Package.versioncmp(@es_version, '2.0.0') >= 0) && (Puppet::Util::Package.versioncmp(@es_version, '3.0.0') < 0)
+  end
+
+  def plugin_version(plugin_name)
+    vendor, plugin, version = plugin_name.split('/')
+    return @es_version if is2x? && version.nil?
+    return version.scan(/\d+\.\d+\.\d+(?:\-\S+)?/).first unless version.nil?
+    return false
+  end
+
+  def plugin_name(plugin_name)
+
+    vendor, plugin, version = plugin_name.split('/')
+
+    endname = vendor if plugin.nil? # If its a single name plugin like the ES 2.x official plugins
+    endname = plugin.gsub(/(elasticsearch-|es-)/, '') unless plugin.nil?
+
+    return endname.downcase if is2x?
+    return endname
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,51 @@
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__),"..","..",".."))
+require 'puppet/util/es_instance_validator'
+
+# This file contains a provider for the resource type `es_instance_conn_validator`,
+# which validates the Elasticsearch instance connection by attempting an https connection.
+
+Puppet::Type.type(:es_instance_conn_validator).provide(:tcp_port) do
+  desc "A provider for the resource type `es_instance_conn_validator`,
+        which validates the  connection by attempting an https
+        connection to the Elasticsearch instance." 
+
+  def exists?
+    start_time = Time.now
+    timeout = resource[:timeout]
+
+    success = validator.attempt_connection
+
+    while success == false && ((Time.now - start_time) < timeout)
+      # It can take several seconds for the Elasticsearch instance to start up;
+      # especially on the first install.  Therefore, our first connection attempt
+      # may fail.  Here we have somewhat arbitrarily chosen to retry every 2
+      # seconds until the configurable timeout has expired.
+      Puppet.debug("Failed to connect to the Elasticsearch instance; sleeping 2 seconds before retry")
+      sleep 2
+      success = validator.attempt_connection
+    end
+
+    if success
+      Puppet.debug("Connected to the ES instance in #{Time.now - start_time} seconds.")
+    else
+      Puppet.notice("Failed to connect to the ES instance within timeout window of #{timeout} seconds; giving up.")
+    end
+
+    success
+  end
+
+  def create
+    # If `#create` is called, that means that `#exists?` returned false, which
+    # means that the connection could not be established... so we need to
+    # cause a failure here.
+    raise Puppet::Error, "Unable to connect to ES instance ! (#{@validator.instance_server}:#{@validator.instance_port})"
+  end
+
+  private
+
+  # @api private
+  def validator
+    @validator ||= Puppet::Util::EsInstanceValidator.new(resource[:server], resource[:port])
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/lib/puppet/type/elasticsearch_plugin.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+Puppet::Type.newtype(:elasticsearch_plugin) do
+
+  @doc = "Plugin installation type"
+  
+  ensurable do
+    defaultvalues
+    defaultto :present
+  end
+
+  newparam(:name, :namevar => true) do
+    desc 'An arbitrary name used as the identity of the resource.'
+  end
+
+  newparam(:url) do
+    desc 'Url of the package'
+  end
+
+  newparam(:source) do
+    desc 'Source of the package. puppet:// or file:// resource'
+  end
+
+  newparam(:proxy_args) do
+    desc 'Proxy Host'
+  end
+
+  newparam(:plugin_dir) do
+    desc 'Plugin directory'
+    defaultto '/usr/share/elasticsearch/plugins'
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/lib/puppet/type/es_instance_conn_validator.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,38 @@
+Puppet::Type.newtype(:es_instance_conn_validator) do
+
+  @doc = "Verify that a connection can be successfully established between a node
+  and the Elasticsearch instance. It could potentially be used for other
+  purposes such as monitoring."
+  
+  ensurable do
+    defaultvalues
+    defaultto :present
+  end
+
+  newparam(:name, :namevar => true) do
+    desc 'An arbitrary name used as the identity of the resource.'
+  end
+
+  newparam(:server) do
+    desc 'DNS name or IP address of the server where Elasticsearch instance should be running.'
+    defaultto 'localhost'
+  end
+
+  newparam(:port) do
+    desc 'The port that the Elasticsearch instance should be listening on.'
+    defaultto 9200
+  end
+
+  newparam(:timeout) do
+    desc 'The max number of seconds that the validator should wait before giving up and deciding that the Elasticsearch instance is not running; defaults to 60 seconds.'
+    defaultto 60
+    validate do |value|
+      # This will raise an error if the string is not convertible to an integer
+      Integer(value)
+    end
+    munge do |value|
+      Integer(value)
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/lib/puppet/util/es_instance_validator.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+require 'socket'
+require 'timeout'
+
+module Puppet
+  module Util
+    class EsInstanceValidator
+      attr_reader :instance_server
+      attr_reader :instance_port
+
+      def initialize(instance_server, instance_port)
+        @instance_server = instance_server
+        @instance_port   = instance_port
+      end
+
+      # Utility method; attempts to make an https connection to the Elasticsearch instance.
+      # This is abstracted out into a method so that it can be called multiple times
+      # for retry attempts.
+      #
+      # @return true if the connection is successful, false otherwise.
+      def attempt_connection
+        Timeout::timeout(Puppet[:configtimeout]) do
+          begin
+            TCPSocket.new(@instance_server, @instance_port).close
+            true
+          rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
+            Puppet.debug "Unable to connect to Elasticsearch instance (#{@instance_server}:#{@instance_port}): #{e.message}"
+            false
+          end
+        end
+      rescue Timeout::Error
+        false
+      end
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/config.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,141 @@
+# == Class: elasticsearch::config
+#
+# This class exists to coordinate all configuration related actions,
+# functionality and logical units in a central place.
+#
+#
+# === Parameters
+#
+# This class does not provide any parameters.
+#
+#
+# === Examples
+#
+# This class may be imported by other classes to use its functionality:
+#   class { 'elasticsearch::config': }
+#
+# It is not intended to be used directly by external resources like node
+# definitions or other modules.
+#
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+class elasticsearch::config {
+
+  #### Configuration
+
+  File {
+    owner => $elasticsearch::elasticsearch_user,
+    group => $elasticsearch::elasticsearch_group,
+  }
+
+  Exec {
+    path => [ '/bin', '/usr/bin', '/usr/local/bin' ],
+    cwd  => '/',
+  }
+
+  if ( $elasticsearch::ensure == 'present' ) {
+
+    $notify_service = $elasticsearch::restart_on_change ? {
+      true  => Class['elasticsearch::service'],
+      false => undef,
+    }
+
+    file { $elasticsearch::configdir:
+      ensure => directory,
+      mode   => '0644',
+    }
+
+    file { $elasticsearch::params::logdir:
+      ensure  => 'directory',
+      group   => undef,
+      mode    => '0644',
+      recurse => true,
+    }
+
+    file { $elasticsearch::params::homedir:
+      ensure  => 'directory',
+    }
+
+    file { "${elasticsearch::params::homedir}/bin":
+      ensure  => 'directory',
+      recurse => true,
+      mode    => '0755',
+    }
+
+    file { $elasticsearch::datadir:
+      ensure  => 'directory',
+    }
+
+    file { "${elasticsearch::homedir}/lib":
+      ensure  => 'directory',
+      recurse => true,
+    }
+
+    if $elasticsearch::params::pid_dir {
+      file { $elasticsearch::params::pid_dir:
+        ensure  => 'directory',
+        group   => undef,
+        recurse => true,
+      }
+
+      if ($elasticsearch::service_providers == 'systemd') {
+        $user = $elasticsearch::elasticsearch_user
+        $group = $elasticsearch::elasticsearch_group
+        $pid_dir = $elasticsearch::params::pid_dir
+
+        file { '/usr/lib/tmpfiles.d/elasticsearch.conf':
+          ensure  => 'file',
+          content => template("${module_name}/usr/lib/tmpfiles.d/elasticsearch.conf.erb"),
+          owner   => 'root',
+          group   => 'root',
+        }
+      }
+    }
+
+
+    file { "${elasticsearch::params::homedir}/templates_import":
+      ensure => 'directory',
+      mode   => '0644',
+    }
+
+    file { "${elasticsearch::params::homedir}/scripts":
+      ensure => 'directory',
+      mode   => '0644',
+    }
+
+    # Removal of files that are provided with the package which we don't use
+    file { '/etc/init.d/elasticsearch':
+      ensure => 'absent',
+    }
+    file { '/lib/systemd/system/elasticsearch.service':
+      ensure => 'absent',
+    }
+
+    $new_init_defaults = { 'CONF_DIR' => $elasticsearch::configdir }
+    augeas { "${elasticsearch::params::defaults_location}/elasticsearch":
+      incl    => "${elasticsearch::params::defaults_location}/elasticsearch",
+      lens    => 'Shellvars.lns',
+      changes => template("${module_name}/etc/sysconfig/defaults.erb"),
+    }
+
+    file { '/etc/elasticsearch/elasticsearch.yml':
+      ensure => 'absent',
+    }
+    file { '/etc/elasticsearch/logging.yml':
+      ensure => 'absent',
+    }
+
+  } elsif ( $elasticsearch::ensure == 'absent' ) {
+
+    file { $elasticsearch::plugindir:
+      ensure => 'absent',
+      force  => true,
+      backup => false,
+    }
+
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,425 @@
+# == Class: elasticsearch
+#
+# This class is able to install or remove elasticsearch on a node.
+# It manages the status of the related service.
+#
+# === Parameters
+#
+# [*ensure*]
+#   String. Controls if the managed resources shall be <tt>present</tt> or
+#   <tt>absent</tt>. If set to <tt>absent</tt>:
+#   * The managed software packages are being uninstalled.
+#   * Any traces of the packages will be purged as good as possible. This may
+#     include existing configuration files. The exact behavior is provider
+#     dependent. Q.v.:
+#     * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP]
+#     * {Puppet's package provider source code}[http://j.mp/wtVCaL]
+#   * System modifications (if any) will be reverted as good as possible
+#     (e.g. removal of created users, services, changed log settings, ...).
+#   * This is thus destructive and should be used with care.
+#   Defaults to <tt>present</tt>.
+#
+# [*autoupgrade*]
+#   Boolean. If set to <tt>true</tt>, any managed package gets upgraded
+#   on each Puppet run when the package provider is able to find a newer
+#   version than the present one. The exact behavior is provider dependent.
+#   Q.v.:
+#   * Puppet type reference: {package, "upgradeable"}[http://j.mp/xbxmNP]
+#   * {Puppet's package provider source code}[http://j.mp/wtVCaL]
+#   Defaults to <tt>false</tt>.
+#
+# [*status*]
+#   String to define the status of the service. Possible values:
+#   * <tt>enabled</tt>: Service is running and will be started at boot time.
+#   * <tt>disabled</tt>: Service is stopped and will not be started at boot
+#     time.
+#   * <tt>running</tt>: Service is running but will not be started at boot time.
+#     You can use this to start a service on the first Puppet run instead of
+#     the system startup.
+#   * <tt>unmanaged</tt>: Service will not be started at boot time and Puppet
+#     does not care whether the service is running or not. For example, this may
+#     be useful if a cluster management software is used to decide when to start
+#     the service plus assuring it is running on the desired node.
+#   Defaults to <tt>enabled</tt>. The singular form ("service") is used for the
+#   sake of convenience. Of course, the defined status affects all services if
+#   more than one is managed (see <tt>service.pp</tt> to check if this is the
+#   case).
+#
+# [*version*]
+#   String to set the specific version you want to install.
+#   Defaults to <tt>false</tt>.
+#
+# [*restart_on_change*]
+#   Boolean that determines if the application should be automatically restarted
+#   whenever the configuration changes. Disabling automatic restarts on config
+#   changes may be desired in an environment where you need to ensure restarts
+#   occur in a controlled/rolling manner rather than during a Puppet run.
+#
+#   Defaults to <tt>true</tt>, which will restart the application on any config
+#   change. Setting to <tt>false</tt> disables the automatic restart.
+#
+# [*configdir*]
+#   Path to directory containing the elasticsearch configuration.
+#   Use this setting if your packages deviate from the norm (/etc/elasticsearch)
+#
+# [*plugindir*]
+#   Path to directory containing the elasticsearch plugins
+#   Use this setting if your packages deviate from the norm (/usr/share/elasticsearch/plugins)
+#
+# [*plugintool*]
+#   Path to directory containing the elasticsearch plugin installation script
+#   Use this setting if your packages deviate from the norm (/usr/share/elasticsearch/bin/plugin)
+#
+# [*package_url*]
+#   Url to the package to download.
+#   This can be a http,https or ftp resource for remote packages
+#   puppet:// resource or file:/ for local packages
+#
+# [*package_provider*]
+#   Way to install the packages, currently only packages are supported.
+#
+# [*package_dir*]
+#   Directory where the packages are downloaded to
+#
+# [*package_name*]
+#   Name of the package to install
+#
+# [*purge_package_dir*]
+#   Purge package directory on removal
+#
+# [*package_dl_timeout*]
+#   For http,https and ftp downloads you can set howlong the exec resource may take.
+#   Defaults to: 600 seconds
+#
+# [*proxy_url*]
+#   For http and https downloads you can set a proxy server to use
+#   Format: proto://[user:pass@]server[:port]/
+#   Defaults to: undef (proxy disabled)
+#
+# [*elasticsearch_user*]
+#   The user Elasticsearch should run as. This also sets the file rights.
+#
+# [*elasticsearch_group*]
+#   The group Elasticsearch should run as. This also sets the file rights
+#
+# [*purge_configdir*]
+#   Purge the config directory for any unmanaged files
+#
+# [*service_provider*]
+#   Service provider to use. By Default when a single service provider is possibe that one is selected.
+#
+# [*init_defaults*]
+#   Defaults file content in hash representation
+#
+# [*init_defaults_file*]
+#   Defaults file as puppet resource
+#
+# [*init_template*]
+#   Service file as a template
+#
+# [*config*]
+#   Elasticsearch configuration hash
+#
+# [*datadir*]
+#   Allows you to set the data directory of Elasticsearch
+#
+# [*java_install*]
+#  Install java which is required for Elasticsearch.
+#  Defaults to: false
+#
+# [*java_package*]
+#   If you like to install a custom java package, put the name here.
+#
+# [*manage_repo*]
+#   Enable repo management by enabling our official repositories
+#
+# [*repo_version*]
+#   Our repositories are versioned per major version (0.90, 1.0) select here which version you want
+#
+# [*repo_key_id*]
+#   String.  The apt GPG key id
+#   Default: D88E42B4
+#
+# [*repo_key_source*]
+#   String.  URL of the apt GPG key
+#   Default: http://packages.elastic.co/GPG-KEY-elasticsearch
+#
+# [*logging_config*]
+#   Hash representation of information you want in the logging.yml file
+#
+# [*logging_file*]
+#   Instead of a hash you can supply a puppet:// file source for the logging.yml file
+#
+# [*logging_template*]
+#  Use a custom logging template - just supply the reative path ie ${module}/elasticsearch/logging.yml.erb
+#
+# [*default_logging_level*]
+#   Default logging level for Elasticsearch.
+#   Defaults to: INFO
+#
+# [*repo_stage*]
+#   Use stdlib stage setup for managing the repo, instead of anchoring
+#
+# [*instances*]
+#   Define instances via a hash. This is mainly used with Hiera's auto binding
+#   Defaults to: undef
+#
+# [*instances_hiera_merge*]
+#   Enable Hiera's merging function for the instances
+#   Defaults to: false
+#
+# [*plugins*]
+#   Define plugins via a hash. This is mainly used with Hiera's auto binding
+#   Defaults to: undef
+#
+# [*plugins_hiera_merge*]
+#   Enable Hiera's merging function for the plugins
+#   Defaults to: false
+#
+# [*package_pin*]
+#   Enables package version pinning.
+#   This pins the package version to the set version number and avoids
+#   package upgrades.
+#   Defaults to: true
+#
+# The default values for the parameters are set in elasticsearch::params. Have
+# a look at the corresponding <tt>params.pp</tt> manifest file if you need more
+# technical information about them.
+#
+# === Examples
+#
+# * Installation, make sure service is running and will be started at boot time:
+#     class { 'elasticsearch': }
+#
+# * Removal/decommissioning:
+#     class { 'elasticsearch':
+#       ensure => 'absent',
+#     }
+#
+# * Install everything but disable service(s) afterwards
+#     class { 'elasticsearch':
+#       status => 'disabled',
+#     }
+#
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+class elasticsearch(
+  $ensure                = $elasticsearch::params::ensure,
+  $status                = $elasticsearch::params::status,
+  $restart_on_change     = $elasticsearch::params::restart_on_change,
+  $autoupgrade           = $elasticsearch::params::autoupgrade,
+  $version               = false,
+  $package_provider      = 'package',
+  $package_url           = undef,
+  $package_dir           = $elasticsearch::params::package_dir,
+  $package_name          = $elasticsearch::params::package,
+  $package_pin           = true,
+  $purge_package_dir     = $elasticsearch::params::purge_package_dir,
+  $package_dl_timeout    = $elasticsearch::params::package_dl_timeout,
+  $proxy_url             = undef,
+  $elasticsearch_user    = $elasticsearch::params::elasticsearch_user,
+  $elasticsearch_group   = $elasticsearch::params::elasticsearch_group,
+  $configdir             = $elasticsearch::params::configdir,
+  $purge_configdir       = $elasticsearch::params::purge_configdir,
+  $service_provider      = 'init',
+  $init_defaults         = undef,
+  $init_defaults_file    = undef,
+  $init_template         = undef,
+  $config                = undef,
+  $datadir               = $elasticsearch::params::datadir,
+  $plugindir             = $elasticsearch::params::plugindir,
+  $plugintool            = $elasticsearch::params::plugintool,
+  $java_install          = false,
+  $java_package          = undef,
+  $manage_repo           = false,
+  $repo_version          = undef,
+  $repo_key_id           = 'D88E42B4',
+  $repo_key_source       = 'http://packages.elastic.co/GPG-KEY-elasticsearch',
+  $logging_file          = undef,
+  $logging_config        = undef,
+  $logging_template      = undef,
+  $default_logging_level = $elasticsearch::params::default_logging_level,
+  $repo_stage            = false,
+  $instances             = undef,
+  $instances_hiera_merge = false,
+  $plugins               = undef,
+  $plugins_hiera_merge   = false
+) inherits elasticsearch::params {
+
+  anchor {'elasticsearch::begin': }
+
+
+  #### Validate parameters
+
+  # ensure
+  if ! ($ensure in [ 'present', 'absent' ]) {
+    fail("\"${ensure}\" is not a valid ensure parameter value")
+  }
+
+  # autoupgrade
+  validate_bool($autoupgrade)
+
+  # service status
+  if ! ($status in [ 'enabled', 'disabled', 'running', 'unmanaged' ]) {
+    fail("\"${status}\" is not a valid status parameter value")
+  }
+
+  # restart on change
+  validate_bool($restart_on_change)
+
+  # purge conf dir
+  validate_bool($purge_configdir)
+
+  if is_array($elasticsearch::params::service_providers) {
+    # Verify the service provider given is in the array
+    if ! ($service_provider in $elasticsearch::params::service_providers) {
+      fail("\"${service_provider}\" is not a valid provider for \"${::operatingsystem}\"")
+    }
+    $real_service_provider = $service_provider
+  } else {
+    # There is only one option so simply set it
+    $real_service_provider = $elasticsearch::params::service_providers
+  }
+
+  if ($package_url != undef and $version != false) {
+    fail('Unable to set the version number when using package_url option.')
+  }
+
+  if $ensure == 'present' {
+    # validate config hash
+    if ($config != undef) {
+      validate_hash($config)
+    }
+  }
+
+  # java install validation
+  validate_bool($java_install)
+
+  validate_bool($manage_repo)
+
+  if ($manage_repo == true) {
+    if $repo_version == undef {
+      fail('Please fill in a repository version at $repo_version')
+    } else {
+      validate_string($repo_version)
+    }
+  }
+
+  if ($version != false) {
+    case $::osfamily {
+      'RedHat', 'Linux', 'Suse': {
+        if ($version =~ /.+-\d/) {
+          $pkg_version = $version
+        } else {
+          $pkg_version = "${version}-1"
+        }
+      }
+      default: {
+        $pkg_version = $version
+      }
+    }
+  }
+
+  #### Manage actions
+
+  # package(s)
+  class { 'elasticsearch::package': }
+
+  # configuration
+  class { 'elasticsearch::config': }
+
+  # Hiera support for instances
+  validate_bool($instances_hiera_merge)
+
+  if $instances_hiera_merge == true {
+    $x_instances = hiera_hash('elasticsearch::instances', $::elasticsearch::instances)
+  } else {
+    $x_instances = $instances
+  }
+
+  if $x_instances {
+    validate_hash($x_instances)
+    create_resources('elasticsearch::instance', $x_instances)
+  }
+
+  # Hiera support for plugins
+  validate_bool($plugins_hiera_merge)
+
+  if $plugins_hiera_merge == true {
+    $x_plugins = hiera_hash('elasticsearch::plugins', $::elasticsearch::plugins)
+  } else {
+    $x_plugins = $plugins
+  }
+
+  if $x_plugins {
+    validate_hash($x_plugins)
+    create_resources('elasticsearch::plugin', $x_plugins)
+  }
+
+
+  if $java_install == true {
+    # Install java
+    class { '::java':
+      package      => $java_package,
+      distribution => 'jre',
+    }
+
+    # ensure we first install java, the package and then the rest
+    Anchor['elasticsearch::begin']
+    -> Class['::java']
+    -> Class['elasticsearch::package']
+  }
+
+  if ($manage_repo == true) {
+
+    if ($repo_stage == false) {
+      # use anchor for ordering
+
+      # Set up repositories
+      class { 'elasticsearch::repo': }
+
+      # Ensure that we set up the repositories before trying to install
+      # the packages
+      Anchor['elasticsearch::begin']
+      -> Class['elasticsearch::repo']
+      -> Class['elasticsearch::package']
+
+    } else {
+      # use staging for ordering
+
+      if !(defined(Stage[$repo_stage])) {
+        stage { $repo_stage:  before => Stage['main'] }
+      }
+
+      class { 'elasticsearch::repo':
+        stage => $repo_stage,
+      }
+    }
+  }
+
+  #### Manage relationships
+
+  if $ensure == 'present' {
+
+    # we need the software before configuring it
+    Anchor['elasticsearch::begin']
+    -> Class['elasticsearch::package']
+    -> Class['elasticsearch::config']
+    -> Elasticsearch::Plugin <| |>
+    -> Elasticsearch::Instance <| |>
+    -> Elasticsearch::Template <| |>
+
+  } else {
+
+    # make sure all services are getting stopped before software removal
+    Anchor['elasticsearch::begin']
+    -> Elasticsearch::Instance <| |>
+    -> Class['elasticsearch::config']
+    -> Class['elasticsearch::package']
+
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/instance.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,317 @@
+# == Define: elasticsearch::instance
+#
+#  This define allows you to create or remove an elasticsearch instance
+#
+# === Parameters
+#
+# [*ensure*]
+#   String. Controls if the managed resources shall be <tt>present</tt> or
+#   <tt>absent</tt>. If set to <tt>absent</tt>:
+#   * The managed software packages are being uninstalled.
+#   * Any traces of the packages will be purged as good as possible. This may
+#     include existing configuration files. The exact behavior is provider
+#     dependent. Q.v.:
+#     * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP]
+#     * {Puppet's package provider source code}[http://j.mp/wtVCaL]
+#   * System modifications (if any) will be reverted as good as possible
+#     (e.g. removal of created users, services, changed log settings, ...).
+#   * This is thus destructive and should be used with care.
+#   Defaults to <tt>present</tt>.
+#
+# [*status*]
+#   String to define the status of the service. Possible values:
+#   * <tt>enabled</tt>: Service is running and will be started at boot time.
+#   * <tt>disabled</tt>: Service is stopped and will not be started at boot
+#     time.
+#   * <tt>running</tt>: Service is running but will not be started at boot time.
+#     You can use this to start a service on the first Puppet run instead of
+#     the system startup.
+#   * <tt>unmanaged</tt>: Service will not be started at boot time and Puppet
+#     does not care whether the service is running or not. For example, this may
+#     be useful if a cluster management software is used to decide when to start
+#     the service plus assuring it is running on the desired node.
+#   Defaults to <tt>enabled</tt>. The singular form ("service") is used for the
+#   sake of convenience. Of course, the defined status affects all services if
+#   more than one is managed (see <tt>service.pp</tt> to check if this is the
+#   case).
+#
+# [*config*]
+#   Elasticsearch configuration hash
+#
+# [*configdir*]
+#   Path to directory containing the elasticsearch configuration.
+#   Use this setting if your packages deviate from the norm (/etc/elasticsearch)
+#
+# [*datadir*]
+#   Allows you to set the data directory of Elasticsearch
+#
+# [*logging_file*]
+#   Instead of a hash you can supply a puppet:// file source for the logging.yml file
+#
+# [*logging_config*]
+#   Hash representation of information you want in the logging.yml file
+#
+# [*logging_template*]
+#  Use a custom logging template - just supply the reative path ie ${module}/elasticsearch/logging.yml.erb
+#
+# [*logging_level*]
+#   Default logging level for Elasticsearch.
+#   Defaults to: INFO
+#
+# [*init_defaults*]
+#   Defaults file content in hash representation
+#
+# [*init_defaults_file*]
+#   Defaults file as puppet resource
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+define elasticsearch::instance(
+  $ensure             = $elasticsearch::ensure,
+  $status             = $elasticsearch::status,
+  $config             = undef,
+  $configdir          = undef,
+  $datadir            = undef,
+  $logging_file       = undef,
+  $logging_config     = undef,
+  $logging_template   = undef,
+  $logging_level      = $elasticsearch::default_logging_level,
+  $init_defaults      = undef,
+  $init_defaults_file = undef
+) {
+
+  require elasticsearch::params
+
+  File {
+    owner => $elasticsearch::elasticsearch_user,
+    group => $elasticsearch::elasticsearch_group,
+  }
+
+  Exec {
+    path => [ '/bin', '/usr/bin', '/usr/local/bin' ],
+    cwd  => '/',
+  }
+
+  # ensure
+  if ! ($ensure in [ 'present', 'absent' ]) {
+    fail("\"${ensure}\" is not a valid ensure parameter value")
+  }
+
+  $notify_service = $elasticsearch::restart_on_change ? {
+    true  => Elasticsearch::Service[$name],
+    false => undef,
+  }
+
+  # Instance config directory
+  if ($configdir == undef) {
+    $instance_configdir = "${elasticsearch::configdir}/${name}"
+  } else {
+    $instance_configdir = $configdir
+  }
+
+  if ($ensure == 'present') {
+
+    # Configuration hash
+    if ($config == undef) {
+      $instance_config = {}
+    } else {
+      validate_hash($config)
+      $instance_config = $config
+    }
+
+    if(has_key($instance_config, 'node.name')) {
+      $instance_node_name = {}
+    } elsif(has_key($instance_config,'node')) {
+      if(has_key($instance_config['node'], 'name')) {
+        $instance_node_name = {}
+      } else {
+        $instance_node_name = { 'node.name' => "${::hostname}-${name}" }
+      }
+    } else {
+      $instance_node_name = { 'node.name' => "${::hostname}-${name}" }
+    }
+
+    # String or array for data dir(s)
+    if ($datadir == undef) {
+      if (is_array($elasticsearch::datadir)) {
+        $instance_datadir = array_suffix($elasticsearch::datadir, "/${name}")
+      } else {
+        $instance_datadir = "${elasticsearch::datadir}/${name}"
+      }
+    } else {
+      $instance_datadir = $datadir
+    }
+
+    # Logging file or hash
+    if ($logging_file != undef) {
+      $logging_source = $logging_file
+      $logging_content = undef
+    } elsif ($elasticsearch::logging_file != undef) {
+      $logging_source = $elasticsearch::logging_file
+      $logging_content = undef
+    } else {
+
+      if(is_hash($elasticsearch::logging_config)) {
+        $main_logging_config = $elasticsearch::logging_config
+      } else {
+        $main_logging_config = { }
+      }
+
+      if(is_hash($logging_config)) {
+        $instance_logging_config = $logging_config
+      } else {
+        $instance_logging_config = { }
+      }
+      $logging_hash = merge($elasticsearch::params::logging_defaults, $main_logging_config, $instance_logging_config)
+      if ($logging_template != undef ) {
+        $logging_content = template($logging_template)
+      } elsif ($elasticsearch::logging_template != undef) {
+        $logging_content = template($elasticsearch::logging_template)
+      } else {
+        $logging_content = template("${module_name}/etc/elasticsearch/logging.yml.erb")
+      }
+      $logging_source = undef
+    }
+
+    if ($elasticsearch::config != undef) {
+      $main_config = $elasticsearch::config
+    } else {
+      $main_config = { }
+    }
+
+    if(has_key($instance_config, 'path.data')) {
+      $instance_datadir_config = { 'path.data' => $instance_datadir }
+    } elsif(has_key($instance_config, 'path')) {
+      if(has_key($instance_config['path'], 'data')) {
+        $instance_datadir_config = { 'path' => { 'data' => $instance_datadir } }
+      } else {
+        $instance_datadir_config = { 'path.data' => $instance_datadir }
+      }
+    } else {
+      $instance_datadir_config = { 'path.data' => $instance_datadir }
+    }
+
+    if(is_array($instance_datadir)) {
+      $dirs = join($instance_datadir, ' ')
+    } else {
+      $dirs = $instance_datadir
+    }
+
+    exec { "mkdir_datadir_elasticsearch_${name}":
+      command => "mkdir -p ${dirs}",
+      creates => $instance_datadir,
+      require => Class['elasticsearch::package'],
+      before  => Elasticsearch::Service[$name],
+    }
+
+    file { $instance_datadir:
+      ensure  => 'directory',
+      owner   => $elasticsearch::elasticsearch_user,
+      group   => undef,
+      mode    => '0644',
+      recurse => true,
+      require => [ Exec["mkdir_datadir_elasticsearch_${name}"], Class['elasticsearch::package'] ],
+      before  => Elasticsearch::Service[$name],
+    }
+
+    exec { "mkdir_configdir_elasticsearch_${name}":
+      command => "mkdir -p ${instance_configdir}",
+      creates => $elasticsearch::configdir,
+      require => Class['elasticsearch::package'],
+      before  => Elasticsearch::Service[$name],
+    }
+
+    file { $instance_configdir:
+      ensure  => 'directory',
+      mode    => '0644',
+      purge   => $elasticsearch::purge_configdir,
+      force   => $elasticsearch::purge_configdir,
+      require => [ Exec["mkdir_configdir_elasticsearch_${name}"], Class['elasticsearch::package'] ],
+      before  => Elasticsearch::Service[$name],
+    }
+
+    file { "${instance_configdir}/logging.yml":
+      ensure  => file,
+      content => $logging_content,
+      source  => $logging_source,
+      mode    => '0644',
+      notify  => $notify_service,
+      require => Class['elasticsearch::package'],
+      before  => Elasticsearch::Service[$name],
+    }
+
+    file { "${instance_configdir}/scripts":
+      ensure => 'link',
+      target => "${elasticsearch::params::homedir}/scripts",
+    }
+
+    # build up new config
+    $instance_conf = merge($main_config, $instance_node_name, $instance_config, $instance_datadir_config)
+
+    # defaults file content
+    # ensure user did not provide both init_defaults and init_defaults_file
+    if (($init_defaults != undef) and ($init_defaults_file != undef)) {
+      fail ('Only one of $init_defaults and $init_defaults_file should be defined')
+    }
+
+    if (is_hash($elasticsearch::init_defaults)) {
+      $global_init_defaults = $elasticsearch::init_defaults
+    } else {
+      $global_init_defaults = { }
+    }
+
+    $instance_init_defaults_main = { 'CONF_DIR' => $instance_configdir, 'CONF_FILE' => "${instance_configdir}/elasticsearch.yml", 'LOG_DIR' => "/var/log/elasticsearch/${name}", 'ES_HOME' => '/usr/share/elasticsearch' }
+
+    if (is_hash($init_defaults)) {
+      $instance_init_defaults = $init_defaults
+    } else {
+      $instance_init_defaults = { }
+    }
+    $init_defaults_new = merge($global_init_defaults, $instance_init_defaults_main, $instance_init_defaults )
+
+    $user = $elasticsearch::elasticsearch_user
+    $group = $elasticsearch::elasticsearch_group
+
+    datacat_fragment { "main_config_${name}":
+      target => "${instance_configdir}/elasticsearch.yml",
+      data   => $instance_conf,
+    }
+
+    datacat { "${instance_configdir}/elasticsearch.yml":
+      template => "${module_name}/etc/elasticsearch/elasticsearch.yml.erb",
+      notify   => $notify_service,
+      require  => Class['elasticsearch::package'],
+      owner    => $elasticsearch::elasticsearch_user,
+      group    => $elasticsearch::elasticsearch_group,
+    }
+
+    $require_service = Class['elasticsearch::package']
+    $before_service  = undef
+
+  } else {
+
+    file { $instance_configdir:
+      ensure  => 'absent',
+      recurse => true,
+      force   => true,
+    }
+
+    $require_service = undef
+    $before_service  = File[$instance_configdir]
+
+    $init_defaults_new = {}
+  }
+
+  elasticsearch::service { $name:
+    ensure             => $ensure,
+    status             => $status,
+    init_defaults      => $init_defaults_new,
+    init_defaults_file => $init_defaults_file,
+    init_template      => "${module_name}/etc/init.d/${elasticsearch::params::init_template}",
+    require            => $require_service,
+    before             => $before_service,
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/package.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,177 @@
+# == Class: elasticsearch::package
+#
+# This class exists to coordinate all software package management related
+# actions, functionality and logical units in a central place.
+#
+#
+# === Parameters
+#
+# This class does not provide any parameters.
+#
+#
+# === Examples
+#
+# This class may be imported by other classes to use its functionality:
+#   class { 'elasticsearch::package': }
+#
+# It is not intended to be used directly by external resources like node
+# definitions or other modules.
+#
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+class elasticsearch::package {
+
+  Exec {
+    path      => [ '/bin', '/usr/bin', '/usr/local/bin' ],
+    cwd       => '/',
+    tries     => 3,
+    try_sleep => 10,
+  }
+
+  #### Package management
+
+
+  # set params: in operation
+  if $elasticsearch::ensure == 'present' {
+
+    # Create directory to place the package file
+    exec { 'create_package_dir_elasticsearch':
+      cwd     => '/',
+      path    => ['/usr/bin', '/bin'],
+      command => "mkdir -p ${elasticsearch::package_dir}",
+      creates => $elasticsearch::package_dir,
+    }
+
+    file { $elasticsearch::package_dir:
+      ensure  => 'directory',
+      purge   => $elasticsearch::purge_package_dir,
+      force   => $elasticsearch::purge_package_dir,
+      backup  => false,
+      require => Exec['create_package_dir_elasticsearch'],
+    }
+
+
+    # Check if we want to install a specific version or not
+    if $elasticsearch::version == false {
+
+      $package_ensure = $elasticsearch::autoupgrade ? {
+        true  => 'latest',
+        false => 'present',
+      }
+
+    } else {
+
+      # install specific version
+      $package_ensure = $elasticsearch::pkg_version
+
+    }
+
+    # action
+    if ($elasticsearch::package_url != undef) {
+
+      case $elasticsearch::package_provider {
+        'package': { $before = Package[$elasticsearch::package_name]  }
+        default:   { fail("software provider \"${elasticsearch::package_provider}\".") }
+      }
+
+      $package_dir = $elasticsearch::package_dir
+
+      $filenameArray = split($elasticsearch::package_url, '/')
+      $basefilename = $filenameArray[-1]
+
+      $sourceArray = split($elasticsearch::package_url, ':')
+      $protocol_type = $sourceArray[0]
+
+      $extArray = split($basefilename, '\.')
+      $ext = $extArray[-1]
+
+      $pkg_source = "${package_dir}/${basefilename}"
+
+      case $protocol_type {
+
+        'puppet': {
+
+          file { $pkg_source:
+            ensure  => file,
+            source  => $elasticsearch::package_url,
+            require => File[$package_dir],
+            backup  => false,
+            before  => $before,
+          }
+
+        }
+        'ftp', 'https', 'http': {
+
+          if $elasticsearch::proxy_url != undef {
+            $exec_environment = [
+              'use_proxy=yes',
+              "http_proxy=${elasticsearch::proxy_url}",
+              "https_proxy=${elasticsearch::proxy_url}",
+            ]
+          }
+
+          exec { 'download_package_elasticsearch':
+            command     => "${elasticsearch::params::download_tool} ${pkg_source} ${elasticsearch::package_url} 2> /dev/null",
+            creates     => $pkg_source,
+            environment => $exec_environment,
+            timeout     => $elasticsearch::package_dl_timeout,
+            require     => File[$package_dir],
+            before      => $before,
+          }
+
+        }
+        'file': {
+
+          $source_path = $sourceArray[1]
+          file { $pkg_source:
+            ensure  => file,
+            source  => $source_path,
+            require => File[$package_dir],
+            backup  => false,
+            before  => $before,
+          }
+
+        }
+        default: {
+          fail("Protocol must be puppet, file, http, https, or ftp. You have given \"${protocol_type}\"")
+        }
+      }
+
+      if ($elasticsearch::package_provider == 'package') {
+
+        case $ext {
+          'deb':   { Package { provider => 'dpkg', source => $pkg_source } }
+          'rpm':   { Package { provider => 'rpm', source => $pkg_source } }
+          default: { fail("Unknown file extention \"${ext}\".") }
+        }
+
+      }
+
+    }
+
+  # Package removal
+  } else {
+
+    if ($::operatingsystem == 'OpenSuSE') {
+      Package {
+        provider  => 'rpm',
+      }
+    }
+    $package_ensure = 'purged'
+
+  }
+
+  if ($elasticsearch::package_provider == 'package') {
+
+    package { $elasticsearch::package_name:
+      ensure   => $package_ensure,
+    }
+
+  } else {
+    fail("\"${elasticsearch::package_provider}\" is not supported")
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/params.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,220 @@
+# == Class: elasticsearch::params
+#
+# This class exists to
+# 1. Declutter the default value assignment for class parameters.
+# 2. Manage internally used module variables in a central place.
+#
+# Therefore, many operating system dependent differences (names, paths, ...)
+# are addressed in here.
+#
+#
+# === Parameters
+#
+# This class does not provide any parameters.
+#
+#
+# === Examples
+#
+# This class is not intended to be used directly.
+#
+#
+# === Links
+#
+# * {Puppet Docs: Using Parameterized Classes}[http://j.mp/nVpyWY]
+#
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard@ispavailability.com>
+#
+class elasticsearch::params {
+
+  #### Default values for the parameters of the main module class, init.pp
+
+  # ensure
+  $ensure = 'present'
+
+  # autoupgrade
+  $autoupgrade = false
+
+  # service status
+  $status = 'enabled'
+
+  # restart on configuration change?
+  $restart_on_change = true
+
+  # Purge configuration directory
+  $purge_configdir = false
+
+  $purge_package_dir = false
+
+  # package download timeout
+  $package_dl_timeout = 600 # 300 seconds is default of puppet
+
+  $default_logging_level = 'INFO'
+
+  $logging_defaults = {
+    'action'                 => 'DEBUG',
+    'com.amazonaws'          => 'WARN',
+    'index.search.slowlog'   => 'TRACE, index_search_slow_log_file',
+    'index.indexing.slowlog' => 'TRACE, index_indexing_slow_log_file',
+  }
+
+  #### Internal module values
+
+  # User and Group for the files and user to run the service as.
+  case $::kernel {
+    'Linux': {
+      $elasticsearch_user  = 'elasticsearch'
+      $elasticsearch_group = 'elasticsearch'
+    }
+    'Darwin': {
+      $elasticsearch_user  = 'elasticsearch'
+      $elasticsearch_group = 'elasticsearch'
+    }
+    default: {
+      fail("\"${module_name}\" provides no user/group default value
+           for \"${::kernel}\"")
+    }
+  }
+
+  # Download tool
+
+  case $::kernel {
+    'Linux': {
+      $download_tool = 'wget --no-check-certificate -O'
+    }
+    'Darwin': {
+      $download_tool = 'curl --insecure -o'
+    }
+    default: {
+      fail("\"${module_name}\" provides no download tool default value
+           for \"${::kernel}\"")
+    }
+  }
+
+  # Different path definitions
+  case $::kernel {
+    'Linux': {
+      $configdir   = '/etc/elasticsearch'
+      $logdir      = '/var/log/elasticsearch'
+      $package_dir = '/opt/elasticsearch/swdl'
+      $installpath = '/opt/elasticsearch'
+      $homedir     = '/usr/share/elasticsearch'
+      $plugindir   = "${homedir}/plugins"
+      $plugintool  = "${homedir}/bin/plugin"
+      $datadir     = '/usr/share/elasticsearch/data'
+    }
+    default: {
+      fail("\"${module_name}\" provides no config directory default value
+           for \"${::kernel}\"")
+    }
+  }
+
+  # packages
+  case $::operatingsystem {
+    'RedHat', 'CentOS', 'Fedora', 'Scientific', 'Amazon', 'OracleLinux', 'SLC': {
+      # main application
+      $package = [ 'elasticsearch' ]
+    }
+    'Debian', 'Ubuntu': {
+      # main application
+      $package = [ 'elasticsearch' ]
+    }
+    'OpenSuSE': {
+      $package = [ 'elasticsearch' ]
+    }
+    default: {
+      fail("\"${module_name}\" provides no package default value
+            for \"${::operatingsystem}\"")
+    }
+  }
+
+  # service parameters
+  case $::operatingsystem {
+    'RedHat', 'CentOS', 'Fedora', 'Scientific', 'OracleLinux', 'SLC': {
+      $service_name       = 'elasticsearch'
+      $service_hasrestart = true
+      $service_hasstatus  = true
+      $service_pattern    = $service_name
+      $defaults_location  = '/etc/sysconfig'
+      $pid_dir            = '/var/run/elasticsearch'
+
+      if versioncmp($::operatingsystemmajrelease, '7') >= 0 {
+        $init_template     = 'elasticsearch.systemd.erb'
+        $service_providers = 'systemd'
+      } else {
+        $init_template     = 'elasticsearch.RedHat.erb'
+        $service_providers = 'init'
+      }
+
+    }
+    'Amazon': {
+      $service_name       = 'elasticsearch'
+      $service_hasrestart = true
+      $service_hasstatus  = true
+      $service_pattern    = $service_name
+      $defaults_location  = '/etc/sysconfig'
+      $pid_dir            = '/var/run/elasticsearch'
+      $init_template      = 'elasticsearch.RedHat.erb'
+      $service_providers  = 'init'
+    }
+    'Debian': {
+      $service_name       = 'elasticsearch'
+      $service_hasrestart = true
+      $service_hasstatus  = true
+      $service_pattern    = $service_name
+      $defaults_location  = '/etc/default'
+      if versioncmp($::operatingsystemmajrelease, '8') >= 0 {
+        $init_template     = 'elasticsearch.systemd.erb'
+        $service_providers = 'systemd'
+        $pid_dir           = '/var/run/elasticsearch'
+      } else {
+        $init_template     = 'elasticsearch.Debian.erb'
+        $service_providers = [ 'init' ]
+        $pid_dir           = false
+      }
+    }
+    'Ubuntu': {
+      $service_name       = 'elasticsearch'
+      $service_hasrestart = true
+      $service_hasstatus  = true
+      $service_pattern    = $service_name
+      $defaults_location  = '/etc/default'
+
+      if versioncmp($::operatingsystemmajrelease, '15') >= 0 {
+        $init_template     = 'elasticsearch.systemd.erb'
+        $service_providers = 'systemd'
+        $pid_dir           = '/var/run/elasticsearch'
+      } else {
+        $init_template     = 'elasticsearch.Debian.erb'
+        $service_providers = [ 'init' ]
+        $pid_dir           = false
+      }
+    }
+    'Darwin': {
+      $service_name       = 'FIXME/TODO'
+      $service_hasrestart = true
+      $service_hasstatus  = true
+      $service_pattern    = $service_name
+      $service_providers  = 'launchd'
+      $defaults_location  = false
+      $pid_dir            = false
+    }
+    'OpenSuSE': {
+      $service_name       = 'elasticsearch'
+      $service_hasrestart = true
+      $service_hasstatus  = true
+      $service_pattern    = $service_name
+      $service_providers  = 'systemd'
+      $defaults_location  = '/etc/sysconfig'
+      $init_template      = 'elasticsearch.systemd.erb'
+      $pid_dir            = '/var/run/elasticsearch'
+    }
+    default: {
+      fail("\"${module_name}\" provides no service parameters
+            for \"${::operatingsystem}\"")
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/plugin.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,147 @@
+# == Define: elasticsearch::plugin
+#
+# This define allows you to install arbitrary Elasticsearch plugins
+# either by using the default repositories or by specifying an URL
+#
+# All default values are defined in the elasticsearch::params class.
+#
+#
+# === Parameters
+#
+# [*module_dir*]
+#   Directory name where the module will be installed
+#   Value type is string
+#   Default value: None
+#   This variable is deprecated
+#
+# [*ensure*]
+#   Whether the plugin will be installed or removed.
+#   Set to 'absent' to ensure a plugin is not installed
+#   Value type is string
+#   Default value: present
+#   This variable is optional
+#
+# [*url*]
+#   Specify an URL where to download the plugin from.
+#   Value type is string
+#   Default value: None
+#   This variable is optional
+#
+# [*source*]
+#   Specify the source of the plugin.
+#   This will copy over the plugin to the node and use it for installation.
+#   Useful for offline installation
+#   Value type is string
+#   This variable is optional
+#
+# [*proxy_host*]
+#   Proxy host to use when installing the plugin
+#   Value type is string
+#   Default value: None
+#   This variable is optional
+#
+# [*proxy_port*]
+#   Proxy port to use when installing the plugin
+#   Value type is number
+#   Default value: None
+#   This variable is optional
+#
+# [*instances*]
+#   Specify all the instances related
+#   value type is string or array
+#
+# === Examples
+#
+# # From official repository
+# elasticsearch::plugin{'mobz/elasticsearch-head': module_dir => 'head'}
+#
+# # From custom url
+# elasticsearch::plugin{ 'elasticsearch-jetty':
+#  module_dir => 'elasticsearch-jetty',
+#  url        => 'https://oss-es-plugins.s3.amazonaws.com/elasticsearch-jetty/elasticsearch-jetty-0.90.0.zip',
+# }
+#
+# === Authors
+#
+# * Matteo Sessa <mailto:matteo.sessa@catchoftheday.com.au>
+# * Dennis Konert <mailto:dkonert@gmail.com>
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+define elasticsearch::plugin(
+    $instances,
+    $module_dir  = undef,
+    $ensure      = 'present',
+    $url         = undef,
+    $source      = undef,
+    $proxy_host  = undef,
+    $proxy_port  = undef,
+) {
+
+  include elasticsearch
+
+  $notify_service = $elasticsearch::restart_on_change ? {
+    false   => undef,
+    default => Elasticsearch::Service[$instances],
+  }
+
+  if ($module_dir != undef) {
+    warning("module_dir settings is deprecated for plugin ${name}. The directory is now auto detected.")
+  }
+
+  # set proxy by override or parse and use proxy_url from
+  # elasticsearch::proxy_url or use no proxy at all
+  
+  if ($proxy_host != undef and $proxy_port != undef) {
+    $proxy = "-DproxyPort=${proxy_port} -DproxyHost=${proxy_host}"
+  }
+  elsif ($elasticsearch::proxy_url != undef) {
+    $proxy_host_from_url = regsubst($elasticsearch::proxy_url, '(http|https)://([^:]+)(|:\d+).+', '\2')
+    $proxy_port_from_url = regsubst($elasticsearch::proxy_url, '(?:http|https)://[^:/]+(?::([0-9]+))?(?:/.*)?', '\1')
+    
+    # validate parsed values before using them
+    if (is_string($proxy_host_from_url) and is_integer($proxy_port_from_url)) {
+      $proxy = "-DproxyPort=${proxy_port_from_url} -DproxyHost=${proxy_host_from_url}"
+    }
+  }
+  else {
+    $proxy = undef
+  }
+
+  if ($source != undef) {
+
+    $filenameArray = split($source, '/')
+    $basefilename = $filenameArray[-1]
+
+    $file_source = "${elasticsearch::package_dir}/${basefilename}"
+
+    file { $file_source:
+      ensure => 'file',
+      source => $source,
+    }
+
+  } elsif ($url != undef) {
+    validate_string($url)
+  }
+
+  case $ensure {
+    'installed', 'present': {
+
+      elasticsearch_plugin { $name:
+        ensure     => 'present',
+        source     => $file_source,
+        url        => $url,
+        proxy_args => $proxy,
+        notify     => $notify_service,
+      }
+
+    }
+    'absent': {
+      elasticsearch_plugin { $name:
+        ensure => absent,
+      }
+    }
+    default: {
+      fail("${ensure} is not a valid ensure command.")
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/python.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,70 @@
+# == Define: elasticsearch::python
+#
+# there are many python bindings for elasticsearch. This provides all
+# the ones we know about http://www.elasticsearch.org/guide/clients/
+#
+# === Parameters
+#
+# [*ensure*]
+#   String. Controls if the managed resources shall be <tt>present</tt> or
+#   <tt>absent</tt>. If set to <tt>absent</tt>:
+#   * The managed software packages are being uninstalled.
+#   * Any traces of the packages will be purged as good as possible. This may
+#     include existing configuration files. The exact behavior is provider
+#     dependent. Q.v.:
+#     * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP]
+#     * {Puppet's package provider source code}[http://j.mp/wtVCaL]
+#   * System modifications (if any) will be reverted as good as possible
+#     (e.g. removal of created users, services, changed log settings, ...).
+#   * This is thus destructive and should be used with care.
+#   Defaults to <tt>present</tt>.
+#
+# === Examples
+#
+# elasticsearch::python { 'pyes':; }
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+define elasticsearch::python (
+  $ensure = 'present'
+) {
+
+  if ! ($ensure in [ 'present', 'absent' ]) {
+    fail("\"${ensure}\" is not a valid ensure parameter value")
+  }
+
+  # make sure the package name is valid and setup the provider as
+  # necessary
+  case $name {
+    'pyes': {
+      $provider = 'pip'
+    }
+    'rawes': {
+      $provider = 'pip'
+    }
+    'pyelasticsearch': {
+      $provider = 'pip'
+    }
+    'ESClient': {
+      $provider = 'pip'
+    }
+    'elasticutils': {
+      $provider = 'pip'
+    }
+    'elasticsearch': {
+      $provider = 'pip'
+    }
+    default: {
+      fail("unknown python binding package '${name}'")
+    }
+  }
+
+  package { "python_${name}":
+    ensure   => $ensure,
+    name     => $name,
+    provider => $provider,
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/repo.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,106 @@
+# == Class: elasticsearch::repo
+#
+# This class exists to install and manage yum and apt repositories
+# that contain elasticsearch official elasticsearch packages
+#
+#
+# === Parameters
+#
+# This class does not provide any parameters.
+#
+#
+# === Examples
+#
+# This class may be imported by other classes to use its functionality:
+#   class { 'elasticsearch::repo': }
+#
+# It is not intended to be used directly by external resources like node
+# definitions or other modules.
+#
+#
+# === Authors
+#
+# * Phil Fenstermacher <mailto:phillip.fenstermacher@gmail.com>
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+class elasticsearch::repo {
+
+  Exec {
+    path      => [ '/bin', '/usr/bin', '/usr/local/bin' ],
+    cwd       => '/',
+  }
+
+  case $::osfamily {
+    'Debian': {
+      include ::apt
+      Class['apt::update'] -> Package[$elasticsearch::package_name]
+
+      apt::source { 'elasticsearch':
+        location    => "http://packages.elastic.co/elasticsearch/${elasticsearch::repo_version}/debian",
+        release     => 'stable',
+        repos       => 'main',
+        key         => $::elasticsearch::repo_key_id,
+        key_source  => $::elasticsearch::repo_key_source,
+        include_src => false,
+      }
+    }
+    'RedHat', 'Linux': {
+      yumrepo { 'elasticsearch':
+        descr    => 'elasticsearch repo',
+        baseurl  => "http://packages.elastic.co/elasticsearch/${elasticsearch::repo_version}/centos",
+        gpgcheck => 1,
+        gpgkey   => $::elasticsearch::repo_key_source,
+        enabled  => 1,
+      }
+    }
+    'Suse': {
+      exec { 'elasticsearch_suse_import_gpg':
+        command => "rpmkeys --import ${::elasticsearch::repo_key_source}",
+        unless  => "test $(rpm -qa gpg-pubkey | grep -i '${::elasticsearch::repo_key_id}' | wc -l) -eq 1 ",
+        notify  => [ Zypprepo['elasticsearch'] ],
+      }
+
+      zypprepo { 'elasticsearch':
+        baseurl     => "http://packages.elastic.co/elasticsearch/${elasticsearch::repo_version}/centos",
+        enabled     => 1,
+        autorefresh => 1,
+        name        => 'elasticsearch',
+        gpgcheck    => 1,
+        gpgkey      => $::elasticsearch::repo_key_source,
+        type        => 'yum',
+      }
+    }
+    default: {
+      fail("\"${module_name}\" provides no repository information for OSfamily \"${::osfamily}\"")
+    }
+  }
+
+  # Package pinning
+
+    case $::osfamily {
+      'Debian': {
+        include ::apt
+
+        if ($elasticsearch::package_pin == true and $elasticsearch::version != false) {
+          apt::pin { $elasticsearch::package_name:
+            ensure   => 'present',
+            packages => $elasticsearch::package_name,
+            version  => $elasticsearch::version,
+            priority => 1000,
+          }
+        }
+
+      }
+      'RedHat', 'Linux': {
+
+        if ($elasticsearch::package_pin == true and $elasticsearch::version != false) {
+          yum::versionlock { "0:elasticsearch-${elasticsearch::pkg_version}.noarch":
+            ensure => 'present',
+          }
+        }
+      }
+      default: {
+        warning("Unable to pin package for OSfamily \"${::osfamily}\".")
+      }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/ruby.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,67 @@
+# == Define: elasticsearch::ruby
+#
+# there are many ruby bindings for elasticsearch. This provides all
+# the ones we know about http://www.elasticsearch.org/guide/clients/
+#
+# === Parameters
+#
+# [*ensure*]
+#   String. Controls if the managed resources shall be <tt>present</tt> or
+#   <tt>absent</tt>. If set to <tt>absent</tt>:
+#   * The managed software packages are being uninstalled.
+#   * Any traces of the packages will be purged as good as possible. This may
+#     include existing configuration files. The exact behavior is provider
+#     dependent. Q.v.:
+#     * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP]
+#     * {Puppet's package provider source code}[http://j.mp/wtVCaL]
+#   * System modifications (if any) will be reverted as good as possible
+#     (e.g. removal of created users, services, changed log settings, ...).
+#   * This is thus destructive and should be used with care.
+#   Defaults to <tt>present</tt>.
+#
+# === Examples
+#
+# elasticsearch::ruby { 'elasticsearch':; }
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard@ispavailability.com>
+#
+define elasticsearch::ruby (
+  $ensure = 'present'
+) {
+
+  if ! ($ensure in [ 'present', 'absent' ]) {
+    fail("\"${ensure}\" is not a valid ensure parameter value")
+  }
+
+  # make sure the package name is valid and setup the provider as
+  # necessary
+  case $name {
+    'tire': {
+      $provider = 'gem'
+    }
+    'stretcher': {
+      $provider = 'gem'
+    }
+    'elastic_searchable': {
+      $provider = 'gem'
+    }
+    'elasticsearch': {
+      $provider = 'gem'
+    }
+    'flex': {
+      $provider = 'gem'
+    }
+    default: {
+      fail("unknown ruby client package '${name}'")
+    }
+  }
+
+  package { "ruby_${name}":
+    ensure   => $ensure,
+    name     => $name,
+    provider => $provider,
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/script.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,55 @@
+# == Define: elasticsearch::script
+#
+#  This define allows you to insert, update or delete scripts that are used within Elasticsearch
+#
+# === Parameters
+#
+# [*ensure*]
+#   String. Controls if the managed resources shall be <tt>present</tt> or
+#   <tt>absent</tt>. If set to <tt>absent</tt>:
+#   * The managed software packages are being uninstalled.
+#   * Any traces of the packages will be purged as good as possible. This may
+#     include existing configuration files. The exact behavior is provider
+#     dependent. Q.v.:
+#     * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP]
+#     * {Puppet's package provider source code}[http://j.mp/wtVCaL]
+#   * System modifications (if any) will be reverted as good as possible
+#     (e.g. removal of created users, services, changed log settings, ...).
+#   * This is thus destructive and should be used with care.
+#   Defaults to <tt>present</tt>.
+#
+# [*source*]
+#   Puppet source of the script
+#   Value type is string
+#   Default value: undef
+#   This variable is mandatory
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+define elasticsearch::script(
+  $source,
+  $ensure  = 'present',
+) {
+
+  require elasticsearch
+
+  # ensure
+  if ! ($ensure in [ 'present', 'absent' ]) {
+    fail("\"${ensure}\" is not a valid ensure parameter value")
+  }
+
+  validate_re($source, '^(puppet|file)://')
+
+  $filenameArray = split($source, '/')
+  $basefilename = $filenameArray[-1]
+
+  file { "${elasticsearch::params::homedir}/scripts/${basefilename}":
+    ensure => $ensure,
+    source => $source,
+    owner  => $elasticsearch::elasticsearch_user,
+    group  => $elasticsearch::elasticsearch_group,
+    mode   => '0644',
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/service.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,91 @@
+# == Class: elasticsearch::service
+#
+# This class exists to coordinate all service management related actions,
+# functionality and logical units in a central place.
+#
+# <b>Note:</b> "service" is the Puppet term and type for background processes
+# in general and is used in a platform-independent way. E.g. "service" means
+# "daemon" in relation to Unix-like systems.
+#
+#
+# === Parameters
+#
+# [*ensure*]
+#   String. Controls if the managed resources shall be <tt>present</tt> or
+#   <tt>absent</tt>. If set to <tt>absent</tt>:
+#   * The managed software packages are being uninstalled.
+#   * Any traces of the packages will be purged as good as possible. This may
+#     include existing configuration files. The exact behavior is provider
+#     dependent. Q.v.:
+#     * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP]
+#     * {Puppet's package provider source code}[http://j.mp/wtVCaL]
+#   * System modifications (if any) will be reverted as good as possible
+#     (e.g. removal of created users, services, changed log settings, ...).
+#   * This is thus destructive and should be used with care.
+#   Defaults to <tt>present</tt>.
+#
+# [*status*]
+#   String to define the status of the service. Possible values:
+#   * <tt>enabled</tt>: Service is running and will be started at boot time.
+#   * <tt>disabled</tt>: Service is stopped and will not be started at boot
+#     time.
+#   * <tt>running</tt>: Service is running but will not be started at boot time.
+#     You can use this to start a service on the first Puppet run instead of
+#     the system startup.
+#   * <tt>unmanaged</tt>: Service will not be started at boot time and Puppet
+#     does not care whether the service is running or not. For example, this may
+#     be useful if a cluster management software is used to decide when to start
+#     the service plus assuring it is running on the desired node.
+#   Defaults to <tt>enabled</tt>. The singular form ("service") is used for the
+#   sake of convenience. Of course, the defined status affects all services if
+#   more than one is managed (see <tt>service.pp</tt> to check if this is the
+#   case).
+#
+# [*init_defaults*]
+#   Defaults file content in hash representation
+#
+# [*init_defaults_file*]
+#   Defaults file as puppet resource
+#
+# [*init_template*]
+#   Service file as a template
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+define elasticsearch::service(
+  $ensure             = $elasticsearch::ensure,
+  $status             = $elasticsearch::status,
+  $init_defaults_file = undef,
+  $init_defaults      = undef,
+  $init_template      = undef,
+) {
+
+  case $elasticsearch::real_service_provider {
+
+    'init': {
+      elasticsearch::service::init { $name:
+        ensure             => $ensure,
+        status             => $status,
+        init_defaults_file => $init_defaults_file,
+        init_defaults      => $init_defaults,
+        init_template      => $init_template,
+      }
+    }
+    'systemd': {
+      elasticsearch::service::systemd { $name:
+        ensure             => $ensure,
+        status             => $status,
+        init_defaults_file => $init_defaults_file,
+        init_defaults      => $init_defaults,
+        init_template      => $init_template,
+      }
+    }
+    default: {
+      fail("Unknown service provider ${elasticsearch::real_service_provider}")
+    }
+
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/service/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,195 @@
+# == Define: elasticsearch::service::init
+#
+# This class exists to coordinate all service management related actions,
+# functionality and logical units in a central place.
+#
+# <b>Note:</b> "service" is the Puppet term and type for background processes
+# in general and is used in a platform-independent way. E.g. "service" means
+# "daemon" in relation to Unix-like systems.
+#
+#
+# === Parameters
+#
+# [*ensure*]
+#   String. Controls if the managed resources shall be <tt>present</tt> or
+#   <tt>absent</tt>. If set to <tt>absent</tt>:
+#   * The managed software packages are being uninstalled.
+#   * Any traces of the packages will be purged as good as possible. This may
+#     include existing configuration files. The exact behavior is provider
+#     dependent. Q.v.:
+#     * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP]
+#     * {Puppet's package provider source code}[http://j.mp/wtVCaL]
+#   * System modifications (if any) will be reverted as good as possible
+#     (e.g. removal of created users, services, changed log settings, ...).
+#   * This is thus destructive and should be used with care.
+#   Defaults to <tt>present</tt>.
+#
+# [*status*]
+#   String to define the status of the service. Possible values:
+#   * <tt>enabled</tt>: Service is running and will be started at boot time.
+#   * <tt>disabled</tt>: Service is stopped and will not be started at boot
+#     time.
+#   * <tt>running</tt>: Service is running but will not be started at boot time.
+#     You can use this to start a service on the first Puppet run instead of
+#     the system startup.
+#   * <tt>unmanaged</tt>: Service will not be started at boot time and Puppet
+#     does not care whether the service is running or not. For example, this may
+#     be useful if a cluster management software is used to decide when to start
+#     the service plus assuring it is running on the desired node.
+#   Defaults to <tt>enabled</tt>. The singular form ("service") is used for the
+#   sake of convenience. Of course, the defined status affects all services if
+#   more than one is managed (see <tt>service.pp</tt> to check if this is the
+#   case).
+#
+# [*init_defaults*]
+#   Defaults file content in hash representation
+#
+# [*init_defaults_file*]
+#   Defaults file as puppet resource
+#
+# [*init_template*]
+#   Service file as a template
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+define elasticsearch::service::init(
+  $ensure             = $elasticsearch::ensure,
+  $status             = $elasticsearch::status,
+  $init_defaults_file = undef,
+  $init_defaults      = undef,
+  $init_template      = undef,
+) {
+
+  #### Service management
+
+  # set params: in operation
+  if $ensure == 'present' {
+
+    case $status {
+      # make sure service is currently running, start it on boot
+      'enabled': {
+        $service_ensure = 'running'
+        $service_enable = true
+      }
+      # make sure service is currently stopped, do not start it on boot
+      'disabled': {
+        $service_ensure = 'stopped'
+        $service_enable = false
+      }
+      # make sure service is currently running, do not start it on boot
+      'running': {
+        $service_ensure = 'running'
+        $service_enable = false
+      }
+      # do not start service on boot, do not care whether currently running
+      # or not
+      'unmanaged': {
+        $service_ensure = undef
+        $service_enable = false
+      }
+      # unknown status
+      # note: don't forget to update the parameter check in init.pp if you
+      #       add a new or change an existing status.
+      default: {
+        fail("\"${status}\" is an unknown service status value")
+      }
+    }
+
+  # set params: removal
+  } else {
+
+    # make sure the service is stopped and disabled (the removal itself will be
+    # done by package.pp)
+    $service_ensure = 'stopped'
+    $service_enable = false
+
+  }
+
+  $notify_service = $elasticsearch::restart_on_change ? {
+    true  => Service["elasticsearch-instance-${name}"],
+    false => undef,
+  }
+
+
+  if ( $status != 'unmanaged' and $ensure == 'present' ) {
+
+    # defaults file content. Either from a hash or file
+    if ($init_defaults_file != undef) {
+      file { "${elasticsearch::params::defaults_location}/elasticsearch-${name}":
+        ensure => $ensure,
+        source => $init_defaults_file,
+        owner  => 'root',
+        group  => 'root',
+        mode   => '0644',
+        before => Service["elasticsearch-instance-${name}"],
+        notify => $notify_service,
+      }
+
+    } elsif ($init_defaults != undef and is_hash($init_defaults) ) {
+
+      if(has_key($init_defaults, 'ES_USER')) {
+        if($init_defaults['ES_USER'] != $elasticsearch::elasticsearch_user) {
+          fail('Found ES_USER setting for init_defaults but is not same as elasticsearch_user setting. Please use elasticsearch_user setting.')
+        }
+      }
+
+      $init_defaults_pre_hash = { 'ES_USER' => $elasticsearch::elasticsearch_user, 'ES_GROUP' => $elasticsearch::elasticsearch_group, 'MAX_OPEN_FILES' => '65535' }
+      $new_init_defaults = merge($init_defaults_pre_hash, $init_defaults)
+
+      augeas { "defaults_${name}":
+        incl    => "${elasticsearch::params::defaults_location}/elasticsearch-${name}",
+        lens    => 'Shellvars.lns',
+        changes => template("${module_name}/etc/sysconfig/defaults.erb"),
+        before  => Service["elasticsearch-instance-${name}"],
+        notify  => $notify_service,
+      }
+
+    }
+
+    # init file from template
+    if ($init_template != undef) {
+
+      file { "/etc/init.d/elasticsearch-${name}":
+        ensure  => $ensure,
+        content => template($init_template),
+        owner   => 'root',
+        group   => 'root',
+        mode    => '0755',
+        before  => Service["elasticsearch-instance-${name}"],
+        notify  => $notify_service,
+      }
+
+    }
+
+  } elsif ($status != 'unmanaged') {
+
+    file { "/etc/init.d/elasticsearch-${name}":
+      ensure    => 'absent',
+      subscribe => Service["elasticsearch-instance-${name}"],
+    }
+
+    file { "${elasticsearch::params::defaults_location}/elasticsearch-${name}":
+      ensure    => 'absent',
+      subscribe => Service["elasticsearch-${$name}"],
+    }
+
+  }
+
+
+  if ( $status != 'unmanaged') {
+
+    # action
+    service { "elasticsearch-instance-${name}":
+      ensure     => $service_ensure,
+      enable     => $service_enable,
+      name       => "elasticsearch-${name}",
+      hasstatus  => $elasticsearch::params::service_hasstatus,
+      hasrestart => $elasticsearch::params::service_hasrestart,
+      pattern    => $elasticsearch::params::service_pattern,
+    }
+
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/service/systemd.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,216 @@
+# == Define: elasticsearch::service::systemd
+#
+# This define exists to coordinate all service management related actions,
+# functionality and logical units in a central place.
+#
+# <b>Note:</b> "service" is the Puppet term and type for background processes
+# in general and is used in a platform-independent way. E.g. "service" means
+# "daemon" in relation to Unix-like systems.
+#
+#
+# === Parameters
+#
+# [*ensure*]
+#   String. Controls if the managed resources shall be <tt>present</tt> or
+#   <tt>absent</tt>. If set to <tt>absent</tt>:
+#   * The managed software packages are being uninstalled.
+#   * Any traces of the packages will be purged as good as possible. This may
+#     include existing configuration files. The exact behavior is provider
+#     dependent. Q.v.:
+#     * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP]
+#     * {Puppet's package provider source code}[http://j.mp/wtVCaL]
+#   * System modifications (if any) will be reverted as good as possible
+#     (e.g. removal of created users, services, changed log settings, ...).
+#   * This is thus destructive and should be used with care.
+#   Defaults to <tt>present</tt>.
+#
+# [*status*]
+#   String to define the status of the service. Possible values:
+#   * <tt>enabled</tt>: Service is running and will be started at boot time.
+#   * <tt>disabled</tt>: Service is stopped and will not be started at boot
+#     time.
+#   * <tt>running</tt>: Service is running but will not be started at boot time.
+#     You can use this to start a service on the first Puppet run instead of
+#     the system startup.
+#   * <tt>unmanaged</tt>: Service will not be started at boot time and Puppet
+#     does not care whether the service is running or not. For example, this may
+#     be useful if a cluster management software is used to decide when to start
+#     the service plus assuring it is running on the desired node.
+#   Defaults to <tt>enabled</tt>. The singular form ("service") is used for the
+#   sake of convenience. Of course, the defined status affects all services if
+#   more than one is managed (see <tt>service.pp</tt> to check if this is the
+#   case).
+#
+# [*init_defaults*]
+#   Defaults file content in hash representation
+#
+# [*init_defaults_file*]
+#   Defaults file as puppet resource
+#
+# [*init_template*]
+#   Service file as a template
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+define elasticsearch::service::systemd(
+  $ensure             = $elasticsearch::ensure,
+  $status             = $elasticsearch::status,
+  $init_defaults_file = undef,
+  $init_defaults      = undef,
+  $init_template      = undef,
+) {
+
+  #### Service management
+
+  # set params: in operation
+  if $ensure == 'present' {
+
+    case $status {
+      # make sure service is currently running, start it on boot
+      'enabled': {
+        $service_ensure = 'running'
+        $service_enable = true
+      }
+      # make sure service is currently stopped, do not start it on boot
+      'disabled': {
+        $service_ensure = 'stopped'
+        $service_enable = false
+      }
+      # make sure service is currently running, do not start it on boot
+      'running': {
+        $service_ensure = 'running'
+        $service_enable = false
+      }
+      # do not start service on boot, do not care whether currently running
+      # or not
+      'unmanaged': {
+        $service_ensure = undef
+        $service_enable = false
+      }
+      # unknown status
+      # note: don't forget to update the parameter check in init.pp if you
+      #       add a new or change an existing status.
+      default: {
+        fail("\"${status}\" is an unknown service status value")
+      }
+    }
+  } else {
+    # make sure the service is stopped and disabled (the removal itself will be
+    # done by package.pp)
+    $service_ensure = 'stopped'
+    $service_enable = false
+  }
+
+  $notify_service = $elasticsearch::restart_on_change ? {
+    true  => [ Exec["systemd_reload_${name}"], Service["elasticsearch-instance-${name}"] ],
+    false => Exec["systemd_reload_${name}"]
+  }
+
+  if ( $status != 'unmanaged' and $ensure == 'present' ) {
+
+    # defaults file content. Either from a hash or file
+    if ($init_defaults_file != undef) {
+      file { "${elasticsearch::params::defaults_location}/elasticsearch-${name}":
+        ensure => $ensure,
+        source => $init_defaults_file,
+        owner  => 'root',
+        group  => 'root',
+        mode   => '0644',
+        before => Service["elasticsearch-instance-${name}"],
+        notify => $notify_service,
+      }
+
+    } else {
+      if ($init_defaults != undef and is_hash($init_defaults) ) {
+
+        if(has_key($init_defaults, 'ES_USER')) {
+          if($init_defaults['ES_USER'] != $elasticsearch::elasticsearch_user) {
+            fail('Found ES_USER setting for init_defaults but is not same as elasticsearch_user setting. Please use elasticsearch_user setting.')
+          }
+        }
+      }
+      $init_defaults_pre_hash = { 'ES_USER' => $elasticsearch::elasticsearch_user, 'ES_GROUP' => $elasticsearch::elasticsearch_group, 'MAX_OPEN_FILES' => '65535' }
+      $new_init_defaults = merge($init_defaults_pre_hash, $init_defaults)
+
+      augeas { "defaults_${name}":
+        incl    => "${elasticsearch::params::defaults_location}/elasticsearch-${name}",
+        lens    => 'Shellvars.lns',
+        changes => template("${module_name}/etc/sysconfig/defaults.erb"),
+        before  => Service["elasticsearch-instance-${name}"],
+        notify  => $notify_service,
+      }
+    }
+
+    # init file from template
+    if ($init_template != undef) {
+
+      $user              = $elasticsearch::elasticsearch_user
+      $group             = $elasticsearch::elasticsearch_group
+      $pid_dir           = $elasticsearch::pid_dir
+      $defaults_location = $elasticsearch::defaults_location
+
+      if ($new_init_defaults != undef and is_hash($new_init_defaults) and has_key($new_init_defaults, 'MAX_OPEN_FILES')) {
+        $nofile = $new_init_defaults['MAX_OPEN_FILES']
+      }else{
+        $nofile = '65535'
+      }
+
+      if ($new_init_defaults != undef and is_hash($new_init_defaults) and has_key($new_init_defaults, 'MAX_LOCKED_MEMORY')) {
+        $memlock = $new_init_defaults['MAX_LOCKED_MEMORY']
+      }else{
+        $memlock = undef
+      }
+
+      file { "/lib/systemd/system/elasticsearch-${name}.service":
+        ensure  => $ensure,
+        content => template($init_template),
+        before  => Service["elasticsearch-instance-${name}"],
+        notify  => $notify_service,
+      }
+
+    }
+
+  $service_require = Exec["systemd_reload_${name}"]
+
+  } elsif($status != 'unmanaged') {
+
+    file { "/lib/systemd/system/elasticsearch-${name}.service":
+      ensure    => 'absent',
+      subscribe => Service["elasticsearch-instance-${name}"],
+      notify    => Exec["systemd_reload_${name}"],
+    }
+
+    file { "${elasticsearch::params::defaults_location}/elasticsearch-${name}":
+      ensure    => 'absent',
+      subscribe => Service["elasticsearch-instance-${name}"],
+      notify    => Exec["systemd_reload_${name}"],
+    }
+
+    $service_require = undef
+
+  }
+
+  exec { "systemd_reload_${name}":
+    command     => '/bin/systemctl daemon-reload',
+    refreshonly => true,
+  }
+
+  if ($status != 'unmanaged') {
+
+    # action
+    service { "elasticsearch-instance-${name}":
+      ensure     => $service_ensure,
+      enable     => $service_enable,
+      name       => "elasticsearch-${name}.service",
+      hasstatus  => $elasticsearch::params::service_hasstatus,
+      hasrestart => $elasticsearch::params::service_hasrestart,
+      pattern    => $elasticsearch::params::service_pattern,
+      provider   => 'systemd',
+      require    => $service_require,
+    }
+
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/manifests/template.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,145 @@
+# == Define: elasticsearch::template
+#
+#  This define allows you to insert, update or delete templates that are used within Elasticsearch for the indexes
+#
+# === Parameters
+#
+# [*ensure*]
+#   String. Controls if the managed resources shall be <tt>present</tt> or
+#   <tt>absent</tt>. If set to <tt>absent</tt>:
+#   * The managed software packages are being uninstalled.
+#   * Any traces of the packages will be purged as good as possible. This may
+#     include existing configuration files. The exact behavior is provider
+#     dependent. Q.v.:
+#     * Puppet type reference: {package, "purgeable"}[http://j.mp/xbxmNP]
+#     * {Puppet's package provider source code}[http://j.mp/wtVCaL]
+#   * System modifications (if any) will be reverted as good as possible
+#     (e.g. removal of created users, services, changed log settings, ...).
+#   * This is thus destructive and should be used with care.
+#   Defaults to <tt>present</tt>.
+#
+# [*file*]
+#   File path of the template ( json file )
+#   Value type is string
+#   Default value: undef
+#   This variable is optional
+#
+# [*content*]
+#   Contents of the template ( json )
+#   Value type is string
+#   Default value: undef
+#   This variable is optional
+#
+# [*host*]
+#   Host name or IP address of the ES instance to connect to
+#   Value type is string
+#   Default value: localhost
+#   This variable is optional
+#
+# [*port*]
+#   Port number of the ES instance to connect to
+#   Value type is number
+#   Default value: 9200
+#   This variable is optional
+#
+# === Authors
+#
+# * Richard Pijnenburg <mailto:richard.pijnenburg@elasticsearch.com>
+#
+define elasticsearch::template(
+  $ensure  = 'present',
+  $file    = undef,
+  $content = undef,
+  $host    = 'localhost',
+  $port    = 9200
+) {
+
+  require elasticsearch
+
+  # ensure
+  if ! ($ensure in [ 'present', 'absent' ]) {
+    fail("\"${ensure}\" is not a valid ensure parameter value")
+  }
+
+  if ! is_integer($port) {
+    fail("\"${port}\" is not an integer")
+  }
+
+  Exec {
+    path      => [ '/bin', '/usr/bin', '/usr/local/bin' ],
+    cwd       => '/',
+    tries     => 6,
+    try_sleep => 10,
+  }
+
+  # Build up the url
+  $es_url = "http://${host}:${port}/_template/${name}"
+
+  # Can't do a replace and delete at the same time
+
+  if ($ensure == 'present') {
+
+    # Fail when no file or content is supplied
+    if $file == undef and $content == undef {
+      fail('The variables "file" and "content" cannot be empty when inserting or updating a template.')
+    } elsif $file != undef and $content != undef {
+      fail('The variables "file" and "content" cannot be used together when inserting or updating a template.')
+    } else { # we are good to go. notify to insert in case we deleted
+      $insert_notify = Exec[ "insert_template_${name}" ]
+    }
+
+  } else {
+
+    $insert_notify = undef
+
+  }
+
+  # Delete the existing template
+  # First check if it exists of course
+  exec { "delete_template_${name}":
+    command     => "curl -s -XDELETE ${es_url}",
+    onlyif      => "test $(curl -s '${es_url}?pretty=true' | wc -l) -gt 1",
+    notify      => $insert_notify,
+    refreshonly => true,
+  }
+
+  if ($ensure == 'absent') {
+
+    # delete the template file on disk and then on the server
+    file { "${elasticsearch::params::homedir}/templates_import/elasticsearch-template-${name}.json":
+      ensure  => 'absent',
+      notify  => Exec[ "delete_template_${name}" ],
+      require => File[ "${elasticsearch::params::homedir}/templates_import" ],
+    }
+  }
+
+  if ($ensure == 'present') {
+
+    if $content == undef {
+      # place the template file using the file source
+      file { "${elasticsearch::params::homedir}/templates_import/elasticsearch-template-${name}.json":
+        ensure  => file,
+        source  => $file,
+        notify  => Exec[ "delete_template_${name}" ],
+        require => File[ "${elasticsearch::params::homedir}/templates_import" ],
+      }
+    } else {
+      # place the template file using content
+      file { "${elasticsearch::params::homedir}/templates_import/elasticsearch-template-${name}.json":
+        ensure  => file,
+        content => $content,
+        notify  => Exec[ "delete_template_${name}" ],
+        require => File[ "${elasticsearch::params::homedir}/templates_import" ],
+      }
+    }
+
+    exec { "insert_template_${name}":
+      command     => "curl -sL -w \"%{http_code}\\n\" -XPUT ${es_url} -d @${elasticsearch::params::homedir}/templates_import/elasticsearch-template-${name}.json -o /dev/null | egrep \"(200|201)\" > /dev/null",
+      unless      => "test $(curl -s '${es_url}?pretty=true' | wc -l) -gt 1",
+      refreshonly => true,
+      loglevel    => 'debug',
+    }
+
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/metadata.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,96 @@
+{
+  "name": "elasticsearch-elasticsearch",
+  "version": "0.10.1",
+  "source": "https://github.com/elastic/puppet-elasticsearch",
+  "author": "elasticsearch",
+  "license": "Apache-2.0",
+  "summary": "Module for managing and configuring Elasticsearch nodes",
+  "description": "Module for managing and configuring Elasticsearch nodes",
+  "project_page": "https://github.com/elastic/puppet-elasticsearch",
+  "issues_url": "https://github.com/elastic/puppet-elasticsearch/issues",
+  "dependencies": [
+    {
+      "name": "puppetlabs/stdlib",
+      "version_requirement": ">= 3.2.0 < 5.0.0"
+    },
+    {
+      "name": "puppetlabs/apt",
+      "version_requirement": ">= 1.4.0 < 3.0.0"
+    },
+    {
+      "name": "ceritsc/yum",
+      "version_requirement": ">= 0.9.6 < 1.0.0"
+    },
+    {
+      "name": "richardc/datacat",
+      "version_requirement": ">= 0.6.2 < 1.0.0"
+    }
+  ],
+  "operatingsystem_support": [
+    {
+      "operatingsystem": "RedHat",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "CentOS",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "OracleLinux",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Scientific",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Debian",
+      "operatingsystemrelease": [
+        "6",
+        "7",
+        "8"
+      ]
+    },
+    {
+      "operatingsystem": "Ubuntu",
+      "operatingsystemrelease": [
+        "10.04",
+        "12.04",
+        "14.04"
+      ]
+    },
+    {
+      "operatingsystem": "OpenSuSE",
+      "operatingsystemrelease": [
+        "12",
+        "13"
+      ]
+    }
+  ],
+  "requirements": [
+    {
+      "name": "pe",
+      "version_requirement": ">= 3.3.2"
+    },
+    {
+      "name": "puppet",
+      "version_requirement": ">=3.2.0 <4.3.0"
+    }
+  ]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/001_basic_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+require 'spec_helper_acceptance'
+
+# Here we put the more basic fundamental tests, ultra obvious stuff.
+describe "basic tests:" do
+  it 'make sure we have copied the module across' do
+    shell("ls #{default['distmoduledir']}/elasticsearch/metadata.json", {:acceptable_exit_codes => 0})
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/002_class_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,149 @@
+require 'spec_helper_acceptance'
+
+describe "elasticsearch class:" do
+
+  describe "single instance" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch001' }
+    end
+
+    describe file('/usr/share/elasticsearch/templates_import') do
+      it { should be_directory }
+    end
+
+
+  end
+
+
+  describe "multiple instances" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+            elasticsearch::instance { 'es-02': config => { 'node.name' => 'elasticsearch002', 'http.port' => '#{test_settings['port_b']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe service(test_settings['service_name_b']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe file(test_settings['pid_file_b']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "make sure elasticsearch can serve requests #{test_settings['port_a']}" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe "make sure elasticsearch can serve requests #{test_settings['port_b']}" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_b']}", default, "http://localhost:#{test_settings['port_b']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch001' }
+    end
+
+    describe file('/etc/elasticsearch/es-02/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch002' }
+    end
+
+  end
+
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+            elasticsearch::instance{ 'es-02': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe file('/etc/elasticsearch/es-02') do
+      it { should_not be_directory }
+    end
+
+    describe file('/etc/elasticsearch/es-03') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+    describe service(test_settings['service_name_b']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/003_template_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,70 @@
+require 'spec_helper_acceptance'
+
+describe "elasticsearch template define:" do
+
+  shell("mkdir -p #{default['distmoduledir']}/another/files")
+  shell("echo '#{test_settings['good_json']}' >> #{default['distmoduledir']}/another/files/good.json")
+  shell("echo '#{test_settings['bad_json']}' >> #{default['distmoduledir']}/another/files/bad.json")
+
+  describe "Insert a template with valid json content" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+          elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+          elasticsearch::template { 'foo': ensure => 'present', file => 'puppet:///modules/another/good.json' }"
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    it 'should report as existing in Elasticsearch' do
+      curl_with_retries('validate template as installed', default, "http://localhost:#{test_settings['port_a']}/_template/foo | grep logstash", 0)
+    end
+  end
+
+  if fact('puppetversion') =~ /3\.[2-9]\./
+    describe "Insert a template with bad json content" do
+
+      it 'run should fail' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+             elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+             elasticsearch::template { 'foo': ensure => 'present', file => 'puppet:///modules/another/bad.json' }"
+
+        apply_manifest(pp, :expect_failures => true)
+      end
+
+    end
+
+  else
+    # The exit codes have changes since Puppet 3.2x
+    # Since beaker expectations are based on the most recent puppet code All runs on previous versions fails.
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/004_plugin_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,299 @@
+require 'spec_helper_acceptance'
+
+describe "elasticsearch plugin define:" do
+
+  shell("mkdir -p #{default['distmoduledir']}/another/files")
+  shell("cp /tmp/elasticsearch-bigdesk.zip #{default['distmoduledir']}/another/files/elasticsearch-bigdesk.zip")
+
+  describe "Install a plugin from official repository" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+            elasticsearch::plugin{'mobz/elasticsearch-head': module_dir => 'head', instances => 'es-01' }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    it 'make sure the directory exists' do
+      shell('ls /usr/share/elasticsearch/plugins/head/', {:acceptable_exit_codes => 0})
+    end
+
+    it 'make sure elasticsearch reports it as existing' do
+      curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep head", 0)
+    end
+
+  end
+  describe "Install a plugin from custom git repo" do
+    it 'should run successfully' do
+    end
+
+    it 'make sure the directory exists' do
+    end
+
+    it 'make sure elasticsearch reports it as existing' do
+    end
+
+  end
+
+  if fact('puppetversion') =~ /3\.[2-9]\./
+
+    describe "Install a non existing plugin" do
+
+      it 'should run successfully' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'elasticsearch/non-existing': module_dir => 'non-existing', instances => 'es-01' }
+        "
+        #  Run it twice and test for idempotency
+        apply_manifest(pp, :expect_failures => true)
+      end
+
+    end
+
+  else
+    # The exit codes have changes since Puppet 3.2x
+    # Since beaker expectations are based on the most recent puppet code All runs on previous versions fails.
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+
+  describe "install plugin while running ES under user 'root'" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true, elasticsearch_user => 'root', elasticsearch_group => 'root' }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+            elasticsearch::plugin{'lmenezes/elasticsearch-kopf': module_dir => 'kopf', instances => 'es-01' }
+      "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    it 'make sure the directory exists' do
+      shell('ls /usr/share/elasticsearch/plugins/kopf/', {:acceptable_exit_codes => 0})
+    end
+
+    it 'make sure elasticsearch reports it as existing' do
+      curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep kopf", 0)
+    end
+
+  end
+
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+  describe 'plugin upgrading' do
+
+    describe 'Setup first plugin' do
+      it 'should run successful' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true, elasticsearch_user => 'root', elasticsearch_group => 'root' }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'elasticsearch/elasticsearch-cloud-aws/2.1.1': module_dir => 'cloud-aws', instances => 'es-01' }
+        "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+      end
+
+      it 'make sure the directory exists' do
+        shell('ls /usr/share/elasticsearch/plugins/cloud-aws/', {:acceptable_exit_codes => 0})
+      end
+
+      it 'make sure elasticsearch reports it as existing' do
+        curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep cloud-aws | grep 2.1.1", 0)
+      end
+
+    end
+
+    describe "Upgrade plugin" do
+      it 'Should run succesful' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true, elasticsearch_user => 'root', elasticsearch_group => 'root' }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'elasticsearch/elasticsearch-cloud-aws/2.2.0': module_dir => 'cloud-aws', instances => 'es-01' }
+        "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+      end
+
+      it 'make sure elasticsearch reports it as existing' do
+        curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep cloud-aws | grep 2.2.0", 0)
+      end
+    end
+
+  end
+
+  describe "offline install via puppetmaster" do
+      it 'Should run succesful' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true, elasticsearch_user => 'root', elasticsearch_group => 'root' }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'bigdesk': source => 'puppet:///modules/another/elasticsearch-bigdesk.zip', instances => 'es-01' }
+        "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+      end
+
+      it 'make sure elasticsearch reports it as existing' do
+        curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep bigdesk", 0)
+      end
+
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+  describe "install via url" do
+      it 'Should run succesful' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'HQ': url => 'https://github.com/royrusso/elasticsearch-HQ/archive/v2.0.3.zip', instances => 'es-01' }
+        "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+      end
+
+      it 'make sure elasticsearch reports it as existing' do
+        curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep HQ", 0)
+      end
+
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/009_datapath_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,361 @@
+require 'spec_helper_acceptance'
+
+describe "Data dir settings" do
+
+  describe "Default data dir" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain "/usr/share/elasticsearch/data/es-01" }
+    end
+
+     describe "Elasticsearch config has the data path" do
+      it {
+        curl_with_retries("check data path on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/_nodes?pretty=true | grep /usr/share/elasticsearch/data/es-01", 0)
+      }
+
+    end
+
+    describe file('/usr/share/elasticsearch/data/es-01') do
+      it { should be_directory }
+    end
+
+  end
+
+
+  describe "Single data dir from main class" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true, datadir => '/var/lib/elasticsearch-data' }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain '/var/lib/elasticsearch-data/es-01' }
+    end
+
+     describe "Elasticsearch config has the data path" do
+      it {
+        curl_with_retries("check data path on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/_nodes?pretty=true | grep /var/lib/elasticsearch-data/es-01", 0)
+      }
+
+    end
+
+    describe file('/var/lib/elasticsearch-data/es-01') do
+      it { should be_directory }
+    end
+
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+  describe "Single data dir from instance config" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}'}, datadir => '#{test_settings['datadir_1']}' }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain "#{test_settings['datadir_1']}" }
+    end
+
+     describe "Elasticsearch config has the data path" do
+      it {
+        curl_with_retries("check data path on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/_nodes?pretty=true | grep #{test_settings['datadir_1']}", 0)
+      }
+    end
+
+    describe file(test_settings['datadir_1']) do
+      it { should be_directory }
+    end
+
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+  describe "multiple data dir's from main class" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true, datadir => [ '/var/lib/elasticsearch/01', '/var/lib/elasticsearch/02'] }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain '/var/lib/elasticsearch/01/es-01' }
+      it { should contain '/var/lib/elasticsearch/02/es-01' }
+    end
+
+     describe "Elasticsearch config has the data path" do
+      it {
+        curl_with_retries("check data path on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/_nodes?pretty=true | grep /var/lib/elasticsearch/01/es-01", 0)
+      }
+      it {
+        curl_with_retries("check data path on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/_nodes?pretty=true | grep /var/lib/elasticsearch/02/es-01", 0)
+      }
+
+    end
+
+    describe file('/var/lib/elasticsearch/01/es-01') do
+      it { should be_directory }
+    end
+
+    describe file('/var/lib/elasticsearch/02/es-01') do
+      it { should be_directory }
+    end
+
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+
+  describe "multiple data dir's from instance config" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' }, datadir => [ '#{test_settings['datadir_1']}', '#{test_settings['datadir_2']}'] }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain "#{test_settings['datadir_1']}" }
+      it { should contain "#{test_settings['datadir_2']}" }
+    end
+
+     describe "Elasticsearch config has the data path" do
+      it {
+        curl_with_retries("check data path on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/_nodes?pretty=true | grep #{test_settings['datadir_1']}", 0)
+      }
+      it {
+        curl_with_retries("check data path on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/_nodes?pretty=true | grep #{test_settings['datadir_2']}", 0)
+      }
+
+    end
+
+    describe file(test_settings['datadir_1']) do
+      it { should be_directory }
+    end
+
+    describe file(test_settings['datadir_2']) do
+      it { should be_directory }
+    end
+
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/010_pkg_url_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,167 @@
+require 'spec_helper_acceptance'
+
+describe "Elasticsearch class:" do
+
+  shell("mkdir -p #{default['distmoduledir']}/another/files")
+  shell("cp #{test_settings['local']} #{default['distmoduledir']}/another/files/#{test_settings['puppet']}")
+
+  context "install via http resource" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': package_url => '#{test_settings['url']}', java_install => true, config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' } }
+            elasticsearch::instance{ 'es-01': }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    it 'make sure elasticsearch can serve requests' do
+      curl_with_retries('check ES', default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+  end
+
+  context "Clean" do
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+  context "Install via local file resource" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': package_url => 'file:#{test_settings['local']}', java_install => true, config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' } }
+            elasticsearch::instance{ 'es-01': }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    it 'make sure elasticsearch can serve requests' do
+      curl_with_retries('check ES', default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+  end
+
+  context "Clean" do
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+  context "Install via Puppet resource" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': package_url => 'puppet:///modules/another/#{test_settings['puppet']}', java_install => true, config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' } }
+            elasticsearch::instance { 'es-01': }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    it 'make sure elasticsearch can serve requests' do
+      curl_with_retries('check ES', default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+  end
+
+  context "Clean" do
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/011_service_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,77 @@
+require 'spec_helper_acceptance'
+
+describe "Service tests:" do
+
+  describe "Make sure we can manage the defaults file" do
+
+    context "Change the defaults file" do
+      it 'should run successfully' do
+        pp = "class { 'elasticsearch': manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true, config => { 'cluster.name' => '#{test_settings['cluster_name']}' }, init_defaults => { 'ES_JAVA_OPTS' => '\"-server -XX:+UseTLAB -XX:+CMSClassUnloadingEnabled\"' } }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001' } }
+             "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+      end
+
+      describe service(test_settings['service_name_a']) do
+        it { should be_enabled }
+        it { should be_running }
+      end
+
+      describe package(test_settings['package_name']) do
+        it { should be_installed }
+      end
+
+      describe file(test_settings['pid_file_a']) do
+        it { should be_file }
+        its(:content) { should match /[0-9]+/ }
+      end
+
+      describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+        it { should be_file }
+        it { should contain 'name: elasticsearch001' }
+      end
+
+      describe 'make sure elasticsearch can serve requests' do
+        it {
+          curl_with_retries('check ES', default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+        }
+      end
+
+      context "Make sure we have ES_USER=root" do
+
+        describe file(test_settings['defaults_file_a']) do
+          its(:content) { should match /^ES_JAVA_OPTS="-server -XX:\+UseTLAB -XX:\+CMSClassUnloadingEnabled"/ }
+        end
+
+      end
+
+    end
+
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/012_instances_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,197 @@
+require 'spec_helper_acceptance'
+
+describe "elasticsearch class:" do
+
+  describe "Setup single instance" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch001' }
+    end
+
+    describe file('/usr/share/elasticsearch/templates_import') do
+      it { should be_directory }
+    end
+
+    describe file('/usr/share/elasticsearch/scripts') do
+      it { should be_directory }
+    end
+
+    describe file('/etc/elasticsearch/es-01/scripts') do
+      it { should be_symlink }
+    end
+
+  end
+
+
+  describe "Setup second instance" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+            elasticsearch::instance { 'es-02': config => { 'node.name' => 'elasticsearch002', 'http.port' => '#{test_settings['port_b']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe service(test_settings['service_name_b']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe file(test_settings['pid_file_b']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "make sure elasticsearch can serve requests #{test_settings['port_a']}" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe "make sure elasticsearch can serve requests #{test_settings['port_b']}" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_b']}", default, "http://localhost:#{test_settings['port_b']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch001' }
+    end
+
+    describe file('/etc/elasticsearch/es-02/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch002' }
+    end
+
+    describe file('/usr/share/elasticsearch/scripts') do
+      it { should be_directory }
+    end
+
+    describe file('/etc/elasticsearch/es-01/scripts') do
+      it { should be_symlink }
+    end
+
+    describe file('/etc/elasticsearch/es-02/scripts') do
+      it { should be_symlink }
+    end
+
+  end
+
+
+  describe "Remove instance 1" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+            elasticsearch::instance { 'es-02': config => { 'node.name' => 'elasticsearch002', 'http.port' => '#{test_settings['port_b']}' } }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+    describe service(test_settings['service_name_b']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe file(test_settings['pid_file_b']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "make sure elasticsearch can serve requests #{test_settings['port_b']}" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_b']}", default, "http://localhost:#{test_settings['port_b']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-02/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch002' }
+    end
+
+  end
+
+  describe "Cleanup" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-02': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-02') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_b']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/013_config_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,83 @@
+require 'spec_helper_acceptance'
+
+describe "elasticsearch class:" do
+
+  describe "Setup single instance" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => 'foobar' }, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}', 'node.master' => true, 'node.data' => false, 'index' => { 'routing' => { 'allocation' => { 'include' => 'tag1', 'exclude' => [ 'tag2', 'tag3' ] } } }, 'node' => { 'rack' => 46 }, 'boostrap.mlockall' => true, 'cluster.name' => '#{test_settings['cluster_name']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch001' }
+      it { should contain 'master: true' }
+      it { should contain 'data: false' }
+      it { should contain "cluster:\n  name: #{test_settings['cluster_name']}" }
+      it { should contain 'rack: 46' }
+      it { should contain "index: \n  routing: \n    allocation: \n      exclude: \n             - tag2\n             - tag3\n      include: tag1" }
+    end
+
+    describe file('/usr/share/elasticsearch/templates_import') do
+      it { should be_directory }
+    end
+
+    describe file('/usr/share/elasticsearch/scripts') do
+      it { should be_directory }
+    end
+
+    describe file('/etc/elasticsearch/es-01/scripts') do
+      it { should be_symlink }
+    end
+
+  end
+
+  describe "Cleanup" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/014_hiera_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,181 @@
+require 'spec_helper_acceptance'
+
+# Here we put the more basic fundamental tests, ultra obvious stuff.
+
+describe "Hiera tests" do
+
+  describe "single instance" do
+
+    it 'should run successfully' do
+      write_hiera_config(['singleinstance'])
+      pp = "class { 'elasticsearch': manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }"
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: es-01' }
+    end
+
+    describe file('/usr/share/elasticsearch/templates_import') do
+      it { should be_directory }
+    end
+
+  end
+
+  describe "single instance with plugin" do
+
+    it 'should run successfully' do
+      write_hiera_config(['singleplugin'])
+      pp = "class { 'elasticsearch': manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }"
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: es-01' }
+    end
+
+    describe file('/usr/share/elasticsearch/templates_import') do
+      it { should be_directory }
+    end
+
+    it 'make sure the directory exists' do
+      shell('ls /usr/share/elasticsearch/plugins/head/', {:acceptable_exit_codes => 0})
+    end
+
+    it 'make sure elasticsearch reports it as existing' do
+      curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep head", 0)
+    end
+
+  end
+
+  describe "multiple instances" do
+
+
+    it 'should run successfully' do
+      write_hiera_config(['multipleinstances'])
+      pp = "class { 'elasticsearch': manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }"
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe service(test_settings['service_name_b']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe file(test_settings['pid_file_b']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "make sure elasticsearch can serve requests #{test_settings['port_a']}" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe "make sure elasticsearch can serve requests #{test_settings['port_b']}" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_b']}", default, "http://localhost:#{test_settings['port_b']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: es-01' }
+    end
+
+    describe file('/etc/elasticsearch/es-02/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: es-02' }
+    end
+
+  end
+
+
+  describe "Cleanup" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/015_staged_removal.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,69 @@
+require 'spec_helper_acceptance'
+
+describe "elasticsearch class:" do
+
+  describe "Setup" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+            elasticsearch::instance { 'es-02': config => { 'node.name' => 'elasticsearch002', 'http.port' => '#{test_settings['port_b']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+  end
+
+  describe "First removal of instance 1" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+            elasticsearch::instance { 'es-02': config => { 'node.name' => 'elasticsearch002', 'http.port' => '#{test_settings['port_b']}' } }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+  end
+
+  describe "Second removal of instance 1" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+            elasticsearch::instance { 'es-02': config => { 'node.name' => 'elasticsearch002', 'http.port' => '#{test_settings['port_b']}' } }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+  end
+
+  describe "First removal of the rest" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-02': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+  end
+
+  describe "Second removal of the rest" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-02': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/016_package_pin_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,107 @@
+require 'spec_helper_acceptance'
+
+describe "Package pinning:" do
+
+  if fact('osfamily') != 'Suse'
+
+    describe "Pinning enabled" do
+
+      describe "Setup" do
+
+        it 'should run successful' do
+          write_hiera_config('')
+          pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', version => '#{test_settings['install_package_version']}', java_install => true }
+                elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+               "
+          # Run it twice and test for idempotency
+          apply_manifest(pp, :catch_failures => true)
+          expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+        end
+
+        describe package(test_settings['package_name']) do
+          it { should be_installed.with_version(test_settings['install_version']) }
+        end
+
+      end # end setup
+
+      describe "Run upgrade" do
+        it 'should run fine' do
+          case fact('osfamily')
+          when 'Debian'
+            shell('apt-get update && apt-get -y install elasticsearch')
+          when 'RedHat'
+            shell('yum -y update elasticsearch')
+          end
+        end
+      end
+
+      describe "check installed package" do
+
+        describe package(test_settings['package_name']) do
+          it { should be_installed.with_version(test_settings['install_version']) }
+        end
+
+      end
+
+      describe "Upgrade" do
+
+        it 'should run successful' do
+          pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', version => '#{test_settings['upgrade_package_version']}', java_install => true }
+                elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+               "
+          # Run it twice and test for idempotency
+          apply_manifest(pp, :catch_failures => true)
+          expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+        end
+
+        describe package(test_settings['package_name']) do
+          it { should be_installed.with_version(test_settings['upgrade_version']) }
+        end
+
+      end # end setup
+
+      describe "Run upgrade" do
+        it 'should run fine' do
+          case fact('osfamily')
+          when 'Debian'
+            shell('apt-get update && apt-get -y install elasticsearch')
+          when 'RedHat'
+            shell('yum -y update elasticsearch')
+          end
+        end
+      end
+
+      describe "check installed package" do
+
+        describe package(test_settings['package_name']) do
+          it { should be_installed.with_version(test_settings['upgrade_version']) }
+        end
+
+      end
+
+    end
+
+    describe "Cleanup" do
+
+      it 'should run successfully' do
+        pp = "class { 'elasticsearch': ensure => 'absent' }
+              elasticsearch::instance{ 'es-01': ensure => 'absent' }
+             "
+
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      describe file('/etc/elasticsearch/es-01') do
+        it { should_not be_directory }
+      end
+
+      describe service(test_settings['service_name_a']) do
+        it { should_not be_enabled }
+        it { should_not be_running }
+      end
+
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/017_restart_on_change_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,144 @@
+require 'spec_helper_acceptance'
+
+describe "elasticsearch class:" do
+
+  describe "Setup" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true, restart_on_change => false }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+            elasticsearch::plugin{'lmenezes/elasticsearch-kopf': instances => 'es-01' }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe "Returns correct node name" do
+      it {
+        curl_with_retries("check hostname on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true | grep elasticsearch001", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch001' }
+    end
+
+    describe file('/usr/share/elasticsearch/templates_import') do
+      it { should be_directory }
+    end
+
+
+  end
+
+  describe "Change config" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true, restart_on_change => false }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch002', 'http.port' => '#{test_settings['port_a']}' } }
+            elasticsearch::plugin{'lmenezes/elasticsearch-kopf': instances => 'es-01' }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe "Returns correct node name" do
+      it {
+        curl_with_retries("check hostname on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true | grep elasticsearch001", 0)
+      }
+    end
+
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch002' }
+    end
+
+    describe file('/usr/share/elasticsearch/templates_import') do
+      it { should be_directory }
+    end
+
+
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe file('/etc/elasticsearch/es-02') do
+      it { should_not be_directory }
+    end
+
+    describe file('/etc/elasticsearch/es-03') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+    describe service(test_settings['service_name_b']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/020_usergroup_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,91 @@
+require 'spec_helper_acceptance'
+
+describe "elasticsearch class:" do
+
+  describe "Run as a different user" do
+
+    it 'should run successfully' do
+
+      write_hiera_config('')
+      shell("rm -rf /usr/share/elasticsearch")
+      pp = "user { 'esuser': ensure => 'present', groups => ['esgroup', 'esuser'] }
+            group { 'esuser': ensure => 'present' }
+            group { 'esgroup': ensure => 'present' }
+            class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, manage_repo => true, repo_version => '#{test_settings['repo_version']}', java_install => true, elasticsearch_user => 'esuser', elasticsearch_group => 'esgroup' }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      it { should be_owned_by 'esuser' }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "make sure elasticsearch can serve requests #{test_settings['port_a']}" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should be_owned_by 'esuser' }
+      it { should contain 'name: elasticsearch001' }
+    end
+
+    describe file('/usr/share/elasticsearch') do
+      it { should be_directory }
+      it { should be_owned_by 'esuser' }
+    end
+
+    describe file('/var/log/elasticsearch') do
+      it { should be_directory }
+      it { should be_owned_by 'esuser' }
+    end
+
+    describe file('/etc/elasticsearch') do
+      it { should be_directory }
+      it { should be_owned_by 'esuser' }
+    end
+
+
+  end
+
+
+  describe "Cleanup" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/021_es2x_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,351 @@
+require 'spec_helper_acceptance'
+
+describe "elasticsearch 2x:" do
+
+  shell("mkdir -p #{default['distmoduledir']}/another/files")
+  shell("cp /tmp/elasticsearch-kopf.zip #{default['distmoduledir']}/another/files/elasticsearch-kopf.zip")
+
+  describe "Install a plugin from official repository" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version2x']}', java_install => true, version => '2.0.0' }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+            elasticsearch::plugin{'lmenezes/elasticsearch-kopf': instances => 'es-01' }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    it 'make sure the directory exists' do
+      shell('ls /usr/share/elasticsearch/plugins/kopf/', {:acceptable_exit_codes => 0})
+    end
+
+    it 'make sure elasticsearch reports it as existing' do
+      curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep kopf", 0)
+    end
+
+  end
+  describe "Install a plugin from custom git repo" do
+    it 'should run successfully' do
+    end
+
+    it 'make sure the directory exists' do
+    end
+
+    it 'make sure elasticsearch reports it as existing' do
+    end
+
+  end
+
+  if fact('puppetversion') =~ /3\.[2-9]\./
+
+    describe "Install a non existing plugin" do
+
+      it 'should run successfully' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version2x']}', java_install => true, version => '2.0.0' }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'elasticsearch/non-existing': module_dir => 'non-existing', instances => 'es-01' }
+        "
+        #  Run it twice and test for idempotency
+        apply_manifest(pp, :expect_failures => true)
+      end
+
+    end
+
+  else
+    # The exit codes have changes since Puppet 3.2x
+    # Since beaker expectations are based on the most recent puppet code All runs on previous versions fails.
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+
+  describe "install plugin while running ES under user 'elasticsearch'" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version2x']}', java_install => true, elasticsearch_user => 'elasticsearch', elasticsearch_group => 'elasticsearch', version => '2.0.0' }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+            elasticsearch::plugin{'lmenezes/elasticsearch-kopf': module_dir => 'kopf', instances => 'es-01' }
+      "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    it 'make sure the directory exists' do
+      shell('ls /usr/share/elasticsearch/plugins/kopf/', {:acceptable_exit_codes => 0})
+    end
+
+    it 'make sure elasticsearch reports it as existing' do
+      curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep kopf", 0)
+    end
+
+  end
+
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+  describe 'upgrading', :upgrade => true do
+
+    describe 'Setup 2.0.0' do
+      it 'should run successful' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version2x']}', java_install => true, version => '2.0.0' }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'cloud-aws': instances => 'es-01' }
+        "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+      end
+
+      it 'make sure the directory exists' do
+        shell('ls /usr/share/elasticsearch/plugins/cloud-aws/', {:acceptable_exit_codes => 0})
+      end
+
+      it 'make sure elasticsearch reports it as existing' do
+        curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep cloud-aws | grep 2.0.0", 0)
+      end
+
+    end
+
+    describe "Upgrade to 2.0.1" do
+      it 'Should run succesful' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version2x']}', java_install => true, version => '2.0.1' }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'cloud-aws': instances => 'es-01' }
+        "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+      end
+
+      it 'make sure the directory exists' do
+        shell('ls /usr/share/elasticsearch/plugins/cloud-aws/', {:acceptable_exit_codes => 0})
+      end
+
+      it 'make sure elasticsearch reports it as existing' do
+        curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep cloud-aws | grep 2.0.1", 0)
+      end
+    end
+
+  end
+
+  describe "offline install via puppet resource" do
+      it 'Should run succesful' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version2x']}', java_install => true }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'kopf': source => 'puppet:///modules/another/elasticsearch-kopf.zip', instances => 'es-01' }
+        "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+      end
+
+      it 'make sure elasticsearch reports it as existing' do
+        curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep kopf", 0)
+      end
+
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+            file { '/usr/share/elasticsearch/plugin':
+              ensure => 'absent',
+              force => true,
+              recurse => true,
+            }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+  describe "offline install via file url" do
+      it 'Should run succesful' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version2x']}', java_install => true }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'kopf': url => 'file:///tmp/elasticsearch-kopf.zip', instances => 'es-01' }
+        "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+      end
+
+      it 'make sure elasticsearch reports it as existing' do
+        curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep kopf", 0)
+      end
+
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+  describe "install via url" do
+      it 'Should run succesful' do
+        pp = "class { 'elasticsearch': config => { 'node.name' => 'elasticsearch001', 'cluster.name' => '#{test_settings['cluster_name']}' }, manage_repo => true, repo_version => '#{test_settings['repo_version2x']}', java_install => true }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'HQ': url => 'https://github.com/royrusso/elasticsearch-HQ/archive/v2.0.3.zip', instances => 'es-01' }
+        "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+
+      end
+
+      it 'make sure elasticsearch reports it as existing' do
+        curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep hq", 0)
+      end
+
+  end
+
+  describe "module removal" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': ensure => 'absent' }
+            elasticsearch::instance{ 'es-01': ensure => 'absent' }
+           "
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    describe file('/etc/elasticsearch/es-01') do
+      it { should_not be_directory }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should_not be_installed }
+    end
+
+    describe service(test_settings['service_name_a']) do
+      it { should_not be_enabled }
+      it { should_not be_running }
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/integration001.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,153 @@
+require 'spec_helper_acceptance'
+
+describe "Integration testing" do
+
+  shell("mkdir -p #{default['distmoduledir']}/another/files")
+  shell("echo '#{test_settings['good_json']}' >> #{default['distmoduledir']}/another/files/good.json")
+  shell("echo '#{test_settings['bad_json']}' >> #{default['distmoduledir']}/another/files/bad.json")
+
+
+  describe "Setup Elasticsearch", :main => true do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, java_install => true, package_url => '#{test_settings['snapshot_package']}' }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch001' }
+    end
+
+    describe file('/usr/share/elasticsearch/templates_import') do
+      it { should be_directory }
+    end
+
+  end
+
+  describe "Template tests", :template => true do
+
+    describe "Insert a template with valid json content" do
+
+      it 'should run successfully' do
+        pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, java_install => true, package_url => '#{test_settings['snapshot_package']}' }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::template { 'foo': ensure => 'present', file => 'puppet:///modules/another/good.json' }"
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+      end
+
+      it 'should report as existing in Elasticsearch' do
+        curl_with_retries('validate template as installed', default, "http://localhost:#{test_settings['port_a']}/_template/foo | grep logstash", 0)
+      end
+    end
+
+    if fact('puppetversion') =~ /3\.[2-9]\./
+      describe "Insert a template with bad json content" do
+
+        it 'run should fail' do
+          pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, java_install => true, package_url => '#{test_settings['snapshot_package']}' }
+                elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+                elasticsearch::template { 'foo': ensure => 'present', file => 'puppet:///modules/another/bad.json' }"
+
+          apply_manifest(pp, :expect_failures => true)
+        end
+
+      end
+
+    else
+      # The exit codes have changes since Puppet 3.2x
+      # Since beaker expectations are based on the most recent puppet code All runs on previous versions fails.
+    end
+
+  end
+
+  describe "Plugin tests", :plugin => true do
+
+    describe "Install a plugin from official repository" do
+
+      it 'should run successfully' do
+        pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, java_install => true, package_url => '#{test_settings['snapshot_package']}' }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'lmenezes/elasticsearch-kopf': instances => 'es-01' }
+             "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+      end
+
+      describe service(test_settings['service_name_a']) do
+        it { should be_enabled }
+        it { should be_running }
+      end
+
+      describe package(test_settings['package_name']) do
+        it { should be_installed }
+      end
+
+      describe file(test_settings['pid_file_a']) do
+        it { should be_file }
+        its(:content) { should match /[0-9]+/ }
+      end
+
+      it 'make sure the directory exists' do
+        shell('ls /usr/share/elasticsearch/plugins/kopf/', {:acceptable_exit_codes => 0})
+      end
+
+      it 'make sure elasticsearch reports it as existing' do
+        curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep kopf", 0)
+      end
+
+    end
+
+    if fact('puppetversion') =~ /3\.[2-9]\./
+
+      describe "Install a non existing plugin" do
+
+        it 'should run successfully' do
+          pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, java_install => true, package_url => '#{test_settings['snapshot_package']}' }
+                elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+                elasticsearch::plugin{'elasticsearch/non-existing': module_dir => 'non-existing', instances => 'es-01' }
+               "
+          apply_manifest(pp, :expect_failures => true)
+        end
+
+      end
+
+    else
+      # The exit codes have changes since Puppet 3.2x
+      # Since beaker expectations are based on the most recent puppet code All runs on previous versions fails.
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/centos-6-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+HOSTS:
+  centos-6-x64:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: el-6-x86_64
+    image: electrical/centos:6.4
+    hypervisor: docker
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'yum install -y wget ntpdate rubygems ruby-augeas ruby-devel augeas-devel'
+      - 'touch /etc/sysconfig/network'
+    docker_preserve_image: true
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/centos-7-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  centos-7-x64:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: el-7-x86_64
+    image: electrical/centos:7
+    hypervisor: docker
+    docker_cmd: '["/usr/sbin/init"]'
+    docker_image_commands:
+      - 'yum install -y wget ntpdate rubygems ruby-devel augeas-devel ruby-augeas tar'
+    docker_preserve_image: true
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/debian-6-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+HOSTS:
+  debian-6:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: debian-6-amd64
+    image: electrical/debian:6.0.8
+    hypervisor: docker
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -yq lsb-release wget net-tools ruby rubygems ruby1.8-dev libaugeas-dev libaugeas-ruby ntpdate locales-all'
+      - 'REALLY_GEM_UPDATE_SYSTEM=1 gem update --system --no-ri --no-rdoc'
+    docker_preserve_image: true
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/debian-7-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+HOSTS:
+  debian-7:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: debian-7-amd64
+    image: electrical/debian:7.3
+    hypervisor: docker
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -yq lsb-release wget net-tools ruby rubygems ruby1.8-dev libaugeas-dev libaugeas-ruby ntpdate locales-all'
+      - 'REALLY_GEM_UPDATE_SYSTEM=1 gem update --system --no-ri --no-rdoc'
+    docker_preserve_image: true
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/debian-8-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+HOSTS:
+  debian-8:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: debian-8-amd64
+    image: electrical/debian:8
+    hypervisor: docker
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -yq ruby ruby-dev lsb-release wget net-tools libaugeas-dev libaugeas-ruby ntpdate locales-all'
+      - 'REALLY_GEM_UPDATE_SYSTEM=1 gem update --system --no-ri --no-rdoc'
+    docker_preserve_image: true
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/opensuse-121-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+HOSTS:
+  opensuse-121-x64:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: sles-12-x64
+    box: opensuse-121-x64
+    box_url: https://s3.amazonaws.com/circlejtp/OpenSuseVagrant/OpenSuse12_1x64_July14.box
+    hypervisor: vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/opensuse-131-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+HOSTS:
+  opensuse-131-x64:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: sles-13-x64
+    box: opensuse-13.1-test
+    box_url: https://s3-eu-west-1.amazonaws.com/users.eu.elasticsearch.org/electrical/opensuse-131.box
+    hypervisor: vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/sles-11sp3-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+HOSTS:
+  sles-11-x64:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: sles-11-x86_64
+    box: sles-11sp3-x64
+    box_url: https://s3-eu-west-1.amazonaws.com/users.eu.elasticsearch.org/electrical/sles-11sp3-x64.box
+    hypervisor: vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1204-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-12-04:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    image: electrical/ubuntu:12.04
+    hypervisor: docker
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -yq ruby1.8-dev libaugeas-dev libaugeas-ruby ruby rubygems lsb-release wget net-tools curl'
+    docker_preserve_image: true
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1210-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-12-10:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.10-amd64
+    image: electrical/ubuntu:12.10
+    hypervisor: docker
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -yq ruby1.8-dev libaugeas-dev libaugeas-ruby ruby rubygems lsb-release wget net-tools curl'
+    docker_preserve_image: true
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1304-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-13-04:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-13.04-amd64
+    image: electrical/ubuntu:13.04
+    hypervisor: docker
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -yq ruby1.8-dev libaugeas-dev libaugeas-ruby ruby rubygems lsb-release wget net-tools curl'
+    docker_preserve_image: true
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-13-10:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-13.10-amd64
+    image: electrical/ubuntu:13.10
+    hypervisor: docker
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -yq ruby1.8-dev libaugeas-dev libaugeas-ruby ruby rubygems lsb-release wget net-tools curl'
+    docker_preserve_image: true
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  ubuntu-14-04:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-14.04-amd64
+    image: electrical/ubuntu:14.04
+    hypervisor: docker
+    docker_cmd: '["/sbin/init"]'
+    docker_image_commands:
+      - 'apt-get install -yq ruby ruby1.9.1-dev libaugeas-dev libaugeas-ruby lsb-release wget net-tools curl'
+    docker_preserve_image: true
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/acceptance/xplugins001.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,91 @@
+require 'spec_helper_acceptance'
+
+describe "Integration testing" do
+
+  describe "Setup Elasticsearch" do
+
+    it 'should run successfully' do
+      pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, java_install => true, package_url => '#{test_settings['snapshot_package']}' }
+            elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+           "
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+    end
+
+
+    describe service(test_settings['service_name_a']) do
+      it { should be_enabled }
+      it { should be_running }
+    end
+
+    describe package(test_settings['package_name']) do
+      it { should be_installed }
+    end
+
+    describe file(test_settings['pid_file_a']) do
+      it { should be_file }
+      its(:content) { should match /[0-9]+/ }
+    end
+
+    describe "Elasticsearch serves requests on" do
+      it {
+        curl_with_retries("check ES on #{test_settings['port_a']}", default, "http://localhost:#{test_settings['port_a']}/?pretty=true", 0)
+      }
+    end
+
+    describe file('/etc/elasticsearch/es-01/elasticsearch.yml') do
+      it { should be_file }
+      it { should contain 'name: elasticsearch001' }
+    end
+
+    describe file('/usr/share/elasticsearch/templates_import') do
+      it { should be_directory }
+    end
+
+  end
+
+  describe "Plugin tests" do
+
+    describe "Install a plugin from official repository" do
+
+      it 'should run successfully' do
+        pp = "class { 'elasticsearch': config => { 'cluster.name' => '#{test_settings['cluster_name']}'}, java_install => true, package_url => '#{test_settings['snapshot_package']}' }
+              elasticsearch::instance { 'es-01': config => { 'node.name' => 'elasticsearch001', 'http.port' => '#{test_settings['port_a']}' } }
+              elasticsearch::plugin{'#{ENV['LICENSE_PLUGIN_NAME']}': instances => 'es-01', url => '#{ENV['LICENSE_PLUGIN_URL']}' }
+              elasticsearch::plugin{'#{ENV['PLUGIN_NAME']}': instances => 'es-01', url => '#{ENV['PLUGIN_URL']}' }
+             "
+
+        # Run it twice and test for idempotency
+        apply_manifest(pp, :catch_failures => true)
+        expect(apply_manifest(pp, :catch_failures => true).exit_code).to be_zero
+      end
+
+      describe service(test_settings['service_name_a']) do
+        it { should be_enabled }
+        it { should be_running }
+      end
+
+      describe package(test_settings['package_name']) do
+        it { should be_installed }
+      end
+
+      describe file(test_settings['pid_file_a']) do
+        it { should be_file }
+        its(:content) { should match /[0-9]+/ }
+      end
+
+      it 'make sure the directory exists' do
+        shell("ls /usr/share/elasticsearch/plugins/#{ENV['PLUGIN_NAME']}", {:acceptable_exit_codes => 0})
+      end
+
+      it 'make sure elasticsearch reports it as existing' do
+        curl_with_retries('validated plugin as installed', default, "http://localhost:#{test_settings['port_a']}/_nodes/?plugin | grep #{ENV['PLUGIN_NAME']}", 0)
+      end
+
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/classes/000_elasticsearch_init_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,306 @@
+require 'spec_helper'
+
+describe 'elasticsearch', :type => 'class' do
+
+  default_params = {
+    :config  => { 'node.name' => 'foo' }
+  }
+
+  on_supported_os.each do |os, facts|
+
+    context "on #{os}" do
+
+      case facts[:osfamily]
+      when 'Debian'
+        let(:defaults_path) { '/etc/default' }
+        let(:pkg_ext) { 'deb' }
+        let(:pkg_prov) { 'dpkg' }
+        let(:version_add) { '' }
+        if facts[:lsbmajdistrelease] >= '8'
+          test_pid = true
+        else
+          test_pid = false
+        end
+      when 'RedHat'
+        let(:defaults_path) { '/etc/sysconfig' }
+        let(:pkg_ext) { 'rpm' }
+        let(:pkg_prov) { 'rpm' }
+        let(:version_add) { '-1' }
+        if facts[:operatingsystemmajrelease] >= '7'
+          test_pid = true
+        else
+          test_pid = false
+        end
+      when 'Suse'
+        let(:defaults_path) { '/etc/sysconfig' }
+        let(:pkg_ext) { 'rpm' }
+        let(:pkg_prov) { 'rpm' }
+        let(:version_add) { '-1' }
+      end
+
+      let(:facts) do
+        facts.merge({ 'scenario' => '', 'common' => '' })
+      end
+
+      let (:params) do
+        default_params.merge({ })
+      end
+
+      context 'main class tests' do
+
+        # init.pp
+        it { should compile.with_all_deps }
+        it { should contain_class('elasticsearch') }
+        it { should contain_anchor('elasticsearch::begin') }
+        it { should contain_class('elasticsearch::params') }
+        it { should contain_class('elasticsearch::package').that_requires('Anchor[elasticsearch::begin]') }
+        it { should contain_class('elasticsearch::config').that_requires('Class[elasticsearch::package]') }
+
+        # Base directories
+        it { should contain_file('/etc/elasticsearch') }
+        it { should contain_file('/usr/share/elasticsearch/templates_import') }
+        it { should contain_file('/usr/share/elasticsearch/scripts') }
+        it { should contain_file('/usr/share/elasticsearch') }
+        it { should contain_file('/usr/share/elasticsearch/lib') }
+        # it { should contain_file('/usr/share/elasticsearch/plugins') }
+        it { should contain_file('/usr/share/elasticsearch/bin').with(:mode => '0755') }
+	it { should contain_augeas("#{defaults_path}/elasticsearch") }
+
+        # Base files
+        if test_pid == true
+          it { should contain_file('/usr/lib/tmpfiles.d/elasticsearch.conf') }
+        end
+
+	# file removal from package
+	it { should contain_file('/etc/init.d/elasticsearch').with(:ensure => 'absent') }
+	it { should contain_file('/lib/systemd/system/elasticsearch.service').with(:ensure => 'absent') }
+	it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:ensure => 'absent') }
+	it { should contain_file('/etc/elasticsearch/logging.yml').with(:ensure => 'absent') }
+      end
+
+      context 'package installation' do
+
+        context 'via repository' do
+
+          context 'with default settings' do
+
+            it { should contain_package('elasticsearch').with(:ensure => 'present') }
+            it { should_not contain_package('my-elasticsearch').with(:ensure => 'present') }
+
+          end
+
+          context 'with specified version' do
+
+            let (:params) {
+              default_params.merge({
+                :version => '1.0'
+              })
+            }
+
+            it { should contain_package('elasticsearch').with(:ensure => "1.0#{version_add}") }
+          end
+
+          if facts[:osfamily] == 'RedHat'
+            context 'Handle special CentOS/RHEL package versioning' do
+
+              let (:params) {
+                default_params.merge({
+                  :version => '1.1-2'
+                })
+              }
+
+              it { should contain_package('elasticsearch').with(:ensure => "1.1-2") }
+            end
+          end
+
+          context 'with specified package name' do
+
+            let (:params) {
+              default_params.merge({
+                :package_name => 'my-elasticsearch'
+              })
+            }
+
+            it { should contain_package('my-elasticsearch').with(:ensure => 'present') }
+            it { should_not contain_package('elasticsearch').with(:ensure => 'present') }
+          end
+
+          context 'with auto upgrade enabled' do
+
+            let (:params) {
+              default_params.merge({
+                :autoupgrade => true
+              })
+            }
+
+            it { should contain_package('elasticsearch').with(:ensure => 'latest') }
+          end
+
+        end
+
+        context 'when setting package version and package_url' do
+
+          let (:params) {
+            default_params.merge({
+              :version     => '0.90.10',
+              :package_url => "puppet:///path/to/some/elasticsearch-0.90.10.#{pkg_ext}"
+            })
+          }
+
+          it { expect { should raise_error(Puppet::Error) } }
+
+        end
+
+        context 'via package_url setting' do
+
+          context 'using puppet:/// schema' do
+
+            let (:params) {
+              default_params.merge({
+                :package_url => "puppet:///path/to/package.#{pkg_ext}"
+              })
+            }
+
+            it { should contain_file("/opt/elasticsearch/swdl/package.#{pkg_ext}").with(:source => "puppet:///path/to/package.#{pkg_ext}", :backup => false) }
+            it { should contain_package('elasticsearch').with(:ensure => 'present', :source => "/opt/elasticsearch/swdl/package.#{pkg_ext}", :provider => "#{pkg_prov}") }
+          end
+
+          context 'using http:// schema' do
+
+            let (:params) {
+              default_params.merge({
+                :package_url => "http://www.domain.com/path/to/package.#{pkg_ext}"
+              })
+            }
+
+            it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /opt/elasticsearch/swdl') }
+            it { should contain_file('/opt/elasticsearch/swdl').with(:purge => false, :force => false, :require => "Exec[create_package_dir_elasticsearch]") }
+            it { should contain_exec('download_package_elasticsearch').with(:command => "wget --no-check-certificate -O /opt/elasticsearch/swdl/package.#{pkg_ext} http://www.domain.com/path/to/package.#{pkg_ext} 2> /dev/null", :require => 'File[/opt/elasticsearch/swdl]') }
+            it { should contain_package('elasticsearch').with(:ensure => 'present', :source => "/opt/elasticsearch/swdl/package.#{pkg_ext}", :provider => "#{pkg_prov}") }
+          end
+
+          context 'using http:// schema with proxy_url' do
+
+            let (:params) {
+              default_params.merge({
+                :package_url  => "http://www.domain.com/path/to/package.#{pkg_ext}",
+                :proxy_url    => "http://proxy.example.com:12345/",
+              })
+            }
+            it { should contain_exec('download_package_elasticsearch').with(:environment => ["use_proxy=yes","http_proxy=http://proxy.example.com:12345/","https_proxy=http://proxy.example.com:12345/",]) }
+          end
+
+          context 'using https:// schema' do
+
+            let (:params) {
+              default_params.merge({
+                :package_url => "https://www.domain.com/path/to/package.#{pkg_ext}"
+              })
+            }
+
+            it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /opt/elasticsearch/swdl') }
+            it { should contain_file('/opt/elasticsearch/swdl').with(:purge => false, :force => false, :require => 'Exec[create_package_dir_elasticsearch]') }
+            it { should contain_exec('download_package_elasticsearch').with(:command => "wget --no-check-certificate -O /opt/elasticsearch/swdl/package.#{pkg_ext} https://www.domain.com/path/to/package.#{pkg_ext} 2> /dev/null", :require => 'File[/opt/elasticsearch/swdl]') }
+            it { should contain_package('elasticsearch').with(:ensure => 'present', :source => "/opt/elasticsearch/swdl/package.#{pkg_ext}", :provider => "#{pkg_prov}") }
+          end
+
+          context 'using ftp:// schema' do
+
+            let (:params) {
+              default_params.merge({
+                :package_url => "ftp://www.domain.com/path/to/package.#{pkg_ext}"
+              })
+            }
+
+            it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /opt/elasticsearch/swdl') }
+            it { should contain_file('/opt/elasticsearch/swdl').with(:purge => false, :force => false, :require => 'Exec[create_package_dir_elasticsearch]') }
+            it { should contain_exec('download_package_elasticsearch').with(:command => "wget --no-check-certificate -O /opt/elasticsearch/swdl/package.#{pkg_ext} ftp://www.domain.com/path/to/package.#{pkg_ext} 2> /dev/null", :require => 'File[/opt/elasticsearch/swdl]') }
+            it { should contain_package('elasticsearch').with(:ensure => 'present', :source => "/opt/elasticsearch/swdl/package.#{pkg_ext}", :provider => "#{pkg_prov}") }
+          end
+
+          context 'using file:// schema' do
+
+            let (:params) {
+              default_params.merge({
+                :package_url => "file:/path/to/package.#{pkg_ext}"
+              })
+            }
+
+            it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /opt/elasticsearch/swdl') }
+            it { should contain_file('/opt/elasticsearch/swdl').with(:purge => false, :force => false, :require => 'Exec[create_package_dir_elasticsearch]') }
+            it { should contain_file("/opt/elasticsearch/swdl/package.#{pkg_ext}").with(:source => "/path/to/package.#{pkg_ext}", :backup => false) }
+            it { should contain_package('elasticsearch').with(:ensure => 'present', :source => "/opt/elasticsearch/swdl/package.#{pkg_ext}", :provider => "#{pkg_prov}") }
+          end
+
+        end
+
+      end # package
+
+      context 'when setting the module to absent' do
+
+        let (:params) {
+          default_params.merge({
+            :ensure => 'absent'
+          })
+        }
+
+        it { should contain_package('elasticsearch').with(:ensure => 'purged') }
+        it { should contain_file('/usr/share/elasticsearch/plugins').with(:ensure => 'absent') }
+
+      end
+
+      context 'When managing the repository' do
+
+        let (:params) {
+          default_params.merge({
+            :manage_repo => true,
+            :repo_version => '1.0'
+          })
+        }
+        case facts[:osfamily]
+        when 'Debian'
+          it { should contain_class('elasticsearch::repo').that_requires('Anchor[elasticsearch::begin]') }
+          it { should contain_class('apt') }
+          it { should contain_apt__source('elasticsearch').with(:release => 'stable', :repos => 'main', :location => 'http://packages.elastic.co/elasticsearch/1.0/debian') }
+        when 'RedHat'
+          it { should contain_class('elasticsearch::repo').that_requires('Anchor[elasticsearch::begin]') }
+          it { should contain_yumrepo('elasticsearch').with(:baseurl => 'http://packages.elastic.co/elasticsearch/1.0/centos', :gpgkey => 'http://packages.elastic.co/GPG-KEY-elasticsearch', :enabled => 1) }
+        when 'SuSE'
+          it { should contain_class('elasticsearch::repo').that_requires('Anchor[elasticsearch::begin]') }
+          it { should contain_exec('elasticsearch_suse_import_gpg') }
+          it { should contain_zypprepo('elasticsearch').with(:baseurl => 'http://packages.elastic.co/elasticsearch/1.0/centos') }
+        end
+
+      end
+
+      context 'when not supplying a repo_version' do
+        let (:params) {
+          default_params.merge({
+            :manage_repo => true,
+          })
+        }
+        it { expect { should raise_error(Puppet::Error, 'Please fill in a repository version at $repo_version') } }
+      end
+
+      context "Running a a different user" do
+
+        let (:params) {
+          default_params.merge({
+            :elasticsearch_user => 'myesuser',
+            :elasticsearch_group => 'myesgroup'
+          })
+        }
+
+        it { should contain_file('/etc/elasticsearch').with(:owner => 'myesuser', :group => 'myesgroup') }
+        it { should contain_file('/var/log/elasticsearch').with(:owner => 'myesuser') }
+        it { should contain_file('/usr/share/elasticsearch').with(:owner => 'myesuser', :group => 'myesgroup') }
+        # it { should contain_file('/usr/share/elasticsearch/plugins').with(:owner => 'myesuser', :group => 'myesgroup') }
+        it { should contain_file('/usr/share/elasticsearch/data').with(:owner => 'myesuser', :group => 'myesgroup') }
+        it { should contain_file('/var/run/elasticsearch').with(:owner => 'myesuser') } if facts[:osfamily] == 'RedHat'
+      end
+
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/classes/001_hiera_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,192 @@
+require 'spec_helper'
+
+describe 'elasticsearch', :type => 'class' do
+
+  default_params = {
+    :config  => { 'node.name' => 'foo' }
+  }
+
+  facts = {
+    :operatingsystem => 'CentOS',
+    :kernel => 'Linux',
+    :osfamily => 'RedHat',
+    :operatingsystemmajrelease => '6'
+  }
+
+  let (:params) do
+    default_params.merge({ })
+  end
+
+  context "Hiera" do
+  
+    context 'when specifying instances to create' do
+
+      context 'a single instance' do
+
+        let (:facts) {
+          facts.merge({
+            :scenario => 'singleinstance',
+            :common => ''
+          })
+        }
+
+        it { should contain_elasticsearch__instance('es-01').with(:config => { 'node.name' => 'es-01' }) }
+        it { should contain_elasticsearch__service('es-01') }
+        it { should contain_elasticsearch__service__init('es-01') }
+        it { should contain_service('elasticsearch-instance-es-01') }
+        it { should contain_augeas('defaults_es-01') }
+        it { should contain_file('/etc/elasticsearch/es-01').with(:ensure => 'directory') }
+        it { should contain_file('/etc/elasticsearch/es-01/elasticsearch.yml') }
+        it { should contain_file('/etc/elasticsearch/es-01/logging.yml') }
+        it { should contain_exec('mkdir_datadir_elasticsearch_es-01').with(:command => 'mkdir -p /usr/share/elasticsearch/data/es-01') }
+        it { should contain_file('/usr/share/elasticsearch/data/es-01') }
+        it { should contain_file('/etc/init.d/elasticsearch-es-01') }
+        it { should contain_file('/etc/elasticsearch/es-01/scripts').with(:target => '/usr/share/elasticsearch/scripts') }
+        it { should contain_datacat_fragment('main_config_es-01') }
+        it { should contain_datacat('/etc/elasticsearch/es-01/elasticsearch.yml') }
+
+      end
+
+      context 'multiple instances' do
+
+        let (:facts) {
+          facts.merge({
+            :scenario => 'multipleinstances',
+            :common => ''
+          })
+        }
+
+        it { should contain_elasticsearch__instance('es-01').with(:config => { 'node.name' => 'es-01' }) }
+        it { should contain_elasticsearch__service('es-01') }
+        it { should contain_elasticsearch__service__init('es-01') }
+        it { should contain_service('elasticsearch-instance-es-01') }
+        it { should contain_augeas('defaults_es-01') }
+        it { should contain_exec('mkdir_configdir_elasticsearch_es-01') }
+        it { should contain_file('/etc/elasticsearch/es-01').with(:ensure => 'directory') }
+        it { should contain_file('/etc/elasticsearch/es-01/elasticsearch.yml') }
+        it { should contain_file('/etc/elasticsearch/es-01/logging.yml') }
+        it { should contain_exec('mkdir_datadir_elasticsearch_es-01') }
+        it { should contain_file('/usr/share/elasticsearch/data/es-01') }
+        it { should contain_file('/etc/init.d/elasticsearch-es-01') }
+        it { should contain_file('/etc/elasticsearch/es-01/scripts').with(:target => '/usr/share/elasticsearch/scripts') }
+        it { should contain_datacat_fragment('main_config_es-01') }
+        it { should contain_datacat('/etc/elasticsearch/es-01/elasticsearch.yml') }
+
+
+        it { should contain_elasticsearch__instance('es-02').with(:config => { 'node.name' => 'es-02' }) }
+        it { should contain_elasticsearch__service('es-02') }
+        it { should contain_elasticsearch__service__init('es-02') }
+        it { should contain_service('elasticsearch-instance-es-02') }
+        it { should contain_augeas('defaults_es-02') }
+        it { should contain_exec('mkdir_configdir_elasticsearch_es-02') }
+        it { should contain_file('/etc/elasticsearch/es-02').with(:ensure => 'directory') }
+        it { should contain_file('/etc/elasticsearch/es-02/elasticsearch.yml') }
+        it { should contain_file('/etc/elasticsearch/es-02/logging.yml') }
+        it { should contain_exec('mkdir_datadir_elasticsearch_es-02') }
+        it { should contain_file('/usr/share/elasticsearch/data/es-02') }
+        it { should contain_file('/etc/init.d/elasticsearch-es-02') }
+        it { should contain_file('/etc/elasticsearch/es-02/scripts').with(:target => '/usr/share/elasticsearch/scripts') }
+        it { should contain_datacat_fragment('main_config_es-02') }
+        it { should contain_datacat('/etc/elasticsearch/es-02/elasticsearch.yml') }
+
+
+      end
+
+    end
+
+    context 'when we haven\'t specfied any instances to create' do
+
+      let (:facts) {
+        facts.merge({
+          :scenario => '',
+          :common => ''
+        })
+      }
+
+      it { should_not contain_elasticsearch__instance }
+
+    end
+
+    # Hiera Plugin creation.
+
+    context 'when specifying plugins to create' do
+
+      let (:facts) {
+        facts.merge({
+          :scenario => 'singleplugin',
+          :common => ''
+        })
+      }
+
+      it { should contain_elasticsearch__plugin('mobz/elasticsearch-head/1.0.0').with(:ensure => 'present', :module_dir => 'head', :instances => ['es-01'] ) }
+      it { should contain_elasticsearch_plugin('mobz/elasticsearch-head/1.0.0') }
+
+    end
+
+    context 'when we haven\'t specified any plugins to create' do
+
+      let (:facts) {
+        facts.merge({
+          :scenario => '',
+          :common => ''
+        })
+      }
+
+      it { should_not contain_elasticsearch__plugin }
+
+    end
+
+    context "multiple instances using hiera_merge" do
+
+      let (:params) {
+        default_params.merge({
+        :instances_hiera_merge => true
+        })
+      }
+
+      let (:facts) {
+        facts.merge({
+          :common => 'defaultinstance',
+          :scenario => 'singleinstance'
+        })
+      }
+
+      it { should contain_elasticsearch__instance('default').with(:config => { 'node.name' => 'default' }) }
+      it { should contain_elasticsearch__service('default') }
+      it { should contain_elasticsearch__service__init('default') }
+      it { should contain_service('elasticsearch-instance-default') }
+      it { should contain_augeas('defaults_default') }
+      it { should contain_exec('mkdir_configdir_elasticsearch_default') }
+      it { should contain_file('/etc/elasticsearch/default').with(:ensure => 'directory') }
+      it { should contain_file('/etc/elasticsearch/default/elasticsearch.yml') }
+      it { should contain_file('/etc/elasticsearch/default/logging.yml') }
+      it { should contain_exec('mkdir_datadir_elasticsearch_default') }
+      it { should contain_file('/usr/share/elasticsearch/data/default') }
+      it { should contain_file('/etc/init.d/elasticsearch-default') }
+      it { should contain_file('/etc/elasticsearch/default/scripts').with(:target => '/usr/share/elasticsearch/scripts') }
+      it { should contain_datacat_fragment('main_config_default') }
+      it { should contain_datacat('/etc/elasticsearch/default/elasticsearch.yml') }
+
+
+      it { should contain_elasticsearch__instance('es-01').with(:config => { 'node.name' => 'es-01' }) }
+      it { should contain_elasticsearch__service('es-01') }
+      it { should contain_elasticsearch__service__init('es-01') }
+      it { should contain_service('elasticsearch-instance-es-01') }
+      it { should contain_augeas('defaults_es-01') }
+      it { should contain_exec('mkdir_configdir_elasticsearch_es-01') }
+      it { should contain_file('/etc/elasticsearch/es-01').with(:ensure => 'directory') }
+      it { should contain_file('/etc/elasticsearch/es-01/elasticsearch.yml') }
+      it { should contain_file('/etc/elasticsearch/es-01/logging.yml') }
+      it { should contain_exec('mkdir_datadir_elasticsearch_es-01').with(:command => 'mkdir -p /usr/share/elasticsearch/data/es-01') }
+      it { should contain_file('/usr/share/elasticsearch/data/es-01') }
+      it { should contain_file('/etc/init.d/elasticsearch-es-01') }
+      it { should contain_file('/etc/elasticsearch/es-01/scripts').with(:target => '/usr/share/elasticsearch/scripts') }
+      it { should contain_datacat_fragment('main_config_es-01') }
+      it { should contain_datacat('/etc/elasticsearch/es-01/elasticsearch.yml') }
+
+
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/classes/005_elasticsearch_repo_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,143 @@
+require 'spec_helper'
+
+describe 'elasticsearch', :type => 'class' do
+
+  default_params = {
+    :config => {},
+    :manage_repo => true,
+    :repo_version => '1.3',
+    :version => '1.6.0'
+  }
+
+  on_supported_os.each do |os, facts|
+
+    context "on #{os}" do
+
+
+      let(:facts) do
+        facts.merge({ 'scenario' => '', 'common' => '' })
+      end
+
+      let (:params) do
+        default_params
+      end
+
+      context "Use anchor type for ordering" do
+
+        let :params do
+          default_params
+        end
+
+        it { should contain_class('elasticsearch::repo').that_requires('Anchor[elasticsearch::begin]') }
+      end
+
+
+      context "Use stage type for ordering" do
+
+        let :params do
+          default_params.merge({
+            :repo_stage => 'setup'
+          })
+        end
+
+        it { should contain_stage('setup') }
+        it { should contain_class('elasticsearch::repo').with(:stage => 'setup') }
+
+      end
+
+      case facts[:osfamily]
+      when 'Debian'
+        context 'has apt repo parts' do
+          it { should contain_apt__source('elasticsearch').with(:location => 'http://packages.elastic.co/elasticsearch/1.3/debian') }
+        end
+      when 'RedHat'
+        context 'has yum repo parts' do
+          it { should contain_yumrepo('elasticsearch').with(:baseurl => 'http://packages.elastic.co/elasticsearch/1.3/centos') }
+        end
+      when 'Suse'
+        context 'has zypper repo parts' do
+          it { should contain_exec('elasticsearch_suse_import_gpg').with(:command => 'rpmkeys --import http://packages.elastic.co/GPG-KEY-elasticsearch') }
+          it { should contain_zypprepo('elasticsearch').with(:baseurl => 'http://packages.elastic.co/elasticsearch/1.3/centos') }
+        end
+      end
+
+      context "Package pinning" do
+
+        let :params do
+          default_params.merge({
+            :package_pin => true
+          })
+        end
+
+        case facts[:osfamily]
+        when 'Debian'
+          context 'is supported' do
+            it { should contain_apt__pin('elasticsearch').with(:packages => ['elasticsearch'], :version => '1.6.0') }
+          end
+        when 'RedHat'
+          context 'is supported' do
+            it { should contain_yum__versionlock('0:elasticsearch-1.6.0-1.noarch') }
+          end
+        else
+          context 'is not supported' do
+            pending("unable to test for warnings yet. https://github.com/rodjek/rspec-puppet/issues/108")
+          end
+        end
+
+      end
+
+      context "Override repo key ID" do
+
+        let :params do
+          default_params.merge({
+            :repo_key_id => '46095ACC8548582C1A2699A9D27D666CD88E42B4'
+          })
+        end
+
+        case facts[:osfamily]
+        when 'Debian'
+          context 'has override apt key' do
+            it { is_expected.to contain_apt__source('elasticsearch').with({
+              :key => '46095ACC8548582C1A2699A9D27D666CD88E42B4',
+            })}
+          end
+        when 'Suse'
+          context 'has override yum key' do
+            it { is_expected.to contain_exec('elasticsearch_suse_import_gpg').with({
+              :unless  => "test $(rpm -qa gpg-pubkey | grep -i '46095ACC8548582C1A2699A9D27D666CD88E42B4' | wc -l) -eq 1 ",
+            })}
+          end
+        end
+
+      end
+
+      context "Override repo source URL" do
+
+        let :params do
+          default_params.merge({
+            :repo_key_source => 'https://packages.elasticsearch.org/GPG-KEY-elasticsearch'
+          })
+        end
+
+        case facts[:osfamily]
+        when 'Debian'
+          context 'has override apt key source' do
+            it { is_expected.to contain_apt__source('elasticsearch').with({
+              :key_source => 'https://packages.elasticsearch.org/GPG-KEY-elasticsearch',
+            })}
+          end
+        when 'RedHat'
+          context 'has override yum key source' do
+            it { should contain_yumrepo('elasticsearch').with(:gpgkey => 'https://packages.elasticsearch.org/GPG-KEY-elasticsearch') }
+          end
+        when 'Suse'
+          context 'has override yum key source' do
+            it { should contain_exec('elasticsearch_suse_import_gpg').with(:command => 'rpmkeys --import https://packages.elasticsearch.org/GPG-KEY-elasticsearch') }
+          end
+        end
+
+      end
+
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/classes/010_elasticsearch_init_unkown_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+describe 'elasticsearch', :type => 'class' do
+
+  context "on an unknown OS" do
+
+    context "it should fail" do
+      let :facts do {
+        :operatingsystem => 'Windows'
+      } end
+ 
+      it { expect { should raise_error(Puppet::Error) } }
+
+    end
+
+  end
+ 
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/classes/099_coverage_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+at_exit { RSpec::Puppet::Coverage.report! }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/defines/001_elasticsearch_python_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'elasticsearch::python', :type => 'define' do
+
+  let :facts do {
+    :operatingsystem => 'CentOS',
+    :kernel => 'Linux',
+    :osfamily => 'RedHat'
+  } end
+
+  [ 'pyes', 'rawes', 'pyelasticsearch', 'ESClient', 'elasticutils', 'elasticsearch' ].each do |pythonlib|
+
+    context "installation of library #{pythonlib}" do
+
+      let(:title) { pythonlib }
+
+      it { should contain_elasticsearch__python(pythonlib) }
+      it { should contain_package("python_#{pythonlib}").with(:provider => 'pip', :name => pythonlib) }
+
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/defines/002_elasticsearch_ruby_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'elasticsearch::ruby', :type => 'define' do
+
+  let :facts do {
+    :operatingsystem => 'CentOS',
+    :kernel => 'Linux',
+    :osfamily => 'RedHat'
+  } end
+
+  [ 'tire', 'stretcher', 'elastic_searchable', 'elasticsearch', 'flex'].each do |rubylib|
+
+    context "installation of library #{rubylib}" do
+
+      let(:title) { rubylib }
+
+      it { should contain_elasticsearch__ruby(rubylib) }
+      it { should contain_package("ruby_#{rubylib}").with(:provider => 'gem', :name => rubylib) }
+
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/defines/003_elasticsearch_template_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,64 @@
+require 'spec_helper'
+
+describe 'elasticsearch::template', :type => 'define' do
+
+  let :facts do {
+    :operatingsystem => 'CentOS',
+    :kernel => 'Linux',
+    :osfamily => 'RedHat',
+    :operatingsystemmajrelease => '6',
+    :scenario => '',
+    :common => ''
+  } end
+
+  let(:title) { 'foo' }
+  let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }}}'}
+
+  context "Add a template" do
+
+    let :params do {
+      :ensure => 'present',
+      :file   => 'puppet:///path/to/foo.json',
+    } end
+
+    it { should contain_elasticsearch__template('foo') }
+    it { should contain_file('/usr/share/elasticsearch/templates_import/elasticsearch-template-foo.json').with(:source => 'puppet:///path/to/foo.json', :notify => "Exec[delete_template_foo]") }
+    it { should contain_exec('insert_template_foo').with(:command => "curl -sL -w \"%{http_code}\\n\" -XPUT http://localhost:9200/_template/foo -d @/usr/share/elasticsearch/templates_import/elasticsearch-template-foo.json -o /dev/null | egrep \"(200|201)\" > /dev/null", :unless => 'test $(curl -s \'http://localhost:9200/_template/foo?pretty=true\' | wc -l) -gt 1') }
+  end
+
+  context "Delete a template" do
+
+    let :params do {
+      :ensure => 'absent'
+    } end
+
+    it { should contain_elasticsearch__template('foo') }
+    it { should_not contain_file('/usr/share/elasticsearch/templates_import/elasticsearch-template-foo.json').with(:source => 'puppet:///path/to/foo.json') }
+    it { should_not contain_exec('insert_template_foo') }
+    it { should contain_exec('delete_template_foo').with(:command => 'curl -s -XDELETE http://localhost:9200/_template/foo', :notify => nil, :onlyif => 'test $(curl -s \'http://localhost:9200/_template/foo?pretty=true\' | wc -l) -gt 1' ) }
+  end
+
+  context "Add template with alternative host and port" do
+
+    let :params do {
+      :file => 'puppet:///path/to/foo.json',
+      :host => 'otherhost',
+      :port => 9201
+    } end
+
+    it { should contain_elasticsearch__template('foo') }
+    it { should contain_file('/usr/share/elasticsearch/templates_import/elasticsearch-template-foo.json').with(:source => 'puppet:///path/to/foo.json') }
+    it { should contain_exec('insert_template_foo').with(:command => "curl -sL -w \"%{http_code}\\n\" -XPUT http://otherhost:9201/_template/foo -d @/usr/share/elasticsearch/templates_import/elasticsearch-template-foo.json -o /dev/null | egrep \"(200|201)\" > /dev/null", :unless => 'test $(curl -s \'http://otherhost:9201/_template/foo?pretty=true\' | wc -l) -gt 1') }
+  end
+
+  context "Add template using content" do
+
+    let :params do {
+      :content => '{"template":"*","settings":{"number_of_replicas":0}}'
+    } end
+
+    it { should contain_elasticsearch__template('foo') }
+    it { should contain_file('/usr/share/elasticsearch/templates_import/elasticsearch-template-foo.json').with(:content => '{"template":"*","settings":{"number_of_replicas":0}}') }
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/defines/004_elasticsearch_plugin_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,75 @@
+require 'spec_helper'
+
+describe 'elasticsearch::plugin', :type => 'define' do
+
+  let(:title) { 'mobz/elasticsearch-head/1.0.0' }
+  let :facts do {
+    :operatingsystem => 'CentOS',
+    :kernel => 'Linux',
+    :osfamily => 'RedHat',
+    :operatingsystemmajrelease => '6',
+    :scenario => '',
+    :common => ''
+  } end
+  let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }}}'}
+
+  context 'with module_dir' do
+
+    context "Add a plugin" do
+
+      let :params do {
+        :ensure     => 'present',
+        :module_dir => 'head',
+        :instances  => 'es-01'
+      } end
+
+      it { should contain_elasticsearch__plugin('mobz/elasticsearch-head/1.0.0') }
+      it { should contain_elasticsearch_plugin('mobz/elasticsearch-head/1.0.0') }
+    end
+
+    context "Remove a plugin" do
+
+      let :params do {
+        :ensure     => 'absent',
+        :module_dir => 'head',
+        :instances  => 'es-01'
+      } end
+
+      it { should contain_elasticsearch__plugin('mobz/elasticsearch-head/1.0.0') }
+      it { should contain_elasticsearch_plugin('mobz/elasticsearch-head/1.0.0').with(:ensure => 'absent') }
+    end
+
+  end
+
+  context 'with url' do
+
+    context "Add a plugin with full name" do
+
+      let :params do {
+        :ensure     => 'present',
+        :instances  => 'es-01',
+        :url        => 'https://github.com/mobz/elasticsearch-head/archive/master.zip',
+      } end
+
+      it { should contain_elasticsearch__plugin('mobz/elasticsearch-head/1.0.0') }
+      it { should contain_elasticsearch_plugin('mobz/elasticsearch-head/1.0.0').with(:ensure => 'present', :url => 'https://github.com/mobz/elasticsearch-head/archive/master.zip') }
+    end
+
+  end
+
+  context "offline plugin install" do
+
+      let(:title) { 'head' }
+      let :params do {
+        :ensure     => 'present',
+        :instances  => 'es-01',
+        :source     => 'puppet:///path/to/my/plugin.zip',
+      } end
+
+      it { should contain_elasticsearch__plugin('head') }
+      it { should contain_file('/opt/elasticsearch/swdl/plugin.zip').with(:source => 'puppet:///path/to/my/plugin.zip') }
+      it { should contain_elasticsearch_plugin('head').with(:ensure => 'present', :source => '/opt/elasticsearch/swdl/plugin.zip') }
+
+  end
+  
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/defines/005_elasticsearch_instance_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,329 @@
+require 'spec_helper'
+
+describe 'elasticsearch::instance', :type => 'define' do
+
+  default_params = { }
+
+  on_supported_os.each do |os, facts|
+
+    let(:title) { 'es-01' }
+    context "on #{os}" do
+
+      case facts[:osfamily]
+      when 'Debian'
+        let(:defaults_path) { '/etc/default' }
+        let(:pkg_ext) { 'deb' }
+        let(:pkg_prov) { 'dpkg' }
+        case facts[:operatingsystem]
+        when 'Debian'
+          if facts[:operatingsystemmajrelease].to_i >= 8
+            let(:initscript) { 'systemd' }
+          else
+            let(:initscript) { 'Debian' }
+          end
+        when 'Ubuntu'
+          if facts[:operatingsystemmajrelease].to_i >= 15
+            let(:initscript) { 'systemd' }
+          else
+            let(:initscript) { 'Debian' }
+          end
+        end
+      when 'RedHat'
+        let(:defaults_path) { '/etc/sysconfig' }
+        let(:pkg_ext) { 'rpm' }
+        let(:pkg_prov) { 'rpm' }
+        if facts[:operatingsystemmajrelease].to_i >= 7
+          let(:initscript) { 'systemd' }
+        else
+          let(:initscript) { 'RedHat' }
+        end
+      when 'Suse'
+        let(:defaults_path) { '/etc/sysconfig' }
+        let(:pkg_ext) { 'rpm' }
+        let(:pkg_prov) { 'rpm' }
+        let(:initscript) { 'systemd' }
+      end
+
+      let(:facts) do
+        facts.merge({ 'scenario' => '', 'common' => '' })
+      end
+
+      let (:params) do
+        default_params.merge({ })
+      end
+
+      let(:title) { 'es-01' }
+      let(:pre_condition) { 'class {"elasticsearch": }'  }
+
+      context "Service" do
+
+          it { should contain_elasticsearch__service('es-01').with(:init_template => "elasticsearch/etc/init.d/elasticsearch.#{initscript}.erb", :init_defaults => {"CONF_DIR"=>"/etc/elasticsearch/es-01", "CONF_FILE"=>"/etc/elasticsearch/es-01/elasticsearch.yml", "LOG_DIR"=>"/var/log/elasticsearch/es-01", "ES_HOME"=>"/usr/share/elasticsearch"}) }
+
+      end
+
+    end
+
+  end
+
+  let :facts do {
+    :operatingsystem => 'CentOS',
+    :kernel => 'Linux',
+    :osfamily => 'RedHat',
+    :operatingsystemmajrelease => '6',
+    :scenario => '',
+    :common => '',
+    :hostname => 'foo'
+  } end
+
+  let(:title) { 'es-01' }
+  let(:pre_condition) { 'class {"elasticsearch": }'  }
+
+
+  context "Config file" do
+
+    let :params do {
+      :config => { }
+    } end
+
+    it { should contain_datacat_fragment('main_config_es-01') }
+    it { should contain_datacat('/etc/elasticsearch/es-01/elasticsearch.yml') }
+    it { should contain_datacat_collector('/etc/elasticsearch/es-01/elasticsearch.yml') }
+    it { should contain_file('/etc/elasticsearch/es-01/elasticsearch.yml') }
+
+  end
+
+  context "service restarts" do
+
+    context "does not restart when restart_on_change is false" do
+      let :params do {
+        :config => { 'node' => { 'name' => 'test' }  },
+      } end
+      let(:pre_condition) { 'class {"elasticsearch": config => { }, restart_on_change => false }'  }
+      it { should contain_datacat_fragment('main_config_es-01') }
+      it { should contain_datacat('/etc/elasticsearch/es-01/elasticsearch.yml').without_notify }
+
+    end
+
+    context "should happen restart_on_change is true (default)" do
+      let :params do {
+        :config => { 'node' => { 'name' => 'test' }  },
+      } end
+      let(:pre_condition) { 'class {"elasticsearch": config => { }}'  }
+
+      it { should contain_datacat_fragment('main_config_es-01') }
+      it { should contain_datacat('/etc/elasticsearch/es-01/elasticsearch.yml').with(:notify => "Elasticsearch::Service[es-01]") }
+
+    end
+
+  end
+
+  context "Config dir" do
+
+    context "default" do
+      let(:pre_condition) { 'class {"elasticsearch": }'  }
+      it { should contain_exec('mkdir_configdir_elasticsearch_es-01') }
+      it { should contain_file('/etc/elasticsearch/es-01').with(:ensure => 'directory') }
+      it { should contain_datacat_fragment('main_config_es-01') }
+      it { should contain_datacat('/etc/elasticsearch/es-01/elasticsearch.yml') }
+
+      it { should contain_file('/etc/elasticsearch/es-01/logging.yml') }
+      it { should contain_file('/usr/share/elasticsearch/scripts') }
+      it { should contain_file('/etc/elasticsearch/es-01/scripts').with(:target => '/usr/share/elasticsearch/scripts') }
+    end
+
+    context "Set in main class" do
+      let(:pre_condition) { 'class {"elasticsearch": configdir => "/etc/elasticsearch-config" }'  }
+
+      it { should contain_exec('mkdir_configdir_elasticsearch_es-01') }
+      it { should contain_file('/etc/elasticsearch-config').with(:ensure => 'directory') }
+      it { should contain_file('/usr/share/elasticsearch/templates_import').with(:ensure => 'directory') }
+      it { should contain_file('/etc/elasticsearch-config/es-01').with(:ensure => 'directory') }
+      it { should contain_datacat_fragment('main_config_es-01') }
+      it { should contain_datacat('/etc/elasticsearch-config/es-01/elasticsearch.yml') }
+
+      it { should contain_file('/etc/elasticsearch-config/es-01/logging.yml') }
+      it { should contain_file('/usr/share/elasticsearch/scripts') }
+      it { should contain_file('/etc/elasticsearch-config/es-01/scripts').with(:target => '/usr/share/elasticsearch/scripts') }
+    end
+
+    context "set in instance" do
+      let(:pre_condition) { 'class {"elasticsearch": }'  }
+      let :params do {
+        :configdir => '/etc/elasticsearch-config/es-01'
+      } end
+
+      it { should contain_exec('mkdir_configdir_elasticsearch_es-01') }
+      it { should contain_file('/etc/elasticsearch').with(:ensure => 'directory') }
+      it { should contain_file('/etc/elasticsearch-config/es-01').with(:ensure => 'directory') }
+      it { should contain_datacat_fragment('main_config_es-01') }
+      it { should contain_datacat('/etc/elasticsearch-config/es-01/elasticsearch.yml') }
+
+      it { should contain_file('/etc/elasticsearch-config/es-01/logging.yml') }
+      it { should contain_file('/usr/share/elasticsearch/scripts') }
+      it { should contain_file('/etc/elasticsearch-config/es-01/scripts').with(:target => '/usr/share/elasticsearch/scripts') }
+    end
+
+  end
+
+
+  context "data directory" do
+    let(:pre_condition) { 'class {"elasticsearch": }'  }
+
+    context "default" do
+      it { should contain_exec('mkdir_datadir_elasticsearch_es-01') }
+      it { should contain_file('/usr/share/elasticsearch/data/es-01').with( :ensure => 'directory') }
+      it { should contain_file('/usr/share/elasticsearch/data').with( :ensure => 'directory') }
+    end
+
+    context "single from main config " do
+      let(:pre_condition) { 'class {"elasticsearch": datadir => "/var/lib/elasticsearch-data" }'  }
+
+      it { should contain_exec('mkdir_datadir_elasticsearch_es-01') }
+      it { should contain_file('/var/lib/elasticsearch-data').with( :ensure => 'directory') }
+      it { should contain_file('/var/lib/elasticsearch-data/es-01').with( :ensure => 'directory') }
+    end
+
+    context "single from instance config" do
+      let(:pre_condition) { 'class {"elasticsearch": }'  }
+      let :params do {
+        :datadir => '/var/lib/elasticsearch/data'
+      } end
+
+      it { should contain_exec('mkdir_datadir_elasticsearch_es-01') }
+      it { should contain_file('/var/lib/elasticsearch/data').with( :ensure => 'directory') }
+
+    end
+
+    context "multiple from main config" do
+      let(:pre_condition) { 'class {"elasticsearch": datadir => [ "/var/lib/elasticsearch-data01", "/var/lib/elasticsearch-data02"] }'  }
+
+      it { should contain_exec('mkdir_datadir_elasticsearch_es-01') }
+      it { should contain_file('/var/lib/elasticsearch-data01').with( :ensure => 'directory') }
+      it { should contain_file('/var/lib/elasticsearch-data01/es-01').with( :ensure => 'directory') }
+      it { should contain_file('/var/lib/elasticsearch-data02').with( :ensure => 'directory') }
+      it { should contain_file('/var/lib/elasticsearch-data02/es-01').with( :ensure => 'directory') }
+    end
+
+    context "multiple from instance config" do
+      let(:pre_condition) { 'class {"elasticsearch": }'  }
+      let :params do {
+        :datadir => ['/var/lib/elasticsearch-data/01', '/var/lib/elasticsearch-data/02']
+      } end
+
+      it { should contain_exec('mkdir_datadir_elasticsearch_es-01') }
+      it { should contain_file('/var/lib/elasticsearch-data/01').with( :ensure => 'directory') }
+      it { should contain_file('/var/lib/elasticsearch-data/02').with( :ensure => 'directory') }
+    end
+
+   context "Conflicting setting path.data" do
+     let(:pre_condition) { 'class {"elasticsearch": }'  }
+     let :params do {
+       :datadir => '/var/lib/elasticsearch/data',
+       :config  => { 'path.data' => '/var/lib/elasticsearch/otherdata' }
+     } end
+
+      it { should contain_exec('mkdir_datadir_elasticsearch_es-01') }
+      it { should contain_file('/var/lib/elasticsearch/data').with( :ensure => 'directory') }
+      it { should_not contain_file('/var/lib/elasticsearch/otherdata').with( :ensure => 'directory') }
+   end
+
+   context "Conflicting setting path => data" do
+     let(:pre_condition) { 'class {"elasticsearch": }'  }
+     let :params do {
+       :datadir => '/var/lib/elasticsearch/data',
+       :config  => { 'path' => { 'data' => '/var/lib/elasticsearch/otherdata' } }
+     } end
+
+      it { should contain_exec('mkdir_datadir_elasticsearch_es-01') }
+      it { should contain_file('/var/lib/elasticsearch/data').with( :ensure => 'directory') }
+      it { should_not contain_file('/var/lib/elasticsearch/otherdata').with( :ensure => 'directory') }
+   end
+
+   context "With other path options defined" do
+     let(:pre_condition) { 'class {"elasticsearch": }'  }
+     let :params do {
+       :datadir => '/var/lib/elasticsearch/data',
+       :config  => { 'path' => { 'home' => '/var/lib/elasticsearch' } }
+     } end
+
+      it { should contain_exec('mkdir_datadir_elasticsearch_es-01') }
+      it { should contain_file('/var/lib/elasticsearch/data').with( :ensure => 'directory') }
+   end
+
+
+  end
+
+  context "Logging" do
+
+    let(:pre_condition) { 'class {"elasticsearch": }'  }
+
+    context "default" do
+      it { should contain_file('/etc/elasticsearch/es-01/logging.yml').with_content(/^logger.index.search.slowlog: TRACE, index_search_slow_log_file$/).with(:source => nil) }
+    end
+
+    context "from main class" do
+
+      context "config" do
+        let(:pre_condition) { 'class {"elasticsearch": logging_config => { "index.search.slowlog" => "DEBUG, index_search_slow_log_file" } }'  }
+
+        it { should contain_file('/etc/elasticsearch/es-01/logging.yml').with_content(/^logger.index.search.slowlog: DEBUG, index_search_slow_log_file$/).with(:source => nil) }
+      end
+
+      context "logging file " do
+        let(:pre_condition) { 'class {"elasticsearch": logging_file => "puppet:///path/to/logging.yml" }'  }
+
+        it { should contain_file('/etc/elasticsearch/es-01/logging.yml').with(:source => 'puppet:///path/to/logging.yml', :content => nil) }
+      end
+
+    end
+
+    context "from instance" do
+
+      let(:pre_condition) { 'class {"elasticsearch": }'  }
+
+      context "config" do
+        let :params do {
+          :logging_config => { 'index.search.slowlog' => 'INFO, index_search_slow_log_file' }
+        } end
+
+        it { should contain_file('/etc/elasticsearch/es-01/logging.yml').with_content(/^logger.index.search.slowlog: INFO, index_search_slow_log_file$/).with(:source => nil) }
+      end
+
+      context "logging file " do
+        let :params do {
+          :logging_file => 'puppet:///path/to/logging.yml'
+        } end
+
+        it { should contain_file('/etc/elasticsearch/es-01/logging.yml').with(:source => 'puppet:///path/to/logging.yml', :content => nil) }
+      end
+
+    end
+
+  end
+
+  context "running as an other user" do
+
+    let(:pre_condition) { 'class {"elasticsearch": elasticsearch_user => "myesuser", elasticsearch_group => "myesgroup" }'  }
+
+    it { should contain_file('/usr/share/elasticsearch/data/es-01').with(:owner => 'myesuser') }
+    it { should contain_file('/etc/elasticsearch/es-01').with(:owner => 'myesuser', :group => 'myesgroup') }
+    it { should contain_datacat('/etc/elasticsearch/es-01/elasticsearch.yml').with(:owner => 'myesuser', :group => 'myesgroup') }
+    it { should contain_file('/etc/elasticsearch/es-01/elasticsearch.yml').with(:owner => 'myesuser', :group => 'myesgroup') }
+    it { should contain_file('/etc/elasticsearch/es-01/logging.yml').with(:owner => 'myesuser', :group => 'myesgroup') }
+  end
+
+    context "setting different service status then main class" do
+
+    let(:pre_condition) { 'class {"elasticsearch": status => "enabled" }'  }
+
+    context "staus option" do
+
+      let :params do {
+        :status => 'running'
+      } end
+
+      it { should contain_service('elasticsearch-instance-es-01').with(:ensure => 'running', :enable => false) }
+
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/defines/006_elasticsearch_script_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe 'elasticsearch::script', :type => 'define' do
+
+  let :facts do {
+    :operatingsystem => 'CentOS',
+    :kernel => 'Linux',
+    :osfamily => 'RedHat',
+    :operatingsystemmajrelease => '6',
+    :scenario => '',
+    :common => ''
+  } end
+
+  let(:title) { 'foo' }
+  let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }}}'}
+
+  context "Add a script" do
+
+    let :params do {
+      :ensure => 'present',
+      :source   => 'puppet:///path/to/foo.groovy',
+    } end
+
+    it { should contain_elasticsearch__script('foo') }
+    it { should contain_file('/usr/share/elasticsearch/scripts/foo.groovy').with(:source => 'puppet:///path/to/foo.groovy', :ensure => 'present') }
+  end
+
+  context "Delete a script" do
+
+    let :params do {
+      :ensure => 'absent',
+      :source => 'puppet:///path/to/foo.groovy',
+    } end
+
+    it { should contain_elasticsearch__script('foo') }
+    it { should contain_file('/usr/share/elasticsearch/scripts/foo.groovy').with(:source => 'puppet:///path/to/foo.groovy', :ensure => 'absent') }
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/defines/010_elasticsearch_service_init_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,128 @@
+require 'spec_helper'
+
+describe 'elasticsearch::service::init', :type => 'define' do
+
+  let :facts do {
+    :operatingsystem => 'CentOS',
+    :kernel => 'Linux',
+    :osfamily => 'RedHat',
+    :operatingsystemmajrelease => '6',
+    :scenario => '',
+    :common => ''
+  } end
+
+  let(:title) { 'es-01' }
+  let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }}}' }
+
+  context "Setup service" do
+
+    let :params do {
+      :ensure => 'present',
+      :status => 'enabled'
+    } end
+
+    it { should contain_elasticsearch__service__init('es-01') }
+    it { should contain_service('elasticsearch-instance-es-01').with(:ensure => 'running', :enable => true) }
+  end
+
+  context "Remove service" do
+
+    let :params do {
+      :ensure => 'absent'
+    } end
+
+    it { should contain_elasticsearch__service__init('es-01') }
+    it { should contain_service('elasticsearch-instance-es-01').with(:ensure => 'stopped', :enable => false) }
+  end
+
+  context "unmanaged" do
+      let :params do {
+        :ensure => 'present',
+	:status => 'unmanaged'
+      } end
+
+    it { should contain_elasticsearch__service__init('es-01') }
+      it { should_not contain_service('elasticsearch-instance-es-01') }
+      it { should_not contain_file('/etc/init.d/elasticsearch-es-01') }
+      it { should_not contain_file('/etc/sysconfig/elasticsearch-es-01') }
+
+  end
+
+  context "Defaults file" do
+
+    context "Set via file" do
+      let :params do {
+        :ensure => 'present',
+	:status => 'enabled',
+	:init_defaults_file => 'puppet:///path/to/initdefaultsfile'
+      } end
+
+      it { should contain_file('/etc/sysconfig/elasticsearch-es-01').with(:source => 'puppet:///path/to/initdefaultsfile', :notify => 'Service[elasticsearch-instance-es-01]', :before => 'Service[elasticsearch-instance-es-01]') }
+    end
+
+    context "Set via hash" do
+      let :params do {
+        :ensure => 'present',
+	:status => 'enabled',
+	:init_defaults => {'ES_HOME' => '/usr/share/elasticsearch' }
+      } end
+
+      it { should contain_augeas('defaults_es-01').with(:incl => '/etc/sysconfig/elasticsearch-es-01', :changes => "set ES_GROUP 'elasticsearch'\nset ES_HOME '/usr/share/elasticsearch'\nset ES_USER 'elasticsearch'\nset MAX_OPEN_FILES '65535'\n", :notify => 'Service[elasticsearch-instance-es-01]', :before => 'Service[elasticsearch-instance-es-01]') }
+    end
+
+    context "No restart when 'restart_on_change' is false" do
+      let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }}, restart_on_change => false } ' }
+
+      context "Set via file" do
+        let :params do {
+          :ensure => 'present',
+	  :status => 'enabled',
+	  :init_defaults_file => 'puppet:///path/to/initdefaultsfile'
+        } end
+
+        it { should contain_file('/etc/sysconfig/elasticsearch-es-01').with(:source => 'puppet:///path/to/initdefaultsfile', :notify => nil, :before => 'Service[elasticsearch-instance-es-01]') }
+      end
+
+      context "Set via hash" do
+        let :params do {
+          :ensure => 'present',
+  	  :status => 'enabled',
+  	  :init_defaults => {'ES_HOME' => '/usr/share/elasticsearch' }
+        } end
+
+        it { should contain_augeas('defaults_es-01').with(:incl => '/etc/sysconfig/elasticsearch-es-01', :changes => "set ES_GROUP 'elasticsearch'\nset ES_HOME '/usr/share/elasticsearch'\nset ES_USER 'elasticsearch'\nset MAX_OPEN_FILES '65535'\n", :notify => nil, :before => 'Service[elasticsearch-instance-es-01]') }
+      end
+
+    end
+
+  end
+
+  context "Init file" do
+    let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }} } ' }
+
+    context "Via template" do
+      let :params do {
+        :ensure => 'present',
+	:status => 'enabled',
+	:init_template => 'elasticsearch/etc/init.d/elasticsearch.RedHat.erb'
+      } end
+
+      it { should contain_file('/etc/init.d/elasticsearch-es-01').with(:notify => 'Service[elasticsearch-instance-es-01]', :before => 'Service[elasticsearch-instance-es-01]') }
+    end
+
+    context "No restart when 'restart_on_change' is false" do
+      let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }}, restart_on_change => false } ' }
+
+      let :params do {
+        :ensure => 'present',
+	:status => 'enabled',
+	:init_template => 'elasticsearch/etc/init.d/elasticsearch.RedHat.erb'
+      } end
+
+      it { should contain_file('/etc/init.d/elasticsearch-es-01').with(:notify => nil, :before => 'Service[elasticsearch-instance-es-01]') }
+
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/defines/011_elasticsearch_service_system_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,130 @@
+require 'spec_helper'
+
+describe 'elasticsearch::service::systemd', :type => 'define' do
+
+  let :facts do {
+    :operatingsystem => 'OpenSuSE',
+    :kernel => 'Linux',
+    :osfamily => 'Suse',
+    :operatingsystemmajrelease => '11',
+    :scenario => '',
+    :common => ''
+  } end
+
+  let(:title) { 'es-01' }
+  let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }}}' }
+
+  context "Setup service" do
+
+    let :params do {
+      :ensure => 'present',
+      :status => 'enabled'
+    } end
+
+    it { should contain_elasticsearch__service__systemd('es-01') }
+    it { should contain_exec('systemd_reload_es-01').with(:command => '/bin/systemctl daemon-reload') }
+    it { should contain_service('elasticsearch-instance-es-01').with(:ensure => 'running', :enable => true, :provider => 'systemd') }
+  end
+
+  context "Remove service" do
+
+    let :params do {
+      :ensure => 'absent'
+    } end
+
+    it { should contain_elasticsearch__service__systemd('es-01') }
+    it { should contain_exec('systemd_reload_es-01').with(:command => '/bin/systemctl daemon-reload') }
+    it { should contain_service('elasticsearch-instance-es-01').with(:ensure => 'stopped', :enable => false, :provider => 'systemd') }
+  end
+
+  context "unmanaged" do
+    let :params do {
+      :ensure => 'present',
+      :status => 'unmanaged'
+    } end
+
+    it { should contain_elasticsearch__service__systemd('es-01') }
+    it { should_not contain_service('elasticsearch-instance-es-01') }
+    it { should_not contain_file('/lib/systemd/system/elasticsearch-es-01.service') }
+    it { should_not contain_file('/etc/sysconfig/elasticsearch-es-01') }
+
+  end
+
+  context "Defaults file" do
+
+    context "Set via file" do
+      let :params do {
+        :ensure => 'present',
+	:status => 'enabled',
+	:init_defaults_file => 'puppet:///path/to/initdefaultsfile'
+      } end
+
+      it { should contain_file('/etc/sysconfig/elasticsearch-es-01').with(:source => 'puppet:///path/to/initdefaultsfile', :before => 'Service[elasticsearch-instance-es-01]') }
+    end
+
+    context "Set via hash" do
+      let :params do {
+        :ensure => 'present',
+	:status => 'enabled',
+	:init_defaults => {'ES_HOME' => '/usr/share/elasticsearch' }
+      } end
+
+      it { should contain_augeas('defaults_es-01').with(:incl => '/etc/sysconfig/elasticsearch-es-01', :changes => "set ES_GROUP 'elasticsearch'\nset ES_HOME '/usr/share/elasticsearch'\nset ES_USER 'elasticsearch'\nset MAX_OPEN_FILES '65535'\n", :before => 'Service[elasticsearch-instance-es-01]') }
+    end
+
+    context "No restart when 'restart_on_change' is false" do
+      let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }}, restart_on_change => false } ' }
+
+      context "Set via file" do
+        let :params do {
+          :ensure => 'present',
+	  :status => 'enabled',
+	  :init_defaults_file => 'puppet:///path/to/initdefaultsfile'
+        } end
+
+        it { should contain_file('/etc/sysconfig/elasticsearch-es-01').with(:source => 'puppet:///path/to/initdefaultsfile', :notify => 'Exec[systemd_reload_es-01]', :before => 'Service[elasticsearch-instance-es-01]') }
+      end
+
+      context "Set via hash" do
+        let :params do {
+          :ensure => 'present',
+  	  :status => 'enabled',
+  	  :init_defaults => {'ES_HOME' => '/usr/share/elasticsearch' }
+        } end
+
+        it { should contain_augeas('defaults_es-01').with(:incl => '/etc/sysconfig/elasticsearch-es-01', :changes => "set ES_GROUP 'elasticsearch'\nset ES_HOME '/usr/share/elasticsearch'\nset ES_USER 'elasticsearch'\nset MAX_OPEN_FILES '65535'\n", :notify => 'Exec[systemd_reload_es-01]', :before => 'Service[elasticsearch-instance-es-01]') }
+      end
+
+    end
+
+  end
+
+  context "Init file" do
+    let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }} } ' }
+
+    context "Via template" do
+      let :params do {
+        :ensure => 'present',
+	:status => 'enabled',
+	:init_template => 'elasticsearch/etc/init.d/elasticsearch.systemd.erb'
+      } end
+
+      it { should contain_file('/lib/systemd/system/elasticsearch-es-01.service').with(:before => 'Service[elasticsearch-instance-es-01]') }
+    end
+
+    context "No restart when 'restart_on_change' is false" do
+      let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }}, restart_on_change => false } ' }
+
+      let :params do {
+        :ensure => 'present',
+	:status => 'enabled',
+	:init_template => 'elasticsearch/etc/init.d/elasticsearch.systemd.erb'
+      } end
+
+      it { should contain_file('/lib/systemd/system/elasticsearch-es-01.service').with(:notify => 'Exec[systemd_reload_es-01]', :before => 'Service[elasticsearch-instance-es-01]') }
+
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/fixtures/facts/facts_url1.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+{
+  "status" : 200,
+  "name" : "Warlock",
+  "cluster_name" : "elasticsearch",
+  "version" : {
+    "number" : "1.4.2",
+    "build_hash" : "927caff6f05403e936c20bf4529f144f0c89fd8c",
+    "build_timestamp" : "2014-12-16T14:11:12Z",
+    "build_snapshot" : false,
+    "lucene_version" : "4.10.2"
+  },
+  "tagline" : "You Know, for Search"
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/fixtures/facts/facts_url2.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+{"cluster_name":"elasticsearch","nodes":{"yQAWBO3FS8CupZnSvAVziQ":{"name":"Warlock","transport_address":"inet[/192.168.100.40:9300]","host":"devel01","ip":"192.168.100.40","version":"1.4.2","build":"927caff","http_address":"inet[/192.168.100.40:9200]","settings":{"path":{"data":"/var/lib/elasticsearch","work":"/tmp/elasticsearch","home":"/usr/share/elasticsearch","conf":"/etc/elasticsearch","logs":"/var/log/elasticsearch"},"pidfile":"/var/run/elasticsearch.pid","cluster":{"name":"elasticsearch"},"config":"/etc/elasticsearch/elasticsearch.yml","client":{"type":"node"},"name":"Warlock"},"os":{"refresh_interval_in_millis":1000,"available_processors":2,"cpu":{"vendor":"Intel","model":"Common KVM processor","mhz":3399,"total_cores":2,"total_sockets":1,"cores_per_socket":2,"cache_size_in_bytes":4096},"mem":{"total_in_bytes":2099183616},"swap":{"total_in_bytes":2145382400}},"process":{"refresh_interval_in_millis":1000,"id":20638,"max_file_descriptors":65535,"mlockall":false},"jvm":{"pid":20638,"version":"1.7.0_55","vm_name":"OpenJDK 64-Bit Server VM","vm_version":"24.51-b03","vm_vendor":"Oracle Corporation","start_time_in_millis":1421686713108,"mem":{"heap_init_in_bytes":268435456,"heap_max_in_bytes":1056309248,"non_heap_init_in_bytes":24313856,"non_heap_max_in_bytes":224395264,"direct_max_in_bytes":1056309248},"gc_collectors":["ParNew","ConcurrentMarkSweep"],"memory_pools":["Code Cache","Par Eden Space","Par Survivor Space","CMS Old Gen","CMS Perm Gen"]},"thread_pool":{"generic":{"type":"cached","keep_alive":"30s","queue_size":-1},"index":{"type":"fixed","min":2,"max":2,"queue_size":"200"},"bench":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"get":{"type":"fixed","min":2,"max":2,"queue_size":"1k"},"snapshot":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"merge":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"suggest":{"type":"fixed","min":2,"max":2,"queue_size":"1k"},"bulk":{"type":"fixed","min":2,"max":2,"queue_size":"50"},"optimize":{"type":"fixed","min":1,"max":1,"queue_size":-1},"warmer":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"flush":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1},"search":{"type":"fixed","min":6,"max":6,"queue_size":"1k"},"listener":{"type":"fixed","min":1,"max":1,"queue_size":-1},"percolate":{"type":"fixed","min":2,"max":2,"queue_size":"1k"},"management":{"type":"scaling","min":1,"max":5,"keep_alive":"5m","queue_size":-1},"refresh":{"type":"scaling","min":1,"max":1,"keep_alive":"5m","queue_size":-1}},"network":{"refresh_interval_in_millis":5000,"primary_interface":{"address":"192.168.100.40","name":"eth0","mac_address":"9E:FA:5C:B8:CC:4D"}},"transport":{"bound_address":"inet[/0:0:0:0:0:0:0:0:9300]","publish_address":"inet[/192.168.100.40:9300]"},"http":{"bound_address":"inet[/0:0:0:0:0:0:0:0:9200]","publish_address":"inet[/192.168.100.40:9200]","max_content_length_in_bytes":104857600},"plugins":[{"name":"kopf","version":"1.4.3","description":"kopf - simple web administration tool for ElasticSearch","url":"/_plugin/kopf/","jvm":false,"site":true}]}}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/fixtures/hiera/hiera.yaml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+---
+:backends: yaml
+:yaml:
+  :datadir: spec/fixtures/hiera/hieradata
+:hierarchy:
+- ! '%{scenario}'
+- envs/%{common}
+:logger: console
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/fixtures/hiera/hieradata/envs/defaultinstance.yaml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+---
+elasticsearch::instances:
+  default:
+    config:
+      node.name: 'default'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/fixtures/hiera/hieradata/multipleinstances.yaml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+---
+elasticsearch::instances:
+  es-01:
+    config:
+      node.name: 'es-01'
+  es-02:
+    config:
+      node.name: 'es-02'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleinstance.yaml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+---
+elasticsearch::instances:
+  es-01:
+    config:
+      node.name: 'es-01'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleplugin.yaml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+---
+elasticsearch::instances:
+  es-01:
+    config:
+      node.name: 'es-01'
+elasticsearch::plugins:
+  'mobz/elasticsearch-head/1.0.0':
+    ensure: 'present'
+    module_dir: 'head'
+    instances:
+      - 'es-01'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/functions/es_facts_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,74 @@
+require 'spec_helper'
+require 'webmock/rspec'
+
+describe "ES facts" do
+
+  before(:each) do
+    stub_request(:get, "http://localhost:9200/").with(:headers => {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}).to_return(:status => 200, :body => File.read(File.join(fixture_path, 'facts/facts_url1.json') ), :headers => {})
+    stub_request(:get, "http://localhost:9200/_nodes/Warlock").with(:headers => {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}).to_return(:status => 200, :body => File.read(File.join(fixture_path, 'facts/facts_url2.json') ))
+
+    allow(File).to receive(:directory?).with('/etc/elasticsearch').and_return(true)
+    allow(Dir).to receive(:foreach).and_yield('es01')
+    allow(File).to receive(:exists?).with('/etc/elasticsearch/es01/elasticsearch.yml').and_return(true)
+    allow(YAML).to receive(:load_file).with('/etc/elasticsearch/es01/elasticsearch.yml').and_return({})
+    require 'lib/facter/es_facts'
+  end
+
+  describe "main" do
+    it "elasticsearch_ports" do 
+      expect(Facter.fact(:elasticsearch_ports).value).to eq("9200")
+    end
+
+  end
+
+  describe "instance" do
+
+    it "elasticsearch_9200_name" do 
+      expect(Facter.fact(:elasticsearch_9200_name).value).to eq("Warlock")
+    end
+
+    it "elasticsearch_9200_version" do 
+      expect(Facter.fact(:elasticsearch_9200_version).value).to eq("1.4.2")
+    end
+
+    it "elasticsearch_9200_cluster_name" do 
+      expect(Facter.fact(:elasticsearch_9200_cluster_name).value).to eq("elasticsearch")
+    end
+
+    it "elasticsearch_9200_node_id" do 
+      expect(Facter.fact(:elasticsearch_9200_node_id).value).to eq("yQAWBO3FS8CupZnSvAVziQ")
+    end
+    
+    it "elasticsearch_9200_mlockall" do 
+      expect(Facter.fact(:elasticsearch_9200_mlockall).value).to be_falsy
+    end
+    
+    it "elasticsearch_9200_plugins" do 
+      expect(Facter.fact(:elasticsearch_9200_plugins).value).to eq("kopf")
+    end
+ 
+    describe "plugin kopf" do
+      it "elasticsearch_9200_plugin_kopf_version" do 
+        expect(Facter.fact(:elasticsearch_9200_plugin_kopf_version).value).to eq("1.4.3")
+      end
+      
+      it "elasticsearch_9200_plugin_kopf_description" do 
+        expect(Facter.fact(:elasticsearch_9200_plugin_kopf_description).value).to eq("kopf - simple web administration tool for ElasticSearch")
+      end
+      
+      it "elasticsearch_9200_plugin_kopf_url" do 
+        expect(Facter.fact(:elasticsearch_9200_plugin_kopf_url).value).to eq("/_plugin/kopf/")
+      end
+
+      it "elasticsearch_9200_plugin_kopf_jvm" do 
+        expect(Facter.fact(:elasticsearch_9200_plugin_kopf_jvm).value).to be_falsy
+      end
+      
+      it "elasticsearch_9200_plugin_kopf_site" do 
+        expect(Facter.fact(:elasticsearch_9200_plugin_kopf_site).value).to be_truthy
+      end
+
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/functions/plugin_dir_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,47 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+
+describe "the plugin_dir function" do
+  let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+  it "should exist" do
+    expect(Puppet::Parser::Functions.function("plugin_dir")).to eq("function_plugin_dir")
+  end
+
+  it "should raise a ParseError if there is less than 1 argument" do
+    expect { scope.function_plugin_dir([]) }.to raise_error(Puppet::ParseError)
+  end
+
+  it "should raise a ParseError if there are more than 2 arguments" do
+    expect { scope.function_plugin_dir(['a', 'b', 'c']) }.to raise_error(Puppet::ParseError)
+  end
+
+  it "should complain about non-string first argument" do
+    expect { scope.function_plugin_dir([[]]) }.to raise_error(Puppet::ParseError)
+  end
+
+  list = [
+    { 'name' => 'mobz/elasticsearch-head',  'dir' => 'head' },
+    { 'name' => 'lukas-vlcek/bigdesk/2.4.0', 'dir' => 'bigdesk' },
+    { 'name' => 'elasticsearch/elasticsearch-cloud-aws/2.5.1', 'dir' => 'cloud-aws' },
+    { 'name' => 'com.sksamuel.elasticsearch/elasticsearch-river-redis/1.1.0', 'dir' => 'river-redis' },
+    { 'name' => 'com.github.lbroudoux.elasticsearch/amazon-s3-river/1.4.0', 'dir' => 'amazon-s3-river' },
+    { 'name' => 'elasticsearch/elasticsearch-lang-groovy/2.0.0', 'dir' => 'lang-groovy' },
+    { 'name' => 'royrusso/elasticsearch-HQ', 'dir' => 'HQ' },
+    { 'name' => 'polyfractal/elasticsearch-inquisitor', 'dir' => 'inquisitor' },
+    { 'name' => 'mycustomplugin', 'dir' => 'mycustomplugin' },
+  ]
+
+  describe "passing plugin name" do
+
+    list.each do |plugin|
+
+      it "should return #{plugin['dir']} directory name for #{plugin['name']}" do
+        result = scope.function_plugin_dir([plugin['name']])
+        expect(result).to eq(plugin['dir'])
+      end
+
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/spec_acceptance_common.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,191 @@
+  test_settings['cluster_name'] = SecureRandom.hex(10)
+
+  test_settings['repo_version2x'] = '2.x'
+  case fact('osfamily')
+    when 'RedHat'
+      test_settings['repo_version']    = '1.3'
+      test_settings['url']             = 'http://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.3.1.noarch.rpm'
+      test_settings['local']           = '/tmp/elasticsearch-1.3.1.noarch.rpm'
+      test_settings['puppet']          = 'elasticsearch-1.3.1.noarch.rpm'
+      test_settings['package_name']    = 'elasticsearch'
+      test_settings['service_name_a']  = 'elasticsearch-es-01'
+      test_settings['service_name_b']  = 'elasticsearch-es-02'
+      test_settings['pid_file_a']      = '/var/run/elasticsearch/elasticsearch-es-01.pid'
+      test_settings['pid_file_b']      = '/var/run/elasticsearch/elasticsearch-es-02.pid'
+      test_settings['defaults_file_a'] = '/etc/sysconfig/elasticsearch-es-01'
+      test_settings['defaults_file_b'] = '/etc/sysconfig/elasticsearch-es-02'
+      test_settings['port_a']          = '9200'
+      test_settings['port_b']          = '9201'
+      test_settings['install_package_version'] = '1.3.5'
+      test_settings['install_version'] = '1.3.5'
+      test_settings['upgrade_package_version'] = '1.3.6'
+      test_settings['upgrade_version'] = '1.3.6'
+    when 'Debian'
+      case fact('operatingsystem')
+        when 'Ubuntu'
+          test_settings['repo_version']    = '1.3'
+          test_settings['url']             = 'http://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.3.1.deb'
+          test_settings['local']           = '/tmp/elasticsearch-1.3.1.deb'
+          test_settings['puppet']          = 'elasticsearch-1.3.1.deb'
+          test_settings['pid_file_a']      = '/var/run/elasticsearch-es-01.pid'
+          test_settings['pid_file_b']      = '/var/run/elasticsearch-es-02.pid'
+          test_settings['install_package_version'] = '1.3.5'
+          test_settings['install_version'] = '1.3.5'
+          test_settings['upgrade_package_version'] = '1.3.6'
+          test_settings['upgrade_version'] = '1.3.6'
+        when 'Debian'
+          case fact('lsbmajdistrelease')
+            when '6'
+              test_settings['repo_version']    = '1.1'
+              test_settings['url']             = 'http://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.1.0.deb'
+              test_settings['local']           = '/tmp/elasticsearch-1.1.0.deb'
+              test_settings['puppet']          = 'elasticsearch-1.1.0.deb'
+              test_settings['pid_file_a']      = '/var/run/elasticsearch-es-01.pid'
+              test_settings['pid_file_b']      = '/var/run/elasticsearch-es-02.pid'
+              test_settings['install_package_version'] = '1.1.1'
+              test_settings['install_version'] = '1.1.1'
+              test_settings['upgrade_package_version'] = '1.1.2'
+              test_settings['upgrade_version'] = '1.1.2'
+            when '7'
+              test_settings['repo_version']    = '1.3'
+              test_settings['url']             = 'http://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.3.1.deb'
+              test_settings['local']           = '/tmp/elasticsearch-1.3.1.deb'
+              test_settings['puppet']          = 'elasticsearch-1.3.1.deb'
+              test_settings['pid_file_a']      = '/var/run/elasticsearch-es-01.pid'
+              test_settings['pid_file_b']      = '/var/run/elasticsearch-es-02.pid'
+              test_settings['install_package_version'] = '1.3.5'
+              test_settings['install_version'] = '1.3.5'
+              test_settings['upgrade_package_version'] = '1.3.6'
+              test_settings['upgrade_version'] = '1.3.6'
+            else
+              test_settings['repo_version']    = '1.3'
+              test_settings['url']             = 'http://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.3.1.deb'
+              test_settings['local']           = '/tmp/elasticsearch-1.3.1.deb'
+              test_settings['puppet']          = 'elasticsearch-1.3.1.deb'
+              test_settings['pid_file_a']      = '/var/run/elasticsearch/elasticsearch-es-01.pid'
+              test_settings['pid_file_b']      = '/var/run/elasticsearch/elasticsearch-es-02.pid'
+              test_settings['install_package_version'] = '1.3.5'
+              test_settings['install_version'] = '1.3.5'
+              test_settings['upgrade_package_version'] = '1.3.6'
+              test_settings['upgrade_version'] = '1.3.6'
+          end
+      end
+      test_settings['package_name']    = 'elasticsearch'
+      test_settings['service_name_a']  = 'elasticsearch-es-01'
+      test_settings['service_name_b']  = 'elasticsearch-es-02'
+      test_settings['defaults_file_a'] = '/etc/default/elasticsearch-es-01'
+      test_settings['defaults_file_b'] = '/etc/default/elasticsearch-es-02'
+      test_settings['port_a']          = '9200'
+      test_settings['port_b']          = '9201'
+    when 'Suse'
+      test_settings['repo_version']    = '1.3'
+      test_settings['url']             = 'http://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.3.1.noarch.rpm'
+      test_settings['local']           = '/tmp/elasticsearch-1.3.1.noarch.rpm'
+      test_settings['puppet']          = 'elasticsearch-1.3.1.noarch.rpm'
+      test_settings['install_package_version'] = '1.3.5'
+      test_settings['install_version'] = '1.3.5'
+      test_settings['upgrade_package_version'] = '1.3.6'
+      test_settings['upgrade_version'] = '1.3.6'
+      test_settings['package_name']    = 'elasticsearch'
+      test_settings['service_name_a']  = 'elasticsearch-es-01'
+      test_settings['service_name_b']  = 'elasticsearch-es-02'
+      test_settings['pid_file_a']      = '/var/run/elasticsearch/elasticsearch-es-01.pid'
+      test_settings['pid_file_b']      = '/var/run/elasticsearch/elasticsearch-es-02.pid'
+      test_settings['defaults_file_a'] = '/etc/sysconfig/elasticsearch-es-01'
+      test_settings['defaults_file_b'] = '/etc/sysconfig/elasticsearch-es-02'
+      test_settings['port_a']          = '9200'
+      test_settings['port_b']          = '9201'
+  end
+
+  test_settings['datadir_1'] = '/var/lib/elasticsearch-data/1/'
+  test_settings['datadir_2'] = '/var/lib/elasticsearch-data/2/'
+  test_settings['datadir_3'] = '/var/lib/elasticsearch-data/3/'
+
+  test_settings['good_json']='{
+    "template" : "logstash-*",
+    "settings" : {
+      "index.refresh_interval" : "5s",
+      "analysis" : {
+	"analyzer" : {
+	  "default" : {
+	    "type" : "standard",
+	    "stopwords" : "_none_"
+	  }
+	}
+      }
+    },
+    "mappings" : {
+      "_default_" : {
+	 "_all" : {"enabled" : true},
+	 "dynamic_templates" : [ {
+	   "string_fields" : {
+	     "match" : "*",
+	     "match_mapping_type" : "string",
+	     "mapping" : {
+	       "type" : "multi_field",
+		 "fields" : {
+		   "{name}" : {"type": "string", "index" : "analyzed", "omit_norms" : true },
+		   "raw" : {"type": "string", "index" : "not_analyzed", "ignore_above" : 256}
+		 }
+	     }
+	   }
+	 } ],
+	 "properties" : {
+	   "@version": { "type": "string", "index": "not_analyzed" },
+	   "geoip"  : {
+	     "type" : "object",
+	       "dynamic": true,
+	       "path": "full",
+	       "properties" : {
+		 "location" : { "type" : "geo_point" }
+	       }
+	   }
+	 }
+      }
+    }
+  }'
+
+  test_settings['bad_json']='{
+    "settings" : {
+      "index.refresh_interval" : "5s",
+      "analysis" : {
+	"analyzer" : {
+	  "default" : {
+	    "type" : "standard",
+	    "stopwords" : "_none_"
+	  }
+	}
+      }
+    },
+    "mappings" : {
+      "_default_" : {
+	 "_all" : {"enabled" : true},
+	 "dynamic_templates" : [ {
+	   "string_fields" : {
+	     "match" : "*",
+	     "match_mapping_type" : "string",
+	     "mapping" : {
+	       "type" : "multi_field",
+		 "fields" : {
+		   "{name}" : {"type": "string", "index" : "analyzed", "omit_norms" : true },
+		   "raw" : {"type": "string", "index" : "not_analyzed", "ignore_above" : 256}
+		 }
+	     }
+	   }
+	 } ],
+	 "properties" : {
+	   "@version": { "type": "string", "index": "not_analyzed" },
+	   "geoip"  : {
+	     "type" : "object",
+	       "dynamic": true,
+	       "path": "full",
+	       "properties" : {
+		 "location" : { "type" : "geo_point" }
+	       }
+	   }
+	 }
+      }
+    }
+  }'
+
+RSpec.configuration.test_settings = test_settings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/spec_acceptance_integration.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+
+def get_url
+
+  urls = { 
+    'URL_MASTER' => 'http://s3-eu-west-1.amazonaws.com/build-eu.elasticsearch.org/origin/master/nightly/JDK7/elasticsearch-latest-SNAPSHOT.$EXT$',
+    'URL_SNAP' => 'http://s3-eu-west-1.amazonaws.com/build.eu-west-1.elastic.co/origin/$VERSION$/nightly/JDK7/elasticsearch-latest-SNAPSHOT.$EXT$',
+    'URL_TAGS' => 'http://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-$VERSION$.$EXT$',
+    'URL_TAGS2' => 'https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/$EXT$/elasticsearch/$VERSION$/elasticsearch-$VERSION$.$EXT$'
+  }
+
+  es_version = ENV['ES_VERSION']
+
+  if es_version == 'MASTER_nightly'
+    # We are testing the master branch snapshot
+    url = urls['URL_MASTER']
+  elsif es_version =~ /_nightly$/
+    # We are testing a version snapshot
+    ver = es_version.split('_')[0]
+    url = urls["URL_SNAP"].gsub('$VERSION$', ver)
+  else
+    # we are testing a released version
+    if es_version =~ /^2/
+      _url = urls['URL_TAGS2']
+    else
+      _url = urls['URL_TAGS']
+    end
+    url = _url.gsub('$VERSION$', es_version)
+  end
+
+  return url
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/spec_helper.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+require 'puppetlabs_spec_helper/module_spec_helper'
+require 'rspec-puppet-facts'
+include RspecPuppetFacts
+
+def fixture_path
+  File.expand_path(File.join(__FILE__, '..', 'fixtures'))
+end
+
+$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../'))
+
+RSpec.configure do |c|
+  c.add_setting :fixture_path, :default => fixture_path
+  c.mock_with(:rspec)
+  c.hiera_config = File.join(fixture_path, '/hiera/hiera.yaml')
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/spec_helper_acceptance.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,154 @@
+require 'beaker-rspec'
+require 'pry'
+require 'securerandom'
+require_relative 'spec_acceptance_integration'
+
+def test_settings
+  RSpec.configuration.test_settings
+end
+
+RSpec.configure do |c|
+  c.add_setting :test_settings, :default => {}
+end
+
+files_dir = ENV['files_dir'] || '/home/jenkins/puppet'
+
+proxy_host = ENV['BEAKER_PACKAGE_PROXY'] || ''
+
+if !proxy_host.empty?
+  gem_proxy = "http_proxy=#{proxy_host}" unless proxy_host.empty?
+
+  hosts.each do |host|
+    on host, "echo 'export http_proxy='#{proxy_host}'' >> /root/.bashrc"
+    on host, "echo 'export https_proxy='#{proxy_host}'' >> /root/.bashrc"
+    on host, "echo 'export no_proxy=\"localhost,127.0.0.1,localaddress,.localdomain.com,#{host.name}\"' >> /root/.bashrc"
+  end
+else
+  gem_proxy = ''
+end
+
+hosts.each do |host|
+
+  # Install Puppet
+  if host.is_pe?
+    install_pe
+  else
+    puppetversion = ENV['VM_PUPPET_VERSION']
+    on host, "#{gem_proxy} gem install puppet --no-ri --no-rdoc --version '~> #{puppetversion}'"
+    on host, "mkdir -p #{host['distmoduledir']}"
+
+    if fact('osfamily') == 'Suse'
+      install_package host, 'rubygems ruby-devel augeas-devel libxml2-devel'
+      on host, "#{gem_proxy} gem install ruby-augeas --no-ri --no-rdoc"
+    end
+
+    if host[:type] == 'aio'
+      on host, "mkdir -p /var/log/puppetlabs/puppet"
+    end
+
+  end
+
+  if ENV['ES_VERSION']
+
+    case fact('osfamily')
+      when 'RedHat'
+        if ENV['ES_VERSION'][0,1] == '1'
+          ext='noarch.rpm'
+        else
+          ext='rpm'
+        end
+      when 'Debian'
+        ext='deb'
+      when  'Suse'
+        ext='rpm'
+    end
+
+    url = get_url
+    RSpec.configuration.test_settings['snapshot_package'] = url.gsub('$EXT$', ext)
+
+  else
+
+    case fact('osfamily')
+      when 'RedHat'
+        scp_to(host, "#{files_dir}/elasticsearch-1.3.1.noarch.rpm", '/tmp/elasticsearch-1.3.1.noarch.rpm')
+      when 'Debian'
+        case fact('lsbmajdistrelease')
+          when '6'
+            scp_to(host, "#{files_dir}/elasticsearch-1.1.0.deb", '/tmp/elasticsearch-1.1.0.deb')
+          else
+            scp_to(host, "#{files_dir}/elasticsearch-1.3.1.deb", '/tmp/elasticsearch-1.3.1.deb')
+        end
+      when 'Suse'
+        case fact('operatingsystem')
+          when 'OpenSuSE'
+            scp_to(host, "#{files_dir}/elasticsearch-1.3.1.noarch.rpm", '/tmp/elasticsearch-1.3.1.noarch.rpm')
+        end
+    end
+
+    scp_to(host, "#{files_dir}/elasticsearch-bigdesk.zip", "/tmp/elasticsearch-bigdesk.zip")
+    scp_to(host, "#{files_dir}/elasticsearch-kopf.zip", "/tmp/elasticsearch-kopf.zip")
+
+  end
+
+  # on debian/ubuntu nodes ensure we get the latest info
+  # Can happen we have stalled data in the images
+  if fact('osfamily') == 'Debian'
+    on host, "apt-get update"
+  end
+  if fact('osfamily') == 'RedHat'
+    on host, "yum -y update"
+  end
+
+end
+
+RSpec.configure do |c|
+  # Project root
+  proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+  # Readable test descriptions
+  c.formatter = :documentation
+
+  # Configure all nodes in nodeset
+  c.before :suite do
+    # Install module and dependencies
+    puppet_module_install(:source => proj_root, :module_name => 'elasticsearch')
+    hosts.each do |host|
+
+      copy_hiera_data_to(host, 'spec/fixtures/hiera/hieradata/')
+      on host, puppet('module','install','puppetlabs-java'), { :acceptable_exit_codes => [0,1] }
+      on host, puppet('module','install','richardc-datacat'), { :acceptable_exit_codes => [0,1] }
+
+      if fact('osfamily') == 'Debian'
+        on host, puppet('module','install','puppetlabs-apt', '--version=1.8.0'), { :acceptable_exit_codes => [0,1] }
+      end
+      if fact('osfamily') == 'Suse'
+        on host, puppet('module','install','darin-zypprepo'), { :acceptable_exit_codes => [0,1] }
+      end
+      if fact('osfamily') == 'RedHat'
+        on host, puppet('module', 'upgrade', 'puppetlabs-stdlib'), {  :acceptable_exit_codes => [0,1] }
+        on host, puppet('module', 'install', 'ceritsc-yum'), { :acceptable_exit_codes => [0,1] }
+      end
+
+      if host.is_pe?
+        on(host, 'sed -i -e "s/PATH=PATH:\/opt\/puppet\/bin:/PATH=PATH:/" ~/.ssh/environment')
+      end
+
+      on(host, 'mkdir -p etc/puppet/modules/another/files/')
+
+    end
+  end
+
+  c.after :suite do
+    if ENV['ES_VERSION']
+      hosts.each do |host|
+        timestamp = Time.now
+        log_dir = File.join('./spec/logs', timestamp.strftime("%F_%H_%M_%S"))
+        FileUtils.mkdir_p(log_dir) unless File.directory?(log_dir)
+        scp_from(host, '/var/log/elasticsearch', log_dir)
+      end
+    end
+  end
+
+end
+
+require_relative 'spec_acceptance_common'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/unit/provider/plugin_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,112 @@
+require 'spec_helper'
+
+provider_class = Puppet::Type.type(:elasticsearch_plugin).provider(:plugin)
+
+describe provider_class do
+
+  let(:resource_name) { 'lmenezes/elasticsearch-kopf' }
+  let(:resource) do
+    Puppet::Type.type(:elasticsearch_plugin).new(
+      :name     => resource_name,
+      :ensure   => :present,
+      :provider => 'plugin'
+    )
+  end
+
+  let(:provider) do
+    provider = provider_class.new
+    provider.resource = resource
+    provider
+  end
+
+  describe "ES 1.x" do
+    before(:each) do
+      provider_class.expects(:es).with('-v').returns("Version: 1.7.1, Build: b88f43f/2015-07-29T09:54:16Z, JVM: 1.7.0_79")
+      allow(File).to receive(:open)
+      provider.es_version
+    end
+
+    let(:shortname) { provider.plugin_name(resource_name) }
+
+    describe 'install' do
+      it 'installs plugin' do
+        provider.expects(:plugin).with(['install', [ resource_name] ])
+        provider.create
+      end
+
+
+      it 'with url' do
+        resource[:url] = 'http://url/to/my/plugin.zip'
+        provider.expects(:plugin).with(['install', [ shortname, '--url', 'http://url/to/my/plugin.zip' ] ])
+        provider.create
+      end
+
+      it 'with local file' do
+        resource[:source] = '/tmp/plugin.zip'
+        provider.expects(:plugin).with(['install', [ shortname, '--url', 'file:///tmp/plugin.zip' ] ])
+        provider.create
+      end
+
+      it 'with proxy' do
+        resource[:proxy_args] = '-dproxyport=3128 -dproxyhost=localhost'
+        provider.expects(:plugin).with([['-dproxyport=3128', '-dproxyhost=localhost'], 'install', [resource_name] ])
+        provider.create
+      end
+
+    end
+
+    describe 'removal' do
+      it 'destroys' do
+        provider.expects(:plugin).with(['remove', resource_name])
+        provider.destroy
+      end
+    end
+
+  end
+
+  describe "ES 2.x" do
+
+    before(:each) do
+      allow(provider_class).to receive(:es).with('-v').and_raise(Puppet::ExecutionFailure)
+      allow(provider_class).to receive(:es).with('--version').and_return("Version: 2.0.0, Build: de54438/2015-10-22T08:09:48Z, JVM: 1.8.0_66")
+      allow(File).to receive(:open)
+      provider.es_version
+    end
+
+    let(:shortname) { provider.plugin_name(resource_name) }
+
+    describe 'install' do
+      it 'installs plugin' do
+        provider.expects(:plugin).with(['install', [ resource_name] ])
+        provider.create
+      end
+
+      it 'with url' do
+        resource[:url] = 'http://url/to/my/plugin.zip'
+        provider.expects(:plugin).with(['install', [ 'http://url/to/my/plugin.zip' ] ])
+        provider.create
+      end
+
+      it 'with local file' do
+        resource[:source] = '/tmp/plugin.zip'
+        provider.expects(:plugin).with(['install', [ 'file:///tmp/plugin.zip' ] ])
+        provider.create
+      end
+
+      it 'with proxy' do
+        resource[:proxy_args] = '-dproxyport=3128 -dproxyhost=localhost'
+        provider.expects(:plugin).with([['-dproxyport=3128', '-dproxyhost=localhost'], 'install', [resource_name] ])
+        provider.create
+      end
+    end
+
+    describe 'removal' do
+      it 'destroys' do
+        provider.expects(:plugin).with(['remove', resource_name])
+        provider.destroy
+      end
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/spec/unit/type/plugin_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,57 @@
+require 'spec_helper'
+
+describe Puppet::Type.type(:elasticsearch_plugin).provider(:plugin) do
+
+  let(:resource_name) { "lmenezes/elasticsearch-kopf" }
+
+  describe "input validation" do
+
+    let(:type) { Puppet::Type.type(:elasticsearch_plugin) }
+
+    before do
+      Process.stubs(:euid).returns 0
+      Puppet::Util::Storage.stubs(:store)
+    end
+
+    it "should default to being installed" do
+      plugin = Puppet::Type.type(:elasticsearch_plugin).new(:name => resource_name )
+      expect(plugin.should(:ensure)).to eq(:present)
+    end
+
+    describe "when validating attributes" do
+      [:name, :source, :url, :proxy_args].each do |param|
+        it "should have a #{param} parameter" do
+          expect(type.attrtype(param)).to eq(:param)
+        end
+      end
+
+      it "should have an ensure property" do
+        expect(type.attrtype(:ensure)).to eq(:property)
+      end
+    end
+
+  end
+
+end
+
+  describe 'other tests' do
+
+    prov_c = Puppet::Type.type(:elasticsearch_plugin).provider(:plugin)
+
+    describe prov_c do
+
+      it 'should install a plugin' do
+        resource = Puppet::Type.type(:elasticsearch_plugin).new(
+          :name => "lmenezes/elasticsearch-kopf",
+          :ensure => :present
+        )
+        allow(File).to receive(:open)
+        provider = prov_c.new(resource)
+        provider.expects(:es).with('-v').returns('Version: 1.7.3, Build: b88f43f/2015-07-29T09:54:16Z, JVM: 1.7.0_79')
+        provider.expects(:plugin).with(['install', ['lmenezes/elasticsearch-kopf']])
+        provider.create
+      end
+
+    end
+  end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/templates/etc/elasticsearch/elasticsearch.yml.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,93 @@
+<%-
+
+  # Function to make a structured and sorted yaml representation out of a hash
+  def recursive_hash_to_yml_string(hash, depth=0)
+    spacer = ""
+    depth.times { spacer += "  "}
+    hash.keys.sort.each do |sorted_key|
+      @yml_string += spacer + sorted_key + ": "
+      if hash[sorted_key].is_a?(::Array)
+         keyspacer = ""
+         sorted_key.length.times { keyspacer += " " }
+         @yml_string += "\n"
+         hash[sorted_key].each do |item|
+           @yml_string += spacer + keyspacer + "- " + item +"\n"
+         end
+      elsif hash[sorted_key].is_a?(::Hash)
+        @yml_string += "\n"
+        recursive_hash_to_yml_string(hash[sorted_key], depth+1)
+      else
+        @yml_string += "#{hash[sorted_key].to_s}\n"
+      end
+    end
+  end
+
+  # Function to transform shorted write up of the keys into full hash representation
+  def transform(hash)
+  return_vals = []
+
+  hash.each do |key,val|
+    if m = /^([^.]+)\.(.*)$/.match(key)
+      temp = { m[1] => { m[2] => val } }
+      transform(temp).each do |stuff|
+        return_vals << stuff
+      end
+    else
+      if val.is_a?(::Hash)
+        transform(val).each do |stuff|
+          return_vals << { key => stuff }
+        end
+      else
+        return_vals << { key => val }
+      end
+    end
+  end
+
+  return_vals
+  end
+
+  # Function to deep merge hashes with same keys
+  class ::Hash
+    def deep_merge_with_array_values_concatenated(hash)
+    target = dup
+
+    hash.keys.each do |key|
+      if hash[key].is_a? ::Hash and self[key].is_a? ::Hash
+        target[key] = target[key].deep_merge_with_array_values_concatenated(hash[key])
+        next
+      end
+
+      if hash[key].is_a?(::Array) && target[key].is_a?(::Array)
+        target[key] = target[key] + hash[key]
+      else
+        target[key] = hash[key]
+      end
+    end
+
+    target
+    end
+  end
+
+  # initial string
+  @yml_string = "### MANAGED BY PUPPET ###\n"
+
+  if !@data.empty?
+
+    @yml_string += "---\n"
+
+    ## Transform shorted keys into full write up
+    transformed_config = transform(@data)
+
+    # Merge it back into a hash
+    tmphash = { }
+    transformed_config.each do |subhash|
+      tmphash = tmphash.deep_merge_with_array_values_concatenated(subhash)
+    end
+
+    # Transform it into yaml
+    recursive_hash_to_yml_string(tmphash)
+
+  end
+
+-%>
+<%= @yml_string -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/templates/etc/elasticsearch/logging.yml.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,52 @@
+# This file is managed by Puppet, do not edit manually, your changes *will* be overwritten!
+#
+# Please see the source file for context and more information:
+#
+# https://github.com/elasticsearch/elasticsearch/blob/master/config/logging.yml
+#
+
+es.logger.level: <%= @logging_level %>
+rootLogger: <%= @logging_level %>, console, file
+
+# ----- Configuration set by Puppet ---------------------------------------------
+
+<% @logging_hash.sort.each do |key,value| %>
+logger.<%= key %>: <%= value %>
+<% end %>
+
+# -------------------------------------------------------------------------------
+
+additivity:
+  index.search.slowlog: false
+  index.indexing.slowlog: false
+
+appender:
+  console:
+    type: console
+    layout:
+      type: consolePattern
+      conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"
+
+  file:
+    type: dailyRollingFile
+    file: ${path.logs}/${cluster.name}.log
+    datePattern: "'.'yyyy-MM-dd"
+    layout:
+      type: pattern
+      conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"
+
+  index_search_slow_log_file:
+    type: dailyRollingFile
+    file: ${path.logs}/${cluster.name}_index_search_slowlog.log
+    datePattern: "'.'yyyy-MM-dd"
+    layout:
+      type: pattern
+      conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"
+
+  index_indexing_slow_log_file:
+    type: dailyRollingFile
+    file: ${path.logs}/${cluster.name}_index_indexing_slowlog.log
+    datePattern: "'.'yyyy-MM-dd"
+    layout:
+      type: pattern
+      conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/templates/etc/init.d/elasticsearch.Debian.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,206 @@
+#!/bin/sh
+#
+# /etc/init.d/elasticsearch-<%= @name %> -- startup script for Elasticsearch
+#
+# Written by Miquel van Smoorenburg <miquels@cistron.nl>.
+# Modified for Debian GNU/Linux	by Ian Murdock <imurdock@gnu.ai.mit.edu>.
+# Modified for Tomcat by Stefan Gybas <sgybas@debian.org>.
+# Modified for Tomcat6 by Thierry Carrez <thierry.carrez@ubuntu.com>.
+# Additional improvements by Jason Brittain <jason.brittain@mulesoft.com>.
+# Modified by Nicolas Huray for Elasticsearch <nicolas.huray@gmail.com>.
+#
+### BEGIN INIT INFO
+# Provides:          elasticsearch-<%= @name %>
+# Required-Start:    $network $remote_fs $named
+# Required-Stop:     $network $remote_fs $named
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Starts elasticsearch-<%= @name %>
+# Description:       Starts elasticsearch-<%= @name %> using start-stop-daemon
+### END INIT INFO
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+NAME=elasticsearch-<%= @name %>
+DESC="Elasticsearch Server <%= @name %>"
+DEFAULT=/etc/default/$NAME
+
+if [ `id -u` -ne 0 ]; then
+	echo "You need root privileges to run this script"
+	exit 1
+fi
+
+
+. /lib/lsb/init-functions
+
+if [ -r /etc/default/rcS ]; then
+	. /etc/default/rcS
+fi
+
+
+# The following variables can be overwritten in $DEFAULT
+
+# Run Elasticsearch as this user ID and group ID
+ES_USER=elasticsearch
+ES_GROUP=elasticsearch
+
+# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT)
+JDK_DIRS="/usr/lib/jvm/java-8-oracle /usr/lib/jvm/java-8-openjdk /usr/lib/jvm/java-8-openjdk-amd64/ /usr/lib/jvm/java-8-openjdk-armhf /usr/lib/jvm/java-8-openjdk-i386/ /usr/lib/jvm/java-7-oracle /usr/lib/jvm/java-7-openjdk /usr/lib/jvm/java-7-openjdk-amd64/ /usr/lib/jvm/java-7-openjdk-armhf /usr/lib/jvm/java-7-openjdk-i386/ /usr/lib/jvm/java-6-sun /usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-openjdk-armhf /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/default-java"
+
+
+# Look for the right JVM to use
+for jdir in $JDK_DIRS; do
+    if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then
+        JAVA_HOME="$jdir"
+    fi
+done
+export JAVA_HOME
+
+# Directory where the Elasticsearch binary distribution resides
+ES_HOME=/usr/share/$NAME
+
+# Heap Size (defaults to 256m min, 1g max)
+#ES_HEAP_SIZE=2g
+
+# Heap new generation
+#ES_HEAP_NEWSIZE=
+
+# max direct memory
+#ES_DIRECT_SIZE=
+
+# Additional Java OPTS
+#ES_JAVA_OPTS=
+
+# Maximum number of open files
+MAX_OPEN_FILES=65535
+
+# Maximum amount of locked memory
+#MAX_LOCKED_MEMORY=
+
+# Elasticsearch log directory
+LOG_DIR=/var/log/$NAME
+
+# Elasticsearch data directory
+DATA_DIR=/var/lib/$NAME
+
+# Elasticsearch work directory
+WORK_DIR=/tmp/$NAME
+
+# Elasticsearch configuration directory
+CONF_DIR=/etc/$NAME
+
+# Elasticsearch configuration file (elasticsearch.yml)
+CONF_FILE=$CONF_DIR/elasticsearch.yml
+
+# Maximum number of VMA (Virtual Memory Areas) a process can own
+MAX_MAP_COUNT=262144
+
+# End of variables that can be overwritten in $DEFAULT
+
+# overwrite settings from default file
+if [ -f "$DEFAULT" ]; then
+	. "$DEFAULT"
+fi
+
+# Define other required variables
+PID_FILE=/var/run/$NAME.pid
+DAEMON=$ES_HOME/bin/elasticsearch
+DAEMON_OPTS="-d -p $PID_FILE -Des.default.path.home=$ES_HOME -Des.default.path.logs=$LOG_DIR -Des.default.path.data=$DATA_DIR -Des.default.path.work=$WORK_DIR -Des.default.path.conf=$CONF_DIR"
+
+export ES_HEAP_SIZE
+export ES_HEAP_NEWSIZE
+export ES_DIRECT_SIZE
+export ES_JAVA_OPTS
+export ES_CLASSPATH
+export ES_INCLUDE
+
+# Check DAEMON exists
+test -x $DAEMON || exit 0
+
+checkJava() {
+	if [ -x "$JAVA_HOME/bin/java" ]; then
+		JAVA="$JAVA_HOME/bin/java"
+	else
+		JAVA=`which java`
+	fi
+
+	if [ ! -x "$JAVA" ]; then
+		echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME"
+		exit 1
+	fi
+}
+
+case "$1" in
+  start)
+	checkJava
+
+	if [ -n "$MAX_LOCKED_MEMORY" -a -z "$ES_HEAP_SIZE" ]; then
+		log_failure_msg "MAX_LOCKED_MEMORY is set - ES_HEAP_SIZE must also be set"
+		exit 1
+	fi
+
+	log_daemon_msg "Starting $DESC"
+
+	pid=`pidofproc -p $PID_FILE elasticsearch`
+	if [ -n "$pid" ] ; then
+		log_begin_msg "Already running."
+		log_end_msg 0
+		exit 0
+	fi
+
+	# Prepare environment
+	mkdir -p "$LOG_DIR" "$DATA_DIR" "$WORK_DIR" && chown "$ES_USER":"$ES_GROUP" "$LOG_DIR" "$DATA_DIR" "$WORK_DIR"
+	touch "$PID_FILE" && chown "$ES_USER":"$ES_GROUP" "$PID_FILE"
+
+	if [ -n "$MAX_OPEN_FILES" ]; then
+		ulimit -n $MAX_OPEN_FILES
+	fi
+
+	if [ -n "$MAX_LOCKED_MEMORY" ]; then
+		ulimit -l $MAX_LOCKED_MEMORY
+	fi
+
+	if [ -n "$MAX_MAP_COUNT" ]; then
+		sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT
+	fi
+
+	# Start Daemon
+	start-stop-daemon --start -b --user "$ES_USER" -c "$ES_USER" --pidfile "$PID_FILE" --exec $DAEMON -- $DAEMON_OPTS
+	log_end_msg $?
+	;;
+  stop)
+	log_daemon_msg "Stopping $DESC"
+
+	if [ -f "$PID_FILE" ]; then
+		start-stop-daemon --stop --pidfile "$PID_FILE" \
+			--user "$ES_USER" \
+			--retry=TERM/20/KILL/5 >/dev/null
+		if [ $? -eq 1 ]; then
+			log_progress_msg "$DESC is not running but pid file exists, cleaning up"
+		elif [ $? -eq 3 ]; then
+			PID="`cat $PID_FILE`"
+			log_failure_msg "Failed to stop $DESC (pid $PID)"
+			exit 1
+		fi
+		rm -f "$PID_FILE"
+	else
+		log_progress_msg "(not running)"
+	fi
+	log_end_msg 0
+	;;
+  status)
+	status_of_proc -p $PID_FILE elasticsearch elasticsearch && exit 0 || exit $?
+    ;;
+  restart|force-reload)
+	if [ -f "$PID_FILE" ]; then
+		$0 stop
+		sleep 1
+	fi
+	$0 start
+	;;
+  *)
+	log_success_msg "Usage: $0 {start|stop|restart|force-reload|status}"
+	exit 1
+	;;
+esac
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/templates/etc/init.d/elasticsearch.RedHat.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,161 @@
+#!/bin/sh
+#
+# elasticsearch<%= @name %> <summary>
+#
+# chkconfig:   2345 80 20
+# description: Starts and stops a single elasticsearch instance on this system
+#
+
+### BEGIN INIT INFO
+# Provides: Elasticsearch-<%= @name %>
+# Required-Start: $network $named
+# Required-Stop: $network $named
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: This service manages the elasticsearch daemon
+# Description: Elasticsearch is a very scalable, schema-free and high-performance search solution supporting multi-tenancy and near realtime search.
+### END INIT INFO
+
+#
+# init.d / servicectl compatibility (openSUSE)
+#
+if [ -f /etc/rc.status ]; then
+    . /etc/rc.status
+    rc_reset
+fi
+
+#
+# Source function library.
+#
+if [ -f /etc/rc.d/init.d/functions ]; then
+    . /etc/rc.d/init.d/functions
+fi
+
+exec="/usr/share/elasticsearch/bin/elasticsearch"
+prog="elasticsearch-<%= @name %>"
+pidfile=/var/run/elasticsearch/${prog}.pid
+
+[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
+
+export ES_HEAP_SIZE
+export ES_HEAP_NEWSIZE
+export ES_DIRECT_SIZE
+export ES_JAVA_OPTS
+export ES_CLASSPATH
+export JAVA_HOME 
+export ES_INCLUDE
+
+lockfile=/var/lock/subsys/$prog
+
+# backwards compatibility for old config sysconfig files, pre 0.90.1
+if [ -n $USER ] && [ -z $ES_USER ] ; then
+   ES_USER=$USER
+fi
+
+checkJava() {
+    if [ -x "$JAVA_HOME/bin/java" ]; then
+        JAVA="$JAVA_HOME/bin/java"
+    else
+        JAVA=`which java`
+    fi
+
+    if [ ! -x "$JAVA" ]; then
+        echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME"
+        exit 1
+    fi
+}
+
+start() {
+    checkJava
+    [ -x $exec ] || exit 5
+    [ -f $CONF_FILE ] || exit 6
+    if [ -n "$MAX_LOCKED_MEMORY" -a -z "$ES_HEAP_SIZE" ]; then
+        echo "MAX_LOCKED_MEMORY is set - ES_HEAP_SIZE must also be set"
+        return 7
+    fi
+    if [ -n "$MAX_OPEN_FILES" ]; then
+        ulimit -n $MAX_OPEN_FILES
+    fi
+    if [ -n "$MAX_LOCKED_MEMORY" ]; then
+        ulimit -l $MAX_LOCKED_MEMORY
+    fi
+    if [ -n "$MAX_MAP_COUNT" ]; then
+        sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT
+    fi
+    if [ -n "$WORK_DIR" ]; then
+        mkdir -p "$WORK_DIR"
+        chown "$ES_USER":"$ES_GROUP" "$WORK_DIR"
+    fi
+    echo -n $"Starting $prog: "
+    # if not running, start it up here, usually something like "daemon $exec"
+    daemon --user $ES_USER --pidfile $pidfile $exec -p $pidfile -d -Des.default.path.home=$ES_HOME -Des.default.path.logs=$LOG_DIR -Des.default.path.data=$DATA_DIR -Des.default.path.work=$WORK_DIR -Des.default.path.conf=$CONF_DIR
+    retval=$?
+    echo
+    [ $retval -eq 0 ] && touch $lockfile
+    return $retval
+}
+
+stop() {
+    echo -n $"Stopping $prog: "
+    # stop it here, often "killproc $prog"
+    killproc -p $pidfile -d 20 $prog
+    retval=$?
+    echo
+    [ $retval -eq 0 ] && rm -f $lockfile
+    return $retval
+}
+
+restart() {
+    stop
+    start
+}
+
+reload() {
+    restart
+}
+
+force_reload() {
+    restart
+}
+
+rh_status() {
+    # run checks to determine if the service is running or use generic status
+    status -p $pidfile $prog
+}
+
+rh_status_q() {
+    rh_status >/dev/null 2>&1
+}
+
+
+case "$1" in
+    start)
+        rh_status_q && exit 0
+        $1
+        ;;
+    stop)
+        rh_status_q || exit 0
+        $1
+        ;;
+    restart)
+        $1
+        ;;
+    reload)
+        rh_status_q || exit 7
+        $1
+        ;;
+    force-reload)
+        force_reload
+        ;;
+    status)
+        rh_status
+        ;;
+    condrestart|try-restart)
+        rh_status_q || exit 0
+        restart
+        ;;
+    *)
+        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
+        exit 2
+esac
+exit $?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/templates/etc/init.d/elasticsearch.systemd.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+[Unit]
+Description=Starts and stops a single elasticsearch instance on this system
+Documentation=http://www.elasticsearch.org
+
+[Service]
+Type=forking
+EnvironmentFile=<%= @defaults_location %>/elasticsearch-<%= @name %>
+User=<%= @user %>
+Group=<%= @group %>
+PIDFile=<%= @pid_dir %>/elasticsearch-<%= @name %>.pid
+ExecStart=/usr/share/elasticsearch/bin/elasticsearch -d -p <%= @pid_dir %>/elasticsearch-<%= @name %>.pid -Des.default.path.home=${ES_HOME} -Des.default.path.logs=${LOG_DIR} -Des.default.path.data=${DATA_DIR} -Des.default.path.work=${WORK_DIR} -Des.default.path.conf=${CONF_DIR}
+# See MAX_OPEN_FILES in sysconfig
+LimitNOFILE=<%= @nofile %>
+# See MAX_LOCKED_MEMORY in sysconfig, use "infinity" when MAX_LOCKED_MEMORY=unlimited and using bootstrap.mlockall: true
+<% if @memlock == 'unlimited' %>
+LimitMEMLOCK=infinity
+<% elsif @memlock %>
+LimitMEMLOCK=<%= @memlock %>
+<% end %>
+# Shutdown delay in seconds, before process is tried to be killed with KILL (if configured)
+TimeoutStopSec=20
+
+[Install]
+WantedBy=multi-user.target
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/templates/etc/sysconfig/defaults.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+<% @new_init_defaults.sort.map do |key, value| -%>
+set <%= key %> '<%= value %>'
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/elasticsearch/templates/usr/lib/tmpfiles.d/elasticsearch.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+d    <%= @pid_dir %>   0755 <%= @user %> <%= @group %> - -
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/CHANGELOG.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,658 @@
+## Supported Release 3.6.2
+###Summary
+
+Small release for support of newer PE versions. This increments the version of PE in the metadata.json file.
+
+## 2015-09-22 - Supported Release 3.6.1
+### Summary
+This is a security and bugfix release that fixes incorrect username truncation in the munge for the mysql_user type, incorrect function used in `mysql::server::backup` and fixes compatibility issues with PE 3.3.x.
+
+#### Bugfixes
+- Loosen the regex in mysql_user munging so the username is not unintentionally truncated.
+- Use `warning()` not `warn()`
+- Metadata had inadvertantly dropped 3.3.x support
+- Some 3.3.x compatibility issues in `mysqltuner` were corrected
+
+## 2015-08-10 - Supported Release 3.6.0
+### Summary
+This release adds the ability to use mysql::db and `mysql_*` types against unmanaged or external mysql instances.
+
+#### Features
+- Add ability to use mysql::db WITHOUT mysql::server (ie, externally)
+- Add prescript attribute to mysql::server::backup for xtrabackup
+- Add postscript ability to xtrabackup provider.
+
+#### Bugfixes
+- Fix default root passwords blocking puppet on mysql 5.8
+- Fix service dependency when package_manage is false
+- Fix selinux permissions on my.cnf
+
+##2015-07-23 - Supported Release 3.5.0
+###Summary
+A small release to add explicit support to newer Puppet versions and accumulated patches.
+
+####Features/Improvements
+- Start running tests against puppet 4
+- Support longer usernames on newer MariaDB versions
+- Add parameters for Solaris 11 and 12
+
+####Bugfixes
+- Fix references to the mysql-server package
+- mysql_server_id doesn't throw and error on machines without macaddress
+
+##2015-05-19 - Supported Release 3.4.0
+###Summary
+This release includes the addition of extra facts, OpenBSD compatibility, and a number of other features, improvements and bug fixes.
+
+####Features/Improvements
+- Added server_id fact which includes mac address for better uniqueness
+- Added OpenBSD compatibility, only for 'OpenBSD -current' (due to the recent switch to mariadb)
+- Added a $mysql_group parameter, and use that instead of the $root_group parameter to define the group membership of the mysql error log file.
+- Updated tests for rspec-puppet 2 and future parser
+- Further acceptance testing improvements
+- MODULES-1928 - allow log-error to be undef
+- Split package installation and database install
+- README wording improvements
+- Added options for including/excluding triggers and routines
+- Made the 'TRIGGER' privilege of mysqldump backups depend on whether or not we are actually backing up triggers
+- Cleaned up the privilege assignment in the mysqldump backup script
+- Add a fact for capturing the mysql version installed
+
+####Bugfixes
+- mysql backup: fix regression in mysql_user call
+- Set service_ensure to undef, in the case of an unmanaged service
+- README Typos fixed
+- Bugfix on Xtrabackup crons
+- Fixed a permission problem that was preventing triggers from being backed up
+- MODULES-1981: Revoke and grant difference of old and new privileges
+- Fix an issue were we assume triggers work
+- Change default for mysql::server::backup to ignore_triggers = false
+
+####Deprecations
+mysql::server::old_root_password property
+
+##2015-03-03 - Supported Release 3.3.0
+###Summary
+This release includes major README updates, the addition of backup providers, and a fix for managing the log-bin directory.
+
+####Features
+- Add package_manage parameters to `mysql::server` and `mysql::client` (MODULES-1143)
+- README improvements
+- Add `mysqldump`, `mysqlbackup`, and `xtrabackup` backup providers.
+
+####Bugfixes
+- log-error overrides were not being properly used (MODULES-1804)
+- check for full path for log-bin to stop puppet from managing file '.'
+
+##2015-02-09 - Supported Release 3.2.0
+###Summary
+This release includes several new features and bugfixes, including support for various plugins, making the output from mysql_password more consistent when input is empty and improved username validation.
+
+####Features
+- Add type and provider to manage plugins
+- Add support for authentication plugins
+- Add support for mysql_install_db on freebsd
+- Add `create_root_user` and `create_root_my_cnf` parameters to `mysql::server`
+
+####Bugfixes
+- Remove dependency on stdlib >= 4.1.0 (MODULES-1759)
+- Make grant autorequire user
+- Remove invalid parameter 'provider' from mysql_user instance (MODULES-1731)
+- Return empty string for empty input in mysql_password
+- Fix `mysql::account_security` when fqdn==localhost
+- Update username validation (MODULES-1520)
+- Future parser fix in params.pp
+- Fix package name for debian 8
+- Don't start the service until the server package is installed and the config file is in place
+- Test fixes
+- Lint fixes
+
+##2014-12-16 - Supported Release 3.1.0
+###Summary
+
+This release includes several new features, including SLES12 support, and a number of bug fixes.
+
+####Notes
+
+`mysql::server::mysqltuner` has been refactored to fetch the mysqltuner script from github by default. If you are running on a non-network-connected system, you will need to download that file and have it available to your node at a path specified by the `source` parameter to the `mysqltuner` class.
+
+####Features
+- Add support for install_options for all package resources (MODULES-1484)
+- Add log-bin directory creation
+- Allow mysql::db to import multiple files (MODULES-1338)
+- SLES12 support
+- Improved identifier quoting detections
+- Reworked `mysql::server::mysqltuner` so that we are no longer packaging the script as it is licensed under the GPL.
+
+####Bugfixes
+- Fix regression in username validation
+- Proper containment for mysql::client in mysql::db
+- Support quoted usernames of length 15 and 16 chars
+
+##2014-11-11 - Supported Release 3.0.0
+###Summary
+
+Added several new features including MariaDB support and future parser
+
+####Backwards-incompatible Changes
+* Remove the deprecated `database`, `database_user`, and `database_grant` resources. The correct resources to use are `mysql`, `mysql_user`, and `mysql_grant` respectively.
+
+####Features
+* Add MariaDB Support
+* The mysqltuner perl script has been updated to 1.3.0 based on work at http://github.com/major/MySQLTuner-perl
+* Add future parse support, fixed issues with undef to empty string
+* Pass the backup credentials to 'SHOW DATABASES'
+* Ability to specify the Includedir for `mysql::server`
+* `mysql::db` now has an import\_timeout feature that defaults to 300
+* The `mysql` class has been removed
+* `mysql::server` now takes an `override_options` hash that will affect the installation
+* Ability to install both dev and client dev
+
+####BugFix
+* `mysql::server::backup` now passes `ensure` param to the nested `mysql_grant`
+* `mysql::server::service` now properly requires the presence of the `log_error` file
+* `mysql::config` now occurs before `mysql::server::install_db` correctly
+
+##2014-07-15 - Supported Release 2.3.1
+###Summary
+
+This release merely updates metadata.json so the module can be uninstalled and
+upgraded via the puppet module command.
+
+##2014-05-14 - Supported Release 2.3.0
+
+This release primarily adds support for RHEL7 and Ubuntu 14.04 but it
+also adds a couple of new parameters to allow for further customization,
+as well as ensuring backups can backup stored procedures properly.
+
+####Features
+Added `execpath` to allow a custom executable path for non-standard mysql installations.
+Added `dbname` to mysql::db and use ensure_resource to create the resource.
+Added support for RHEL7 and Fedora Rawhide.
+Added support for Ubuntu 14.04.
+Create a warning for if you disable SSL.
+Ensure the error logfile is owned by MySQL.
+Disable ssl on FreeBSD.
+Add PROCESS privilege for backups.
+
+####Bugfixes
+
+####Known Bugs
+* No known bugs
+
+##2014-03-04 - Supported Release 2.2.3
+###Summary
+
+This is a supported release.  This release removes a testing symlink that can
+cause trouble on systems where /var is on a seperate filesystem from the
+modulepath.
+
+####Features
+####Bugfixes
+####Known Bugs
+* No known bugs
+
+##2014-03-04 - Supported Release 2.2.2
+###Summary
+This is a supported release. Mostly comprised of enhanced testing, plus a
+bugfix for Suse.
+
+####Bugfixes
+- PHP bindings on Suse
+- Test fixes
+
+####Known Bugs
+* No known bugs
+
+##2014-02-19 - Version 2.2.1
+
+###Summary
+
+Minor release that repairs mysql_database{} so that it sees the correct
+collation settings (it was only checking the global mysql ones, not the
+actual database and constantly setting it over and over since January 22nd).
+
+Also fixes a bunch of tests on various platforms.
+
+
+##2014-02-13 - Version 2.2.0
+
+###Summary
+
+####Features
+- Add `backupdirmode`, `backupdirowner`, `backupdirgroup` to
+  mysql::server::backup to allow customizing the mysqlbackupdir.
+- Support multiple options of the same name, allowing you to
+  do 'replicate-do-db' => ['base1', 'base2', 'base3'] in order to get three
+  lines of replicate-do-db = base1, replicate-do-db = base2 etc.
+
+####Bugfixes
+- Fix `restart` so it actually stops mysql restarting if set to false.
+- DRY out the defaults_file functionality in the providers.
+- mysql_grant fixed to work with root@localhost/@.
+- mysql_grant fixed for WITH MAX_QUERIES_PER_HOUR
+- mysql_grant fixed so revoking all privileges accounts for GRANT OPTION
+- mysql_grant fixed to remove duplicate privileges.
+- mysql_grant fixed to handle PROCEDURES when removing privileges.
+- mysql_database won't try to create existing databases, breaking replication.
+- bind_address renamed bind-address in 'mysqld' options.
+- key_buffer renamed to key_buffer_size.
+- log_error renamed to log-error.
+- pid_file renamed to pid-file.
+- Ensure mysql::server:root_password runs before mysql::server::backup
+- Fix options_override -> override_options in the README.
+- Extensively rewrite the README to be accurate and awesome.
+- Move to requiring stdlib 3.2.0, shipped in PE3.0
+- Add many new tests.
+
+
+##2013-11-13 - Version 2.1.0
+
+###Summary
+
+The most important changes in 2.1.0 are improvements to the my.cnf creation,
+as well as providers.  Setting options to = true strips them to be just the
+key name itself, which is required for some options.
+
+The provider updates fix a number of bugs, from lowercase privileges to
+deprecation warnings.
+
+Last, the new hiera integration functionality should make it easier to
+externalize all your grants, users, and, databases.  Another great set of
+community submissions helped to make this release.
+
+####Features
+- Some options can not take a argument. Gets rid of the '= true' when an
+option is set to true.
+- Easier hiera integration:  Add hash parameters to mysql::server to allow
+specifying grants, users, and databases.
+
+####Bugfixes
+- Fix an issue with lowercase privileges in mysql_grant{} causing them to be reapplied needlessly.
+- Changed defaults-file to defaults-extra-file in providers.
+- Ensure /root/.my.cnf is 0600 and root owned.
+- database_user deprecation warning was incorrect.
+- Add anchor pattern for client.pp
+- Documentation improvements.
+- Various test fixes.
+
+
+##2013-10-21 - Version 2.0.1
+
+###Summary
+
+This is a bugfix release to handle an issue where unsorted mysql_grant{}
+privileges could cause Puppet to incorrectly reapply the permissions on
+each run.
+
+####Bugfixes
+- Mysql_grant now sorts privileges in the type and provider for comparison.
+- Comment and test tweak for PE3.1.
+
+
+##2013-10-14 - Version 2.0.0
+
+###Summary
+
+(Previously detailed in the changelog for 2.0.0-rc1)
+
+This module has been completely refactored and works significantly different.
+The changes are broad and touch almost every piece of the module.
+
+See the README.md for full details of all changes and syntax.
+Please remain on 1.0.0 if you don't have time to fully test this in dev.
+
+* mysql::server, mysql::client, and mysql::bindings are the primary interface
+classes.
+* mysql::server takes an `override_options` parameter to set my.cnf options,
+with the hash format: { 'section' => { 'thing' => 'value' }}
+* mysql attempts backwards compatibility by forwarding all parameters to
+mysql::server.
+
+
+##2013-10-09 - Version 2.0.0-rc5
+
+###Summary
+
+Hopefully the final rc!  Further fixes to mysql_grant (stripping out the
+cleverness so we match a much wider range of input.)
+
+####Bugfixes
+- Make mysql_grant accept '.*'@'.*' in terms of input for user@host.
+
+
+##2013-10-09 - Version 2.0.0-rc4
+
+###Summary
+
+Bugfixes to mysql_grant and mysql_user form the bulk of this rc, as well as
+ensuring that values in the override_options hash that contain a value of ''
+are created as just "key" in the conf rather than "key =" or "key = false".
+
+####Bugfixes
+- Improve mysql_grant to work with IPv6 addresses (both long and short).
+- Ensure @host users work as well as user@host users.
+- Updated my.cnf template to support items with no values.
+
+
+##2013-10-07 - Version 2.0.0-rc3
+
+###Summary
+Fix mysql::server::monitor's use of mysql_user{}.
+
+####Bugfixes
+- Fix myql::server::monitor's use of mysql_user{} to grant the proper
+permissions.  Add specs as well.  (Thanks to treydock!)
+
+
+##2013-10-03 - Version 2.0.0-rc2
+
+###Summary
+Bugfixes
+
+####Bugfixes
+- Fix a duplicate parameter in mysql::server
+
+
+##2013-10-03 - Version 2.0.0-rc1
+
+###Summary
+
+This module has been completely refactored and works significantly different.
+The changes are broad and touch almost every piece of the module.
+
+See the README.md for full details of all changes and syntax.
+Please remain on 1.0.0 if you don't have time to fully test this in dev.
+
+* mysql::server, mysql::client, and mysql::bindings are the primary interface
+classes.
+* mysql::server takes an `override_options` parameter to set my.cnf options,
+with the hash format: { 'section' => { 'thing' => 'value' }}
+* mysql attempts backwards compatibility by forwarding all parameters to
+mysql::server.
+
+---
+##2013-09-23 - Version 1.0.0
+
+###Summary
+
+This release introduces a number of new type/providers, to eventually
+replace the database_ ones.  The module has been converted to call the
+new providers rather than the previous ones as they have a number of
+fixes, additional options, and work with puppet resource.
+
+This 1.0.0 release precedes a large refactoring that will be released
+almost immediately after as 2.0.0.
+
+####Features
+- Added mysql_grant, mysql_database, and mysql_user.
+- Add `mysql::bindings` class and refactor all other bindings to be contained underneath mysql::bindings:: namespace.
+- Added support to back up specified databases only with 'mysqlbackup' parameter.
+- Add option to mysql::backup to set the backup script to perform a mysqldump on each database to its own file
+
+####Bugfixes
+- Update my.cnf.pass.erb to allow custom socket support
+- Add environment variable for .my.cnf in mysql::db.
+- Add HOME environment variable for .my.cnf to mysqladmin command when
+(re)setting root password
+
+---
+##2013-07-15 - Version 0.9.0
+####Features
+- Add `mysql::backup::backuprotate` parameter
+- Add `mysql::backup::delete_before_dump` parameter
+- Add `max_user_connections` attribute to `database_user` type
+
+####Bugfixes
+- Add client package dependency for `mysql::db`
+- Remove duplicate `expire_logs_days` and `max_binlog_size` settings
+- Make root's `.my.cnf` file path dynamic
+- Update pidfile path for Suse variants
+- Fixes for lint
+
+##2013-07-05 - Version 0.8.1
+####Bugfixes
+ - Fix a typo in the Fedora 19 support.
+
+##2013-07-01 - Version 0.8.0
+####Features
+ - mysql::perl class to install perl-DBD-mysql.
+ - minor improvements to the providers to improve reliability
+ - Install the MariaDB packages on Fedora 19 instead of MySQL.
+ - Add new `mysql` class parameters:
+   -  `max_connections`: The maximum number of allowed connections.
+   -  `manage_config_file`: Opt out of puppetized control of my.cnf.
+   -  `ft_min_word_len`: Fine tune the full text search.
+   -  `ft_max_word_len`: Fine tune the full text search.
+ - Add new `mysql` class performance tuning parameters:
+   -  `key_buffer`
+   -  `thread_stack`
+   -  `thread_cache_size`
+   -  `myisam-recover`
+   -  `query_cache_limit`
+   -  `query_cache_size`
+   -  `max_connections`
+   -  `tmp_table_size`
+   -  `table_open_cache`
+   -  `long_query_time`
+ - Add new `mysql` class replication parameters:
+   -  `server_id`
+   -  `sql_log_bin`
+   -  `log_bin`
+   -  `max_binlog_size`
+   -  `binlog_do_db`
+   -  `expire_logs_days`
+   -  `log_bin_trust_function_creators`
+   -  `replicate_ignore_table`
+   -  `replicate_wild_do_table`
+   -  `replicate_wild_ignore_table`
+   -  `expire_logs_days`
+   -  `max_binlog_size`
+
+####Bugfixes
+ - No longer restart MySQL when /root/.my.cnf changes.
+ - Ensure mysql::config runs before any mysql::db defines.
+
+##2013-06-26 - Version 0.7.1
+####Bugfixes
+- Single-quote password for special characters
+- Update travis testing for puppet 3.2.x and missing Bundler gems
+
+##2013-06-25 - Version 0.7.0
+This is a maintenance release for community bugfixes and exposing
+configuration variables.
+
+* Add new `mysql` class parameters:
+  -  `basedir`: The base directory mysql uses
+  -  `bind_address`: The IP mysql binds to
+  -  `client_package_name`: The name of the mysql client package
+  -  `config_file`: The location of the server config file
+  -  `config_template`: The template to use to generate my.cnf
+  -  `datadir`: The directory MySQL's datafiles are stored
+  -  `default_engine`: The default engine to use for tables
+  -  `etc_root_password`: Whether or not to add the mysql root password to
+ /etc/my.cnf
+  -  `java_package_name`: The name of the java package containing the java
+ connector
+  -  `log_error`: Where to log errors
+  -  `manage_service`: Boolean dictating if mysql::server should manage the
+ service
+  -  `max_allowed_packet`: Maximum network packet size mysqld will accept
+  -  `old_root_password`: Previous root user password
+  -  `php_package_name`: The name of the phpmysql package to install
+  -  `pidfile`: The location mysql will expect the pidfile to be
+  -  `port`: The port mysql listens on
+  -  `purge_conf_dir`: Value fed to recurse and purge parameters of the
+ /etc/mysql/conf.d resource
+  -  `python_package_name`: The name of the python mysql package to install
+  -  `restart`: Whether to restart mysqld
+  -  `root_group`: Use specified group for root-owned files
+  -  `root_password`: The root MySQL password to use
+  -  `ruby_package_name`: The name of the ruby mysql package to install
+  -  `ruby_package_provider`: The installation suite to use when installing the
+ ruby package
+  -  `server_package_name`: The name of the server package to install
+  -  `service_name`: The name of the service to start
+  -  `service_provider`: The name of the service provider
+  -  `socket`: The location of the MySQL server socket file
+  -  `ssl_ca`: The location of the SSL CA Cert
+  -  `ssl_cert`: The location of the SSL Certificate to use
+  -  `ssl_key`: The SSL key to use
+  -  `ssl`: Whether or not to enable ssl
+  -  `tmpdir`: The directory MySQL's tmpfiles are stored
+* Deprecate `mysql::package_name` parameter in favor of
+`mysql::client_package_name`
+* Fix local variable template deprecation
+* Fix dependency ordering in `mysql::db`
+* Fix ANSI quoting in queries
+* Fix travis support (but still messy)
+* Fix typos
+
+##2013-01-11 - Version 0.6.1
+* Fix providers when /root/.my.cnf is absent
+
+##2013-01-09 - Version 0.6.0
+* Add `mysql::server::config` define for specific config directives
+* Add `mysql::php` class for php support
+* Add `backupcompress` parameter to `mysql::backup`
+* Add `restart` parameter to `mysql::config`
+* Add `purge_conf_dir` parameter to `mysql::config`
+* Add `manage_service` parameter to `mysql::server`
+* Add syslog logging support via the `log_error` parameter
+* Add initial SuSE support
+* Fix remove non-localhost root user when fqdn != hostname
+* Fix dependency in `mysql::server::monitor`
+* Fix .my.cnf path for root user and root password
+* Fix ipv6 support for users
+* Fix / update various spec tests
+* Fix typos
+* Fix lint warnings
+
+##2012-08-23 - Version 0.5.0
+* Add puppetlabs/stdlib as requirement
+* Add validation for mysql privs in provider
+* Add `pidfile` parameter to mysql::config
+* Add `ensure` parameter to mysql::db
+* Add Amazon linux support
+* Change `bind_address` parameter to be optional in my.cnf template
+* Fix quoting root passwords
+
+##2012-07-24 - Version 0.4.0
+* Fix various bugs regarding database names
+* FreeBSD support
+* Allow specifying the storage engine
+* Add a backup class
+* Add a security class to purge default accounts
+
+##2012-05-03 - Version 0.3.0
+* 14218 Query the database for available privileges
+* Add mysql::java class for java connector installation
+* Use correct error log location on different distros
+* Fix set_mysql_rootpw to properly depend on my.cnf
+
+##2012-04-11 - Version 0.2.0
+
+##2012-03-19 - William Van Hevelingen <blkperl@cat.pdx.edu>
+* (#13203) Add ssl support (f7e0ea5)
+
+##2012-03-18 - Nan Liu <nan@puppetlabs.com>
+* Travis ci before script needs success exit code. (0ea463b)
+
+##2012-03-18 - Nan Liu <nan@puppetlabs.com>
+* Fix Puppet 2.6 compilation issues. (9ebbbc4)
+
+##2012-03-16 - Nan Liu <nan@puppetlabs.com>
+* Add travis.ci for testing multiple puppet versions. (33c72ef)
+
+##2012-03-15 - William Van Hevelingen <blkperl@cat.pdx.edu>
+* (#13163) Datadir should be configurable (f353fc6)
+
+##2012-03-16 - Nan Liu <nan@puppetlabs.com>
+* Document create_resources dependency. (558a59c)
+
+##2012-03-16 - Nan Liu <nan@puppetlabs.com>
+* Fix spec test issues related to error message. (eff79b5)
+
+##2012-03-16 - Nan Liu <nan@puppetlabs.com>
+* Fix mysql service on Ubuntu. (72da2c5)
+
+##2012-03-16 - Dan Bode <dan@puppetlabs.com>
+* Add more spec test coverage (55e399d)
+
+##2012-03-16 - Nan Liu <nan@puppetlabs.com>
+* (#11963) Fix spec test due to path changes. (1700349)
+
+##2012-03-07 - François Charlier <fcharlier@ploup.net>
+* Add a test to check path for 'mysqld-restart' (b14c7d1)
+
+##2012-03-07 - François Charlier <fcharlier@ploup.net>
+* Fix path for 'mysqld-restart' (1a9ae6b)
+
+##2012-03-15 - Dan Bode <dan@puppetlabs.com>
+* Add rspec-puppet tests for mysql::config (907331a)
+
+##2012-03-15 - Dan Bode <dan@puppetlabs.com>
+* Moved class dependency between sever and config to server (da62ad6)
+
+##2012-03-14 - Dan Bode <dan@puppetlabs.com>
+* Notify mysql restart from set_mysql_rootpw exec (0832a2c)
+
+##2012-03-15 - Nan Liu <nan@puppetlabs.com>
+* Add documentation related to osfamily fact. (8265d28)
+
+##2012-03-14 - Dan Bode <dan@puppetlabs.com>
+* Mention osfamily value in failure message (e472d3b)
+
+##2012-03-14 - Dan Bode <dan@puppetlabs.com>
+* Fix bug when querying for all database users (015490c)
+
+##2012-02-09 - Nan Liu <nan@puppetlabs.com>
+* Major refactor of mysql module. (b1f90fd)
+
+##2012-01-11 - Justin Ellison <justin.ellison@buckle.com>
+* Ruby and Python's MySQL libraries are named differently on different distros. (1e926b4)
+
+##2012-01-11 - Justin Ellison <justin.ellison@buckle.com>
+* Per @ghoneycutt, we should fail explicitly and explain why. (09af083)
+
+##2012-01-11 - Justin Ellison <justin.ellison@buckle.com>
+* Removing duplicate declaration (7513d03)
+
+##2012-01-10 - Justin Ellison <justin.ellison@buckle.com>
+* Use socket value from params class instead of hardcoding. (663e97c)
+
+##2012-01-10 - Justin Ellison <justin.ellison@buckle.com>
+* Instead of hardcoding the config file target, pull it from mysql::params (031a47d)
+
+##2012-01-10 - Justin Ellison <justin.ellison@buckle.com>
+* Moved $socket to within the case to toggle between distros.  Added a $config_file variable to allow per-distro config file destinations. (360eacd)
+
+##2012-01-10 - Justin Ellison <justin.ellison@buckle.com>
+* Pretty sure this is a bug, 99% of Linux distros out there won't ever hit the default. (3462e6b)
+
+##2012-02-09 - William Van Hevelingen <blkperl@cat.pdx.edu>
+* Changed the README to use markdown (3b7dfeb)
+
+##2012-02-04 - Daniel Black <grooverdan@users.sourceforge.net>
+* (#12412) mysqltuner.pl update (b809e6f)
+
+##2011-11-17 - Matthias Pigulla <mp@webfactory.de>
+* (#11363) Add two missing privileges to grant: event_priv, trigger_priv (d15c9d1)
+
+##2011-12-20 - Jeff McCune <jeff@puppetlabs.com>
+* (minor) Fixup typos in Modulefile metadata (a0ed6a1)
+
+##2011-12-19 - Carl Caum <carl@carlcaum.com>
+* Only notify Exec to import sql if sql is given (0783c74)
+
+##2011-12-19 - Carl Caum <carl@carlcaum.com>
+* (#11508) Only load sql_scripts on DB creation (e3b9fd9)
+
+##2011-12-13 - Justin Ellison <justin.ellison@buckle.com>
+* Require not needed due to implicit dependencies (3058feb)
+
+##2011-12-13 - Justin Ellison <justin.ellison@buckle.com>
+* Bug #11375: puppetlabs-mysql fails on CentOS/RHEL (a557b8d)
+
+##2011-06-03 - Dan Bode <dan@puppetlabs.com> - 0.0.1
+* initial commit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/CONTRIBUTING.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,220 @@
+Checklist (and a short version for the impatient)
+=================================================
+
+  * Commits:
+
+    - Make commits of logical units.
+
+    - Check for unnecessary whitespace with "git diff --check" before
+      committing.
+
+    - Commit using Unix line endings (check the settings around "crlf" in
+      git-config(1)).
+
+    - Do not check in commented out code or unneeded files.
+
+    - The first line of the commit message should be a short
+      description (50 characters is the soft limit, excluding ticket
+      number(s)), and should skip the full stop.
+
+    - Associate the issue in the message. The first line should include
+      the issue number in the form "(#XXXX) Rest of message".
+
+    - The body should provide a meaningful commit message, which:
+
+      - uses the imperative, present tense: "change", not "changed" or
+        "changes".
+
+      - includes motivation for the change, and contrasts its
+        implementation with the previous behavior.
+
+    - Make sure that you have tests for the bug you are fixing, or
+      feature you are adding.
+
+    - Make sure the test suites passes after your commit:
+      `bundle exec rspec spec/acceptance` More information on [testing](#Testing) below
+
+    - When introducing a new feature, make sure it is properly
+      documented in the README.md
+
+  * Submission:
+
+    * Pre-requisites:
+
+      - Make sure you have a [GitHub account](https://github.com/join)
+
+      - [Create a ticket](https://tickets.puppetlabs.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppetlabs.com/browse/) you are patching for.
+
+    * Preferred method:
+
+      - Fork the repository on GitHub.
+
+      - Push your changes to a topic branch in your fork of the
+        repository. (the format ticket/1234-short_description_of_change is
+        usually preferred for this project).
+
+      - Submit a pull request to the repository in the puppetlabs
+        organization.
+
+The long version
+================
+
+  1.  Make separate commits for logically separate changes.
+
+      Please break your commits down into logically consistent units
+      which include new or changed tests relevant to the rest of the
+      change.  The goal of doing this is to make the diff easier to
+      read for whoever is reviewing your code.  In general, the easier
+      your diff is to read, the more likely someone will be happy to
+      review it and get it into the code base.
+
+      If you are going to refactor a piece of code, please do so as a
+      separate commit from your feature or bug fix changes.
+
+      We also really appreciate changes that include tests to make
+      sure the bug is not re-introduced, and that the feature is not
+      accidentally broken.
+
+      Describe the technical detail of the change(s).  If your
+      description starts to get too long, that is a good sign that you
+      probably need to split up your commit into more finely grained
+      pieces.
+
+      Commits which plainly describe the things which help
+      reviewers check the patch and future developers understand the
+      code are much more likely to be merged in with a minimum of
+      bike-shedding or requested changes.  Ideally, the commit message
+      would include information, and be in a form suitable for
+      inclusion in the release notes for the version of Puppet that
+      includes them.
+
+      Please also check that you are not introducing any trailing
+      whitespace or other "whitespace errors".  You can do this by
+      running "git diff --check" on your changes before you commit.
+
+  2.  Sending your patches
+
+      To submit your changes via a GitHub pull request, we _highly_
+      recommend that you have them on a topic branch, instead of
+      directly on "master".
+      It makes things much easier to keep track of, especially if
+      you decide to work on another thing before your first change
+      is merged in.
+
+      GitHub has some pretty good
+      [general documentation](http://help.github.com/) on using
+      their site.  They also have documentation on
+      [creating pull requests](http://help.github.com/send-pull-requests/).
+
+      In general, after pushing your topic branch up to your
+      repository on GitHub, you can switch to the branch in the
+      GitHub UI and click "Pull Request" towards the top of the page
+      in order to open a pull request.
+
+
+  3.  Update the related GitHub issue.
+
+      If there is a GitHub issue associated with the change you
+      submitted, then you should update the ticket to include the
+      location of your branch, along with any other commentary you
+      may wish to make.
+
+Testing
+=======
+
+Getting Started
+---------------
+
+Our puppet modules provide [`Gemfile`](./Gemfile)s which can tell a ruby
+package manager such as [bundler](http://bundler.io/) what Ruby packages,
+or Gems, are required to build, develop, and test this software.
+
+Please make sure you have [bundler installed](http://bundler.io/#getting-started)
+on your system, then use it to install all dependencies needed for this project,
+by running
+
+```shell
+% bundle install
+Fetching gem metadata from https://rubygems.org/........
+Fetching gem metadata from https://rubygems.org/..
+Using rake (10.1.0)
+Using builder (3.2.2)
+-- 8><-- many more --><8 --
+Using rspec-system-puppet (2.2.0)
+Using serverspec (0.6.3)
+Using rspec-system-serverspec (1.0.0)
+Using bundler (1.3.5)
+Your bundle is complete!
+Use `bundle show [gemname]` to see where a bundled gem is installed.
+```
+
+NOTE some systems may require you to run this command with sudo.
+
+If you already have those gems installed, make sure they are up-to-date:
+
+```shell
+% bundle update
+```
+
+With all dependencies in place and up-to-date we can now run the tests:
+
+```shell
+% bundle exec rake spec
+```
+
+This will execute all the [rspec tests](http://rspec-puppet.com/) tests
+under [spec/defines](./spec/defines), [spec/classes](./spec/classes),
+and so on. rspec tests may have the same kind of dependencies as the
+module they are testing. While the module defines in its [Modulefile](./Modulefile),
+rspec tests define them in [.fixtures.yml](./fixtures.yml).
+
+Some puppet modules also come with [beaker](https://github.com/puppetlabs/beaker)
+tests. These tests spin up a virtual machine under
+[VirtualBox](https://www.virtualbox.org/)) with, controlling it with
+[Vagrant](http://www.vagrantup.com/) to actually simulate scripted test
+scenarios. In order to run these, you will need both of those tools
+installed on your system.
+
+You can run them by issuing the following command
+
+```shell
+% bundle exec rake spec_clean
+% bundle exec rspec spec/acceptance
+```
+
+This will now download a pre-fabricated image configured in the [default node-set](./spec/acceptance/nodesets/default.yml),
+install puppet, copy this module and install its dependencies per [spec/spec_helper_acceptance.rb](./spec/spec_helper_acceptance.rb)
+and then run all the tests under [spec/acceptance](./spec/acceptance).
+
+Writing Tests
+-------------
+
+XXX getting started writing tests.
+
+If you have commit access to the repository
+===========================================
+
+Even if you have commit access to the repository, you will still need to
+go through the process above, and have someone else review and merge
+in your changes.  The rule is that all changes must be reviewed by a
+developer on the project (that did not write the code) to ensure that
+all changes go through a code review process.
+
+Having someone other than the author of the topic branch recorded as
+performing the merge is the record that they performed the code
+review.
+
+
+Additional Resources
+====================
+
+* [Getting additional help](http://puppetlabs.com/community/get-help)
+
+* [Writing tests](http://projects.puppetlabs.com/projects/puppet/wiki/Development_Writing_Tests)
+
+* [Patchwork](https://patchwork.puppetlabs.com)
+
+* [General GitHub documentation](http://help.github.com/)
+
+* [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/Gemfile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,49 @@
+source ENV['GEM_SOURCE'] || "https://rubygems.org"
+
+def location_for(place, fake_version = nil)
+  if place =~ /^(git[:@][^#]*)#(.*)/
+    [fake_version, { :git => $1, :branch => $2, :require => false }].compact
+  elsif place =~ /^file:\/\/(.*)/
+    ['>= 0', { :path => File.expand_path($1), :require => false }]
+  else
+    [place, { :require => false }]
+  end
+end
+
+group :development, :unit_tests do
+  gem 'rspec-core', '3.1.7',     :require => false
+  gem 'puppetlabs_spec_helper',  :require => false
+  gem 'simplecov',               :require => false
+  gem 'puppet_facts',            :require => false
+  gem 'json',                    :require => false
+  gem 'metadata-json-lint',      :require => false
+end
+
+group :system_tests do
+  if beaker_version = ENV['BEAKER_VERSION']
+    gem 'beaker', *location_for(beaker_version)
+  end
+  if beaker_rspec_version = ENV['BEAKER_RSPEC_VERSION']
+    gem 'beaker-rspec', *location_for(beaker_rspec_version)
+  else
+    gem 'beaker-rspec',  :require => false
+  end
+  gem 'serverspec',                    :require => false
+  gem 'beaker-puppet_install_helper',  :require => false
+end
+
+
+
+if facterversion = ENV['FACTER_GEM_VERSION']
+  gem 'facter', facterversion, :require => false
+else
+  gem 'facter', :require => false
+end
+
+if puppetversion = ENV['PUPPET_GEM_VERSION']
+  gem 'puppet', puppetversion, :require => false
+else
+  gem 'puppet', :require => false
+end
+
+# vim:ft=ruby
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/LICENSE	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!) The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 2013 Puppet Labs
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/README.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,847 @@
+# mysql
+
+#### Table of Contents
+
+1. [Module Description - What the module does and why it is useful](#module-description)
+2. [Backwards compatibility information](#backwards-compatibility)
+3. [Setup - The basics of getting started with mysql](#setup)
+    * [Beginning with mysql](#beginning-with-mysql)
+4. [Usage - Configuration options and additional functionality](#usage)
+    * [Customizing Server Options](#customizing-server-options)
+    * [Creating a Database](#creating-a-database)
+    * [Custom Configuration](#custom-configuration)
+5. [Reference - An under-the-hood peek at what the module is doing and how](#reference)
+6. [Limitations - OS compatibility, etc.](#limitations)
+7. [Development - Guide for contributing to the module](#development)
+
+## Module Description
+
+The MySQL module installs, configures, and manages the MySQL service.
+
+The MySQL module manages both the installation and configuration of MySQL, as well as extending Puppet to allow management of MySQL resources, such as databases, users, and grants.
+
+## Setup
+
+### Beginning with MySQL
+
+If you want a server installed with the default options you can run
+`include '::mysql::server'`. 
+
+If you need to customize options, such as the root
+password or `/etc/my.cnf` settings, then you must also pass in an override hash:
+
+~~~
+class { '::mysql::server':
+  root_password           => 'strongpassword',
+  remove_default_accounts => true,
+  override_options        => $override_options
+}
+~~~
+
+See [**Customizing Server Options**](#customizing-server-options) below for examples of the hash structure for $override_options`.
+
+## Usage
+
+All interaction for the server is done via `mysql::server`. To install the client, use `mysql::client`. To install bindings, use `mysql::bindings`.
+
+### Customizing Server Options
+
+The hash structure for overrides in `mysql::server` can be structured like a hash in the my.cnf file, so:
+
+~~~
+$override_options = {
+  'section' => {
+    'item' => 'thing',
+  }
+}
+~~~
+
+For items that you would traditionally represent as
+
+~~~
+[section]
+thing = X
+~~~
+
+you can make an entry like `thing => true`, `thing => value`, or `thing => "` in the hash. Alternatively, you can pass an array, as `thing => ['value', 'value2']`, or list each `thing => value` separately on separate lines. 
+
+MySQL doesn't care if 'thing' is alone or set to a value; it happily accepts both. To keep an option out of the my.cnf file --- e.g., when using `override_options` to revert to a default value --- you can pass `thing => undef`.
+
+If an option needs multiple instances, you can pass an array. For example,
+
+~~~
+$override_options = {
+  'mysqld' => {
+    'replicate-do-db' => ['base1', 'base2'],
+  }
+}
+~~~
+
+produces
+
+~~~
+[mysqld]
+replicate-do-db = base1
+replicate-do-db = base2
+~~~
+
+### Creating a database
+
+To use `mysql::db` to create a database with a user and assign some privileges:
+
+~~~
+mysql::db { 'mydb':
+  user     => 'myuser',
+  password => 'mypass',
+  host     => 'localhost',
+  grant    => ['SELECT', 'UPDATE'],
+}
+~~~
+
+Or to use a different resource name with exported resources:
+
+~~~
+ @@mysql::db { "mydb_${fqdn}":
+  user     => 'myuser',
+  password => 'mypass',
+  dbname   => 'mydb',
+  host     => ${fqdn},
+  grant    => ['SELECT', 'UPDATE'],
+  tag      => $domain,
+}
+~~~
+
+Then you can collect it on the remote DB server:
+
+~~~
+Mysql::Db <<| tag == $domain |>>
+~~~
+
+If you set the sql param to a file when creating a database, the file gets imported into the new database.
+
+For large sql files, you should raise the $import_timeout parameter, set by default to 300 seconds.
+
+~~~
+mysql::db { 'mydb':
+  user     => 'myuser',
+  password => 'mypass',
+  host     => 'localhost',
+  grant    => ['SELECT', 'UPDATE'],
+  sql      => '/path/to/sqlfile',
+  import_timeout => 900,
+}
+~~~
+
+### Custom Configuration
+
+To add custom MySQL configuration, drop additional files into
+`includedir`. Dropping files into `includedir` allows you to override settings or add additional ones, which is helpful if you choose not to use `override_options` in `mysql::server`. The `includedir` location is by default set to /etc/mysql/conf.d.
+
+### Working with an existing server
+
+You can use the MySQL module to instantiate databases and
+users on an existing MySQL server. For this to work, you need an
+appropriate `.my.cnf` in `root`'s home directory containing the remote
+server address and credentials. For example:
+
+    [client]
+    user=root
+    host=localhost
+    password=secret
+
+When working with a remote server, do *not* use the
+`mysql::server` class in your Puppet manifests.
+
+## Reference
+
+### Classes
+
+#### Public classes
+
+* [`mysql::server`](#mysqlserver): Installs and configures MySQL.
+* [`mysql::server::monitor`](#mysqlservermonitor): Sets up a monitoring user.
+* [`mysql::server::mysqltuner`](#mysqlservermysqltuner): Installs MySQL tuner script.
+* [`mysql::server::backup`](#mysqlserverbackup): Sets up MySQL backups via cron.
+* [`mysql::bindings`](#mysqlbindings): Installs various MySQL language bindings.
+* [`mysql::client`](#mysqlclient): Installs MySQL client (for non-servers).
+
+#### Private classes
+
+* `mysql::server::install`: Installs packages.
+* `mysql::server::config`: Configures MYSQL.
+* `mysql::server::service`: Manages service.
+* `mysql::server::account_security`: Deletes default MySQL accounts.
+* `mysql::server::root_password`: Sets MySQL root password.
+* `mysql::server::providers`: Creates users, grants, and databases.
+* `mysql::bindings::client_dev`: Installs MySQL client development package.
+* `mysql::bindings::daemon_dev`: Installs MySQL daemon development package.
+* `mysql::bindings::java`: Installs Java bindings.
+* `mysql::bindings::perl`: Installs Perl bindings.
+* `mysql::bindings::php`: Installs PHP bindings.
+* `mysql::bindings::python`: Installs Python bindings.
+* `mysql::bindings::ruby`: Installs Ruby bindings.
+* `mysql::client::install`:  Installs MySQL client.
+* `mysql::backup::mysqldump`: Implements mysqldump backups.
+* `mysql::backup::mysqlbackup`: Implements backups with Oracle MySQL Enterprise Backup.
+* `mysql::backup::xtrabackup`: Implements backups with XtraBackup from Percona.
+
+### Parameters
+
+#### mysql::server
+
+##### `create_root_user`
+
+Specify whether root user should be created. Valid values are 'true', 'false'. Defaults to 'true'.
+
+This is useful for a cluster setup with Galera. The root user has to
+be created only once. `create_root_user` can be set to 'true' on one node while
+it is set to 'false' on the remaining nodes.
+
+#####  `create_root_my_cnf`
+
+If set to 'true', creates `/root/.my.cnf`. Valid values are 'true', 'false'. Defaults to 'true'.
+
+`create_root_my_cnf` allows creation of `/root/.my.cnf` independently of `create_root_user`. This can be used for a cluster setup with Galera where you want `/root/.my.cnf` to exist on all nodes.
+
+#####  `root_password`
+
+The MySQL root password. Puppet attempts to set the root password and update `/root/.my.cnf` with it.
+
+This is required if `create_root_user` or `create_root_my_cnf` are 'true'. If `root_password` is 'UNSET', then `create_root_user` and `create_root_my_cnf` are assumed to be false --- that is, the MySQL root user and `/root/.my.cnf` are not created.
+
+Password changes are supported; however, the old password must be set in `/root/.my.cnf`. Effectively, Puppet uses the old password, configured in `/root/my.cnf`, to set the new password in MySQL, and then updates `/root/.my.cnf` with the new password. 
+
+##### `old_root_password`
+
+This parameter no longer does anything. It exists only for backwards compatibility. See the `root_password` parameter above for details on changing the root password.
+
+##### `override_options`
+
+The hash of override options to pass into MySQL. Structured like a hash in the my.cnf file:
+
+~~~
+$override_options = {
+  'section' => {
+    'item'             => 'thing',
+  }
+}
+~~~
+
+See [**Customizing Server Options**](#customizing-server-options) above for usage details.
+
+##### `config_file`
+
+The location, as a path, of the MySQL configuration file.
+
+##### `manage_config_file`
+
+Whether the MySQL configuration file should be managed. Valid values are 'true', 'false'. Defaults to 'true'.
+
+##### `includedir`
+The location, as a path, of !includedir for custom configuration overrides.
+
+##### `install_options`
+Pass [install_options](https://docs.puppetlabs.com/references/latest/type.html#package-attribute-install_options) array to managed package resources. You must pass the appropriate options for the specified package manager.
+
+##### `purge_conf_dir`
+
+Whether the `includedir` directory should be purged. Valid values are 'true', 'false'. Defaults to 'false'.
+
+##### `restart`
+
+Whether the service should be restarted when things change. Valid values are 'true', 'false'. Defaults to 'false'.
+
+##### `root_group`
+
+The name of the group used for root. Can be a group name or a group ID. See more about the [`group` file attribute](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-group).
+
+##### `mysql_group`
+
+The name of the group of the MySQL daemon user. Can be a group name or a group ID. See more about the [`group` file attribute](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-group).
+
+##### `package_ensure`
+
+Whether the package exists or should be a specific version. Valid values are 'present', 'absent', or 'x.y.z'. Defaults to 'present'.
+
+##### `package_manage`
+
+Whether to manage the MySQL server package. Defaults to true.
+
+##### `package_name`
+
+The name of the MySQL server package to install.
+
+##### `remove_default_accounts`
+
+Specify whether to automatically include `mysql::server::account_security`. Valid values are 'true', 'false'. Defaults to 'false'.
+
+##### `service_enabled`
+
+Specify whether the service should be enabled. Valid values are 'true', 'false'. Defaults to 'true'.
+
+##### `service_manage`
+
+Specify whether the service should be managed. Valid values are 'true', 'false'. Defaults to 'true'.
+
+##### `service_name`
+
+The name of the MySQL server service. Defaults are OS dependent, defined in params.pp.
+
+##### `service_provider`
+
+The provider to use to manage the service. For Ubuntu, defaults to 'upstart'; otherwise, default is undefined.
+
+##### `users`
+
+Optional hash of users to create, which are passed to [mysql_user](#mysql_user). 
+
+~~~
+users => {
+  'someuser@localhost' => {
+    ensure                   => 'present',
+    max_connections_per_hour => '0',
+    max_queries_per_hour     => '0',
+    max_updates_per_hour     => '0',
+    max_user_connections     => '0',
+    password_hash            => '*F3A2A51A9B0F2BE2468926B4132313728C250DBF',
+  },
+}
+~~~
+
+##### `grants`
+
+Optional hash of grants, which are passed to [mysql_grant](#mysql_grant). 
+
+~~~
+grants => {
+  'someuser@localhost/somedb.*' => {
+    ensure     => 'present',
+    options    => ['GRANT'],
+    privileges => ['SELECT', 'INSERT', 'UPDATE', 'DELETE'],
+    table      => 'somedb.*',
+    user       => 'someuser@localhost',
+  },
+}
+~~~
+
+##### `databases`
+
+Optional hash of databases to create, which are passed to [mysql_database](#mysql_database).
+
+~~~
+databases   => {
+  'somedb'  => {
+    ensure  => 'present',
+    charset => 'utf8',
+  },
+}
+~~~
+
+#### mysql::server::backup
+
+##### `backupuser`
+
+MySQL user to create for backups.
+
+##### `backuppassword`
+
+MySQL user password for backups.
+
+##### `backupdir`
+
+Directory in which to store backups.
+
+##### `backupdirmode`
+
+Permissions applied to the backup directory. This parameter is passed directly
+to the `file` resource.
+
+##### `backupdirowner`
+
+Owner for the backup directory. This parameter is passed directly to the `file`
+resource.
+
+##### `backupdirgroup`
+
+Group owner for the backup directory. This parameter is passed directly to the
+`file` resource.
+
+##### `backupcompress`
+
+Whether backups should be compressed. Valid values are 'true', 'false'. Defaults to 'true'.
+
+##### `backuprotate`
+
+How many days to keep backups. Valid value is an integer. Defaults to '30'.
+
+##### `delete_before_dump`
+
+Whether to delete old .sql files before backing up. Setting to 'true' deletes old files before backing up, while setting to 'false' deletes them after backup. Valid values are 'true', 'false'. Defaults to 'false'.
+
+##### `backupdatabases`
+
+Specify an array of databases to back up.
+
+##### `file_per_database`
+
+Whether a separate file be used per database. Valid values are 'true', 'false'. Defaults to 'false'.
+
+##### `include_routines`
+
+Whether or not to include routines for each database when doing a `file_per_database` backup. Defaults to `false`.
+
+##### `include_triggers`
+
+Whether or not to include triggers for each database when doing a `file_per_database` backup. Defaults to `false`.
+
+##### `ensure`
+
+Allows you to remove the backup scripts. Valid values are 'present', 'absent'. Defaults to 'present'.
+
+##### `execpath`
+
+Allows you to set a custom PATH should your MySQL installation be non-standard places. Defaults to `/usr/bin:/usr/sbin:/bin:/sbin`.
+
+##### `time`
+
+An array of two elements to set the backup time. Allows ['23', '5'] (i.e., 23:05) or ['3', '45'] (i.e., 03:45) for HH:MM times.
+
+##### `postscript`
+
+A script that is executed when the backup is finished. This could be used to (r)sync the backup to a central store. This script can be either a single line that is directly executed or a number of lines supplied as an array. It could also be one or more externally managed (executable) files.
+
+##### `prescript`
+
+A script that is executed before the backup begins.
+
+##### `provider`
+
+Sets the server backup implementation. Valid values are:
+
+* `mysqldump`: Implements backups with mysqldump. Backup type: Logical. This is the default value.
+* `mysqlbackup`: Implements backups with MySQL Enterprise Backup from Oracle. Backup type: Physical. To use this type of backup, you'll need the `meb` package, which is available in RPM and TAR formats from Oracle. For Ubuntu, you can use [meb-deb](https://github.com/dveeden/meb-deb) to create a package from an official tarball.
+* `xtrabackup`: Implements backups with XtraBackup from Percona. Backup type: Physical.
+
+#### mysql::server::monitor
+
+##### `mysql_monitor_username`
+
+The username to create for MySQL monitoring.
+
+##### `mysql_monitor_password`
+
+The password to create for MySQL monitoring.
+
+##### `mysql_monitor_hostname`
+
+The hostname from which the monitoring user requests are allowed access. 
+
+#### mysql::server::mysqltuner
+
+**Note**: If you're using this class on a non-network-connected system, you must download the mysqltuner.pl script and have it hosted somewhere accessible via `http(s)://`, `puppet://`, `ftp://`, or a fully qualified file path.
+
+##### `ensure`
+
+Ensures that the resource exists. Valid values are `present`, `absent`. Defaults to `present`.
+
+##### `version`
+
+The version to install from the major/MySQLTuner-perl github repository. Must be a valid tag. Defaults to 'v1.3.0'.
+
+##### `source`
+
+Parameter to optionally specify the source. If not specified, defaults to `https://github.com/major/MySQLTuner-perl/raw/${version}/mysqltuner.pl`
+
+#### mysql::bindings
+
+##### `client_dev`
+
+Specify whether `::mysql::bindings::client_dev` should be included. Valid values are true', 'false'. Defaults to 'false'.
+
+##### `daemon_dev`
+
+Specify whether `::mysql::bindings::daemon_dev` should be included. Valid values are 'true', 'false'. Defaults to 'false'.
+
+##### `java_enable`
+
+Specify whether `::mysql::bindings::java` should be included. Valid values are 'true', 'false'. Defaults to 'false'.
+
+#####  `perl_enable`
+
+Specify whether `mysql::bindings::perl` should be included. Valid values are 'true', 'false'. Defaults to 'false'.
+
+##### `php_enable`
+
+Specify whether `mysql::bindings::php` should be included. Valid values are 'true', 'false'. Defaults to 'false'.
+
+##### `python_enable`
+
+Specify whether `mysql::bindings::python` should be included. Valid values are 'true', 'false'. Defaults to 'false'.
+
+##### `ruby_enable`
+
+Specify whether `mysql::bindings::ruby` should be included. Valid values are 'true', 'false'. Defaults to 'false'.
+
+##### `install_options`
+
+Pass `install_options` array to managed package resources. You must pass the [appropriate options](https://docs.puppetlabs.com/references/latest/type.html#package-attribute-install_options) for the package manager(s).
+
+##### `client_dev_package_ensure`
+
+Whether the package should be present, absent, or a specific version. Valid values are 'present', 'absent', or 'x.y.z'. Only applies if `client_dev => true`.
+ 
+##### `client_dev_package_name`
+
+The name of the client_dev package to install. Only applies if `client_dev => true`.
+ 
+##### `client_dev_package_provider`
+
+The provider to use to install the client_dev package. Only applies if `client_dev => true`.
+
+##### `daemon_dev_package_ensure`
+
+Whether the package should be present, absent, or a specific version. Valid values are 'present', 'absent', or 'x.y.z'. Only applies if `daemon_dev => true`.
+
+##### `daemon_dev_package_name`
+
+The name of the daemon_dev package to install. Only applies if `daemon_dev => true`.
+
+##### `daemon_dev_package_provider`
+
+The provider to use to install the daemon_dev package. Only applies if `daemon_dev => true`.
+
+##### `java_package_ensure`
+
+Whether the package should be present, absent, or a specific version. Valid values are 'present', 'absent', or 'x.y.z'. Only applies if `java_enable => true`.
+
+##### `java_package_name`
+
+The name of the Java package to install. Only applies if `java_enable => true`.
+
+##### `java_package_provider`
+
+The provider to use to install the Java package. Only applies if `java_enable => true`.
+
+##### `perl_package_ensure`
+
+Whether the package should be present, absent, or a specific version. Valid values are 'present', 'absent', or 'x.y.z'. Only applies if `perl_enable => true`.
+
+##### `perl_package_name`
+
+The name of the Perl package to install. Only applies if `perl_enable => true`.
+
+##### `perl_package_provider`
+
+The provider to use to install the Perl package. Only applies if `perl_enable => true`.
+
+##### `php_package_ensure`
+
+Whether the package should be present, absent, or a specific version. Valid values are 'present', 'absent', or 'x.y.z'. Only applies if `php_enable => true`.
+ 
+##### `php_package_name`
+
+The name of the PHP package to install. Only applies if `php_enable => true`.
+
+##### `python_package_ensure`
+
+Whether the package should be present, absent, or a specific version. Valid values are 'present', 'absent', or 'x.y.z'. Only applies if `python_enable => true`.
+
+##### `python_package_name`
+
+The name of the Python package to install. Only applies if `python_enable => true`.
+
+##### `python_package_provider`
+
+The provider to use to install the PHP package. Only applies if `python_enable => true`.
+
+##### `ruby_package_ensure`
+
+Whether the package should be present, absent, or a specific version. Valid values are 'present', 'absent', or 'x.y.z'. Only applies if `ruby_enable => true`.
+
+##### `ruby_package_name`
+
+The name of the Ruby package to install. Only applies if `ruby_enable => true`.
+
+##### `ruby_package_provider`
+
+What provider should be used to install the package.
+
+#### mysql::client
+
+##### `bindings_enable`
+
+Whether to automatically install all bindings. Valid values are 'true', 'false'. Default to 'false'.
+
+##### `install_options`
+Array of install options for managed package resources. You must pass the appropriate options for the package manager.
+
+##### `package_ensure`
+
+Whether the MySQL package should be present, absent, or a specific version. Valid values are 'present', 'absent', or 'x.y.z'.
+
+##### `package_manage`
+
+Whether to manage the MySQL client package. Defaults to true.
+
+##### `package_name`
+
+The name of the MySQL client package to install.
+
+### Defines
+
+#### mysql::db
+
+~~~
+mysql_database { 'information_schema':
+  ensure  => 'present',
+  charset => 'utf8',
+  collate => 'utf8_swedish_ci',
+}
+mysql_database { 'mysql':
+  ensure  => 'present',
+  charset => 'latin1',
+  collate => 'latin1_swedish_ci',
+}
+~~~
+
+##### `user`
+
+The user for the database you're creating.
+ 
+##### `password`
+
+The password for $user for the database you're creating.
+
+##### `dbname`
+
+The name of the database to create. Defaults to $name.
+ 
+##### `charset`
+
+The character set for the database. Defaults to 'utf8'.
+
+##### `collate`
+
+The collation for the database. Defaults to 'utf8_general_ci'.
+ 
+##### `host`
+
+The host to use as part of user@host for grants. Defaults to 'localhost'.
+
+##### `grant`
+
+The privileges to be granted for user@host on the database. Defaults to 'ALL'.
+
+##### `sql`
+
+The path to the sqlfile you want to execute. This can be single file specified as string, or it can be an array of strings. Defaults to undef.
+
+##### `enforce_sql`
+
+Specify whether executing the sqlfiles should happen on every run. If set to 'false', sqlfiles only run once. Valid values are 'true', 'false'. Defaults to 'false'.
+ 
+##### `ensure`
+
+Specify whether to create the database. Valid values are 'present', 'absent'. Defaults to 'present'. 
+
+##### `import_timeout`
+
+Timeout, in seconds, for loading the sqlfiles. Defaults to '300'.
+
+### Types
+
+#### mysql_database
+
+`mysql_database` creates and manages databases within MySQL.
+
+##### `ensure`
+
+Whether the resource is present. Valid values are 'present', 'absent'. Defaults to 'present'.
+
+##### `name`
+
+The name of the MySQL database to manage.
+
+##### `charset`
+
+The CHARACTER SET setting for the database. Defaults to ':utf8'.
+
+##### `collate`
+
+The COLLATE setting for the database. Defaults to ':utf8_general_ci'. 
+
+#### mysql_user
+
+Creates and manages user grants within MySQL.
+
+~~~
+mysql_user { 'root@127.0.0.1':
+  ensure                   => 'present',
+  max_connections_per_hour => '0',
+  max_queries_per_hour     => '0',
+  max_updates_per_hour     => '0',
+  max_user_connections     => '0',
+}
+~~~
+
+You can also specify an authentication plugin.
+
+~~~
+mysql_user{ 'myuser'@'localhost':
+  ensure                   => 'present',
+  plugin                   => 'unix_socket',
+}
+~~~
+
+##### `name`
+
+The name of the user, as 'username@hostname' or username@hostname.
+
+##### `password_hash`
+
+The user's password hash of the user. Use mysql_password() for creating such a hash.
+
+##### `max_user_connections`
+
+Maximum concurrent connections for the user. Must be an integer value. A value of '0' specifies no (or global) limit.
+
+##### `max_connections_per_hour`
+
+Maximum connections per hour for the user. Must be an integer value. A value of '0' specifies no (or global) limit.
+
+##### `max_queries_per_hour`
+
+Maximum queries per hour for the user. Must be an integer value. A value of '0' specifies no (or global) limit.
+
+##### `max_updates_per_hour`
+
+Maximum updates per hour for the user. Must be an integer value. A value of '0' specifies no (or global) limit.
+
+
+#### mysql_grant
+
+`mysql_grant` creates grant permissions to access databases within
+MySQL. To create grant permissions to access databases with MySQL, use it you must create the title of the resource as shown below,
+following the pattern of `username@hostname/database.table`:
+
+~~~
+mysql_grant { 'root@localhost/*.*':
+  ensure     => 'present',
+  options    => ['GRANT'],
+  privileges => ['ALL'],
+  table      => '*.*',
+  user       => 'root@localhost',
+}
+~~~
+
+It is possible to specify privileges down to the column level:
+
+~~~
+mysql_grant { 'root@localhost/mysql.user':
+  ensure     => 'present',
+  privileges => ['SELECT (Host, User)'],
+  table      => 'mysql.user',
+  user       => 'root@localhost',
+}
+~~~
+
+##### `ensure`
+
+Whether the resource is present. Valid values are 'present', 'absent'. Defaults to 'present'.
+
+##### `name`
+
+Name to describe the grant. Must in a 'user/table' format. 
+
+##### `privileges`
+
+Privileges to grant the user.
+
+##### `table`
+
+The table to which privileges are applied.
+
+##### `user`
+
+User to whom privileges are granted.
+
+##### `options`
+
+MySQL options to grant. Optional.
+
+#### mysql_plugin
+
+`mysql_plugin` can be used to load plugins into the MySQL Server.
+
+~~~
+mysql_plugin { 'auth_socket':
+  ensure     => 'present',
+  soname     => 'auth_socket.so',
+}
+~~~
+
+##### `ensure`
+
+Whether the resource is present. Valid values are 'present', 'absent'. Defaults to 'present'.
+
+##### `name`
+
+The name of the MySQL plugin to manage.
+
+#####  `soname`
+
+The library file name.
+
+### Facts
+
+#### `mysql_version`
+
+Determines the MySQL version by parsing the output from `mysql --version`
+
+#### `mysql_server_id`
+
+Generates a unique id, based on the node's MAC address, which can be used as
+`server_id`. This fact will *always* return `0` on nodes that have only
+loopback interfaces. Because those nodes aren't connected to the outside world, this shouldn't cause any conflicts.
+
+## Limitations
+
+This module has been tested on:
+
+* RedHat Enterprise Linux 5, 6, 7
+* Debian 6, 7
+* CentOS 5, 6, 7
+* Ubuntu 10.04, 12.04, 14.04
+* Scientific Linux 5, 6
+* SLES 11
+
+Testing on other platforms has been minimal and cannot be guaranteed.
+
+## Development
+
+Puppet Labs modules on the Puppet Forge are open projects, and community
+contributions are essential for keeping them great. We can't access the
+huge number of platforms and myriad of hardware, software, and deployment
+configurations that Puppet is intended to serve.
+
+We want to keep it as easy as possible to contribute changes so that our
+modules work in your environment. There are a few guidelines that we need
+contributors to follow so that we can have a chance of keeping on top of things.
+
+Check out our the complete [module contribution guide](https://docs.puppetlabs.com/forge/contributing.html).
+
+### Authors
+
+This module is based on work by David Schmitt. The following contributors have contributed to this module (beyond Puppet Labs):
+
+* Larry Ludwig
+* Christian G. Warden
+* Daniel Black
+* Justin Ellison
+* Lowe Schmidt
+* Matthias Pigulla
+* William Van Hevelingen
+* Michael Arnold
+* Chris Weyl
+* Daniël van Eeden
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/Rakefile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+require 'puppetlabs_spec_helper/rake_tasks'
+require 'puppet-lint/tasks/puppet-lint'
+
+PuppetLint.configuration.fail_on_warnings = true
+PuppetLint.configuration.send('relative')
+PuppetLint.configuration.send('disable_80chars')
+PuppetLint.configuration.send('disable_class_inherits_from_params_class')
+PuppetLint.configuration.send('disable_documentation')
+PuppetLint.configuration.send('disable_single_quote_string_with_variables')
+PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/TODO	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+The best that I can tell is that this code traces back to David Schmitt. It has been forked many times since then :)
+
+1. you cannot add databases to an instance that has a root password
+2. you have to specify username as USER@BLAH or it cannot be found
+3. mysql_grant does not complain if user does not exist
+4. Needs support for pre-seeding on debian
+5. the types may need to take user/password
+6. rather or not to configure /etc/.my.cnf should be configurable
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/checksums.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,111 @@
+{
+  "CHANGELOG.md": "d399acef847a31667783e1f9d5f62547",
+  "CONTRIBUTING.md": "ad65d271f183b5adb9fdd58207939f5f",
+  "Gemfile": "88232482e212d61ac1130f3754ceea71",
+  "LICENSE": "6089b6bd1f0d807edb8bdfd76da0b038",
+  "README.md": "ee38a93d87f069295e16ad5665912c3d",
+  "Rakefile": "d953eb985f82600dc3b9ac6e1f2cfe64",
+  "TODO": "88ca4024a37992b46c34cb46e4ac39e6",
+  "examples/backup.pp": "a61c6f34f153a323209faf25948737f5",
+  "examples/bindings.pp": "35a8387f5c55fa2e479c513a67918674",
+  "examples/java.pp": "0ad9de4f9f2c049642bcf08124757085",
+  "examples/mysql_database.pp": "107ee8793f7b4a12cfca32eddccc6bbd",
+  "examples/mysql_db.pp": "55d2d603f9fb8ab3c8a781d08119aa69",
+  "examples/mysql_grant.pp": "cd42336a6c7b2d27f5d5d6d0e310ee1a",
+  "examples/mysql_plugin.pp": "4f86c988a99b131e736501a309604e94",
+  "examples/mysql_user.pp": "0b76964aebb01714745548e0f2f32fd3",
+  "examples/perl.pp": "454f14dc4492fcf04afbe81b2776917e",
+  "examples/python.pp": "355a7e1ea3978a8fd290b5bc28b63808",
+  "examples/ruby.pp": "a6ae0381aacc5a8d2c403e606c6df0f0",
+  "examples/server/account_security.pp": "375442b7886c01b42fbf75a1fcb31822",
+  "examples/server/config.pp": "659b7c40e9b55634721b3c33a8c6da98",
+  "examples/server.pp": "72e22552a95b9a5e4a349dbfc13639dc",
+  "lib/facter/mysql_server_id.rb": "2102724316f84a45906880d9551ef125",
+  "lib/facter/mysql_version.rb": "e30648f3d394a1cbdd4e54eb5c28d28c",
+  "lib/puppet/parser/functions/mysql_deepmerge.rb": "2b5040ee8cd75a81cf881851e922833a",
+  "lib/puppet/parser/functions/mysql_dirname.rb": "820ba09a6a0df639da560b41cb31242f",
+  "lib/puppet/parser/functions/mysql_password.rb": "100a3fa5ccb4f50c96d7f5167d43737f",
+  "lib/puppet/parser/functions/mysql_strip_hash.rb": "3efe69f1eb189b2913e178b8472aaede",
+  "lib/puppet/provider/mysql.rb": "881f4f76b084054f7299fe2de596e4c9",
+  "lib/puppet/provider/mysql_database/mysql.rb": "5cf9b8044df4ec72a726b5f781c84f8f",
+  "lib/puppet/provider/mysql_grant/mysql.rb": "211b6fb362e340f60a8ce32006349730",
+  "lib/puppet/provider/mysql_plugin/mysql.rb": "49128d2a9a547c4945735bfd75fd6d6c",
+  "lib/puppet/provider/mysql_user/mysql.rb": "3af9f573524a516e2ecd6d0830a92c62",
+  "lib/puppet/type/mysql_database.rb": "438eafbfecc30605462a220d92cf9603",
+  "lib/puppet/type/mysql_grant.rb": "2c04c9df671fc9c91d85cb2487d14ece",
+  "lib/puppet/type/mysql_plugin.rb": "0a52cead6c9283c9aa14ea71bdfa80bd",
+  "lib/puppet/type/mysql_user.rb": "e8dc61e4d81244d58a71b0d8aa01ac76",
+  "manifests/backup/mysqlbackup.pp": "3e97fe877ff4b151eb634ea83a84419c",
+  "manifests/backup/mysqldump.pp": "9883500deb8829cd70cf9a60120b80aa",
+  "manifests/backup/xtrabackup.pp": "6c809f8ba7973b4faaf29badfcbe8469",
+  "manifests/bindings/client_dev.pp": "80753f1bf48de71d2ca1a6cfda4830be",
+  "manifests/bindings/daemon_dev.pp": "94d2d74afc2b247593877cebd548ed76",
+  "manifests/bindings/java.pp": "556b743dc162d2f3264708b0b7ba0328",
+  "manifests/bindings/perl.pp": "4ecbd448ceac580a07df34b5d3e24837",
+  "manifests/bindings/php.pp": "641139f1f27085b8e72ac73fb8bc39d8",
+  "manifests/bindings/python.pp": "ef9e674237eddd7e98ab307131b11069",
+  "manifests/bindings/ruby.pp": "32b0a32161f7a5b50562cb8e154207d9",
+  "manifests/bindings.pp": "8becf04105d44910f12986a58cd566f7",
+  "manifests/client/install.pp": "7b5810404cc9411ec38de404749f1266",
+  "manifests/client.pp": "c350bd6d108acb03a87b860b14d225ef",
+  "manifests/db.pp": "109ea3b19c342c645383df511e6a2782",
+  "manifests/params.pp": "c505d22c458faafbb4767adb1a0df5af",
+  "manifests/server/account_security.pp": "407e8c4bd6f2467927b23f241fc556e3",
+  "manifests/server/backup.pp": "c982860f7e8ac525e3ede3045fdda516",
+  "manifests/server/config.pp": "38610a61d097080a655aad5ee1489159",
+  "manifests/server/install.pp": "3cbbf313b940b582e73c229f4a8c0720",
+  "manifests/server/installdb.pp": "639834afb24583aa6685b9b2b4749f69",
+  "manifests/server/monitor.pp": "3810b5d756a3661e92d709115982cd59",
+  "manifests/server/mysqltuner.pp": "c966679bff1296e875a9ec1462a022f4",
+  "manifests/server/providers.pp": "87a019dce5bbb6b18c9aa61b5f99134c",
+  "manifests/server/root_password.pp": "956b7c181b1e14517811fa94b151eceb",
+  "manifests/server/service.pp": "1278f5cb267024760e1299c99dc1bf80",
+  "manifests/server.pp": "a3fe8f65e57466af28b7581847cef8b4",
+  "metadata.json": "2372889b329a6ac5eac163334a03562b",
+  "spec/acceptance/mysql_backup_spec.rb": "57cb101519fce1ad588fd60f3435d57c",
+  "spec/acceptance/mysql_db_spec.rb": "a7d0d87f1d51d9914b00c849fc694083",
+  "spec/acceptance/mysql_server_spec.rb": "0d7abdd7699fac5acc76ec6b4f9ebb46",
+  "spec/acceptance/nodesets/centos-510-x64.yml": "5698f7e61292730c603e03f64fe19359",
+  "spec/acceptance/nodesets/centos-59-x64.yml": "57eb3e471b9042a8ea40978c467f8151",
+  "spec/acceptance/nodesets/centos-64-x64-pe.yml": "ec075d95760df3d4702abea1ce0a829b",
+  "spec/acceptance/nodesets/centos-65-x64.yml": "3e5c36e6aa5a690229e720f4048bb8af",
+  "spec/acceptance/nodesets/default.yml": "76d6d770f3daf53ef1b9a17cd0163290",
+  "spec/acceptance/nodesets/fedora-18-x64.yml": "80e41b1ee16ea489f53164bfdae58855",
+  "spec/acceptance/nodesets/sles-11-x64.yml": "44e4c6c15c018333bfa9840a5e702f66",
+  "spec/acceptance/nodesets/ubuntu-server-10044-x64.yml": "75e86400b7889888dc0781c0ae1a1297",
+  "spec/acceptance/nodesets/ubuntu-server-12042-x64.yml": "d30d73e34cd50b043c7d14e305955269",
+  "spec/acceptance/nodesets/ubuntu-server-1404-x64.yml": "5f0aed10098ac5b78e4217bb27c7aaf0",
+  "spec/acceptance/types/mysql_database_spec.rb": "047db055103fa9782bc6714297eb2a09",
+  "spec/acceptance/types/mysql_grant_spec.rb": "f9217261e7bae6b63ea46aaa880ebfba",
+  "spec/acceptance/types/mysql_plugin_spec.rb": "e41e1df4997f57d70db4aaff8b0a1549",
+  "spec/acceptance/types/mysql_user_spec.rb": "7ae65d682141d2b6005adeafc4ce4698",
+  "spec/classes/graceful_failures_spec.rb": "47acbf0ef4b19ba26055b927b24d8a95",
+  "spec/classes/mycnf_template_spec.rb": "c37c8eb3dce1c4e913b5b3a60c80d5cb",
+  "spec/classes/mysql_bindings_spec.rb": "fd66517c1c61afdf5a4a13c096fb7288",
+  "spec/classes/mysql_client_spec.rb": "7373be9edd90c54769a66e8af914b852",
+  "spec/classes/mysql_server_account_security_spec.rb": "22e2b1cb11bd284e02b35e86ff6704cf",
+  "spec/classes/mysql_server_backup_spec.rb": "5f049e1581345c6afbfb2b46aea07e17",
+  "spec/classes/mysql_server_monitor_spec.rb": "99e2b530a11e48b31b35f1a50099b8b5",
+  "spec/classes/mysql_server_mysqltuner_spec.rb": "4d5f354c4eae5a096166df1099b93f6b",
+  "spec/classes/mysql_server_spec.rb": "b12a8e7723ca1aff415ba269bfe9d29d",
+  "spec/defines/mysql_db_spec.rb": "a69768ea38014520866bda65948c15c1",
+  "spec/spec.opts": "a600ded995d948e393fbe2320ba8e51c",
+  "spec/spec_helper.rb": "70cdee91641a840b7397d6ef34e5946e",
+  "spec/spec_helper_acceptance.rb": "100dc861896453159dcdc1577126b599",
+  "spec/unit/facter/mysql_server_id_spec.rb": "3b5aeea6d264064032454ed60bc3f60f",
+  "spec/unit/facter/mysql_version_spec.rb": "f593c725b83a7bbf1f0fdc13bf1531df",
+  "spec/unit/puppet/functions/mysql_deepmerge_spec.rb": "f6102e1f82fb9f4aa38cbf3955ee5973",
+  "spec/unit/puppet/functions/mysql_password_spec.rb": "388c74f0a3b46ecc008e84ec6eda70f4",
+  "spec/unit/puppet/provider/mysql_database/mysql_spec.rb": "98a799433ac10b237ac3ad27441610d4",
+  "spec/unit/puppet/provider/mysql_plugin/mysql_spec.rb": "914bac73bb9841ec7d7041488a55d442",
+  "spec/unit/puppet/provider/mysql_user/mysql_spec.rb": "b72cedb4003c6591b9b4eec62ef89c11",
+  "spec/unit/puppet/type/mysql_database_spec.rb": "9fa0d390c2e15c8a52fc2b981e2a63fc",
+  "spec/unit/puppet/type/mysql_grant_spec.rb": "1a003358dc88a74ef21fb33fc71debef",
+  "spec/unit/puppet/type/mysql_plugin_spec.rb": "7ebacf228dfd0c60811bdf8a28a329ff",
+  "spec/unit/puppet/type/mysql_user_spec.rb": "ededed596db6661ea769aa333decc785",
+  "templates/meb.cnf.erb": "b6422b19ee97b8a2883bfac44fdc0292",
+  "templates/my.cnf.erb": "701e3cd51d99fbd3ec60a68aaa1c8417",
+  "templates/my.cnf.pass.erb": "75e3d0aaa6bf2d92cdaae387a3da65a7",
+  "templates/mysqlbackup.sh.erb": "52a4ce563dd3f2dd9c5b1fc1397a3a79",
+  "templates/xtrabackup.sh.erb": "219b487c4faad80a897cda6973b81741"
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/backup.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+class { 'mysql::server':
+  root_password => 'password'
+}
+
+class { 'mysql::server::backup':
+  backupuser     => 'myuser',
+  backuppassword => 'mypassword',
+  backupdir      => '/tmp/backups',
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/bindings.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class { 'mysql::bindings':
+  php_enable => true,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/java.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+class { 'mysql::java':}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/mysql_database.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+class { 'mysql::server':
+  root_password => 'password'
+}
+mysql::db{ ['test1', 'test2', 'test3']:
+  ensure  => present,
+  charset => 'utf8',
+  require => Class['mysql::server'],
+}
+mysql::db{ 'test4':
+  ensure  => present,
+  charset => 'latin1',
+}
+mysql::db{ 'test5':
+  ensure  => present,
+  charset => 'binary',
+  collate => 'binary',
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/mysql_db.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+class { 'mysql::server':
+  root_password => 'password'
+}
+mysql::db { 'mydb':
+  user     => 'myuser',
+  password => 'mypass',
+  host     => 'localhost',
+  grant    => ['SELECT', 'UPDATE'],
+}
+mysql::db { "mydb_${fqdn}":
+  user     => 'myuser',
+  password => 'mypass',
+  dbname   => 'mydb',
+  host     => $::fqdn,
+  grant    => ['SELECT', 'UPDATE'],
+  tag      => $domain,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/mysql_grant.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+mysql_grant{'test1@localhost/redmine.*':
+  user       => 'test1@localhost',
+  table      => 'redmine.*',
+  privileges => ['UPDATE'],
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/mysql_plugin.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+class { 'mysql::server':
+  root_password => 'password'
+}
+
+$validate_password_soname = $::osfamily ? {
+  windows => 'validate_password.dll',
+  default => 'validate_password.so'
+}
+
+mysql::plugin { 'validate_password':
+  ensure => present,
+  soname => $validate_password_soname,
+}
+
+$auth_socket_soname = $::osfamily ? {
+  windows => 'auth_socket.dll',
+  default => 'auth_socket.so'
+}
+
+mysql::plugin { 'auth_socket':
+  ensure => present,
+  soname => $auth_socket_soname,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/mysql_user.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+$mysql_root_pw = 'password'
+
+class { 'mysql::server':
+  root_password => 'password',
+}
+
+mysql_user{ 'redmine@localhost':
+  ensure        => present,
+  password_hash => mysql_password('redmine'),
+  require       => Class['mysql::server'],
+}
+
+mysql_user{ 'dan@localhost':
+  ensure        => present,
+  password_hash => mysql_password('blah')
+}
+
+mysql_user{ 'dan@%':
+  ensure        => present,
+  password_hash => mysql_password('blah'),
+}
+
+mysql_user{ 'socketplugin@%':
+  ensure => present,
+  plugin => 'unix_socket',
+}
+
+mysql_user{ 'socketplugin@%':
+  ensure        => present,
+  password_hash => mysql_password('blah'),
+  plugin        => 'mysql_native_password',
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/perl.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+include mysql::bindings::perl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/python.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+class { 'mysql::bindings::python':}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/ruby.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+include mysql::bindings::ruby
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/server.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class { 'mysql::server':
+  root_password => 'password',
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/server/account_security.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+class { 'mysql::server':
+  root_password => 'password',
+}
+class { 'mysql::server::account_security': }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/examples/server/config.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+mysql::server::config { 'testfile':
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/facter/mysql_server_id.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+def get_mysql_id
+  Facter.value(:macaddress).split(':').inject(0) { |total,value| (total << 4) + value.hex }
+end
+
+Facter.add("mysql_server_id") do
+  setcode do
+    get_mysql_id rescue nil
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/facter/mysql_version.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+Facter.add("mysql_version") do
+  setcode do
+    mysql_ver = Facter::Util::Resolution.exec('mysql --version')
+    if mysql_ver
+      mysql_ver.match(/\d+\.\d+\.\d+/)[0]
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/parser/functions/mysql_deepmerge.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,58 @@
+module Puppet::Parser::Functions
+  newfunction(:mysql_deepmerge, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+    Recursively merges two or more hashes together and returns the resulting hash.
+
+    For example:
+
+        $hash1 = {'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }
+        $hash2 = {'two' => 'dos', 'three' => { 'five' => 5 } }
+        $merged_hash = mysql_deepmerge($hash1, $hash2)
+        # The resulting hash is equivalent to:
+        # $merged_hash = { 'one' => 1, 'two' => 'dos', 'three' => { 'four' => 4, 'five' => 5 } }
+
+    When there is a duplicate key that is a hash, they are recursively merged.
+    When there is a duplicate key that is not a hash, the key in the rightmost hash will "win."
+    When there are conficting uses of dashes and underscores in two keys (which mysql would otherwise equate),
+      the rightmost style will win.
+
+    ENDHEREDOC
+
+    if args.length < 2
+      raise Puppet::ParseError, ("mysql_deepmerge(): wrong number of arguments (#{args.length}; must be at least 2)")
+    end
+
+    result = Hash.new
+    args.each do |arg|
+      next if arg.is_a? String and arg.empty? # empty string is synonym for puppet's undef
+      # If the argument was not a hash, skip it.
+      unless arg.is_a?(Hash)
+        raise Puppet::ParseError, "mysql_deepmerge: unexpected argument type #{arg.class}, only expects hash arguments"
+      end
+
+      # Now we have to traverse our hash assigning our non-hash values
+      # to the matching keys in our result while following our hash values
+      # and repeating the process.
+      overlay( result, arg )
+    end
+    return( result )
+  end
+end
+
+def has_normalized!(hash, key)
+  return true if hash.has_key?( key )
+  return false unless key.match(/-|_/)
+  other_key = key.include?('-') ? key.gsub( '-', '_' ) : key.gsub( '_', '-' )
+  return false unless hash.has_key?( other_key )
+  hash[key] = hash.delete( other_key )
+  return true;
+end
+
+def overlay( hash1, hash2 )
+  hash2.each do |key, value|
+    if(has_normalized!( hash1, key ) and value.is_a?(Hash) and hash1[key].is_a?(Hash))
+      overlay( hash1[key], value )
+    else
+      hash1[key] = value
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/parser/functions/mysql_dirname.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+module Puppet::Parser::Functions
+  newfunction(:mysql_dirname, :type => :rvalue, :doc => <<-EOS
+    Returns the dirname of a path.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "mysql_dirname(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    path = arguments[0]
+    return File.dirname(path)
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/parser/functions/mysql_password.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+# hash a string as mysql's "PASSWORD()" function would do it
+require 'digest/sha1'
+
+module Puppet::Parser::Functions
+  newfunction(:mysql_password, :type => :rvalue, :doc => <<-EOS
+    Returns the mysql password hash from the clear text password.
+    EOS
+  ) do |args|
+
+    raise(Puppet::ParseError, 'mysql_password(): Wrong number of arguments ' +
+      "given (#{args.size} for 1)") if args.size != 1
+
+    return '' if args[0].empty?
+    '*' + Digest::SHA1.hexdigest(Digest::SHA1.digest(args[0])).upcase
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/parser/functions/mysql_strip_hash.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+module Puppet::Parser::Functions
+  newfunction(:mysql_strip_hash, :type => :rvalue, :arity => 1, :doc => <<-EOS
+TEMPORARY FUNCTION: EXPIRES 2014-03-10
+When given a hash this function strips out all blank entries.
+EOS
+  ) do |args|
+
+    hash = args[0]
+    unless hash.is_a?(Hash)
+      raise(Puppet::ParseError, 'mysql_strip_hash(): Requires hash to work with')
+    end
+
+    # Filter out all the top level blanks.
+    hash.reject{|k,v| v == ''}.each do |k,v|
+      if v.is_a?(Hash)
+        v.reject!{|ki,vi| vi == '' }
+      end
+    end
+
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/provider/mysql.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,70 @@
+class Puppet::Provider::Mysql < Puppet::Provider
+
+  # Without initvars commands won't work.
+  initvars
+  commands :mysql      => 'mysql'
+  commands :mysqladmin => 'mysqladmin'
+
+  # Optional defaults file
+  def self.defaults_file
+    if File.file?("#{Facter.value(:root_home)}/.my.cnf")
+      "--defaults-extra-file=#{Facter.value(:root_home)}/.my.cnf"
+    else
+      nil
+    end
+  end
+  
+  def defaults_file
+    self.class.defaults_file
+  end
+
+  def self.users
+    mysql([defaults_file, '-NBe', "SELECT CONCAT(User, '@',Host) AS User FROM mysql.user"].compact).split("\n")
+  end
+
+  # Take root@localhost and munge it to 'root'@'localhost'
+  def self.cmd_user(user)
+    "'#{user.sub('@', "'@'")}'"
+  end
+
+  # Take root.* and return ON `root`.*
+  def self.cmd_table(table)
+    table_string = ''
+
+    # We can't escape *.* so special case this.
+    if table == '*.*'
+      table_string << '*.*'
+    # Special case also for PROCEDURES
+    elsif table.start_with?('PROCEDURE ')
+      table_string << table.sub(/^PROCEDURE (.*)(\..*)/, 'PROCEDURE `\1`\2')
+    else
+      table_string << table.sub(/^(.*)(\..*)/, '`\1`\2')
+    end
+    table_string
+  end
+
+  def self.cmd_privs(privileges)
+    if privileges.include?('ALL')
+      return 'ALL PRIVILEGES'
+    else
+      priv_string = ''
+      privileges.each do |priv|
+        priv_string << "#{priv}, "
+      end
+    end
+    # Remove trailing , from the last element.
+    priv_string.sub(/, $/, '')
+  end
+
+  # Take in potential options and build up a query string with them.
+  def self.cmd_options(options)
+    option_string = ''
+    options.each do |opt|
+      if opt == 'GRANT'
+        option_string << ' WITH GRANT OPTION'
+      end
+    end
+    option_string
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/provider/mysql_database/mysql.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,68 @@
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mysql'))
+Puppet::Type.type(:mysql_database).provide(:mysql, :parent => Puppet::Provider::Mysql) do
+  desc 'Manages MySQL databases.'
+
+  commands :mysql => 'mysql'
+
+  def self.instances
+    mysql([defaults_file, '-NBe', 'show databases'].compact).split("\n").collect do |name|
+      attributes = {}
+      mysql([defaults_file, '-NBe', "show variables like '%_database'", name].compact).split("\n").each do |line|
+        k,v = line.split(/\s/)
+        attributes[k] = v
+      end
+      new(:name    => name,
+          :ensure  => :present,
+          :charset => attributes['character_set_database'],
+          :collate => attributes['collation_database']
+         )
+    end
+  end
+
+  # We iterate over each mysql_database entry in the catalog and compare it against
+  # the contents of the property_hash generated by self.instances
+  def self.prefetch(resources)
+    databases = instances
+    resources.keys.each do |database|
+      if provider = databases.find { |db| db.name == database }
+        resources[database].provider = provider
+      end
+    end
+  end
+
+  def create
+    mysql([defaults_file, '-NBe', "create database if not exists `#{@resource[:name]}` character set `#{@resource[:charset]}` collate `#{@resource[:collate]}`"].compact)
+
+    @property_hash[:ensure]  = :present
+    @property_hash[:charset] = @resource[:charset]
+    @property_hash[:collate] = @resource[:collate]
+
+    exists? ? (return true) : (return false)
+  end
+
+  def destroy
+    mysql([defaults_file, '-NBe', "drop database if exists `#{@resource[:name]}`"].compact)
+
+    @property_hash.clear
+    exists? ? (return false) : (return true)
+  end
+
+  def exists?
+    @property_hash[:ensure] == :present || false
+  end
+
+  mk_resource_methods
+
+  def charset=(value)
+    mysql([defaults_file, '-NBe', "alter database `#{resource[:name]}` CHARACTER SET #{value}"].compact)
+    @property_hash[:charset] = value
+    charset == value ? (return true) : (return false)
+  end
+
+  def collate=(value)
+    mysql([defaults_file, '-NBe', "alter database `#{resource[:name]}` COLLATE #{value}"].compact)
+    @property_hash[:collate] = value
+    collate == value ? (return true) : (return false)
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/provider/mysql_grant/mysql.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,168 @@
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mysql'))
+Puppet::Type.type(:mysql_grant).provide(:mysql, :parent => Puppet::Provider::Mysql) do
+
+  desc 'Set grants for users in MySQL.'
+
+  def self.instances
+    instances = []
+    users.select{ |user| user =~ /.+@/ }.collect do |user|
+      user_string = self.cmd_user(user)
+      query = "SHOW GRANTS FOR #{user_string};"
+      begin
+        grants = mysql([defaults_file, "-NBe", query].compact)
+      rescue Puppet::ExecutionFailure => e
+        # Silently ignore users with no grants. Can happen e.g. if user is
+        # defined with fqdn and server is run with skip-name-resolve. Example:
+        # Default root user created by mysql_install_db on a host with fqdn
+        # of myhost.mydomain.my: root@myhost.mydomain.my, when MySQL is started
+        # with --skip-name-resolve.
+        if e.inspect =~ /There is no such grant defined for user/
+          next
+        else
+          raise Puppet::Error, "#mysql had an error ->  #{e.inspect}"
+        end
+      end
+      # Once we have the list of grants generate entries for each.
+      grants.each_line do |grant|
+        # Match the munges we do in the type.
+        munged_grant = grant.delete("'").delete("`")
+        # Matching: GRANT (SELECT, UPDATE) PRIVILEGES ON (*.*) TO ('root')@('127.0.0.1') (WITH GRANT OPTION)
+        if match = munged_grant.match(/^GRANT\s(.+)\sON\s(.+)\sTO\s(.*)@(.*?)(\s.*)?$/)
+          privileges, table, user, host, rest = match.captures
+          table.gsub!('\\\\', '\\')
+
+          # split on ',' if it is not a non-'('-containing string followed by a
+          # closing parenthesis ')'-char - e.g. only split comma separated elements not in
+          # parentheses
+          stripped_privileges = privileges.strip.split(/\s*,\s*(?![^(]*\))/).map do |priv|
+            # split and sort the column_privileges in the parentheses and rejoin
+            if priv.include?('(')
+              type, col=priv.strip.split(/\s+|\b/,2)
+              type.upcase + " (" + col.slice(1...-1).strip.split(/\s*,\s*/).sort.join(', ') + ")"
+            else
+              # Once we split privileges up on the , we need to make sure we
+              # shortern ALL PRIVILEGES to just all.
+              priv == 'ALL PRIVILEGES' ? 'ALL' : priv.strip
+            end
+          end
+          # Same here, but to remove OPTION leaving just GRANT.
+          options = ['GRANT'] if rest.match(/WITH\sGRANT\sOPTION/)
+          # fix double backslash that MySQL prints, so resources match
+          table.gsub!("\\\\", "\\")
+          # We need to return an array of instances so capture these
+          instances << new(
+              :name       => "#{user}@#{host}/#{table}",
+              :ensure     => :present,
+              :privileges => stripped_privileges.sort,
+              :table      => table,
+              :user       => "#{user}@#{host}",
+              :options    => options
+          )
+        end
+      end
+    end
+    return instances
+  end
+
+  def self.prefetch(resources)
+    users = instances
+    resources.keys.each do |name|
+      if provider = users.find { |user| user.name == name }
+        resources[name].provider = provider
+      end
+    end
+  end
+
+  def grant(user, table, privileges, options)
+    user_string = self.class.cmd_user(user)
+    priv_string = self.class.cmd_privs(privileges)
+    table_string = self.class.cmd_table(table)
+    query = "GRANT #{priv_string}"
+    query << " ON #{table_string}"
+    query << " TO #{user_string}"
+    query << self.class.cmd_options(options) unless options.nil?
+    mysql([defaults_file, '-e', query].compact)
+  end
+
+  def create
+    grant(@resource[:user], @resource[:table], @resource[:privileges], @resource[:options])
+
+    @property_hash[:ensure]     = :present
+    @property_hash[:table]      = @resource[:table]
+    @property_hash[:user]       = @resource[:user]
+    @property_hash[:options]    = @resource[:options] if @resource[:options]
+    @property_hash[:privileges] = @resource[:privileges]
+
+    exists? ? (return true) : (return false)
+  end
+
+  def revoke(user, table, revoke_privileges = ['ALL'])
+    user_string = self.class.cmd_user(user)
+    table_string = self.class.cmd_table(table)
+    priv_string = self.class.cmd_privs(revoke_privileges)
+    # revoke grant option needs to be a extra query, because
+    # "REVOKE ALL PRIVILEGES, GRANT OPTION [..]" is only valid mysql syntax
+    # if no ON clause is used.
+    # It hast to be executed before "REVOKE ALL [..]" since a GRANT has to
+    # exist to be executed successfully
+    if revoke_privileges.include? 'ALL'
+      query = "REVOKE GRANT OPTION ON #{table_string} FROM #{user_string}"
+      mysql([defaults_file, '-e', query].compact)
+    end
+    query = "REVOKE #{priv_string} ON #{table_string} FROM #{user_string}"
+    mysql([defaults_file, '-e', query].compact)
+  end
+
+  def destroy
+    revoke(@property_hash[:user], @property_hash[:table])
+    @property_hash.clear
+
+    exists? ? (return false) : (return true)
+  end
+
+  def exists?
+    @property_hash[:ensure] == :present || false
+  end
+
+  def flush
+    @property_hash.clear
+    mysql([defaults_file, '-NBe', 'FLUSH PRIVILEGES'].compact)
+  end
+
+  mk_resource_methods
+
+  def diff_privileges(privileges_old, privileges_new)
+    diff = {:revoke => Array.new, :grant => Array.new}
+    if privileges_old.include? 'ALL'
+      diff[:revoke] = privileges_old
+      diff[:grant] = privileges_new
+    elsif privileges_new.include? 'ALL'
+      diff[:grant] = privileges_new
+    else
+      diff[:revoke] = privileges_old - privileges_new
+      diff[:grant] = privileges_new - privileges_old
+    end
+    return diff
+  end
+
+  def privileges=(privileges)
+    diff = diff_privileges(@property_hash[:privileges], privileges)
+    if not diff[:revoke].empty?
+      revoke(@property_hash[:user], @property_hash[:table], diff[:revoke])
+    end
+    if not diff[:grant].empty?
+      grant(@property_hash[:user], @property_hash[:table], diff[:grant], @property_hash[:options])
+    end
+    @property_hash[:privileges] = privileges
+    self.privileges
+  end
+
+  def options=(options)
+    revoke(@property_hash[:user], @property_hash[:table])
+    grant(@property_hash[:user], @property_hash[:table], @property_hash[:privileges], options)
+    @property_hash[:options] = options
+
+    self.options
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/provider/mysql_plugin/mysql.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,53 @@
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mysql'))
+Puppet::Type.type(:mysql_plugin).provide(:mysql, :parent => Puppet::Provider::Mysql) do
+  desc 'Manages MySQL plugins.'
+
+  commands :mysql => 'mysql'
+
+  def self.instances
+    mysql([defaults_file, '-NBe', 'show plugins'].compact).split("\n").collect do |line|
+      name, status, type, library, license = line.split(/\t/)
+      new(:name    => name,
+          :ensure  => :present,
+          :soname  => library
+         )
+    end
+  end
+
+  # We iterate over each mysql_plugin entry in the catalog and compare it against
+  # the contents of the property_hash generated by self.instances
+  def self.prefetch(resources)
+    plugins = instances
+    resources.keys.each do |plugin|
+      if provider = plugins.find { |pl| pl.name == plugin }
+        resources[plugin].provider = provider
+      end
+    end
+  end
+
+  def create
+    # Use plugin_name.so as soname if it's not specified. This won't work on windows as
+    # there it should be plugin_name.dll
+    @resource[:soname].nil? ? (soname=@resource[:name] + '.so') : (soname=@resource[:soname])
+    mysql([defaults_file, '-NBe', "install plugin #{@resource[:name]} soname '#{soname}'"].compact)
+
+    @property_hash[:ensure]  = :present
+    @property_hash[:soname] = @resource[:soname]
+
+    exists? ? (return true) : (return false)
+  end
+
+  def destroy
+    mysql([defaults_file, '-NBe', "uninstall plugin #{@resource[:name]}"].compact)
+
+    @property_hash.clear
+    exists? ? (return false) : (return true)
+  end
+
+  def exists?
+    @property_hash[:ensure] == :present || false
+  end
+
+  mk_resource_methods
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/provider/mysql_user/mysql.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,125 @@
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mysql'))
+Puppet::Type.type(:mysql_user).provide(:mysql, :parent => Puppet::Provider::Mysql) do
+
+  desc 'manage users for a mysql database.'
+  commands :mysql => 'mysql'
+
+  # Build a property_hash containing all the discovered information about MySQL
+  # users.
+  def self.instances
+    users = mysql([defaults_file, '-NBe',
+      "SELECT CONCAT(User, '@',Host) AS User FROM mysql.user"].compact).split("\n")
+    # To reduce the number of calls to MySQL we collect all the properties in
+    # one big swoop.
+    users.collect do |name|
+      query = "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, PASSWORD /*!50508 , PLUGIN */ FROM mysql.user WHERE CONCAT(user, '@', host) = '#{name}'"
+      @max_user_connections, @max_connections_per_hour, @max_queries_per_hour,
+      @max_updates_per_hour, @password, @plugin = mysql([defaults_file, "-NBe", query].compact).split(/\s/)
+
+      new(:name                     => name,
+          :ensure                   => :present,
+          :password_hash            => @password,
+          :plugin                   => @plugin,
+          :max_user_connections     => @max_user_connections,
+          :max_connections_per_hour => @max_connections_per_hour,
+          :max_queries_per_hour     => @max_queries_per_hour,
+          :max_updates_per_hour     => @max_updates_per_hour
+         )
+    end
+  end
+
+  # We iterate over each mysql_user entry in the catalog and compare it against
+  # the contents of the property_hash generated by self.instances
+  def self.prefetch(resources)
+    users = instances
+    resources.keys.each do |name|
+      if provider = users.find { |user| user.name == name }
+        resources[name].provider = provider
+      end
+    end
+  end
+
+  def create
+    merged_name              = @resource[:name].sub('@', "'@'")
+    password_hash            = @resource.value(:password_hash)
+    plugin                   = @resource.value(:plugin)
+    max_user_connections     = @resource.value(:max_user_connections) || 0
+    max_connections_per_hour = @resource.value(:max_connections_per_hour) || 0
+    max_queries_per_hour     = @resource.value(:max_queries_per_hour) || 0
+    max_updates_per_hour     = @resource.value(:max_updates_per_hour) || 0
+
+    # Use CREATE USER to be compatible with NO_AUTO_CREATE_USER sql_mode
+    # This is also required if you want to specify a authentication plugin
+    if !plugin.nil?
+      mysql([defaults_file, '-e', "CREATE USER '#{merged_name}' IDENTIFIED WITH '#{plugin}'"].compact)
+      @property_hash[:ensure] = :present
+      @property_hash[:plugin] = plugin
+    else
+      mysql([defaults_file, '-e', "CREATE USER '#{merged_name}' IDENTIFIED BY PASSWORD '#{password_hash}'"].compact)
+      @property_hash[:ensure] = :present
+      @property_hash[:password_hash] = password_hash
+    end
+    mysql([defaults_file, '-e', "GRANT USAGE ON *.* TO '#{merged_name}' WITH MAX_USER_CONNECTIONS #{max_user_connections} MAX_CONNECTIONS_PER_HOUR #{max_connections_per_hour} MAX_QUERIES_PER_HOUR #{max_queries_per_hour} MAX_UPDATES_PER_HOUR #{max_updates_per_hour}"].compact)
+    @property_hash[:max_user_connections] = max_user_connections
+    @property_hash[:max_connections_per_hour] = max_connections_per_hour
+    @property_hash[:max_queries_per_hour] = max_queries_per_hour
+    @property_hash[:max_updates_per_hour] = max_updates_per_hour
+
+    exists? ? (return true) : (return false)
+  end
+
+  def destroy
+    merged_name = @resource[:name].sub('@', "'@'")
+    mysql([defaults_file, '-e', "DROP USER '#{merged_name}'"].compact)
+
+    @property_hash.clear
+    exists? ? (return false) : (return true)
+  end
+
+  def exists?
+    @property_hash[:ensure] == :present || false
+  end
+
+  ##
+  ## MySQL user properties
+  ##
+
+  # Generates method for all properties of the property_hash
+  mk_resource_methods
+
+  def password_hash=(string)
+    merged_name = self.class.cmd_user(@resource[:name])
+    mysql([defaults_file, '-e', "SET PASSWORD FOR #{merged_name} = '#{string}'"].compact)
+
+    password_hash == string ? (return true) : (return false)
+  end
+
+  def max_user_connections=(int)
+    merged_name = self.class.cmd_user(@resource[:name])
+    mysql([defaults_file, '-e', "GRANT USAGE ON *.* TO #{merged_name} WITH MAX_USER_CONNECTIONS #{int}"].compact).chomp
+
+    max_user_connections == int ? (return true) : (return false)
+  end
+
+  def max_connections_per_hour=(int)
+    merged_name = self.class.cmd_user(@resource[:name])
+    mysql([defaults_file, '-e', "GRANT USAGE ON *.* TO #{merged_name} WITH MAX_CONNECTIONS_PER_HOUR #{int}"].compact).chomp
+
+    max_connections_per_hour == int ? (return true) : (return false)
+  end
+
+  def max_queries_per_hour=(int)
+    merged_name = self.class.cmd_user(@resource[:name])
+    mysql([defaults_file, '-e', "GRANT USAGE ON *.* TO #{merged_name} WITH MAX_QUERIES_PER_HOUR #{int}"].compact).chomp
+
+    max_queries_per_hour == int ? (return true) : (return false)
+  end
+
+  def max_updates_per_hour=(int)
+    merged_name = self.class.cmd_user(@resource[:name])
+    mysql([defaults_file, '-e', "GRANT USAGE ON *.* TO #{merged_name} WITH MAX_UPDATES_PER_HOUR #{int}"].compact).chomp
+
+    max_updates_per_hour == int ? (return true) : (return false)
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/type/mysql_database.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+Puppet::Type.newtype(:mysql_database) do
+  @doc = 'Manage MySQL databases.'
+
+  ensurable
+
+  autorequire(:file) { '/root/.my.cnf' }
+  autorequire(:class) { 'mysql::server' }
+
+  newparam(:name, :namevar => true) do
+    desc 'The name of the MySQL database to manage.'
+  end
+
+  newproperty(:charset) do
+    desc 'The CHARACTER SET setting for the database'
+    defaultto :utf8
+    newvalue(/^\S+$/)
+  end
+
+  newproperty(:collate) do
+    desc 'The COLLATE setting for the database'
+    defaultto :utf8_general_ci
+    newvalue(/^\S+$/)
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/type/mysql_grant.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,101 @@
+# This has to be a separate type to enable collecting
+Puppet::Type.newtype(:mysql_grant) do
+  @doc = "Manage a MySQL user's rights."
+  ensurable
+
+  autorequire(:file) { '/root/.my.cnf' }
+  autorequire(:mysql_user) { self[:user] }
+
+  def initialize(*args)
+    super
+    # Forcibly munge any privilege with 'ALL' in the array to exist of just
+    # 'ALL'.  This can't be done in the munge in the property as that iterates
+    # over the array and there's no way to replace the entire array before it's
+    # returned to the provider.
+    if self[:ensure] == :present and Array(self[:privileges]).count > 1 and self[:privileges].to_s.include?('ALL')
+      self[:privileges] = 'ALL'
+    end
+    # Sort the privileges array in order to ensure the comparision in the provider
+    # self.instances method match.  Otherwise this causes it to keep resetting the
+    # privileges.
+    self[:privileges] = Array(self[:privileges]).map{ |priv|
+       # split and sort the column_privileges in the parentheses and rejoin
+       if priv.include?('(')
+         type, col=priv.strip.split(/\s+|\b/,2)
+         type.upcase + " (" + col.slice(1...-1).strip.split(/\s*,\s*/).sort.join(', ') + ")"
+       else
+         priv.strip.upcase
+       end
+     }.uniq.reject{|k| k == 'GRANT' or k == 'GRANT OPTION'}.sort!
+  end
+
+  validate do
+    fail('privileges parameter is required.') if self[:ensure] == :present and self[:privileges].nil?
+    fail('table parameter is required.') if self[:ensure] == :present and self[:table].nil?
+    fail('user parameter is required.') if self[:ensure] == :present and self[:user].nil?
+    fail('name must match user and table parameters') if self[:name] != "#{self[:user]}/#{self[:table]}"
+  end
+
+  newparam(:name, :namevar => true) do
+    desc 'Name to describe the grant.'
+
+    munge do |value|
+      value.delete("'")
+    end
+  end
+
+  newproperty(:privileges, :array_matching => :all) do
+    desc 'Privileges for user'
+  end
+
+  newproperty(:table) do
+    desc 'Table to apply privileges to.'
+
+    munge do |value|
+      value.delete("`")
+    end
+
+    newvalues(/.*\..*/,/@/)
+  end
+
+  newproperty(:user) do
+    desc 'User to operate on.'
+    validate do |value|
+      # http://dev.mysql.com/doc/refman/5.5/en/identifiers.html
+      # If at least one special char is used, string must be quoted
+
+      # http://stackoverflow.com/questions/8055727/negating-a-backreference-in-regular-expressions/8057827#8057827
+      if matches = /^(['`"])((?!\1).)*\1@([\w%\.:\-\/]+)$/.match(value)
+        user_part = matches[2]
+        host_part = matches[3]
+      elsif matches = /^([0-9a-zA-Z$_]*)@([\w%\.:\-\/]+)$/.match(value)
+        user_part = matches[1]
+        host_part = matches[2]
+      elsif matches = /^((?!['`"]).*[^0-9a-zA-Z$_].*)@(.+)$/.match(value)
+        user_part = matches[1]
+        host_part = matches[2]
+      else
+        raise(ArgumentError, "Invalid database user #{value}")
+      end
+
+      mysql_version = Facter.value(:mysql_version)
+      unless mysql_version.nil?
+        if Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') < 0 and user_part.size > 16
+          raise(ArgumentError, 'MySQL usernames are limited to a maximum of 16 characters')
+        elsif Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') > 0 and user_part.size > 80
+          raise(ArgumentError, 'MySQL usernames are limited to a maximum of 80 characters')
+        end
+      end
+    end
+
+    munge do |value|
+      matches = /^((['`"]?).*\2)@(.+)$/.match(value)
+      "#{matches[1]}@#{matches[3].downcase}"
+    end
+  end
+
+  newproperty(:options, :array_matching => :all) do
+    desc 'Options to grant.'
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/type/mysql_plugin.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+Puppet::Type.newtype(:mysql_plugin) do
+  @doc = 'Manage MySQL plugins.'
+
+  ensurable
+
+  autorequire(:file) { '/root/.my.cnf' }
+
+  newparam(:name, :namevar => true) do
+    desc 'The name of the MySQL plugin to manage.'
+  end
+
+  newproperty(:soname) do
+    desc 'The name of the library'
+    newvalue(/^\w+\.\w+$/)
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/lib/puppet/type/mysql_user.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,76 @@
+# This has to be a separate type to enable collecting
+Puppet::Type.newtype(:mysql_user) do
+  @doc = 'Manage a MySQL user. This includes management of users password as well as privileges.'
+
+  ensurable
+
+  autorequire(:file) { '/root/.my.cnf' }
+  autorequire(:class) { 'mysql::server' }
+
+  newparam(:name, :namevar => true) do
+    desc "The name of the user. This uses the 'username@hostname' or username@hostname."
+    validate do |value|
+      # http://dev.mysql.com/doc/refman/5.5/en/identifiers.html
+      # If at least one special char is used, string must be quoted
+
+      # http://stackoverflow.com/questions/8055727/negating-a-backreference-in-regular-expressions/8057827#8057827
+      if matches = /^(['`"])((?:(?!\1).)*)\1@([\w%\.:\-\/]+)$/.match(value)
+        user_part = matches[2]
+        host_part = matches[3]
+      elsif matches = /^([0-9a-zA-Z$_]*)@([\w%\.:\-\/]+)$/.match(value)
+        user_part = matches[1]
+        host_part = matches[2]
+      elsif matches = /^((?!['`"]).*[^0-9a-zA-Z$_].*)@(.+)$/.match(value)
+        user_part = matches[1]
+        host_part = matches[2]
+      else
+        raise(ArgumentError, "Invalid database user #{value}")
+      end
+
+      mysql_version = Facter.value(:mysql_version)
+      unless mysql_version.nil?
+        if Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') < 0 and user_part.size > 16
+          raise(ArgumentError, 'MySQL usernames are limited to a maximum of 16 characters')
+        elsif Puppet::Util::Package.versioncmp(mysql_version, '10.0.0') > 0 and user_part.size > 80
+          raise(ArgumentError, 'MySQL usernames are limited to a maximum of 80 characters')
+        end
+      end
+    end
+
+    munge do |value|
+      matches = /^((['`"]?).*\2)@(.+)$/.match(value)
+      "#{matches[1]}@#{matches[3].downcase}"
+    end
+  end
+
+  newproperty(:password_hash) do
+    desc 'The password hash of the user. Use mysql_password() for creating such a hash.'
+    newvalue(/\w*/)
+  end
+
+  newproperty(:plugin) do
+    desc 'The authentication plugin of the user.'
+    newvalue(/\w+/)
+  end
+
+  newproperty(:max_user_connections) do
+    desc "Max concurrent connections for the user. 0 means no (or global) limit."
+    newvalue(/\d+/)
+  end
+
+  newproperty(:max_connections_per_hour) do
+    desc "Max connections per hour for the user. 0 means no (or global) limit."
+    newvalue(/\d+/)
+  end
+
+  newproperty(:max_queries_per_hour) do
+    desc "Max queries per hour for the user. 0 means no (or global) limit."
+    newvalue(/\d+/)
+  end
+
+  newproperty(:max_updates_per_hour) do
+    desc "Max updates per hour for the user. 0 means no (or global) limit."
+    newvalue(/\d+/)
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/backup/mysqlbackup.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,105 @@
+# See README.me for usage.
+class mysql::backup::mysqlbackup (
+  $backupuser         = '',
+  $backuppassword     = '',
+  $backupdir          = '',
+  $backupdirmode      = '0700',
+  $backupdirowner     = 'root',
+  $backupdirgroup     = $mysql::params::root_group,
+  $backupcompress     = true,
+  $backuprotate       = 30,
+  $ignore_events      = true,
+  $delete_before_dump = false,
+  $backupdatabases    = [],
+  $file_per_database  = false,
+  $include_triggers   = true,
+  $include_routines   = false,
+  $ensure             = 'present',
+  $time               = ['23', '5'],
+  $prescript          = false,
+  $postscript         = false,
+  $execpath           = '/usr/bin:/usr/sbin:/bin:/sbin',
+) {
+
+  mysql_user { "${backupuser}@localhost":
+    ensure        => $ensure,
+    password_hash => mysql_password($backuppassword),
+    require       => Class['mysql::server::root_password'],
+  }
+
+  package { 'meb':
+    ensure    => $ensure,
+  }
+
+  # http://dev.mysql.com/doc/mysql-enterprise-backup/3.11/en/mysqlbackup.privileges.html
+  mysql_grant { "${backupuser}@localhost/*.*":
+    ensure     => $ensure,
+    user       => "${backupuser}@localhost",
+    table      => '*.*',
+    privileges => [ 'RELOAD', 'SUPER', 'REPLICATION CLIENT' ],
+    require    => Mysql_user["${backupuser}@localhost"],
+  }
+
+  mysql_grant { "${backupuser}@localhost/mysql.backup_progress":
+    ensure     => $ensure,
+    user       => "${backupuser}@localhost",
+    table      => 'mysql.backup_progress',
+    privileges => [ 'CREATE', 'INSERT', 'DROP', 'UPDATE' ],
+    require    => Mysql_user["${backupuser}@localhost"],
+  }
+
+  mysql_grant { "${backupuser}@localhost/mysql.backup_history":
+    ensure     => $ensure,
+    user       => "${backupuser}@localhost",
+    table      => 'mysql.backup_history',
+    privileges => [ 'CREATE', 'INSERT', 'SELECT', 'DROP', 'UPDATE' ],
+    require    => Mysql_user["${backupuser}@localhost"],
+  }
+
+  cron { 'mysqlbackup-weekly':
+    ensure  => $ensure,
+    command => 'mysqlbackup backup',
+    user    => 'root',
+    hour    => $time[0],
+    minute  => $time[1],
+    weekday => 0,
+    require => Package['meb'],
+  }
+
+  cron { 'mysqlbackup-daily':
+    ensure  => $ensure,
+    command => 'mysqlbackup --incremental backup',
+    user    => 'root',
+    hour    => $time[0],
+    minute  => $time[1],
+    weekday => 1-6,
+    require => Package['meb'],
+  }
+
+  $default_options = {
+    'mysqlbackup' => {
+      'backup-dir'             => $backupdir,
+      'with-timestamp'         => true,
+      'incremental_base'       => 'history:last_backup',
+      'incremental_backup_dir' => $backupdir,
+      'user'                   => $backupuser,
+      'password'               => $backuppassword,
+    }
+  }
+  $options = mysql_deepmerge($default_options, $mysql::server::override_options)
+
+  file { 'mysqlbackup-config-file':
+    path    => '/etc/mysql/conf.d/meb.cnf',
+    content => template('mysql/meb.cnf.erb'),
+    mode    => '0600',
+  }
+
+  file { 'mysqlbackupdir':
+    ensure => 'directory',
+    path   => $backupdir,
+    mode   => $backupdirmode,
+    owner  => $backupdirowner,
+    group  => $backupdirgroup,
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/backup/mysqldump.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,70 @@
+# See README.me for usage.
+class mysql::backup::mysqldump (
+  $backupuser         = '',
+  $backuppassword     = '',
+  $backupdir          = '',
+  $backupdirmode      = '0700',
+  $backupdirowner     = 'root',
+  $backupdirgroup     = $mysql::params::root_group,
+  $backupcompress     = true,
+  $backuprotate       = 30,
+  $ignore_events      = true,
+  $delete_before_dump = false,
+  $backupdatabases    = [],
+  $file_per_database  = false,
+  $include_triggers   = false,
+  $include_routines   = false,
+  $ensure             = 'present',
+  $time               = ['23', '5'],
+  $prescript          = false,
+  $postscript         = false,
+  $execpath           = '/usr/bin:/usr/sbin:/bin:/sbin',
+) {
+
+  mysql_user { "${backupuser}@localhost":
+    ensure        => $ensure,
+    password_hash => mysql_password($backuppassword),
+    require       => Class['mysql::server::root_password'],
+  }
+
+  if $include_triggers  {
+    $privs = [ 'SELECT', 'RELOAD', 'LOCK TABLES', 'SHOW VIEW', 'PROCESS', 'TRIGGER' ]
+  } else {
+    $privs = [ 'SELECT', 'RELOAD', 'LOCK TABLES', 'SHOW VIEW', 'PROCESS' ]
+  }
+
+  mysql_grant { "${backupuser}@localhost/*.*":
+    ensure     => $ensure,
+    user       => "${backupuser}@localhost",
+    table      => '*.*',
+    privileges => $privs,
+    require    => Mysql_user["${backupuser}@localhost"],
+  }
+
+  cron { 'mysql-backup':
+    ensure  => $ensure,
+    command => '/usr/local/sbin/mysqlbackup.sh',
+    user    => 'root',
+    hour    => $time[0],
+    minute  => $time[1],
+    require => File['mysqlbackup.sh'],
+  }
+
+  file { 'mysqlbackup.sh':
+    ensure  => $ensure,
+    path    => '/usr/local/sbin/mysqlbackup.sh',
+    mode    => '0700',
+    owner   => 'root',
+    group   => $mysql::params::root_group,
+    content => template('mysql/mysqlbackup.sh.erb'),
+  }
+
+  file { 'mysqlbackupdir':
+    ensure => 'directory',
+    path   => $backupdir,
+    mode   => $backupdirmode,
+    owner  => $backupdirowner,
+    group  => $backupdirgroup,
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/backup/xtrabackup.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,65 @@
+# See README.me for usage.
+class mysql::backup::xtrabackup (
+  $backupuser         = '',
+  $backuppassword     = '',
+  $backupdir          = '',
+  $backupmethod       = 'mysqldump',
+  $backupdirmode      = '0700',
+  $backupdirowner     = 'root',
+  $backupdirgroup     = $mysql::params::root_group,
+  $backupcompress     = true,
+  $backuprotate       = 30,
+  $ignore_events      = true,
+  $delete_before_dump = false,
+  $backupdatabases    = [],
+  $file_per_database  = false,
+  $include_triggers   = true,
+  $include_routines   = false,
+  $ensure             = 'present',
+  $time               = ['23', '5'],
+  $prescript          = false,
+  $postscript         = false,
+  $execpath           = '/usr/bin:/usr/sbin:/bin:/sbin',
+) {
+
+  package{ 'percona-xtrabackup':
+    ensure  => $ensure,
+  }
+
+  cron { 'xtrabackup-weekly':
+    ensure  => $ensure,
+    command => "/usr/local/sbin/xtrabackup.sh ${backupdir}",
+    user    => 'root',
+    hour    => $time[0],
+    minute  => $time[1],
+    weekday => 0,
+    require => Package['percona-xtrabackup'],
+  }
+
+  cron { 'xtrabackup-daily':
+    ensure  => $ensure,
+    command => "/usr/local/sbin/xtrabackup.sh --incremental ${backupdir}",
+    user    => 'root',
+    hour    => $time[0],
+    minute  => $time[1],
+    weekday => 1-6,
+    require => Package['percona-xtrabackup'],
+  }
+
+  file { 'mysqlbackupdir':
+    ensure => 'directory',
+    path   => $backupdir,
+    mode   => $backupdirmode,
+    owner  => $backupdirowner,
+    group  => $backupdirgroup,
+  }
+
+  file { 'xtrabackup.sh':
+    ensure  => $ensure,
+    path    => '/usr/local/sbin/xtrabackup.sh',
+    mode    => '0700',
+    owner   => 'root',
+    group   => $mysql::params::root_group,
+    content => template('mysql/xtrabackup.sh.erb'),
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/bindings.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,57 @@
+# See README.md.
+class mysql::bindings (
+  $install_options = undef,
+  # Boolean to determine if we should include the classes.
+  $java_enable     = false,
+  $perl_enable     = false,
+  $php_enable      = false,
+  $python_enable   = false,
+  $ruby_enable     = false,
+  $client_dev      = false,
+  $daemon_dev      = false,
+  # Settings for the various classes.
+  $java_package_ensure         = $mysql::params::java_package_ensure,
+  $java_package_name           = $mysql::params::java_package_name,
+  $java_package_provider       = $mysql::params::java_package_provider,
+  $perl_package_ensure         = $mysql::params::perl_package_ensure,
+  $perl_package_name           = $mysql::params::perl_package_name,
+  $perl_package_provider       = $mysql::params::perl_package_provider,
+  $php_package_ensure          = $mysql::params::php_package_ensure,
+  $php_package_name            = $mysql::params::php_package_name,
+  $php_package_provider        = $mysql::params::php_package_provider,
+  $python_package_ensure       = $mysql::params::python_package_ensure,
+  $python_package_name         = $mysql::params::python_package_name,
+  $python_package_provider     = $mysql::params::python_package_provider,
+  $ruby_package_ensure         = $mysql::params::ruby_package_ensure,
+  $ruby_package_name           = $mysql::params::ruby_package_name,
+  $ruby_package_provider       = $mysql::params::ruby_package_provider,
+  $client_dev_package_ensure   = $mysql::params::client_dev_package_ensure,
+  $client_dev_package_name     = $mysql::params::client_dev_package_name,
+  $client_dev_package_provider = $mysql::params::client_dev_package_provider,
+  $daemon_dev_package_ensure   = $mysql::params::daemon_dev_package_ensure,
+  $daemon_dev_package_name     = $mysql::params::daemon_dev_package_name,
+  $daemon_dev_package_provider = $mysql::params::daemon_dev_package_provider
+) inherits mysql::params {
+
+  case $::osfamily {
+    'Archlinux': {
+      if $java_enable   { fail("::mysql::bindings::java cannot be managed by puppet on ${::osfamily} as it is not in official repositories. Please disable java mysql binding.") }
+      if $perl_enable   { include '::mysql::bindings::perl' }
+      if $php_enable    { warning("::mysql::bindings::php does not need to be managed by puppet on ${::osfamily} as it is included in mysql package by default.") }
+      if $python_enable { include '::mysql::bindings::python' }
+      if $ruby_enable   { fail("::mysql::bindings::ruby cannot be managed by puppet on ${::osfamily} as it is not in official repositories. Please disable ruby mysql binding.") }
+    }
+
+    default: {
+      if $java_enable   { include '::mysql::bindings::java' }
+      if $perl_enable   { include '::mysql::bindings::perl' }
+      if $php_enable    { include '::mysql::bindings::php' }
+      if $python_enable { include '::mysql::bindings::python' }
+      if $ruby_enable   { include '::mysql::bindings::ruby' }
+    }
+  }
+
+  if $client_dev    { include '::mysql::bindings::client_dev' }
+  if $daemon_dev    { include '::mysql::bindings::daemon_dev' }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/bindings/client_dev.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+# Private class
+class mysql::bindings::client_dev {
+
+  if $mysql::bindings::client_dev_package_name {
+    package { 'mysql-client_dev':
+      ensure          => $mysql::bindings::client_dev_package_ensure,
+      install_options => $mysql::bindings::install_options,
+      name            => $mysql::bindings::client_dev_package_name,
+      provider        => $mysql::bindings::client_dev_package_provider,
+    }
+  } else {
+    warning("No MySQL client development package configured for ${::operatingsystem}.")
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/bindings/daemon_dev.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+# Private class
+class mysql::bindings::daemon_dev {
+
+  if $mysql::bindings::daemon_dev_package_name {
+    package { 'mysql-daemon_dev':
+      ensure          => $mysql::bindings::daemon_dev_package_ensure,
+      install_options => $mysql::bindings::install_options,
+      name            => $mysql::bindings::daemon_dev_package_name,
+      provider        => $mysql::bindings::daemon_dev_package_provider,
+    }
+  } else {
+    warning("No MySQL daemon development package configured for ${::operatingsystem}.")
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/bindings/java.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+# Private class
+class mysql::bindings::java {
+
+  package { 'mysql-connector-java':
+    ensure          => $mysql::bindings::java_package_ensure,
+    install_options => $mysql::bindings::install_options,
+    name            => $mysql::bindings::java_package_name,
+    provider        => $mysql::bindings::java_package_provider,
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/bindings/perl.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+# Private class
+class mysql::bindings::perl {
+
+  package{ 'perl_mysql':
+    ensure          => $mysql::bindings::perl_package_ensure,
+    install_options => $mysql::bindings::install_options,
+    name            => $mysql::bindings::perl_package_name,
+    provider        => $mysql::bindings::perl_package_provider,
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/bindings/php.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+# Private class: See README.md
+class mysql::bindings::php {
+
+  package { 'php-mysql':
+    ensure          => $mysql::bindings::php_package_ensure,
+    install_options => $mysql::bindings::install_options,
+    name            => $mysql::bindings::php_package_name,
+    provider        => $mysql::bindings::php_package_provider,
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/bindings/python.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+# Private class
+class mysql::bindings::python {
+
+  package { 'python-mysqldb':
+    ensure          => $mysql::bindings::python_package_ensure,
+    install_options => $mysql::bindings::install_options,
+    name            => $mysql::bindings::python_package_name,
+    provider        => $mysql::bindings::python_package_provider,
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/bindings/ruby.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+# Private class
+class mysql::bindings::ruby {
+
+  package{ 'ruby_mysql':
+    ensure          => $mysql::bindings::ruby_package_ensure,
+    install_options => $mysql::bindings::install_options,
+    name            => $mysql::bindings::ruby_package_name,
+    provider        => $mysql::bindings::ruby_package_provider,
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/client.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,29 @@
+#
+class mysql::client (
+  $bindings_enable = $mysql::params::bindings_enable,
+  $install_options = undef,
+  $package_ensure  = $mysql::params::client_package_ensure,
+  $package_manage  = $mysql::params::client_package_manage,
+  $package_name    = $mysql::params::client_package_name,
+) inherits mysql::params {
+
+  include '::mysql::client::install'
+
+  if $bindings_enable {
+    class { 'mysql::bindings':
+      java_enable   => true,
+      perl_enable   => true,
+      php_enable    => true,
+      python_enable => true,
+      ruby_enable   => true,
+    }
+  }
+
+
+  # Anchor pattern workaround to avoid resources of mysql::client::install to
+  # "float off" outside mysql::client
+  anchor { 'mysql::client::start': } ->
+    Class['mysql::client::install'] ->
+  anchor { 'mysql::client::end': }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/client/install.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+# See README.md.
+class mysql::client::install {
+
+  if $mysql::client::package_manage {
+
+    package { 'mysql_client':
+      ensure          => $mysql::client::package_ensure,
+      install_options => $mysql::client::install_options,
+      name            => $mysql::client::package_name,
+    }
+
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/db.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,75 @@
+# See README.md for details.
+define mysql::db (
+  $user,
+  $password,
+  $dbname         = $name,
+  $charset        = 'utf8',
+  $collate        = 'utf8_general_ci',
+  $host           = 'localhost',
+  $grant          = 'ALL',
+  $sql            = undef,
+  $enforce_sql    = false,
+  $ensure         = 'present',
+  $import_timeout = 300,
+) {
+  #input validation
+  validate_re($ensure, '^(present|absent)$',
+  "${ensure} is not supported for ensure. Allowed values are 'present' and 'absent'.")
+  $table = "${dbname}.*"
+
+  if !(is_array($sql) or is_string($sql)) {
+    fail('$sql must be either a string or an array.')
+  }
+
+  $sql_inputs = join([$sql], ' ')
+
+  include '::mysql::client'
+
+  anchor{"mysql::db_${name}::begin": }->
+  Class['::mysql::client']->
+  anchor{"mysql::db_${name}::end": }
+
+  $db_resource = {
+    ensure   => $ensure,
+    charset  => $charset,
+    collate  => $collate,
+    provider => 'mysql',
+    require  => [ Class['mysql::client'] ],
+  }
+  ensure_resource('mysql_database', $dbname, $db_resource)
+
+  $user_resource = {
+    ensure        => $ensure,
+    password_hash => mysql_password($password),
+    provider      => 'mysql',
+  }
+  ensure_resource('mysql_user', "${user}@${host}", $user_resource)
+
+  if $ensure == 'present' {
+    mysql_grant { "${user}@${host}/${table}":
+      privileges => $grant,
+      provider   => 'mysql',
+      user       => "${user}@${host}",
+      table      => $table,
+      require    => [
+        Mysql_database[$dbname],
+        Mysql_user["${user}@${host}"],
+      ],
+    }
+
+    $refresh = ! $enforce_sql
+
+    if $sql {
+      exec{ "${dbname}-import":
+        command     => "cat ${sql_inputs} | mysql ${dbname}",
+        logoutput   => true,
+        environment => "HOME=${::root_home}",
+        refreshonly => $refresh,
+        path        => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin',
+        require     => Mysql_grant["${user}@${host}/${table}"],
+        subscribe   => Mysql_database[$dbname],
+        timeout     => $import_timeout,
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/params.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,411 @@
+# Private class: See README.md.
+class mysql::params {
+
+  $manage_config_file     = true
+  $purge_conf_dir         = false
+  $restart                = false
+  $root_password          = 'UNSET'
+  $install_secret_file    = '/.mysql_secret'
+  $server_package_ensure  = 'present'
+  $server_package_manage  = true
+  $server_service_manage  = true
+  $server_service_enabled = true
+  $client_package_ensure  = 'present'
+  $client_package_manage  = true
+  $create_root_user       = true
+  $create_root_my_cnf     = true
+  # mysql::bindings
+  $bindings_enable             = false
+  $java_package_ensure         = 'present'
+  $java_package_provider       = undef
+  $perl_package_ensure         = 'present'
+  $perl_package_provider       = undef
+  $php_package_ensure          = 'present'
+  $php_package_provider        = undef
+  $python_package_ensure       = 'present'
+  $python_package_provider     = undef
+  $ruby_package_ensure         = 'present'
+  $ruby_package_provider       = undef
+  $client_dev_package_ensure   = 'present'
+  $client_dev_package_provider = undef
+  $daemon_dev_package_ensure   = 'present'
+  $daemon_dev_package_provider = undef
+
+
+  case $::osfamily {
+    'RedHat': {
+      case $::operatingsystem {
+        'Fedora': {
+          if versioncmp($::operatingsystemrelease, '19') >= 0 or $::operatingsystemrelease == 'Rawhide' {
+            $provider = 'mariadb'
+          } else {
+            $provider = 'mysql'
+          }
+        }
+        /^(RedHat|CentOS|Scientific|OracleLinux)$/: {
+          if versioncmp($::operatingsystemmajrelease, '7') >= 0 {
+            $provider = 'mariadb'
+          } else {
+            $provider = 'mysql'
+          }
+        }
+        default: {
+          $provider = 'mysql'
+        }
+      }
+
+      if $provider == 'mariadb' {
+        $client_package_name = 'mariadb'
+        $server_package_name = 'mariadb-server'
+        $server_service_name = 'mariadb'
+        $log_error           = '/var/log/mariadb/mariadb.log'
+        $config_file         = '/etc/my.cnf.d/server.cnf'
+        # mariadb package by default has !includedir set in my.cnf to /etc/my.cnf.d
+        $includedir          = undef
+        $pidfile             = '/var/run/mariadb/mariadb.pid'
+      } else {
+        $client_package_name = 'mysql'
+        $server_package_name = 'mysql-server'
+        $server_service_name = 'mysqld'
+        $log_error           = '/var/log/mysqld.log'
+        $config_file         = '/etc/my.cnf'
+        $includedir          = '/etc/my.cnf.d'
+        $pidfile             = '/var/run/mysqld/mysqld.pid'
+      }
+
+      $basedir                 = '/usr'
+      $datadir                 = '/var/lib/mysql'
+      $root_group              = 'root'
+      $mysql_group             = 'mysql'
+      $socket                  = '/var/lib/mysql/mysql.sock'
+      $ssl_ca                  = '/etc/mysql/cacert.pem'
+      $ssl_cert                = '/etc/mysql/server-cert.pem'
+      $ssl_key                 = '/etc/mysql/server-key.pem'
+      $tmpdir                  = '/tmp'
+      # mysql::bindings
+      $java_package_name       = 'mysql-connector-java'
+      $perl_package_name       = 'perl-DBD-MySQL'
+      $php_package_name        = 'php-mysql'
+      $python_package_name     = 'MySQL-python'
+      $ruby_package_name       = 'ruby-mysql'
+      $client_dev_package_name = undef
+      $daemon_dev_package_name = 'mysql-devel'
+    }
+
+    'Suse': {
+      case $::operatingsystem {
+        'OpenSuSE': {
+          $client_package_name = 'mysql-community-server-client'
+          $server_package_name = 'mysql-community-server'
+          $basedir             = '/usr'
+        }
+        'SLES','SLED': {
+          if versioncmp($::operatingsystemrelease, '12') >= 0 {
+            $client_package_name = 'mariadb-client'
+            $server_package_name = 'mariadb'
+            $basedir             = undef
+          } else {
+            $client_package_name = 'mysql-client'
+            $server_package_name = 'mysql'
+            $basedir             = '/usr'
+          }
+        }
+        default: {
+          fail("Unsupported platform: puppetlabs-${module_name} currently doesn't support ${::operatingsystem}")
+        }
+      }
+      $config_file         = '/etc/my.cnf'
+      $includedir          = '/etc/my.cnf.d'
+      $datadir             = '/var/lib/mysql'
+      $log_error           = $::operatingsystem ? {
+        /OpenSuSE/         => '/var/log/mysql/mysqld.log',
+        /(SLES|SLED)/      => '/var/log/mysqld.log',
+      }
+      $pidfile             = $::operatingsystem ? {
+        /OpenSuSE/         => '/var/run/mysql/mysqld.pid',
+        /(SLES|SLED)/      => '/var/lib/mysql/mysqld.pid',
+      }
+      $root_group          = 'root'
+      $mysql_group         = 'mysql'
+      $server_service_name = 'mysql'
+      $socket              = $::operatingsystem ? {
+        /OpenSuSE/         => '/var/run/mysql/mysql.sock',
+        /(SLES|SLED)/      => '/var/lib/mysql/mysql.sock',
+      }
+      $ssl_ca              = '/etc/mysql/cacert.pem'
+      $ssl_cert            = '/etc/mysql/server-cert.pem'
+      $ssl_key             = '/etc/mysql/server-key.pem'
+      $tmpdir              = '/tmp'
+      # mysql::bindings
+      $java_package_name   = 'mysql-connector-java'
+      $perl_package_name   = 'perl-DBD-mysql'
+      $php_package_name    = 'apache2-mod_php53'
+      $python_package_name = 'python-mysql'
+      $ruby_package_name   = $::operatingsystem ? {
+        /OpenSuSE/         => 'rubygem-mysql',
+        /(SLES|SLED)/      => 'ruby-mysql',
+      }
+      $client_dev_package_name = 'libmysqlclient-devel'
+      $daemon_dev_package_name = 'mysql-devel'
+    }
+
+    'Debian': {
+      $client_package_name     = 'mysql-client'
+      $server_package_name     = 'mysql-server'
+
+      $basedir                 = '/usr'
+      $config_file             = '/etc/mysql/my.cnf'
+      $includedir              = '/etc/mysql/conf.d'
+      $datadir                 = '/var/lib/mysql'
+      $log_error               = '/var/log/mysql/error.log'
+      $pidfile                 = '/var/run/mysqld/mysqld.pid'
+      $root_group              = 'root'
+      $mysql_group             = 'mysql'
+      $server_service_name     = 'mysql'
+      $socket                  = '/var/run/mysqld/mysqld.sock'
+      $ssl_ca                  = '/etc/mysql/cacert.pem'
+      $ssl_cert                = '/etc/mysql/server-cert.pem'
+      $ssl_key                 = '/etc/mysql/server-key.pem'
+      $tmpdir                  = '/tmp'
+      # mysql::bindings
+      $java_package_name   = 'libmysql-java'
+      $perl_package_name   = 'libdbd-mysql-perl'
+      $php_package_name    = 'php5-mysql'
+      $python_package_name = 'python-mysqldb'
+      $ruby_package_name   = $::lsbdistcodename ? {
+        'trusty'           => 'ruby-mysql',
+        'jessie'           => 'ruby-mysql',
+        default            => 'libmysql-ruby',
+      }
+      $client_dev_package_name = 'libmysqlclient-dev'
+      $daemon_dev_package_name = 'libmysqld-dev'
+    }
+
+    'Archlinux': {
+      $client_package_name = 'mariadb-clients'
+      $server_package_name = 'mariadb'
+      $basedir             = '/usr'
+      $config_file         = '/etc/mysql/my.cnf'
+      $datadir             = '/var/lib/mysql'
+      $log_error           = '/var/log/mysqld.log'
+      $pidfile             = '/var/run/mysqld/mysqld.pid'
+      $root_group          = 'root'
+      $mysql_group         = 'mysql'
+      $server_service_name = 'mysqld'
+      $socket              = '/var/lib/mysql/mysql.sock'
+      $ssl_ca              = '/etc/mysql/cacert.pem'
+      $ssl_cert            = '/etc/mysql/server-cert.pem'
+      $ssl_key             = '/etc/mysql/server-key.pem'
+      $tmpdir              = '/tmp'
+      # mysql::bindings
+      $java_package_name   = 'mysql-connector-java'
+      $perl_package_name   = 'perl-dbd-mysql'
+      $php_package_name    = undef
+      $python_package_name = 'mysql-python'
+      $ruby_package_name   = 'mysql-ruby'
+    }
+
+    'Gentoo': {
+      $client_package_name = 'virtual/mysql'
+      $server_package_name = 'virtual/mysql'
+      $basedir             = '/usr'
+      $config_file         = '/etc/mysql/my.cnf'
+      $datadir             = '/var/lib/mysql'
+      $log_error           = '/var/log/mysql/mysqld.err'
+      $pidfile             = '/run/mysqld/mysqld.pid'
+      $root_group          = 'root'
+      $mysql_group         = 'mysql'
+      $server_service_name = 'mysql'
+      $socket              = '/run/mysqld/mysqld.sock'
+      $ssl_ca              = '/etc/mysql/cacert.pem'
+      $ssl_cert            = '/etc/mysql/server-cert.pem'
+      $ssl_key             = '/etc/mysql/server-key.pem'
+      $tmpdir              = '/tmp'
+      # mysql::bindings
+      $java_package_name   = 'dev-java/jdbc-mysql'
+      $perl_package_name   = 'dev-perl/DBD-mysql'
+      $php_package_name    = undef
+      $python_package_name = 'dev-python/mysql-python'
+      $ruby_package_name   = 'dev-ruby/mysql-ruby'
+    }
+
+    'FreeBSD': {
+      $client_package_name = 'databases/mysql56-client'
+      $server_package_name = 'databases/mysql56-server'
+      $basedir             = '/usr/local'
+      $config_file         = '/usr/local/etc/my.cnf'
+      $includedir          = '/usr/local/etc/my.cnf.d'
+      $datadir             = '/var/db/mysql'
+      $log_error           = '/var/log/mysqld.log'
+      $pidfile             = '/var/run/mysql.pid'
+      $root_group          = 'wheel'
+      $mysql_group         = 'mysql'
+      $server_service_name = 'mysql-server'
+      $socket              = '/var/db/mysql/mysql.sock'
+      $ssl_ca              = undef
+      $ssl_cert            = undef
+      $ssl_key             = undef
+      $tmpdir              = '/tmp'
+      # mysql::bindings
+      $java_package_name   = 'databases/mysql-connector-java'
+      $perl_package_name   = 'p5-DBD-mysql'
+      $php_package_name    = 'php5-mysql'
+      $python_package_name = 'databases/py-MySQLdb'
+      $ruby_package_name   = 'databases/ruby-mysql'
+      # The libraries installed by these packages are included in client and server packages, no installation required.
+      $client_dev_package_name     = undef
+      $daemon_dev_package_name     = undef
+    }
+
+    'OpenBSD': {
+      $client_package_name = 'mariadb-client'
+      $server_package_name = 'mariadb-server'
+      $basedir             = '/usr/local'
+      $config_file         = '/etc/my.cnf'
+      $includedir          = undef
+      $datadir             = '/var/mysql'
+      $log_error           = "/var/mysql/${::hostname}.err"
+      $pidfile             = '/var/mysql/mysql.pid'
+      $root_group          = 'wheel'
+      $mysql_group         = '_mysql'
+      $server_service_name = 'mysqld'
+      $socket              = '/var/run/mysql/mysql.sock'
+      $ssl_ca              = undef
+      $ssl_cert            = undef
+      $ssl_key             = undef
+      $tmpdir              = '/tmp'
+      # mysql::bindings
+      $java_package_name   = undef
+      $perl_package_name   = 'p5-DBD-mysql'
+      $php_package_name    = 'php-mysql'
+      $python_package_name = 'py-mysql'
+      $ruby_package_name   = 'ruby-mysql'
+      # The libraries installed by these packages are included in client and server packages, no installation required.
+      $client_dev_package_name     = undef
+      $daemon_dev_package_name     = undef
+    }
+
+    'Solaris': {
+      $client_package_name = 'database/mysql-55/client'
+      $server_package_name = 'database/mysql-55'
+      $basedir             = undef
+      $config_file         = '/etc/mysql/5.5/my.cnf'
+      $datadir             = '/var/mysql/5.5/data'
+      $log_error           = "/var/mysql/5.5/data/${::hostname}.err"
+      $pidfile             = "/var/mysql/5.5/data/${::hostname}.pid"
+      $root_group          = 'bin'
+      $server_service_name = 'application/database/mysql:version_55'
+      $socket              = '/tmp/mysql.sock'
+      $ssl_ca              = undef
+      $ssl_cert            = undef
+      $ssl_key             = undef
+      $tmpdir              = '/tmp'
+      # mysql::bindings
+      $java_package_name   = undef
+      $perl_package_name   = undef
+      $php_package_name    = 'web/php-53/extension/php-mysql'
+      $python_package_name = 'library/python/python-mysql'
+      $ruby_package_name   = undef
+      # The libraries installed by these packages are included in client and server packages, no installation required.
+      $client_dev_package_name     = undef
+      $daemon_dev_package_name     = undef
+    }
+
+    default: {
+      case $::operatingsystem {
+        'Amazon': {
+          $client_package_name = 'mysql'
+          $server_package_name = 'mysql-server'
+          $basedir             = '/usr'
+          $config_file         = '/etc/my.cnf'
+          $includedir          = '/etc/my.cnf.d'
+          $datadir             = '/var/lib/mysql'
+          $log_error           = '/var/log/mysqld.log'
+          $pidfile             = '/var/run/mysqld/mysqld.pid'
+          $root_group          = 'root'
+          $mysql_group         = 'mysql'
+          $server_service_name = 'mysqld'
+          $socket              = '/var/lib/mysql/mysql.sock'
+          $ssl_ca              = '/etc/mysql/cacert.pem'
+          $ssl_cert            = '/etc/mysql/server-cert.pem'
+          $ssl_key             = '/etc/mysql/server-key.pem'
+          $tmpdir              = '/tmp'
+          # mysql::bindings
+          $java_package_name   = 'mysql-connector-java'
+          $perl_package_name   = 'perl-DBD-MySQL'
+          $php_package_name    = 'php-mysql'
+          $python_package_name = 'MySQL-python'
+          $ruby_package_name   = 'ruby-mysql'
+          # The libraries installed by these packages are included in client and server packages, no installation required.
+          $client_dev_package_name     = undef
+          $daemon_dev_package_name     = undef
+        }
+
+        default: {
+          fail("Unsupported platform: puppetlabs-${module_name} currently doesn't support ${::osfamily} or ${::operatingsystem}")
+        }
+      }
+    }
+  }
+
+  case $::operatingsystem {
+    'Ubuntu': {
+      $server_service_provider = upstart
+    }
+    default: {
+      $server_service_provider = undef
+    }
+  }
+
+  $default_options = {
+    'client'          => {
+      'port'          => '3306',
+      'socket'        => $mysql::params::socket,
+    },
+    'mysqld_safe'        => {
+      'nice'             => '0',
+      'log-error'        => $mysql::params::log_error,
+      'socket'           => $mysql::params::socket,
+    },
+    'mysqld'                  => {
+      'basedir'               => $mysql::params::basedir,
+      'bind-address'          => '127.0.0.1',
+      'datadir'               => $mysql::params::datadir,
+      'expire_logs_days'      => '10',
+      'key_buffer_size'       => '16M',
+      'log-error'             => $mysql::params::log_error,
+      'max_allowed_packet'    => '16M',
+      'max_binlog_size'       => '100M',
+      'max_connections'       => '151',
+      'myisam_recover'        => 'BACKUP',
+      'pid-file'              => $mysql::params::pidfile,
+      'port'                  => '3306',
+      'query_cache_limit'     => '1M',
+      'query_cache_size'      => '16M',
+      'skip-external-locking' => true,
+      'socket'                => $mysql::params::socket,
+      'ssl'                   => false,
+      'ssl-ca'                => $mysql::params::ssl_ca,
+      'ssl-cert'              => $mysql::params::ssl_cert,
+      'ssl-key'               => $mysql::params::ssl_key,
+      'ssl-disable'           => false,
+      'thread_cache_size'     => '8',
+      'thread_stack'          => '256K',
+      'tmpdir'                => $mysql::params::tmpdir,
+      'user'                  => 'mysql',
+    },
+    'mysqldump'             => {
+      'max_allowed_packet'  => '16M',
+      'quick'               => true,
+      'quote-names'         => true,
+    },
+    'isamchk'      => {
+      'key_buffer_size' => '16M',
+    },
+  }
+
+  ## Additional graceful failures
+  if $::osfamily == 'RedHat' and $::operatingsystemmajrelease == '4' {
+    fail("Unsupported platform: puppetlabs-${module_name} only supports RedHat 5.0 and beyond")
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/server.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,87 @@
+# Class: mysql::server:  See README.md for documentation.
+class mysql::server (
+  $config_file             = $mysql::params::config_file,
+  $includedir              = $mysql::params::includedir,
+  $install_options         = undef,
+  $install_secret_file     = $mysql::params::install_secret_file,
+  $manage_config_file      = $mysql::params::manage_config_file,
+  $override_options        = {},
+  $package_ensure          = $mysql::params::server_package_ensure,
+  $package_manage          = $mysql::params::server_package_manage,
+  $package_name            = $mysql::params::server_package_name,
+  $purge_conf_dir          = $mysql::params::purge_conf_dir,
+  $remove_default_accounts = false,
+  $restart                 = $mysql::params::restart,
+  $root_group              = $mysql::params::root_group,
+  $mysql_group             = $mysql::params::mysql_group,
+  $root_password           = $mysql::params::root_password,
+  $service_enabled         = $mysql::params::server_service_enabled,
+  $service_manage          = $mysql::params::server_service_manage,
+  $service_name            = $mysql::params::server_service_name,
+  $service_provider        = $mysql::params::server_service_provider,
+  $create_root_user        = $mysql::params::create_root_user,
+  $create_root_my_cnf      = $mysql::params::create_root_my_cnf,
+  $users                   = {},
+  $grants                  = {},
+  $databases               = {},
+
+  # Deprecated parameters
+  $enabled                 = undef,
+  $manage_service          = undef,
+  $old_root_password       = undef
+) inherits mysql::params {
+
+  # Deprecated parameters.
+  if $enabled {
+    crit('This parameter has been renamed to service_enabled.')
+    $real_service_enabled = $enabled
+  } else {
+    $real_service_enabled = $service_enabled
+  }
+  if $manage_service {
+    crit('This parameter has been renamed to service_manage.')
+    $real_service_manage = $manage_service
+  } else {
+    $real_service_manage = $service_manage
+  }
+  if $old_root_password {
+    warning('old_root_password is no longer used and will be removed in a future release')
+  }
+
+  # Create a merged together set of options.  Rightmost hashes win over left.
+  $options = mysql_deepmerge($mysql::params::default_options, $override_options)
+
+  Class['mysql::server::root_password'] -> Mysql::Db <| |>
+
+  include '::mysql::server::install'
+  include '::mysql::server::config'
+  include '::mysql::server::installdb'
+  include '::mysql::server::service'
+  include '::mysql::server::root_password'
+  include '::mysql::server::providers'
+
+  if $remove_default_accounts {
+    class { '::mysql::server::account_security':
+      require => Anchor['mysql::server::end'],
+    }
+  }
+
+  anchor { 'mysql::server::start': }
+  anchor { 'mysql::server::end': }
+
+  if $restart {
+    Class['mysql::server::config'] ~>
+    Class['mysql::server::service']
+  }
+
+  Anchor['mysql::server::start'] ->
+  Class['mysql::server::install'] ->
+  Class['mysql::server::config'] ->
+  Class['mysql::server::installdb'] ->
+  Class['mysql::server::service'] ->
+  Class['mysql::server::root_password'] ->
+  Class['mysql::server::providers'] ->
+  Anchor['mysql::server::end']
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/server/account_security.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+# See README.md.
+class mysql::server::account_security {
+  mysql_user {
+    [ 'root@127.0.0.1',
+      'root@::1',
+      '@localhost',
+      '@%']:
+    ensure  => 'absent',
+    require => Anchor['mysql::server::end'],
+  }
+  if ($::fqdn != 'localhost.localdomain') {
+    mysql_user {
+      [ 'root@localhost.localdomain',
+        '@localhost.localdomain']:
+      ensure  => 'absent',
+      require => Anchor['mysql::server::end'],
+    }
+  }
+  if ($::fqdn != 'localhost') {
+    mysql_user {
+      [ "root@${::fqdn}",
+        "@${::fqdn}"]:
+      ensure  => 'absent',
+      require => Anchor['mysql::server::end'],
+    }
+  }
+  if ($::fqdn != $::hostname) {
+    if ($::hostname != 'localhost') {
+      mysql_user { ["root@${::hostname}", "@${::hostname}"]:
+        ensure  => 'absent',
+        require => Anchor['mysql::server::end'],
+      }
+    }
+  }
+  mysql_database { 'test':
+    ensure  => 'absent',
+    require => Anchor['mysql::server::end'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/server/backup.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,53 @@
+# See README.me for usage.
+class mysql::server::backup (
+  $backupuser         = undef,
+  $backuppassword     = undef,
+  $backupdir          = undef,
+  $backupdirmode      = '0700',
+  $backupdirowner     = 'root',
+  $backupdirgroup     = 'root',
+  $backupcompress     = true,
+  $backuprotate       = 30,
+  $ignore_events      = true,
+  $delete_before_dump = false,
+  $backupdatabases    = [],
+  $file_per_database  = false,
+  $include_routines   = false,
+  $include_triggers   = false,
+  $ensure             = 'present',
+  $time               = ['23', '5'],
+  $prescript          = false,
+  $postscript         = false,
+  $execpath           = '/usr/bin:/usr/sbin:/bin:/sbin',
+  $provider           = 'mysqldump',
+) {
+
+  if $prescript and $provider =~ /(mysqldump|mysqlbackup)/ {
+    warning("The \$prescript option is not currently implemented for the ${provider} backup provider.")
+  }
+
+  create_resources('class', {
+    "mysql::backup::${provider}" => {
+      'backupuser'         => $backupuser,
+      'backuppassword'     => $backuppassword,
+      'backupdir'          => $backupdir,
+      'backupdirmode'      => $backupdirmode,
+      'backupdirowner'     => $backupdirowner,
+      'backupdirgroup'     => $backupdirgroup,
+      'backupcompress'     => $backupcompress,
+      'backuprotate'       => $backuprotate,
+      'ignore_events'      => $ignore_events,
+      'delete_before_dump' => $delete_before_dump,
+      'backupdatabases'    => $backupdatabases,
+      'file_per_database'  => $file_per_database,
+      'include_routines'   => $include_routines,
+      'include_triggers'   => $include_triggers,
+      'ensure'             => $ensure,
+      'time'               => $time,
+      'prescript'          => $prescript,
+      'postscript'         => $postscript,
+      'execpath'           => $execpath,
+    }
+  })
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/server/config.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,52 @@
+# See README.me for options.
+class mysql::server::config {
+
+  $options = $mysql::server::options
+  $includedir = $mysql::server::includedir
+
+  File {
+    owner  => 'root',
+    group  => $mysql::server::root_group,
+    mode   => '0400',
+  }
+
+  if $includedir and $includedir != '' {
+    file { $includedir:
+      ensure  => directory,
+      mode    => '0755',
+      recurse => $mysql::server::purge_conf_dir,
+      purge   => $mysql::server::purge_conf_dir,
+    }
+  }
+
+  $logbin = pick($options['mysqld']['log-bin'], $options['mysqld']['log_bin'], false)
+
+  if $logbin {
+    $logbindir = mysql_dirname($logbin)
+
+    #Stop puppet from managing directory if just a filename/prefix is specified
+    if $logbindir != '.' {
+      file { $logbindir:
+        ensure => directory,
+        mode   => '0755',
+        owner  => $options['mysqld']['user'],
+        group  => $options['mysqld']['user'],
+      }
+    }
+  }
+
+  if $mysql::server::manage_config_file  {
+    file { 'mysql-config-file':
+      path                    => $mysql::server::config_file,
+      content                 => template('mysql/my.cnf.erb'),
+      mode                    => '0644',
+      selinux_ignore_defaults => true,
+    }
+  }
+
+  if $options['mysqld']['ssl-disable'] {
+    notify {'ssl-disable':
+      message =>'Disabling SSL is evil! You should never ever do this except if you are forced to use a mysql version compiled without SSL support'
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/server/install.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+#
+class mysql::server::install {
+
+  if $mysql::server::package_manage {
+
+    package { 'mysql-server':
+      ensure          => $mysql::server::package_ensure,
+      install_options => $mysql::server::install_options,
+      name            => $mysql::server::package_name,
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/server/installdb.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+#
+class mysql::server::installdb {
+
+  if $mysql::server::package_manage {
+
+    # Build the initial databases.
+    $mysqluser = $mysql::server::options['mysqld']['user']
+    $datadir = $mysql::server::options['mysqld']['datadir']
+    $basedir = $mysql::server::options['mysqld']['basedir']
+    $config_file = $mysql::server::config_file
+
+    if $mysql::server::manage_config_file {
+      $install_db_args = "--basedir=${basedir} --defaults-extra-file=${config_file} --datadir=${datadir} --user=${mysqluser}"
+
+    }
+
+    exec { 'mysql_install_db':
+      command   => "mysql_install_db ${install_db_args}",
+      creates   => "${datadir}/mysql",
+      logoutput => on_failure,
+      path      => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin',
+      require   => Package['mysql-server'],
+    }
+
+    if $mysql::server::restart {
+      Exec['mysql_install_db'] {
+        notify => Class['mysql::server::service'],
+      }
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/server/monitor.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+#This is a helper class to add a monitoring user to the database
+class mysql::server::monitor (
+  $mysql_monitor_username = '',
+  $mysql_monitor_password = '',
+  $mysql_monitor_hostname = ''
+) {
+
+  Anchor['mysql::server::end'] -> Class['mysql::server::monitor']
+
+  mysql_user { "${mysql_monitor_username}@${mysql_monitor_hostname}":
+    ensure        => present,
+    password_hash => mysql_password($mysql_monitor_password),
+    require       => Class['mysql::server::service'],
+  }
+
+  mysql_grant { "${mysql_monitor_username}@${mysql_monitor_hostname}/*.*":
+    ensure     => present,
+    user       => "${mysql_monitor_username}@${mysql_monitor_hostname}",
+    table      => '*.*',
+    privileges => [ 'PROCESS', 'SUPER' ],
+    require    => Mysql_user["${mysql_monitor_username}@${mysql_monitor_hostname}"],
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/server/mysqltuner.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,52 @@
+#
+class mysql::server::mysqltuner(
+  $ensure  = 'present',
+  $version = 'v1.3.0',
+  $source  = undef,
+) {
+
+  if $source {
+    $_version = $source
+    $_source  = $source
+  } else {
+    $_version = $version
+    $_source  = "https://github.com/major/MySQLTuner-perl/raw/${version}/mysqltuner.pl"
+  }
+
+  if $ensure == 'present' {
+    # $::puppetversion doesn't exist in puppet 4.x so would break strict
+    # variables
+    if ! $::settings::strict_variables {
+      $_puppetversion = $::puppetversion
+    } else {
+      # defined only works with puppet >= 3.5.0, so don't use it unless we're
+      # actually using strict variables
+      $_puppetversion = defined('$puppetversion') ? {
+        true    => $::puppetversion,
+        default => undef,
+      }
+    }
+    # see https://tickets.puppetlabs.com/browse/ENTERPRISE-258
+    if $_puppetversion and $_puppetversion =~ /Puppet Enterprise/ and versioncmp($_puppetversion, '3.8.0') < 0 {
+      class { 'staging':
+        path => '/opt/mysql_staging',
+      }
+    } else {
+      class { 'staging': }
+    }
+
+    staging::file { "mysqltuner-${_version}":
+      source => $_source,
+    }
+    file { '/usr/local/bin/mysqltuner':
+      ensure  => $ensure,
+      mode    => '0550',
+      source  => "${::staging::path}/mysql/mysqltuner-${_version}",
+      require => Staging::File["mysqltuner-${_version}"],
+    }
+  } else {
+    file { '/usr/local/bin/mysqltuner':
+      ensure => $ensure,
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/server/providers.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+# Convenience class to call each of the three providers with the corresponding
+# hashes provided in mysql::server.
+# See README.md for details.
+class mysql::server::providers {
+  create_resources('mysql_user', $mysql::server::users)
+  create_resources('mysql_grant', $mysql::server::grants)
+  create_resources('mysql_database', $mysql::server::databases)
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/server/root_password.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+#
+class mysql::server::root_password {
+
+  $options = $mysql::server::options
+  $secret_file = $mysql::server::install_secret_file
+
+  # New installations of MySQL will configure a default random password for the root user
+  # with an expiration. No actions can be performed until this password is changed. The
+  # below exec will remove this default password. If the user has supplied a root
+  # password it will be set further down with the mysql_user resource.
+  $rm_pass_cmd = join([
+    "mysqladmin -u root --password=\$(grep -o '[^ ]\\+\$' ${secret_file}) password ''",
+    "rm -f ${secret_file}"
+  ], ' && ')
+  exec { 'remove install pass':
+    command => $rm_pass_cmd,
+    onlyif  => "test -f ${secret_file}",
+    path    => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin'
+  }
+
+  # manage root password if it is set
+  if $mysql::server::create_root_user == true and $mysql::server::root_password != 'UNSET' {
+    mysql_user { 'root@localhost':
+      ensure        => present,
+      password_hash => mysql_password($mysql::server::root_password),
+      require       => Exec['remove install pass']
+    }
+  }
+
+  if $mysql::server::create_root_my_cnf == true and $mysql::server::root_password != 'UNSET' {
+    file { "${::root_home}/.my.cnf":
+      content => template('mysql/my.cnf.pass.erb'),
+      owner   => 'root',
+      mode    => '0600',
+    }
+
+    # show_diff was added with puppet 3.0
+    if versioncmp($::puppetversion, '3.0') <= 0 {
+      File["${::root_home}/.my.cnf"] { show_diff => false }
+    }
+    if $mysql::server::create_root_user == true {
+      Mysql_user['root@localhost'] -> File["${::root_home}/.my.cnf"]
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/manifests/server/service.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,50 @@
+#
+class mysql::server::service {
+  $options = $mysql::server::options
+
+  if $mysql::server::real_service_manage {
+    if $mysql::server::real_service_enabled {
+      $service_ensure = 'running'
+    } else {
+      $service_ensure = 'stopped'
+    }
+  } else {
+    $service_ensure = undef
+  }
+
+  if $mysql::server::override_options and $mysql::server::override_options['mysqld'] and $mysql::server::override_options['mysqld']['user'] {
+    $mysqluser = $mysql::server::override_options['mysqld']['user']
+  } else {
+    $mysqluser = $options['mysqld']['user']
+  }
+
+  if $options['mysqld']['log-error'] {
+    file { $options['mysqld']['log-error']:
+      ensure => present,
+      owner  => $mysqluser,
+      group  => $::mysql::server::mysql_group,
+    }
+  }
+
+  service { 'mysqld':
+    ensure   => $service_ensure,
+    name     => $mysql::server::service_name,
+    enable   => $mysql::server::real_service_enabled,
+    provider => $mysql::server::service_provider,
+  }
+
+  # only establish ordering between service and package if
+  # we're managing the package.
+  if $mysql::server::package_manage {
+    Service['mysqld'] {
+      require  => Package['mysql-server'],
+    }
+  }
+
+  # only establish ordering between config file and service if
+  # we're managing the config file.
+  if $mysql::server::manage_config_file {
+    File['mysql-config-file'] -> Service['mysqld']
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/metadata.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,89 @@
+{
+  "name": "puppetlabs-mysql",
+  "version": "3.6.2",
+  "author": "Puppet Labs",
+  "summary": "Installs, configures, and manages the MySQL service.",
+  "license": "Apache-2.0",
+  "source": "git://github.com/puppetlabs/puppetlabs-mysql.git",
+  "project_page": "http://github.com/puppetlabs/puppetlabs-mysql",
+  "issues_url": "https://tickets.puppetlabs.com/browse/MODULES",
+  "dependencies": [
+    {"name":"puppetlabs/stdlib","version_requirement":">= 3.2.0 < 5.0.0"},
+    {"name":"nanliu/staging","version_requirement":">= 1.0.1 < 2.0.0"}
+  ],
+  "operatingsystem_support": [
+    {
+      "operatingsystem": "RedHat",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "CentOS",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "OracleLinux",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Scientific",
+      "operatingsystemrelease": [
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "SLES",
+      "operatingsystemrelease": [
+        "11 SP1",
+        "12"
+      ]
+    },
+    {
+      "operatingsystem": "Debian",
+      "operatingsystemrelease": [
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Ubuntu",
+      "operatingsystemrelease": [
+        "10.04",
+        "12.04",
+        "14.04"
+      ]
+    },
+    {
+      "operatingsystem": "Solaris",
+      "operatingsystemrelease": [
+        "11.2",
+        "11.3",
+        "12.0"
+      ]
+    }
+  ],
+  "requirements": [
+    {
+      "name": "pe",
+      "version_requirement": ">= 3.0.0 < 2015.4.0"
+    },
+    {
+      "name": "puppet",
+      "version_requirement": ">= 3.0.0 < 5.0.0"
+    }
+  ],
+  "description": "Mysql module"
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/mysql_backup_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,187 @@
+require 'spec_helper_acceptance'
+require 'puppet'
+require 'puppet/util/package'
+
+describe 'mysql::server::backup class' do
+
+  def pre_run
+    apply_manifest("class { 'mysql::server': root_password => 'password' }", :catch_failures => true)
+    @mysql_version = (on default, 'mysql --version').output.chomp.match(/\d+\.\d+\.\d+/)[0]
+  end
+
+  def version_is_greater_than(version)
+    return Puppet::Util::Package.versioncmp(@mysql_version, version) > 0
+  end
+
+  context 'should work with no errors' do
+    it 'when configuring mysql backups' do
+      pp = <<-EOS
+        class { 'mysql::server': root_password => 'password' }
+        mysql::db { [
+          'backup1',
+          'backup2'
+        ]:
+          user     => 'backup',
+          password => 'secret',
+        }
+
+        class { 'mysql::server::backup':
+          backupuser     => 'myuser',
+          backuppassword => 'mypassword',
+          backupdir      => '/tmp/backups',
+          backupcompress => true,
+          postscript     => [
+            'rm -rf /var/tmp/mysqlbackups',
+            'rm -f /var/tmp/mysqlbackups.done',
+            'cp -r /tmp/backups /var/tmp/mysqlbackups',
+            'touch /var/tmp/mysqlbackups.done',
+          ],
+          execpath      => '/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin',
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_failures => true)
+    end
+  end
+
+  describe 'mysqlbackup.sh' do
+    it 'should run mysqlbackup.sh with no errors' do
+      shell("/usr/local/sbin/mysqlbackup.sh") do |r|
+        expect(r.stderr).to eq("")
+      end
+    end
+
+    it 'should dump all databases to single file' do
+      shell('ls -l /tmp/backups/mysql_backup_*-*.sql.bz2 | wc -l') do |r|
+        expect(r.stdout).to match(/1/)
+        expect(r.exit_code).to be_zero
+      end
+    end
+
+    context 'should create one file per database per run' do
+      it 'executes mysqlbackup.sh a second time' do
+        shell('sleep 1')
+        shell('/usr/local/sbin/mysqlbackup.sh')
+      end
+
+      it 'creates at least one backup tarball' do
+        shell('ls -l /tmp/backups/mysql_backup_*-*.sql.bz2 | wc -l') do |r|
+          expect(r.stdout).to match(/2/)
+          expect(r.exit_code).to be_zero
+        end
+      end
+    end
+  end
+
+  context 'with one file per database' do
+    context 'should work with no errors' do
+      it 'when configuring mysql backups' do
+        pp = <<-EOS
+          class { 'mysql::server': root_password => 'password' }
+          mysql::db { [
+            'backup1',
+            'backup2'
+          ]:
+            user     => 'backup',
+            password => 'secret',
+          }
+
+          class { 'mysql::server::backup':
+            backupuser        => 'myuser',
+            backuppassword    => 'mypassword',
+            backupdir         => '/tmp/backups',
+            backupcompress    => true,
+            file_per_database => true,
+            postscript        => [
+              'rm -rf /var/tmp/mysqlbackups',
+              'rm -f /var/tmp/mysqlbackups.done',
+              'cp -r /tmp/backups /var/tmp/mysqlbackups',
+              'touch /var/tmp/mysqlbackups.done',
+            ],
+            execpath          => '/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin',
+          }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe 'mysqlbackup.sh' do
+      it 'should run mysqlbackup.sh with no errors without root credentials' do
+        shell("HOME=/tmp/dontreadrootcredentials /usr/local/sbin/mysqlbackup.sh") do |r|
+          expect(r.stderr).to eq("")
+        end
+      end
+
+      it 'should create one file per database' do
+        ['backup1', 'backup2'].each do |database|
+          shell("ls -l /tmp/backups/mysql_backup_#{database}_*-*.sql.bz2 | wc -l") do |r|
+            expect(r.stdout).to match(/1/)
+            expect(r.exit_code).to be_zero
+          end
+        end
+      end
+
+      context 'should create one file per database per run' do
+        it 'executes mysqlbackup.sh a second time' do
+          shell('sleep 1')
+          shell('HOME=/tmp/dontreadrootcredentials /usr/local/sbin/mysqlbackup.sh')
+        end
+
+        it 'has one file per database per run' do
+          ['backup1', 'backup2'].each do |database|
+            shell("ls -l /tmp/backups/mysql_backup_#{database}_*-*.sql.bz2 | wc -l") do |r|
+              expect(r.stdout).to match(/2/)
+              expect(r.exit_code).to be_zero
+            end
+          end
+        end
+      end
+    end
+  end
+
+  context 'with triggers and routines' do
+    it 'when configuring mysql backups with triggers and routines' do
+      pre_run
+      pp = <<-EOS
+        class { 'mysql::server': root_password => 'password' }
+        mysql::db { [
+          'backup1',
+          'backup2'
+          ]:
+          user => 'backup',
+          password => 'secret',
+        }
+        package { 'bzip2':
+          ensure => present,
+        }
+        class { 'mysql::server::backup':
+          backupuser => 'myuser',
+          backuppassword => 'mypassword',
+          backupdir => '/tmp/backups',
+          backupcompress => true,
+          file_per_database => true,
+          include_triggers => #{version_is_greater_than('5.1.5')},
+          include_routines => true,
+          postscript => [
+            'rm -rf /var/tmp/mysqlbackups',
+            'rm -f /var/tmp/mysqlbackups.done',
+            'cp -r /tmp/backups /var/tmp/mysqlbackups',
+            'touch /var/tmp/mysqlbackups.done',
+          ],
+          execpath => '/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin',
+          require => Package['bzip2'],
+        }
+      EOS
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should run mysqlbackup.sh with no errors' do
+      shell("/usr/local/sbin/mysqlbackup.sh") do |r|
+        expect(r.stderr).to eq("")
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/mysql_db_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,71 @@
+require 'spec_helper_acceptance'
+
+describe 'mysql::db define' do
+  describe 'creating a database' do
+    # Using puppet_apply as a helper
+    it 'should work with no errors' do
+      pp = <<-EOS
+        class { 'mysql::server': root_password => 'password' }
+        mysql::db { 'spec1':
+          user     => 'root1',
+          password => 'password',
+        }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+
+      expect(shell("mysql -e 'show databases;'|grep spec1").exit_code).to be_zero
+    end
+  end
+
+  describe 'creating a database with post-sql' do
+    # Using puppet_apply as a helper
+    it 'should work with no errors' do
+      pp = <<-EOS
+        class { 'mysql::server': override_options => { 'root_password' => 'password' } }
+        file { '/tmp/spec.sql':
+          ensure  => file,
+          content => 'CREATE TABLE table1 (id int);',
+          before  => Mysql::Db['spec2'],
+        }
+        mysql::db { 'spec2':
+          user     => 'root1',
+          password => 'password',
+          sql      => '/tmp/spec.sql',
+        }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    it 'should have the table' do
+      expect(shell("mysql -e 'show tables;' spec2|grep table1").exit_code).to be_zero
+    end
+  end
+
+  describe 'creating a database with dbname parameter' do
+    # Using puppet_apply as a helper
+    it 'should work with no errors' do
+      pp = <<-EOS
+        class { 'mysql::server': override_options => { 'root_password' => 'password' } }
+        mysql::db { 'spec1':
+          user     => 'root1',
+          password => 'password',
+          dbname   => 'realdb',
+        }
+      EOS
+
+      # Run it twice and test for idempotency
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    it 'should have the database named realdb' do
+      expect(shell("mysql -e 'show databases;'|grep realdb").exit_code).to be_zero
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/mysql_server_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,68 @@
+require 'spec_helper_acceptance'
+
+describe 'mysql class' do
+
+  describe 'running puppet code' do
+    # Using puppet_apply as a helper
+    it 'should work with no errors' do
+      tmpdir = default.tmpdir('mysql')
+      pp = <<-EOS
+        class { 'mysql::server':
+          config_file             => '#{tmpdir}/my.cnf',
+          includedir              => '#{tmpdir}/include',
+          manage_config_file      => 'true',
+          override_options        => { 'mysqld' => { 'key_buffer_size' => '32M' }},
+          package_ensure          => 'present',
+          purge_conf_dir          => 'true',
+          remove_default_accounts => 'true',
+          restart                 => 'true',
+          root_group              => 'root',
+          root_password           => 'test',
+          service_enabled         => 'true',
+          service_manage          => 'true',
+          users                   => {
+            'someuser@localhost' => {
+              ensure                   => 'present',
+              max_connections_per_hour => '0',
+              max_queries_per_hour     => '0',
+              max_updates_per_hour     => '0',
+              max_user_connections     => '0',
+              password_hash            => '*F3A2A51A9B0F2BE2468926B4132313728C250DBF',
+            }},
+          grants                  => {
+            'someuser@localhost/somedb.*' => {
+              ensure     => 'present',
+              options    => ['GRANT'],
+              privileges => ['SELECT', 'INSERT', 'UPDATE', 'DELETE'],
+              table      => 'somedb.*',
+              user       => 'someuser@localhost',
+            },
+          },
+          databases => {
+            'somedb' => {
+              ensure  => 'present',
+              charset => 'utf8',
+            },
+          }
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+  end
+
+  describe 'configuration needed for syslog' do
+    it 'should work with no errors' do
+      pp = <<-EOS
+        class { 'mysql::server':
+          override_options => { 'mysqld' => { 'log-error' => undef }, 'mysqld_safe' => { 'log-error' => false, 'syslog' => true }},
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/nodesets/centos-510-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-510-x64:
+    roles:
+      - master
+    platform: el-5-x86_64
+    box : centos-510-x64-virtualbox-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-510-x64-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/nodesets/centos-59-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-59-x64:
+    roles:
+      - master
+    platform: el-5-x86_64
+    box : centos-59-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/nodesets/centos-64-x64-pe.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+HOSTS:
+  centos-64-x64:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: el-6-x86_64
+    box : centos-64-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: pe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/nodesets/centos-65-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-65-x64:
+    roles:
+      - master
+    platform: el-6-x86_64
+    box : centos-65-x64-vbox436-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/nodesets/default.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  centos-64-x64:
+    roles:
+      - master
+      - default
+    platform: el-6-x86_64
+    box : centos-64-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/nodesets/fedora-18-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  fedora-18-x64:
+    roles:
+      - master
+    platform: fedora-18-x86_64
+    box : fedora-18-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/fedora-18-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/nodesets/sles-11-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  sles-11-x64.local:
+    roles:
+      - master
+    platform: sles-11-x64
+    box : sles-11sp1-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/sles-11sp1-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+    type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-server-10044-x64:
+    roles:
+      - master
+    platform: ubuntu-10.04-amd64
+    box : ubuntu-server-10044-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-server-12042-x64:
+    roles:
+      - master
+    platform: ubuntu-12.04-amd64
+    box : ubuntu-server-12042-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  ubuntu-server-1404-x64:
+    roles:
+      - master
+    platform: ubuntu-14.04-amd64
+    box : puppetlabs/ubuntu-14.04-64-nocm
+    box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm
+    hypervisor : vagrant
+CONFIG:
+  log_level   : debug
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/types/mysql_database_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,64 @@
+require 'spec_helper_acceptance'
+
+describe 'mysql_database' do
+  describe 'setup' do
+    it 'should work with no errors' do
+      pp = <<-EOS
+        class { 'mysql::server': }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+  end
+
+  describe 'creating database' do
+    it 'should work without errors' do
+      pp = <<-EOS
+        mysql_database { 'spec_db':
+          ensure => present,
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should find the database' do
+      shell("mysql -NBe \"SHOW DATABASES LIKE 'spec_db'\"") do |r|
+        expect(r.stdout).to match(/^spec_db$/)
+        expect(r.stderr).to be_empty
+      end
+    end
+  end
+
+  describe 'charset and collate' do
+    it 'should create two db of different types idempotently' do
+      pp = <<-EOS
+        mysql_database { 'spec_latin1':
+          charset => 'latin1',
+          collate => 'latin1_swedish_ci',
+        }
+        mysql_database { 'spec_utf8':
+          charset => 'utf8',
+          collate => 'utf8_general_ci',
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+
+    it 'should find latin1 db' do
+      shell("mysql -NBe \"SHOW VARIABLES LIKE '%_database'\" spec_latin1") do |r|
+        expect(r.stdout).to match(/^character_set_database\tlatin1\ncollation_database\tlatin1_swedish_ci$/)
+        expect(r.stderr).to be_empty
+      end
+    end
+
+    it 'should find utf8 db' do
+      shell("mysql -NBe \"SHOW VARIABLES LIKE '%_database'\" spec_utf8") do |r|
+        expect(r.stdout).to match(/^character_set_database\tutf8\ncollation_database\tutf8_general_ci$/)
+        expect(r.stderr).to be_empty
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/types/mysql_grant_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,416 @@
+require 'spec_helper_acceptance'
+
+describe 'mysql_grant' do
+
+  describe 'setup' do
+    it 'setup mysql::server' do
+      pp = <<-EOS
+        class { 'mysql::server': }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+  end
+
+  describe 'missing privileges for user' do
+    it 'should fail' do
+      pp = <<-EOS
+        mysql_grant { 'test1@tester/test.*':
+          ensure => 'present',
+          table  => 'test.*',
+          user   => 'test1@tester',
+        }
+      EOS
+
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/privileges parameter is required/)
+    end
+
+    it 'should not find the user' do
+      expect(shell("mysql -NBe \"SHOW GRANTS FOR test1@tester\"", { :acceptable_exit_codes => 1}).stderr).to match(/There is no such grant defined for user 'test1' on host 'tester'/)
+    end
+  end
+
+  describe 'missing table for user' do
+    it 'should fail' do
+      pp = <<-EOS
+        mysql_grant { 'atest@tester/test.*':
+          ensure => 'present',
+          user   => 'atest@tester',
+          privileges => ['ALL'],
+        }
+      EOS
+
+      apply_manifest(pp, :expect_failures => true)
+    end
+
+    it 'should not find the user' do
+      expect(shell("mysql -NBe \"SHOW GRANTS FOR atest@tester\"", {:acceptable_exit_codes => 1}).stderr).to match(/There is no such grant defined for user 'atest' on host 'tester'/)
+    end
+  end
+
+  describe 'adding privileges' do
+    it 'should work without errors' do
+      pp = <<-EOS
+        mysql_grant { 'test2@tester/test.*':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test2@tester',
+          privileges => ['SELECT', 'UPDATE'],
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should find the user' do
+      shell("mysql -NBe \"SHOW GRANTS FOR test2@tester\"") do |r|
+        expect(r.stdout).to match(/GRANT SELECT, UPDATE.*TO 'test2'@'tester'/)
+        expect(r.stderr).to be_empty
+      end
+    end
+  end
+
+  describe 'adding privileges with special character in name' do
+    it 'should work without errors' do
+      pp = <<-EOS
+        mysql_grant { 'test-2@tester/test.*':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test-2@tester',
+          privileges => ['SELECT', 'UPDATE'],
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should find the user' do
+      shell("mysql -NBe \"SHOW GRANTS FOR 'test-2'@tester\"") do |r|
+        expect(r.stdout).to match(/GRANT SELECT, UPDATE.*TO 'test-2'@'tester'/)
+        expect(r.stderr).to be_empty
+      end
+    end
+  end
+
+  describe 'adding privileges with invalid name' do
+    it 'should fail' do
+      pp = <<-EOS
+        mysql_grant { 'test':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test2@tester',
+          privileges => ['SELECT', 'UPDATE'],
+        }
+      EOS
+
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/name must match user and table parameters/)
+    end
+  end
+
+  describe 'adding option' do
+    it 'should work without errors' do
+      pp = <<-EOS
+        mysql_grant { 'test3@tester/test.*':
+          ensure  => 'present',
+          table   => 'test.*',
+          user    => 'test3@tester',
+          options => ['GRANT'],
+          privileges => ['SELECT', 'UPDATE'],
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should find the user' do
+      shell("mysql -NBe \"SHOW GRANTS FOR test3@tester\"") do |r|
+        expect(r.stdout).to match(/GRANT SELECT, UPDATE ON `test`.* TO 'test3'@'tester' WITH GRANT OPTION$/)
+        expect(r.stderr).to be_empty
+      end
+    end
+  end
+
+  describe 'adding all privileges without table' do
+    it 'should fail' do
+      pp = <<-EOS
+        mysql_grant { 'test4@tester/test.*':
+          ensure     => 'present',
+          user       => 'test4@tester',
+          options    => ['GRANT'],
+          privileges => ['SELECT', 'UPDATE', 'ALL'],
+        }
+      EOS
+
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/table parameter is required./)
+    end
+  end
+
+  describe 'adding all privileges' do
+    it 'should only try to apply ALL' do
+      pp = <<-EOS
+        mysql_grant { 'test4@tester/test.*':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test4@tester',
+          options    => ['GRANT'],
+          privileges => ['SELECT', 'UPDATE', 'ALL'],
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should find the user' do
+      shell("mysql -NBe \"SHOW GRANTS FOR test4@tester\"") do |r|
+        expect(r.stdout).to match(/GRANT ALL PRIVILEGES ON `test`.* TO 'test4'@'tester' WITH GRANT OPTION/)
+        expect(r.stderr).to be_empty
+      end
+    end
+  end
+
+  # Test combinations of user@host to ensure all cases work.
+  describe 'short hostname' do
+    it 'should apply' do
+      pp = <<-EOS
+        mysql_grant { 'test@short/test.*':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test@short',
+          privileges => 'ALL',
+        }
+        mysql_grant { 'test@long.hostname.com/test.*':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test@long.hostname.com',
+          privileges => 'ALL',
+        }
+        mysql_grant { 'test@192.168.5.6/test.*':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test@192.168.5.6',
+          privileges => 'ALL',
+        }
+        mysql_grant { 'test@2607:f0d0:1002:0051:0000:0000:0000:0004/test.*':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test@2607:f0d0:1002:0051:0000:0000:0000:0004',
+          privileges => 'ALL',
+        }
+        mysql_grant { 'test@::1/128/test.*':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test@::1/128',
+          privileges => 'ALL',
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'finds short hostname' do
+      shell("mysql -NBe \"SHOW GRANTS FOR test@short\"") do |r|
+        expect(r.stdout).to match(/GRANT ALL PRIVILEGES ON `test`.* TO 'test'@'short'/)
+        expect(r.stderr).to be_empty
+      end
+    end
+    it 'finds long hostname' do
+      shell("mysql -NBe \"SHOW GRANTS FOR 'test'@'long.hostname.com'\"") do |r|
+        expect(r.stdout).to match(/GRANT ALL PRIVILEGES ON `test`.* TO 'test'@'long.hostname.com'/)
+        expect(r.stderr).to be_empty
+      end
+    end
+    it 'finds ipv4' do
+      shell("mysql -NBe \"SHOW GRANTS FOR 'test'@'192.168.5.6'\"") do |r|
+        expect(r.stdout).to match(/GRANT ALL PRIVILEGES ON `test`.* TO 'test'@'192.168.5.6'/)
+        expect(r.stderr).to be_empty
+      end
+    end
+    it 'finds ipv6' do
+      shell("mysql -NBe \"SHOW GRANTS FOR 'test'@'2607:f0d0:1002:0051:0000:0000:0000:0004'\"") do |r|
+        expect(r.stdout).to match(/GRANT ALL PRIVILEGES ON `test`.* TO 'test'@'2607:f0d0:1002:0051:0000:0000:0000:0004'/)
+        expect(r.stderr).to be_empty
+      end
+    end
+    it 'finds short ipv6' do
+      shell("mysql -NBe \"SHOW GRANTS FOR 'test'@'::1/128'\"") do |r|
+        expect(r.stdout).to match(/GRANT ALL PRIVILEGES ON `test`.* TO 'test'@'::1\/128'/)
+        expect(r.stderr).to be_empty
+      end
+    end
+  end
+
+  describe 'complex test' do
+    it 'setup mysql::server' do
+      pp = <<-EOS
+      $dbSubnet = '10.10.10.%'
+
+      mysql_database { 'foo':
+        ensure => present,
+      }
+
+      exec { 'mysql-create-table':
+        command     => '/usr/bin/mysql -NBe "CREATE TABLE foo.bar (name VARCHAR(20))"',
+        environment => "HOME=${::root_home}",
+        unless      => '/usr/bin/mysql -NBe "SELECT 1 FROM foo.bar LIMIT 1;"',
+        require     => Mysql_database['foo'],
+      }
+
+      Mysql_grant {
+          ensure     => present,
+          options    => ['GRANT'],
+          privileges => ['ALL'],
+          table      => '*.*',
+          require    => [ Mysql_database['foo'], Exec['mysql-create-table'] ],
+      }
+
+      mysql_grant { "user1@${dbSubnet}/*.*":
+          user       => "user1@${dbSubnet}",
+      }
+      mysql_grant { "user2@${dbSubnet}/foo.bar":
+          privileges => ['SELECT', 'INSERT', 'UPDATE'],
+          user       => "user2@${dbSubnet}",
+          table      => 'foo.bar',
+      }
+      mysql_grant { "user3@${dbSubnet}/foo.*":
+          privileges => ['SELECT', 'INSERT', 'UPDATE'],
+          user       => "user3@${dbSubnet}",
+          table      => 'foo.*',
+      }
+      mysql_grant { 'web@%/*.*':
+          user       => 'web@%',
+      }
+      mysql_grant { "web@${dbSubnet}/*.*":
+          user       => "web@${dbSubnet}",
+      }
+      mysql_grant { "web@${fqdn}/*.*":
+          user       => "web@${fqdn}",
+      }
+      mysql_grant { 'web@localhost/*.*':
+          user       => 'web@localhost',
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+      apply_manifest(pp, :catch_changes => true)
+    end
+  end
+
+  describe 'lower case privileges' do
+    it 'create ALL privs' do
+      pp = <<-EOS
+      mysql_grant { 'lowercase@localhost/*.*':
+          user       => 'lowercase@localhost',
+          privileges => 'ALL',
+          table      => '*.*',
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'create lowercase all privs' do
+      pp = <<-EOS
+      mysql_grant { 'lowercase@localhost/*.*':
+          user       => 'lowercase@localhost',
+          privileges => 'all',
+          table      => '*.*',
+      }
+      EOS
+
+      expect(apply_manifest(pp, :catch_failures => true).exit_code).to eq(0)
+    end
+  end
+
+  describe 'adding procedure privileges' do
+    it 'should work without errors' do
+       pp = <<-EOS
+       mysql_grant { 'test2@tester/PROCEDURE test.simpleproc':
+         ensure     => 'present',
+         table      => 'PROCEDURE test.simpleproc',
+         user       => 'test2@tester',
+         privileges => ['EXECUTE'],
+       }
+       EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should find the user' do
+      shell("mysql -NBe \"SHOW GRANTS FOR test2@tester\"") do |r|
+        expect(r.stdout).to match(/GRANT EXECUTE ON PROCEDURE `test`.`simpleproc` TO 'test2'@'tester'/)
+        expect(r.stderr).to be_empty
+      end
+    end
+  end
+
+  describe 'grants with skip-name-resolve specified' do
+    it 'setup mysql::server' do
+      pp = <<-EOS
+        class { 'mysql::server':
+          override_options => {
+            'mysqld' => {'skip-name-resolve' => true}
+          },
+          restart          => true,
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should apply' do
+      pp = <<-EOS
+        mysql_grant { 'test@fqdn.com/test.*':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test@fqdn.com',
+          privileges => 'ALL',
+        }
+        mysql_grant { 'test@192.168.5.7/test.*':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test@192.168.5.7',
+          privileges => 'ALL',
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should fail with fqdn' do
+      expect(shell("mysql -NBe \"SHOW GRANTS FOR test@fqdn.com\"", { :acceptable_exit_codes => 1}).stderr).to match(/There is no such grant defined for user 'test' on host 'fqdn.com'/)
+    end
+    it 'finds ipv4' do
+      shell("mysql -NBe \"SHOW GRANTS FOR 'test'@'192.168.5.7'\"") do |r|
+        expect(r.stdout).to match(/GRANT ALL PRIVILEGES ON `test`.* TO 'test'@'192.168.5.7'/)
+        expect(r.stderr).to be_empty
+      end
+    end
+
+    it 'should fail to execute while applying' do
+      pp = <<-EOS
+        mysql_grant { 'test@fqdn.com/test.*':
+          ensure     => 'present',
+          table      => 'test.*',
+          user       => 'test@fqdn.com',
+          privileges => 'ALL',
+        }
+      EOS
+
+      mysql_cmd = shell('which mysql').stdout.chomp
+      shell("mv #{mysql_cmd} #{mysql_cmd}.bak")
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/Command mysql is missing/)
+      shell("mv #{mysql_cmd}.bak #{mysql_cmd}")
+    end
+
+    it 'reset mysql::server config' do
+      pp = <<-EOS
+        class { 'mysql::server':
+          restart          => true,
+        }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/types/mysql_plugin_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,72 @@
+require 'spec_helper_acceptance'
+
+# Different operating systems (and therefore different versions/forks
+# of mysql) have varying levels of support for plugins and have
+# different plugins available. Choose a plugin that works or don't try
+# to test plugins if not available.
+if fact('osfamily') =~ /RedHat/
+  if fact('operatingsystemrelease') =~ /^5\./
+    plugin = nil # Plugins not supported on mysql on RHEL 5
+  elsif fact('operatingsystemrelease') =~ /^6\./
+    plugin     = 'example'
+    plugin_lib = 'ha_example.so'
+  elsif fact('operatingsystemrelease') =~ /^7\./
+    plugin     = 'pam'
+    plugin_lib = 'auth_pam.so'
+  end
+elsif fact('osfamily') =~ /Debian/
+  if fact('operatingsystem') =~ /Debian/
+    if fact('operatingsystemrelease') =~ /^6\./
+      # Only available plugin is innodb which is already loaded and not unload- or reload-able
+      plugin = nil
+    elsif fact('operatingsystemrelease') =~ /^7\./
+      plugin     = 'example'
+      plugin_lib = 'ha_example.so'
+    end
+  elsif fact('operatingsystem') =~ /Ubuntu/
+    if fact('operatingsystemrelease') =~ /^10\.04/
+      # Only available plugin is innodb which is already loaded and not unload- or reload-able
+      plugin = nil
+    else
+      plugin     = 'example'
+      plugin_lib = 'ha_example.so'
+    end
+  end
+elsif fact('osfamily') =~ /Suse/
+  plugin = nil # Plugin library path is broken on Suse http://lists.opensuse.org/opensuse-bugs/2013-08/msg01123.html
+end
+
+describe 'mysql_plugin' do
+  if plugin # if plugins are supported
+    describe 'setup' do
+      it 'should work with no errors' do
+        pp = <<-EOS
+          class { 'mysql::server': }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+
+    describe 'load plugin' do
+      it 'should work without errors' do
+        pp = <<-EOS
+          mysql_plugin { #{plugin}:
+            ensure => present,
+            soname => '#{plugin_lib}',
+          }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      it 'should find the plugin' do
+        shell("mysql -NBe \"select plugin_name from information_schema.plugins where plugin_name='#{plugin}'\"") do |r|
+          expect(r.stdout).to match(/^#{plugin}$/i)
+          expect(r.stderr).to be_empty
+        end
+      end
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/acceptance/types/mysql_user_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,86 @@
+require 'spec_helper_acceptance'
+
+describe 'mysql_user' do
+  describe 'setup' do
+    it 'should work with no errors' do
+      pp = <<-EOS
+        class { 'mysql::server': }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+  end
+
+  context 'using ashp@localhost' do
+    describe 'adding user' do
+      it 'should work without errors' do
+        pp = <<-EOS
+          mysql_user { 'ashp@localhost':
+            password_hash => '6f8c114b58f2ce9e',
+          }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      it 'should find the user' do
+        shell("mysql -NBe \"select '1' from mysql.user where CONCAT(user, '@', host) = 'ashp@localhost'\"") do |r|
+          expect(r.stdout).to match(/^1$/)
+          expect(r.stderr).to be_empty
+        end
+      end
+    end
+  end
+
+  context 'using ashp-dash@localhost' do
+    describe 'adding user' do
+      it 'should work without errors' do
+        pp = <<-EOS
+          mysql_user { 'ashp-dash@localhost':
+            password_hash => '6f8c114b58f2ce9e',
+          }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      it 'should find the user' do
+        shell("mysql -NBe \"select '1' from mysql.user where CONCAT(user, '@', host) = 'ashp-dash@localhost'\"") do |r|
+          expect(r.stdout).to match(/^1$/)
+          expect(r.stderr).to be_empty
+        end
+      end
+    end
+  end
+
+  context 'using ashp@LocalHost' do
+    describe 'adding user' do
+      it 'should work without errors' do
+        pp = <<-EOS
+          mysql_user { 'ashp@LocalHost':
+            password_hash => '6f8c114b58f2ce9e',
+          }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+      end
+
+      it 'should find the user' do
+        shell("mysql -NBe \"select '1' from mysql.user where CONCAT(user, '@', host) = 'ashp@localhost'\"") do |r|
+          expect(r.stdout).to match(/^1$/)
+          expect(r.stderr).to be_empty
+        end
+      end
+    end
+  end
+  context 'using resource should throw no errors' do
+    describe 'find users' do
+      it {
+        on default, puppet('resource mysql_user'), {:catch_failures => true} do |r|
+          expect(r.stdout).to_not match(/Error:/)
+          expect(r.stdout).to_not match(/must be properly quoted, invalid character:/)
+        end
+      }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/classes/graceful_failures_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe 'mysql::server' do
+  on_pe_unsupported_platforms.each do |pe_version,pe_platforms|
+    pe_platforms.each do |pe_platform,facts|
+      describe "on #{pe_version} #{pe_platform}" do
+        let(:facts) { facts }
+
+        context 'should gracefully fail' do
+          it { expect { is_expected.to compile}.to raise_error(Puppet::Error, /Unsupported platform:/) }
+        end
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/classes/mycnf_template_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,79 @@
+require 'spec_helper'
+
+describe 'mysql::server' do
+  context 'my.cnf template' do
+    on_pe_supported_platforms(PLATFORMS).each do |pe_version,pe_platforms|
+      pe_platforms.each do |pe_platform,facts|
+        describe "on #{pe_version} #{pe_platform}" do
+          let(:facts) { facts }
+
+          context 'normal entry' do
+            let(:params) {{ :override_options => { 'mysqld' => { 'socket' => '/var/lib/mysql/mysql.sock' } } }}
+            it do
+              is_expected.to contain_file('mysql-config-file').with({
+                :mode                    => '0644',
+                :selinux_ignore_defaults => true,
+              }).with_content(/socket = \/var\/lib\/mysql\/mysql.sock/)
+            end
+          end
+
+          describe 'array entry' do
+            let(:params) {{ :override_options => { 'mysqld' => { 'replicate-do-db' => ['base1', 'base2'], } }}}
+            it do
+              is_expected.to contain_file('mysql-config-file').with_content(
+                /.*replicate-do-db = base1\nreplicate-do-db = base2.*/
+              )
+            end
+          end
+
+          describe 'ssl set to true' do
+            let(:params) {{ :override_options => { 'mysqld' => { 'ssl' => true }}}}
+            it { is_expected.to contain_file('mysql-config-file').with_content(/ssl/) }
+            it { is_expected.to contain_file('mysql-config-file').without_content(/ssl = true/) }
+          end
+
+          describe 'ssl set to false' do
+            let(:params) {{ :override_options => { 'mysqld' => { 'ssl' => false }}}}
+            it { is_expected.to contain_file('mysql-config-file').with_content(/ssl = false/) }
+          end
+
+          # ssl-disable (and ssl) are special cased within mysql.
+          describe 'possibility of disabling ssl completely' do
+            let(:params) {{ :override_options => { 'mysqld' => { 'ssl' => true, 'ssl-disable' => true }}}}
+            it { is_expected.to contain_file('mysql-config-file').without_content(/ssl = true/) }
+          end
+
+          describe 'a non ssl option set to true' do
+            let(:params) {{ :override_options => { 'mysqld' => { 'test' => true }}}}
+            it { is_expected.to contain_file('mysql-config-file').with_content(/^test$/) }
+            it { is_expected.to contain_file('mysql-config-file').without_content(/test = true/) }
+          end
+
+          context 'with includedir' do
+            let(:params) {{ :includedir => '/etc/my.cnf.d' }}
+            it 'makes the directory' do
+              is_expected.to contain_file('/etc/my.cnf.d').with({
+                :ensure => :directory,
+                :mode   => '0755',
+              })
+            end
+
+            it { is_expected.to contain_file('mysql-config-file').with_content(/!includedir/) }
+          end
+
+          context 'without includedir' do
+            let(:params) {{ :includedir => '' }}
+            it 'shouldnt contain the directory' do
+              is_expected.not_to contain_file('mysql-config-file').with({
+                :ensure => :directory,
+                :mode   => '0755',
+              })
+            end
+
+            it { is_expected.to contain_file('mysql-config-file').without_content(/!includedir/) }
+          end
+        end
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/classes/mysql_bindings_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe 'mysql::bindings' do
+  on_pe_supported_platforms(PLATFORMS).each do |pe_version,pe_platforms|
+    pe_platforms.each do |pe_platform,facts|
+      describe "on #{pe_version} #{pe_platform}" do
+        let(:facts) { facts }
+
+        let(:params) {{
+          'java_enable'             => true,
+          'perl_enable'             => true,
+          'php_enable'              => true,
+          'python_enable'           => true,
+          'ruby_enable'             => true,
+          'client_dev'              => true,
+          'daemon_dev'              => true,
+          'client_dev_package_name' => 'libmysqlclient-devel',
+          'daemon_dev_package_name' => 'mysql-devel',
+        }}
+
+        it { is_expected.to contain_package('mysql-connector-java') }
+        it { is_expected.to contain_package('perl_mysql') }
+        it { is_expected.to contain_package('python-mysqldb') }
+        it { is_expected.to contain_package('ruby_mysql') }
+        it { is_expected.to contain_package('mysql-client_dev') }
+        it { is_expected.to contain_package('mysql-daemon_dev') }
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/classes/mysql_client_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+require 'spec_helper'
+
+describe 'mysql::client' do
+  on_pe_supported_platforms(PLATFORMS).each do |pe_version,pe_platforms|
+    pe_platforms.each do |pe_platform,facts|
+      describe "on #{pe_version} #{pe_platform}" do
+        let(:facts) { facts }
+
+        context 'with defaults' do
+          it { is_expected.not_to contain_class('mysql::bindings') }
+          it { is_expected.to contain_package('mysql_client') }
+        end
+
+        context 'with bindings enabled' do
+          let(:params) {{ :bindings_enable => true }}
+
+          it { is_expected.to contain_class('mysql::bindings') }
+          it { is_expected.to contain_package('mysql_client') }
+        end
+
+        context 'with package_manage set to true' do
+          let(:params) {{ :package_manage => true }}
+
+          it { is_expected.to contain_package('mysql_client') }
+        end
+
+        context 'with package_manage set to false' do
+          let(:params) {{ :package_manage => false }}
+
+          it { is_expected.not_to contain_package('mysql_client') }
+        end
+
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/classes/mysql_server_account_security_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,68 @@
+require 'spec_helper'
+
+describe 'mysql::server::account_security' do
+  on_pe_supported_platforms(PLATFORMS).each do |pe_version,pe_platforms|
+    pe_platforms.each do |pe_platform,facts|
+      describe "on #{pe_version} #{pe_platform}" do
+        let(:facts) { facts.merge({:fqdn => 'myhost.mydomain', :hostname => 'myhost'}) }
+
+        [ 'root@myhost.mydomain',
+          'root@127.0.0.1',
+          'root@::1',
+          '@myhost.mydomain',
+          '@localhost',
+          '@%',
+        ].each do |user|
+          it "removes Mysql_User[#{user}]" do
+            is_expected.to contain_mysql_user(user).with_ensure('absent')
+          end
+        end
+
+        # When the hostname doesn't match the fqdn we also remove these.
+        # We don't need to test the inverse as when they match they are
+        # covered by the above list.
+        [ 'root@myhost', '@myhost' ].each do |user|
+          it "removes Mysql_User[#{user}]" do
+            is_expected.to contain_mysql_user(user).with_ensure('absent')
+          end
+        end
+
+        it 'should remove Mysql_database[test]' do
+          is_expected.to contain_mysql_database('test').with_ensure('absent')
+        end
+      end
+
+      describe "on #{pe_version} #{pe_platform} with fqdn==localhost" do
+        let(:facts) { facts.merge({:fqdn => 'localhost', :hostname => 'localhost'}) }
+
+        [ 'root@127.0.0.1',
+          'root@::1',
+          '@localhost',
+          'root@localhost.localdomain',
+          '@localhost.localdomain',
+          '@%',
+        ].each do |user|
+          it "removes Mysql_User[#{user}]" do
+            is_expected.to contain_mysql_user(user).with_ensure('absent')
+          end
+        end
+      end
+
+      describe "on #{pe_version} #{pe_platform} with fqdn==localhost.localdomain" do
+        let(:facts) { facts.merge({:fqdn => 'localhost.localdomain', :hostname => 'localhost'}) }
+
+        [ 'root@127.0.0.1',
+          'root@::1',
+          '@localhost',
+          'root@localhost.localdomain',
+          '@localhost.localdomain',
+          '@%',
+        ].each do |user|
+          it "removes Mysql_User[#{user}]" do
+            is_expected.to contain_mysql_user(user).with_ensure('absent')
+          end
+        end
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/classes/mysql_server_backup_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,403 @@
+require 'spec_helper'
+
+describe 'mysql::server::backup' do
+  on_pe_supported_platforms(PLATFORMS).each do |pe_version,pe_platforms|
+    pe_platforms.each do |pe_platform,facts|
+      describe "on #{pe_version} #{pe_platform}" do
+        let(:facts) { facts }
+
+        let(:default_params) {
+          { 'backupuser'         => 'testuser',
+            'backuppassword'     => 'testpass',
+            'backupdir'          => '/tmp',
+            'backuprotate'       => '25',
+            'delete_before_dump' => true,
+            'execpath'           => '/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin',
+          }
+        }
+
+        context 'standard conditions' do
+          let(:params) { default_params }
+
+          # Cannot use that_requires here, doesn't work on classes.
+          it { is_expected.to contain_mysql_user('testuser@localhost').with(
+            :require => 'Class[Mysql::Server::Root_password]') }
+
+          it { is_expected.to contain_mysql_grant('testuser@localhost/*.*').with(
+            :privileges => ['SELECT', 'RELOAD', 'LOCK TABLES', 'SHOW VIEW', 'PROCESS']
+          ).that_requires('Mysql_user[testuser@localhost]') }
+
+          context 'with triggers included' do
+            let(:params) do
+              { :include_triggers => true }.merge(default_params)
+            end
+            it { is_expected.to contain_mysql_grant('testuser@localhost/*.*').with(
+              :privileges => ['SELECT', 'RELOAD', 'LOCK TABLES', 'SHOW VIEW', 'PROCESS', 'TRIGGER']
+            ).that_requires('Mysql_user[testuser@localhost]') }
+          end
+
+          it { is_expected.to contain_cron('mysql-backup').with(
+            :command => '/usr/local/sbin/mysqlbackup.sh',
+            :ensure  => 'present'
+          )}
+
+          it { is_expected.to contain_file('mysqlbackup.sh').with(
+            :path   => '/usr/local/sbin/mysqlbackup.sh',
+            :ensure => 'present'
+          ) }
+
+          it { is_expected.to contain_file('mysqlbackupdir').with(
+            :path   => '/tmp',
+            :ensure => 'directory'
+          )}
+
+          it 'should have compression by default' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(
+              /bzcat -zc/
+            )
+          end
+
+          it 'should skip backing up events table by default' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(
+              /ADDITIONAL_OPTIONS="--ignore-table=mysql.event"/
+            )
+          end
+
+          it 'should not mention triggers by default because file_per_database is false' do
+            is_expected.to contain_file('mysqlbackup.sh').without_content(
+              /.*triggers.*/
+            )
+          end
+
+          it 'should not mention routines by default because file_per_database is false' do
+            is_expected.to contain_file('mysqlbackup.sh').without_content(
+              /.*routines.*/
+            )
+          end
+
+          it 'should have 25 days of rotation' do
+            # MySQL counts from 0
+            is_expected.to contain_file('mysqlbackup.sh').with_content(/.*ROTATE=24.*/)
+          end
+
+          it 'should have a standard PATH' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(%r{PATH=/usr/bin:/usr/sbin:/bin:/sbin:/opt/zimbra/bin})
+          end
+        end
+
+        context 'custom ownership and mode for backupdir' do
+          let(:params) do
+            { :backupdirmode => '0750',
+              :backupdirowner => 'testuser',
+              :backupdirgroup => 'testgrp',
+            }.merge(default_params)
+          end
+
+          it { is_expected.to contain_file('mysqlbackupdir').with(
+            :path => '/tmp',
+            :ensure => 'directory',
+            :mode => '0750',
+            :owner => 'testuser',
+            :group => 'testgrp'
+          ) }
+        end
+
+        context 'with compression disabled' do
+          let(:params) do
+            { :backupcompress => false }.merge(default_params)
+          end
+
+          it { is_expected.to contain_file('mysqlbackup.sh').with(
+            :path   => '/usr/local/sbin/mysqlbackup.sh',
+            :ensure => 'present'
+          ) }
+
+          it 'should be able to disable compression' do
+            is_expected.to contain_file('mysqlbackup.sh').without_content(
+              /.*bzcat -zc.*/
+            )
+          end
+        end
+
+        context 'with mysql.events backedup' do
+          let(:params) do
+            { :ignore_events => false }.merge(default_params)
+          end
+
+          it { is_expected.to contain_file('mysqlbackup.sh').with(
+            :path   => '/usr/local/sbin/mysqlbackup.sh',
+            :ensure => 'present'
+          ) }
+
+          it 'should be able to backup events table' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(
+              /ADDITIONAL_OPTIONS="--events"/
+            )
+          end
+        end
+
+        context 'with database list specified' do
+          let(:params) do
+            { :backupdatabases => ['mysql'] }.merge(default_params)
+          end
+
+          it { is_expected.to contain_file('mysqlbackup.sh').with(
+            :path   => '/usr/local/sbin/mysqlbackup.sh',
+            :ensure => 'present'
+            )
+          }
+
+          it 'should have a backup file for each database' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(
+              /mysql | bzcat -zc \${DIR}\\\${PREFIX}mysql_`date'/
+            )
+          end
+
+          it 'should skip backup triggers by default' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(
+              /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-triggers"/
+            )
+          end
+
+          it 'should skip backing up routines by default' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(
+               /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-routines"/
+            )
+          end
+
+          context 'with include_triggers set to true' do
+            let(:params) do
+              default_params.merge({
+                :backupdatabases => ['mysql'],
+                :include_triggers => true
+              })
+            end
+
+            it 'should backup triggers when asked' do
+              is_expected.to contain_file('mysqlbackup.sh').with_content(
+                /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --triggers"/
+              )
+            end
+          end
+
+          context 'with include_triggers set to false' do
+            let(:params) do
+              default_params.merge({
+                :backupdatabases => ['mysql'],
+                :include_triggers => false
+              })
+            end
+
+            it 'should skip backing up triggers when asked to skip' do
+              is_expected.to contain_file('mysqlbackup.sh').with_content(
+                /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-triggers"/
+              )
+            end
+          end
+
+          context 'with include_routines set to true' do
+            let(:params) do
+              default_params.merge({
+                :backupdatabases => ['mysql'],
+                :include_routines => true
+              })
+            end
+
+            it 'should backup routines when asked' do
+              is_expected.to contain_file('mysqlbackup.sh').with_content(
+                /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --routines"/
+              )
+            end
+          end
+
+          context 'with include_routines set to false' do
+            let(:params) do
+              default_params.merge({
+                :backupdatabases => ['mysql'],
+                :include_triggers => true
+              })
+            end
+
+            it 'should skip backing up routines when asked to skip' do
+              is_expected.to contain_file('mysqlbackup.sh').with_content(
+                /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-routines"/
+              )
+            end
+          end
+        end
+
+        context 'with file per database' do
+          let(:params) do
+            default_params.merge({ :file_per_database => true })
+          end
+
+          it 'should loop through backup all databases' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(/.*SHOW DATABASES.*/)
+          end
+
+          context 'with compression disabled' do
+            let(:params) do
+              default_params.merge({ :file_per_database => true, :backupcompress => false })
+            end
+
+            it 'should loop through backup all databases without compression' do
+              is_expected.to contain_file('mysqlbackup.sh').with_content(
+                /.*SHOW DATABASES.*/
+              )
+              is_expected.to contain_file('mysqlbackup.sh').without_content(
+                /.*bzcat -zc.*/
+              )
+            end
+          end
+
+          it 'should skip backup triggers by default' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(
+              /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-triggers"/
+            )
+          end
+
+          it 'should skip backing up routines by default' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(
+              /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-routines"/
+            )
+          end
+
+          context 'with include_triggers set to true' do
+            let(:params) do
+              default_params.merge({
+                :file_per_database => true,
+                :include_triggers => true
+              })
+            end
+
+            it 'should backup triggers when asked' do
+              is_expected.to contain_file('mysqlbackup.sh').with_content(
+                /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --triggers"/
+              )
+            end
+          end
+
+          context 'with include_triggers set to false' do
+            let(:params) do
+              default_params.merge({
+                :file_per_database => true,
+                :include_triggers => false
+              })
+            end
+
+            it 'should skip backing up triggers when asked to skip' do
+              is_expected.to contain_file('mysqlbackup.sh').with_content(
+                /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-triggers"/
+              )
+            end
+          end
+
+          context 'with include_routines set to true' do
+            let(:params) do
+              default_params.merge({
+                :file_per_database => true,
+                :include_routines => true
+              })
+            end
+
+            it 'should backup routines when asked' do
+              is_expected.to contain_file('mysqlbackup.sh').with_content(
+                /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --routines"/
+              )
+            end
+          end
+
+          context 'with include_routines set to false' do
+            let(:params) do
+              default_params.merge({
+                :file_per_database => true,
+                :include_triggers => true
+              })
+            end
+
+            it 'should skip backing up routines when asked to skip' do
+              is_expected.to contain_file('mysqlbackup.sh').with_content(
+                /ADDITIONAL_OPTIONS="\$ADDITIONAL_OPTIONS --skip-routines"/
+              )
+            end
+          end
+        end
+
+        context 'with postscript' do
+          let(:params) do
+            default_params.merge({ :postscript => 'rsync -a /tmp backup01.local-lan:' })
+          end
+
+          it 'should be add postscript' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(
+              /rsync -a \/tmp backup01.local-lan:/
+            )
+          end
+        end
+
+        context 'with postscripts' do
+          let(:params) do
+            default_params.merge({ :postscript => [
+              'rsync -a /tmp backup01.local-lan:',
+              'rsync -a /tmp backup02.local-lan:',
+            ]})
+          end
+
+          it 'should be add postscript' do
+            is_expected.to contain_file('mysqlbackup.sh').with_content(
+              /.*rsync -a \/tmp backup01.local-lan:\n\nrsync -a \/tmp backup02.local-lan:.*/
+            )
+          end
+        end
+
+        context 'with the xtrabackup provider' do
+          let(:params) do
+            default_params.merge({:provider => 'xtrabackup'})
+          end
+
+          it 'should contain the wrapper script' do
+            is_expected.to contain_file('xtrabackup.sh').with_content(
+              /^innobackupex\s+"\$@"/
+            )
+          end
+
+          context 'with prescript defined' do
+            let(:params) do
+              default_params.merge({
+                :provider  => 'xtrabackup',
+                :prescript => [
+                  'rsync -a /tmp backup01.local-lan:',
+                  'rsync -a /tmp backup02.local-lan:',
+                ]
+              })
+            end
+
+            it 'should contain the prescript' do
+              is_expected.to contain_file('xtrabackup.sh').with_content(
+                /.*rsync -a \/tmp backup01.local-lan:\n\nrsync -a \/tmp backup02.local-lan:.*/
+              )
+            end
+          end
+
+          context 'with postscript defined' do
+            let(:params) do
+              default_params.merge({
+                :provider  => 'xtrabackup',
+                :postscript => [
+                  'rsync -a /tmp backup01.local-lan:',
+                  'rsync -a /tmp backup02.local-lan:',
+                ]
+              })
+            end
+
+            it 'should contain the prostscript' do
+              is_expected.to contain_file('xtrabackup.sh').with_content(
+                /.*rsync -a \/tmp backup01.local-lan:\n\nrsync -a \/tmp backup02.local-lan:.*/
+              )
+            end
+          end
+        end
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/classes/mysql_server_monitor_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+require 'spec_helper'
+describe 'mysql::server::monitor' do
+  on_pe_supported_platforms(PLATFORMS).each do |pe_version,pe_platforms|
+    pe_platforms.each do |pe_platform,facts|
+      describe "on #{pe_version} #{pe_platform}" do
+        let(:facts) { facts }
+        let :pre_condition do
+          "include 'mysql::server'"
+        end
+
+        let :default_params do
+          {
+            :mysql_monitor_username   => 'monitoruser',
+            :mysql_monitor_password   => 'monitorpass',
+            :mysql_monitor_hostname   => 'monitorhost',
+          }
+        end
+
+        let :params do
+          default_params
+        end
+
+        it { is_expected.to contain_mysql_user('monitoruser@monitorhost')}
+
+        it { is_expected.to contain_mysql_grant('monitoruser@monitorhost/*.*').with(
+          :ensure     => 'present',
+          :user       => 'monitoruser@monitorhost',
+          :table      => '*.*',
+          :privileges => ["PROCESS", "SUPER"],
+          :require    => 'Mysql_user[monitoruser@monitorhost]'
+        )}
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/classes/mysql_server_mysqltuner_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe 'mysql::server::mysqltuner' do
+  on_pe_supported_platforms(PLATFORMS).each do |pe_version,pe_platforms|
+    pe_platforms.each do |pe_platform,facts|
+      describe "on #{pe_version} #{pe_platform}" do
+        let(:facts) { facts }
+
+        context 'ensure => present' do
+          it { is_expected.to compile }
+          it { is_expected.to contain_staging__file('mysqltuner-v1.3.0').with({
+            :source => 'https://github.com/major/MySQLTuner-perl/raw/v1.3.0/mysqltuner.pl',
+          })
+          }
+        end
+
+        context 'ensure => absent' do
+          let(:params) {{ :ensure => 'absent' }}
+          it { is_expected.to compile }
+          it { is_expected.to contain_file('/usr/local/bin/mysqltuner').with(:ensure => 'absent') }
+        end
+
+        context 'custom version' do
+          let(:params) {{ :version => 'v1.2.0' }}
+          it { is_expected.to compile }
+          it { is_expected.to contain_staging__file('mysqltuner-v1.2.0').with({
+            :source => 'https://github.com/major/MySQLTuner-perl/raw/v1.2.0/mysqltuner.pl',
+          })
+          }
+        end
+
+        context 'custom source' do
+          let(:params) {{ :source => '/tmp/foo' }}
+          it { is_expected.to compile }
+          it { is_expected.to contain_staging__file('mysqltuner-/tmp/foo').with({
+            :source => '/tmp/foo',
+          })
+          }
+        end
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/classes/mysql_server_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,187 @@
+require 'spec_helper'
+
+describe 'mysql::server' do
+  on_pe_supported_platforms(PLATFORMS).each do |pe_version,pe_platforms|
+    pe_platforms.each do |pe_platform,facts|
+      describe "on #{pe_version} #{pe_platform}" do
+        let(:facts) { facts }
+
+        context 'with defaults' do
+          it { is_expected.to contain_class('mysql::server::install') }
+          it { is_expected.to contain_class('mysql::server::config') }
+          it { is_expected.to contain_class('mysql::server::service') }
+          it { is_expected.to contain_class('mysql::server::root_password') }
+          it { is_expected.to contain_class('mysql::server::providers') }
+        end
+
+        context 'with remove_default_accounts set' do
+          let(:params) {{ :remove_default_accounts => true }}
+          it { is_expected.to contain_class('mysql::server::account_security') }
+        end
+
+        context 'mysql::server::install' do
+          it 'contains the package by default' do
+            is_expected.to contain_package('mysql-server').with({
+              :ensure => :present,
+            })
+          end
+          context 'with package_manage set to true' do
+            let(:params) {{ :package_manage => true }}
+            it { is_expected.to contain_package('mysql-server') }
+          end
+          context 'with package_manage set to false' do
+            let(:params) {{ :package_manage => false }}
+            it { is_expected.not_to contain_package('mysql-server') }
+          end
+          context 'with datadir overridden' do
+            let(:params) {{ :override_options => { 'mysqld' => { 'datadir' => '/tmp' }} }}
+            it { is_expected.to contain_exec('mysql_install_db') }
+          end
+        end
+
+        context 'mysql::server::service' do
+          context 'with defaults' do
+            it { is_expected.to contain_service('mysqld') }
+          end
+          context 'with package_manage set to true' do
+            let(:params) {{ :package_manage => true }}
+            it { is_expected.to contain_service('mysqld').that_requires('Package[mysql-server]') }
+          end
+          context 'with package_manage set to false' do
+            let(:params) {{ :package_manage => false }}
+            it { is_expected.to contain_service('mysqld') }
+            it { is_expected.not_to contain_service('mysqld').that_requires('Package[mysql-server]') }
+          end
+          context 'service_enabled set to false' do
+            let(:params) {{ :service_enabled => false }}
+
+            it do
+              is_expected.to contain_service('mysqld').with({
+                :ensure => :stopped
+              })
+            end
+          end
+          context 'with log-error overridden' do
+            let(:params) {{ :override_options => { 'mysqld' => { 'log-error' => '/tmp/error.log' }} }}
+            it { is_expected.to contain_file('/tmp/error.log') }
+          end
+        end
+
+        context 'mysql::server::root_password' do
+          describe 'when defaults' do
+            it {
+               is_expected.to contain_exec('remove install pass').with(
+                 :command => 'mysqladmin -u root --password=$(grep -o \'[^ ]\\+$\' /.mysql_secret) password \'\' && rm -f /.mysql_secret',
+                 :onlyif  => 'test -f /.mysql_secret',
+                 :path    => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin'
+               )
+             }
+            it { is_expected.not_to contain_mysql_user('root@localhost') }
+            it { is_expected.not_to contain_file('/root/.my.cnf') }
+          end
+          describe 'when root_password set' do
+            let(:params) {{:root_password => 'SET' }}
+            it { is_expected.to contain_mysql_user('root@localhost') }
+            it { is_expected.to contain_file('/root/.my.cnf').that_requires('Mysql_user[root@localhost]') }
+          end
+          describe 'when root_password set, create_root_user set to false' do
+            let(:params) {{ :root_password => 'SET', :create_root_user => false }}
+            it { is_expected.not_to contain_mysql_user('root@localhost') }
+            it { is_expected.to contain_file('/root/.my.cnf') }
+          end
+          describe 'when root_password set, create_root_my_cnf set to false' do
+            let(:params) {{ :root_password => 'SET', :create_root_my_cnf => false }}
+            it { is_expected.to contain_mysql_user('root@localhost') }
+            it { is_expected.not_to contain_file('/root/.my.cnf') }
+          end
+          describe 'when root_password set, create_root_user and create_root_my_cnf set to false' do
+            let(:params) {{ :root_password => 'SET', :create_root_user => false, :create_root_my_cnf => false }}
+            it { is_expected.not_to contain_mysql_user('root@localhost') }
+            it { is_expected.not_to contain_file('/root/.my.cnf') }
+          end
+          describe 'when install_secret_file set to /root/.mysql_secret' do
+            let(:params) {{ :install_secret_file => '/root/.mysql_secret' }}
+            it {
+              is_expected.to contain_exec('remove install pass').with(
+                 :command => 'mysqladmin -u root --password=$(grep -o \'[^ ]\\+$\' /root/.mysql_secret) password \'\' && rm -f /root/.mysql_secret',
+                 :onlyif  => 'test -f /root/.mysql_secret'
+              )
+            }
+          end 
+        end
+
+        context 'mysql::server::providers' do
+          describe 'with users' do
+            let(:params) {{:users => {
+              'foo@localhost' => {
+                'max_connections_per_hour' => '1',
+                'max_queries_per_hour'     => '2',
+                'max_updates_per_hour'     => '3',
+                'max_user_connections'     => '4',
+                'password_hash'            => '*F3A2A51A9B0F2BE2468926B4132313728C250DBF'
+              },
+              'foo2@localhost' => {}
+            }}}
+            it { is_expected.to contain_mysql_user('foo@localhost').with(
+              :max_connections_per_hour => '1',
+              :max_queries_per_hour     => '2',
+              :max_updates_per_hour     => '3',
+              :max_user_connections     => '4',
+              :password_hash            => '*F3A2A51A9B0F2BE2468926B4132313728C250DBF'
+            )}
+            it { is_expected.to contain_mysql_user('foo2@localhost').with(
+              :max_connections_per_hour => nil,
+              :max_queries_per_hour     => nil,
+              :max_updates_per_hour     => nil,
+              :max_user_connections     => nil,
+              :password_hash            => nil
+            )}
+          end
+
+          describe 'with grants' do
+            let(:params) {{:grants => {
+              'foo@localhost/somedb.*' => {
+                'user'       => 'foo@localhost',
+                'table'      => 'somedb.*',
+                'privileges' => ["SELECT", "UPDATE"],
+                'options'    => ["GRANT"],
+              },
+              'foo2@localhost/*.*' => {
+                'user'       => 'foo2@localhost',
+                'table'      => '*.*',
+                'privileges' => ["SELECT"],
+              },
+            }}}
+            it { is_expected.to contain_mysql_grant('foo@localhost/somedb.*').with(
+              :user       => 'foo@localhost',
+              :table      => 'somedb.*',
+              :privileges => ["SELECT", "UPDATE"],
+              :options    => ["GRANT"]
+            )}
+            it { is_expected.to contain_mysql_grant('foo2@localhost/*.*').with(
+              :user       => 'foo2@localhost',
+              :table      => '*.*',
+              :privileges => ["SELECT"],
+              :options    => nil
+            )}
+          end
+
+          describe 'with databases' do
+            let(:params) {{:databases => {
+              'somedb' => {
+                'charset' => 'latin1',
+                'collate' => 'latin1',
+              },
+              'somedb2' => {}
+            }}}
+            it { is_expected.to contain_mysql_database('somedb').with(
+              :charset => 'latin1',
+              :collate => 'latin1'
+            )}
+            it { is_expected.to contain_mysql_database('somedb2')}
+          end
+        end
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/defines/mysql_db_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,75 @@
+require 'spec_helper'
+
+describe 'mysql::db', :type => :define do
+  on_pe_supported_platforms(PLATFORMS).each do |pe_version,pe_platforms|
+    pe_platforms.each do |pe_platform,facts|
+      describe "on #{pe_version} #{pe_platform}" do
+        let(:facts) { facts }
+
+        let(:title) { 'test_db' }
+
+        let(:params) {
+          { 'user'     => 'testuser',
+            'password' => 'testpass',
+          }
+        }
+
+        it 'should report an error when ensure is not present or absent' do
+          params.merge!({'ensure' => 'invalid_val'})
+          expect { catalogue }.to raise_error(Puppet::Error,
+                                            /invalid_val is not supported for ensure\. Allowed values are 'present' and 'absent'\./)
+        end
+
+        it 'should not notify the import sql exec if no sql script was provided' do
+          is_expected.to contain_mysql_database('test_db').without_notify
+        end
+
+        it 'should subscribe to database if sql script is given' do
+          params.merge!({'sql' => 'test_sql'})
+          is_expected.to contain_exec('test_db-import').with_subscribe('Mysql_database[test_db]')
+        end
+
+        it 'should only import sql script on creation if not enforcing' do
+          params.merge!({'sql' => 'test_sql', 'enforce_sql' => false})
+          is_expected.to contain_exec('test_db-import').with_refreshonly(true)
+        end
+
+        it 'should import sql script on creation if enforcing' do
+          params.merge!({'sql' => 'test_sql', 'enforce_sql' => true})
+          is_expected.to contain_exec('test_db-import').with_refreshonly(false)
+          is_expected.to contain_exec('test_db-import').with_command("cat test_sql | mysql test_db")
+        end
+
+        it 'should import sql scripts when more than one is specified' do
+          params.merge!({'sql' => ['test_sql', 'test_2_sql']})
+          is_expected.to contain_exec('test_db-import').with_command('cat test_sql test_2_sql | mysql test_db')
+        end
+
+        it 'should report an error if sql isn\'t a string or an array' do
+          params.merge!({'sql' => {'foo' => 'test_sql', 'bar' => 'test_2_sql'}})
+          expect { catalogue }.to raise_error(Puppet::Error,
+                                            /\$sql must be either a string or an array\./)
+        end
+
+        it 'should not create database and database user' do
+          params.merge!({'ensure' => 'absent', 'host' => 'localhost'})
+          is_expected.to contain_mysql_database('test_db').with_ensure('absent')
+          is_expected.to contain_mysql_user('testuser@localhost').with_ensure('absent')
+        end
+
+        it 'should create with an appropriate collate and charset' do
+          params.merge!({'charset' => 'utf8', 'collate' => 'utf8_danish_ci'})
+          is_expected.to contain_mysql_database('test_db').with({
+            'charset' => 'utf8',
+            'collate' => 'utf8_danish_ci',
+          })
+        end
+
+        it 'should use dbname parameter as database name instead of name' do
+          params.merge!({'dbname' => 'real_db'})
+          is_expected.to contain_mysql_database('real_db')
+        end
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/spec.opts	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+--format
+s
+--colour
+--loadby
+mtime
+--backtrace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/spec_helper.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+require 'puppetlabs_spec_helper/module_spec_helper'
+require 'puppet_facts'
+include PuppetFacts
+
+# The default set of platforms to test again.
+ENV['UNIT_TEST_PLATFORMS'] = 'centos-6-x86_64 ubuntu-1404-x86_64'
+PLATFORMS = ENV['UNIT_TEST_PLATFORMS'].split(' ')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/spec_helper_acceptance.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,49 @@
+require 'beaker-rspec'
+require 'beaker/puppet_install_helper'
+
+run_puppet_install_helper
+
+UNSUPPORTED_PLATFORMS = [ 'Windows', 'Solaris', 'AIX' ]
+
+RSpec.configure do |c|
+  # Project root
+  proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+  # Readable test descriptions
+  c.formatter = :documentation
+
+  # Configure all nodes in nodeset
+  c.before :suite do
+    # Install module and dependencies
+    puppet_module_install(:source => proj_root, :module_name => 'mysql')
+    hosts.each do |host|
+      # Required for binding tests.
+      if fact('osfamily') == 'RedHat'
+        version = fact("operatingsystemmajrelease")
+        if fact('operatingsystemmajrelease') =~ /7/ || fact('operatingsystem') =~ /Fedora/
+          shell("yum install -y bzip2")
+        end
+      end
+
+      # Solaris 11 doesn't ship the SSL CA root for the forgeapi server
+      # therefore we need to use a different way to deploy the module to
+      # the host
+      if host['platform'] =~ /solaris-11/i
+        apply_manifest_on(host, 'package { "git": }')
+        # PE 3.x and 2015.2 require different locations to install modules
+        modulepath = host.puppet['modulepath']
+        modulepath = modulepath.split(':').first if modulepath
+
+        environmentpath = host.puppet['environmentpath']
+        environmentpath = environmentpath.split(':').first if environmentpath
+
+        destdir = modulepath || "#{environmentpath}/production/modules"
+        on host, "git clone https://github.com/puppetlabs/puppetlabs-stdlib #{destdir}/stdlib && cd #{destdir}/stdlib && git checkout 3.2.0"
+        on host, "git clone https://github.com/stahnma/puppet-module-epel.git #{destdir}/epel && cd #{destdir}/epel && git checkout 1.0.2"
+      else
+        on host, puppet('module','install','puppetlabs-stdlib','--version','3.2.0')
+        on host, puppet('module','install','stahnma/epel')
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/unit/facter/mysql_server_id_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+require "spec_helper"
+
+describe Facter::Util::Fact do
+  before {
+    Facter.clear
+  }
+
+  describe "mysql_server_id" do
+    context "igalic's laptop" do
+      before :each do
+        Facter.fact(:macaddress).stubs(:value).returns('3c:97:0e:69:fb:e1')
+      end
+      it do
+        Facter.fact(:mysql_server_id).value.to_s.should == '72898961'
+      end
+    end
+
+    context "node with lo only" do
+      before :each do
+        Facter.fact(:macaddress).stubs(:value).returns('00:00:00:00:00:00')
+      end
+      it do
+        Facter.fact(:mysql_server_id).value.to_s.should == '0'
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/unit/facter/mysql_version_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+require "spec_helper"
+
+describe Facter::Util::Fact do
+  before {
+    Facter.clear
+  }
+
+  describe "mysql_version" do
+    context 'with value' do
+      before :each do
+        Facter::Util::Resolution.stubs(:exec).with('mysql --version').returns('mysql  Ver 14.12 Distrib 5.0.95, for redhat-linux-gnu (x86_64) using readline 5.1')
+      end
+      it {
+        expect(Facter.fact(:mysql_version).value).to eq('5.0.95')
+      }
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/unit/puppet/functions/mysql_deepmerge_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,91 @@
+#! /usr/bin/env ruby -S rspec
+
+require 'spec_helper'
+
+describe Puppet::Parser::Functions.function(:mysql_deepmerge) do
+  let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+  describe 'when calling mysql_deepmerge from puppet' do
+    it "should not compile when no arguments are passed" do
+      skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
+      Puppet[:code] = '$x = mysql_deepmerge()'
+      expect {
+        scope.compiler.compile
+      }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
+    end
+
+    it "should not compile when 1 argument is passed" do
+      skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./
+      Puppet[:code] = "$my_hash={'one' => 1}\n$x = mysql_deepmerge($my_hash)"
+      expect {
+        scope.compiler.compile
+      }.to raise_error(Puppet::ParseError, /wrong number of arguments/)
+    end
+  end
+
+  describe 'when calling mysql_deepmerge on the scope instance' do
+    it 'should require all parameters are hashes' do
+      expect { new_hash = scope.function_mysql_deepmerge([{}, '2'])}.to raise_error(Puppet::ParseError, /unexpected argument type String/)
+      expect { new_hash = scope.function_mysql_deepmerge([{}, 2])}.to raise_error(Puppet::ParseError, /unexpected argument type Fixnum/)
+    end
+
+    it 'should accept empty strings as puppet undef' do
+      expect { new_hash = scope.function_mysql_deepmerge([{}, ''])}.not_to raise_error
+    end
+
+    it 'should be able to mysql_deepmerge two hashes' do
+      new_hash = scope.function_mysql_deepmerge([{'one' => '1', 'two' => '1'}, {'two' => '2', 'three' => '2'}])
+      expect(new_hash['one']).to   eq('1')
+      expect(new_hash['two']).to   eq('2')
+      expect(new_hash['three']).to eq('2')
+    end
+
+    it 'should mysql_deepmerge multiple hashes' do
+      hash = scope.function_mysql_deepmerge([{'one' => 1}, {'one' => '2'}, {'one' => '3'}])
+      expect(hash['one']).to eq('3')
+    end
+
+    it 'should accept empty hashes' do
+      expect(scope.function_mysql_deepmerge([{},{},{}])).to eq({})
+    end
+
+    it 'should mysql_deepmerge subhashes' do
+      hash = scope.function_mysql_deepmerge([{'one' => 1}, {'two' => 2, 'three' => { 'four' => 4 } }])
+      expect(hash['one']).to eq(1)
+      expect(hash['two']).to eq(2)
+      expect(hash['three']).to eq({ 'four' => 4 })
+    end
+
+    it 'should append to subhashes' do
+      hash = scope.function_mysql_deepmerge([{'one' => { 'two' => 2 } }, { 'one' => { 'three' => 3 } }])
+      expect(hash['one']).to eq({ 'two' => 2, 'three' => 3 })
+    end
+
+    it 'should append to subhashes 2' do
+      hash = scope.function_mysql_deepmerge([{'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }, {'two' => 'dos', 'three' => { 'five' => 5 } }])
+      expect(hash['one']).to eq(1)
+      expect(hash['two']).to eq('dos')
+      expect(hash['three']).to eq({ 'four' => 4, 'five' => 5 })
+    end
+
+    it 'should append to subhashes 3' do
+      hash = scope.function_mysql_deepmerge([{ 'key1' => { 'a' => 1, 'b' => 2 }, 'key2' => { 'c' => 3 } }, { 'key1' => { 'b' => 99 } }])
+      expect(hash['key1']).to eq({ 'a' => 1, 'b' => 99 })
+      expect(hash['key2']).to eq({ 'c' => 3 })
+    end
+
+    it 'should equate keys mod dash and underscore' do
+      hash = scope.function_mysql_deepmerge([{  'a-b-c' => 1 } , { 'a_b_c' => 10 }])
+      expect(hash['a_b_c']).to eq(10)
+      expect(hash).not_to have_key('a-b-c')
+    end
+
+    it 'should keep style of the last when keys are euqal mod dash and underscore' do
+      hash = scope.function_mysql_deepmerge([{  'a-b-c' => 1,  'b_c_d' => { 'c-d-e' => 2, 'e-f-g' => 3 }} , { 'a_b_c' => 10, 'b-c-d' => { 'c_d_e' => 12 } }])
+      expect(hash['a_b_c']).to eq(10)
+      expect(hash).not_to have_key('a-b-c')
+      expect(hash['b-c-d']).to eq({ 'e-f-g' => 3, 'c_d_e' => 12 })
+      expect(hash).not_to have_key('b_c_d')
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/unit/puppet/functions/mysql_password_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe 'the mysql_password function' do
+  before :all do
+    Puppet::Parser::Functions.autoloader.loadall
+  end
+
+  let(:scope) { PuppetlabsSpec::PuppetInternals.scope }
+
+  it 'should exist' do
+    expect(Puppet::Parser::Functions.function('mysql_password')).to eq('function_mysql_password')
+  end
+
+  it 'should raise a ParseError if there is less than 1 arguments' do
+    expect { scope.function_mysql_password([]) }.to( raise_error(Puppet::ParseError))
+  end
+
+  it 'should raise a ParseError if there is more than 1 arguments' do
+    expect { scope.function_mysql_password(%w(foo bar)) }.to( raise_error(Puppet::ParseError))
+  end
+
+  it 'should convert password into a hash' do
+    result = scope.function_mysql_password(%w(password))
+    expect(result).to(eq('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19'))
+  end
+  
+  it 'should convert an empty password into a empty string' do
+    result = scope.function_mysql_password([""])
+    expect(result).to(eq(''))
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/unit/puppet/provider/mysql_database/mysql_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,118 @@
+require 'spec_helper'
+
+describe Puppet::Type.type(:mysql_database).provider(:mysql) do
+
+  let(:defaults_file) { '--defaults-extra-file=/root/.my.cnf' }
+
+  let(:raw_databases) do
+    <<-SQL_OUTPUT
+information_schema
+mydb
+mysql
+performance_schema
+test
+    SQL_OUTPUT
+  end
+
+  let(:parsed_databases) { %w(information_schema mydb mysql performance_schema test) }
+
+  let(:resource) { Puppet::Type.type(:mysql_database).new(
+    { :ensure   => :present,
+      :charset  => 'latin1',
+      :collate  => 'latin1_swedish_ci',
+      :name     => 'new_database',
+      :provider => described_class.name
+    }
+  )}
+  let(:provider) { resource.provider }
+
+  before :each do
+    Facter.stubs(:value).with(:root_home).returns('/root')
+    Puppet::Util.stubs(:which).with('mysql').returns('/usr/bin/mysql')
+    File.stubs(:file?).with('/root/.my.cnf').returns(true)
+    provider.class.stubs(:mysql).with([defaults_file, '-NBe', 'show databases']).returns('new_database')
+    provider.class.stubs(:mysql).with([defaults_file, '-NBe', "show variables like '%_database'", 'new_database']).returns("character_set_database latin1\ncollation_database latin1_swedish_ci\nskip_show_database OFF")
+  end
+
+  let(:instance) { provider.class.instances.first }
+
+  describe 'self.instances' do
+    it 'returns an array of databases' do
+      provider.class.stubs(:mysql).with([defaults_file, '-NBe', 'show databases']).returns(raw_databases)
+      raw_databases.each_line do |db|
+        provider.class.stubs(:mysql).with([defaults_file, '-NBe', "show variables like '%_database'", db.chomp]).returns("character_set_database latin1\ncollation_database  latin1_swedish_ci\nskip_show_database  OFF")
+      end
+      databases = provider.class.instances.collect {|x| x.name }
+      expect(parsed_databases).to match_array(databases)
+    end
+  end
+
+  describe 'self.prefetch' do
+    it 'exists' do
+      provider.class.instances
+      provider.class.prefetch({})
+    end
+  end
+
+  describe 'create' do
+    it 'makes a database' do
+      provider.expects(:mysql).with([defaults_file, '-NBe', "create database if not exists `#{resource[:name]}` character set `#{resource[:charset]}` collate `#{resource[:collate]}`"])
+      provider.expects(:exists?).returns(true)
+      expect(provider.create).to be_truthy
+    end
+  end
+
+  describe 'destroy' do
+    it 'removes a database if present' do
+      provider.expects(:mysql).with([defaults_file, '-NBe', "drop database if exists `#{resource[:name]}`"])
+      provider.expects(:exists?).returns(false)
+      expect(provider.destroy).to be_truthy
+    end
+  end
+
+  describe 'exists?' do
+    it 'checks if database exists' do
+      expect(instance.exists?).to be_truthy
+    end
+  end
+
+  describe 'self.defaults_file' do
+    it 'sets --defaults-extra-file' do
+      File.stubs(:file?).with('/root/.my.cnf').returns(true)
+      expect(provider.defaults_file).to eq '--defaults-extra-file=/root/.my.cnf'
+    end
+    it 'fails if file missing' do
+      File.stubs(:file?).with('/root/.my.cnf').returns(false)
+      expect(provider.defaults_file).to be_nil
+    end
+  end
+
+  describe 'charset' do
+    it 'returns a charset' do
+      expect(instance.charset).to eq('latin1')
+    end
+  end
+
+  describe 'charset=' do
+    it 'changes the charset' do
+      provider.expects(:mysql).with([defaults_file, '-NBe', "alter database `#{resource[:name]}` CHARACTER SET blah"]).returns('0')
+
+      provider.charset=('blah')
+    end
+  end
+
+  describe 'collate' do
+    it 'returns a collate' do
+      expect(instance.collate).to eq('latin1_swedish_ci')
+    end
+  end
+
+  describe 'collate=' do
+    it 'changes the collate' do
+      provider.expects(:mysql).with([defaults_file, '-NBe', "alter database `#{resource[:name]}` COLLATE blah"]).returns('0')
+
+      provider.collate=('blah')
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/unit/puppet/provider/mysql_plugin/mysql_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,71 @@
+require 'spec_helper'
+
+describe Puppet::Type.type(:mysql_plugin).provider(:mysql) do
+
+  let(:defaults_file) { '--defaults-extra-file=/root/.my.cnf' }
+
+  let(:resource) { Puppet::Type.type(:mysql_plugin).new(
+    { :ensure   => :present,
+      :soname   => 'auth_socket.so',
+      :name     => 'auth_socket',
+      :provider => described_class.name
+    }
+  )}
+  let(:provider) { resource.provider }
+
+  before :each do
+    Facter.stubs(:value).with(:root_home).returns('/root')
+    Puppet::Util.stubs(:which).with('mysql').returns('/usr/bin/mysql')
+    File.stubs(:file?).with('/root/.my.cnf').returns(true)
+    provider.class.stubs(:mysql).with([defaults_file, '-NBe', 'show plugins']).returns('auth_socket	ACTIVE	AUTHENTICATION	auth_socket.so	GPL')
+  end
+
+  let(:instance) { provider.class.instances.first }
+
+  describe 'self.prefetch' do
+    it 'exists' do
+      provider.class.instances
+      provider.class.prefetch({})
+    end
+  end
+
+  describe 'create' do
+    it 'loads a plugin' do
+      provider.expects(:mysql).with([defaults_file, '-NBe', "install plugin #{resource[:name]} soname '#{resource[:soname]}'"])
+      provider.expects(:exists?).returns(true)
+      expect(provider.create).to be_truthy
+    end
+  end
+
+  describe 'destroy' do
+    it 'unloads a plugin if present' do
+      provider.expects(:mysql).with([defaults_file, '-NBe', "uninstall plugin #{resource[:name]}"])
+      provider.expects(:exists?).returns(false)
+      expect(provider.destroy).to be_truthy
+    end
+  end
+
+  describe 'exists?' do
+    it 'checks if plugin exists' do
+      expect(instance.exists?).to be_truthy
+    end
+  end
+
+  describe 'self.defaults_file' do
+    it 'sets --defaults-extra-file' do
+      File.stubs(:file?).with('/root/.my.cnf').returns(true)
+      expect(provider.defaults_file).to eq '--defaults-extra-file=/root/.my.cnf'
+    end
+    it 'fails if file missing' do
+      File.stubs(:file?).with('/root/.my.cnf').returns(false)
+      expect(provider.defaults_file).to be_nil
+    end
+  end
+
+  describe 'soname' do
+    it 'returns a soname' do
+      expect(instance.soname).to eq('auth_socket.so')
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/unit/puppet/provider/mysql_user/mysql_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,132 @@
+require 'spec_helper'
+
+describe Puppet::Type.type(:mysql_user).provider(:mysql) do
+  let(:defaults_file) { '--defaults-extra-file=/root/.my.cnf' }
+  let(:newhash) { '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5' }
+
+  let(:raw_users) do
+    <<-SQL_OUTPUT
+root@127.0.0.1
+root@::1
+@localhost
+debian-sys-maint@localhost
+root@localhost
+usvn_user@localhost
+@vagrant-ubuntu-raring-64
+    SQL_OUTPUT
+  end
+
+  let(:parsed_users) { %w(root@127.0.0.1 root@::1 @localhost debian-sys-maint@localhost root@localhost usvn_user@localhost @vagrant-ubuntu-raring-64) }
+
+  let(:resource) { Puppet::Type.type(:mysql_user).new(
+      { :ensure                   => :present,
+        :password_hash            => '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4',
+        :name                     => 'joe@localhost',
+        :max_user_connections     => '10',
+        :max_connections_per_hour => '10',
+        :max_queries_per_hour     => '10',
+        :max_updates_per_hour     => '10',
+        :provider                 => described_class.name
+      }
+  )}
+  let(:provider) { resource.provider }
+
+  before :each do
+    # Set up the stubs for an instances call.
+    Facter.stubs(:value).with(:root_home).returns('/root')
+    Facter.stubs(:value).with(:mysql_version).returns('5.6.24')
+    Puppet::Util.stubs(:which).with('mysql').returns('/usr/bin/mysql')
+    File.stubs(:file?).with('/root/.my.cnf').returns(true)
+    provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT CONCAT(User, '@',Host) AS User FROM mysql.user"]).returns('joe@localhost')
+    provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, PASSWORD /*!50508 , PLUGIN */ FROM mysql.user WHERE CONCAT(user, '@', host) = 'joe@localhost'"]).returns('10 10 10 10 *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4')
+  end
+
+  let(:instance) { provider.class.instances.first }
+
+  describe 'self.instances' do
+    it 'returns an array of users' do
+      provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT CONCAT(User, '@',Host) AS User FROM mysql.user"]).returns(raw_users)
+      parsed_users.each do |user|
+        provider.class.stubs(:mysql).with([defaults_file, '-NBe', "SELECT MAX_USER_CONNECTIONS, MAX_CONNECTIONS, MAX_QUESTIONS, MAX_UPDATES, PASSWORD /*!50508 , PLUGIN */ FROM mysql.user WHERE CONCAT(user, '@', host) = '#{user}'"]).returns('10 10 10 10 ')
+      end
+
+      usernames = provider.class.instances.collect {|x| x.name }
+      expect(parsed_users).to match_array(usernames)
+    end
+  end
+
+  describe 'self.prefetch' do
+    it 'exists' do
+      provider.class.instances
+      provider.class.prefetch({})
+    end
+  end
+
+  describe 'create' do
+    it 'makes a user' do
+      provider.expects(:mysql).with([defaults_file, '-e', "CREATE USER 'joe'@'localhost' IDENTIFIED BY PASSWORD '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4'"])
+      provider.expects(:mysql).with([defaults_file, '-e', "GRANT USAGE ON *.* TO 'joe'@'localhost' WITH MAX_USER_CONNECTIONS 10 MAX_CONNECTIONS_PER_HOUR 10 MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 10"])
+      provider.expects(:exists?).returns(true)
+      expect(provider.create).to be_truthy
+    end
+  end
+
+  describe 'destroy' do
+    it 'removes a user if present' do
+      provider.expects(:mysql).with([defaults_file, '-e', "DROP USER 'joe'@'localhost'"])
+      provider.expects(:exists?).returns(false)
+      expect(provider.destroy).to be_truthy
+    end
+  end
+
+  describe 'exists?' do
+    it 'checks if user exists' do
+      expect(instance.exists?).to be_truthy
+    end
+  end
+
+  describe 'self.defaults_file' do
+    it 'sets --defaults-extra-file' do
+      File.stubs(:file?).with('/root/.my.cnf').returns(true)
+      expect(provider.defaults_file).to eq '--defaults-extra-file=/root/.my.cnf'
+    end
+    it 'fails if file missing' do
+      File.expects(:file?).with('/root/.my.cnf').returns(false)
+      expect(provider.defaults_file).to be_nil
+    end
+  end
+
+  describe 'password_hash' do
+    it 'returns a hash' do
+      expect(instance.password_hash).to eq('*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4')
+    end
+  end
+
+  describe 'password_hash=' do
+    it 'changes the hash' do
+      provider.expects(:mysql).with([defaults_file, '-e', "SET PASSWORD FOR 'joe'@'localhost' = '*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5'"]).returns('0')
+
+      provider.expects(:password_hash).returns('*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5')
+      provider.password_hash=('*6C8989366EAF75BB670AD8EA7A7FC1176A95CEF5')
+    end
+  end
+
+  ['max_user_connections', 'max_connections_per_hour', 'max_queries_per_hour',
+   'max_updates_per_hour'].each do |property|
+
+    describe property do
+      it "returns #{property}" do
+        expect(instance.send("#{property}".to_sym)).to eq('10')
+      end
+    end
+
+    describe "#{property}=" do
+      it "changes #{property}" do
+        provider.expects(:mysql).with([defaults_file, '-e', "GRANT USAGE ON *.* TO 'joe'@'localhost' WITH #{property.upcase} 42"]).returns('0')
+        provider.expects(property.to_sym).returns('42')
+        provider.send("#{property}=".to_sym, '42')
+      end
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/unit/puppet/type/mysql_database_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,29 @@
+require 'puppet'
+require 'puppet/type/mysql_database'
+describe Puppet::Type.type(:mysql_database) do
+
+  before :each do
+    @user = Puppet::Type.type(:mysql_database).new(:name => 'test', :charset => 'utf8', :collate => 'utf8_blah_ci')
+  end
+
+  it 'should accept a database name' do
+    expect(@user[:name]).to eq('test')
+  end
+
+  it 'should accept a charset' do
+    @user[:charset] = 'latin1'
+    expect(@user[:charset]).to eq('latin1')
+  end
+
+  it 'should accept a collate' do
+    @user[:collate] = 'latin1_swedish_ci'
+    expect(@user[:collate]).to eq('latin1_swedish_ci')
+  end
+
+  it 'should require a name' do
+    expect {
+      Puppet::Type.type(:mysql_database).new({})
+    }.to raise_error(Puppet::Error, 'Title or name must be provided')
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/unit/puppet/type/mysql_grant_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,74 @@
+require 'puppet'
+require 'puppet/type/mysql_grant'
+describe Puppet::Type.type(:mysql_grant) do
+
+  before :each do
+    @user = Puppet::Type.type(:mysql_grant).new(:name => 'foo@localhost/*.*', :privileges => ['ALL', 'PROXY'], :table => ['*.*','@'], :user => 'foo@localhost')
+  end
+
+  it 'should accept a grant name' do
+    expect(@user[:name]).to eq('foo@localhost/*.*')
+  end
+  
+  it 'should accept ALL privileges' do
+    @user[:privileges] = 'ALL'
+    expect(@user[:privileges]).to eq(['ALL'])
+  end
+
+  it 'should accept PROXY privilege' do
+    @user[:privileges] = 'PROXY'
+    expect(@user[:privileges]).to eq(['PROXY'])
+  end
+  
+  it 'should accept a table' do
+    @user[:table] = '*.*'
+    expect(@user[:table]).to eq('*.*')
+  end
+  
+  it 'should accept @ for table' do
+    @user[:table] = '@'
+    expect(@user[:table]).to eq('@')
+  end
+  
+  it 'should accept a user' do
+    @user[:user] = 'foo@localhost'
+    expect(@user[:user]).to eq('foo@localhost')
+  end
+  
+  it 'should require a name' do
+    expect {
+      Puppet::Type.type(:mysql_grant).new({})
+    }.to raise_error(Puppet::Error, 'Title or name must be provided')
+  end
+
+  it 'should require the name to match the user and table' do
+    expect {
+      Puppet::Type.type(:mysql_grant).new(:name => 'foo', :privileges => ['ALL', 'PROXY'], :table => ['*.*','@'], :user => 'foo@localhost')
+    }.to raise_error /name must match user and table parameters/
+  end
+
+  describe 'it should munge privileges' do
+
+    it 'to just ALL' do
+      @user = Puppet::Type.type(:mysql_grant).new(
+        :name => 'foo@localhost/*.*',  :table => ['*.*','@'], :user => 'foo@localhost',
+        :privileges => ['ALL', 'PROXY'] )
+      expect(@user[:privileges]).to eq(['ALL'])
+    end
+
+    it 'to upcase and ordered' do
+      @user = Puppet::Type.type(:mysql_grant).new(
+        :name => 'foo@localhost/*.*',  :table => ['*.*','@'], :user => 'foo@localhost',
+        :privileges => ['select', 'Insert'] )
+      expect(@user[:privileges]).to eq(['INSERT', 'SELECT'])
+    end
+
+    it 'ordered including column privileges' do
+      @user = Puppet::Type.type(:mysql_grant).new(
+        :name => 'foo@localhost/*.*',  :table => ['*.*','@'], :user => 'foo@localhost',
+        :privileges => ['SELECT(Host,Address)', 'Insert'] )
+      expect(@user[:privileges]).to eq(['INSERT', 'SELECT (Address, Host)'])
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/unit/puppet/type/mysql_plugin_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'puppet'
+require 'puppet/type/mysql_plugin'
+describe Puppet::Type.type(:mysql_plugin) do
+
+  before :each do
+    @plugin = Puppet::Type.type(:mysql_plugin).new(:name => 'test', :soname => 'test.so')
+  end
+
+  it 'should accept a plugin name' do
+    expect(@plugin[:name]).to eq('test')
+  end
+
+  it 'should accept a library name' do
+    @plugin[:soname] = 'test.so'
+    expect(@plugin[:soname]).to eq('test.so')
+  end
+
+  it 'should require a name' do
+    expect {
+      Puppet::Type.type(:mysql_plugin).new({})
+    }.to raise_error(Puppet::Error, 'Title or name must be provided')
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/spec/unit/puppet/type/mysql_user_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,131 @@
+require 'puppet'
+require 'puppet/type/mysql_user'
+describe Puppet::Type.type(:mysql_user) do
+
+  context "On MySQL 5.x" do
+    let(:facts) {{ :mysql_version => '5.6.24' }}
+    it 'should fail with a long user name' do
+      expect {
+        Puppet::Type.type(:mysql_user).new({:name => '12345678901234567@localhost', :password_hash => 'pass'})
+      }.to raise_error /MySQL usernames are limited to a maximum of 16 characters/
+    end
+  end
+
+  context "On MariaDB 10.0.0+" do
+    let(:facts) {{ :mysql_version => '10.0.19' }}
+    it 'should succeed with a long user name on MariaDB' do
+      expect {
+        Puppet::Type.type(:mysql_user).new({:name => '12345678901234567@localhost', :password_hash => 'pass'})
+      }.to raise_error /MySQL usernames are limited to a maximum of 16 characters/
+    end
+  end
+
+  it 'should require a name' do
+    expect {
+      Puppet::Type.type(:mysql_user).new({})
+    }.to raise_error(Puppet::Error, 'Title or name must be provided')
+  end
+
+  context 'using foo@localhost' do
+    before :each do
+      @user = Puppet::Type.type(:mysql_user).new(:name => 'foo@localhost', :password_hash => 'pass')
+    end
+
+    it 'should accept a user name' do
+      expect(@user[:name]).to eq('foo@localhost')
+    end
+
+    it 'should accept a password' do
+      @user[:password_hash] = 'foo'
+      expect(@user[:password_hash]).to eq('foo')
+    end
+  end
+
+  context 'using foo@LocalHost' do
+    before :each do
+      @user = Puppet::Type.type(:mysql_user).new(:name => 'foo@LocalHost', :password_hash => 'pass')
+    end
+
+    it 'should lowercase the user name' do
+      expect(@user[:name]).to eq('foo@localhost')
+    end
+  end
+
+  context 'using foo@192.168.1.0/255.255.255.0' do
+    before :each do
+      @user = Puppet::Type.type(:mysql_user).new(:name => 'foo@192.168.1.0/255.255.255.0', :password_hash => 'pass')
+    end
+
+    it 'should create the user with the netmask' do
+      expect(@user[:name]).to eq('foo@192.168.1.0/255.255.255.0')
+    end
+  end
+
+  context 'using allo_wed$char@localhost' do
+    before :each do
+      @user = Puppet::Type.type(:mysql_user).new(:name => 'allo_wed$char@localhost', :password_hash => 'pass')
+    end
+
+    it 'should accept a user name' do
+      expect(@user[:name]).to eq('allo_wed$char@localhost')
+    end
+  end
+
+  context 'ensure the default \'debian-sys-main\'@localhost user can be parsed' do
+    before :each do
+      @user = Puppet::Type.type(:mysql_user).new(:name => '\'debian-sys-maint\'@localhost', :password_hash => 'pass')
+    end
+
+    it 'should accept a user name' do
+      expect(@user[:name]).to eq('\'debian-sys-maint\'@localhost')
+    end
+  end
+
+  context 'using a quoted 16 char username' do
+    let(:facts) {{ :mysql_version => '5.6.24' }}
+    before :each do
+      @user = Puppet::Type.type(:mysql_user).new(:name => '"debian-sys-maint"@localhost', :password_hash => 'pass')
+    end
+
+    it 'should accept a user name' do
+      expect(@user[:name]).to eq('"debian-sys-maint"@localhost')
+    end
+  end
+
+  context 'using a quoted username that is too long ' do
+    let(:facts) {{ :mysql_version => '5.6.24' }}
+    it 'should fail with a size error' do
+      expect {
+        Puppet::Type.type(:mysql_user).new(:name => '"debian-sys-maint2"@localhost', :password_hash => 'pass')
+      }.to raise_error /MySQL usernames are limited to a maximum of 16 characters/
+    end
+  end
+
+  context 'using `speci!al#`@localhost' do
+    before :each do
+      @user = Puppet::Type.type(:mysql_user).new(:name => '`speci!al#`@localhost', :password_hash => 'pass')
+    end
+
+    it 'should accept a quoted user name with special chatracters' do
+      expect(@user[:name]).to eq('`speci!al#`@localhost')
+    end
+  end
+
+  context 'using in-valid@localhost' do
+    before :each do
+      @user = Puppet::Type.type(:mysql_user).new(:name => 'in-valid@localhost', :password_hash => 'pass')
+    end
+
+    it 'should accept a user name with special chatracters' do
+      expect(@user[:name]).to eq('in-valid@localhost')
+    end
+  end
+
+  context 'using "misquoted@localhost' do
+    it 'should fail with a misquoted username is used' do
+      expect {
+        Puppet::Type.type(:mysql_user).new(:name => '"misquoted@localhost', :password_hash => 'pass')
+      }.to raise_error /Invalid database user "misquoted@localhost/
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/templates/meb.cnf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+### MANAGED BY PUPPET ###
+
+<% @options.sort.map do |k,v| -%>
+<%   if v.is_a?(Hash) -%>
+[<%=   k %>]
+<%     v.sort.map do |ki, vi| -%>
+<%       if vi == true or v == '' -%>
+<%=        ki %>
+<%       elsif vi.is_a?(Array) -%>
+<%         vi.each do |vii| -%>
+<%=          ki %> = <%= vii %>
+<%         end -%>
+<%       elsif ![nil, '', :undef].include?(vi) -%>
+<%=        ki %> = <%= vi %>
+<%       end -%>
+<%     end -%>
+<%   end %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/templates/my.cnf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+### MANAGED BY PUPPET ###
+
+<% @options.sort.map do |k,v| -%>
+<%   if v.is_a?(Hash) -%>
+[<%=   k %>]
+<%     v.sort.map do |ki, vi| -%>
+<%       if ki == 'ssl-disable' or (ki =~ /^ssl/ and v['ssl-disable'] == true) -%>
+<%         next %>
+<%       elsif vi == true or v == '' -%>
+<%=        ki %>
+<%       elsif vi.is_a?(Array) -%>
+<%         vi.each do |vii| -%>
+<%=          ki %> = <%= vii %>
+<%         end -%>
+<%       elsif ![nil, '', :undef].include?(vi) -%>
+<%=        ki %> = <%= vi %>
+<%       end -%>
+<%     end -%>
+<%   end %>
+<% end -%>
+
+<% if @includedir and @includedir != '' %>
+!includedir <%= @includedir %>
+<% end %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/templates/my.cnf.pass.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+### MANAGED BY PUPPET ###
+
+[client]
+user=root
+host=localhost
+<% unless scope.lookupvar('mysql::server::root_password') == 'UNSET' -%>
+password='<%= scope.lookupvar('mysql::server::root_password') %>'
+<% end -%>
+socket=<%= @options['client']['socket'] -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/templates/mysqlbackup.sh.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,93 @@
+<%- if @kernel == 'Linux' -%>
+#!/bin/bash
+<%- else -%>
+#!/bin/sh
+<%- end -%>
+#
+# MySQL Backup Script
+#  Dumps mysql databases to a file for another backup tool to pick up.
+#
+# MySQL code:
+# GRANT SELECT, RELOAD, LOCK TABLES ON *.* TO 'user'@'localhost'
+# IDENTIFIED BY 'password';
+# FLUSH PRIVILEGES;
+#
+##### START CONFIG ###################################################
+
+USER=<%= @backupuser %>
+PASS='<%= @backuppassword %>'
+DIR=<%= @backupdir %>
+ROTATE=<%= [ Integer(@backuprotate) - 1, 0 ].max %>
+
+PREFIX=mysql_backup_
+<% if @ignore_events %>
+ADDITIONAL_OPTIONS="--ignore-table=mysql.event"
+<% else %>
+ADDITIONAL_OPTIONS="--events"
+<% end %>
+<%# Only include routines or triggers if we're doing a file per database -%>
+<%# backup. This happens if we named databases, or if we explicitly set -%>
+<%# file per database mode -%>
+<% if !@backupdatabases.empty? || @file_per_database -%>
+<% if @include_triggers -%>
+ADDITIONAL_OPTIONS="$ADDITIONAL_OPTIONS --triggers"
+<% else -%>
+ADDITIONAL_OPTIONS="$ADDITIONAL_OPTIONS --skip-triggers"
+<% end -%>
+<% if @include_routines -%>
+ADDITIONAL_OPTIONS="$ADDITIONAL_OPTIONS --routines"
+<% else -%>
+ADDITIONAL_OPTIONS="$ADDITIONAL_OPTIONS --skip-routines"
+<% end -%>
+<% end -%>
+
+##### STOP CONFIG ####################################################
+PATH=<%= @execpath %>
+
+
+
+<%- if @kernel == 'Linux' -%>
+set -o pipefail
+<%- end -%>
+
+cleanup()
+{
+    find "${DIR}/" -maxdepth 1 -type f -name "${PREFIX}*.sql*" -mtime +${ROTATE} -print0 | xargs -0 -r rm -f
+}
+
+<% if @delete_before_dump -%>
+cleanup
+
+<% end -%>
+<% if @backupdatabases.empty? -%>
+<% if @file_per_database -%>
+mysql -u${USER} -p${PASS} -s -r -N -e 'SHOW DATABASES' | while read dbname
+do
+  mysqldump -u${USER} -p${PASS} --opt --flush-logs --single-transaction \
+    ${ADDITIONAL_OPTIONS} \
+    ${dbname} <% if @backupcompress %>| bzcat -zc <% end %>> ${DIR}/${PREFIX}${dbname}_`date +%Y%m%d-%H%M%S`.sql<% if @backupcompress %>.bz2<% end  %>
+done
+<% else -%>
+mysqldump -u${USER} -p${PASS} --opt --flush-logs --single-transaction \
+ ${ADDITIONAL_OPTIONS} \
+ --all-databases <% if @backupcompress %>| bzcat -zc <% end %>> ${DIR}/${PREFIX}`date +%Y%m%d-%H%M%S`.sql<% if @backupcompress %>.bz2<% end  %>
+<% end -%>
+<% else -%>
+<% @backupdatabases.each do |db| -%>
+mysqldump -u${USER} -p${PASS} --opt --flush-logs --single-transaction \
+    ${ADDITIONAL_OPTIONS} \
+ <%= db %><% if @backupcompress %>| bzcat -zc <% end %>> ${DIR}/${PREFIX}<%= db %>_`date +%Y%m%d-%H%M%S`.sql<% if @backupcompress %>.bz2<% end  %>
+<% end -%>
+<% end -%>
+
+<% unless @delete_before_dump -%>
+if [ $? -eq 0 ] ; then
+    cleanup
+fi
+<% end -%>
+
+<% if @postscript -%>
+  <%- [@postscript].flatten.compact.each do |script|%>
+<%= script %>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/mysql/templates/xtrabackup.sh.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+<%- if @kernel == 'Linux' -%>
+#!/bin/bash
+<%- else -%>
+#!/bin/sh
+<%- end -%>
+#
+# A wrapper for Xtrabackup
+#
+<% if @prescript -%>
+  <%- [@prescript].flatten.compact.each do |script| %>
+<%= script %>
+  <%- end -%>
+<% end -%>
+
+innobackupex "$@"
+
+<% if @postscript -%>
+  <%- [@postscript].flatten.compact.each do |script| %>
+<%= script %>
+  <%- end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/.fixtures.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+fixtures:
+  repositories:
+    "concat": "git://github.com/puppetlabs/puppetlabs-concat.git"
+    "stdlib": "git://github.com/puppetlabs/puppetlabs-stdlib.git"
+  symlinks:
+    "puppi": "#{source_dir}"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/.gitignore	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+/.gradle
+/metadata.json
+/.rvmrc
+build
+pkg/
+Session.vim
+spec/fixtures
+.*.sw[a-z]
+*.un~
+vendor
+.bundle
+Gemfile.lock
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/.project	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>puppi</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.cloudsmith.geppetto.pp.dsl.ui.modulefileBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.cloudsmith.geppetto.pp.dsl.ui.puppetNature</nature>
+		<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
+	</natures>
+</projectDescription>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/.travis.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+---
+language: ruby
+script:
+  - "bundle exec rake lint spec SPEC_OPTS='--format documentation'"
+sudo: false
+matrix:
+  include:
+  # Debian 7
+  - rvm: 1.8.7
+    env: PUPPET_GEM_VERSION="~> 2.7.23" FACTER_GEM_VERSION="~> 1.6.10"
+  # Debian 8
+  - rvm: 2.1.2
+    env: PUPPET_GEM_VERSION="~> 3.7.2" FACTER_GEM_VERSION="~> 2.2.0"
+  # Puppet 3.1 with Ruby 1.9.3
+  - rvm: 1.9.3
+    env: PUPPET_GEM_VERSION="~> 3.1.0"
+  # recent
+  - rvm: 2.1.2
+    env: STRICT_VARIABLES="yes"
+  # puppet 4 AIO
+  - rvm: 2.1.4
+    env: STRICT_VARIABLES="yes"
+
+notifications:
+  email:
+    - al@lab42.it
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/Gemfile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+source 'https://rubygems.org'
+
+if facterversion = ENV['FACTER_GEM_VERSION']
+  gem 'facter', facterversion, :require => false
+else
+  gem 'facter', :require => false
+end
+
+if puppetversion = ENV['PUPPET_GEM_VERSION']
+  gem 'puppet', puppetversion, :require => false
+  # Puppet 2.7 and Ruby 1.8 fails with newer rspec
+  gem 'rspec', '~>3.1.0', :require => false, :platform => [:ruby_18]
+else
+  gem 'puppet', :require => false
+end
+
+
+gem 'puppet-lint'
+gem 'puppetlabs_spec_helper', '>= 0.1.0'
+
+# vim:ft=ruby
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/LICENSE	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+Copyright (C) 2013 Alessandro Franceschi / Lab42
+
+for the relevant commits Copyright (C) by the respective authors.
+
+Contact Lab42 at: info@lab42.it
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/Modulefile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+name 'example42-puppi'
+version '2.1.11'
+
+author 'lab42'
+license 'Apache'
+project_page 'https://github.com/example42/puppi'
+source 'git://github.com/example42/puppi'
+summary 'Installs and configures Puppi'
+description 'This module provides the Puppi libraries required by Example42 modules and, if explicitely included, the puppi command, its working environment, the defines and procedures to deploy applications'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/README.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,273 @@
+# Puppi: Puppet Knowledge to the CLI
+
+Puppi One and Puppi module written by Alessandro Franceschi / al @ lab42.it
+
+Puppi Gem by Celso Fernandez / Zertico
+
+Source: http://www.example42.com
+
+Licence: Apache 2
+
+Puppi is a unique tool that serves both as a Puppet module and a CLI command tool.
+It's data is entirely driven by Puppet code.
+Example use cases for Puppi may include:
+- creating a standardize method to automate the deployment of web applications
+- or to provide a set of standard commands to query and check system resources based on "user definded actions".
+
+Its structure provides FULL flexibility on the type of "actions" that may be required for virtually any kind of application deployment and/or system information gathering.
+
+The module provides:
+
+* Old-Gen and Next-Gen Puppi implementation.
+
+* A set of scripts that can be chained togehter to automate any kind of deployment.
+
+* Puppet defines that make it easy to prepare a puppi set of commands for a project deployment.
+
+* Puppet defines to populate the output of the different actions.
+
+
+## HOW TO INSTALL
+
+Download Puppi from GitHub and place it in your modules directory:
+
+```bash
+git clone https://github.com/example42/puppi.git /etc/puppet/modules/puppi
+```
+
+To use the Puppi "Original, old and widely tested" version, just declare or include the puppi class
+
+```ruby
+class { 'puppi': }
+```
+
+To test the Next-Gen version you can perform the following command. Please note that this module is
+not stable yet:
+
+```ruby
+class { 'puppi':
+  version => '2',
+}
+```
+
+If you have resources conflicts, do not install automatically the Puppi dependencies (commands and packages)
+
+```ruby
+class { 'puppi':
+  install_dependencies => false,
+}
+```
+
+## HOW TO USE
+
+Once Puppi is installed you can use it to:
+
+* Easily define in Puppet manifests Web Applications deploy procedures. For example:
+
+  ```ruby
+  puppi::project::war { "myapp":
+    source           => "http://repo.example42.com/deploy/prod/myapp.war",
+    deploy_root      => "/opt/tomcat/myapp/webapps",
+  }
+  ```
+
+* Integrate with your modules for puppi check, info and log
+
+* Enable Example42 modules integration
+
+
+## HOW TO USE WITH EXAMPLE42 MODULES
+
+The Example42 modules provide (optional) Puppi integration.
+Once enabled for each module you have puppi check, info and log commands.
+
+To enable Puppi in OldGen Modules, set in the scope these variables:
+
+```
+$puppi = yes            # Enables puppi integration
+$monitor = yes          # Enables automatic monitoring
+$monitor_tool = "puppi" # Sets puppi as monitoring tool
+```
+
+For the NextGen modules set the same parameters via Hiera, at Top Scope or as class arguments:
+
+```ruby
+class { 'openssh':
+  puppi        => yes,
+  monitor      => yes,
+  monitor_tool => 'puppi',
+}
+```
+
+## USAGE OF THE PUPPI COMMAND (OLD GEN)
+
+```bash
+puppi <action> <project_name> [ -options ]
+```
+
+The puppi command has these possible actions:
+
+First time initialization of the defined project (if available)
+        puppi init <project>
+
+Deploy the specified project
+        puppi deploy <project>
+
+Rollback to a previous deploy state
+        puppi rollback <project>
+
+Run local checks on system and applications
+        puppi check
+
+Tail system or application logs
+        puppi log
+
+Show system information (for all or only the specified topic)
+        puppi info [topic]
+
+Show things to do (or done) manually on the system (not done via Puppet)
+        puppi todo
+
+In the deploy/rollback/init actions, puppi runs the commands in /etc/puppi/projects/$project/$action, logs their status and then run the commands in /etc/puppi/projects/$project/report to provide reporting, in whatever, pluggable, way.
+
+You can also provide some options:
+
+* -f : Force puppi commands execution also on CRITICAL errors
+
+* -i : Interactively ask confirmation for every command
+
+* -t : Test mode. Just show the commands that should be executed without doing anything
+
+* -d <yes|full>: Debug mode. Show debugging info during execution
+
+* -o "parameter=value parameter2=value2" : Set manual options to override defaults. The options must be in parameter=value syntax, separated by spaces and inside double quotes.
+
+
+Some common puppi commnds when you log for an application deployment:
+
+```bash
+puppi check
+puppi log &    # (More readable if done on another window)
+puppi deploy myapp
+puppi check
+puppi info myapp
+```
+
+## THE PUPPI MODULE
+
+The set of commands needed for each of these actions are entirely managed with specific
+Puppet "basic defines":
+
+Create the main project structure. One or more different deployment projects can exist on a node.
+        puppi::project
+
+Create a single command to be placed in the init sequence. It's not required for every project.
+        puppi::initialize
+
+Create a single command to be placed in the deploy sequence. More than one is generally needed for each project.
+        puppi::deploy
+
+Create a single command to be placed in the rollback sequence. More than one is generally needed for each project.
+        puppi::rollback
+
+Create a single check (based on Nagios plugins) for a project or for the whole host (host wide checks are auto generated by Example42 monitor module)
+        puppi::check
+
+Create a reporting command to be placed in the report sequence.
+        puppi::report
+
+Create a log filename entry for a project or the whole hosts.
+        puppi::log
+
+Create an info entry with the commands used to provide info on a topic
+        puppi::info
+
+Read details in the relevant READMEs
+
+
+## FILE PATHS (all of them are provided, and can be configured, in the puppi module):
+
+A link to the actual version of puppi enabled
+        /usr/sbin/puppi
+
+The original puppi bash command.
+        /usr/sbin/puppi.one
+
+Puppi (one) main config file. Various puppi wide paths are defined here.
+        /etc/puppi/puppi.conf
+
+Directory where by default all the host wide checks can be placed. If you use the Example42 monitor module and have "puppi" as $monitor_tool, this directory is automatically filled with Nagios plugins based checks.
+        /etc/puppi/checks/ ($checksdir)
+
+Directory that containts projects subdirs, with the commands to be run for deploy, rollback and check actions. They are completely built (and purged) by the Puppet module.
+        /etc/puppi/projects/ ($projectsdir)
+
+The general-use scripts directory, these are used by the above commands and may require one or more arguments.
+        /etc/puppi/scripts/ ($scriptsdir)
+
+The general-use directory where files are placed which contain the log paths to be used by puppi log
+        /etc/puppi/logs/ ($logssdir)
+
+The general-use directory where files are placed which contain the log paths to be used by puppi log
+        /etc/puppi/info/ ($infodir)
+
+Where all data to rollback is placed.
+        /var/lib/puppi/archive/ ($archivedir)
+
+Where logs and reports of the different commands are placed.
+        /var/log/puppi/ ($logdir)
+
+Temporary, scratchable, directory where Puppi places temporary files.
+        /tmp/puppi/ ($workdir)
+
+A runtime configuration file, which is used by all all the the scripts invoked by puppi to read and write dynamic variables at runtime. This is necessary to mantain "state" information that changes on every puppi run (such as the deploy datetime, used for backups).
+        /tmp/puppi/$project/config
+
+
+## HOW TO CUSTOMIZE
+It should be clear that with puppi you have full flexibility in the definition of a deployment
+procedure, since the puppi command is basically a wrapper that executes arbitrary scripts with
+a given sequence, in pure KISS logic.
+
+The advantanges though, are various:
+* You have a common syntax to manage deploys and rollbacks on an host
+
+* In your Puppet manifests, you can set in simple, coherent and still flexible and customizable
+  defines all the elements, you need for your application deployments.
+  Think about it: with just a Puppet define you build the whole deploy logic
+
+* Reporting for each deploy/rollback is built-in and extensible
+
+* Automatic checks can be built in the deploy procedure
+
+* You have a common, growing, set of general-use scripts for typical actions
+
+* You have quick and useful command to see what's happening on the system (puppi check, log, info)
+
+There are different parts where you can customize the behaviour of puppi:
+
+* The set of general-use scripts in /etc/puppi/scripts/ ( this directory is filled with the content
+  of puppi/files/scripts/ ) can/should be enhanced. These can be arbitrary scripts in whatever
+  language. If you want to follow puppi's logic, though, consider that they should import the
+  common and runtime configuration files and have an exit code logic similar to the one of
+  Nagios plugins: 0 is OK, 1 is WARNING, 2 is CRITICAL. Note that by default a script that
+  exits with WARNING doesn't block the deploy procedure, on the other hand, if a script exits
+  with CRITICAL (exit 2) by default it blocks the procedure.
+  Take a second, also, to explore the runtime config file created by the puppi command that
+  contains variables that can be set and used by the scripts invoked by puppi.
+
+* The custom project defines that describe deploy templates. These are placed in
+  puppi/manifests/project/ and can request all the arguments you want to feed your scripts with.
+  Generally is a good idea to design a standard enough template that can be used for all the
+  cases where the deployment procedure involves similar steps. Consider also that you can handle
+  exceptions with variables (see the $loadbalancer_ip usage in puppi/manifests/project/maven.pp)
+
+
+## (NO) DEPENDENCIES AND CONFLICTS
+Puppi is self contained. It doesn't require other modules.
+(And is required by all Example42 modules).
+
+For correct functionality by default some extra packages are installed.
+If you have conflicts with your existing modules, set the argument:
+  install_dependencies => false
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/README_check.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,67 @@
+# PUPPI CHECK INSTRUCTIONS
+Documentation and examples related to the puppi action check
+
+## SYNOPSIS (cli)
+        puppi check [project_name] [-r yes|no|fail]
+
+## EXAMPLES (cli)
+Run host-wide checks.
+        puppi check
+Run project "myapp" specific tests AND host-wide checks
+        puppi check myapp
+
+Run checks and send reports only if some of them fail
+        puppi check -r fail
+
+Run checks and send reports
+        puppi check -r yes
+
+Run checks and show only failed ones
+        puppi check -s fail
+
+## EXAMPLES (puppet)
+The basic define related to a check is:
+        puppi::check   - Creates a single command to be placed in the check sequence.
+
+A simple example might be:
+        puppi::check { 'Port_Apache':
+          command  => "check_tcp -H ${fqdn} -p 80" ,
+        }
+
+but also something that uses variables Puppet already knows
+        puppi::check { 'apache_process':
+          command  => "check_procs  -c 1: -C ${apache::params::processname}" ,
+        }
+
+To avoid repetitions you can include the relevant checks in defines you already have
+to manage, for example, virtualhosts, and use the data you already provide to configure
+their local puppi checks. 
+        puppi::check { "Url_$name":
+          enable   => $enable,
+          command  => "check_http -I '${target}' -p '${port}' -u '${url}' -s '${pattern}'" ,
+        }
+
+You can also use custom scripts for your checks. They should behave similarly to Nagios plugins inn their exit codes: 0 for SUCCESS, 1 for WARNINGS, 2 for CRITICAL. In this case you've to specify the directory there the scripts stays:
+        puppi::check { 'my_stack':
+          command  => 'stack_check.sh',
+          bade_dir => '/usr/bin',
+        }
+
+
+## EXAMPLES (with example42 puppet modules)
+If you use the whole Example42 modules set you get automatically many service related checks out of the box.
+Just set (via an ENC, facts or manifests) these puppet variables:
+        $monitor="yes" # To enable automagic monitoring
+        $monitor_tool = "puppi"  # As monitoring tool define at least puppi. If you like Nagios, you may use:
+        $monitor_tool = ["nagios","puppi"] # This enables the below checks both for Puppi and Nagios
+        $puppi=yes # To enable puppi extensions autoloading
+
+To the port and service checks automatically added for the included modules, you can add custom url checks 
+with something like:
+        monitor::url { "URL_Check_Database_Connection":
+          url      => "http://www.example42.com/check/db",
+          pattern  => 'SUCCESS',
+          port     => '80',
+          target   => "${fqdn}",
+        }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/README_deploy.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,292 @@
+# PUPPI DEPLOY INSTRUCTIONS
+Documentation and examples related to the puppi actions: deploy, rollback and init
+
+## SYNOPSIS (COMMAND LINE)
+Shell command to launch a deploy:
+
+        puppi deploy <project_name>
+        puppi deploy <project_name> [-f] [-i] [-t] [-d yes|full] [-r yes|no|fail] [-p "parameter=value parameter2=value2"]
+
+Shell command to launch a rollback:
+
+        puppi rollback <project_name> 
+
+Shell command to launch the first deploy:
+
+        puppi init <project_name>
+
+
+## EXAMPLES (cli)
+
+Deploy myapp with the standard logic/parameters defined in Puppet:
+
+        puppi deploy myapp
+
+Deploy myapp and doesn't stop in case of Critical errors:
+
+        puppi deploy myapp -f
+
+Deploy myapp in interactive mode. Confirmation is asked for each step
+
+        puppi deploy myapp -i
+
+Test mode. Just show the commands that would be executed
+
+        puppi deploy myapp -t
+
+Deploy myapp with full debugging output
+
+        puppi deploy myapp -d full
+
+Deploy myapp in interactive mode and sets some custom options that override the standard Puppet params.
+Note that these parameters change according to the script you use (and the scripts must honour this override in order to make this option work).
+
+        puppi deploy myapp -i -o "version=1.1 source_url=http://dev.example42.com/code/my_app/"
+
+Make the first deploy of "myapp". Can be optional and may require a subsequent puppi deploy myapp
+
+        puppi init myapp
+
+Rollback myapp to a previous archived state. User is asked to choose which deploy to override. Note that by default you have 5 backups to rollback from. Older backups are automatically removed.
+
+        puppi rollback myapp
+
+Automatically rollback to the latest saved state (unattended).
+
+        puppi rollback myapp latest
+
+
+## EXAMPLES (puppet)
+Here follow some sample defines you can use out of the box in your manifests once you include puppi.
+Get a war from $source and deploy it in $deploy_root:
+
+        puppi::project::war { 'myapp':
+          source           => 'http://repo.example42.com/deploy/prod/myapp.war',
+          deploy_root      => '/store/tomcat/myapp/webapps',
+        }
+
+Get a tarball from $source, unpack it in $deploy_root, restart service called apache and send a mail
+to $report_mail (you can have a comma separated list of destination addresses):
+
+        puppi::project::tar { 'mysite':
+          source           => 'rsync://repo.example42.com/deploy/prod/release.tgz',
+          init_script      => 'apache',
+          deploy_root      => '/var/www/html/',
+          report_email     => 'sysadmins@example42.com',
+          enable           => 'true', # Redundant
+        }
+
+Get a tarfile with a .sql query file and apply to to you local Mysql with the credentials provided:
+
+        puppi::project::mysql { 'myweb_sql':
+          source          => 'http://repo.example42.com/deploy/prod/database.sql.gz',
+          mysql_user      => 'myweb',
+          mysql_password  => $secret::mysql_myweb_pw,
+          mysql_host      => 'localhost',
+          mysql_database  => 'myweb',
+          report_email    => 'sysadmins@example42.com,dbadmins@example42.com',
+          enable          => 'true',
+        }
+
+Get a list of files from $source, retrieve the actual files from $source_baseurl and place them
+in $deploy_root:
+
+        puppi::project::files { 'gfxupdates':
+          source           => 'http://deploy.example42.com/prod/website2/list.txt',
+          source_baseurl   => 'http://design.example42.com/website2/gfx/',
+          deploy_root      => '/var/www/html/gfx',
+          report_email     => 'sysadmins@example42.com,designers@example42.com',
+          enable           => 'true',
+        }
+
+Deploy from a Nexus repository (retrieve maven-metadata.xml from dir specified in $source), get the war 
+(version is achieved from the "release" tag in the xml) and deploy it in $deploy_root and then restart tomcat.
+
+        puppi::project::maven { 'supersite':
+          source           => 'http://nexus.example42.com/nexus/content/repositories/releases/it/example42/supersite/',
+          deploy_root      => '/usr/local/tomcat/supersite/webapps',
+          init_script      => 'tomcat',
+          report_email     => 'sysadmins@example42.com',
+          enable           => 'true',
+        }
+
+Get the maven-metadata.xml from a Nexus repository and deploy:
+- The release war in $deploy_root
+- A configurations tarball tagged with the Maven qualifier $config_suffix in $config_root
+- A static files tarball tagged with the Maven qualifier $document_suffix in $document_root
+
+        puppi::project::maven { 'supersite':
+          source           => 'http://nexus.example42.com/nexus/content/repositories/releases/it/example42/supersite/',
+          deploy_root      => '/usr/local/tomcat/supersite/webapps',
+          config_suffix    => 'cfg',
+          config_root      => '/srv/htdocs/supersite',
+          document_suffix  => 'css',
+          document_root    => '/srv/htdocs/supersite',
+          init_script      => 'tomcat',
+          report_email     => 'sysadmins@example42.com',
+          enable           => 'true',
+        }
+
+The same deploy Nexus repository with some more options:
+- A Source dir to be used to deploy static files when issuing "puppi init supersite"
+- A block from a loadbalancer IP (managing different sites addresess)
+- Some more elaborate rsync exclusion rules
+- A backup retention of 3 archives (instead of the default 5)
+
+        puppi::project::maven { 'supersite':
+          source           => 'http://nexus.example42.com/nexus/content/repositories/releases/it/example42/supersite/',
+          deploy_root      => '/usr/local/tomcat/supersite/webapps',
+          config_suffix    => 'cfg',
+          config_root      => '/srv/htdocs/supersite',
+          document_suffix  => 'css',
+          document_root    => '/srv/htdocs/supersite',
+          document_init_source => 'rsync://backup.example42.com/initdir/supersite/',
+          firewall_src_ip  => $site ? {
+              dr      => '192.168.101.1/30',
+              main    => '192.168.1.1/30',
+          },
+          backup_rsync_options => '--exclude .snapshot --exclude /doc_root/autojs/*** --exclude /doc_root/autocss/*** --exclude /doc_root/xsl',
+          backup_retention => '3',
+          init_script      => 'tomcat',
+          report_email     => 'sysadmins@example42.com',
+          enable           => 'true',
+        }
+
+An elaborated war deploy:
+- get from $source,
+- execute /usr/local/bin/mychecks.sh as root before the deploy
+(or better with sequence number 39)
+- deploy to /data/tomcat/myapp/webapps as user pippo
+- stop and start tomcat-myapp but also monit and puppet
+- backup passing  $backup_rsync_options to rsync:
+
+        puppi::project::war { 'myapp':
+          source                  => 'http://repo.example42.com/deploy/prod/myapp.war',
+          deploy_root             => '/store/tomcat/myapp/webapps',
+          predeploy_customcommand => '/usr/local/bin/mychecks.sh',
+          predeploy_priority      => '39',
+          predeploy_user          => 'root',
+          backup_rsync_options    => '--exclude logs/',
+          user                    => 'pippo',
+          init_script             => 'tomcat-myapp',
+          deploy_root             => '/data/tomcat/myapp/webapps',
+          report_email            => 'sysadmins@example42.com',
+          disable_services        => 'monit puppet',
+        }
+An example of usage of the generic builder define to deploy a zip file, with an example custom
+post deploy command executed as root (as all puppi commands, if not specified otherwise)
+
+        puppi::project::builder { 'cms':
+          source                   => 'http://repo.example42.com/deploy/cms/cms.zip',
+          source_type              => 'zip',
+          user                     => 'root',
+          deploy_root              => '/var/www',
+          postdeploy_customcommand => 'chown -R www-data /var/www/files',
+          postdeploy_user          => 'root',
+          postdeploy_priority      => '41',
+          report_email             => 'sysadmins@example42.com',
+          enable                   => 'true',
+        }
+
+These are just examples, possibilities are many, refer to the docs in puppi/manifests/project/*.pp
+to have a full list of the available options.
+
+
+## BASIC PUPPI DEFINES
+The above puppi::projects defines manage more or less complex deployments procedures for different kind of projects. They are just samples of possible procedures and you may create your one ones, if the ones provided there don't fit your needs.
+They will have to contain one or more of these basic puppi defines.
+
+Create the main project structure. One or more different deployment projects can exist on a node.
+
+        puppi::project
+
+Create a single command to be placed in the init sequence. It's not required for every project.
+
+        puppi::initialize
+
+Create a single command to be placed in the deploy sequence. More than one is generally needed for each project.
+
+        puppi::deploy
+
+Create a single command to be placed in the rollback sequence. More than one is generally needed for each project.
+
+         puppi::rollback
+
+These defines have generally a standard structure and similar arguments.
+Every one is reversable (enable => false) but you can wipe out the whole /etc/puppi directory
+to have it rebuilt from scratch. Here is an example for a single deploy command:
+
+        puppi::deploy { 'Retrieve files':       # The $name of the define is used in the file name
+          command  => 'get_curl.sh',          # The name of the general-use script to use
+          argument => 'file:///storage/file', # The argument(s) passed to the above script
+          priority => '10',                   # Lower priority scripts are executed first
+          user     => 'root',                 # As what user we run the script
+          project  => 'my-web.app',           # The name of the project to use
+        }
+
+This define creates a file named:
+
+        /etc/puppi/projects/${project}/deploy/${priority}-${name}
+
+Its content is, simply:
+
+        su - ${user} -c "export project=${project} && /etc/puppi/scripts/${command} ${arguments}"
+
+
+## DEPLOY PROCEDURES DEFINES
+The puppi module provides some examples of deploy workflows they are in the puppi/manifests/project
+directory and contain simple to use defines that contain one puppi::project and several puppi::deploy and
+puppi::rollback defines to design a specific workflow using the builtin commands present in
+puppi/files/scripts.
+Note that if you need to design your own deploy procedure you have different options:
+- Verify if you can reuse the existing ones, using optional arguments as pre/postdeploy_commands
+- Use the existing ones as a base to make you own custom defines, reusing parts of their logic 
+  and the builtin commands (puppi/files/scripts/*) they use
+- Write your own commands (in whatever language) and integrate them in your own procedure.
+
+Here follow the main and most reusable deploy workflows defines available in puppi/manifests/project/.
+The have generally a set of common arguments that make you manage if to stop and restart specific 
+services, if you want to isolate your server from a loadbalancer during the deploy procedure, what to backup,
+how many backup copies to mantain, if to send a report mail to specific addresses and if you need
+to run custom commands during the standard procedure.
+For all of the you have to specify a source from where to get the source files (http/ftp/rsync/file..) 
+a directory where to place them and the user that has to own the deploy files.
+Full documentation is available in the relevant .pp files
+
+- puppi::project::tar - Use this to retrieve and deploy a simple tar file
+- puppi::project::war - Use this to retrieve and deploy a war
+- puppi::project::files - Use this to deploy one or more files based on a provided list
+- puppi::project::dir - Use this to syncronize a remote directory to a local deploy one
+- puppi::project::mysql - Use this to retrive and apply a .sql file for mysql schema updates 
+- puppi::project::maven - Use this to deploy war and tar files generated via Maven released on Nexus or similar. A good source of Open Source Java artifacts is http://www.artifact-repository.org/
+- puppi::project::builder - This is a general purpose define that incorporates most the of cases provided by the above procedures
+
+
+## BUILTIN COMMANDS
+The puppi/files/scripts directory in the module contains some general usage "native" bash scripts
+that can be used in custom deployments. They are generally made to work together according to a
+specific logic, which is at the base of the deploy procedures defines in puppi/manifests/project/
+but you're free to write your own scripts, in whatever language, according to your needs.
+
+The default scripts are engineered to follow these steps for a deployment:
+- Remote files are downloaded in /tmp/puppi/$project/store or directly in the predeploy
+  directory: /tmp/puppi/$project/deploy
+- If  necessary the downloaded files are expanded in one or more predeploy directories
+  (default:/tmp/puppi/$project/deploy).
+- Runtime configuration entries might be saved in /tmp/puppi/$project/config
+- Files are eventually backed from the deploy directory (Apache' docroot, Tomcat webapps or whatever)
+  to the archive directory (/var/lib/puppi/archive/$project). Older backups are deleted (by default
+  there's a retention of 5 backups).
+- Files are copied from the predeploy directory to the deploy dir.
+- Relevant services are eventually stopped and started
+
+The most used common scripts are (they might have different arguments, some of them are quite simple):
+- get_file.sh - Retrieves a file via ssh/http/rsync/svn and places it in a temp dir (store or predeploy)
+- deploy.sh - Copies the files in the predeploy dir to deploy dir
+- archive.sh - Backups and restores files in deploy dir
+- service.sh - Stops or starts one or more services
+- wait.sh - Waits for the presence or absence of a file, for the presence of a string in a file or a defined number or seconds.
+- get_metadata.sh - Extracts metadata from various sources in order to provide info to other scripts. These info are save in the Runtime configuration file (/tmp/puppi/$project/config)
+- report_mail.sh - Sends a mail with the report of the operations done
+
+General functions, used by both the puppi command and these scripts, are in puppi/files/scripts/functions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/README_info.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,60 @@
+# PUPPI INFO README
+The puppi info commands executes scripts in /etc/puppi/info/ which are generated by templates provided by the puppi::info define
+These scripts are supposed to show status details on the omonimous info topic.
+
+## SYNOPSIS (cli)
+        puppi info [topic] [-i]
+
+## EXAMPLES (cli)
+Show host-wide infos. Much stuff.
+        puppi info
+
+Show info about apache (connections, processes, config, logs...)
+        puppi info apache
+
+Interactively select the info topics you want to show
+        puppi info -i
+
+Show complete info and send reports (email, rest ... )
+        puppi info -r yes
+
+Grep the output with the string defined
+        puppi info -g <string>
+
+
+## EXAMPLES (puppet)
+The basic define related to a info is puppi::info, it creates a script executed
+when running "puppi info $name" based on the provided template.
+Customize the template to customize the info you want to see.
+
+A sample that just runs commands using the default template:
+        puppi::info { 'network':
+          description => 'Network settings and stats' ,
+          run         => [ 'ifconfig' , 'route -n' , 'cat /etc/resolv.conf' , 'netstat -natup | grep LISTEN' ],
+        }
+
+You can have more useful and dedicated info topics using a custom puppi::info define inside your
+own defines. For example in a define that creates a tomcat instance you can add something like:
+        puppi::info::instance { "tomcat-${instance_name}":
+          servicename => "tomcat-${instance_name}",
+          processname => "${instance_name}",
+          configdir   => "${tomcat::params::storedir}/${instance_name}/conf/",
+          bindir      => "${tomcat::params::storedir}/${instance_name}/bin/",
+          pidfile     => "${instance_rundir}/tomcat-${instance_name}.pid",
+          datadir     => "${instance_path}/webapps",
+          logdir      => "${instance_logdir}",
+          httpport    => "${instance_httpport}",
+          controlport => "${instance_controlport}",
+          ajpport     => "${instance_ajpport}",
+          templatefile=> "puppi/info/instance.erb",
+          description => "Info for ${instance_name} Tomcat instance" ,
+        }
+which has custom arguments, feeded by the data you provided to the define, and a custom
+template file that uses these variables. 
+
+## EXAMPLES (with example42 puppet modules)
+If you use the old Example42 modules set you get automatically many service related infos out of the box to be used with Puppi One.
+NextGen modules are supposed to provide pupi info intergration on Puppi Two (TO DO)
+Just set (via an ENC, facts or manifests) $puppi=yes to enable puppi extensions autoloading.
+This will automatically deploy info topics related to the modules you use.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/README_log.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,44 @@
+# PUPPI LOG README
+Documentation and examples related to the puppi action log
+
+## SYNOPSIS (cli)
+        puppi log [topic] [-i]
+
+## EXAMPLES (cli)
+
+Tails (tail -10f) all the known logs.
+        puppi log
+
+Tails only the logs related to the given topic
+        puppi log apache
+
+Choose interactively which logs to show
+        puppi log
+
+Grep the output with the string defined
+        puppi log -g <string>
+
+## EXAMPLES (puppet)
+The basic define related to a log is:
+        puppi::log
+it creates a file in /etc/puppi/logs/ with one or more logs paths.
+
+A simple, operating system aware, example might be:
+        puppi::log { 'auth':
+          description => 'Users and authentication' ,
+          log => $::operatingsystem ? { 
+            redhat => '/var/log/secure',
+            darwin => '/var/log/secure.log',
+            ubuntu => ['/var/log/user.log','/var/log/auth.log'],
+          }
+        }
+
+but also something that uses variables Puppet already knows
+        puppi::log { "tomcat-${instance_name}":
+          log => "${tomcat::params::storedir}/${instance_name}/logs/catalina.out"
+        }
+
+EXAMPLES (with example42 puppet modules)
+If you use the old Example42 modules set you get automatically many service related logs out of the box to be used with Puppi One.
+NextGen modules are supposed to provide puppi log intergration on Puppi Two (TO DO)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/Rakefile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+require 'puppetlabs_spec_helper/rake_tasks'
+require 'puppet-lint'
+
+PuppetLint.configuration.fail_on_warnings = true
+PuppetLint.configuration.send('relative')
+PuppetLint.configuration.send("disable_80chars")
+PuppetLint.configuration.send('disable_class_inherits_from_params_class')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/composer.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+{
+    "name": "example42/puppi",
+    "description": "Puppet driven applications deployment tool",
+    "homepage": "https://github.com/example42/puppi",
+    "type": "library",
+    "license": "Apache License, Version 2.0",
+    "authors": [
+        {
+            "name": "Example42",
+            "homepage": "http://www.example42.com/"
+        }
+    ]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/info/readme/readme	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,2 @@
+Default ReadMe File.
+Edit puppi/files/info/readme/readme to change this message
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/info/readme/readme-default	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+No extra node or role related info available.
+To have node or role specific extar info, create 
+modules/puppi/files/info/readme/readme--$hostname or
+modules/puppi/files/info/readme/readme-$role 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/mailpuppicheck	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,72 @@
+#!/bin/bash
+# File Managed by Puppet
+# Possible Usage:
+# Run this command at the end of each Puppet run to be 
+# immediately notified if a Puppet Runs has broken some service
+# 
+# Options:
+# -m destination_email
+# -i <interval> (in seconds) before retrying a Puppi check
+# -r <number_of_retries> how many attempts to retry if there are failures
+#
+# In puppet.conf add something like:
+# postrun_command = "/usr/bin/mailpuppicheck -m roots@example.com"
+#
+retries=1
+interval=2
+workdir="/tmp"
+counter=0
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -m)
+      mail=$2
+      shift 2 ;;
+    -i)
+      internal=$2
+      shift 2 ;;
+    -r)
+      retries=$2
+      shift 2 ;;
+  esac
+done
+
+if [ ! $mail ] ; then
+    echo "Provide at least an email addess"
+    exit 1
+fi
+
+# randfile="$(mktemp)"
+lastrunfile=$workdir/puppicheck_lastrun
+savedfile=$workdir/puppicheck_saved
+
+while [ $counter -lt $retries ] ; do
+  puppi check | grep FAILED > $lastrunfile
+  if [ "x$?" == "x0" ] ; then
+    errors="yes"
+    sleep $interval
+  else
+    errors="no"
+    echo "Run $counter - Errors $errors"
+    echo > $savedfile
+    exit 0
+  fi
+  echo "Run $counter - Errors $errors"
+  let counter=$counter+1
+done
+
+diff $lastrunfile $savedfile
+if [ "x$?" == "x0" ] ; then
+  echo "No changes detected"
+else
+  echo "Changes detected"
+  notify="yes"
+fi
+
+cp $lastrunfile $savedfile
+if [ "x$notify" == "xyes" ] ; then 
+  # Yes, it's ugly
+  cat -v $lastrunfile  | sed -e 's:\^\[\[60G\[\^\[\[0;31m: :g' | sed -e 's:\^\[\[0;39m\]\^M: :g' | mail -s "[puppet] Errors after Puppet run on $(hostname -f)" $mail
+  echo "Sent notification"
+fi
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/mcollective/mc-puppi	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,65 @@
+#!/usr/bin/env ruby
+
+# Client program for the mcollective puppi agent 
+#
+# Released under Apache License 2.0
+
+require 'mcollective'
+
+include MCollective::RPC
+
+options = rpcoptions do |parser, options|
+    options[:timeout] = 180
+
+    parser.define_head "Execute Puppi commands"
+    parser.banner = "Usage: mc-puppi [filters] command [project] [puppioptions]"
+    parser.separator ""
+    parser.separator "Available commands:"
+    parser.separator "  check [project] - Run puppi check"
+    parser.separator "  info [topic] - Run puppi info. For all or specified topic"
+    parser.separator "  log [topic] - Run puppi log. For all or specified topic"
+    parser.separator "  todo - Run puppi todo"
+    parser.separator "  deploy <project> - Run puppi deploy on the defined project"
+    parser.separator "  configure <project> - Run puppi configure on the defined project"
+    parser.separator "  rollback <project> - Run puppi rollback latest on the defined project"
+    parser.separator "  init <project> - Run puppi init on the defined project"
+end
+
+if MCollective::Util.empty_filter?(options[:filter])
+    print("Do you really want to operate on services unfiltered? (y/n): ")
+    STDOUT.flush
+
+    exit unless STDIN.gets.chomp =~ /^y$/
+end
+
+if ARGV.length >= 1
+    command = ARGV.shift
+    project = ARGV.shift
+    puppioptions = ARGV.shift
+
+    unless command =~ /^(check|deploy|rollback|init|configure|info|log|todo)$/
+        puts("Command has to be check|info|log|deploy|rollback|init|configure|todo")
+        exit 1
+    end
+else
+    puts("Please specify at least a command")
+    exit 1
+end
+
+mc = rpcclient("puppi", :options => options)
+mc.progress = true
+# mc.send(command, {:project => project}) do |resp|
+args = {};
+args[:project] = project if project
+args[:puppioptions] = puppioptions if puppioptions
+mc.send(command, args) do |resp|
+    begin
+#        puts resp[:serverid]
+        puts resp[:body][:data]
+#        puts resp[:body][:exitcode]
+
+    rescue RPCError => er
+        puts "RPC Agent error: #{er}"
+    end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/mcollective/puppi.ddl	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,68 @@
+metadata    :name        => "SimpleRPC Agent For PUPPI Commands",
+            :description => "Agent to query PUPPI commands via MCollective", 
+            :author      => "Al @ Lab42",
+            :license     => "Apache License 2.0",
+            :version     => "0.3",
+            :url         => "http://www.example42.com/",
+            :timeout     => 600
+
+[ "check" , "log" , "info" ].each do |myact| 
+    action myact, :description => "Run puppi myact" do
+        display :always
+
+        input :project,
+              :prompt      => "Project",
+              :description => "PUPPI project",
+              :type        => :string,
+              :validation  => '^[a-zA-Z\-\.=_\d]+$',
+              :optional    => true,
+              :maxlength   => 50
+
+        input :puppioptions,
+              :prompt      => "Puppi options",
+              :description => "PUPPI options",
+              :type        => :string,
+              :validation  => '^[a-zA-Z\-\.=_\d]+$',
+              :optional    => true,
+              :maxlength   => 50
+
+        output :data,
+              :description => "Output from the Puppi run",
+              :display_as  => "Output"
+
+        output :exitcode,
+              :description  => "Exit Code from the Puppi run",
+              :display_as => "Exit Code"
+    end
+end
+
+[ "deploy" , "rollback" , "init" , "configure" ].each do |myact|
+    action myact, :description => "Run puppi myact" do
+        display :always
+
+        input :project,
+              :prompt      => "Project",
+              :description => "PUPPI project",
+              :type        => :string,
+              :validation  => '^[a-zA-Z\-\.=_\d]+$',
+              :optional    => false,
+              :maxlength   => 50
+
+        input :puppioptions,
+              :prompt      => "Puppi options",
+              :description => "PUPPI options",
+              :type        => :string,
+              :validation  => '^[a-zA-Z\-\.=_\d]+$',
+              :optional    => true,
+              :maxlength   => 50
+
+        output :data,
+              :description => "Output from the Puppi run",
+              :display_as  => "Output"
+
+        output :exitcode,
+              :description  => "Exit Code from the Puppi run",
+              :display_as => "Exit Code"
+    end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/mcollective/puppi.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,83 @@
+module MCollective
+    module Agent
+        class Puppi<RPC::Agent
+            metadata    :name        => "SimpleRPC Agent For PUPPI Commands",
+                        :description => "Agent to execute PUPPI actions via MCollective",
+                        :author      => "Al @ Lab42",
+                        :license     => "Apache License 2.0",
+                        :version     => "0.3",
+                        :url         => "http://www.example42.com/",
+                        :timeout     => 600
+
+            def check_action
+#                   validate :project, :shellsafe
+                    project = request[:project] if request[:project]
+                    reply.data = %x[puppi check #{project}].chomp
+                    if ($?.exitstatus > 0)
+                      reply.fail "FAILED: #{reply.data}"
+                    end
+            end
+
+            def info_action
+#                   validate :project, :shellsafe
+                    project = request[:project] if request[:project]
+                    reply.data = %x[puppi info #{project}].chomp
+                    if ($?.exitstatus > 0)
+                      reply.fail "FAILED: #{reply.data}"
+                    end
+            end
+
+            def log_action
+#                   validate :project, :shellsafe
+                    project = request[:project] if request[:project]
+                    reply.data = %x[puppi log #{project} -c 10].chomp
+                    if ($?.exitstatus > 0)
+                      reply.fail "FAILED: #{reply.data}"
+                    end
+            end
+
+            def deploy_action
+                    validate :project, :shellsafe
+                    project = request[:project] if request[:project]
+                    if (!File.directory? "/etc/puppi/projects/#{project}")
+                      reply.fail "No such project #{project}"
+                      return
+                    end
+                    puppioptions = request[:puppioptions]
+                    reply.data = %x[puppi deploy #{project} -o "#{puppioptions}"].chomp
+                    if ($?.exitstatus > 0)
+                      reply.fail "FAILED: #{reply.data}"
+                    end
+            end
+
+            def rollback_action
+                    validate :project, :shellsafe
+                    project = request[:project] if request[:project]
+                    reply.data = %x[puppi rollback #{project} latest].chomp
+                    if ($?.exitstatus > 0)
+                      reply.fail "FAILED: #{reply.data}"
+                    end
+            end
+
+            def init_action
+                    validate :project, :shellsafe
+                    project = request[:project] if request[:project]
+                    reply.data = %x[puppi init #{project}].chomp
+                    if ($?.exitstatus > 0)
+                      reply.fail "FAILED: #{reply.data}"
+                    end
+            end
+            
+            def configure_action
+                  validate :project, :shellsafe
+                  project = request[:project] if request[:project]
+                  reply.data = %x[puppi configure #{project}].chomp
+                  if ($?.exitstatus > 0)
+                    reply.fail "FAILED: #{reply.data}"
+                  end
+            end
+
+        end
+    end
+end
+# vi:tabstop=4:expandtab:ai
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/mcollective/puppicheck	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#!/bin/bash
+# File Managed by Puppet
+PATH=$PATH:/usr/local/bin
+
+if [ ! $1 ] ; then
+    echo "Provide at least a match pattern. For example:"
+    echo "role=fep-pgol"
+    exit 1
+fi
+
+filtered=$(echo $* | sed "s/[^a-Z0-9= _.\-]//Ig")
+
+randfile="$(mktemp)"
+
+trap "rm -f $randfile" SIGINT SIGTERM EXIT
+
+myarg=$(echo $filtered | sed -e "s/ / -F /g")
+
+mc-puppi check -F $myarg | tee $randfile
+grep FAILED $randfile && exit 1
+exit 0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/mcollective/puppideploy	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#!/bin/bash
+# File Managed by Puppet
+PATH=$PATH:/usr/local/bin
+
+if [ ! $2 ] ; then
+    echo "Provide the hostname and the project you want to deploy:"
+    echo "superdeploy web01.example42.com myapp"
+    exit 1
+fi
+
+filtered=$(echo $* | sed "s/[^a-Z0-9= _.\-]//Ig")
+
+randfile="$(mktemp)"
+
+trap "rm -f $randfile" SIGINT SIGTERM EXIT
+
+myarg=$(echo $filtered | sed -e "s/ / -F /g")
+
+mc-puppi deploy -I $1 $2 | tee $randfile
+grep FAILED $randfile && exit 1
+exit 0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/archive.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,168 @@
+#!/bin/bash
+# archive.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script is used to backup or restore contents to/from puppi archivedir"
+    echo "It has the following options:"
+    echo "-b <backup_source> - Backups the files to be changed in the defined directory"
+    echo "-r <recovery_destination> - Recovers file to the provided destination"
+    echo "-s <copy|move> - Specifies the backup strategy (move or copy files)"
+    echo "-t <tag> - Specifies a tag to be used for the backup"
+    echo "-d <variable> - Specifies the runtime variable that defines the predeploy dir"
+    echo "-c <yes|no> - Specifies if you want compressed (tar.gz) archives. Default: yes"
+    echo "-o 'options' - Specifies the rsync options to use during backup. Use it to specify custom "
+    echo "               exclude patterns of files you don't want to archive, for example"
+    echo "-m <full|diff> - Specifies the backup type: 'full' backups all the files in backup_source,"
+    echo "                 'diff' backups only the files deployed"
+    echo "-n <number> - Number of copies of backups to keep on the filesystem. Default 5"
+    echo 
+    echo "Examples:"
+    echo "archive.sh -b /var/www/html/my_app -t html -c yes"
+}
+
+# Arguments check
+if [ "$#" = "0" ] ; then
+    showhelp
+    exit
+fi
+
+# Default settings
+compression=yes
+backuptag=all
+strategy=copy
+backupmethod=full
+bakret=5
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -b)
+      backuproot=$2
+#      [ $deploy_root ] && backuproot=$deploy_root # This is needed to allow override of $deploy_root via puppi cmd. But breaks on puppi::project::maven
+      action=backup
+      shift 2 ;;
+    -r)
+      backuproot=$2
+#      [ $deploy_root ] && backuproot=$deploy_root # This is needed to allow override of $deploy_root via puppi cmd. But breaks on puppi::project::maven
+      action=recovery
+      shift 2 ;;
+    -t)
+      backuptag=$2
+      shift 2 ;;
+    -s)
+      case "$2" in
+        mv) strategy="move" ;;
+        move) strategy="move" ;;
+        *) strategy="copy" ;;
+      esac
+      shift 2 ;;
+    -m)
+      case "$2" in
+        diff) backupmethod="diff" ;;
+        *) backupmethod="full" ;;
+      esac
+      shift 2 ;;
+    -c)
+      case "$2" in
+        yes) compression="yes" ;;
+        y) compression="yes" ;;
+        *) compression="none" ;;
+      esac
+      shift 2  ;;
+    -d)
+      predeploydir="$(eval "echo \${$(echo $2)}")"
+      shift 2 ;;
+    -o) 
+      rsync_options=$2
+      shift 2 ;;
+    -n)
+      bakret=$2
+      shift 2 ;;
+    *)
+      showhelp
+      exit
+      ;;
+  esac
+done
+
+
+# Backup and Restore functions
+backup () {
+    mkdir -p $archivedir/$project/$tag/$backuptag
+    if [ $archivedir/$project/latest ] ; then
+        rm -f $archivedir/$project/latest
+    fi
+    ln -sf $archivedir/$project/$tag $archivedir/$project/latest
+
+    filelist=$storedir/filelist
+    cd $predeploydir
+    find . | cut -c 3- | grep -v "^$" > $filelist
+
+    if [ "$strategy" = "move" ] ; then 
+        for file in $(cat $filelist) ; do
+            mv $backuproot/$file $archivedir/$project/$tag/$backuptag/
+        done
+        if [ "$backupmethod" = "full" ] ; then
+            rsync -a $rsync_options $backuproot/ $archivedir/$project/$tag/$backuptag/
+        fi
+    else
+        if [ "$backupmethod" = "full" ] ; then
+            rsync -a $rsync_options $backuproot/ $archivedir/$project/$tag/$backuptag/
+        else
+            rsync -a $rsync_options --files-from=$filelist $backuproot/ $archivedir/$project/$tag/$backuptag/
+        fi
+    fi
+
+    if [ "$compression" = "yes" ] ; then
+        cd $archivedir/$project/$tag/$backuptag/
+        tar -czf ../$backuptag.tar.gz .
+        cd $archivedir/$project/$tag/
+        rm -rf $archivedir/$project/$tag/$backuptag/
+    fi
+}
+
+recovery () {
+    if [ ! $rollbackversion ] ; then
+        echo "Variable rollbackversion must exist!"
+        exit 2 
+    fi
+
+    if [ -d $archivedir/$project ] ; then
+        cd $archivedir/$project
+    else 
+        echo "Can't find archivedir for this project"
+        exit 2
+    fi
+
+    if [ "$compression" = "yes" ] ; then
+        cd $backuproot/
+        tar -xzf $archivedir/$project/$rollbackversion/$backuptag.tar.gz .
+    else 
+        rsync -a $rsync_options $rollbackversion/$backuptag/* $backuproot
+    fi
+
+}
+
+delete_old () {
+    # We don't count the "latest" symlink
+    bakret=$(expr $bakret + 1 )
+
+    cd $archivedir/$project
+
+    ddirs=$(ls -1p 2>/dev/null | wc -l)
+    while [ $ddirs -gt $bakret ]
+    do
+        victim=$(ls -tr 2>/dev/null | head -1)
+        rm -rf $victim && echo "Deleted old $archivedir/$project/$victim"
+        ddirs=$(ls -1p 2>/dev/null | wc -l)
+    done
+}
+
+# Action!
+case "$action" in
+    backup) backup ; delete_old ;;
+    recovery) recovery ;;
+esac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/check_project.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+#!/bin/bash
+# check_project.sh - Made for Puppi
+# This script runs the checks defined in $projectsdir/$project/check and then in $checksdir
+# It can be used to automatically run tests during the deploy procedure
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Main functions
+handle_check () {
+        RETVAL=$?
+        if [ "$RETVAL" = "1" ] ; then
+            EXITWARN="1"
+        fi
+        if [ "$RETVAL" = "2" ] ; then
+            EXITCRIT="1"
+        fi
+}
+
+check () {
+    for command in $(ls -v1 $projectsdir/$project/check) ; do
+        "$projectsdir/$project/check/$command"
+        handle_check
+    done
+
+    for command in $(ls -v1 $checksdir) ; do
+        "$checksdir/$command" 
+        handle_check
+    done
+}
+
+# For nicer output when launched via cli
+echo -n "\n"
+
+# Run checks
+check
+
+# Manage general return code
+if [ "$EXITCRIT" = "1" ] ; then
+    exit 1
+fi
+
+if [ "$EXITWARN" = "1" ] ; then
+    exit 1
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/checkwardir.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,63 @@
+#!/bin/bash
+# checkwardir.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script is used to check if a webapp directory is successfully created or removed"
+    echo " after the (un)deploy of a war file"
+    echo "It implies that a directory with the name of the war file is created in the same path"
+    echo "-p <warname> - Waits until war created dir is present"
+    echo "-a <warname> - Wait until war created dir is absent"
+    echo "-s <seconds> - Wait some more seconds after the check"
+    echo "-c <configentry> - Name of the runtime config variable that contains the warname"
+    echo "Examples:"
+    echo "checkwardir.sh -p /store/tomcat/myapp/webapps/myapp.war"
+    echo "checkwardir.sh -a /store/tomcat/myoldapp/webapps/myoldapp.war"
+}
+
+seconds=2
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -s)
+      seconds=$2
+      shift 2
+      ;;
+    -p)
+      check="present"
+      warname=$2
+      shift 2
+      ;;
+    -a)
+      check="absent"
+      warname=$2
+      shift 2
+      ;;
+    -c)
+      warname="$(eval "echo \${$(echo ${2})}")"      
+      shift 2
+      ;;
+    *)
+      showhelp
+      exit
+      ;;
+  esac
+done
+
+checkdir () {
+    wardir=${warname%\.*}
+    while true
+       do
+        if [ $check == absent ] ; then
+            [ ! -d $wardir ] && break
+        else
+            [ -f $wardir/WEB-INF/web.xml ] && break
+        fi
+        sleep $seconds
+    done
+}
+
+checkdir
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/clean_filelist.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+#!/bin/bash
+# clean_filelist.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script is used to cleanup a list of files to download from unwanted data"
+    echo "It has 1 optional argument:"
+    echo "The prefix, present in the list, to cut out when defining files to deploy"
+    echo "The list file is defined as $downloadedfile , these variables are gathered from the Puppi runtime"
+    echo "  config file."
+    echo 
+    echo "Example:"
+    echo "clean_filelist.sh http://svn.example42.com/myproject"
+}
+
+
+if [ $1 ] ; then
+    prefix=$1
+else
+    prefix=""
+fi
+
+deployfilelist=$downloadedfile
+
+# Clean list
+cleanlist () {
+
+    sed -i "s/^$prefix//g" $deployfilelist
+
+}
+
+cleanlist
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/database.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,96 @@
+#!/bin/bash
+# database.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script executes database queries and dumps"
+    echo "It integrates and uses variables provided by other core Puppi scripts"
+    echo "It has the following options:"
+    echo "-t <database_type> The database type. Currently only mysql is suppoerted"
+    echo "-a <action> The action to perform:"
+    echo "            run - Run a mysql command based on a given .sql file"
+    echo "            dump - Dump the specified database in the archive dir"
+    echo "            restore - Restore the specified database from the archive dir"
+    echo "-d <database_name> The database name to manage"
+    echo "-u <database_user> The database user used to run the queries"
+    echo "-p <database_password> The user password"
+    echo "-h <host> The database server hostname"
+}
+
+# Arguments defaults
+db_type=mysql
+db_action=run
+db_user=root
+db_host=localhost
+db_password=""
+
+# Check Arguments
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -t)
+      db_type=$2
+      shift 2 ;;
+    -a)
+      db_action=$2
+      shift 2 ;;
+    -d)
+      db_name=$2
+      shift 2 ;;
+    -u)
+      db_user=$2
+      shift 2 ;;
+    -p)
+      db_password=$2
+      shift 2 ;;
+    -h)
+      db_host=$2
+      shift 2 ;;
+  esac
+done
+
+
+
+mysql_run () {
+    case "$db_action" in
+      run)
+        file $downloadedfile | grep gzip &>/dev/null 2>&1 && sqlfile_type="gzip"
+        file $downloadedfile | grep Zip &>/dev/null 2>&1 && sqlfile_type="zip"
+        case "$sqlfile_type" in
+          gzip)
+            zcat $downloadedfile | mysql -u $db_user -p$db_password -h $db_host $db_name
+            check_retcode ;;
+          zip)
+            unzip -p $downloadedfile | mysql -u $db_user -p$db_password -h $db_host $db_name
+            check_retcode ;;
+          *)
+            mysql -u $db_user -p$db_password -h $db_host $db_name < $downloadedfile
+            check_retcode ;;
+        esac
+        ;;
+      dump)
+        mkdir -p $archivedir/$project/$tag
+        if [ $archivedir/$project/latest ] ; then
+            rm -f $archivedir/$project/latest
+        fi
+        ln -sf $archivedir/$project/$tag $archivedir/$project/latest
+
+        mysqldump -u $db_user -p$db_password -h $db_host --add-drop-table --databases $db_name | gzip > $archivedir/$project/$tag/$db_name.sql.gz
+        check_retcode ;;
+      restore)
+        zcat $archivedir/$project/$rollbackversion/$db_name.sql.gz | mysql -u $db_user -p$db_password -h $db_host $db_name
+        check_retcode ;;
+    esac
+}
+
+case "$db_type" in
+      mysql)
+        mysql_run
+        ;;
+      *)
+        showhelp
+        ;;
+esac
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/delete.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+#!/bin/bash
+# delete.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Manage script variables
+if [ $1 ] ; then
+    tobedeleted=$1
+else
+    echo "You must provide a file or directory to delete!"
+    exit 2 
+fi
+
+if [ "$tobedeleted" = "/" ] ; then
+    echo "Be Serious!"
+    exit 2
+fi
+
+# Move file
+move () {
+    mkdir -p $workdir/$project/deleted
+    mv $tobedeleted $workdir/$project/deleted
+}
+
+move
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/deploy.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,59 @@
+#!/bin/bash
+# deploy.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script deploys the files present in the \$predeploydir to the deploy destination dir"
+    echo "It has the following options:"
+    echo "\$1 (Required) - Destination directory where to deploy files"
+    echo "\$2 (Optional) - Name of the variable that identifies a specific predeploydir"
+    echo 
+    echo "Examples:"
+    echo "deploy.sh /var/www/html/my_app"
+    echo "deploy.sh /var/www/html/my_app/conf config"
+}
+
+# Check arguments
+if [ $1 ] ; then
+    deploy_destdir=$1
+# This breaks on projects::maven when using more than one deploy destinations
+#    [ $deploy_root ] && deploy_destdir=$deploy_root
+else
+    showhelp
+    exit 2 
+fi
+
+# Obtain the value of the variable with name passed as second argument
+# If no one is given, we take all the files in $predeploydir
+if [ $2 ] ; then
+    deployfilevar=$2
+    deploy_sourcedir="$(eval "echo \${$(echo ${deployfilevar})}")"
+    if [ "$deploy_sourcedir" = "" ] ; then
+        exit 0
+    fi
+else
+    deploy_sourcedir="$predeploydir"
+fi
+
+# Copy files
+deploy () {
+    case "$debug" in
+        yes)
+            rsync -rlptDv $deploy_sourcedir/ $deploy_destdir/
+            check_retcode
+        ;;
+        full)
+            rsync -rlptDv $deploy_sourcedir/ $deploy_destdir/
+            check_retcode
+        ;;
+        *)
+            rsync -rlptD $deploy_sourcedir/ $deploy_destdir/
+            check_retcode
+        ;;
+    esac
+}
+
+deploy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/deploy_files.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,69 @@
+#!/bin/bash
+# deploy_files.sh - Made for Puppi
+# This is an extended version of the deploy script
+# It accepts more options to better handle how files are deployed
+# in the destination directory
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script deploys the files present in the \$predeploydir to the deploy destination dir"
+    echo "It has the following options:"
+    echo "-d <path> (Required) - Destination directory where to deploy files"
+    echo "-p <name> (Optional) - Name of the variable that identifies a specific predeploydir"
+    echo "-c <true|false> (Default: false) - If to enabled the --delete option to the rsync command"
+    echo 
+    echo "Examples:"
+    echo "deploy_files.sh -d /var/www/html/my_app"
+    echo "deploy_files.sh -d /var/www/html/my_app/conf -p config"
+    echo "deploy_files.sh -d /var/www/html/my_app/conf -c true"
+}
+
+deploy_sourcedir="$predeploydir"
+clean_destdir="false"
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -d)
+      deploy_destdir=$2
+      shift 2 ;;
+    -p)
+      deployfilevar=$2
+      deploy_sourcedir="$(eval "echo \${$(echo ${deployfilevar})}")"
+      shift 2 ;;
+    -c)
+      clean_destdir=$2
+      shift 2 ;;
+    *)
+      showhelp
+      exit
+      ;;
+  esac
+done
+
+rsync_delete=""
+if [ x$clean_destdir == "xtrue" ] ; then
+  rsync_delete="--delete"
+fi
+
+# Copy files
+deploy () {
+    case "$debug" in
+        yes)
+            rsync -rlptDv $rsync_delete $deploy_sourcedir/ $deploy_destdir/
+            check_retcode
+        ;;
+        full)
+            rsync -rlptDv $rsync_delete $deploy_sourcedir/ $deploy_destdir/
+            check_retcode
+        ;;
+        *)
+            rsync -rlptD $rsync_delete $deploy_sourcedir/ $deploy_destdir/
+            check_retcode
+        ;;
+    esac
+}
+
+deploy
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/execute.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+#!/bin/bash
+# execute.sh - Made for Puppi
+# This script just executes what is passed as argument
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+#parse variables
+command=$(eval "echo "$*"")
+
+#execute command
+eval "${command}"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/firewall.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,63 @@
+#!/bin/bash
+# firewall.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script places a temporary firewall (iptables) rule to block access from the IP defined"
+    echo "It has the following options:"
+    echo "\$1 (Required) - Remote Ip address to block (Generally a load balancer"
+    echo "\$2 (Required) - Local port to block (0 for all ports"
+    echo "\$3 (Required) - Set on or off to insert or remove the blocking rule"
+    echo "\$4 (Required) - Number of seconds to sleep after having set the rule"
+    echo 
+    echo "Examples:"
+    echo "firewall.sh 10.42.0.1 0 on"
+    echo "firewall.sh 10.42.0.1 0 off"
+}
+
+# Check arguments
+if [ $2 ] ; then
+    ip=$1
+    port=$2
+else
+    showhelp
+    exit 2 
+fi
+
+if [ $3 ] ; then
+    if [ "$3" = "on" ] ; then
+        action="-I"
+    elif [ "$3" = "off" ] ; then
+        action="-D"
+    else 
+        showhelp
+        exit 2
+    fi
+else
+    showhelp
+    exit 2
+fi
+
+if [ $4 ] ; then
+    delay=$4
+else
+    delay="1"
+fi
+
+# Block
+run_iptables () {
+    if [ "$port" = "0" ] ; then
+        iptables $action INPUT -s $ip -j DROP
+    else
+        iptables $action INPUT -s $ip -p tcp --dport $port -j DROP
+    fi
+}
+
+run_iptables
+echo "Sleeping for $delay seconds"
+sleep $delay
+
+# Sooner or later this script will have multiOS support
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/functions	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,229 @@
+#!/bin/bash
+# General Puppi functions
+
+BOOTUP=color
+RES_COL=75
+MOVE_TO_COL="echo -en \\033[${RES_COL}G"
+SETCOLOR_SUCCESS="echo -en \\033[0;32m"
+SETCOLOR_FAILURE="echo -en \\033[0;31m"
+SETCOLOR_WARNING="echo -en \\033[0;33m"
+SETCOLOR_NORMAL="echo -en \\033[0;39m"
+SETCOLOR_TITLE="echo -en \\033[0;35m"
+SETCOLOR_BOLD="echo -en \\033[0;1m"
+
+echo_success() {
+  [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
+  echo -n "["
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
+  echo -n $"  OK  "
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+  echo -n "]"
+  echo -ne "\r"
+  return 0
+}
+
+echo_dontdeploy() {
+  [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
+  echo -n "["
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS
+  echo -n $" NO NEED TO DEPLOY "
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+  echo -n "]"
+  echo -ne "\r"
+  return 0
+}
+
+echo_failure() {
+  [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
+  echo -n "["
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
+  echo -n $"FAILED"
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+  echo -n "]"
+  echo -ne "\r"
+  return 1
+}
+
+echo_passed() {
+  [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
+  echo -n "["
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+  echo -n $"PASSED"
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+  echo -n "]"
+  echo -ne "\r"
+  return 1
+}
+
+echo_warning() {
+  [ "$BOOTUP" = "color" ] && $MOVE_TO_COL
+  echo -n "["
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
+  echo -n $"WARNING"
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+  echo -n "]"
+  echo -ne "\r"
+  return 1
+}
+
+echo_title () {
+  echo
+  echo
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_TITLE
+  echo "$1"
+  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
+}
+
+check_retcode () {
+    if [ $? = "0" ] ; then
+        true
+    else
+        exit 2
+    fi
+}
+
+handle_result () {
+        RETVAL=$?
+        if [ "$RETVAL" = "0" ] ; then
+            showresult="echo_success"
+            result="OK"
+        fi
+        if [ "$RETVAL" = "1" ] ; then
+            showresult="echo_warning"
+            EXITWARN="1"
+            result="WARNING"
+        fi
+        if [ "$RETVAL" = "2" ] ; then
+            showresult="echo_failure"
+            EXITCRIT="1"
+            result="CRITICAL"
+        fi
+        if [ "$RETVAL" = "99" ] ; then
+            showresult="echo_dontdeploy"
+            DONTDEPLOY="1"
+            result="OK"
+        fi
+        if [ x$show == "xyes" ] ; then
+            $showresult
+            echo
+            echo -e "$output"
+            echo
+        elif [ x$show == "xfail" ] && [ x$RETVAL != "x0" ] ; then
+            $showresult
+            echo
+            echo -e "$output"
+            echo
+        fi
+
+        # Output to file
+        if [ ! -d $logdir/$project/$tag ] ; then
+            mkdir -p $logdir/$project/$tag
+        fi
+        let counter=counter+1
+        echo $title > $logdir/$project/$tag/$counter-$command
+        echo $code >> $logdir/$project/$tag/$counter-$command
+        echo $result >> $logdir/$project/$tag/$counter-$command
+        echo $output >> $logdir/$project/$tag/$counter-$command
+
+}
+
+
+# Function taken from http://www.threadstates.com/articles/parsing_xml_in_bash.html
+xml_parse () {
+    local tag=$1
+    local xml=$2
+
+    # Find tag in the xml, convert tabs to spaces, remove leading spaces, remove the tag.
+    grep $tag $xml | \
+        tr '\011' '\040' | \
+        sed -e 's/^[ ]*//' \
+            -e 's/^<.*>\([^<].*\)<.*>$/\1/'
+}
+
+# Stores the passed arguments in Project runtime config file
+# Only if the parameter is not already defined
+# Usage:
+# save_runtime_config parameter=value # Sets or overrides parameter
+# save_runtime_config parameter=value notforce # Sets parameters only if is not already set
+save_runtime_config () {
+    parameter=$(echo $1 | cut -d '=' -f1)
+    value=$(echo $1 | cut -d '=' -f2-)
+    force=$2
+
+    if [[ ! $(grep $parameter $workdir/$project/config) ]] ; then
+        echo  >> $workdir/$project/config
+        echo "# Added by $0" >> $workdir/$project/config
+        echo "$parameter=\"$value\"" >> $workdir/$project/config
+    else
+#        sed -i "/^$parameter=/d" $workdir/$project/config # No real need to remove lines with old configs
+        if [[ x$force == xnotforce ]] ; then
+            echo  >> $workdir/$project/config
+            echo "# CHANGE NOT FORCED by $0" >> $workdir/$project/config
+            echo "# $parameter=\"$value\"" >> $workdir/$project/config
+        else
+            echo  >> $workdir/$project/config
+            echo "# CHANGED by $0" >> $workdir/$project/config
+            echo "$parameter=\"$value\"" >> $workdir/$project/config
+       fi
+    fi
+    
+}
+
+# Adds a runtime comment to Project runtime config file
+save_runtime_comment () {
+    echo  >> $workdir/$project/config
+    echo "# Added by $0" >> $workdir/$project/config
+    echo "  ## $1" >> $workdir/$project/config
+}
+
+
+# Stores the passed arguments in Project runtime config file
+# Forces parameter overwrite if already defined
+overwrite_runtime_config () {
+    echo "$1" >> $workdir/$project/config
+}
+
+ask_interactive () {
+    if [ x$show == "xyes" ] ; then
+        echo -n $title
+    fi
+
+    if [ "$interactive" = "yes" ] ; then
+        echo 
+        echo "INTERACTIVE MODE: Press 'x' to exit or just return to go on" 
+        read press
+        case $press in 
+            x) exit 2 ;;
+            *) return
+        esac
+    fi
+}
+
+# Shows or executes a command
+show_command () {
+   echo
+   $SETCOLOR_BOLD ; echo "$HOSTNAME: $*" ; $SETCOLOR_NORMAL
+
+   bash -c "$*"
+
+# Grep filter at show_command level
+#   if [ ! -z "$greppattern" ] ; then
+#       bash -c "$*" | grep $greppattern
+#   else
+#       bash -c "$*"
+#   fi
+}
+
+# Filtering out only:  $ ; ` | < >
+shell_filter () {
+    echo $1 | sed 's/\$//g' | sed 's/;//g' | sed 's/`//g' | sed 's/|//g' | sed 's/<//g' | sed 's/>//g'
+}
+
+shell_filter_strict () {
+# Filtering out:  $ ; ` | < > = ! { } [ ] / \ # &
+    echo $1 | sed 's/\$//g' | sed 's/;//g' | sed 's/`//g' | sed 's/|//g' | sed 's/<//g' | sed 's/>//g'  | sed 's/=//g' | sed 's/!//g' | sed 's/{//g' | sed 's/}//g' | sed 's/\[//g' | sed 's/\]//g' | sed 's/\///g' | sed 's/\\//g' | sed 's/#//g' | sed 's/&//g'
+
+# Filtering out: all but accepted chars
+#     echo $1 | sed "s/[^a-Z0-9_\-]//Ig"
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/get_file.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,165 @@
+#!/bin/bash
+# get_file.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script is used to retrieve the file defined after the -s parameter"
+    echo "The source specified  can be any of these:"
+    echo "  file://local/file/path"
+    echo "  http(s)://my.server/file/path"
+    echo "  ssh://user@my.server/file/path"
+    echo "  svn://user:password@my.server/file/path"
+    echo "Note: Avoid using chars like : / and @ outside the Uri standards paths"
+    echo
+    echo "It has the following options:"
+    echo "-s <source_file> - The URL of the file to get"
+    echo "-t <file_type> - The type of file that is retrieved: list|tarball|maven-metadata|dir"
+    echo "-d <local_dir> - An alternative destination directory (default is automatically chosen)"
+    echo "-a <yes|no> - If 'no' return a special error code (99) if the download checksum is the same of the one previously downloaded"
+    echo "-u <http_user> - in case of type http, specify a http_user for curl"
+    echo "-p <http_password> - in case of type http, specifiy http_user for curl"
+    echo "-k - tell curl not to validate ssl certs"
+    echo "              This option can be used for automatic deploys (ie via cron) that actually deploy only new changes"
+}
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -s)
+      type=$(echo $2 | cut -d':' -f1)
+      url=$2
+      downloadfilename=$(basename $2)
+      downloaddir=$predeploydir
+      shift 2 ;;
+    -t)
+      case $2 in
+      # This logic is applied:
+      # In $predeploydir go ($workdir/$project/deploy) go file that have to be deployed
+      # In $storedir go ($workdir/$project/store) go support files as tarballs or lists
+          list)
+          downloaddir=$storedir
+          save_runtime_config "source_type=list"
+          ;;
+          tarball)
+          downloaddir=$storedir
+          save_runtime_config "source_type=tarball"
+          ;;
+          tar)
+          downloaddir=$storedir
+          save_runtime_config "source_type=tar"
+          ;;
+          zip)
+          downloaddir=$storedir
+          save_runtime_config "source_type=zip"
+          ;;
+          maven-metadata)
+          downloaddir=$storedir
+          save_runtime_config "source_type=maven"
+          ;;
+          dir)
+          downloaddir=$predeploydir
+          save_runtime_config "source_type=dir"
+          ;;
+          war)
+          downloaddir=$predeploydir
+          save_runtime_config "source_type=war"
+          ;;
+          mysql)
+          downloaddir=$storedir
+          save_runtime_config "source_type=mysql"
+          ;;
+          gz)
+          downloaddir=$storedir
+          save_runtime_config "source_type=gz"
+          ;;
+      esac
+      shift 2 ;;
+    -d)
+      # Enforces and overrides and alternative downloaddir
+      downloaddir=$2
+      shift 2 ;;
+    -a)
+      alwaysdeploy=$2
+      shift 2 ;;
+    -u)
+      http_user=$2
+      shift 2 ;;
+    -p)
+      http_password=$2
+      shift 2 ;;
+    -k)
+      ssl_arg=$1
+      shift 1 ;;
+    *)
+      showhelp
+      exit
+      ;;
+  esac
+done
+
+# Define what to use for downloads
+cd $downloaddir
+
+case $type in
+    s3)
+        s3cmd get $url
+        check_retcode
+        save_runtime_config "downloadedfile=$downloaddir/$downloadfilename"
+    ;;
+    ssh|scp) 
+        # ssh://user@my.server/file/path
+        scpuri=$(echo $url | cut -d'/' -f3-)
+        scpconn=$(echo $scpuri | cut -d'/' -f1)
+        scppath=/$(echo $scpuri | cut -d'/' -f2-)
+        rsync -rlptD -e ssh $scpconn:$scppath .
+        check_retcode
+        save_runtime_config "downloadedfile=$downloaddir/$downloadfilename"
+    ;;
+    http|https)
+        if [ -z "$http_password" ] ; then
+          curl $ssl_arg -s -f -L "$url" -O
+        else
+          curl $ssl_arg -s -f -L --anyauth --user $http_user:$http_password "$url" -O
+	fi
+        check_retcode
+        save_runtime_config "downloadedfile=$downloaddir/$downloadfilename"
+    ;;
+    svn)
+        svnuri=$(echo $url | cut -d'/' -f3-)
+        svnusername=$(echo $svnuri | cut -d':' -f1)
+        svnpassword=$(echo $svnuri | cut -d':' -f2 | cut -d'@' -f1)
+        svnserver=$(echo $svnuri | cut -d'@' -f2 | cut -d'/' -f1)
+        svnpath=/$(echo $svnuri | cut -d'@' -f2 | cut -d'/' -f2-)
+        mkdir -p $(dirname $svnpath)
+        svn export --force --username="$svnusername" --password="$svnpassword" svn://$svnserver/$svnpath $downloaddir
+        check_retcode
+        save_runtime_config "downloadedfile=$downloaddir/$downloadfilename"
+    ;;
+    file)
+        # file:///file/path
+        filesrc=$(echo $url | cut -d '/' -f3-)
+        rsync -rlptD $filesrc .
+        check_retcode
+        save_runtime_config "downloadedfile=$downloaddir/$downloadfilename"
+    ;;
+    rsync)
+        rsync -a "$url" .
+        # rsync -rlptD $url . # Why not preserving users/groups?
+        check_retcode
+        save_runtime_config "downloadedfile=$downloaddir/$downloadfilename"
+    ;;
+
+esac
+
+if [ x$alwaysdeploy == "xno" ] ; then
+    # Here is checked the md5sum of the downloaded file against a previously save one
+    # If the sums are the same the scripts exits 99 and puppi will stop the deploy without any warning or notification
+    [ -d $archivedir/$project ] || mkdir -p $archivedir/$project
+    touch $archivedir/$project/md5sum
+    md5sum $downloaddir/$downloadfilename > $workdir/$project/md5sum_downloaded
+    cat $archivedir/$project/md5sum > $workdir/$project/md5sum_deployed
+    diff $workdir/$project/md5sum_downloaded $workdir/$project/md5sum_deployed && exit 99
+    md5sum $downloaddir/$downloadfilename > $archivedir/$project/md5sum
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/get_filesfromlist.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,67 @@
+#!/bin/bash
+# get_filesfromlist.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script is used to retrieve the files present in a text file list."
+    echo "It has 1 required argument:"
+    echo "First argument (\$1 - required) is the base url (in URI format) from where to retrieve the files defined in the list"
+    echo "The list file is defined as \$downloadedfile , these variables are gathered from the Puppi runtime"
+    echo "  config file."
+    echo 
+    echo "Examples: "
+    echo "get_filesfromlist.sh http://svn.example42.com/myproject"
+    echo "get_filesfromlist.sh file:///mount/wwwdata/myproject"
+    echo "get_filesfromlist.sh ssh://user@server/var/www/myproject"
+    echo "get_filesfromlist.sh svn://user:password@server/repo/myproject"
+}
+
+
+if [ $1 ] ; then
+    baseurl=$1
+    type=$(echo $1 | cut -d':' -f1)
+else
+    showhelp
+    exit 2 
+fi
+
+
+# Download files
+downloadfiles () {
+
+    cd $predeploydir
+
+    for file in $(cat $downloadedfile | grep -v "^#" | grep -v "^$" ) ; do
+        filepath=$file
+        filedir=$(dirname $filepath)
+        mkdir -p $filedir
+        check_retcode
+        
+        case $type in 
+            ssh|scp) 
+                scp "$baseurl:$filepath" $filepath
+                check_retcode
+            ;;
+            http|https|file)
+                curl -s -f "$baseurl/$filepath" -o $filepath
+                check_retcode
+            ;;
+            svn)
+                svnuri=$(echo $baseurl/$filepath | cut -d'/' -f3-)
+                svnusername=$(echo $svnuri | cut -d':' -f1)
+                svnpassword=$(echo $svnuri | cut -d':' -f2 | cut -d'@' -f1)
+                svnserver=$(echo $svnuri | cut -d'@' -f2 | cut -d'/' -f1)
+                svnpath=/$(echo $svnuri | cut -d'@' -f2 | cut -d'/' -f2-)
+                mkdir -p $(dirname $svnpath)
+                svn export --force --username="$svnusername" --password="$svnpassword" http://$svnserver/$svnpath $(dirname $svnpath)
+                check_retcode
+            ;;
+        esac
+
+    done
+}
+
+downloadfiles
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/get_maven_files.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,99 @@
+#!/bin/bash
+# get_maven_files.sh - Made for Puppi
+# This script retrieves the files to deploy from a Maven repository.
+# It uses variables defined in the general and project runtime configuration files.
+# It uses curl to retrieve files so the $1 argument (base url of the maven repository) 
+# has to be in curl friendly format
+#   It has the following options:
+#   -u <http_user> - in case of type http, specify a http_user for curl
+#   -p <http_password> - in case of type http, specifiy http_user for curl
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -u)
+      http_user=$2
+      shift 2 ;;
+    -p)
+      http_password=$2
+      shift 2 ;;
+    *)
+      url=$1
+      ftype=$2
+      shift 2 ;;
+  esac
+done
+
+# Obtain the value of the variable with name passed as second argument
+# If no one is given, we take all the files in storedir
+
+#echo "Download and deploy $2 ? (Y/n)" 
+#read press
+#case $press in 
+#    Y|y) true ;;
+#    N|n) save_runtime_config "predeploydir_$2=" ; exit 0
+#esac
+
+if [ $debug ] ; then
+    tarcommand="tar -xvf"
+else
+    tarcommand="tar -xf"
+fi
+
+if [ $debug ] ; then
+    zipcommand="unzip"
+else
+    zipcommand="unzip -q"
+fi
+
+cd $storedir
+
+if [ -z "$http_password" ] ; then
+    authparam=""
+else
+    authparam="--anyauth --user $http_user:$http_password"
+fi
+
+case $ftype in
+    warfile)
+        curl -s -f $authparam "$url/$version/$warfile" -O
+        check_retcode
+        cp -a $warfile $predeploydir/$artifact.war
+        save_runtime_config "deploy_warpath=$deploy_root/$artifact.war"
+    ;;
+    jarfile)
+        curl -s -f $authparam "$url/$version/$jarfile" -O
+        check_retcode
+        cp -a $jarfile $predeploydir/$artifact.jar
+        save_runtime_config "deploy_jarpath=$deploy_root/$artifact.jar"
+    ;;
+    configfile)
+        curl -s -f $authparam "$url/$version/$configfile" -O
+        check_retcode
+        mkdir $workdir/$project/deploy_configfile
+        cd $workdir/$project/deploy_configfile
+        $tarcommand $storedir/$configfile
+        check_retcode
+        save_runtime_config "predeploydir_configfile=$workdir/$project/deploy_configfile"
+    ;;
+    srcfile)
+        curl -s -f $authparam "$url/$version/$srcfile" -O
+        check_retcode
+        mkdir $workdir/$project/deploy_srcfile
+        cd $workdir/$project/deploy_srcfile
+        $tarcommand $storedir/$srcfile
+        check_retcode
+        save_runtime_config "predeploydir_srcfile=$workdir/$project/deploy_srcfile"
+    ;;
+    zipfile)
+        curl -s -f $authparam "$url/$version/$zipfile" -O
+        check_retcode
+        mkdir $workdir/$project/deploy_zipfile
+        cd $workdir/$project/deploy_zipfile
+        $zipcommand $storedir/$zipfile
+        check_retcode
+        save_runtime_config "predeploydir_zipfile=$workdir/$project/deploy_zipfile"
+    ;;
+esac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/get_metadata.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,124 @@
+#!/bin/bash
+# get_metadata.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script retrieves some metadata from the downwloaded files "
+    echo "The metadatasource is automatically detected from the \$source_type runtime config"
+    echo
+    echo "It has some, not required, options:"
+    echo "-m <magicstring> - The string to use as *fix in custom metadata info provided "
+    echo "-mc <anotherstring> - The string to use as qualifier for Maven metadata config tars"
+    echo "-mj <anotherstring> - The string to use as qualifier for Maven metadata jars"
+    echo "-mw <anotherstring> - The string to use as qualifier for Maven metadata wars"
+    echo "-mz <anotherstring> - The string to use as qualifier for Maven metadata zips"
+    echo "-at <anotherstring> - The type to obtain the artifact, should be \"release\", "
+    echo "                      \"latest\", \"snapshot\" or a specific version (e.g. \"2.5.0\")"
+}
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -m)
+      suffix=$2
+      shift 2 ;;
+    -mc)
+      config_suffix=$2
+      shift 2 ;;
+    -mj)
+      jar_suffix=$2
+      shift 2 ;;
+    -mw)
+      war_suffix=$2
+      shift 2 ;;
+    -mz)
+      zip_suffix=$2
+      shift 2 ;;
+    -at)
+      artifact_type=$2
+      shift 2 ;;
+    -h)
+      showhelp ;;
+  esac
+done
+
+# validating input
+# see http://docs.codehaus.org/display/MAVEN/Repository+Metadata for specs
+case $artifact_type in
+    release)
+    ;;
+    latest)
+    ;;
+    snapshot)
+    ;;
+    *)
+    # defaulting to version 
+    version=$artifact_type
+    ;;
+esac
+
+case $source_type in
+    list)
+    if [ -z $suffix ] ; then
+        suffix="####"
+    fi
+    # TODO Make this more secure, for God's sake!
+    for param in $(cat $downloadedfile | grep "^$suffix" ) ; do
+        save_runtime_comment $param
+    done
+    ;;
+    tarball)
+    ;;
+    maven)
+    [ ${#version} -eq 0 ] && version=$(xml_parse $artifact_type $downloadedfile )
+    artifact=$(xml_parse artifactId $downloadedfile )
+
+    # Definition of qualifiers for Maven has changed from the (wrong) assumption
+    # of having cfg-$suffix and src-$suffix for staticfiles and config tarballs
+    # to a more flexible management of qualifiers names with two different params (-m and -mc)
+    # The "suffixnotset" string is passed by default by the Puppi maven define
+    # YES, it's crap. 
+    if [[ x$suffix != "xsuffixnotset" ]] ; then
+        srcfile=$artifact-$version-$suffix.tar
+    else 
+        srcfile=$artifact-$version.tar
+    fi
+
+    if [[ x$config_suffix != "xsuffixnotset" ]] ; then
+        configfile=$artifact-$version-$config_suffix.tar
+    else
+        configfile=$artifact-$version.tar
+    fi
+
+    if [[ x$jar_suffix != "xsuffixnotset" ]] ; then
+        jarfile=$artifact-$version-$jar_suffix.jar
+    else
+        jarfile=$artifact-$version.jar
+    fi
+
+    if [[ x$war_suffix != "xsuffixnotset" ]] ; then
+        warfile=$artifact-$version-$war_suffix.war
+    else
+        warfile=$artifact-$version.war
+    fi
+
+    if [[ x$zip_suffix != "xsuffixnotset" ]] ; then
+        zipfile=$artifact-$version-$zip_suffix.zip
+    else
+        zipfile=$artifact-$version.zip
+    fi
+
+    # Store metadata
+    save_runtime_config "version=$version" 
+    save_runtime_config "artifact=$artifact"
+    # Store filenames
+    save_runtime_config "zipfile=$zipfile"
+    save_runtime_config "warfile=$warfile"
+    save_runtime_config "jarfile=$jarfile"
+    save_runtime_config "srcfile=$srcfile" 
+    save_runtime_config "configfile=$configfile" 
+    ;;
+esac
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/git.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,176 @@
+#!/bin/bash
+# git.sh - Made for Puppi
+
+# All variables are exported
+set -a 
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script performs the git operations required by puppi::project::git"
+    echo "It integrates and uses variables provided by other core Puppi scripts"
+    echo "It has the following options:"
+    echo "-a <action> (Optional) What action to perform. Available options: deploy (default), rollback"
+    echo "-s <source> (Required) Git source repo to use"
+    echo "-d <destination> (Required) Directory where files are deployed"
+    echo "-u <user> (Optional) User that performs the deploy operations. Default root"
+    echo "-gs <git_subdir> (Optional) If only a specific subdir of the gitrepo has to be copied to the install destination"
+    echo "-t <tag> (Optional) Tag to deploy"
+    echo "-b <branch> (Optional) Branch to deploy"
+    echo "-c <commit> (Optional) Commit to deploy"
+    echo "-v <true|false> (Optional) If verbose"
+    echo "-k <true|false> (Optional) If .git dir is kept on deploy_root"
+    echo 
+    echo "Examples:"
+    echo "git.sh -a deploy -s $source -d $deploy_root -u $user -gs $git_subdir -t $tag -b $branch -c $commit -v $bool_verbose -k $bool_keep_gitdata"
+}
+
+verbose="true"
+
+# Check Arguments
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -a)
+      case $2 in
+          rollback)
+          action="rollback"
+          ;;
+          *)
+          action="install"
+          ;;
+      esac 
+      shift 2 ;;
+    -s)
+      if [ $source ] ; then
+        source=$source
+      else
+        source=$2
+      fi
+      shift 2 ;;
+    -d)
+      if [ $deploy_root ] ; then
+        deploy_root=$deploy_root
+      else
+        deploy_root=$2
+      fi
+      shift 2 ;;
+    -u)
+      if [ $user ] ; then
+        deploy_user=$user
+      else
+        deploy_user=$2
+      fi
+      shift 2 ;;
+    -gs)
+      if [ $git_subdir ] ; then
+        git_subdir=$git_subdir
+      else
+        git_subdir=$2
+      fi
+      shift 2 ;;
+    -t)
+      if [ $git_tag ] ; then
+        git_tag=$git_tag
+      else
+        git_tag=$2
+      fi
+      shift 2 ;;
+    -b)
+      if [ $branch ] ; then
+        branch=$branch
+      else
+        branch=$2
+      fi
+      shift 2 ;;
+    -c)
+      if [ $commit ] ; then
+        commit=$commit
+      else
+        commit=$2
+      fi
+      shift 2 ;;
+    -v)
+      if [ $verbose ] ; then
+        verbose=$verbose
+      else
+        verbose=$2
+      fi
+      shift 2 ;;
+    -k)
+      if [ $keep_gitdata ] ; then
+        keep_gitdata=$keep_gitdata
+      else
+        keep_gitdata=$2
+      fi
+      shift 2 ;;
+    *)
+      showhelp
+      exit ;;
+  esac
+done
+
+if [ "x$verbose" == "xtrue" ] ; then
+  verbosity=""
+else
+  verbosity="--quiet"
+fi
+
+cd /
+
+gitsubdir=""
+gitdir=$deploy_root
+if [ "x$keep_gitdata" != "xtrue" ] ; then
+  if [ ! -d $archivedir/$project-git ] ; then
+    mkdir $archivedir/$project-git
+    chown -R $deploy_user:$deploy_user $archivedir/$project-git
+  fi
+  gitdir=$archivedir/$project-git/gitrepo
+fi
+if [ "x$git_subdir" != "xundefined" ] ; then
+  if [ ! -d $archivedir/$project-git ] ; then
+    mkdir $archivedir/$project-git
+    chown -R $deploy_user:$deploy_user $archivedir/$project-git
+  fi
+  gitdir=$archivedir/$project-git
+  gitsubdir="$git_subdir/"
+fi
+
+do_install () {
+  if [ -d $gitdir/.git ] ; then
+    cd $gitdir
+    git pull $verbosity origin $branch
+    git checkout $verbosity $branch
+    if [ "x$?" != "x0" ] ; then
+      git checkout -b $verbosity $branch
+    fi
+  else
+    git clone $verbosity --branch $branch --recursive $source $gitdir
+    cd $gitdir
+  fi
+
+  if [ "x$git_tag" != "xundefined" ] ; then
+    git checkout $verbosity $git_tag
+  fi
+
+  if [ "x$commit" != "xundefined" ] ; then
+    git checkout $verbosity $commit
+  fi
+
+  if [ "x$gitdir" == "x$archivedir/$project-git/gitrepo" ] ; then
+    rsync -a --exclude=".git" $gitdir/$gitsubdir $deploy_root/
+  fi
+
+}
+
+do_rollback () {
+
+  echo "Rollback not yet supported"
+}
+
+# Action!
+case "$action" in
+    install) export -f do_install ; su $deploy_user -c do_install ;;
+    rollback) do_rollback ;;
+esac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/header	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+configfile="/etc/puppi/puppi.conf"
+
+# Load general configurations
+if [ ! -f $configfile ] ; then
+    echo "Config file: $configfile not found"
+    exit 2
+else
+    . $configfile
+    . $scriptsdir/functions
+fi
+
+# Load project runtime configuration
+projectconfigfile="$workdir/$project/config"
+if [ ! -f $projectconfigfile ] ; then
+    echo "Project runtime config file: $projectconfigfile not found"
+    exit 2
+else
+    . $projectconfigfile
+fi
+
+# Activate debug 
+case "$debug" in
+    yes) set -x  ;;
+    full) set -xv  ;;
+esac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/hg.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,159 @@
+#!/bin/bash
+# hg.sh - Made for Puppi
+
+# All variables are exported
+set -a 
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script performs the hg operations required by puppi::project::hg"
+    echo "It integrates and uses variables provided by other core Puppi scripts"
+    echo "It has the following options:"
+    echo "-a <action> (Optional) What action to perform. Available options: deploy (default), rollback"
+    echo "-s <source> (Required) Git source repo to use"
+    echo "-d <destination> (Required) Directory where files are deployed"
+    echo "-u <user> (Optional) User that performs the deploy operations. Default root"
+    echo "-t <tag> (Optional) Tag to deploy"
+    echo "-b <branch> (Optional) Branch to deploy"
+    echo "-c <commit> (Optional) Commit to deploy"
+    echo "-v <true|false> (Optional) If verbose"
+    echo "-k <true|false> (Optional) If .hg dir is kept on deploy_root"
+    echo 
+    echo "Examples:"
+    echo "hg.sh -a deploy -s $source -d $deploy_root -u $user -t $tag -b $branch -c $commit -v $bool_verbose -k $bool_keep_hgdata"
+}
+
+verbose="true"
+
+# Check Arguments
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -a)
+      case $2 in
+          rollback)
+          action="rollback"
+          ;;
+          *)
+          action="install"
+          ;;
+      esac 
+      shift 2 ;;
+    -s)
+      if [ $source ] ; then
+        source=$source
+      else
+        source=$2
+      fi
+      shift 2 ;;
+    -d)
+      if [ $deploy_root ] ; then
+        deploy_root=$deploy_root
+      else
+        deploy_root=$2
+      fi
+      shift 2 ;;
+    -u)
+      if [ $user ] ; then
+        deploy_user=$user
+      else
+        deploy_user=$2
+      fi
+      shift 2 ;;
+    -t)
+      if [ $hg_tag ] ; then
+        hg_tag=$hg_tag
+      else
+        hg_tag=$2
+      fi
+      shift 2 ;;
+    -b)
+      if [ $branch ] ; then
+        branch=$branch
+      else
+        branch=$2
+      fi
+      shift 2 ;;
+    -c)
+      if [ $commit ] ; then
+        commit=$commit
+      else
+        commit=$2
+      fi
+      shift 2 ;;
+    -v)
+      if [ $verbose ] ; then
+        verbose=$verbose
+      else
+        verbose=$2
+      fi
+      shift 2 ;;
+    -k)
+      if [ $keep_hgdata ] ; then
+        keep_hgdata=$keep_hgdata
+      else
+        keep_hgdata=$2
+      fi
+      shift 2 ;;
+    *)
+      showhelp
+      exit ;;
+  esac
+done
+
+if [ "x$verbose" == "xtrue" ] ; then
+  verbosity="-v"
+else
+  verbosity=""
+fi
+
+cd /
+
+hgdir=$deploy_root
+if [ "x$keep_hgdata" != "xtrue" ] ; then
+  if [ ! -d $archivedir/$project-hg ] ; then
+    mkdir $archivedir/$project-hg
+    chown -R $deploy_user:$deploy_user $archivedir/$project-hg
+  fi
+  hgdir=$archivedir/$project-hg/hgrepo
+fi
+
+do_install () {
+  if [ -d $hgdir/.hg ] ; then
+    cd $hgdir
+    hg pull $verbosity origin $branch
+    hg update $verbosity $branch
+    if [ "x$?" != "x0" ] ; then
+      hg update $verbosity $branch
+    fi
+  else
+    hg clone $verbosity --branch $branch $source $hgdir
+    cd $hgdir
+  fi
+
+  if [ "x$hg_tag" != "xundefined" ] ; then
+    hg update $verbosity $hg_tag
+  fi
+
+  if [ "x$commit" != "xundefined" ] ; then
+    hg update $verbosity $commit
+  fi
+
+  if [ "x$hgdir" == "x$archivedir/$project-hg" ] ; then
+    rsync -a --exclude=".hg" $hgdir/$hgsubdir $deploy_root/
+  fi
+
+}
+
+do_rollback () {
+
+  echo "Rollback not yet supported"
+}
+
+# Action!
+case "$action" in
+    install) export -f do_install ; su $deploy_user -c do_install ;;
+    rollback) do_rollback ;;
+esac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/predeploy.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,95 @@
+#!/bin/bash
+# predeploy.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script prepares the contents of the predeploy directory"
+    echo "It integrates and uses variables provided by other core Puppi scripts"
+    echo "It has the following options:"
+    echo "-v <variable_name> (optional) Name of the variable that identifies the file to untar/unzip"
+    echo "                              By default is used $downloadedfile"
+    echo "-t <file_type> (optional) The type of file that is retrieved: zip|tarball"
+    echo "                          By default is used $source_type "
+    echo "-m <magicfix> (optional) The prefix (directory) you may not want to put in the deploy"
+    echo "                       Use this if the zip or tar contain a base dir (as often) and you want to copy"
+    echo "                       to the deploy dir only its contents and not the whole directory"
+    echo 
+    echo "Examples:"
+    echo "predeploy.sh "
+    echo "predeploy.sh -t zip"
+    echo "predeploy.sh -t zip -v myz"
+}
+
+
+# Check Arguments
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -v)
+      downloadedfile="$(eval "echo \${$(echo ${2})}")"
+      shift 2 ;;
+    -t)
+      source_type=$2
+      shift 2 ;;
+    -m)
+      predeploy_dirprefix=$2
+      shift 2 ;;
+  esac
+done
+
+
+
+predeploy () {
+    cd $predeploydir
+    case "$source_type" in
+      tarball)
+        case "$debug" in
+          yes|full)
+            tar -zxvf $downloadedfile
+            check_retcode
+          ;;
+          *)
+            tar -zxf $downloadedfile
+            check_retcode
+          ;;
+        esac
+        ;;
+      zip)
+        case "$debug" in
+          yes|full)
+            unzip $downloadedfile
+            check_retcode
+          ;;
+          *)
+            unzip -qq $downloadedfile
+            check_retcode
+          ;;
+        esac
+        ;;
+      gz)
+        case "$debug" in
+          yes|full)
+            gzip -d $downloadedfile
+            check_retcode
+          ;;
+          *)
+            gzip -d -q $downloadedfile
+            check_retcode
+          ;;
+        esac
+        ;;
+      war)
+        cp $downloadedfile .
+        check_retcode
+        ;;
+    esac
+}
+
+predeploy
+
+# Updates predeploydir if a directory prefix exists
+if [[ x$predeploy_dirprefix != "x" ]] ; then
+   save_runtime_config "predeploydir=$predeploydir/$predeploy_dirprefix"
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/predeploy_tar.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+#!/bin/bash
+# predeploy_tar.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script unpacks (tar) file from the download dir (storedir) to the predeploydir"
+    echo "It has the following options:"
+    echo "\$1 (Required) - Name of the variable that identifies the tar to predeploy"
+    echo 
+    echo "Examples:"
+    echo "predeploy_tar.sh tarfile"
+}
+
+# Check Arguments
+if [ $1 ] ; then
+    deployfilevar=$1
+    deployfile="$(eval "echo \${$(echo ${deployfilevar})}")"
+else
+    showhelp
+    exit 2 
+fi
+
+# Untar  file
+untar () {
+    cd $predeploydir
+#    file $deployfile | grep gzip 2>&1>/dev/null
+#    if [ $? == "0"] ; then
+        tar -zxf $deployfile
+#    else
+#        tar -xvf $deployfile
+#    fi
+}
+
+untar
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/report_mail.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+#!/bin/bash
+# report_mail.sh - Made for Puppi
+# This script sends a summary mail to the recipients defined in $1
+# Use a comma separated list for multiple emails
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Check arguments & eventually apply runtimeconfig overwrite
+recipients=$1
+[ $report_email ] && recipients=$report_email
+
+# Main functions
+mail_send () {
+    result=$(grep result $logdir/$project/$tag/summary | awk '{ print $NF }')
+    cat $logdir/$project/$tag/summary | mail -s "[puppi] $result $action of $project on $(hostname)" $recipients
+}
+
+mail_send
+
+if [ "$EXITCRIT" = "1" ] ; then
+    exit 2
+fi
+
+if [ "$EXITWARN" = "1" ] ; then
+    exit 1
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/report_mongo.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,112 @@
+#!/bin/bash
+
+# report_mongodb.sh - Made for Puppi
+# e.g. somemongohost/dbname
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+
+# Show help
+showhelp () {
+    echo "This script reports deployments to a mongo DB."
+    echo "It has the following options:"
+    echo "-e <env_key> - Facter key to identify server environment (default: env)."
+    echo "If no facter key can be found, the fallback is ''environment''."
+    echo 
+    echo "Examples:"
+    echo "deploy_files.sh mongodb://someuser:hispassword@somehost/somedb"
+    echo "deploy_files.sh -e env mongodb://someuser:hispassword@somehost/somedb"
+}
+
+
+env_key="env"
+fallback_key="environment"
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -e)
+      env_key=$2
+      echo "env_key"
+      shift 2 ;;
+    *)
+      mongourl=$1
+      shift 1
+      ;;
+  esac
+done
+
+if [ "$EXITCRIT" = "1" ] ; then
+    proposed_exit=2
+fi
+
+if [ "$EXITWARN" = "1" ] ; then
+    proposed_exit=1
+fi
+
+# check prerequisites
+mongo -version > /dev/null
+if [ $? -ne 0 ]; then
+        echo "mongo-client is not installed, aborting"
+        exit $proposed_exit
+fi
+
+fqdn=$(facter fqdn)
+
+environment=$(facter ${env_key} -p)
+
+if [ -z "${environment} ]
+then
+    environment=$(facter ${fallback_key} -p)
+fi
+
+
+# something like mongodb://someuser:hispassword@somehost/somedb
+
+
+if [[ ! $mongourl =~ "mongodb://" ]]; then
+  echo "WARNING: mongourl invalid! Please use a valid monurl!"
+  showhelp
+  exit $proposed_exit
+fi
+
+if [[ $mongourl =~ @ ]]; then
+  # ok we have to deal with passwords
+  # you HAVE to provide a password if you provide a user
+  mongodb=`echo $mongourl | sed 's/.*@//'`
+  mongouser=`echo $mongourl | sed 's/mongodb:\/\///' | sed 's/:.*//' `
+  mongopassword=`echo $mongourl | sed 's/mongodb:\/\///' | sed 's/[^:]*://' | sed 's/@.*//' `
+  mongoarguments="--username $mongouser --password $mongopassword"
+else
+  mongodb=`echo $mongourl | sed 's/mongodb:\/\///'` 	
+fi
+
+result=$(grep result $logdir/$project/$tag/summary | awk '{ print $NF }')
+summary=$(cat $logdir/$project/$tag/summary)
+
+mcmd="db.deployments.insert({ts:new Date(),result:\"${result}\",fqdn:\"${fqdn}\",project:\"${project}\",source:\"${source}\",tag:\"${tag}\",version:\"${version}\",artifact:\"${artifact}\",testmode:\"${testmode}\",warfile:\"${warfile}\",environment:\"${environment}\"}); quit(0)"
+
+
+mongo $mongoarguments $mongodb --eval "$mcmd"
+
+# Now do a reporting to enable "most-recent-versions on all servers"
+
+read -r -d '' mcmd <<'EOF'
+var map = function() {
+  project=this.project ;
+  emit( this.fqdn +":"+ this.project,  {project:this.project, fqdn:this.fqdn, ts:this.ts,version:this.version,environment:this.environment}  );
+};
+var reduce = function(k,vals) {
+  result = vals[0];
+  vals.forEach(function(val) { if (val.ts > result.ts) result=val } ) ;
+  return result;
+};
+db.deployments.mapReduce(
+  map,
+  reduce,
+  {out:{replace:"versions"}})
+EOF
+
+mongo $mongoarguments $mongodb --eval "$mcmd"
+
+exit $proposed_exit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/service.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+#!/bin/bash
+# service.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script is used to manage one or more services"
+    echo "It requires AT LEAST 2 arguments:"
+    echo "First argument (\$1 - required) is the script command (stop|start|restart|reload)"
+    echo "Second argument and following (\$2 - required) is the space separated list of sevices to manage"
+    echo
+    echo "Examples:"
+    echo "service.sh stop monit puppet"
+}
+
+# Check arguments
+if [ $1 ] ; then
+    servicecommand=$1
+else
+    showhelp
+    exit 2
+fi
+
+
+if [ $# -ge 2 ] ; then
+    shift
+    services=$@
+else
+    showhelp
+    exit 2
+fi
+
+# Manage service
+service () {
+    for serv in $services ; do
+        /etc/init.d/$serv $servicecommand
+    done
+}
+
+service
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/svn.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,215 @@
+#!/bin/bash
+# svn.sh - Made for Puppi
+
+# All variables are exported
+set -a 
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script performs the svn operations required by puppi::project::svn"
+    echo "It integrates and uses variables provided by other core Puppi scripts"
+    echo "It has the following options:"
+    echo "-a <action> (Optional) What action to perform. Available options: deploy (default), rollback"
+    echo "-s <source> (Required) Subversion source repo to use"
+    echo "-d <destination> (Required) Directory where files are deployed"
+    echo "-u <user> (Optional) User that performs the deploy operations. Default root"
+    echo "-su <user> (Optional) Username for access to private svn repo"
+    echo "-sp <password> (Optional) Password for access to private svn repo"
+    echo "-gs <svn_subdir> (Optional) If only a specific subdir of the svnrepo has to be copied to the install destination"
+    echo "-t <tag> (Optional) Tag to deploy"
+    echo "-b <branch> (Optional) Branch to deploy"
+    echo "-c <commit> (Optional) Commit to deploy"
+    echo "-v <true|false> (Optional) If verbose"
+    echo "-k <true|false> (Optional) If .svn dir is kept on deploy_root"
+    echo "-e <true|false> (Optional) If use export instead of checkout for svn operations"
+    echo 
+    echo "Examples:"
+    echo "svn.sh -a deploy -s $source -d $deploy_root -u $user -gs $svn_subdir -t $tag -b $branch -c $commit -v $bool_verbose -k $bool_keep_svndata"
+}
+
+verbose="true"
+
+# Check Arguments
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -a)
+      case $2 in
+          rollback)
+          action="rollback"
+          ;;
+          *)
+          action="install"
+          ;;
+      esac 
+      shift 2 ;;
+    -s)
+      if [ $source ] ; then
+        source=$source
+      else
+        source=$2
+      fi
+      shift 2 ;;
+    -d)
+      if [ $deploy_root ] ; then
+        deploy_root=$deploy_root
+      else
+        deploy_root=$2
+      fi
+      shift 2 ;;
+    -u)
+      if [ $user ] ; then
+        deploy_user=$user
+      else
+        deploy_user=$2
+      fi
+      shift 2 ;;
+    -gs)
+      if [ $svn_subdir ] ; then
+        svn_subdir=$svn_subdir
+      else
+        svn_subdir=$2
+      fi
+      shift 2 ;;
+    -su)
+      if [ $svn_user ] ; then
+        svn_user=$svn_user
+      else
+        svn_user=$2
+      fi
+      shift 2 ;;
+    -sp)
+      if [ $svn_password ] ; then
+        svn_password=$svn_password
+      else
+        svn_password=$2
+      fi
+      shift 2 ;;
+    -t)
+      if [ $svn_tag ] ; then
+        svn_tag=$svn_tag
+      else
+        svn_tag=$2
+      fi
+      shift 2 ;;
+    -b)
+      if [ $branch ] ; then
+        branch=$branch
+      else
+        branch=$2
+      fi
+      shift 2 ;;
+    -c)
+      if [ $commit ] ; then
+        commit=$commit
+      else
+        commit=$2
+      fi
+      shift 2 ;;
+    -v)
+      if [ $verbose ] ; then
+        verbose=$verbose
+      else
+        verbose=$2
+      fi
+      shift 2 ;;
+    -k)
+      if [ $keep_svndata ] ; then
+        keep_svndata=$keep_svndata
+      else
+        keep_svndata=$2
+      fi
+      shift 2 ;;
+    -e)
+      if [ $svn_export ] ; then
+        svn_export=$svn_export
+      else
+        svn_export=$2
+      fi
+      shift 2 ;;
+    *)
+      showhelp
+      exit ;;
+  esac
+done
+
+if [ "x$verbose" == "xtrue" ] ; then
+  verbosity=""
+else
+  verbosity="--quiet"
+fi
+
+cd /
+
+if [ "x$branch" == "xundefined" ] ; then
+  branch="trunk"
+fi
+
+real_source="$source/$branch"
+
+if [ "x$svn_tag" != "xundefined" ] ; then
+  real_source="$source/$svn_tag"
+fi
+
+if [ "x$svn_user" != "xundefined" ] && [ "x$svn_password" != "xundefined" ] ; then
+  svn_auth="--username=$svn_user --password=$svn_password"
+else
+  svn_auth=""
+fi
+
+svnsubdir=""
+svndir=$deploy_root
+
+
+do_install () {
+  if [ "x$keep_svndata" != "xtrue" ] ; then
+    if [ ! -d $archivedir/$project-svn ] ; then
+      mkdir $archivedir/$project-svn
+      chown -R $user:$user $archivedir/$project-svn
+    fi
+    svndir=$archivedir/$project-svn/svnrepo
+  fi
+  if [ "x$svn_subdir" != "xundefined" ] ; then
+    if [ ! -d $archivedir/$project-svn ] ; then
+      mkdir $archivedir/$project-svn
+      chown -R $user:$user $archivedir/$project-svn
+    fi
+    svndir=$archivedir/$project-svn
+    svnsubdir="$svn_subdir/"
+  fi
+
+  if [ -d $svndir/.svn ] ; then
+    cd $svndir
+    svn up $verbosity $svn_auth --non-interactive
+  else
+    svn co $verbosity $real_source $svndir $svn_auth --non-interactive
+    cd $svndir
+  fi
+
+  if [ "x$svndir" == "x$archivedir/$project-svn/svnrepo" ] ; then
+    rsync -a --exclude=".svn" $svndir/$svnsubdir $deploy_root/
+  fi
+}
+
+do_export () {
+  svn export $verbosity $svn_auth --force --non-interactive $real_source/$svn_subdir $deploy_root
+}
+
+do_rollback () {
+  echo "Rollback not yet supported"
+}
+
+# Action!
+case "$action" in
+    install) 
+      if [ "x$svn_export" == "xtrue" ] ; then
+        export -f do_export ; su $user -c do_export
+      else
+        export -f do_install ; su $user -c do_install
+      fi
+      ;;
+    rollback) do_rollback ;;
+esac
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/wait.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,54 @@
+#!/bin/bash
+# wait.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script is used to introduce pauses during the deploy workflow"
+    echo
+    echo "It has the following options:"
+    echo "-s <seconds> - The number of seconds to wait"
+    echo "-p <filename> - Wait until filename is present"
+    echo "-a <filename> - Wait until filename is absent"
+    echo "-f <pattern> <filename> - Wait until is found the pattern in the filename"
+}
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -s)
+      sleep $2
+      exit 0
+      ;;
+    -p)
+      while true
+         do
+            [ -e $2 ] && break
+         sleep 1
+      done
+      exit 0
+      ;;
+    -a)
+      while true
+         do
+            [ ! -e $2 ] && break
+         sleep 1
+      done
+      exit 0
+      ;;
+    -f)
+      while true
+         do
+            grep $2 $3 && break
+         sleep 1
+      done
+      exit 0
+      ;;
+    *)
+      showhelp
+      exit
+      ;;
+  esac
+done
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/yant.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,38 @@
+#!/bin/bash
+# yant.sh - Made for Puppi
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script is used to call ant in a hybris-system"
+    echo "It requires AT LEAST 2 arguments:"
+    echo "First the \${hybris_parent_dir} where it can find a hybris-directory"
+    echo "Second argument: Everything you want to pass through to ant"
+    echo "The script assumes that hybris is located in \${hybris_parent_dir}/hybris"
+    echo
+    echo "Examples:"
+    echo "yant.sh /home/hybris clean all"
+}
+
+# Unfortunately, showhelp will never be called
+
+cd $1/hybris/bin/platform
+. ./setantenv.sh
+
+# somehow dirty ...
+shift
+
+if [ -d /opt/hybris/config ]; then
+	template=""
+else
+	template=-Dinput.template=develop 
+fi
+
+if [ $debug ] ; then
+    ant -Dinput.template=develop $* 
+else
+    ant $* > /dev/null
+fi
+
+handle_result
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/files/scripts/yum.sh	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,93 @@
+#!/bin/bash
+# yum.sh - Made for Puppi
+
+# Sources common header for Puppi scripts
+. $(dirname $0)/header || exit 10
+
+# Show help
+showhelp () {
+    echo "This script performs the yum operations required by puppi::project::yum"
+    echo "It integrates and uses variables provided by other core Puppi scripts"
+    echo "It has the following options:"
+    echo "-a <action> (Optional) What action to perform. Available options: deploy (default), rollback, remove"
+    echo "-n <rpm_name> (Required) Name of the package to handle"
+    echo "-v <rpm_version> (Optional) The version of the rpm to manage. Default: latest"
+    echo "-r <install_root> (Optional) The Instll root path. Default: /"
+    echo 
+    echo "Examples:"
+    echo "yum.sh -a deploy -n ${rpm} -r ${install_root} -v ${rpm_version}"
+}
+
+rpm_version="latest"
+install_root="/"
+
+# Check Arguments
+while [ $# -gt 0 ]; do
+  case "$1" in
+    -a)
+      case $2 in
+          rollback)
+          action="rollback"
+          ;;
+          remove)
+          action="remove"
+          ;;
+          *)
+          action="install"
+          ;;
+      esac 
+      shift 2 ;;
+    -n)
+      rpm_name=$2
+      shift 2 ;;
+    -v)
+      rpm_version=$2
+      shift 2 ;;
+    -r)
+      install_root=$2
+      shift 2 ;;
+    *)
+      showhelp
+      exit ;;
+  esac
+done
+
+
+do_install () {
+    if [ x$rpm_version == "xlatest" ] ; then
+        full_rpm_name=$rpm_name
+    else
+        full_rpm_name=$rpm_name-$rpm_version
+    fi
+
+    # Archives version of the rpm to update
+    oldversion=$(rpm -q $rpm_name --qf  "%{VERSION}-%{RELEASE}\n")
+    if [ "$?" = "0" ]; then
+        mkdir -p $archivedir/$project/$oldversion
+        if [ $archivedir/$project/latest ] ; then
+            rm -f $archivedir/$project/latest
+        fi
+        ln -sf $archivedir/$project/$oldversion $archivedir/$project/latest
+    fi
+
+    if [ x$install_root != "x/" ] ; then
+        yum install -y -q --installroot=$install_root $full_rpm_name
+    else
+        yum install -y -q $full_rpm_name
+    fi
+}
+
+do_rollback () {
+    yum downgrade -y -q $rpm_name-$rollbackversion
+}
+
+do_remove () {
+    yum remove -y -q $rpm_name
+}
+
+# Action!
+case "$action" in
+    install) do_install ;;
+    rollback) do_rollback ;;
+    remove) do_remove ;;
+esac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/facter/last_run.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+require 'facter'
+Facter.add("last_run") do
+  confine :kernel => [ 'Linux' , 'SunOS' , 'FreeBSD' , 'Darwin' ]
+  setcode do
+    Facter::Util::Resolution.exec("date '+%a %b %d %T:%N %Z %Y'")
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/facter/puppi_projects.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+require 'facter'
+Facter.add("puppi_projects") do
+  confine :kernel => [ 'Linux' , 'SunOS' , 'FreeBSD' , 'Darwin' ]
+  setcode do
+    Facter::Util::Resolution.exec('ls `grep projectsdir  /etc/puppi/puppi.conf | sed \'s/projectsdir="\([^"]*\)"/\1/\'` | tr \'\n\' \',\' | sed \'s/,$//\'') if File.exists?("/etc/puppi/puppi.conf")
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/facter/windows_common_appdata.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+require 'facter'
+Facter.add(:windows_common_appdata) do
+  confine :operatingsystem => :windows
+  if Facter.value(:osfamily) == "windows"
+    require 'win32/dir'
+  end
+  setcode do
+    Dir::COMMON_APPDATA
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/puppet/functions/params_lookup.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,80 @@
+#
+# params_lookup.rb
+#
+# Puppet 4 implementation
+#
+# This function lookups for a variable value in various locations
+# following this order (first match is returned)
+# - Hiera backend (if present) for modulename_varname
+# - Hiera backend (if present) for varname (if second argument is 'global')
+# - Top Scope Variable ::modulename_varname
+# - Top Scope Variable ::varname (if second argument is 'global')
+# - Module default: ::modulename::params::varname
+#
+# Alessandro Franceschi al@lab42.it
+#
+Puppet::Functions.create_function(:params_lookup, Puppet::Functions::InternalFunction) do
+  dispatch :single do
+    scope_param()
+    param          'String', :varname
+    optional_param 'String', :lookup_type
+#    arg_count 1, 3
+  end
+
+  def single(scope, varname, lookup_type='')
+    value = ''
+    modulename = scope["module_name"]
+
+    # OK - Hiera Lookup modulename_varname
+    value = call_function('hiera', "#{modulename}_#{varname}" , '')
+    return value if (value != '')
+
+    # OK - Hiera Lookup varname (global)
+    value = call_function('hiera', "#{varname}", '') if lookup_type == 'global'
+    return value if (not value.nil?) && (value != :undefined) && (value != '')
+
+    # OK - Top Scope Variable Lookup (::modulename_varname)
+    catch (:undefined_variable) do
+      begin
+        value = scope["::#{modulename}_#{varname}"]
+      rescue Puppet::ParseError => e
+        raise unless e.to_s =~ /.Could not look./
+      end
+    end
+    return value if (not value.nil?) && (value != :undefined) && (value != '')
+
+    # OK - Top Scope Variable Lookup ::varname (global)
+    if lookup_type == 'global'
+      catch (:undefined_variable) do
+        begin
+          value = scope["::#{varname}"]
+        rescue Puppet::ParseError => e
+          raise unless e.to_s =~ /.Could not look./
+        end
+      end
+      return value if (not value.nil?) && (value != :undefined) && (value != '')
+    end
+
+    # TODO: Set the correct classname when params_lookup used in subclasses
+    classname = modulename
+    # classname = scope.self.resource.name.downcase 
+
+    loaded_classes = closure_scope.catalog.classes
+
+    # TOTEST - legacy params lookup (self::params)
+    if loaded_classes.include?("#{classname}::params")
+      value = closure_scope["::#{classname}::params::#{varname}"]
+      return value if (not value.nil?)
+      # return value if (not value.nil?) && (value != :undefined) && (value != '')
+    end
+
+    # OK - default params lookup
+    if loaded_classes.include?("#{modulename}::params")
+      value = closure_scope["::#{modulename}::params::#{varname}"]
+      return value if (not value.nil?)
+      # return value if (not value.nil?) && (value != :undefined) && (value != '')
+    end
+
+    return ''
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/puppet/parser/functions/any2bool.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,44 @@
+#
+# any2bool.rb
+#
+# This define is heavily based on PuppetLabs' stdlib str2bool
+#
+module Puppet::Parser::Functions
+  newfunction(:any2bool, :type => :rvalue, :doc => <<-EOS
+This converts any input to a boolean. This attempt to convert strings that 
+contain things like: y, 1, t, true to 'true' and strings that contain things
+like: 0, f, n, false, no to 'false'.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "any2bool(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    string = arguments[0]
+
+#    unless string.is_a?(String)
+#      raise(Puppet::ParseError, 'str2bool(): Requires either ' +
+#        'string to work with')
+#    end
+
+    # We consider all the yes, no, y, n and so on too ...
+    result = case string
+      #
+      # This is how undef looks like in Puppet ...
+      # We yield false in this case.
+      #
+      when false then false
+      when true then true
+      when /^$/, '' then false # Empty string will be false ...
+      when /^(1|t|y|true|yes)$/  then true
+      when /^(0|f|n|false|no)$/  then false
+      when /^(undef|undefined)$/ then false # This is not likely to happen ...
+      else
+        raise(Puppet::ParseError, 'any2bool(): Unknown type of boolean given')
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/puppet/parser/functions/bool2ensure.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+#
+# bool2ensure.rb
+#
+# This define return present/absent accroding to the boolean value passed
+#
+module Puppet::Parser::Functions
+  newfunction(:bool2ensure, :type => :rvalue, :doc => <<-EOS
+This converts any input similar to a boolean to the stringpresent or absent
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "bool2ensure(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    string = arguments[0]
+
+    result = case string
+      when false then "absent"
+      when true then "present"
+      when /^$/, '' then "present" 
+      when /^(1|t|y|true|yes)$/  then "present"
+      when /^(0|f|n|false|no)$/  then "absent"
+      when /^(undef|undefined)$/ then "present"
+      else
+        raise(Puppet::ParseError, 'bool2ensure(): Unknown type of boolean given')
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/puppet/parser/functions/get_class_args.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+# This function is based on Ken Barber's get_scope_args
+# It has been slightly changed and renamed to avoid naming clash
+
+module Puppet::Parser::Functions
+  newfunction(:get_class_args, :type => :rvalue, :doc => <<-EOS
+This function will return all arguments passed to the current scope. This could
+be a class or defined resource.
+    EOS
+  ) do |arguments|
+ 
+    if (arguments.size != 0) then
+      raise(Puppet::ParseError, "validate_resource(): Wrong number of arguments "+
+        "given #{arguments.size} for 0")
+    end
+
+    # Grab the current scope, turn it to a hash but do not be recursive 
+    # about it.
+    classhash = to_hash(recursive=false)
+
+    # Strip bits that do not matter for validation
+#    classhash.delete("name")
+#    classhash.delete("title")
+#    classhash.delete("caller_module_name")
+#    classhash.delete("module_name")
+
+    # Return munged classhash
+    classhash
+  end
+end
+
+# vim: set ts=2 sw=2 et :
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/puppet/parser/functions/get_magicvar.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+#
+# get_magicvar.rb
+#
+# This define return the value of the the provided var name
+#
+module Puppet::Parser::Functions
+  newfunction(:get_magicvar, :type => :rvalue, :doc => <<-EOS
+This returns the value of the input variable. For example if you input role
+it returns the value of $role'.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "get_magicvar(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    my_var = arguments[0]
+    result = lookupvar("#{my_var}")
+    result = 'all' if ( result == :undefined || result == '' )
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/puppet/parser/functions/get_module_path.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+module Puppet::Parser::Functions
+  newfunction(:get_module_path, :type =>:rvalue, :doc => <<-EOT
+    Returns the absolute path of the specified module for the current
+    environment.
+
+    Example:
+      $module_path = get_module_path('stdlib')
+  EOT
+  ) do |args|
+    raise(Puppet::ParseError, "get_module_path(): Wrong number of arguments, expects one") unless args.size == 1
+    if module_path = Puppet::Module.find(args[0], compiler.environment.to_s)
+      module_path.path
+    else
+      raise(Puppet::ParseError, "Could not find module #{args[0]} in environment #{compiler.environment}")
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/puppet/parser/functions/nslookup.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,44 @@
+#
+# nslookup.rb
+#
+# This fuction looks up the ip address of a hostname.
+#
+# Params:
+#  * Hostname: (string) The hostname to lookup
+#  * Type: (string) The DNS type to lookup. Optional. Default: 'AAAA'
+#
+# Returns: an array with the ip addresses that belong to this hostname
+#
+# Dolf Schimmel - Freeaqingme <dolf@dolfschimmel.nl>
+# 
+module Puppet::Parser::Functions
+  newfunction(:nslookup, :type => :rvalue, :doc => <<-EOS
+Lookup a hostname and return its ip addresses
+    EOS
+  ) do |vals|
+    hostname, type = vals
+    raise(ArgumentError, 'Must specify a hostname') unless hostname
+    type = 'AAAA' unless type
+    
+    require 'ipaddr'
+    
+    if (ip = IPAddr.new(hostname) rescue nil)
+      if (ip.ipv6? and type == 'AAAA') or (ip.ipv4? and type != 'AAAA')
+        return hostname
+      else
+        return []
+      end
+    end
+
+    typeConst = Resolv::DNS::Resource::IN.const_get "#{type.upcase}"
+    out = []
+    
+    Resolv::DNS.open do |dns|
+      dns.getresources(hostname, typeConst).collect {|r| 
+        out << IPAddr::new_ntoh(r.address.address).to_s
+      }
+    end
+
+    return out
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/puppet/parser/functions/options_lookup.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,56 @@
+#
+# options_lookup.rb
+#
+# This fuction takes two arguments (option, and default value) and looks for the given
+# option key in the calling modules options hash, and returns the value.
+# The function is intended to be used in templates.
+# If no option is found in the options hash, default value (second argument), is returned.
+#
+# Example usages:
+#
+# Default value of no
+#   <%= scope.function_options_lookup(['PasswordAuthentication', 'no']) %>
+# Empty default value
+#   <%= scope.function_options_lookup(['PasswordAuthentication', '']) %>
+# Fact or param based default value
+#   <%= scope.function_options_lookup(['Listen', ipaddress]) %>
+# Lookup inside a custom hash - in this case client_options
+#   <%= scope.function_options_lookup(['PasswordAuthentication', 'no', 'client_options']) %>
+#
+#
+# Michal Nowak <mailto:michal@casanowak.com>
+# 
+module Puppet::Parser::Functions
+  newfunction(:options_lookup, :type => :rvalue, :doc => <<-EOS
+This fuction takes two arguments (option, and default value) and looks for the given
+option key in the calling modules options hash, and returns the value.
+The function is intended to be used in templates.
+If no option is found in the options hash, default value (second argument), is returned.
+
+Default value of no
+  <%= scope.function_options_lookup(['PasswordAuthentication', 'no']) %>
+Empty default value
+  <%= scope.function_options_lookup(['PasswordAuthentication', '']) %>
+Fact or param based default value
+   <%= scope.function_options_lookup(['Listen', ipaddress]) %>
+Lookup inside a custom hash - in this case client_options
+   <%= scope.function_options_lookup(['PasswordAuthentication', 'no', 'client_options']) %>
+
+EOS
+  ) do |args|
+
+    raise ArgumentError, ("options_lookup(): wrong number of arguments (#{args.length}; must be 2 or 3)") if (args.length != 2 and args.length != 3)
+
+    value = ''
+    option_name = args[0]
+    default_val = args[1]
+    hash_name = args[2]
+    module_name = parent_module_name
+
+    hash_name = "options" if (hash_name == :undefined || hash_name == '' || hash_name == nil)
+    value = lookupvar("#{module_name}::#{hash_name}")["#{option_name}"] if (lookupvar("#{module_name}::#{hash_name}").size > 0)
+    value = "#{default_val}" if (value == :undefined || value == '' || value == nil)
+
+    return value
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/puppet/parser/functions/params_lookup.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,89 @@
+#
+# params_lookup.rb
+#
+# This function lookups for a variable value in various locations
+# following this order (first match is returned)
+# - Hiera backend (if present) for modulename_varname
+# - Hiera backend (if present) for varname (if second argument is 'global')
+# - Top Scope Variable ::modulename_varname
+# - Top Scope Variable ::varname (if second argument is 'global')
+# - Module default: ::modulename::params::varname
+#
+# It's based on a suggestion of Dan Bode on how to better manage
+# Example42 NextGen modules params lookups.
+# Major help has been given by  Brice Figureau, Peter Meier
+# and Ohad Levy during the Fosdem 2012 days (thanks guys)
+#
+# Tested and adapted to Puppet 2.6.x and later
+#
+# Alessandro Franceschi al@lab42.it
+#
+module Puppet::Parser::Functions
+  newfunction(:params_lookup, :type => :rvalue, :doc => <<-EOS
+This fuction looks for the given variable name in a set of different sources:
+- Hiera, if available ('modulename_varname')
+- Hiera, if available (if second argument is 'global')
+- ::modulename_varname
+- ::varname (if second argument is 'global')
+- ::modulename::params::varname
+If no value is found in the defined sources, it returns an empty string ('')
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "params_lookup(): Define at least the variable name " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = ''
+    var_name = arguments[0]
+    module_name = parent_module_name
+
+    # Hiera Lookup
+    if Puppet::Parser::Functions.function('hiera')
+      value = function_hiera(["#{module_name}_#{var_name}", ''])
+      return value if (not value.nil?) && (value != :undefined) && (value != '')
+
+      value = function_hiera(["#{var_name}", '']) if arguments[1] == 'global'
+      return value if (not value.nil?) && (value != :undefined) && (value != '')
+    end
+
+    # Top Scope Variable Lookup (::modulename_varname)
+    catch (:undefined_variable) do
+      begin
+        value = lookupvar("::#{module_name}_#{var_name}")
+      rescue Puppet::ParseError => e
+        raise unless e.to_s =~ /^Undefined variable /
+      end
+    end
+    return value if (not value.nil?) && (value != :undefined) && (value != '')
+
+    # Look up ::varname (only if second argument is 'global')
+    if arguments[1] == 'global'
+      catch (:undefined_variable) do
+        begin
+          value = lookupvar("::#{var_name}")
+        rescue Puppet::ParseError => e
+          raise unless e.to_s =~ /^Undefined variable /
+        end
+      end
+      return value if (not value.nil?) && (value != :undefined) && (value != '')
+    end
+
+    # needed for the next two lookups
+    classname = self.resource.name.downcase
+    loaded_classes = catalog.classes
+
+    # self::params class lookup for default value
+    if loaded_classes.include?("#{classname}::params")
+      value = lookupvar("::#{classname}::params::#{var_name}")
+      return value if (not value.nil?) && (value != :undefined) && (value != '')
+    end
+
+    # Params class lookup for default value
+    if loaded_classes.include?("#{module_name}::params")
+      value = lookupvar("::#{module_name}::params::#{var_name}")
+      return value if (not value.nil?) && (value != :undefined) && (value != '')
+    end
+
+    return ''
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/lib/puppet/parser/functions/url_parse.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,44 @@
+require 'uri'
+
+Puppet::Parser::Functions::newfunction(:url_parse, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+    Returns information about an url
+    
+    This function expects two arguments, an URL and the part of the url you want to retrieve. 
+
+    Example:
+    $source_filename = url_parse($source_url,path)
+
+    Given an url like: https://my_user:my_pass@www.example.com:8080/path/to/file.php?id=1&ret=0
+    You obtain the following results according to the second argument:
+    scheme   : https
+    userinfo : my_user:my_pass
+    user     : my_user
+    password : my_pass
+    host     : www.example.com
+    port     : 8080
+    path     : /path/to/file.php
+    query    : id=1&ret=0
+    filename : file.php
+    filetype : php
+    filedir  : file
+   
+ 
+  ENDHEREDOC
+  raise ArgumentError, ("url_parse(): wrong number of arguments (#{args.length}; must be 2)") if args.length != 2
+  url=URI.parse args[0]
+  case args[1]
+    when 'scheme' then url.scheme
+    when 'userinfo' then url.userinfo
+    when 'user' then url.user
+    when 'password' then url.password
+    when 'host' then url.host
+    when 'port' then url.port
+    when 'path' then url.path
+    when 'query' then url.query
+    when 'filename' then File.basename url.path
+    when 'filetype' then File.extname url.path
+    when 'filedir' then (File.basename url.path).chomp(File.extname(url.path))
+    else url
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/check.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,50 @@
+# Define puppi::check
+#
+# This define creates a file with a check command that can be used locally.
+# It uses Nagios plugins for all checks so that $command is just the
+# plugin name with its arguments
+#
+# == Usage
+# Basic Usage:
+# puppi::check { "checkname":
+#   command => "check_tcp -H localhost -p 80"
+# }
+#
+# :include:../README.check
+#
+define puppi::check (
+  $command,
+  $base_dir = '',
+  $hostwide = 'no',
+  $priority = '50',
+  $project  = 'default',
+  $enable   = true ) {
+
+  require puppi
+  require puppi::params
+
+  $ensure = bool2ensure($enable)
+  $bool_hostwide = any2bool($hostwide)
+
+  $real_base_dir = $base_dir ? {
+    ''      => $puppi::params::checkpluginsdir,
+    default => $base_dir,
+  }
+
+  $path = $bool_hostwide ? {
+    true  => "${puppi::params::checksdir}/${priority}-${name}" ,
+    false => "${puppi::params::projectsdir}/${project}/check/${priority}-${name}",
+  }
+
+  file { "Puppi_check_${project}_${priority}_${name}":
+    ensure  => $ensure,
+    path    => $path,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => Class['puppi'],
+    content => "${real_base_dir}/${command}\n",
+    tag     => 'puppi_check',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/configure.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,40 @@
+# Define puppi::deploy
+#
+# This define creates a file with a deploy command that can be used locally.
+#
+# == Usage:
+# puppi::configure { "Retrieve files":
+#   command  => "get_file.sh",
+#   argument => "/remote/dir/file",
+#   priority => "10",
+#   user   => "root",
+#   project  => "spysite",
+# }
+#
+# :include:../README.deploy
+#
+define puppi::configure (
+  $command,
+  $project,
+  $arguments = '',
+  $priority  = '50',
+  $user      = 'root',
+  $enable    = true ) {
+
+  require puppi
+  require puppi::params
+
+  $ensure = bool2ensure($enable)
+
+  file { "${puppi::params::projectsdir}/${project}/configure/${priority}-${name}":
+    ensure  => $ensure,
+    mode    => '0750',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => Class['puppi'],
+    content => "su - ${user} -c \"export project=${project} && ${puppi::params::scriptsdir}/${command} ${arguments}\"\n",
+    tag     => 'puppi_deploy',
+  }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/dependencies.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,38 @@
+# Class puppi::dependencies
+#
+# This class provides commands and tools needed for full Puppi
+# functionality. Since you might already have these package
+# resources in your modules, to avoid conflicts you may decide
+# to include the needed packages somewhere else and avoid the
+# direct inclusion of puppi::dependencies with the parameter:
+#   install_dependencies => false
+#
+class puppi::dependencies {
+
+  require puppi::params
+
+  if ! defined(Package['curl']) {
+    package { 'curl' : ensure => present }
+  }
+
+  if ! defined(Package['wget']) {
+    package { 'wget' : ensure => present }
+  }
+
+  if ! defined(Package['unzip']) {
+    package { 'unzip' : ensure => present }
+  }
+
+  if ! defined(Package['rsync']) {
+    package { 'rsync' : ensure => present }
+  }
+
+  if ! defined(Package[$puppi::params::package_nagiosplugins]) {
+    package { $puppi::params::package_nagiosplugins : ensure => present }
+  }
+
+  if ! defined(Package[$puppi::params::package_mail]) {
+    package { $puppi::params::package_mail : ensure => present }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/deploy.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,40 @@
+# Define puppi::deploy
+#
+# This define creates a file with a deploy command that can be used locally.
+#
+# == Usage:
+# puppi::deploy { "Retrieve files":
+#   command  => "get_file.sh",
+#   argument => "/remote/dir/file",
+#   priority => "10",
+#   user   => "root",
+#   project  => "spysite",
+# }
+#
+# :include:../README.deploy
+#
+define puppi::deploy (
+  $command,
+  $project,
+  $arguments = '',
+  $priority  = '50',
+  $user      = 'root',
+  $enable    = true ) {
+
+  require puppi
+  require puppi::params
+
+  $ensure = bool2ensure($enable)
+
+  file { "${puppi::params::projectsdir}/${project}/deploy/${priority}-${name}":
+    ensure  => $ensure,
+    mode    => '0750',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => Class['puppi'],
+    content => "su - ${user} -c \"export project=${project} && ${puppi::params::scriptsdir}/${command} ${arguments}\"\n",
+    tag     => 'puppi_deploy',
+  }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/extras.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,208 @@
+# Class puppi::extras
+#
+# Default extras class with predefined puppi
+# check, log , info content.
+# You can provide a custom extra class to use instead of this
+# with a parameter like:
+#   extra_class=> 'example42::puppi::extras',
+#
+class puppi::extras {
+
+  # Default Checks
+
+  puppi::check { 'NTP_Sync':
+    command  => "check_ntp -H ${puppi::params::ntp}" ,
+    priority => '99' ,
+    hostwide => 'yes' ,
+  }
+
+  puppi::check { 'Disks_Usage':
+    command  => 'check_disk -w 20% -c 10% -L -X tmpfs' ,
+    priority => '10' ,
+    hostwide => 'yes' ,
+  }
+
+  puppi::check { 'System_Load':
+    command  => 'check_load -w 15,10,5 -c 30,25,20' ,
+    priority => '10' ,
+    hostwide => 'yes' ,
+  }
+
+  puppi::check { 'Zombie_Processes':
+    command  => 'check_procs -w 5 -c 10 -s Z' ,
+    priority => '10' ,
+    hostwide => 'yes' ,
+  }
+
+  puppi::check { 'Local_Mail_Queue':
+    command  => 'check_mailq -w 2 -c 5' ,
+    priority => '10' ,
+    hostwide => 'yes' ,
+  }
+
+  puppi::check { 'Connected_Users':
+    command  => 'check_users -w 5 -c 10' ,
+    priority => '10' ,
+    hostwide => 'yes' ,
+  }
+
+  puppi::check { 'DNS_Resolution':
+    command  => 'check_dns -H example.com' ,
+    priority => '15' ,
+    hostwide => 'yes' ,
+  }
+
+
+  # Info Pages
+  $network_run = $::operatingsystem ? {
+    Solaris => [ 'ifconfig -a' , 'netstat -nr' , 'cat /etc/resolv.conf' , 'arp -an' , 'netstat -na' ],
+    default => [ 'ifconfig' , 'route -n' , 'cat /etc/resolv.conf' , 'arp -an' , 'netstat -natup | grep LISTEN' ],
+  }
+
+  puppi::info { 'network':
+    description => 'Network settings and stats' ,
+    run         => $network_run,
+  }
+
+  $users_run = $::operatingsystem ? {
+    Solaris => [ 'who' , 'last' ],
+    default => [ 'who' , 'last' , 'LANG=C lastlog | grep -v \'Never logged in\'' ],
+  }
+
+  puppi::info { 'users':
+    description => 'Users and logins information' ,
+    run         => $users_run,
+  }
+
+  $perf_run = $::operatingsystem ? {
+    Solaris => [ 'uptime' , 'vmstat 1 5' ],
+    default => [ 'uptime' , 'free' , 'vmstat 1 5' ],
+  }
+
+  puppi::info { 'perf':
+    description => 'System performances and resources utilization' ,
+    run         => $perf_run,
+  }
+
+  $disks_run = $::operatingsystem ? {
+    Solaris => [ 'df -h' , 'mount' ],
+    default => [ 'df -h' , 'mount' , 'blkid' , 'fdisk -l' ],
+  }
+
+  puppi::info { 'disks':
+    description => 'Disks and filesystem information' ,
+    run         => $disks_run,
+  }
+
+  $hardware_run = $::operatingsystem ? {
+    Solaris => [ 'find /devices/' ],
+    default => [ 'lspci' , 'cat /proc/cpuinfo' ],
+  }
+
+  puppi::info { 'hardware':
+    description => 'Hardware information' ,
+    run         => $hardware_run,
+  }
+
+  $packages_run = $::operatingsystem ? {
+    /(?i:RedHat|CentOS|Scientific|Amazon|Linux)/ => [ 'yum repolist' , 'rpm -qa' ] ,
+    /(?i:Debian|Ubuntu|Mint)/                    => [ 'apt-config dump' , 'apt-cache stats' , 'apt-key list' , 'dpkg -l' ],
+    /(Solaris)/                                  => [ 'pkginfo' ],
+    /(Archlinux)/                                => [ 'pacman -Qet' ],
+    default                                      => [ 'echo' ],
+  }
+
+  puppi::info { 'packages':
+    description => 'Packages information' ,
+    run         => $packages_run,
+  }
+
+  puppi::info::module { 'puppi':
+    configfile  => ["${puppi::params::basedir}/puppi.conf"],
+    configdir   => [$puppi::params::basedir],
+    datadir     => [$puppi::params::archivedir],
+    logdir      => [$puppi::params::logdir],
+    description => 'What Puppet knows about puppi' ,
+    verbose     => 'yes',
+#   run         => "ls -lR ${puppi::params::logdir}/puppi-data/",
+  }
+
+  ### Default Logs
+  case $::operatingsystem {
+
+    Debian,Ubuntu: {
+      puppi::log { 'system':
+        description => 'General System Messages',
+        log         => ['/var/log/syslog'],
+      }
+      puppi::log { 'auth':
+        description => 'Users and authentication',
+        log         => ['/var/log/user.log','/var/log/auth.log'],
+      }
+      puppi::log { 'mail':
+        description => 'Mail messages',
+        log         => ['/var/log/mail.log'],
+      }
+    }
+
+    RedHat,CentOS,Scientific,Amazon,Linux: {
+      puppi::log { 'system':
+        description => 'General System Messages',
+        log         => ['/var/log/messages'],
+      }
+      puppi::log { 'auth':
+        description => 'Users and authentication',
+        log         => ['/var/log/secure'],
+      }
+      puppi::log { 'mail':
+        description => 'Mail messages',
+        log         => ['/var/log/maillog'],
+      }
+    }
+
+    SLES,OpenSuSE: {
+      puppi::log { 'system':
+        description => 'General System Messages',
+        log         => ['/var/log/messages'],
+      }
+      puppi::log { 'mail':
+        description => 'Mail messages',
+        log         => ['/var/log/mail'],
+      }
+      puppi::log { 'zypper':
+        description => 'Zypper messages',
+        log         => ['/var/log/zypper.log'],
+      }
+    }
+
+    Solaris: {
+      puppi::log { 'system':
+        description => 'General System Messages',
+        log         => ['/var/adm/messages'],
+      }
+      puppi::log { 'auth':
+        description => 'Users and authentication',
+        log         => ['/var/log/authlog'],
+      }
+    }
+
+    Archlinux: {
+      puppi::log { 'system':
+        description => 'General System Messages',
+        log         => ['/var/log/messages.log','/var/log/syslog.log'],
+      }
+      puppi::log { 'auth':
+        description => 'Users and authentication',
+        log         => ['/var/log/user.log','/var/log/auth.log'],
+      }
+      puppi::log { 'mail':
+        description => 'Mail messages',
+        log         => ['/var/log/mail.log'],
+      }
+    }
+
+    default: { }
+
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/helper.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,29 @@
+# Define puppi::helper
+#
+# The Puppi 2.0 define that creates an helper file that contains
+# the commands to execute, for the different puppi actions, using
+# the variables present in the datafile
+#
+# == Usage
+# Basic Usage:
+# puppi::helper { "myhelper":
+#   template => 'myproject/puppi/helpers/myhelper.erb',
+# }
+#
+define puppi::helper (
+  $template,
+  $ensure = 'present' ) {
+
+  require puppi
+  require puppi::params
+
+  file { "puppi_helper_${name}":
+    ensure  => $ensure,
+    path    => "${puppi::params::helpersdir}/${name}.yml",
+    mode    => '0644',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    content => template($template),
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/helpers.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+# Class puppi::helpers
+#
+# A class that defines all the default helpers used by Example42
+#  modules
+#
+# == Usage
+# Automatically included by Puppi
+#
+class puppi::helpers {
+
+  # Standard helper for Example42 modules
+  puppi::helper { 'standard':
+    template => 'puppi/helpers/standard.yml.erb',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/info.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+# Define puppi::info
+#
+# This define creates a basic info file that simply contains a set
+# of commands that show infos about custom topics.
+# To be used by the puppi info command.
+# By default it builds the info script based on the minimal puppi/info.erb
+# template but you can choose a custom template.
+# Other info defines are used to gather and create puppi info scripts with
+# different arguments and contents.
+# Check puppi/manifests/info/ for alternative puppi::info::  plugins
+#
+# == Usage:
+# puppi::info { "network":
+#   description => "Network status and information" ,
+#   run  => [ "ifconfig" , "route -n" ],
+# }
+#
+# :include:../README.info
+#
+define puppi::info (
+  $description  = '',
+  $templatefile = 'puppi/info.erb',
+  $run          = '' ) {
+
+  require puppi
+  require puppi::params
+
+  $array_run = is_array($run) ? {
+    false     => $run ? {
+      ''      => [],
+      default => split($run, ','),
+    },
+    default   => $run,
+  }
+
+  file { "${puppi::params::infodir}/${name}":
+    ensure  => present,
+    mode    => '0750',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => Class['puppi'],
+    content => template($templatefile),
+    tag     => 'puppi_info',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/info/instance.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+# Define puppi::info::instance
+#
+# This is a puppi info plugin specific for the tomcat::instance define
+#
+define puppi::info::instance (
+  $servicename  = '',
+  $processname  = '',
+  $configdir    = '',
+  $bindir       = '',
+  $pidfile      = '',
+  $datadir      = '',
+  $logdir       = '',
+  $httpport     = '',
+  $controlport  = '',
+  $ajpport      = '',
+  $description  = '',
+  $run          = '',
+  $verbose      = 'no',
+  $templatefile = 'puppi/info/instance.erb' ) {
+
+  require puppi
+  require puppi::params
+
+  file { "${puppi::params::infodir}/${name}":
+    ensure  => present,
+    mode    => '0750',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    content => template($templatefile),
+    tag     => 'puppi_info',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/info/module.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,59 @@
+# Define puppi::info::module
+#
+# This is a puppi info plugin that provides automatic info to modules
+# It uses a default template puppi/info/module.erb that can be changed
+# and adapted
+#
+# == Usage
+# (Sample from Example42 apache module where there's wide use of
+# qualified variables, note that you can provide direct values to it
+# without using variables):
+#
+#  puppi::info::module { "apache":
+#    packagename => "${apache::params::packagename}",
+#    servicename => "${apache::params::servicename}",
+#    processname => "${apache::params::processname}",
+#    configfile  => "${apache::params::configfile}",
+#    configdir   => "${apache::params::configdir}",
+#    pidfile     => "${apache::params::pidfile}",
+#    datadir     => "${apache::params::datadir}",
+#    logfile     => "${apache::params::logfile}",
+#    logdir      => "${apache::params::logdir}",
+#    protocol    => "${apache::params::protocol}",
+#    port        => "${apache::params::port}",
+#    description => "What Puppet knows about apache" ,
+#    run         => "httpd -V",
+#  }
+#
+define puppi::info::module (
+  $packagename    = '',
+  $servicename    = '',
+  $processname    = '',
+  $configfile     = '',
+  $configdir      = '',
+  $initconfigfile = '',
+  $pidfile        = '',
+  $datadir        = '',
+  $logfile        = '',
+  $logdir         = '',
+  $protocol       = '',
+  $port           = '',
+  $description    = '',
+  $run            = '',
+  $verbose        = 'no',
+  $templatefile   = 'puppi/info/module.erb' ) {
+
+  require puppi
+  require puppi::params
+
+  file { "${puppi::params::infodir}/${name}":
+    ensure  => present,
+    mode    => '0750',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => Class['puppi'],
+    content => template($templatefile),
+    tag     => 'puppi_info',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/info/readme.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,69 @@
+# Define puppi::info::readme
+#
+# This is a puppi info plugin that provides a Readme text which can be
+# used to show local info on the managed server and eventually run custom commands.
+#
+#  puppi::info::readme { "myapp":
+#    description => "Guidelines for myapp setup",
+#    readme => "myapp/readme.txt" ,
+#    run     => "myapp -V",
+#  }
+#
+define puppi::info::readme (
+  $description       = '',
+  $readme            = '',
+  $autoreadme        = 'no',
+  $run               = '',
+  $source_module     = 'undefined',
+  $templatefile      = 'puppi/info/readme.erb' ) {
+
+  require puppi
+  require puppi::params
+
+  $bool_autoreadme = any2bool($autoreadme)
+
+  file { "${puppi::params::infodir}/${name}":
+    ensure  => present,
+    mode    => '0750',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => Class['puppi'],
+    content => template($templatefile),
+    tag     => 'puppi_info',
+  }
+
+  $readme_source = $readme ? {
+    ''      => 'puppet:///modules/puppi/info/readme/readme',
+    default => $readme,
+  }
+
+  file { "${puppi::params::readmedir}/${name}":
+    ensure  => present,
+    mode    => '0644',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_readmedir'],
+    source  => $readme_source,
+    tag     => 'puppi_info',
+  }
+
+  if $bool_autoreadme == true {
+  file { "${puppi::params::readmedir}/${name}-custom":
+    ensure  => present,
+    mode    => '0644',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_readmedir'],
+    source  => [
+      "puppet:///modules/${source_module}/puppi/info/readme/readme-${::hostname}" ,
+      "puppet:///modules/${source_module}/puppi/info/readme/readme-${::role}" ,
+      "puppet:///modules/${source_module}/puppi/info/readme/readme-default" ,
+      "puppet:///modules/puppi/info/readme/readme-${::hostname}" ,
+      "puppet:///modules/puppi/info/readme/readme-${::role}" ,
+      'puppet:///modules/puppi/info/readme/readme-default'
+    ],
+    tag     => 'puppi_info',
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,77 @@
+# = Class: puppi
+#
+# This is Puppi NextGen
+# Includes both first generation of Puppi and the
+# NextGen developments and modules integration
+#
+# == Parameters
+#
+# [*version*]
+#   Define the Puppi version to use:
+#   1 - First generation of Puppi, compatible with old modules
+#   2 - NextGen version. Intended to work with NextGen modules
+#   Default: 1 , for the moment
+#
+# [*install_dependencies*]
+#   Set to false if you want to manage the sofware puppi needs
+#   with your local modules.
+#
+# [*template*]
+#   Sets the path to a custom template for /etc/puppi/puppi.conf
+#
+# [*helpers_class*]
+#   Name of the class there default helpers are defined
+#   (Used on in Puppi 2)
+#
+# [*logs_retention_days*]
+#   Number of days for retenton of puppi logs. Default 30
+#   This option creates a script in /etc/cron.daily that purges
+#   all the old logs. Set to false or to 0 to remove the purge script.
+#
+# [*extra_class*]
+#   Name of the class where extra puppi resources are added
+#   Here, by default are placed general system commands for
+#   puppi info, check and log
+#
+class puppi (
+  $version              = params_lookup( 'version' ),
+  $install_dependencies = params_lookup( 'install_dependencies' ),
+  $template             = params_lookup( 'template' ),
+  $helpers_class        = params_lookup( 'helpers_class' ),
+  $logs_retention_days  = params_lookup( 'logs_retention_days' ),
+  $extra_class          = params_lookup( 'extra_class' )
+  ) inherits puppi::params {
+
+  $bool_install_dependencies=any2bool($install_dependencies)
+
+  # Manage Version
+  $puppi_ensure = $puppi::version ? {
+    '1' => '/usr/sbin/puppi.one',
+    '2' => '/usr/local/bin/puppi',
+  }
+
+  file { 'puppi.link':
+    ensure => $puppi_ensure,
+    path   => '/usr/sbin/puppi',
+  }
+
+  # Puppi version one is always installed
+  include puppi::one
+
+  # Puppi 2 gem (still experimental) is installed only when forced
+  if $puppi::version == '2' {
+    include puppi::two
+  }
+
+  # Create Puppi common dirs and scripts
+  include puppi::skel
+
+  # Include extra resources
+  include $puppi::extra_class
+
+  # Include some packages needed by Puppi
+  if $bool_install_dependencies {
+    include puppi::dependencies
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/initialize.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+# Define puppi::initialize
+#
+# This define creates a file with a initialize command that can be used locally.
+#
+# Usage:
+# puppi::initialize { "Retrieve files":
+#   command  => "get_file.sh",
+#   argument => "/remote/dir/file",
+#   priority => "10",
+#   user   => "root",
+#   project  => "spysite",
+# }
+#
+define puppi::initialize (
+  $command,
+  $project,
+  $arguments = '',
+  $priority  = '50',
+  $user      = 'root',
+  $enable    = true ) {
+
+  require puppi
+  require puppi::params
+
+  $ensure = bool2ensure($enable)
+
+  file { "${puppi::params::projectsdir}/${project}/initialize/${priority}-${name}":
+    ensure  => $ensure,
+    mode    => '0750',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => Class['puppi'],
+    content => "su - ${user} -c \"export project=${project} && ${puppi::params::scriptsdir}/${command} ${arguments}\"\n",
+    tag     => 'puppi_initialize',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/install_packages.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,83 @@
+# = Define: puppi::install_packages
+#
+# This define installs a list of packages without manging them as Puppet
+# resources. It's useful when you need a set of packages installed,
+# for example as prerequisites to build code from source, but you don't want
+# to create Puppet package resources for them (since they may conflict with
+# existing classes that provide the same packages.
+#
+# == Parameters:
+#
+# [*packages*]
+#   String. Required.
+#   A space separated list of of the packages to install
+#
+# [*template*]
+#   String. Optional. Default: 'puppi/install_packages.erb'
+#   The template to use to generate the script that installs the packages
+#
+# [*scrips_dir*]
+#   String. Optional. Default: '/root/puppi_install_packages'
+#    The directory where you place the scripts created by the define.
+#
+# [*autorun*]
+#   Boolean. Default: true.
+#   Define if to automatically execute the script when Puppet runs.
+#
+# [*refreshonly*]
+#   Boolean. Optional. Default: true
+#   Defines the logic of execution of the script when Puppet runs.
+#   Maps to the omonymous Exec type argument.
+#
+# [*timeout*]
+#   String. Optional. Default: '600'
+#   Exec timeout in seconds.
+#
+# [*ensure*]
+#   Define if the runscript script and eventual cron job
+#   must be present or absent. Default: present.
+#
+# == Examples
+#
+# - Minimal setup
+# puppi::install_packages { 'build_tools':
+#   source           => 'build-essential vim git-core curl bison',
+# }
+#
+define puppi::install_packages (
+  $packages,
+  $template         = 'puppi/install_packages.erb',
+  $scripts_dir      = '/root/puppi_install_packages',
+  $autorun          = true,
+  $refreshonly      = true,
+  $timeout          = '600',
+  $ensure           = 'present' ) {
+
+  if ! defined(File[$scripts_dir]) {
+    file { $scripts_dir:
+      ensure => directory,
+      mode   => '0755',
+      owner  => 'root',
+      group  => 'root',
+    }
+  }
+
+  file { "install_packages_${name}":
+    ensure  => $ensure,
+    path    => "${scripts_dir}/${name}",
+    mode    => '0755',
+    owner   => 'root',
+    group   => 'root',
+    content => template($template),
+  }
+
+  if $autorun == true {
+    exec { "install_packages_${name}":
+      command     => "${scripts_dir}/${name}",
+      refreshonly => $refreshonly,
+      subscribe   => File["install_packages_${name}"],
+      timeout     => $timeout,
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/log.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+# Define puppi::log
+#
+# This define creates a basic log file that simply contains
+# the list of logs to show when issuing the puppi log command.
+#
+# == Usage:
+# puppi::log { "system":
+#   description => "General System Logs" ,
+#   log  => [ "/var/log/syslog" , "/var/log/messages" ],
+# }
+#
+# :include:../README.log
+#
+define puppi::log (
+  $log,
+  $description = '' ) {
+
+  require puppi
+  require puppi::params
+
+  $array_log = is_array($log) ? {
+    false     => split($log, ','),
+    default   => $log,
+  }
+
+  file { "${puppi::params::logsdir}/${name}":
+    ensure  => 'present',
+    mode    => '0644',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => Class['puppi'],
+    content => template('puppi/log.erb'),
+    tag     => 'puppi_log',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/mcollective/client.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,60 @@
+# = Class puppi::mcollective::client
+#
+# This class installs the mc puppi command for mcollective clients
+# (Note that in mcollective terminology a client is an host from
+# where you can manage mcollective servers)
+#
+# The class installs also the puppideploy and puppicheck commands
+# that are simple wrappers about mco puppi that correctly trap
+# remote errors and can be used in automatic procedures or
+# to give limited access (typically via sudo) to mc puppi commands
+#
+# They can be integrated, for example, in Jenkins as remote ssh
+# commands to manage deployments or tests
+#
+# == Usage:
+# include puppi::mcollective::client
+#
+# :include:../README.mcollective
+#
+class puppi::mcollective::client {
+
+  require puppi::params
+  require puppi::mcollective::server
+
+# OLD STYLE mc-puppi command
+  file { '/usr/local/bin/mc-puppi':
+    ensure  => 'present',
+    mode    => '0755',
+    owner   => 'root',
+    group   => 'root',
+    source  => 'puppet:///modules/puppi/mcollective/mc-puppi',
+    require => Class['mcollective'],
+    }
+
+# mco application TODO
+#  file { "${puppi::params::mcollective}/application/puppi.rb":
+#    ensure  => 'present',
+#    mode    => '0644',
+#    owner   => 'root',
+#    group   => 'root',
+#    source  => 'puppet:///modules/puppi/mcollective/mcpuppi.rb',
+#  }
+
+  file { '/usr/bin/puppicheck':
+    ensure => 'present',
+    mode   => '0750',
+    owner  => $puppi::params::mcollective_user,
+    group  => $puppi::params::mcollective_group,
+    source => 'puppet:///modules/puppi/mcollective/puppicheck',
+  }
+
+  file { '/usr/bin/puppideploy':
+    ensure => 'present',
+    mode   => '0750',
+    owner  => $puppi::params::mcollective_user,
+    group  => $puppi::params::mcollective_group,
+    source => 'puppet:///modules/puppi/mcollective/puppideploy',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/mcollective/server.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+# = Class puppi::mcollective::server
+#
+# This class installs the puppi agent on mcollective servers
+# (Note that in mcollective terminology a server is an host
+# managed by a mcollective client)
+#
+# == Usage:
+# include puppi::mcollective::server
+#
+# :include:../README.mcollective
+#
+class puppi::mcollective::server {
+
+  require puppi::params
+
+  file { "${puppi::params::mcollective}/agent/puppi.ddl":
+    ensure  => 'present',
+    mode    => '0644',
+    owner   => 'root',
+    group   => 'root',
+    source  => 'puppet:///modules/puppi/mcollective/puppi.ddl',
+    require => Class['mcollective'],
+  }
+
+  file { "${puppi::params::mcollective}/agent/puppi.rb":
+    ensure  => 'present',
+    mode    => '0644',
+    owner   => 'root',
+    group   => 'root',
+    source  => 'puppet:///modules/puppi/mcollective/puppi.rb',
+    require => Class['mcollective'],
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/netinstall.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,169 @@
+# Define: puppi::netinstall
+#
+# This defines simplifies the installation of a file
+# downloaded from the web. It provides arguments to manage
+# different kind of downloads and custom commands.
+# It's used, among the others, by NextGen modules of webapps
+# when the argument install is set to => source
+#
+# == Variables
+#
+# [*url*]
+#   The Url of the file to retrieve. Required.
+#   Example: http://www.example42.com/file.tar.gz
+#
+# [*destination_dir*]
+#   The final destination where to unpack or copy what has been
+#   downloaded. Required.
+#   Example: /var/www/html
+#
+# [*retrieve_args*]
+#   A string of arguments to pass to wget.
+#
+# [*extracted_dir*]
+#   The name of a directory or file created after the extraction
+#   Needed only if its name is different from the downloaded file name
+#   (without suffixes). Optional.
+#
+# [*owner*]
+#   The user owner of the directory / file created. Default: root
+#
+# [*group*]
+#   The group owner of the directory / file created. Default: root
+#
+# [*timeout*]
+#   The timeout in seconds for each command executed
+#
+# [*work_dir*]
+#   A temporary work dir where file is downloaded. Default: /var/tmp
+#
+# [*path*]
+#  Define the path for the exec commands.
+#  Default: /bin:/sbin:/usr/bin:/usr/sbin
+#
+# [*exec_env*]
+#   Define any additional environment variables to be used with the
+#   exec commands. Note that if you use this to set PATH, it will
+#   override the path attribute. Multiple environment variables
+#   should be specified as an array.
+#
+# [*extract_command*]
+#   The command used to extract the downloaded file.
+#   By default is autocalculated accoring to the file extension
+#   Set 'rsync' if the file has to be placed in the destination_dir
+#   as is (for example for war files)
+#
+# [*preextract_command*]
+#   An optional custom command to run before extracting the file.
+#
+# [*postextract_command*]
+#   An optional custom command to run after having extracted the file.
+#
+define puppi::netinstall (
+  $url,
+  $destination_dir,
+  $extracted_dir       = '',
+  $retrieve_command    = 'wget',
+  $retrieve_args       = '',
+  $owner               = 'root',
+  $group               = 'root',
+  $timeout             = '3600',
+  $work_dir            = '/var/tmp',
+  $path                = '/bin:/sbin:/usr/bin:/usr/sbin',
+  $extract_command     = '',
+  $preextract_command  = '',
+  $postextract_command = '',
+  $postextract_cwd     = '',
+  $exec_env            = []
+  ) {
+
+  $source_filename = url_parse($url,'filename')
+  $source_filetype = url_parse($url,'filetype')
+  $source_dirname = url_parse($url,'filedir')
+
+  $real_extract_command = $extract_command ? {
+    ''      => $source_filetype ? {
+      '.tgz'     => 'tar -zxf',
+      '.gz'      => 'tar -zxf',
+      '.bz2'     => 'tar -jxf',
+      '.tar'     => 'tar -xf',
+      '.zip'     => 'unzip',
+      default    => 'tar -zxf',
+    },
+    default => $extract_command,
+  }
+
+  $extract_command_second_arg = $real_extract_command ? {
+    /^cp.*/    => '.',
+    /^rsync.*/ => '.',
+    default    => '',
+  }
+
+  $real_extracted_dir = $extracted_dir ? {
+    ''      => $real_extract_command ? {
+      /(^cp.*|^rsync.*)/         => $source_filename,
+      /(^tar -zxf*|^tar -jxf*)/  => regsubst($source_dirname,'.tar',''),
+      default                    => $source_dirname,
+    },
+    default => $extracted_dir,
+  }
+
+  $real_postextract_cwd = $postextract_cwd ? {
+    ''      => "${destination_dir}/${real_extracted_dir}",
+    default => $postextract_cwd,
+  }
+
+  if $preextract_command {
+    exec { "PreExtract ${source_filename} in ${destination_dir} - ${title}":
+      command     => $preextract_command,
+      subscribe   => Exec["Retrieve ${url} in ${work_dir} - ${title}"],
+      refreshonly => true,
+      path        => $path,
+      environment => $exec_env,
+      timeout     => $timeout,
+    }
+  }
+
+  exec { "Retrieve ${url} in ${work_dir} - ${title}":
+    cwd         => $work_dir,
+    command     => "${retrieve_command} ${retrieve_args} ${url}",
+    creates     => "${work_dir}/${source_filename}",
+    timeout     => $timeout,
+    path        => $path,
+    environment => $exec_env,
+  }
+
+  exec { "Extract ${source_filename} from ${work_dir} - ${title}":
+    command     => "mkdir -p ${destination_dir} && cd ${destination_dir} && ${real_extract_command} ${work_dir}/${source_filename} ${extract_command_second_arg}",
+    unless      => "ls ${destination_dir}/${real_extracted_dir}",
+    creates     => "${destination_dir}/${real_extracted_dir}",
+    timeout     => $timeout,
+    require     => Exec["Retrieve ${url} in ${work_dir} - ${title}"],
+    path        => $path,
+    environment => $exec_env,
+    notify      => Exec["Chown ${source_filename} in ${destination_dir} - ${title}"],
+  }
+
+  exec { "Chown ${source_filename} in ${destination_dir} - ${title}":
+    command     => "chown -R ${owner}:${group} ${destination_dir}/${real_extracted_dir}",
+    refreshonly => true,
+    timeout     => $timeout,
+    require     => Exec["Extract ${source_filename} from ${work_dir} - ${title}"],
+    path        => $path,
+    environment => $exec_env,
+  }
+
+  if $postextract_command {
+    exec { "PostExtract ${source_filename} in ${destination_dir} - ${title}":
+      command     => $postextract_command,
+      cwd         => $real_postextract_cwd,
+      subscribe   => Exec["Extract ${source_filename} from ${work_dir} - ${title}"],
+      refreshonly => true,
+      timeout     => $timeout,
+      require     => [Exec["Retrieve ${url} in ${work_dir} - ${title}"],Exec["Chown ${source_filename} in ${destination_dir} - ${title}"]],
+      path        => $path,
+      environment => $exec_env,
+    }
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/one.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+# Class: puppi::one
+#
+# Installs Puppi 1.0
+#
+class puppi::one {
+
+  require puppi::params
+
+  # Main configuration file
+  file { 'puppi.conf':
+    ensure  => present,
+    path    => "${puppi::params::basedir}/puppi.conf",
+    mode    => '0644',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    content => template($puppi::template),
+    require => File['puppi_basedir'],
+  }
+
+  # The Puppi 1.0 command
+  file { 'puppi':
+    ensure  => present,
+    path    => '/usr/sbin/puppi.one',
+    mode    => '0750',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    content => template('puppi/puppi.erb'),
+    require => File['puppi_basedir'],
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/params.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,106 @@
+# Class: puppi::params
+#
+# Sets internal variables and defaults for puppi module
+#
+class puppi::params  {
+
+## PARAMETERS
+  $version              = '1'
+  $install_dependencies = true
+  $template             = 'puppi/puppi.conf.erb'
+  $helpers_class        = 'puppi::helpers'
+  $logs_retention_days  = '30'
+  $extra_class          = 'puppi::extras'
+
+
+## INTERNALVARS
+  $basedir     = '/etc/puppi'
+  $scriptsdir  = '/etc/puppi/scripts'
+  $checksdir   = '/etc/puppi/checks'
+  $logsdir     = '/etc/puppi/logs'
+  $infodir     = '/etc/puppi/info'
+  $tododir     = '/etc/puppi/todo'
+  $projectsdir = '/etc/puppi/projects'
+  $datadir     = '/etc/puppi/data'
+  $helpersdir  = '/etc/puppi/helpers'
+  $libdir      = '/var/lib/puppi'
+  $readmedir   = '/var/lib/puppi/readme'
+  $logdir      = '/var/log/puppi'
+
+  $archivedir = $::puppi_archivedir ? {
+    ''      => '/var/lib/puppi/archive',
+    undef   => '/var/lib/puppi/archive',
+    default => $::puppi_archivedir,
+  }
+
+  $workdir = $::puppi_workdir ? {
+    ''      => '/tmp/puppi',
+    undef   => '/tmp/puppi',
+    default => $::puppi_workdir,
+  }
+
+  $configfile_mode  = '0644'
+  $configfile_owner = 'root'
+  $configfile_group = 'root'
+
+# External tools
+# Directory where are placed the checks scripts
+# By default we use Nagios plugins
+  $checkpluginsdir = $::operatingsystem ? {
+    /(?i:RedHat|CentOS|Scientific|Amazon|Linux)/ => $::architecture ? {
+      x86_64  => '/usr/lib64/nagios/plugins',
+      default => '/usr/lib/nagios/plugins',
+    },
+    default                    => '/usr/lib/nagios/plugins',
+  }
+
+  $package_nagiosplugins = $::operatingsystem ? {
+    /(?i:RedHat|CentOS|Scientific|Amazon|Linux|Fedora)/ => 'nagios-plugins-all',
+    default                       => 'nagios-plugins',
+  }
+
+  $package_mail = $::operatingsystem ? {
+    /(?i:Debian|Ubuntu|Mint)/ => 'bsd-mailx',
+    default           => 'mailx',
+  }
+
+  $ntp = $::ntp_server ? {
+    ''    => 'pool.ntp.org' ,
+    default => is_array($::ntp_server) ? {
+      false   => $::ntp_server,
+      true  => $::ntp_server[0],
+      default => $::ntp_server,
+    }
+  }
+
+# Mcollective paths
+# TODO: Add Paths for Puppet Enterprise:
+# /opt/puppet/libexec/mcollective/mcollective/
+  $mcollective = $::operatingsystem ? {
+    debian  => '/usr/share/mcollective/plugins/mcollective',
+    ubuntu  => '/usr/share/mcollective/plugins/mcollective',
+    centos  => '/usr/libexec/mcollective/mcollective',
+    redhat  => '/usr/libexec/mcollective/mcollective',
+    default => '/usr/libexec/mcollective/mcollective',
+  }
+
+  $mcollective_user = 'root'
+  $mcollective_group = 'root'
+
+
+# Commands used in puppi info templates
+  $info_package_query = $::operatingsystem ? {
+    /(?i:RedHat|CentOS|Scientific|Amazon|Linux)/ => 'rpm -qi',
+    /(?i:Ubuntu|Debian|Mint)/          => 'dpkg -s',
+    default                    => 'echo',
+  }
+  $info_package_list = $::operatingsystem ? {
+    /(?i:RedHat|CentOS|Scientific|Amazon|Linux)/ => 'rpm -ql',
+    /(?i:Ubuntu|Debian|Mint)/                    => 'dpkg -L',
+    default                                      => 'echo',
+  }
+  $info_service_check = $::operatingsystem ? {
+    default => '/etc/init.d/',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,100 @@
+# Define puppi::project
+#
+# This define creates and configures a Puppi project
+# You must use different puppi::deploy and puppi::rollback defines
+# to to build up the commands list
+#
+define puppi::project (
+  $enable = true ) {
+
+  require puppi::params
+
+  $ensure = any2bool($enable) ? {
+    false   => 'absent',
+    default => 'directory',
+  }
+
+  $ensurefile = bool2ensure($enable)
+
+  # Create Project subdirs
+  file {
+    "${puppi::params::projectsdir}/${name}":
+      ensure  => $ensure,
+      mode    => '0755',
+      owner   => $puppi::params::configfile_owner,
+      group   => $puppi::params::configfile_group,
+      force   => true;
+
+    "${puppi::params::projectsdir}/${name}/check":
+      ensure  => $ensure,
+      mode    => '0755',
+      owner   => $puppi::params::configfile_owner,
+      group   => $puppi::params::configfile_group,
+      force   => true,
+      recurse => true,
+      purge   => true,
+      require => File["${puppi::params::projectsdir}/${name}"];
+
+    "${puppi::params::projectsdir}/${name}/rollback":
+      ensure  => $ensure,
+      mode    => '0755',
+      owner   => $puppi::params::configfile_owner,
+      group   => $puppi::params::configfile_group,
+      force   => true,
+      recurse => true,
+      purge   => true,
+      require => File["${puppi::params::projectsdir}/${name}"];
+
+    "${puppi::params::projectsdir}/${name}/deploy":
+      ensure  => $ensure,
+      mode    => '0755',
+      owner   => $puppi::params::configfile_owner,
+      group   => $puppi::params::configfile_group,
+      force   => true,
+      recurse => true,
+      purge   => true,
+      require => File["${puppi::params::projectsdir}/${name}"];
+
+    "${puppi::params::projectsdir}/${name}/initialize":
+      ensure  => $ensure,
+      mode    => '0755',
+      owner   => $puppi::params::configfile_owner,
+      group   => $puppi::params::configfile_group,
+      force   => true,
+      recurse => true,
+      purge   => true,
+      require => File["${puppi::params::projectsdir}/${name}"];
+
+    "${puppi::params::projectsdir}/${name}/configure":
+      ensure  => $ensure,
+      mode    => '0755',
+      owner   => $puppi::params::configfile_owner,
+      group   => $puppi::params::configfile_group,
+      force   => true,
+      recurse => true,
+      purge   => true,
+      require => File["${puppi::params::projectsdir}/${name}"];
+
+    "${puppi::params::projectsdir}/${name}/report":
+      ensure  => $ensure,
+      mode    => '0755',
+      owner   => $puppi::params::configfile_owner,
+      group   => $puppi::params::configfile_group,
+      force   => true,
+      recurse => true,
+      purge   => true,
+      require => File["${puppi::params::projectsdir}/${name}"];
+  }
+
+  # Create Project configuration file
+  file {
+    "${puppi::params::projectsdir}/${name}/config":
+      ensure  => $ensurefile,
+      content => template('puppi/project/config.erb'),
+      mode    => '0644',
+      owner   => $puppi::params::configfile_owner,
+      group   => $puppi::params::configfile_group,
+      require => File["${puppi::params::projectsdir}/${name}"];
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/README	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+In this directory you find some examples of deploy procedures
+for general purposes deploys (single wars, single files, tarballs, list
+of files from a list...) described in a single define.
+
+They are made in order to be generic enough to adapt to different 
+environments and scenarious but you might need to design your
+own deployment process.
+
+In order to do that you can create a new define that includes:
+- All the variables, required or optional, you may want
+- One puppi:project statement 
+- All the puppi::deploy statements you need (each one runs a command)
+- All the puppi::rollback statements you need
+- One or more puppi::report statements for reporting
+
+The examples provided here make use of the scripts provided in
+puppi/files/scripts and tend to split the deploy procedures in many 
+different, reusable, scripts (one gets the source file(s), another 
+archives the current content, another one actually copies the files
+to deploy and so on) but you can use just a single new script or 
+whatever combination you might prefer.
+
+The default puppi scripts and the general ordering of commands
+execution in these sample deploy defines follow this scheme:
+Priority - Kind of operations
+1x - Pre Deploy checks 
+2x - Files retrieving and preparation
+3x - Operations to accomplish before the deploy (Archiving, Services stopping..)
+40 - Deploy.sh - The script that actually copied the files on deploy dir
+4x - Operations to accomplish after the deploy (Services start...)
+8x - Post Deploy checks
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/archive.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,406 @@
+# = Define puppi::project::archive
+#
+# This is a puppi deployment project to be used for archives
+# like tarballs and zips
+#
+#
+# It uses different "core" defines (puppi::project, puppi:deploy (many),
+# puppi::rollback (many)) to build a full featured template project for
+# automatic deployments.
+# If you need to customize it, either change the template defined here or
+# build up your own custom ones.
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the main file to retrieve.
+#   Format should be in URI standard (http:// file:// ssh:// rsync://).
+#
+# [*deploy_root*]
+#   The destination directory where the retrieved file(s) are deployed.
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*clean_deploy*]
+#   (Optional, default false) - If during the deploy procedure, all the
+#   existing files that are not on the source have to be deleted.
+#   (When true, a --delete option is added to the rsync command)
+#   Do not set to true if source files are incremental.
+#
+# [*backup_enable*]
+#   (Optional, default true) - If the backup of files in the deploy dir
+#   is done (before deploy). If set to false, rollback is disabled.
+#
+# [*backup_rsync_options*]
+#   (Optional) - The extra options to pass to rsync for backup operations. Use
+#   it, for example, to exclude directories that you don't want to archive.
+#   IE: "--exclude .snapshot --exclude cache --exclude www/cache".
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*always_deploy*]
+#   (Optional) - If you always deploy what has been downloaded. Default="yes",
+#   if set to "no" a checksum is made between the files previously downloaded
+#   and the new files. If they are the same the deploy is not done.
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::archive (
+  $source,
+  $deploy_root,
+  $user                     = 'root',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $clean_deploy             = false,
+  $backup_enable            = true,
+  $backup_rsync_options     = '--exclude .snapshot',
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $always_deploy            = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  $real_always_deploy = any2bool($always_deploy) ? {
+    false   => 'no',
+    true    => 'yes',
+  }
+
+
+  $bool_run_checks = any2bool($run_checks)
+  $bool_clean_deploy = any2bool($clean_deploy)
+  $bool_backup_enable = any2bool($backup_enable)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+  $source_type = url_parse($source,filetype)
+
+  $real_source_type = $source_type ? {
+    '.tar'     => 'tar',
+    '.tar.gz'  => 'tarball',
+    '.gz'      => 'tarball',
+    '.tgz'     => 'tarball',
+    '.zip'     => 'zip',
+  }
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here source file is retrieved
+    puppi::deploy { "${name}-Retrieve_Archive":
+      priority  => '20' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${source} -t ${real_source_type} -a ${real_always_deploy}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+    puppi::deploy { "${name}-PreDeploy_Archive":
+      priority => '25' ,
+      command  => 'predeploy.sh' ,
+      user     => 'root' ,
+      project  => $name ,
+      enable   => $enable ,
+    }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_backup_enable == true) {
+    puppi::deploy { "${name}-Backup_existing_Files":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${deploy_root} -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here is done the deploy on $deploy_root
+    puppi::deploy { "${name}-Deploy":
+      priority  => '40' ,
+      command   => 'deploy_files.sh' ,
+      arguments => "-d ${deploy_root} -c ${bool_clean_deploy}",
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($bool_backup_enable == true) {
+    if ($firewall_src_ip != '') {
+      puppi::rollback { "${name}-Load_Balancer_Block":
+        priority  => '25' ,
+        command   => 'firewall.sh' ,
+        arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($disable_services != '') {
+      puppi::rollback { "${name}-Disable_extra_services":
+        priority  => '37' ,
+        command   => 'service.sh' ,
+        arguments => "stop ${disable_services}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($predeploy_customcommand != '') {
+      puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+        priority  => $predeploy_priority ,
+        command   => 'execute.sh' ,
+        arguments => $predeploy_customcommand ,
+        user      => $predeploy_real_user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    puppi::rollback { "${name}-Recover_Files_To_Deploy":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${deploy_root} -o '${backup_rsync_options}'" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+    if ($postdeploy_customcommand != '') {
+      puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+        priority  => $postdeploy_priority ,
+        command   => 'execute.sh' ,
+        arguments => $postdeploy_customcommand ,
+        user      => $postdeploy_real_user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($disable_services != '') {
+      puppi::rollback { "${name}-Enable_extra_services":
+        priority  => '44' ,
+        command   => 'service.sh' ,
+        arguments => "start ${disable_services}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($firewall_src_ip != '') {
+      puppi::rollback { "${name}-Load_Balancer_Unblock":
+        priority  => '46' ,
+        command   => 'firewall.sh' ,
+        arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($bool_run_checks == true) {
+      puppi::rollback { "${name}-Run_POST-Checks":
+        priority  => '80' ,
+        command   => 'check_project.sh' ,
+        arguments => $name ,
+        user      => 'root' ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+  }
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/builder.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,561 @@
+# = Define puppi::project::builder
+#
+# This is a shortcut define to build a puppi project for the deploy of web
+# applications based on different sources: a war file, a tar file, a source dir,
+# a list of files or a nexus maven repository
+# It uses different "core" defines (puppi::project, puppi:deploy (many),
+# puppi::rollback (many)) to build a full featured template project for
+# automatic deployments.
+# If you need to customize it, either change the template defined here or
+# build up your own custom ones.
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the main file to retrieve.
+#   Format should be in URI standard (http:// file:// ssh:// rsync://).
+#
+# [*source_type*]
+#   The type of file that is retrieved. Accepted values: tarball, zip, list,
+#   war, dir, maven-metadata.
+#
+# [*deploy_root*]
+#   The destination directory where the retrieved file(s) are deployed.
+#
+# [*init_source*]
+#   (Optional) - The full URL to be used to retrieve, for the first time,
+#   the project files. They are copied directly to the $deploy_root
+#   Format should be in URI standard (http:// file:// ssh:// svn://).
+#
+# [*magicfix*]
+#   (Optional) - A string that is used as prefix or suffix according to the
+#   context and the scripts used in the deploy procedure.
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*backup*]
+#   (Optional) - How backups of files are made. Default: "full". Options:
+#   "full" - Make full backup of the deploy_root before making the deploy
+#   "diff" - Backup only the files that are going to be deployed. Note that
+#     in order to make reliable rollbacks of versions older that the latest
+#     you've to individually rollback every intermediate deploy
+#   "false" - Do not make backups. This disables the option to make rollbacks
+#
+# [*backup_rsync_options*]
+#   (Optional) - The extra options to pass to rsync for backup operations. Use
+#   it, for example, to exclude directories that you don't want to archive.
+#   IE: "--exclude .snapshot --exclude cache --exclude www/cache".
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*always_deploy*]
+#   (Optional) - If you always deploy what has been downloaded. Default="yes",
+#   if set to "no" a checksum is made between the files previously downloaded
+#   and the new files. If they are the same the deploy is not done.
+#
+# == Usage
+# A sample deploy of a zip with custom postdeploy command and mail notification
+# puppi::project::builder { "cms":
+#   source                   => "http://repo.example42.com/deploy/cms/cms.zip",
+#   source_type              => "zip",
+#   user                     => "root",
+#   deploy_root              => "/var/www",
+#   postdeploy_customcommand => "chown -R www-data /var/www/files",
+#   postdeploy_user          => "root",
+#   postdeploy_priority      => "41",
+#   report_email             => "sysadmins@example42.com",
+#   enable                   => "true",
+# }
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::builder (
+  $source,
+  $source_type,
+  $deploy_root,
+  $init_source              = '',
+  $user                     = 'root',
+  $magicfix                 = '',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $backup                   = 'full',
+  $backup_rsync_options     = '--exclude .snapshot',
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $always_deploy            = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Autoinclude the puppi class
+  include puppi
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  $real_source_type = $source_type ? {
+    'dir'            => 'dir',
+    'tarball'        => 'tarball',
+    'zip'            => 'zip',
+    'gz'             => 'gz',
+    'maven-metadata' => 'maven-metadata',
+    'maven'          => 'maven-metadata',
+    'war'            => 'war',
+    'list'           => 'list',
+  }
+
+  $real_always_deploy = any2bool($always_deploy) ? {
+    false   => 'no',
+    true    => 'yes',
+  }
+
+  $bool_run_checks = any2bool($run_checks)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+  $source_filename = url_parse($source,'filename')
+
+# Create Project
+  puppi::project { $name: enable => $enable }
+
+
+### INIT SEQUENCE
+  if ($init_source != '') {
+    puppi::initialize { "${name}-Deploy_Files":
+      priority  => '40' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${init_source} -d ${deploy_root}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  # Here source file is retrieved
+  puppi::deploy { "${name}-Retrieve_SourceFile":
+    priority  => '20' ,
+    command   => 'get_file.sh' ,
+    arguments => "-s ${source} -t ${real_source_type} -a ${real_always_deploy}" ,
+    user      => 'root' ,
+    project   => $name ,
+    enable    => $enable ,
+  }
+
+  $args_magicfix = $magicfix ? {
+    ''      => '',
+    default => "-m ${magicfix}" ,
+  }
+
+  if ($real_source_type == 'tarball') {
+    puppi::deploy { "${name}-PreDeploy_Tar":
+      priority  => '25' ,
+      command   => 'predeploy.sh' ,
+      arguments => $args_magicfix,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($real_source_type == 'zip') {
+
+    puppi::deploy { "${name}-PreDeploy_Zip":
+      priority  => '25' ,
+      command   => 'predeploy.sh' ,
+      arguments => $args_magicfix,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($real_source_type == 'list') {
+    puppi::deploy { "${name}-Extract_File_Metadata":
+      priority  => '22' ,
+      command   => 'get_metadata.sh' ,
+      arguments => $args_magicfix,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+    $clean_file_list_magicfix = $magicfix ? {
+      ''      => '',
+      default => $magicfix,
+    }
+
+    puppi::deploy { "${name}-Clean_File_List":
+      priority  => '24' ,
+      command   => 'clean_filelist.sh' ,
+      arguments => $clean_file_list_magicfix,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+    puppi::deploy { "${name}-Retrieve_Files":
+      priority  => '25' ,
+      command   => 'get_filesfromlist.sh' ,
+      arguments => $source ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($backup == 'full') or ($backup == 'diff') {
+    puppi::deploy { "${name}-Backup_existing_Files":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${deploy_root} -m ${backup} -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '34' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($real_source_type == 'war') {
+    puppi::deploy { "${name}-Remove_existing_WAR":
+      priority  => '35' ,
+      command   => 'delete.sh' ,
+      arguments => "${deploy_root}/${source_filename}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+    puppi::deploy { "${name}-Check_undeploy":
+      priority  => '36' ,
+      command   => 'checkwardir.sh' ,
+      arguments => "-a ${deploy_root}/${source_filename}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '37' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here is done the deploy on $deploy_root
+    puppi::deploy { "${name}-Deploy":
+      priority  => '40' ,
+      command   => 'deploy.sh' ,
+      arguments => $deploy_root ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($real_source_type == 'war') {
+    puppi::deploy { "${name}-Check_deploy":
+      priority  => '45' ,
+      command   => 'checkwardir.sh' ,
+      arguments => "-p ${deploy_root}/${source_filename}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Block":
+      priority  => '34' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($real_source_type == 'war') {
+    puppi::rollback { "${name}-Remove_existing_WAR":
+      priority  => '35' ,
+      command   => 'delete.sh' ,
+      arguments => "${deploy_root}/${source_filename}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+    puppi::rollback { "${name}-Check_undeploy":
+      priority  => '36' ,
+      command   => 'checkwardir.sh' ,
+      arguments => "-a ${deploy_root}/${source_filename}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Disable_extra_services":
+      priority  => '37' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($backup == 'full') or ($backup == 'diff') {
+    puppi::rollback { "${name}-Recover_Files_To_Deploy":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${deploy_root} -m ${backup} -o '${backup_rsync_options}'" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($real_source_type == 'war') {
+    puppi::rollback { "${name}-Check_deploy":
+      priority  => '45' ,
+      command   => 'checkwardir.sh' ,
+      arguments => "-p ${deploy_root}/${source_filename}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::rollback { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/dir.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,450 @@
+# = Define puppi::project::dir
+#
+# This is a shortcut define to build a puppi project for a deploy based
+# on the syncronization of a directory.
+# It uses different "core" defines (puppi::project, puppi:deploy (many),
+# puppi::rollback (many)) to build a full featured template project for
+# automatic deployments.
+# If you need to customize it, either change the template defined here or
+# build up your own custom ones.
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the main file to retrieve.
+#   Format should be in URI standard (http:// file:// ssh:// rsync://).
+#
+# [*deploy_root*]
+#   The destination directory where the retrieved file(s) are deployed.
+#
+# [*init_source*]
+#   (Optional) - The full URL to be used to retrieve, for the first time,
+#   the project files. They are copied directly to the $deploy_root
+#   Format should be in URI standard (http:// file:// ssh:// svn://).
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*init_script*]
+#   (Optional - Obsolete) - The name (ex: tomcat) of the init script of your
+#   Application server. If you define it, the AS is stopped and then started
+#   during deploy. This option is deprecated, you can use $disable_services
+#   for the same functionality
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*backup_rsync_options*]
+#   (Optional) - The extra options to pass to rsync for backup operations. Use
+#   it, for example, to exclude directories that you don't want to archive.
+#   IE: "--exclude .snapshot --exclude cache --exclude www/cache".
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*skip_predeploy*]
+#    For large data to deploy predeploy copy in /tmp/puppi might full the
+#    filesystem. Set to "yes" to deploy directly to $deploy_root. Default: no
+#    (files are first predeployed in /tmp/puppi then copied to $deploy_root)
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::dir (
+  $source,
+  $deploy_root,
+  $init_source              = '',
+  $user                     = 'root',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $init_script              = '',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $backup_rsync_options     = '--exclude .snapshot',
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $skip_predeploy           = false,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  $bool_run_checks = any2bool($run_checks)
+  $bool_skip_predeploy = any2bool($skip_predeploy)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+
+### INIT SEQUENCE
+  if ($init_source != '') {
+    puppi::initialize { "${name}-Deploy_Files":
+      priority  => '40' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${init_source} -d ${deploy_root}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_skip_predeploy == false) {
+    puppi::deploy { "${name}-Sync_Files":
+      priority  => '20' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${source} -t dir" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    puppi::deploy { "${name}-Backup_existing_Files":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${deploy_root} -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  # Here is done the deploy on $deploy_root
+  if ($bool_skip_predeploy == false) {
+    puppi::deploy { "${name}-Deploy":
+      priority  => '40' ,
+      command   => 'deploy.sh' ,
+      arguments => $deploy_root ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_skip_predeploy == true) {
+    puppi::deploy { "${name}-Deploy":
+      priority  => '40' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${source} -d ${deploy_root}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+  # End deploy
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_start":
+      priority  => '42' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK SEQUENCE
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Disable_extra_services":
+      priority  => '37' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::rollback { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    puppi::rollback { "${name}-Recover_Files_To_Deploy":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${deploy_root} -o '${backup_rsync_options}'" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::rollback { "${name}-Service_start":
+      priority  => '42' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::rollback { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/files.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,482 @@
+# = Define puppi::project::files
+#
+# This is a sample define to build a puppi project for the deploy of
+# one or more files based on a provided list containing, one per line,
+# the full path of the files to deploy.
+# The place (url) from where to get the files is defined by the
+# $source_baseurl variable.
+# You can strip out some beginning chars from each line with the
+# (optional) $files_prefix variable.
+# Files are then copied to the $deploy_root you define.
+#
+# Many different variables are optional in order to adapt the define
+# to different cases and needs, if you still need to customize it,
+# you can clone this puppi::project into another file and change the
+# define name.
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the main file to retrieve.
+#   Format should be in URI standard (http:// file:// ssh:// rsync://).
+#
+# [*deploy_root*]
+#   The destination directory where the retrieved file(s) are deployed.
+#
+# [*source_baseurl*]
+#   The full URL, in URI standard format, to prepend to the entries i
+#   the files list in order to retrieve the relative files.
+#
+# [*init_source*]
+#   (Optional) - The full URL to be used to retrieve, for the first time,
+#   the project files. They are copied directly to the $deploy_root
+#   Format should be in URI standard (http:// file:// ssh:// svn://).
+#
+# [*prefix*]
+#   (Optional) - The prefix that might be present in the filelist to
+#   define custom  metadata
+#
+# [*files_prefix*]
+#   (Optional) The prefix to remove from the list entries in order to
+#   determine the files path on the deploy_root
+#   We suggest to place in the files list just the deploy_root relative
+#   paths of the files, and in this case the $files_prefix is null
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*init_script*]
+#   (Optional - Obsolete) - The name (ex: tomcat) of the init script of your
+#   Application server. If you define it, the AS is stopped and then started
+#   during deploy. This option is deprecated, you can use $disable_services
+#   for the same functionality
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*backup_rsync_options*]
+#   (Optional) - The extra options to pass to rsync for backup operations. Use
+#   it, for example, to exclude directories that you don't want to archive.
+#   IE: "--exclude .snapshot --exclude cache --exclude www/cache".
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::files (
+  $source,
+  $source_baseurl,
+  $deploy_root,
+  $init_source              = '',
+  $files_prefix             = '',
+  $prefix                   = '',
+  $user                     = 'root',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $init_script              = '',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $backup_rsync_options     = '--exclude .snapshot',
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  $bool_run_checks = any2bool($run_checks)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+
+### INIT SEQUENCE
+  if ($init_source != '') {
+    puppi::initialize { "${name}-Deploy_Files":
+      priority  => '40' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${init_source} -d ${deploy_root}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    puppi::deploy { "${name}-Retrieve_File_List":
+      priority  => '20' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${source} -t list" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+    $args_prefix = $prefix ? {
+      ''      => '',
+      default => "-m ${prefix}",
+    }
+
+    puppi::deploy { "${name}-Extract_File_Metadata":
+      priority  => '22' ,
+      command   => 'get_metadata.sh' ,
+      arguments => $args_prefix,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+    puppi::deploy { "${name}-Clean_File_List":
+      priority  => '24' ,
+      command   => 'clean_filelist.sh' ,
+      arguments => $files_prefix ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+    puppi::deploy { "${name}-Retrieve_Files":
+      priority  => '25' ,
+      command   => 'get_filesfromlist.sh' ,
+      arguments => $source_baseurl ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    puppi::deploy { "${name}-Backup_existing_Files":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${deploy_root} -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  # Here is done the deploy on $deploy_root
+    puppi::deploy { "${name}-Deploy":
+      priority  => '40' ,
+      command   => 'deploy.sh' ,
+      arguments => $deploy_root ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_start":
+      priority  => '42' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK SEQUENCE
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::rollback { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    puppi::rollback { "${name}-Recover_Files_To_Deploy":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${deploy_root} -o '${backup_rsync_options}'" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::rollback { "${name}-Service_start":
+      priority  => '42' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::rollback { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/git.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,418 @@
+# == Define puppi::project::git
+#
+# This is a shortcut define to build a puppi project for the deploy of
+# file from a git repo.
+# It uses different "core" defines (puppi::project, puppi:deploy (many),
+# puppi::rollback (many)) to build a full featured template project for
+# automatic deployments.
+# If you need to customize it, either change the template defined here or
+# build up your own custom ones.
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the git repo to retrieve.
+#   Format should be in git friendly standard (http:// git:// ssh:// ..).
+#
+# [*deploy_root*]
+#   The destination directory where the retrieved file(s) are deployed.
+#
+# [*install_git*]
+#   If the git package hs to be installed. Default true.
+#   Set to false if you install git via other modules and have resource
+#   conflicts.
+#
+# [*git_subdir*]
+#   (Optional) - If you want to copy to the deploy_root only a subdir
+#   of the specified git repo, specify here the path of the directory
+#   relative to the repo root. Default undefined
+#
+# [*tag*]
+#   (Optional) - A specific tag you may want to deploy. Default undefined
+#   You can override the default value via command-line with:
+#   puppi deploy myapp -o "tag=release"
+#
+# [*branch*]
+#   (Optional) - A specific branch you may want to deploy. Default: master
+#   You can override the default value via command-line with:
+#   puppi deploy myapp -o "branch=devel"
+#
+# [*commit*]
+#   (Optional) - A specific commit you may want to use. Default undefined
+#   You can override the default value via command-line with:
+#   puppi deploy myapp -o "commit=1061cb731bc75a1188b58b889b74ce1505ccb412"
+#
+# [*keep_gitdata*]
+#   (Optional) - Define if you want to keep git metadata directory (.git)
+#   in the deploy root. According to this value backup and rollback
+#   operations change (with keep_gitdata set to true no real backups are done
+#   and operations are made on the git tree, if set to false, file are copied
+#   and the $backup_* options used. Default is true
+#
+# [*verbose*]
+#   (Optional) - If you want to see verbose git utput (file names) during
+#   the deploy. Default is true.
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#   If different from root (default) it must have write permissions on
+#   the $deploy_root dir.
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*backup_rsync_options*]
+#   (Optional) - The extra options to pass to rsync for backup operations. Use
+#   it, for example, to exclude directories that you don't want to archive.
+#   IE: "--exclude .snapshot --exclude cache --exclude www/cache".
+#   This option is used when $keep_gitmeta is set to false
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#   This option is used when $keep_gitmeta is set to false
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::git (
+  $source,
+  $deploy_root,
+  $install_git              = true,
+  $git_subdir               = 'undefined',
+  $tag                      = 'undefined',
+  $branch                   = 'master',
+  $commit                   = 'undefined',
+  $keep_gitdata             = true,
+  $verbose                  = true,
+  $user                     = 'root',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $backup_rsync_options     = '--exclude .snapshot',
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  $bool_install_git = any2bool($install_git)
+  $bool_keep_gitdata = any2bool($keep_gitdata)
+  $bool_verbose = any2bool($verbose)
+  $bool_run_checks = any2bool($run_checks)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+### INSTALL GIT
+  if ($bool_install_git == true) {
+    if ! defined(Package['git']) { package { 'git': ensure => installed } }
+  }
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_keep_gitdata == true) {
+    puppi::deploy { "${name}-Backup_existing_data":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${deploy_root} -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here is done the deploy on $deploy_root
+    puppi::deploy { "${name}-Deploy_Files":
+      priority  => '40' ,
+      command   => 'git.sh' ,
+      arguments => "-a deploy -s ${source} -d ${deploy_root} -u ${user} -gs ${git_subdir} -t ${tag} -b ${branch} -c ${commit} -v ${bool_verbose} -k ${bool_keep_gitdata}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Disable_extra_services":
+      priority  => '37' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_keep_gitdata == true) {
+    puppi::rollback { "${name}-Recover_Files_To_Deploy":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${deploy_root} -o '${backup_rsync_options}'" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_keep_gitdata != true) {
+    puppi::rollback { "${name}-Rollback_Files":
+      priority  => '40' ,
+      command   => 'git.sh' ,
+      arguments => "-a rollback -s ${source} -d ${deploy_root} -gs ${git_subdir} -t ${tag} -b ${branch} -c ${commit} -v ${bool_verbose} -k ${bool_keep_gitdata}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::rollback { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/hg.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,412 @@
+# == Define puppi::project::hg
+#
+# This is a shortcut define to build a puppi project for the deploy of
+# file from a mercurial repo.
+# It uses different "core" defines (puppi::project, puppi:deploy (many),
+# puppi::rollback (many)) to build a full featured template project for
+# automatic deployments.
+# If you need to customize it, either change the template defined here or
+# build up your own custom ones.
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the mercurial repo to retrieve.
+#   Format should be in mercurial friendly standard (http:// ssh:// ..).
+#
+# [*deploy_root*]
+#   The destination directory where the retrieved file(s) are deployed.
+#
+# [*install_hg*]
+#   If the mercurial package has to be installed. Default true.
+#   Set to false if you install mercurial via other modules and have resource
+#   conflicts.
+#
+# [*tag*]
+#   (Optional) - A specific tag you may want to deploy. Default undefined
+#   You can override the default value via command-line with:
+#   puppi deploy myapp -o "tag=release"
+#
+# [*branch*]
+#   (Optional) - A specific branch you may want to deploy. Default: master
+#   You can override the default value via command-line with:
+#   puppi deploy myapp -o "branch=devel"
+#
+# [*commit*]
+#   (Optional) - A specific commit you may want to use. Default undefined
+#   You can override the default value via command-line with:
+#   puppi deploy myapp -o "commit=1061cb731bc75a1188b58b889b74ce1505ccb412"
+#
+# [*keep_hgdata*]
+#   (Optional) - Define if you want to keep mercurial metadata directory (.hg)
+#   in the deploy root. According to this value backup and rollback
+#   operations change (with keep_hgdata set to true no real backups are done
+#   and operations are made on the mercurial tree, if set to false, file are copied
+#   and the $backup_* options used. Default is true
+#
+# [*verbose*]
+#   (Optional) - If you want to see verbose mercurial output (file names) during
+#   the deploy. Default is true.
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#   If different from root (default) it must have write permissions on
+#   the $deploy_root dir.
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*backup_rsync_options*]
+#   (Optional) - The extra options to pass to rsync for backup operations. Use
+#   it, for example, to exclude directories that you don't want to archive.
+#   IE: "--exclude .snapshot --exclude cache --exclude www/cache".
+#   This option is used when $keep_hgmeta is set to false
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#   This option is used when $keep_hgmeta is set to false
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::hg (
+  $source,
+  $deploy_root,
+  $install_hg               = true,
+  $tag                      = 'undefined',
+  $branch                   = 'default',
+  $commit                   = 'undefined',
+  $keep_hgdata              = true,
+  $verbose                  = true,
+  $user                     = 'root',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $backup_rsync_options     = '--exclude .snapshot',
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  $bool_install_hg = any2bool($install_hg)
+  $bool_keep_hgdata = any2bool($keep_hgdata)
+  $bool_verbose = any2bool($verbose)
+  $bool_run_checks = any2bool($run_checks)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+### INSTALL HG
+  if ($bool_install_hg == true) {
+    if ! defined(Package['mercurial']) { package { 'mercurial': ensure => installed } }
+  }
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_keep_hgdata == true) {
+    puppi::deploy { "${name}-Backup_existing_data":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${deploy_root} -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here is done the deploy on $deploy_root
+    puppi::deploy { "${name}-Deploy_Files":
+      priority  => '40' ,
+      command   => 'hg.sh' ,
+      arguments => "-a deploy -s ${source} -d ${deploy_root} -u ${user} -t ${tag} -b ${branch} -c ${commit} -v ${bool_verbose} -k ${bool_keep_hgdata}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Disable_extra_services":
+      priority  => '37' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_keep_hgdata == true) {
+    puppi::rollback { "${name}-Recover_Files_To_Deploy":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${deploy_root} -o '${backup_rsync_options}'" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_keep_hgdata != true) {
+    puppi::rollback { "${name}-Rollback_Files":
+      priority  => '40' ,
+      command   => 'hg.sh' ,
+      arguments => "-a rollback -s ${source} -d ${deploy_root} -t ${tag} -b ${branch} -c ${commit} -v ${bool_verbose} -k ${bool_keep_hgdata}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::rollback { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/maven.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,814 @@
+# = Define puppi::project::maven
+#
+# This is a shortcut define to build a puppi project for the
+# deploy of war and tar files generated via Maven and published on
+# a repository like Sonar.
+#
+# It uses different "core" defines (puppi::project, puppi:deploy (many),
+# puppi::rollback (many)) to build a full featured template project for
+# automatic deployments.
+# If you need to customize it, either change the template defined here or
+# build up your own custom ones.
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the maven-metadata.xml file to retrieve.
+#   Format should be in URI standard (http:// file:// ssh:// rsync://).
+#
+# [*http_password*]
+#   The http_password to use for authentication to the source in case of http.
+#
+# [*http_user*]
+#   The http_user to use for authentication to the source in case of http.
+#
+# [*artifact_type*]
+#   The artifact_type to parse the maven-metadata.xml. Either "release", "latest" or
+#   a specific version (e.g. "2.5.0")
+#   Default is "release". With artifactory, don't use the
+#   "Maven Snapshot Version Behavior" "unique" for your repository.
+#
+# [*deploy_root*]
+#   The destination directory where file(s) are deployed.
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#
+# [*war_suffix*]
+#   (Optional) - The suffix (Maven qualifier) that might be appended to the war
+#
+# [*zip_root*]
+#   (Optional) - The destination directory where the zip is unpacked
+#
+# [*zip_user*]
+#   (Optional) - The user to be used for deploy operations of the zip
+#
+# [*zip_suffix*]
+#   (Optional) - The suffix (Maven qualifier) that might be appended to the zip
+#
+# [*jar_root*]
+#   (Optional) - The destination directory where the jar is copied.
+#   If set a jar file is searched in Maven
+#
+# [*jar_user*]
+#   (Optional) - The user to be used for deploy operations of the jar
+#   (owner of the files deployed in $jar_root)
+#
+# [*jar_suffix*]
+#   (Optional) - The suffix (Maven qualifier) that might be appended to the jar
+#
+# [*document_root*]
+#   (Optional) - The destination directory where the eventual tarball generated
+#   via Maven containing static files ("src tar") is unpacked
+#
+# [*document_suffix*]
+#   (Optional) - The suffix (Maven qualifier) that might be appended to the
+#   static files tarballs ("src tar")
+#
+# [*document_init_source*]
+#   (Optional) - The full URL to be used to retrieve, for the first time, the
+#    project files present in the source tarball. They are copied to the
+#    $document_root. Format should be in URI standard (http:// file:// ...)
+#
+# [*document_user*]
+#   (Optional) - The user to be used for deploy operations of the tarball
+#   (owner of the files in $document_root)
+#
+# [*config_root*]
+#   (Optional) - The destination directory where the cfg tar is unpacked
+#
+# [*config_suffix*]
+#   (Optional) - The suffix (Maven qualifier) that might be appended to
+#   configuration tarballs ("cfg tar")
+#
+# [*config_init_source*]
+#   (Optional) - The full URL to be used to retrieve, for the first time, the
+#   project files present in the cfg tar. They are copied to the $config_root.
+#   Format should be in URI standard (http:// file:// ssh:// svn://)
+#
+# [*config_user*]
+#   (Optional) - The user to be used for deploy operations of cfg tar
+#   (owner of the files in $config_root)
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*init_script*]
+#   (Optional - Obsolete) - The name (ex: tomcat) of the init script of your
+#   Application server. If you define it, the AS is stopped and then started
+#   during deploy. This option is deprecated, you can use $disable_services
+#   for the same functionality
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*report_mongo*]
+#   (Optional) - A mongourl with optional user:password to report to. Append the
+#   database with a slash ("mongodb://user:password@mymongo.mydomain.com/theNameOfDb")
+#
+# [*backup_rsync_options*]
+#   (Optional) - The extra options to pass to rsync for backup operations. Use
+#   it, for example, to exclude directories that you don't want to archive.
+#   IE: "--exclude .snapshot --exclude cache --exclude www/cache".
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*always_deploy*]
+#   (Optional) - If you always deploy what has been downloaded. Default="yes",
+#   if set to "no" a checksum is made between the files previously downloaded
+#   and the new files. If they are the same the deploy is not done.
+#
+# [*check_deploy*]
+#   (Optional) - Checks if the war is deployed (Default yes). Set to no if
+#   you deploy on Jboss or the deployed dir is different for the war filename
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::maven (
+  $source,
+  $http_user                = '',
+  $http_password            = '',
+  $artifact_type            = 'release',
+  $deploy_root              = '',
+  $user                     = 'root',
+  $war_suffix               = 'suffixnotset',
+  $zip_root                 = '',
+  $zip_user                 = '',
+  $zip_suffix               = 'suffixnotset',
+  $jar_root                 = '',
+  $jar_user                 = '',
+  $jar_suffix               = 'suffixnotset',
+  $document_root            = '',
+  $document_user            = '',
+  $document_suffix          = 'suffixnotset',
+  $document_init_source     = '',
+  $config_root              = '',
+  $config_user              = '',
+  $config_suffix            = 'suffixnotset',
+  $config_init_source       = '',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $init_script              = '',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $report_mongo             = '',
+  $backup_rsync_options     = '--exclude .snapshot',
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $always_deploy            = true,
+  $check_deploy             = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  $config_real_user = $config_user ? {
+    ''      => $user,
+    default => $config_user,
+  }
+
+  $document_real_user = $document_user ? {
+    ''      => $user,
+    default => $document_user,
+  }
+
+  $jar_real_user = $jar_user ? {
+    ''      => $user,
+    default => $jar_user,
+  }
+
+  $zip_real_user = $zip_user ? {
+    ''      => $user,
+    default => $zip_user,
+  }
+
+  $real_always_deploy = any2bool($always_deploy) ? {
+    false   => 'no',
+    true    => 'yes',
+  }
+
+  $bool_run_checks = any2bool($run_checks)
+  $bool_check_deploy = any2bool($check_deploy)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+
+### INIT SEQUENCE
+  if ($document_init_source != '') {
+    puppi::initialize { "${name}-Deploy_Files":
+      priority  => '40' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${document_init_source} -d ${deploy_root}" ,
+      user      => $document_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($config_init_source != '') {
+    puppi::initialize { "${name}-Deploy_CFG_Files":
+      priority  => '40' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${config_init_source} -d ${deploy_root}" ,
+      user      => $config_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  $metadata_arguments = $http_password ? {
+    '' => "-s ${source}/maven-metadata.xml -t maven-metadata -a ${real_always_deploy}",
+    default => "-s ${source}/maven-metadata.xml -t maven-metadata -a ${real_always_deploy} -u ${http_user} -p ${http_password}"
+  }
+
+  puppi::deploy { "${name}-Get_Maven_Metadata_File":
+    priority  => '20' ,
+    command   => 'get_file.sh' ,
+    arguments => $metadata_arguments,
+    user      => 'root' ,
+    project   => $name ,
+    enable    => $enable ,
+  }
+
+  puppi::deploy { "${name}-Extract_Maven_Metadata":
+    priority  => '22' ,
+    command   => 'get_metadata.sh' ,
+    arguments => "-m ${document_suffix} -mc ${config_suffix} -mj ${jar_suffix} -mw ${war_suffix} -mz ${zip_suffix} -at ${artifact_type}" ,
+    user      => 'root' ,
+    project   => $name ,
+    enable    => $enable ,
+  }
+
+  # Files retrieval
+  if ($deploy_root != '') {
+    $war_arguments = $http_password ? {
+      '' => "${source} warfile",
+      default => "-u ${http_user} -p ${http_password} ${source} warfile"
+    }
+
+    puppi::deploy { "${name}-Get_Maven_Files_WAR":
+      priority  => '25' ,
+      command   => 'get_maven_files.sh' ,
+      arguments => $war_arguments,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($jar_root != '') {
+    puppi::deploy { "${name}-Get_Maven_Files_JAR":
+      priority  => '25' ,
+      command   => 'get_maven_files.sh' ,
+      arguments => "${source} jarfile" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($config_root != '') {
+    puppi::deploy { "${name}-Get_Maven_Files_Config":
+      priority  => '25' ,
+      command   => 'get_maven_files.sh' ,
+      arguments => "${source} configfile" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($document_root != '') {
+    puppi::deploy { "${name}-Get_Maven_Files_SRC":
+      priority  => '25' ,
+      command   => 'get_maven_files.sh' ,
+      arguments => "${source} srcfile" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($zip_root != '') {
+    $real_arguments = $http_password ? {
+      ''      => "${source} zipfile",
+      default => "-u ${http_user} -p ${http_password} ${source} zipfile"
+    }
+
+    puppi::deploy { "${name}-Get_Maven_Files_ZIP":
+      priority  => '25' ,
+      command   => 'get_maven_files.sh' ,
+      arguments =>  $real_arguments,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '30' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  # Existing files backup
+  if ($deploy_root != '') {
+    puppi::deploy { "${name}-Backup_Existing_WAR":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${deploy_root} -t war -s move -m diff -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($jar_root != '') {
+    puppi::deploy { "${name}-Backup_Existing_JAR":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${jar_root} -t jar -s move -m diff -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($config_root != '') {
+    puppi::deploy { "${name}-Backup_Existing_ConfigDir":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${config_root} -t config -d predeploydir_configfile -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($document_root != '') {
+    puppi::deploy { "${name}-Backup_Existing_DocumentDir":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${document_root} -t docroot -d predeploydir_configfile -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($zip_root != '') {
+    puppi::deploy { "${name}-Backup_Existing_ZipDir":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${zip_root} -t ziproot -d predeploydir_zipfile -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_check_deploy == true) and ($deploy_root != '') {
+    puppi::deploy { "${name}-Check_undeploy":
+      priority  => '31' ,
+      command   => 'checkwardir.sh' ,
+      arguments => "-a ${deploy_root} -c deploy_warpath" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  # Deploys
+  if ($deploy_root != '') {
+    puppi::deploy { "${name}-Deploy_Maven_WAR":
+      priority  => '40' ,
+      command   => 'deploy.sh' ,
+      arguments => $deploy_root ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($jar_root != '') {
+    puppi::deploy { "${name}-Deploy_Maven_JAR":
+      priority  => '40' ,
+      command   => 'deploy.sh' ,
+      arguments => $jar_root ,
+      user      => $jar_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($config_root != '') {
+    puppi::deploy { "${name}-Deploy_ConfigDir":
+      priority  => '40' ,
+      command   => 'deploy.sh' ,
+      arguments => "${config_root} predeploydir_configfile" ,
+      user      => $config_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($document_root != '') {
+    puppi::deploy { "${name}-Deploy_DocumentDir":
+      priority  => '40' ,
+      command   => 'deploy.sh' ,
+      arguments => "${document_root} predeploydir_srcfile" ,
+      user      => $document_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($zip_root != '') {
+    puppi::deploy { "${name}-Deploy_Zip":
+      priority  => '40' ,
+      command   => 'deploy.sh' ,
+      arguments => "${zip_root} predeploydir_zipfile" ,
+      user      => $zip_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_start":
+      priority  => '42' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_check_deploy == true) and ($deploy_root != '') {
+    puppi::deploy { "${name}-Check_deploy":
+      priority  => '45' ,
+      command   => 'checkwardir.sh' ,
+      arguments => "-p ${deploy_root} -c deploy_warpath" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Disable_extra_services":
+      priority  => '37' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::rollback { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($deploy_root != '') {
+    puppi::rollback { "${name}-Recover_WAR":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${deploy_root} -t war -o '${backup_rsync_options}'" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($jar_root != '') {
+    puppi::rollback { "${name}-Recover_JAR":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${jar_root} -t jar -o '${backup_rsync_options}'" ,
+      user      => $jar_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($config_root != '') {
+    puppi::rollback { "${name}-Recover_ConfigDir":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${config_root} -t config -o '${backup_rsync_options}'" ,
+      user      => $config_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($document_root != '') {
+    puppi::rollback { "${name}-Recover_DocumentDir":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${document_root} -t docroot -o '${backup_rsync_options}'" ,
+      user      => $document_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::rollback { "${name}-Service_start":
+      priority  => '42' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_check_deploy == true) {
+    puppi::rollback { "${name}-Check_deploy":
+      priority  => '45' ,
+      command   => 'checkwardir.sh' ,
+      arguments => "-p ${deploy_root} -c deploy_warpath" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::rollback { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($report_mongo != '') {
+    puppi::report { "${name}-Mongo_Store":
+      priority  => '30' ,
+      command   => 'report_mongo.sh' ,
+      arguments => $report_mongo ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/mysql.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,425 @@
+# = Define puppi::project::mysql
+#
+# This is a shortcut define to build a puppi project for the
+# management of mysql queries, contained in the .sql file defined
+# as $source
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the main sql file to retrieve.
+#   Format should be in URI standard (http:// file:// ssh:// rsync://).
+#
+# [*mysql_database*]
+#   (Required) - The Mysql database to work on
+#   Default: root
+#
+# [*mysql_user*]
+#   (Optional) - The Mysql user to be used to run the queries
+#   Default: root
+#
+# [*mysql_password*]
+#   (Optional) - The password to use for the specified mysql user
+#   Default: '' (blank)
+#
+# [*mysql_host*]
+#   (Optional) - The Mysql server. Use ip or hostname
+#   Default: localhost
+#
+# [*init_source*]
+#   (Optional) - The full URL to be used to retrieve a sql file to
+#   process only for the first time,
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*backup*]
+#   (Optional) - If and how backups of existing databases are made.
+#   Default: true
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*always_deploy*]
+#   (Optional) - If you always deploy what has been downloaded. Default="yes",
+#   if set to "no" a checksum is made between the files previously downloaded
+#   and the new files. If they are the same the deploy is not done.
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::mysql (
+  $source,
+  $mysql_database,
+  $mysql_user               = 'root',
+  $mysql_host               = 'localhost',
+  $mysql_password           = '',
+  $init_source              = '',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $backup                   = true,
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $always_deploy            = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => 'root',
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => 'root',
+    default => $postdeploy_user,
+  }
+
+  $init_real_source = $init_source ? {
+    ''      => $source,
+    default => $init_source,
+  }
+
+  $real_always_deploy = any2bool($always_deploy) ? {
+    false   => 'no',
+    true    => 'yes',
+  }
+
+  $bool_run_checks = any2bool($run_checks)
+  $bool_backup = any2bool($backup)
+  $real_source_type = 'mysql'
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+  $source_filename = url_parse($source,'filename')
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+
+### INIT SEQUENCE
+  if ($init_source != '') {
+    puppi::initialize { "${name}-Deploy_Files":
+      priority  => '40' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${init_source} -t ${real_source_type}" ,
+      user      => root ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+    puppi::initialize { "${name}-Run_SQL":
+      priority  => '42' ,
+      command   => 'database.sh' ,
+      arguments => "-t mysql -a run -u ${mysql_user} -p '${mysql_password}' -d ${mysql_database} -h ${mysql_host}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    puppi::deploy { "${name}-Retrieve_SQLFile":
+      priority  => '20' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${source} -t ${real_source_type} -a ${real_always_deploy}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_backup == true) {
+    puppi::deploy { "${name}-Backup_Database":
+      priority  => '30' ,
+      command   => 'database.sh' ,
+      arguments => "-t mysql -a dump -u ${mysql_user} -p '${mysql_password}' -d ${mysql_database} -h ${mysql_host}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here is done the db change
+    puppi::deploy { "${name}-Run_SQL":
+      priority  => '40' ,
+      command   => 'database.sh' ,
+      arguments => "-t mysql -a run -u ${mysql_user} -p '${mysql_password}' -d ${mysql_database} -h ${mysql_host}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_backup == true) {
+    puppi::rollback { "${name}-Backup_Database_PreRollback":
+      priority  => '30' ,
+      command   => 'database.sh' ,
+      arguments => "-t mysql -a dump -u ${mysql_user} -p '${mysql_password}' -d ${mysql_database} -h ${mysql_host}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Disable_extra_services":
+      priority  => '37' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_backup == true) {
+    puppi::rollback { "${name}-Recover_Database":
+      priority  => '40' ,
+      command   => 'database.sh' ,
+      arguments => "-t mysql -a restore -u ${mysql_user} -p '${mysql_password}' -d ${mysql_database} -h ${mysql_host}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::rollback { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/service.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,352 @@
+# = Define puppi::project::service
+#
+# This is a shortcut define to build a case-limit puppi project
+# that just manages services and custom commands without deploying
+# any file. It doesn't require any parameter but you should at least
+# provide one among predeploy_customcommand, postdeploy_customcommand,
+# init_script, disable_services to make something useful.
+# The rollback option is kept for coherency with the standard puppi
+# deploy approach, but actually should not be used since there is no
+# data to rollback.
+#
+# == Variables:
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*init_script*]
+#   (Optional - Obsolete) - The name (ex: tomcat) of the init script of your
+#   Application server. If you define it, the AS is stopped and then started
+#   during deploy. This option is deprecated, you can use $disable_services
+#   for the same functionality
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::service (
+  $user                     = 'root',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $init_script              = '',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $run_checks               = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  $bool_run_checks = any2bool($run_checks)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_start":
+      priority  => '42' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Disable_extra_services":
+      priority  => '37' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::rollback { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::rollback { "${name}-Service_start":
+      priority  => '42' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::rollback { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/svn.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,438 @@
+# == Define puppi::project::svn
+#
+# This is a shortcut define to build a puppi project for the deploy of
+# file from a svn repo.
+# It uses different "core" defines (puppi::project, puppi:deploy (many),
+# puppi::rollback (many)) to build a full featured template project for
+# automatic deployments.
+# If you need to customize it, either change the template defined here or
+# build up your own custom ones.
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the svn repo to retrieve.
+#   Format should be in svn friendly standard (http:// svn:// ..).
+#
+# [*svn_user*]
+#   Name of the user to access a private svn repo. Optional.
+#
+# [*svn_password*]
+#   Name of the password to access a private svn repo. Optional.
+#
+# [*deploy_root*]
+#   The destination directory where the retrieved file(s) are deployed.
+#
+# [*install_svn*]
+#   If the svn package has to be installed. Default true.
+#   Set to false if you install svn via other modules and have resource
+#   conflicts.
+#
+# [*svn_subdir*]
+#   (Optional) - If you want to copy to the deploy_root only a subdir
+#   of the specified svn repo, specify here the path of the directory
+#   relative to the repo root. Default undefined
+#
+# [*svn_export*]
+#   (Optional) - If to use a svn export command instead of checkout
+#   Default: false (A checkout is done)
+#
+# [*tag*]
+#   (Optional) - A specific tag you may want to deploy. Default undefined
+#   You can override the default value via command-line with:
+#   puppi deploy myapp -o "tag=release"
+#
+# [*branch*]
+#   (Optional) - A specific branch you may want to deploy. Default: master
+#   You can override the default value via command-line with:
+#   puppi deploy myapp -o "branch=devel"
+#
+# [*commit*]
+#   (Optional) - A specific commit you may want to use. Default undefined
+#   You can override the default value via command-line with:
+#   puppi deploy myapp -o "commit=1061cb731bc75a1188b58b889b74ce1505ccb412"
+#
+# [*keep_svndata*]
+#   (Optional) - Define if you want to keep svn metadata directory (.svn)
+#   in the deploy root. According to this value backup and rollback
+#   operations change (with keep_svndata set to true no real backups are done
+#   and operations are made on the svn tree, if set to false, file are copied
+#   and the $backup_* options used. Default is true
+#
+# [*verbose*]
+#   (Optional) - If you want to see verbose svn utput (file names) during
+#   the deploy. Default is true.
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#   If different from root (default) it must have write permissions on
+#   the $deploy_root dir.
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*backup_enable*]
+#   (Optional, default true) - If the backup of files in the deploy dir
+#   is done (before deploy). If set to false, rollback is disabled.
+#
+# [*backup_rsync_options*]
+#   (Optional) - The extra options to pass to rsync for backup operations. Use
+#   it, for example, to exclude directories that you don't want to archive.
+#   IE: "--exclude .snapshot --exclude cache --exclude www/cache".
+#   This option is used when $keep_svnmeta is set to false
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#   This option is used when $keep_svnmeta is set to false
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::svn (
+  $source,
+  $deploy_root,
+  $install_svn              = true,
+  $svn_user                 = 'undefined',
+  $svn_password             = 'undefined',
+  $svn_subdir               = 'undefined',
+  $svn_export               = false,
+  $tag                      = 'undefined',
+  $branch                   = 'master',
+  $commit                   = 'undefined',
+  $keep_svndata             = true,
+  $verbose                  = true,
+  $user                     = 'root',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $backup_enable            = true,
+  $backup_rsync_options     = '--exclude .snapshot',
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  $bool_install_svn = any2bool($install_svn)
+  $bool_svn_export = any2bool($svn_export)
+  $bool_keep_svndata = any2bool($keep_svndata)
+  $bool_verbose = any2bool($verbose)
+  $bool_backup_enable = any2bool($backup_enable)
+  $bool_run_checks = any2bool($run_checks)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+### INSTALL GIT
+  if ($bool_install_svn == true) {
+    if ! defined(Package['subversion']) { package { 'subversion': ensure => installed } }
+  }
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_keep_svndata == true and $bool_backup_enable == true) {
+    puppi::deploy { "${name}-Backup_existing_data":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${deploy_root} -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here is done the deploy on $deploy_root
+    puppi::deploy { "${name}-Deploy_Files":
+      priority  => '40' ,
+      command   => 'svn.sh' ,
+      arguments => "-a deploy -s ${source} -d ${deploy_root} -u ${user} -gs ${svn_subdir} -su ${svn_user} -sp ${svn_password} -t ${tag} -b ${branch} -c ${commit} -v ${bool_verbose} -k ${bool_keep_svndata} -e ${bool_svn_export}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($bool_backup_enable == true) {
+  if ($firewall_src_ip != '') {
+      puppi::rollback { "${name}-Load_Balancer_Block":
+        priority  => '25' ,
+        command   => 'firewall.sh' ,
+        arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($disable_services != '') {
+      puppi::rollback { "${name}-Disable_extra_services":
+        priority  => '37' ,
+        command   => 'service.sh' ,
+        arguments => "stop ${disable_services}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($predeploy_customcommand != '') {
+      puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+        priority  => $predeploy_priority ,
+        command   => 'execute.sh' ,
+        arguments => $predeploy_customcommand ,
+        user      => $predeploy_real_user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($bool_keep_svndata == true) {
+      puppi::rollback { "${name}-Recover_Files_To_Deploy":
+        priority  => '40' ,
+        command   => 'archive.sh' ,
+        arguments => "-r ${deploy_root} -o '${backup_rsync_options}'" ,
+        user      => $user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($bool_keep_svndata != true) {
+      puppi::rollback { "${name}-Rollback_Files":
+        priority  => '40' ,
+        command   => 'svn.sh' ,
+        arguments => "-a rollback -s ${source} -d ${deploy_root} -gs ${svn_subdir} -t ${tag} -b ${branch} -c ${commit} -v ${bool_verbose} -k ${bool_keep_svndata}" ,
+        user      => $user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($postdeploy_customcommand != '') {
+      puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+        priority  => $postdeploy_priority ,
+        command   => 'execute.sh' ,
+        arguments => $postdeploy_customcommand ,
+        user      => $postdeploy_real_user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($disable_services != '') {
+      puppi::rollback { "${name}-Enable_extra_services":
+        priority  => '44' ,
+        command   => 'service.sh' ,
+        arguments => "start ${disable_services}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($firewall_src_ip != '') {
+      puppi::rollback { "${name}-Load_Balancer_Unblock":
+        priority  => '46' ,
+        command   => 'firewall.sh' ,
+        arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($bool_run_checks == true) {
+      puppi::rollback { "${name}-Run_POST-Checks":
+        priority  => '80' ,
+        command   => 'check_project.sh' ,
+        arguments => $name ,
+        user      => 'root' ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+  }
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/tar.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,479 @@
+# = Define puppi::project::tar
+#
+# This is a shortcut define to build a puppi project for the
+# deploy of a tar.gz file into a deploy root
+#
+# It uses different "core" defines (puppi::project, puppi:deploy (many),
+# puppi::rollback (many)) to build a full featured template project for
+# automatic deployments.
+# If you need to customize it, either change the template defined here or
+# build up your own custom ones.
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the main file to retrieve.
+#   Format should be in URI standard (http:// file:// ssh:// rsync://).
+#
+# [*deploy_root*]
+#   The destination directory where the retrieved file(s) are deployed.
+#
+# [*init_source*]
+#   (Optional) - The full URL to be used to retrieve, for the first time,
+#   the project files. They are copied directly to the $deploy_root
+#   Format should be in URI standard (http:// file:// ssh:// svn://).
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*init_script*]
+#   (Optional - Obsolete) - The name (ex: tomcat) of the init script of your
+#   Application server. If you define it, the AS is stopped and then started
+#   during deploy. This option is deprecated, you can use $disable_services
+#   for the same functionality
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*clean_deploy*]
+#   (Optional, default false) - If during the deploy procedure, all the
+#   existing files that are not on the source have to be deleted.
+#   (When true, a --delete option is added to the rsync command)
+#   Do not set to true if source files are incremental.
+#
+# [*backup_enable*]
+#   (Optional, default true) - If the backup of files in the deploy dir
+#   is done (before deploy). If set to false, rollback is disabled.
+#
+# [*backup_rsync_options*]
+#   (Optional) - The extra options to pass to rsync for backup operations. Use
+#   it, for example, to exclude directories that you don't want to archive.
+#   IE: "--exclude .snapshot --exclude cache --exclude www/cache".
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*always_deploy*]
+#   (Optional) - If you always deploy what has been downloaded. Default="yes",
+#   if set to "no" a checksum is made between the files previously downloaded
+#   and the new files. If they are the same the deploy is not done.
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::tar (
+  $source,
+  $deploy_root,
+  $init_source              = '',
+  $user                     = 'root',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $init_script              = '',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $clean_deploy             = false,
+  $backup_enable            = true,
+  $backup_rsync_options     = '--exclude .snapshot',
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $always_deploy            = true,
+  $auto_deploy              = false,
+  $verify_ssl               = true,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  $init_real_source = $init_source ? {
+    ''      => $source,
+    default => $init_source,
+  }
+
+  $real_always_deploy = any2bool($always_deploy) ? {
+    false   => 'no',
+    true    => 'yes',
+  }
+
+  $bool_clean_deploy = any2bool($clean_deploy)
+  $bool_backup_enable = any2bool($backup_enable)
+  $bool_run_checks = any2bool($run_checks)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+  if ($verify_ssl) {
+    $ssl_arg = ''
+  }else{
+    $ssl_arg = '-k'
+  }
+
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+
+### INIT SEQUENCE
+  if ($init_source != '') {
+    puppi::initialize { "${name}-Deploy_Files":
+      priority  => '40' ,
+      command   => 'get_file.sh' ,
+      arguments => "${ssl_arg} -s '${init_source}' -d ${deploy_root}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here source file is retrieved
+    puppi::deploy { "${name}-Retrieve_TarBall":
+      priority  => '20' ,
+      command   => 'get_file.sh' ,
+      arguments => "${ssl_arg} -s '${source}' -t tarball -a ${real_always_deploy}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+    puppi::deploy { "${name}-PreDeploy_TarBall":
+      priority  => '25' ,
+      command   => 'predeploy_tar.sh' ,
+      arguments => 'downloadedfile' ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_backup_enable == true) {
+    puppi::deploy { "${name}-Backup_existing_Files":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${deploy_root} -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here is done the deploy on $deploy_root
+    puppi::deploy { "${name}-Deploy":
+      priority  => '40' ,
+      command   => 'deploy_files.sh' ,
+      arguments => "-d ${deploy_root} -c ${bool_clean_deploy}",
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_start":
+      priority  => '42' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($bool_backup_enable == true) {
+    if ($firewall_src_ip != '') {
+      puppi::rollback { "${name}-Load_Balancer_Block":
+        priority  => '25' ,
+        command   => 'firewall.sh' ,
+        arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($disable_services != '') {
+      puppi::rollback { "${name}-Disable_extra_services":
+        priority  => '37' ,
+        command   => 'service.sh' ,
+        arguments => "stop ${disable_services}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($init_script != '') {
+      puppi::rollback { "${name}-Service_stop":
+        priority  => '38' ,
+        command   => 'service.sh' ,
+        arguments => "stop ${init_script}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($predeploy_customcommand != '') {
+      puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+        priority  => $predeploy_priority ,
+        command   => 'execute.sh' ,
+        arguments => $predeploy_customcommand ,
+        user      => $predeploy_real_user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+      puppi::rollback { "${name}-Recover_Files_To_Deploy":
+        priority  => '40' ,
+        command   => 'archive.sh' ,
+        arguments => "-r ${deploy_root} -o '${backup_rsync_options}'" ,
+        user      => $user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+
+    if ($postdeploy_customcommand != '') {
+      puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+        priority  => $postdeploy_priority ,
+        command   => 'execute.sh' ,
+        arguments => $postdeploy_customcommand ,
+        user      => $postdeploy_real_user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($init_script != '') {
+      puppi::rollback { "${name}-Service_start":
+        priority  => '42' ,
+        command   => 'service.sh' ,
+        arguments => "start ${init_script}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($disable_services != '') {
+      puppi::rollback { "${name}-Enable_extra_services":
+        priority  => '44' ,
+        command   => 'service.sh' ,
+        arguments => "start ${disable_services}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($firewall_src_ip != '') {
+      puppi::rollback { "${name}-Load_Balancer_Unblock":
+        priority  => '46' ,
+        command   => 'firewall.sh' ,
+        arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($bool_run_checks == true) {
+      puppi::rollback { "${name}-Run_POST-Checks":
+        priority  => '80' ,
+        command   => 'check_project.sh' ,
+        arguments => $name ,
+        user      => 'root' ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+  }
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/war.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,525 @@
+# == Define puppi::project::war
+#
+# This is a shortcut define to build a puppi project for the deploy of warfiles
+# It uses different "core" defines (puppi::project, puppi:deploy (many),
+# puppi::rollback (many)) to build a full featured template project for
+# automatic deployments.
+# If you need to customize it, either change the template defined here or
+# build up your own custom ones.
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the main file to retrieve.
+#   Format should be in URI standard (http:// file:// ssh:// rsync://).
+#
+# [*deploy_root*]
+#   The destination directory where the retrieved file(s) are deployed.
+#
+# [*init_source*]
+#   (Optional) - The full URL to be used to retrieve, for the first time,
+#   the project files. They are copied directly to the $deploy_root
+#   Format should be in URI standard (http:// file:// ssh:// svn://).
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*init_script*]
+#   (Optional - Obsolete) - The name (ex: tomcat) of the init script of your
+#   Application server. If you define it, the AS is stopped and then started
+#   during deploy. This option is deprecated, you can use $disable_services
+#   for the same functionality
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*clean_deploy*]
+#   (Optional, default false) - If during the deploy procedure, all the
+#   existing files that are not on the source have to be deleted.
+#   (When true, a --delete option is added to the rsync command)
+#   Do not set to true if source files are incremental.
+#
+# [*backup_enable*]
+#   (Optional, default true) - If the backup of files in the deploy dir
+#   is done (before deploy). If set to false, rollback is disabled.
+#
+# [*backup_rsync_options*]
+#   (Optional) - The extra options to pass to rsync for backup operations. Use
+#   it, for example, to exclude directories that you don't want to archive.
+#   IE: "--exclude .snapshot --exclude cache --exclude www/cache".
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*always_deploy*]
+#   (Optional) - If you always deploy what has been downloaded. Default="yes",
+#   if set to "no" a checksum is made between the files previously downloaded
+#   and the new files. If they are the same the deploy is not done.
+#
+# [*check_deploy*]
+#   (Optional) - Checks if the war is deployed (Default yes). Set to no if
+#   you deploy on Jboss or the deployed dir is different for the war filename
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::war (
+  $source,
+  $deploy_root,
+  $init_source              = '',
+  $user                     = 'root',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $init_script              = '',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $clean_deploy             = false,
+  $backup_enable            = true,
+  $backup_rsync_options     = '--exclude .snapshot',
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $always_deploy            = true,
+  $check_deploy             = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  # Unless explicitely defined, we assume that the WAR file to use
+  # for initialization is the same to use for deploys
+  $init_real_source = $init_source ? {
+    ''      => $source,
+    default => $init_source,
+  }
+
+  $real_always_deploy = any2bool($always_deploy) ? {
+    false   => 'no',
+    true    => 'yes',
+  }
+
+  $bool_run_checks = any2bool($run_checks)
+  $bool_clean_deploy = any2bool($clean_deploy)
+  $bool_backup_enable = any2bool($backup_enable)
+  $bool_check_deploy = any2bool($check_deploy)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+  $war_file = url_parse($source,'filename')
+
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+
+### INIT SEQUENCE
+  if ($init_source != '') {
+    puppi::initialize { "${name}-Deploy_Files":
+      priority  => '40' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${init_source} -d ${deploy_root}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here source file is retrieved
+    puppi::deploy { "${name}-Retrieve_WAR":
+      priority  => '20' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${source} -a ${real_always_deploy}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_backup_enable == true) {
+    puppi::deploy { "${name}-Backup_existing_WAR":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${deploy_root} -t war -s move -m diff -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+}
+
+  if ($bool_check_deploy == true) {
+    puppi::deploy { "${name}-Check_undeploy":
+      priority  => '32' ,
+      command   => 'checkwardir.sh' ,
+      arguments => "-a ${deploy_root}/${war_file}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here is done the deploy on $deploy_root
+    puppi::deploy { "${name}-Deploy_WAR":
+      priority  => '40' ,
+      command   => 'deploy_files.sh' ,
+      arguments => "-d ${deploy_root} -c ${bool_clean_deploy}",
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_start":
+      priority  => '42' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_check_deploy == true) {
+    puppi::deploy { "${name}-Check_deploy":
+      priority  => '45' ,
+      command   => 'checkwardir.sh' ,
+      arguments => "-p ${deploy_root}/${war_file}" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($bool_backup_enable == true) {
+
+    if ($firewall_src_ip != '') {
+      puppi::rollback { "${name}-Load_Balancer_Block":
+        priority  => '25' ,
+        command   => 'firewall.sh' ,
+        arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+      puppi::rollback { "${name}-Remove_existing_WAR":
+        priority  => '30' ,
+        command   => 'delete.sh' ,
+        arguments => "${deploy_root}/${war_file}" ,
+        user      => 'root' ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+
+    if ($bool_check_deploy == true) {
+      puppi::rollback { "${name}-Check_undeploy":
+        priority  => '36' ,
+        command   => 'checkwardir.sh' ,
+        arguments => "-a ${deploy_root}/${war_file}" ,
+        user      => $user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($disable_services != '') {
+      puppi::rollback { "${name}-Disable_extra_services":
+        priority  => '37' ,
+        command   => 'service.sh' ,
+        arguments => "stop ${disable_services}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($init_script != '') {
+      puppi::rollback { "${name}-Service_stop":
+        priority  => '38' ,
+        command   => 'service.sh' ,
+        arguments => "stop ${init_script}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($predeploy_customcommand != '') {
+      puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+        priority  => $predeploy_priority ,
+        command   => 'execute.sh' ,
+        arguments => $predeploy_customcommand ,
+        user      => $predeploy_real_user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+      puppi::rollback { "${name}-Recover_Files_To_Deploy":
+        priority  => '40' ,
+        command   => 'archive.sh' ,
+        arguments => "-r ${deploy_root} -t war -o '${backup_rsync_options}'" ,
+        user      => $user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+
+    if ($postdeploy_customcommand != '') {
+      puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+        priority  => $postdeploy_priority ,
+        command   => 'execute.sh' ,
+        arguments => $postdeploy_customcommand ,
+        user      => $postdeploy_real_user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($init_script != '') {
+      puppi::rollback { "${name}-Service_start":
+        priority  => '42' ,
+        command   => 'service.sh' ,
+        arguments => "start ${init_script}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($disable_services != '') {
+      puppi::rollback { "${name}-Enable_extra_services":
+        priority  => '44' ,
+        command   => 'service.sh' ,
+        arguments => "start ${disable_services}" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($bool_check_deploy == true) {
+      puppi::rollback { "${name}-Check_deploy":
+        priority  => '45' ,
+        command   => 'checkwardir.sh' ,
+        arguments => "-p ${deploy_root}/${war_file}" ,
+        user      => $user ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($firewall_src_ip != '') {
+      puppi::rollback { "${name}-Load_Balancer_Unblock":
+        priority  => '46' ,
+        command   => 'firewall.sh' ,
+        arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+        user      => 'root',
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+
+    if ($bool_run_checks == true) {
+      puppi::rollback { "${name}-Run_POST-Checks":
+        priority  => '80' ,
+        command   => 'check_project.sh' ,
+        arguments => $name ,
+        user      => 'root' ,
+        project   => $name ,
+        enable    => $enable ,
+      }
+    }
+  }
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/y4maven.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,723 @@
+# = Define puppi::project::y4maven
+#
+# This is a shortcut define to build a puppi project for the
+# deploying hybris-production-zips via Maven and published on
+# a repository like artifactory.
+#
+# It uses different "core" defines (puppi::project, puppi:deploy (many),
+# puppi::rollback (many)) to build a full featured template project for
+# automatic deployments.
+# If you need to customize it, either change the template defined here or
+# build up your own custom ones.
+#
+# == Variables:
+#
+# [*source*]
+#   The full URL of the maven-metadata.xml file to retrieve.
+#   Format should be in URI standard (http:// file:// ssh:// rsync://).
+#
+# [*http_password*]
+#   The http_password to use for authentication to the source in case of http.
+#
+# [*http_user*]
+#   The http_user to use for authentication to the source in case of http.
+#
+# [*artifact_type*]
+#   The artifact_type to parse the maven-metadata.xml. Either "release" or "latest"
+#   Default is "release". With artifactory, don't use the
+#   "Maven Snapshot Version Behavior" "unique" for your repository.
+#
+# [*deploy_root*]
+#   The destination directory where file(s) are deployed.
+#
+# [*user*]
+#   (Optional) - The user to be used for deploy operations.
+#
+# [*war_suffix*]
+#   (Optional) - The suffix (Maven qualifier) that might be appended to the war
+#
+# [*zip_suffix*]
+#   (Optional) - The suffix (Maven qualifier) that might be appended to the zip
+#
+# [*jar_root*]
+#   (Optional) - The destination directory where the jar is copied.
+#   If set a jar file is searched in Maven
+#
+# [*jar_user*]
+#   (Optional) - The user to be used for deploy operations of the jar
+#   (owner of the files deployed in $jar_root)
+#
+# [*jar_suffix*]
+#   (Optional) - The suffix (Maven qualifier) that might be appended to the jar
+#
+# [*document_root*]
+#   (Optional) - The destination directory where the eventual tarball generated
+#   via Maven containing static files ("src tar") is unpacked
+#
+# [*document_suffix*]
+#   (Optional) - The suffix (Maven qualifier) that might be appended to the
+#   static files tarballs ("src tar")
+#
+# [*document_init_source*]
+#   (Optional) - The full URL to be used to retrieve, for the first time, the
+#    project files present in the source tarball. They are copied to the
+#    $document_root. Format should be in URI standard (http:// file:// ...)
+#
+# [*document_user*]
+#   (Optional) - The user to be used for deploy operations of the tarball
+#   (owner of the files in $document_root)
+#
+# [*config_root*]
+#   (Optional) - The destination directory where the cfg tar is unpacked
+#
+# [*config_suffix*]
+#   (Optional) - The suffix (Maven qualifier) that might be appended to
+#   configuration tarballs ("cfg tar")
+#
+# [*config_init_source*]
+#   (Optional) - The full URL to be used to retrieve, for the first time, the
+#   project files present in the cfg tar. They are copied to the $config_root.
+#   Format should be in URI standard (http:// file:// ssh:// svn://)
+#
+# [*config_user*]
+#   (Optional) - The user to be used for deploy operations of cfg tar
+#   (owner of the files in $config_root)
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*init_script*]
+#   (Optional - Obsolete) - The name (ex: tomcat) of the init script of your
+#   Application server. If you define it, the AS is stopped and then started
+#   during deploy. This option is deprecated, you can use $disable_services
+#   for the same functionality
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*backup_rsync_options*]
+#   (Optional) - The extra options to pass to rsync for backup operations. Use
+#   it, for example, to exclude directories that you don't want to archive.
+#   IE: "--exclude .snapshot --exclude cache --exclude www/cache".
+#
+# [*backup_retention*]
+#   (Optional) - Number of backup archives to keep. (Default 5).
+#   Lower the default value if your backups are too large and may fill up the
+#   filesystem.
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*always_deploy*]
+#   (Optional) - If you always deploy what has been downloaded. Default="yes",
+#   if set to "no" a checksum is made between the files previously downloaded
+#   and the new files. If they are the same the deploy is not done.
+#
+# [*check_deploy*]
+#   (Optional) - Checks if the war is deployed (Default yes). Set to no if
+#   you deploy on Jboss or the deployed dir is different for the war filename
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::y4maven (
+  $source,
+  $http_user                = '',
+  $http_password            = '',
+  $artifact_type            = 'release',
+  $deploy_root              = '',
+  $user                     = 'root',
+  $war_suffix               = 'suffixnotset',
+  $zip_suffix               = 'suffixnotset',
+  $jar_root                 = '',
+  $jar_user                 = '',
+  $jar_suffix               = 'suffixnotset',
+  $document_root            = '',
+  $document_user            = '',
+  $document_suffix          = 'suffixnotset',
+  $document_init_source     = '',
+  $config_root              = '',
+  $config_user              = '',
+  $config_suffix            = 'suffixnotset',
+  $config_init_source       = '',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $init_script              = '',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $backup_rsync_options     = '--exclude .snapshot',
+  $backup_retention         = '5',
+  $run_checks               = true,
+  $always_deploy            = true,
+  $check_deploy             = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => $user,
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => $user,
+    default => $postdeploy_user,
+  }
+
+  $config_real_user = $config_user ? {
+    ''      => $user,
+    default => $config_user,
+  }
+
+  $document_real_user = $document_user ? {
+    ''      => $user,
+    default => $document_user,
+  }
+
+  $jar_real_user = $jar_user ? {
+    ''      => $user,
+    default => $jar_user,
+  }
+
+  $real_always_deploy = any2bool($always_deploy) ? {
+    false   => 'no',
+    true    => 'yes',
+  }
+
+  $bool_run_checks = any2bool($run_checks)
+  $bool_check_deploy = any2bool($check_deploy)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+
+### INIT SEQUENCE
+  if ($document_init_source != '') {
+    puppi::initialize { "${name}-Deploy_Files":
+      priority  => '40' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${document_init_source} -d ${deploy_root}" ,
+      user      => $document_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($config_init_source != '') {
+    puppi::initialize { "${name}-Deploy_CFG_Files":
+      priority  => '40' ,
+      command   => 'get_file.sh' ,
+      arguments => "-s ${config_init_source} -d ${deploy_root}" ,
+      user      => $config_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # First: hybrisServer-Platform
+    $platform_metadata_arguments = $http_password ? {
+      '' => "-s ${source}/hybrisServer-Platform/maven-metadata.xml -t maven-metadata -a ${real_always_deploy}" ,
+      default => "-s ${source}/hybrisServer-Platform/maven-metadata.xml -t maven-metadata -a ${real_always_deploy} -u ${http_user} -p ${http_password}"
+    }
+
+    puppi::deploy { "${name}-Get_Maven_Metadata_hybrisServer-Platform_File":
+      priority  => '20' ,
+      command   => 'get_file.sh' ,
+      arguments => $platform_metadata_arguments,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+    puppi::deploy { "${name}-Extract_Maven_Metadata_hybrisServer-Platform":
+      priority  => '21' ,
+      command   => 'get_metadata.sh' ,
+      arguments => "-m ${document_suffix} -mc ${config_suffix} -mj ${jar_suffix} -mw ${war_suffix} -mz ${zip_suffix} -at ${artifact_type}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  # Files retrieval
+  $platform_zipfile_arguments = $http_password ? {
+    ''      => "${source}/hybrisServer-Platform zipfile",
+    default => "-u ${http_user} -p ${http_password} ${source}/hybrisServer-Platform zipfile",
+  }
+
+  if ($deploy_root != '') {
+    puppi::deploy { "${name}-Get_Maven_Files_ZIP_hybrisServer-Platform":
+      priority  => '22' ,
+      command   => 'get_maven_files.sh' ,
+      arguments => $platform_zipfile_arguments,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Second: hybrisServer-AllExtensions
+    $extensions_metadata_arguments = $http_password ? {
+      ''      => "-s ${source}/hybrisServer-AllExtensions/maven-metadata.xml -t maven-metadata -a ${real_always_deploy}",
+      default => "-s ${source}/hybrisServer-AllExtensions/maven-metadata.xml -t maven-metadata -a ${real_always_deploy} -u ${http_user} -p ${http_password}",
+    }
+
+    puppi::deploy { "${name}-Get_Maven_Metadata_hybrisServer-AllExtensions_File":
+      priority  => '23' ,
+      command   => 'get_file.sh' ,
+      arguments => $extensions_metadata_arguments,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+    puppi::deploy { "${name}-Extract_Maven_Metadata_hybrisServer-AllExtensions":
+      priority  => '24' ,
+      command   => 'get_metadata.sh' ,
+      arguments => "-m ${document_suffix} -mc ${config_suffix} -mj ${jar_suffix} -mw ${war_suffix} -mz ${zip_suffix} -at ${artifact_type}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  # Files retrieval
+  if ($deploy_root != '') {
+    $extensions_zipfile_arguments = $http_password ? {
+      ''      => "${source}/hybrisServer-AllExtensions zipfile",
+      default => "-u ${http_user} -p ${http_password} ${source}/hybrisServer-AllExtensions zipfile",
+    }
+
+    puppi::deploy { "${name}-Get_Maven_Files_ZIP_hybrisServer-AllExtensions":
+      priority  => '25' ,
+      command   => 'get_maven_files.sh' ,
+      arguments => $extensions_zipfile_arguments,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+  if ($config_root != '') {
+    # Third: config-tarball (optional, right now not supported)
+    $config_metadata_arguments = $http_password ? {
+      ''      => "-s ${source}/config/maven-metadata.xml -t maven-metadata -a ${real_always_deploy}",
+      default => "-s ${source}/config/maven-metadata.xml -t maven-metadata -a ${real_always_deploy} -u ${http_user} -p ${http_password}"
+    }
+
+    puppi::deploy { "${name}-Get_Maven_Metadata_config-tarball_File":
+      priority  => '26' ,
+      command   => 'get_file.sh' ,
+      arguments => $config_metadata_arguments,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+    puppi::deploy { "${name}-Extract_Maven_Metadata_config-tarball":
+      priority  => '27' ,
+      command   => 'get_metadata.sh' ,
+      arguments => "-m ${document_suffix} -mc ${config_suffix} -mj ${jar_suffix} -mw ${war_suffix} -mz ${zip_suffix} -at ${artifact_type}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+    puppi::deploy { "${name}-Get_Maven_Files_Config":
+      priority  => '28' ,
+      command   => 'get_maven_files.sh' ,
+      arguments => "${source} configfile" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '30' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  # Existing files backup
+  if ($deploy_root != '') {
+    puppi::deploy { "${name}-Backup_Existing_WAR":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${deploy_root} -t war -s move -m diff -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($jar_root != '') {
+    puppi::deploy { "${name}-Backup_Existing_JAR":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${jar_root} -t jar -s move -m diff -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($config_root != '') {
+    puppi::deploy { "${name}-Backup_Existing_ConfigDir":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${config_root} -t config -d predeploydir_configfile -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($document_root != '') {
+    puppi::deploy { "${name}-Backup_Existing_DocumentDir":
+      priority  => '30' ,
+      command   => 'archive.sh' ,
+      arguments => "-b ${document_root} -t docroot -d predeploydir_configfile -o '${backup_rsync_options}' -n ${backup_retention}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  # Deploys
+  if ($deploy_root != '') {
+    puppi::deploy { "${name}-Deploy_Maven_ZIP":
+      priority  => '40' ,
+      command   => 'deploy.sh' ,
+      arguments => "${deploy_root} predeploydir_zipfile ",
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($config_root != '') {
+    puppi::deploy { "${name}-Deploy_ConfigDir":
+      priority  => '40' ,
+      command   => 'deploy.sh' ,
+      arguments => "${config_root} predeploydir_configfile" ,
+      user      => $config_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  puppi::deploy { "${name}-yant":
+    priority  => '42' ,
+    command   => 'yant.sh' ,
+    arguments => "${deploy_root} clean all" ,
+    user      => $user ,
+    project   => $name ,
+    enable    => $enable ,
+  }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::deploy { "${name}-Service_start":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '45' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '47' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Disable_extra_services":
+      priority  => '37' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::rollback { "${name}-Service_stop":
+      priority  => '38' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($deploy_root != '') {
+    puppi::rollback { "${name}-Recover_ZIP":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${deploy_root} -t zip -o '${backup_rsync_options}'" ,
+      user      => $user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($config_root != '') {
+    puppi::rollback { "${name}-Recover_ConfigDir":
+      priority  => '40' ,
+      command   => 'archive.sh' ,
+      arguments => "-r ${config_root} -t config -o '${backup_rsync_options}'" ,
+      user      => $config_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($init_script != '') {
+    puppi::rollback { "${name}-Service_start":
+      priority  => '42' ,
+      command   => 'service.sh' ,
+      arguments => "start ${init_script}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::rollback { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/project/yum.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,347 @@
+# = Define puppi::project::yum
+#
+# This is a shortcut define to build a puppi project for the
+# deploy of applications packaged as rpm and retrievable via yum
+#
+# It uses different "core" defines (puppi::project, puppi:deploy (many),
+# puppi::rollback (many)) to build a full featured template project for
+# automatic deployments.
+# If you need to customize it, either change the template defined here or
+# build up your own custom ones.
+#
+# == Variables:
+#
+# [*rpm*]
+#   The name of the rpm to install
+#
+# [*rpm_version*]
+#   (Optional) - The version to install (default: latest)
+#
+# [*install_root*]
+#   (Optional) - The rpm installation root (default: / )
+#
+# [*predeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute before the deploy. The command is executed as $predeploy_user.
+#
+# [*predeploy_user*]
+#   (Optional) - The user to be used to execute the $predeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*predeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $predeploy_customcommand is executed
+#   Default: 39 (immediately before the copy of files on the deploy root).
+#
+# [*postdeploy_customcommand*]
+#   (Optional) -  Full path with arguments of an eventual custom command to
+#   execute after the deploy. The command is executed as $postdeploy_user.
+#
+# [*postdeploy_user*]
+#   (Optional) - The user to be used to execute the $postdeploy_customcommand.
+#   By default is the same of $user.
+#
+# [*postdeploy_priority*]
+#   (Optional) - The priority (execution sequence number) that defines when,
+#   during the deploy procedure, the $postdeploy_customcommand is executed
+#   Default: 41 (immediately after the copy of files on the deploy root).
+#
+# [*disable_services*]
+#   (Optional) - The names (space separated) of the services you might want to
+#   stop during deploy. By default is blank. Example: "apache puppet monit".
+#
+# [*firewall_src_ip*]
+#   (Optional) - The IP address of a loadbalancer you might want to block out
+#   during a deploy.
+#
+# [*firewall_dst_port*]
+#   (Optional) - The local port to block from the loadbalancer during deploy
+#   (Default all).
+#
+# [*firewall_delay*]
+#   (Optional) - A delay time in seconds to wait after the block of
+#   $firewall_src_ip. Should be at least as long as the loadbalancer check
+#   interval for the services stopped during deploy (Default: 1).
+#
+# [*report_email*]
+#   (Optional) - The (space separated) email(s) to notify of deploy/rollback
+#   operations. If none is specified, no email is sent.
+#
+# [*run_checks*]
+#   (Optional) - If you want to run local puppi checks before and after the
+#   deploy procedure. Default: "true".
+#
+# [*checks_required*]
+#   (Optional) - Set to "true" if you want to block the installation if
+#   preliminary checks fail. Default: "false"
+#
+# [*always_deploy*]
+#   (Optional) - If you always deploy what has been downloaded. Default="yes",
+#   if set to "no" a checksum is made between the files previously downloaded
+#   and the new files. If they are the same the deploy is not done.
+#
+# [*auto_deploy*]
+#   (Optional) - If you want to automatically run this puppi deploy when
+#   Puppet runs. Default: 'false'
+#
+define puppi::project::yum (
+  $rpm,
+  $rpm_version              = 'latest',
+  $install_root             = '/',
+  $predeploy_customcommand  = '',
+  $predeploy_user           = '',
+  $predeploy_priority       = '39',
+  $postdeploy_customcommand = '',
+  $postdeploy_user          = '',
+  $postdeploy_priority      = '41',
+  $disable_services         = '',
+  $firewall_src_ip          = '',
+  $firewall_dst_port        = '0',
+  $firewall_delay           = '1',
+  $report_email             = '',
+  $run_checks               = true,
+  $checks_required          = false,
+  $always_deploy            = true,
+  $auto_deploy              = false,
+  $enable                   = true ) {
+
+  require puppi
+  require puppi::params
+
+  # Set default values
+  $predeploy_real_user = $predeploy_user ? {
+    ''      => 'root',
+    default => $predeploy_user,
+  }
+
+  $postdeploy_real_user = $postdeploy_user ? {
+    ''      => 'root',
+    default => $postdeploy_user,
+  }
+
+  $real_always_deploy = any2bool($always_deploy) ? {
+    true    => 'yes',
+    default => 'no',
+  }
+
+  $real_checks_required = any2bool($checks_required) ? {
+    true    => 'yes',
+    default => 'no',
+  }
+
+  $bool_run_checks = any2bool($run_checks)
+  $bool_auto_deploy = any2bool($auto_deploy)
+
+### CREATE PROJECT
+    puppi::project { $name:
+      enable => $enable ,
+    }
+
+### DEPLOY SEQUENCE
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_PRE-Checks":
+      priority  => '10' ,
+      command   => 'check_project.sh' ,
+      arguments => "${name} ${real_checks_required}",
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Disable_extra_services":
+      priority  => '36' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    # Here is done the deploy on $deploy_root
+    puppi::deploy { "${name}-Deploy":
+      priority  => '40' ,
+      command   => 'yum.sh' ,
+      arguments => "-a deploy -n ${rpm} -r ${install_root} -v ${rpm_version}" ,
+      user      => root ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::deploy { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::deploy { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::deploy { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::deploy { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### ROLLBACK PROCEDURE
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Block":
+      priority  => '25' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} on ${firewall_delay}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Disable_extra_services":
+      priority  => '37' ,
+      command   => 'service.sh' ,
+      arguments => "stop ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($predeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PreDeploy_Script":
+      priority  => $predeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $predeploy_customcommand ,
+      user      => $predeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+    puppi::rollback { "${name}-Rollback":
+      priority  => '40' ,
+      command   => 'yum.sh' ,
+      arguments => "-a rollback -n ${rpm} -r ${install_root} -v ${rpm_version}" ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+
+  if ($postdeploy_customcommand != '') {
+    puppi::rollback { "${name}-Run_Custom_PostDeploy_Script":
+      priority  => $postdeploy_priority ,
+      command   => 'execute.sh' ,
+      arguments => $postdeploy_customcommand ,
+      user      => $postdeploy_real_user ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($disable_services != '') {
+    puppi::rollback { "${name}-Enable_extra_services":
+      priority  => '44' ,
+      command   => 'service.sh' ,
+      arguments => "start ${disable_services}" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($firewall_src_ip != '') {
+    puppi::rollback { "${name}-Load_Balancer_Unblock":
+      priority  => '46' ,
+      command   => 'firewall.sh' ,
+      arguments => "${firewall_src_ip} ${firewall_dst_port} off 0" ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+  if ($bool_run_checks == true) {
+    puppi::rollback { "${name}-Run_POST-Checks":
+      priority  => '80' ,
+      command   => 'check_project.sh' ,
+      arguments => $name ,
+      user      => 'root' ,
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+
+### REPORTING
+
+  if ($report_email != '') {
+    puppi::report { "${name}-Mail_Notification":
+      priority  => '20' ,
+      command   => 'report_mail.sh' ,
+      arguments => $report_email ,
+      user      => 'root',
+      project   => $name ,
+      enable    => $enable ,
+    }
+  }
+
+### AUTO DEPLOY DURING PUPPET RUN
+  if ($bool_auto_deploy == true) {
+    puppi::run { $name: }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/report.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,38 @@
+# Define puppi::report
+#
+# This define creates a file with a report command that can be used locally.
+#
+# Usage:
+# puppi::report { "Retrieve files":
+#   command  => "report_mail.sh",
+#   argument => "roots@example42.com",
+#   priority => "10",
+#   user   => "root",
+#   project  => "spysite",
+# }
+#
+define puppi::report (
+  $project,
+  $command,
+  $arguments = '',
+  $priority  = '50',
+  $user      = 'root',
+  $enable    = true ) {
+
+  require puppi::params
+
+  # Autoinclude the puppi class
+  include puppi
+
+  $ensure = bool2ensure($enable)
+
+  file { "${puppi::params::projectsdir}/${project}/report/${priority}-${name}":
+    ensure  => $ensure,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    content => "su - ${user} -c \"export project=${project} && ${puppi::params::scriptsdir}/${command} ${arguments}\"\n",
+    tag     => 'puppi_report',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/rollback.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+# Define puppi::rollback
+#
+# This define creates a file with a rollback command that can be used locally.
+#
+# Usage:
+# puppi::rollback { "Retrieve files":
+#   command  => "get_file.sh",
+#   argument => "/remote/dir/file",
+#   priority => "10",
+#   user   => "root",
+#   project  => "spysite",
+# }
+#
+define puppi::rollback (
+  $project,
+  $command,
+  $arguments = '',
+  $priority  = '50',
+  $user      = 'root',
+  $enable    = true ) {
+
+  require puppi
+  require puppi::params
+
+  $ensure = bool2ensure($enable)
+
+  file { "${puppi::params::projectsdir}/${project}/rollback/${priority}-${name}":
+    ensure  => $ensure,
+    mode    => '0750',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    content => "su - ${user} -c \"export project=${project} && ${puppi::params::scriptsdir}/${command} ${arguments}\"\n",
+    tag     => 'puppi_rollback',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/run.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+# Define puppi::run
+#
+# This define triggers a puppi deploy run directly during Puppet
+# execution. It can be used to automate FIRST TIME applications
+# deployments directly during the first Puppet execution
+#
+# == Variables
+#
+# [*name*]
+#   The title/name you use has to be the name of an existing puppi::project
+#   procedure define
+#
+# == Usage
+# Basic Usage:
+# puppi::run { "myapp": }
+#
+define puppi::run (
+  $project = '',
+  $timeout = 300) {
+
+  require puppi
+
+  exec { "Run_Puppi_${name}":
+    command => "puppi deploy ${name}; [ $? -le \"1\" ] && touch ${puppi::params::archivedir}/puppirun_${name}",
+    path    => '/bin:/sbin:/usr/sbin:/usr/bin',
+    creates => "${puppi::params::archivedir}/puppirun_${name}",
+    timeout => $timeout,
+    # require => File[ tag == 'puppi_deploy' ],
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/runscript.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,154 @@
+# = Define: puppi::runscript
+#
+# This define creates, executes and optionally crontabs a
+# simple whose content is directly managed by arguments.
+# The script content is provided either with $source or $content arguments.
+# It's placed in:
+# $destination_path , if provided, or in /usr/local/sbin/${name}
+#
+# Cron execution times are defined by the $cron argument (Default empty).
+# Automatic execution of the script via Puppet is managed by the $autorun
+# parameter (default: true).
+# Conditional execution of the script at subsequent puppet runs is
+# defined by the $refreshonly, $creates, $unless $onlyif parameters
+# that map the omonimous exec type arguments.
+#
+# == Parameters:
+#
+# [*source*]
+#   String. Optional. Default: undef. Alternative to content.
+#   Source of the script file to provide for execuution.
+#   Sample: source => 'puppet:///modules/site/scripts/my_script',
+#
+# [*content*]
+#   String. Optional. Default: undef. Alternative to source.
+#   Content of the script file to provide for execuution.
+#   This parameter is alternative to source.
+#   Sample: content => 'template(site/scripts/my_script.erb'),
+#
+# [*destination_path*]
+#   String. Optional. Default: ''
+#   Path of the provided script. If not provided the script in saved in
+#   /usr/local/sbin/${name}
+#
+# [*parameters*]
+#   String. Optional. Default: ''
+#   Optional parameters to pass to the script when executing it.
+#
+# [*autorun*]
+#   Boolean. Default: true.
+#   Define if to automatically execute the script when Puppet runs.
+#
+# [*refreshonly*]
+#   Boolen. Optional. Default: true
+#   Defines the logic of execution of the script when Puppet runs.
+#   Maps to the omonymous Exec type argument.
+#
+# [*creates*]
+#   String. Optional. Default: undef
+#   Defines the logic of execution of the script when Puppet runs.
+#   Maps to the omonymous Exec type argument.
+#
+# [*onlyif*]
+#   String. Optional. Default: undef
+#   Defines the logic of execution of the script when Puppet runs.
+#   Maps to the omonymous Exec type argument.
+#
+# [*unless*]
+#   String. Optional. Default: undef
+#   Defines the logic of execution of the script when Puppet runs.
+#   Maps to the omonymous Exec type argument.
+#
+# [*basedir*]
+#   String. Optional. Default: /usr/local/sbin
+#   Directory where the runscript scripts are created when destination_path
+#   is empty.
+#
+# [*cron*]
+#   String. Optional. Default: ''
+#   Optional cron schedule to crontab the execution of the
+#   script. Format must be in standard cron style.
+#   Example: '0 4 * * *' .
+#   By default no cron is scheduled.
+#
+# [*cron_user*]
+#   String. Optional. Default: 'root'
+#   When cron is enabled the user that executes the cron job.
+#
+# [*owner*]
+#   Owner of the created script. Default: root.
+#
+# [*group*]
+#   Group of the created script. Default: root.
+#
+# [*mode*]
+#   Mode of the created script. Default: '7550'.
+#   NOTE: Keep the execution flag!
+#
+# [*ensure*]
+#   Define if the runscript script and eventual cron job
+#   must be present or absent. Default: present.
+#
+# == Examples
+#
+# - Minimal setup
+# puppi::runscript { 'my_script':
+#   source           => 'puppet:///modules/site/scripts/my_script.sh',
+#   destination_path => '/usr/local/bin/my_script.sh',
+# }
+#
+define puppi::runscript (
+  $source           = undef,
+  $content          = undef,
+  $destination_path = '',
+  $parameters       = '',
+  $autorun          = true,
+  $refreshonly      = true,
+  $creates          = undef,
+  $onlyif           = undef,
+  $unless           = undef,
+  $basedir          = '/usr/local/sbin',
+  $cron             = '',
+  $cron_user        = 'root',
+  $owner            = 'root',
+  $group            = 'root',
+  $mode             = '0755',
+  $ensure           = 'present' ) {
+
+  $real_command = $destination_path ? {
+    ''      => "${basedir}/${name}",
+    default => $destination_path,
+  }
+
+  file { "runscript_${name}":
+    ensure  => $ensure,
+    path    => $real_command,
+    mode    => $mode,
+    owner   => $owner,
+    group   => $group,
+    content => $content,
+    source  => $source,
+  }
+
+  if $autorun == true {
+    exec { "runscript_${name}":
+      command     => $real_command,
+      refreshonly => $refreshonly,
+      creates     => $creates,
+      onlyif      => $onlyif,
+      unless      => $unless,
+      subscribe   => File["runscript_${name}"],
+    }
+  }
+
+  if $cron != '' {
+    file { "runscript_cron_${name}":
+      ensure  => $ensure,
+      path    => "/etc/cron.d/runscript_${name}",
+      mode    => '0644',
+      owner   => 'root',
+      group   => 'root',
+      content => "${cron} ${cron_user} ${real_command} ${parameters}\n",
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/skel.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,184 @@
+#
+# Class puppi::skel
+#
+# Creates the base Puppi dirs
+#
+class puppi::skel {
+
+  require puppi::params
+
+  file { 'puppi_basedir':
+    ensure => directory,
+    path   => $puppi::params::basedir,
+    mode   => '0755',
+    owner  => $puppi::params::configfile_owner,
+    group  => $puppi::params::configfile_group,
+  }
+
+  file { 'puppi_checksdir':
+    ensure  => directory,
+    path    => $puppi::params::checksdir,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_basedir'],
+    recurse => true,
+    purge   => true,
+    force   => true,
+  }
+
+  file { 'puppi_logsdir':
+    ensure  => directory,
+    path    => $puppi::params::logsdir,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_basedir'],
+    recurse => true,
+    purge   => true,
+    force   => true,
+  }
+
+  file { 'puppi_helpersdir':
+    ensure  => directory,
+    path    => $puppi::params::helpersdir,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_basedir'],
+  }
+
+  file { 'puppi_infodir':
+    ensure  => directory,
+    path    => $puppi::params::infodir,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_basedir'],
+    recurse => true,
+    purge   => true,
+    force   => true,
+  }
+
+  file { 'puppi_tododir':
+    ensure  => directory,
+    path    => $puppi::params::tododir,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_basedir'],
+    recurse => true,
+    purge   => true,
+    force   => true,
+  }
+
+  file { 'puppi_projectsdir':
+    ensure  => directory,
+    path    => $puppi::params::projectsdir,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_basedir'],
+    recurse => true,
+    purge   => true,
+    force   => true,
+  }
+
+  file { 'puppi_datadir':
+    ensure  => directory,
+    path    => $puppi::params::datadir,
+    mode    => '0750',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_basedir'],
+    recurse => true,
+    purge   => true,
+    force   => true,
+  }
+
+  file { 'puppi_workdir':
+    ensure  => directory,
+    path    => $puppi::params::workdir,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_basedir'],
+  }
+
+  file { 'puppi_archivedir':
+    ensure  => directory,
+    path    => $puppi::params::archivedir,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_libdir'],
+  }
+
+  file { 'puppi_readmedir':
+    ensure  => directory,
+    path    => $puppi::params::readmedir,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_libdir'],
+  }
+
+  file { 'puppi_libdir':
+    ensure  => directory,
+    path    => $puppi::params::libdir,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_basedir'],
+  }
+
+  file { 'puppi_logdir':
+    ensure  => directory,
+    path    => $puppi::params::logdir,
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => File['puppi_basedir'],
+  }
+
+  # MailPuppiCheck script
+  file { '/usr/bin/mailpuppicheck':
+    ensure => 'present',
+    mode   => '0750',
+    owner  => $puppi::params::configfile_owner,
+    group  => $puppi::params::configfile_group,
+    source => 'puppet:///modules/puppi/mailpuppicheck',
+  }
+
+  # Puppi common scripts
+  file { 'puppi.scripts':
+    ensure  => present,
+    path    => "${puppi::params::scriptsdir}/",
+    mode    => '0755',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    source  => 'puppet:///modules/puppi/scripts/',
+    recurse => true,
+#   purge   => true,
+    ignore  => '.svn',
+  }
+
+  # Logs cleanup script
+  if $::kernel == 'Linux' {
+    if $puppi::logs_retention_days
+    and $puppi::logs_retention_days != '0' {
+      $purge_cron_ensure = 'present'
+    } else {
+      $purge_cron_ensure = 'absent'
+    }
+
+    file { 'puppi_cron_logs_purge':
+      ensure  => $purge_cron_ensure,
+      path    => '/etc/cron.daily/puppi_clean',
+      mode    => '0755',
+      owner   => 'root',
+      group   => 'root',
+      content => template('puppi/puppi_clean.erb'),
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/todo.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,57 @@
+# Define puppi::todo
+#
+# This define creates a basic todo file that simply contains informations
+# on how to complete tasks that for time or other reasons could not be
+# entirely automated by Puppet.
+# The basic idea is to have a quick way to document and check if are completed
+# some specific operations that are required to bring a new, puppettized system
+# to full operative status.
+# This can be useful for cases hard to automate with Puppet:
+# - First setup and import of a database needed by an application (module)
+# - Installation of a legacy application that involves user interaction
+# - Run of any kind of setup/configuration/init command that can't be automated
+# It can also be used as a quick reminder on things done by hand and not
+# Puppettized for lack of time or skill.
+#
+# Use the command puppi todo to show the todo present in your node.
+# The exit status can be:
+# 0 - OK - The task to do has been accomplished because the command specified
+#    as check_command returns true (exit status 0)
+# 1- WARNING - User hasn't specified a check_command to verify if the todo as
+#    been accomplished, so it can't be notified if the todo has been done
+# 2- ERROR - The task to do has not been accomplished becuase the command
+#    specified as check_command returns an error (exit status different from 0)
+#
+# == Usage:
+# puppi::todo { "cacti_db_install":
+#   description => "Manual cacti db installation" ,
+# }
+#
+define puppi::todo (
+  $description   = '',
+  $notes         = '',
+  $check_command = '',
+  $run           = '' ) {
+
+  require puppi
+  require puppi::params
+
+  $array_run = is_array($run) ? {
+    false     => $run ? {
+      ''      => [],
+      default => split($run, ','),
+    },
+    default   => $run,
+  }
+
+  file { "${puppi::params::tododir}/${name}":
+    ensure  => present,
+    mode    => '0750',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    require => Class['puppi'],
+    content => template('puppi/todo.erb'),
+    tag     => 'puppi_todo',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/two.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+# Class: puppi::two
+#
+# Installs Puppi NextGen
+#
+class puppi::two {
+
+  # The Puppi command
+  package { 'puppi':
+    ensure   => present,
+    provider => 'gem',
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/manifests/ze.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+# Define puppi::ze
+#
+# The Puppi 2.0 define that transforms any class variable in data
+# you can use with Puppi
+#
+# == Usage
+# Basic Usage:
+# puppi::ze { "openssh":
+#   variables => get_class_args(),
+# }
+#
+# puppi::ze { "openssh":
+#   variables => get_class_args(),
+#   filter    => '.*content.*|.*key.*',
+# }
+#
+define puppi::ze (
+  $variables,
+  $helper = 'standard',
+  $filter = '.*content.*|.*password.*',
+  $ensure = 'present' ) {
+
+  require puppi
+  require puppi::params
+
+  file { "puppize_${name}":
+    ensure  => $ensure,
+    path    => "${puppi::params::datadir}/${helper}_${name}.yml",
+    mode    => '0644',
+    owner   => $puppi::params::configfile_owner,
+    group   => $puppi::params::configfile_group,
+    content => inline_template("---\n<%= Hash[@variables].reject{ |k,v| k.to_s =~ /(${filter})/ }.keys.sort.map{|k| Array({k => @variables[k]}.to_yaml)[1..-1].join}.join(\"\n\") %>\n"),
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/classes/puppi_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe 'puppi' do
+
+  let(:node) { 'rspec.example42.com' }
+  let(:node) { 'rspec.example42.com' }
+  let(:facts) { { :ipaddress => '10.42.42.42' } }
+
+  describe 'Test standard installation' do
+    it { should contain_file('puppi').with_ensure('present') }
+    it { should contain_file('puppi.conf').with_ensure('present') }
+    it { should contain_file('puppi.scripts').with_ensure('present') }
+    it { should contain_file('puppi_basedir').with_ensure('directory') }
+    it { should contain_file('puppi_datadir').with_ensure('directory') }
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_check_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe 'puppi::check' do
+
+  let(:title) { 'puppi::check' }
+  let(:node) { 'rspec.example42.com' }
+  let(:facts) { { :arch => 'i386' } }
+  let(:params) {
+    { 'enable'   =>  'true',
+      'name'     =>  'get',
+      'command'  =>  'echo',
+      'priority' =>  '50',
+      'project'  =>  'myapp',
+    }
+  }
+
+  describe 'Test puppi check step file creation' do
+    it 'should create a puppi::check step file' do
+      should contain_file('Puppi_check_myapp_50_get').with_ensure('present')
+    end
+    it 'should populate correctly the puppi::check step file' do
+      should contain_file('Puppi_check_myapp_50_get').with_content(/\/usr\/lib\/nagios\/plugins\/echo/)
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_deploy_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe 'puppi::deploy' do
+
+  let(:title) { 'puppi::deploy' }
+  let(:node) { 'rspec.example42.com' }
+  let(:params) {
+    { 'enable'   =>  'true',
+      'name'     =>  'get',
+      'command'  =>  'echo',
+      'priority' =>  '50',
+      'project'  =>  'myapp',
+    }
+  }
+
+  describe 'Test puppi deploy step file creation' do
+    it 'should create a puppi::deploy step file' do
+      should contain_file('/etc/puppi/projects/myapp/deploy/50-get').with_ensure('present')
+    end
+    it 'should populate correctly the puppi::deploy step file' do
+      should contain_file('/etc/puppi/projects/myapp/deploy/50-get').with_content("su - root -c \"export project=myapp && /etc/puppi/scripts/echo \"\n")
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_helper_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe 'puppi::helper' do
+
+  let(:title) { 'spec' }
+  let(:node) { 'rspec.example42.com' }
+  let(:params) {
+    { 'template'   => 'puppi/helpers/standard.yml.erb'  }
+  }
+
+  describe 'Test puppi helper file creation' do
+    it 'should create a puppi helper file' do
+      should contain_file('puppi_helper_spec').with_ensure('present')
+    end
+    it 'should populate correctly the helper file' do
+      should contain_file('puppi_helper_spec').with_content(/info/)
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_info_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'puppi::info' do
+
+  let(:title) { 'puppi::info' }
+  let(:node) { 'rspec.example42.com' }
+  let(:params) {
+    { 'name'         =>  'sample',
+      'description'  =>  'Sample Info',
+      'templatefile' =>  'puppi/info.erb',
+      'run'          =>  'myownscript',
+    }
+  }
+
+  describe 'Test puppi info step file creation' do
+    it 'should create a puppi::info step file' do
+      should contain_file('/etc/puppi/info/sample').with_ensure('present')
+    end
+    it 'should populate correctly the puppi::info step file' do
+      should contain_file('/etc/puppi/info/sample').with_content(/myownscript/)
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_initialize_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe 'puppi::initialize' do
+
+  let(:title) { 'puppi::initialize' }
+  let(:node) { 'rspec.example42.com' }
+  let(:params) {
+    { 'enable'   =>  'true',
+      'name'     =>  'get',
+      'command'  =>  'echo',
+      'priority' =>  '50',
+      'project'  =>  'myapp',
+    }
+  }
+
+  describe 'Test puppi initialize step file creation' do
+    it 'should create a puppi::initialize step file' do
+      should contain_file('/etc/puppi/projects/myapp/initialize/50-get').with_ensure('present')
+    end
+    it 'should populate correctly the puppi::initialize step file' do
+      should contain_file('/etc/puppi/projects/myapp/initialize/50-get').with_content("su - root -c \"export project=myapp && /etc/puppi/scripts/echo \"\n")
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_log_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe 'puppi::log' do
+
+  let(:title) { 'mylog' }
+  let(:node) { 'rspec.example42.com' }
+  let(:params) {
+    { 'log'         =>  '/var/log/mylog.log',
+      'description' =>  'My Log',
+    }
+  }
+
+  describe 'Test puppi log file creation' do
+    it 'should create a puppi::log file' do
+      should contain_file('/etc/puppi/logs/mylog').with_ensure('present')
+    end
+    it 'should populate correctly the puppi::log step file' do
+      should contain_file('/etc/puppi/logs/mylog').with_content(/mylog.log/)
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_project_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe 'puppi::report' do
+
+  let(:title) { 'puppi::report' }
+  let(:node) { 'rspec.example42.com' }
+  let(:params) {
+    { 'enable'   =>  'true',
+      'name'     =>  'get',
+      'command'  =>  'echo',
+      'priority' =>  '50',
+      'project'  =>  'myapp',
+    }
+  }
+
+  describe 'Test puppi report step file creation' do
+    it 'should create a puppi::report step file' do
+      should contain_file('/etc/puppi/projects/myapp/report/50-get').with_ensure('present')
+    end
+    it 'should populate correctly the puppi::report step file' do
+      should contain_file('/etc/puppi/projects/myapp/report/50-get').with_content("su - root -c \"export project=myapp && /etc/puppi/scripts/echo \"\n")
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_report_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe 'puppi::report' do
+
+  let(:title) { 'puppi::report' }
+  let(:node) { 'rspec.example42.com' }
+  let(:params) {
+    { 'enable'   =>  'true',
+      'name'     =>  'get',
+      'command'  =>  'echo',
+      'priority' =>  '50',
+      'project'  =>  'myapp',
+    }
+  }
+
+  describe 'Test puppi report step file creation' do
+    it 'should create a puppi::report step file' do
+      should contain_file('/etc/puppi/projects/myapp/report/50-get').with_ensure('present')
+    end
+    it 'should populate correctly the puppi::report step file' do
+      should contain_file('/etc/puppi/projects/myapp/report/50-get').with_content("su - root -c \"export project=myapp && /etc/puppi/scripts/echo \"\n")
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_rollback_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe 'puppi::rollback' do
+
+  let(:title) { 'puppi::rollback' }
+  let(:node) { 'rspec.example42.com' }
+  let(:params) {
+    { 'enable'   =>  'true',
+      'name'     =>  'get',
+      'command'  =>  'echo',
+      'priority' =>  '50',
+      'project'  =>  'myapp',
+    }
+  }
+
+  describe 'Test puppi rollback step file creation' do
+    it 'should create a puppi::rollback step file' do
+      should contain_file('/etc/puppi/projects/myapp/rollback/50-get').with_ensure('present')
+    end
+    it 'should populate correctly the puppi::rollback step file' do
+      should contain_file('/etc/puppi/projects/myapp/rollback/50-get').with_content("su - root -c \"export project=myapp && /etc/puppi/scripts/echo \"\n")
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_run_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe 'puppi::run' do
+
+  let(:title) { 'myapp' }
+  let(:node) { 'rspec.example42.com' }
+  let(:params) {
+    { 
+      'project'  =>  'myapp',
+    }
+  }
+
+  describe 'Test puppi run exe creation' do
+    it { should contain_exec('Run_Puppi_myapp').with_command(/puppi deploy myapp/) }
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_todo_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'puppi::todo' do
+
+  let(:title) { 'mytodo' }
+  let(:node) { 'rspec.example42.com' }
+  let(:params) {
+    { 'notes'         =>  'Test Notes',
+      'description'   =>  'Test Description',
+      'check_command' =>  'check_test',
+      'run'           =>  'test',
+    }
+  }
+
+  describe 'Test puppi todo file creation' do
+    it 'should create a puppi::todo file' do
+      should contain_file('/etc/puppi/todo/mytodo').with_ensure('present')
+    end
+    it 'should populate correctly the puppi::todo step file' do
+      should contain_file('/etc/puppi/todo/mytodo').with_content(/check_test/)
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/defines/puppi_ze_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe 'puppi::ze' do
+
+  let(:title) { 'sample' }
+  let(:node) { 'rspec.example42.com' }
+  let(:params) {
+    { 'helper'     => 'mytest',
+      'variables'  => { 'var1' => 'get', 'var2' => 'got' },
+      'name'       => 'sample',
+    }
+  }
+
+  describe 'Test puppi ze data file creation' do
+    it 'should create a puppi::ze step file' do
+      should contain_file('puppize_sample').with_ensure('present')
+    end
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/functions/any2bool_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe 'any2bool' do
+
+  describe 'Test Any2True' do
+    it { should run.with_params(true).and_return(true) }
+    it { should run.with_params('true').and_return(true) }
+    it { should run.with_params('yes').and_return(true) }
+    it { should run.with_params('y').and_return(true) }
+  end
+
+  describe 'Test Any2false' do
+    it { should run.with_params(false).and_return(false) }
+    it { should run.with_params('false').and_return(false) }
+    it { should run.with_params('no').and_return(false) }
+    it { should run.with_params('n').and_return(false) }
+  end
+
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/functions/bool2ensure_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe 'bool2ensure' do
+
+  describe 'Test true2present' do
+    it { should run.with_params(true).and_return('present') }
+    it { should run.with_params('true').and_return('present') }
+    it { should run.with_params('yes').and_return('present') }
+    it { should run.with_params('y').and_return('present') }
+  end
+
+  describe 'Test false2absent' do
+    it { should run.with_params(false).and_return('absent') }
+    it { should run.with_params('false').and_return('absent') }
+    it { should run.with_params('no').and_return('absent') }
+    it { should run.with_params('n').and_return('absent') }
+  end
+
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/functions/url_parse_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe 'url_parse' do
+
+  describe 'Test Url Components parsing' do
+    it 'should return correct scheme' do
+      should run.with_params('ftp://www.example.com/test','scheme').and_return('ftp') 
+    end
+    it 'should return correct userinfo' do
+      should run.with_params('https://my_user:my_pass@www.example.com:8080/path/to/file.php?id=1&ret=0','userinfo').and_return('my_user:my_pass') 
+    end
+    it 'should return correct user' do
+      should run.with_params('https://my_user:my_pass@www.example.com:8080/path/to/file.php?id=1&ret=0','user').and_return('my_user') 
+    end
+    it 'should return correct password' do
+      should run.with_params('https://my_user:my_pass@www.example.com:8080/path/to/file.php?id=1&ret=0','password').and_return('my_pass') 
+    end
+    it 'should return correct host' do
+      should run.with_params('https://my_user:my_pass@www.example.com:8080/path/to/file.php?id=1&ret=0','host').and_return('www.example.com') 
+    end
+    it 'should return correct port' do
+      should run.with_params('https://my_user:my_pass@www.example.com:8080/path/to/file.php?id=1&ret=0','port').and_return(8080) 
+    end
+    it 'should return correct path' do
+      should run.with_params('https://my_user:my_pass@www.example.com:8080/path/to/file.php?id=1&ret=0','path').and_return('/path/to/file.php') 
+    end
+    it 'should return correct query' do
+      should run.with_params('https://my_user:my_pass@www.example.com:8080/path/to/file.php?id=1&ret=0','query').and_return('id=1&ret=0') 
+    end
+    it 'should return correct filename' do
+      should run.with_params('https://my_user:my_pass@www.example.com:8080/path/to/file.php?id=1&ret=0','filename').and_return('file.php') 
+    end
+    it 'should return correct filetype' do
+      should run.with_params('https://my_user:my_pass@www.example.com:8080/path/to/file.php?id=1&ret=0','filetype').and_return('.php') 
+    end
+    it 'should return correct filedir' do
+      should run.with_params('https://my_user:my_pass@www.example.com:8080/path/to/file.php?id=1&ret=0','filedir').and_return('file') 
+    end
+
+  end
+
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/spec/spec_helper.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+require 'puppetlabs_spec_helper/module_spec_helper'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/helpers/standard.yml.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,49 @@
+---
+:info:
+  -
+    :command: "<%= scope.lookupvar('puppi::params::info_package_query') %> %{package}"
+    :description: "Package info"
+  -
+    :command: "<%= scope.lookupvar('puppi::params::info_package_list') %> %{package} | egrep '(/bin|^/etc|/sbin|log$)'"
+    :description: "Interesting files from package"
+  -
+    :command: "head %{config_file}"
+    :description: "Main configuration file"
+  -
+    :command: "ls -latr %{config_dir}"
+    :description: "Configuration directory"
+  -
+    :command: "ls -latr %{data_dir}"
+    :description: "Data directory"
+  -
+    :command: "ls -latr %{log_dir}"
+    :description: "Logs directory"
+  -
+    :command: "tail %{log_file}"
+    :description: "Latest log entries"
+  -
+    :command: "service %{service status}"
+    :description: "Service status"
+  -
+    :command: "ps -adef | grep %{process} | grep -v grep | head -20"
+    :description: "Running process"
+  -
+    :command: "netstat -natup | grep %{port} | head -20"
+    :description: "Network connections"
+
+:check:
+  -
+    :command: "service %{service} status"
+    :description: "Service status"
+  -
+    :command: "check_tcp %{port}"
+    :description: "Check listening port"
+  -
+    :command: "check_procs c 1: -C %{process}"
+    :description: "Check process"
+
+:log:
+  -
+    :command: "tail -f %{log_file}"
+    :description: "Tailing logs"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/info.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+#!/bin/bash
+# <%= @description %>
+# Script generated by Puppet. It's executed when you run:
+# puppi info <%= @name %>
+#
+# Sources common header for Puppi scripts
+. <%= scope.lookupvar('puppi::params::scriptsdir') %>/header || exit 10
+
+echo_title "$HOSTNAME - <%= @description %>"
+<% @array_run.each do |cmd| %>show_command "<%= cmd %>"
+<% end %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/info/instance.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,89 @@
+#!/bin/bash
+# <%= @description %>
+# Script generated by Puppet. It's executed when you run:
+# puppi info <%= @name %>
+#
+# Sources common header for Puppi scripts
+. <%= scope.lookupvar('puppi::params::scriptsdir') %>/header || exit 10
+
+<% if @configdir != "" -%>
+# Show config info
+echo_title "$HOSTNAME - <%= @name %>: Configurations directory: <%= @configdir %>"
+show_command "ls -latr <%= @configdir %>"
+<% end -%>
+
+<% if @datadir != "" -%>
+# Show data dir
+echo_title "$HOSTNAME - <%= @name %>: Application data are in: <% datadir.each do |item| %><%= item %><% end %>"
+<% @datadir.each do |item| -%>
+show_command "ls -latr <%= item %>"
+<% end -%>
+<% end -%>
+
+<% if @bindir != "" -%>
+# Show bin dir
+echo_title "$HOSTNAME - <%= @name %>: Startup scripts are in: <% bindir.each do |item| %><%= item %><% end %>"
+<% @bindir.each do |item| -%>
+show_command "ls -latr <%= item %>"
+<% end -%>
+<% end -%>
+
+<% if @logdir != "" -%>
+# Show log dir
+echo_title "$HOSTNAME - <%= @name %>: Logs are in: <% logdir.each do |item| %><%= item %><% end %>"
+<% @logdir.each do |item| -%>
+show_command "ls -latr <%= item %>"
+show_command "tail -30 <%= item %>/catalina.out"
+<% end -%>
+<% end -%>
+
+<% if @run != "" -%>
+echo_title "$HOSTNAME - <%= @name %>: Extra info"
+<% @run.each do |cmd| %>show_command "<%= cmd %>"
+<% end -%>
+<% end -%>
+
+
+<% if @servicename != "" -%>
+# Show service info
+echo_title "$HOSTNAME - <%= @name %>: Services: <% @servicename.each do |item| %><%= item %><% end %>"
+<% @servicename.each do |item| -%>
+show_command "/etc/init.d/<%= item %> status"
+<% end -%>
+<% if @verbose == "yes" -%>
+show_command "ps -adef | grep java | grep <%= @processname %>"
+<% else -%>
+show_command "ps -adef | grep java | grep <%= @processname %> | head -20"
+<% end -%>
+<% end -%>
+
+<% if @httpport != "" -%>
+# Show port info
+echo_title "$HOSTNAME - <%= @name %>: httpport - <%= @httpport %>"
+<% if @verbose == "yes" -%>
+show_command "netstat -natup | grep ':<%= @httpport %> '"
+<% else -%>
+show_command "netstat -natup | grep ':<%= @httpport %> ' | head -20"
+<% end -%>
+<% end -%>
+
+<% if @controlport != "" -%>
+# Show port info
+echo_title "$HOSTNAME - <%= @name %>: controlport - <%= @controlport %>"
+<% if @verbose == "yes" -%>
+show_command "netstat -natup | grep ':<%= @controlport %> '"
+<% else -%>
+show_command "netstat -natup | grep ':<%= @controlport %> ' | head -20"
+<% end -%>
+<% end -%>
+
+<% if @ajpport != "" -%>
+# Show port info
+echo_title "$HOSTNAME - <%= @name %>: ajpport - <%= @ajpport %>"
+<% if @verbose == "yes" -%>
+show_command "netstat -natup | grep ':<%= @ajpport %> '"
+<% else -%>
+show_command "netstat -natup | grep ':<%= @ajpport %> ' | head -20"
+<% end -%>
+<% end -%>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/info/module.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,89 @@
+#!/bin/bash
+# <%= @description %>
+# Script generated by Puppet. It's executed when you run:
+# puppi info <%= @name %> 
+#
+# Sources common header for Puppi scripts
+. <%= scope.lookupvar('puppi::params::scriptsdir') %>/header || exit 10
+
+<% if @packagename != "" -%>
+# Show packages info
+echo_title "$HOSTNAME - <%= @name %>: Packages Installed: <% @packagename.each do |item| %><%= item %><% end %>"
+<% @packagename.each do |item| -%>
+show_command "<%= scope.lookupvar('puppi::params::info_package_query') %> <%= item %>"
+<% if @verbose == "yes" -%>
+show_command "<%= scope.lookupvar('puppi::params::info_package_list') %> <%= item %>"
+<% else -%>
+show_command "<%= scope.lookupvar('puppi::params::info_package_list') %> <%= item %> | egrep '(/bin|^/etc|/sbin|log$)'"
+<% end -%>
+<% end -%>
+<% end -%>
+
+<% if @configfile != "" -%>
+# Show config info
+echo_title "$HOSTNAME - <%= @name %>: Configuration Files managed: <% @configfile.each do |item| %><%= item %><% end %>"
+<% @configfile.each do |item| -%>
+<% if @verbose == "yes" -%>
+show_command "cat <%= item %>"
+<% else -%> 
+show_command "head <%= item %>"
+<% end -%>
+<% end -%>
+<% end -%>
+
+<% if @datadir != "" -%>
+# Show data dir
+echo_title "$HOSTNAME - <%= @name %>: Application data are in: <% @datadir.each do |item| %><%= item %><% end %>"
+<% @datadir.each do |item| -%>
+show_command "ls -latr <%= item %>"
+show_command "df <%= item %>"
+<% end -%>
+<% end -%>
+
+<% if @logdir != "" -%>
+# Show log dir
+echo_title "$HOSTNAME - <%= @name %>: Logs are in: <% @logdir.each do |item| %><%= item %><% end %>"
+<% @logdir.each do |item| -%>
+show_command "ls -latr <%= item %>"
+show_command "df <%= item %>"
+<% end -%>
+<% end -%>
+
+<% if @logfile != "" -%>
+# Show logs
+echo_title "$HOSTNAME - <%= @name %>: Last log entries: <% @logfile.each do |item| %><%= item %><% end %>"
+<% @logfile.each do |item| -%>
+<% if @verbose == "yes" -%>
+show_command "tail -30 <%= item %>"
+<% else -%>
+show_command "tail -10 <%= item %>"
+<% end -%>
+<% end -%>
+<% end -%>
+
+<% if @run != "" -%>
+echo_title "$HOSTNAME - <%= @name %>: Extra info"
+<% @run.each do |cmd| %>show_command "<%= cmd %>"
+<% end -%>
+<% end -%>
+
+
+<% if @servicename != "" -%>
+# Show service info
+echo_title "$HOSTNAME - <%= @name %>: Services: <% @servicename.each do |item| %><%= item %><% end %>"
+<% @servicename.each do |item| -%>
+show_command "/etc/init.d/<%= item %> status"
+<% end -%>
+<% if @verbose == "yes" -%>
+show_command "ps -adef | grep <%= @processname %> | grep -v grep"
+<% else -%>
+show_command "ps -adef | grep <%= @processname %> | grep -v grep | head -20"
+<% end -%>
+<% @port.each do |mport| -%>
+<% if @verbose == "yes" -%>
+show_command "netstat -natup | grep ':<%= mport %> '"
+<% else -%>
+show_command "netstat -natup | grep ':<%= mport %> ' | head -20"
+<% end -%>
+<% end -%>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/info/puppet.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,30 @@
+#!/bin/bash
+# <%= @description %>
+# Script generated by Puppet. It's executed when you run:
+# puppi info <%= @name %>
+#
+# Sources common header for Puppi scripts
+. <%= scope.lookupvar('puppi::params::scriptsdir') %>/header || exit 10
+
+# Show Puppet info
+echo_title "$HOSTNAME - <%= @name %>: Information on management with Puppet"
+echo "Where to configure this node in Puppet:"
+echo "manifests/nodes/<%= @site %>.pp - Node's definition"
+echo "manifests/roles/role_<%= @role %>.pp - Role's definition"
+echo "modules/<modulename>/manifests/init.pp - Main class for each module"
+echo
+
+# Show ReadMe file
+echo_title "$HOSTNAME - <%= @name %>: ReadMe"
+show_command "cat <%= scope.lookupvar('puppi::params::readmedir') %>/<%= @name %>"
+
+<% if @autoreadme == "yes" %>
+echo_title "$HOSTNAME - <%= @name %>: ReadMe Custom"
+show_command "cat <%= scope.lookupvar('puppi::params::readmedir') %>/<%= @name %>-custom"
+<% end %>
+
+<% if @run != "" %>
+echo_title "$HOSTNAME - <%= @name %>: Extra info"
+<% @run.each do |cmd| %>show_command "<%= cmd %>"
+<% end %>
+<% end %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/info/readme.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#!/bin/bash
+# <%= @description %>
+# Script generated by Puppet. It's executed when you run:
+# puppi info <%= @name %>
+#
+# Sources common header for Puppi scripts
+. <%= scope.lookupvar('puppi::params::scriptsdir') %>/header || exit 10
+
+# Show ReadMe file
+echo_title "$HOSTNAME - <%= @name %>: ReadMe"
+show_command "cat <%= scope.lookupvar('puppi::params::readmedir') %>/<%= @name %>"
+
+<% if @autoreadme == "yes" %>
+echo_title "$HOSTNAME - <%= @name %>: ReadMe Custom"
+show_command "cat <%= scope.lookupvar('puppi::params::readmedir') %>/<%= @name %>-custom"
+<% end %>
+
+<% if @run != "" %>
+echo_title "$HOSTNAME - <%= @name %>: Extra info"
+<% @run.each do |cmd| %>show_command "<%= cmd %>"
+<% end %>
+<% end %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/install_packages.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+#!/bin/bash
+# File Managed by Puppet
+export PATH=$PATH:/bin:/sbin:/usr/bin:usr/sbin
+<% if scope.lookupvar('::operatingsystem') == 'Debian' or scope.lookupvar('::operatingsystem') == 'Ubuntu' -%>
+apt-get update ; apt-get install -y <%= @packages %>
+<% elsif scope.lookupvar('::operatingsystem') == 'Centos' or scope.lookupvar('::operatingsystem') == 'RedHat' -%>
+yum install -y <%= @packages %>
+<% end -%>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/log.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,2 @@
+<% @array_log.each do |path| %><%= path %>
+<% end %>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/project/config.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+# File Managed by Puppet
+# This is the base configuration file for project <%= scope.lookupvar('name') %>
+# During a puppi deploy it's copied into the runtime configuration
+#   used by the scripts executed by puppi 
+#
+# Do not edit this file. You can modify these variables:
+# Permanently: directly on your puppi manifests (When you use the puppi:project:: defines)
+# Temporarily: using the puppi option -o to override them.
+#   example: puppi deploy $name -o "source=http://alt.com/file deploy_root=/var/tmp"
+
+# Common variables for project defines
+project="<%= @name %>"
+source="<%= @source %>"
+deploy_root="<%= @deploy_root %>"
+user="<%= @user %>"
+predeploy_customcommand="<%= @predeploy_customcommand %>"
+postdeploy_customcommand="<%= @postdeploy_customcommand %>"
+init_script="<%= @init_script %>"
+disable_services="<%= @disable_services %>"
+firewall_src_ip="<%= @firewall_src_ip %>"
+firewall_dst_port="<%= @firewall_dst_port %>"
+report_email="<%= @report_email %>"
+enable="<%= @enable %>"
+
+# Variables used by project::files
+files_prefix="<%= @files_prefix %>"
+source_baseurl="<%= @source_baseurl %>"
+
+# Variables used by project::maven
+document_root="<%= @document_root %>"
+config_root="<%= @config_root %>"
+
+# Variables added during runtime puppi operations
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/puppi.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+# General configuration file for Puppi tools
+# This file is managed by Puppet
+
+# Directory locations
+basedir="<%= scope.lookupvar('puppi::params::basedir') %>"
+checksdir="<%= scope.lookupvar('puppi::params::checksdir') %>"
+workdir="<%= scope.lookupvar('puppi::params::workdir') %>"
+projectsdir="<%= scope.lookupvar('puppi::params::projectsdir') %>"
+scriptsdir="<%= scope.lookupvar('puppi::params::scriptsdir') %>"
+libdir="<%= scope.lookupvar('puppi::params::libdir') %>"
+archivedir="<%= scope.lookupvar('puppi::params::archivedir') %>"
+logdir="<%= scope.lookupvar('puppi::params::logdir') %>"
+logsdir="<%= scope.lookupvar('puppi::params::logsdir') %>"
+infodir="<%= scope.lookupvar('puppi::params::infodir') %>"
+tododir="<%= scope.lookupvar('puppi::params::tododir') %>"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/puppi.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,517 @@
+#!/bin/bash
+configfile="<%= scope.lookupvar('puppi::params::basedir') %>/puppi.conf"
+
+# This is the actual command used to run the different scripts
+# Use cat for debugging noop purposes 
+# runcommand="cat"
+runcommand=""
+
+# Define defaults
+verbosity="max"
+show="yes"
+
+# Define action tag
+export tag=$(date +%Y%m%d-%H%M%S)
+
+counter=0
+
+# Load general configurations
+if [ ! -f $configfile ] ; then
+    echo "Config file: $configfile not found"
+    exit 1
+else
+    . $configfile
+    . $scriptsdir/functions
+fi
+
+# Main functions
+check_host () {
+    for command in $(ls -1 $checksdir) ; do
+        title="$HOSTNAME check: $command"
+        code=$(cat "$checksdir/$command")
+        ask_interactive
+        output=$($runcommand "$checksdir/$command" 2>&1)
+        handle_result
+    done
+}
+
+check () {
+    for command in $(ls -1 $projectsdir/$project/check) ; do
+        title="$HOSTNAME check: $command"
+        code=$(cat "$projectsdir/$project/check/$command")
+        ask_interactive
+        output=$($runcommand "$projectsdir/$project/check/$command" 2>&1)
+        handle_result
+    done
+
+    check_host
+    # show_report
+}
+
+log () {
+    tailcommand="tail"
+    which colortail >/dev/null 2>&1  && tailcommand="colortail"
+
+    if [ "x$project" != "xdefault" ] ; then
+        if [ $logsdir/$project ] ; then
+            alllog="$alllog $(cat $logsdir/$project)"
+        else
+            echo "WARNING: $logsdir/$project does not exist!"
+            exit 1
+        fi
+    else
+        if [ "$interactive" = "yes" ] ; then
+            echo "Choose one or more log topics to show. Select the last number (done) to end selection"
+            PS3="Type one number to add a log topic to the show list."
+            all_choices=""
+            select choice in $( ls $logsdir ) done
+            do
+                echo "You selected $choice [$REPLY]"
+                [[ $choice == "done" ]] && break
+                all_choices="$all_choices $choice"
+                echo "Your choices: $all_choices"
+            done
+            for log in $all_choices ; do
+                alllog="$alllog $(cat $logsdir/$log)"
+            done
+        else
+            for log in $(ls $logsdir) ; do
+                alllog="$alllog $(cat $logsdir/$log)"
+            done
+        fi
+    fi
+
+    # So, show something
+    if [ ! -z "$counts" ] ; then
+        if [ ! -z "$greppattern" ] ; then
+            $tailcommand -n $counts $alllog | grep $greppattern
+        else
+            $tailcommand -n $counts $alllog
+        fi
+    else
+        if [ ! -z "$greppattern" ] ; then
+            $tailcommand -f $alllog | grep $greppattern
+        else
+            $tailcommand -f $alllog
+        fi
+    fi
+}
+
+info () {
+    if [ "x$project" != "xdefault" ] ; then
+        if [ $infodir/$project ] ; then
+            $infodir/$project 
+        else
+            echo "WARNING: $infodir/$project does not exist!"
+            exit 1
+        fi
+    else
+        if [ "$interactive" = "yes" ] ; then
+            echo "Choose one or more topics to show. Select the last number (done) to end selection"
+            PS3="Type one number to add an info topic to the show list."
+            all_choices=""
+            select choice in $( ls $infodir ) done
+            do
+                echo "You selected $choice [$REPLY]"
+                [[ $choice == "done" ]] && break
+                all_choices="$all_choices $choice"
+                echo "Your choices: $all_choices"
+            done
+            for info in $all_choices ; do
+                if [ ! -z "$greppattern" ] ; then
+                    $infodir/$info | grep $greppattern
+                else
+                    $infodir/$info
+                fi
+            done
+        else
+            for info in $(ls $infodir) ; do
+                if [ ! -z "$greppattern" ] ; then
+                    $infodir/$info | grep $greppattern
+                else
+                    $infodir/$info
+                fi
+            done
+        fi
+    fi
+}
+
+
+todo () {
+    for todo in $(ls $tododir) ; do
+        $tododir/$todo
+    done
+}
+
+
+rollback () {
+    if [ ! -z $rollbackversion ] ; then
+        save_runtime_config "rollbackversion=$rollbackversion" || initerr=1
+    else
+        echo "Choose deploy to rollback:"
+        ls -1 $archivedir/$project
+        read rollbackversion
+        save_runtime_config "rollbackversion=$rollbackversion" || initerr=1
+    fi
+    
+    for command in $(ls -1 $projectsdir/$project/rollback) ; do
+        title="$HOSTNAME Rollback: $command"
+        code=$(cat "$projectsdir/$project/rollback/$command")
+        ask_interactive
+        output=$($runcommand "$projectsdir/$project/rollback/$command" 2>&1)
+        handle_result
+    done
+
+    send_reports
+    show_report
+    [ "$result" = "OK" ] && exit 0
+}
+
+deploy () {
+    for command in $(ls -1 $projectsdir/$project/deploy) ; do
+        title="$HOSTNAME Deploy: $command"
+        code=$(cat "$projectsdir/$project/deploy/$command")
+        ask_interactive
+        output=$($runcommand "$projectsdir/$project/deploy/$command" 2>&1)
+        handle_result
+        [ "$EXITCRIT" = "1" ] && [ "$force" != "yes" ] && break
+        if [ "$DONTDEPLOY" = "1" ] ; then
+             echo "No need to deploy: source file has not changed"
+             echo "Type 'rm $archivedir/$project/md5sum' and run puppi again to force deployment" 
+             exit 0
+        fi
+    done
+
+    send_reports
+    show_report
+    [ "$result" = "OK" ] && exit 0
+}
+
+initialize () {
+    for command in $(ls -1 $projectsdir/$project/initialize) ; do
+        title="$HOSTNAME Init: $command"
+        code=$(cat "$projectsdir/$project/initialize/$command")
+        ask_interactive
+        output=$($runcommand "$projectsdir/$project/initialize/$command" 2>&1)
+        handle_result
+        [ "$EXITCRIT" = "1" ] && [ "$force" != "yes" ] && break
+    done
+
+    send_reports
+    show_report
+    [ "$result" = "OK" ] && exit 0
+}
+
+configure () {
+    for command in $(ls -1 $projectsdir/$project/configure) ; do
+        title="$HOSTNAME Init: $command"
+        code=$(cat "$projectsdir/$project/configure/$command")
+        ask_interactive
+        output=$($runcommand "$projectsdir/$project/configure/$command" 2>&1)
+        handle_result
+        [ "$EXITCRIT" = "1" ] && [ "$force" != "yes" ] && break
+    done
+
+    send_reports
+    show_report
+    [ "$result" = "OK" ] && exit 0
+}
+
+save_summary () {
+    tagend=$(date +%Y%m%d-%H%M%S)
+
+    result="OK"
+    if [ "$EXITWARN" = "1" ] ; then
+        result="WARNING"
+    fi
+    if [ "$EXITCRIT" = "1" ] ; then
+        result="ERROR"
+    fi
+
+    echo "Report for $action on $project" > $logdir/$project/$tag/summary
+    echo "Job start: $tag" >> $logdir/$project/$tag/summary
+    echo "Job end: $tagend" >> $logdir/$project/$tag/summary
+    echo "Job result: $result" >> $logdir/$project/$tag/summary
+    echo "Actions executed:" >> $logdir/$project/$tag/summary
+    cd $logdir/$project/$tag/
+    for message in $(ls -1 $logdir/$project/$tag/ | grep -v summary ) ; do
+        msg_title=$(head -1 $message)
+        msg_code=$(head -2 $message | tail -1) 
+        msg_result=$(head -3 $message | tail -1) 
+        echo "[$msg_result] $msg_title : $msg_code" >> $logdir/$project/$tag/summary
+    done
+
+    # Copy runtime config in archive
+    cp $workdir/$project/config $logdir/$project/$tag/
+
+    # Write runtime config on Summary
+    echo >> $logdir/$project/$tag/summary
+    echo "RUNTIME CONFIGURATION" >> $logdir/$project/$tag/summary
+    cat $workdir/$project/config | grep -vE "^#|^$"  >> $logdir/$project/$tag/summary
+
+}
+
+send_reports () {
+    if [[ "x$report" == "xyes" ]] ; then
+        save_summary
+        for command in $(ls -1 $projectsdir/$project/report) ; do
+            title="Reporting: $command"
+            code=$(cat "$projectsdir/$project/report/$command")
+            echo -n $title
+            output=$($runcommand "$projectsdir/$project/report/$command" 2>&1)
+            # handle_result # This breaks the overall exit code when deploy fails
+        done
+    fi
+}
+
+show_report () {
+    echo
+    echo "REPORT FOR PUPPI - STATUS $result"
+    echo "Summary of operations is: $logdir/$project/$tag/summary "
+    echo "Details are in: $logdir/$project/$tag/"
+    echo "Temporary workdir has been: $workdir/$project/ (Will be rewritten at the next puppi run)"
+    echo "Runtime config file is: $workdir/$project/config"
+    echo "Files have been archived in: $archivedir/$project/$tag"
+    test "$testmode" = "yes" && echo "This was a TEST RUN! Nothing has been done for real."
+}
+
+
+create_runtime_conf () {
+    if [[ ( ! -e $projectsdir/$project ) && ( ! -e $infodir/$project ) && ( ! -e $logsdir/$project ) ]] ; then
+        showhelp
+        exit 1
+    fi
+
+    initerr=0
+
+    # When project is unset we set it to default
+    [ ! -z "$project" ] || export project="default"
+
+    # Clean up and Create runtime configuration file 
+#    command="00-$project-RuntimeConfig-Initialization"
+#    title="Puppi setup: $command"
+#    code="rm -rf $workdir/$project && touch $workdir/$project/config [...]"
+#    echo -n $title
+
+    echo $workdir | grep tmp >/dev/null 2>&1 || ( echo "Workdir must contain string tmp" ; exit 1 )
+    rm -rf $workdir/$project || initerr=1
+
+    mkdir -p $workdir/$project || initerr=1
+    touch $workdir/$project/config || initerr=1
+
+    test -r "$projectsdir/$project/config" && cp $projectsdir/$project/config $workdir/$project/
+    chmod 644 $workdir/$project/config || initerr=1
+
+    save_runtime_config "project=$project" || initerr=1
+    save_runtime_config "tag=$tag" || initerr=1
+    save_runtime_config "action=$action" || initerr=1
+
+    storedir=$workdir/$project/store || initerr=1
+    mkdir -p $storedir || initerr=1
+    save_runtime_config "storedir=$storedir" || initerr=1
+
+    predeploydir=$workdir/$project/deploy || initerr=1
+    mkdir -p $predeploydir || initerr=1
+    save_runtime_config "predeploydir=$predeploydir" || initerr=1
+
+    save_runtime_config "force=$force" || initerr=1
+    save_runtime_config "testmode=$testmode" || initerr=1
+    save_runtime_config "interactive=$interactive" || initerr=1
+    save_runtime_config "debug=$debug" || initerr=1
+    save_runtime_config "report=$report" || initerr=1
+    save_runtime_config "show=$show" || initerr=1
+    save_runtime_config "counts=$counts" || initerr=1
+    save_runtime_config "greppattern=$greppattern" || initerr=1
+
+    for oopt in $(echo $options) ; do
+        save_runtime_config "$(echo $oopt)" || initerr=1
+    done
+    
+    echo $initerr | grep "0" 2>&1 > /dev/null
+#    handle_result
+}
+
+
+showhelp () {
+   echo "Usage: puppi <command> [project|topic] [options]"
+   echo " "
+   echo "Available commands:"
+   echo "check [project] [-s <yes|no|fail>] - Run puppi checks host or project wide"
+   echo "log [topic] [-i] [-g <pattern>] - Show system and application specific logs"
+   echo "info [topic] [-i] [-g <pattern>] - Show informations about the system"
+   echo "todo - Show todo's checklist of the system"
+   echo "init <project> [-i] [-f] [-t] - First time project initialization and setup"
+   echo "configure <project> [-i] [-f] [-t] - Project configuration deployment."
+   echo "deploy <project> [-i] [-f] [-t] [-o ...] - Deploy the specified project"
+   echo "rollback <project> [state] [-i] [-f] [-t] - Rollback the specified project. "
+   echo " "
+   echo "Available options:"
+   echo "-f - Force puppi commands execution flow also on CRITICAL errors"
+   echo "-i - Interactively ask confirmation for every step"
+   echo "-t - Test mode. Just show the commands that should be executed"
+   echo "-d <yes|full> - Debug mode. Show debug of what is done."
+   echo "-r <yes|no|fail> - Enable reporting: yes/no/only on failures. Default depends on action"
+   echo "-s <yes|no|fail> - Show output: yes/no/only for failures. Default: yes"
+   echo "-g <pattern> - Grep command output with the selected pattern"
+   echo "-o \"parameter=value parameter2=value2\" - Set manual options to override defaults"
+   echo " "
+   echo "Available deploy projects:"
+   ls -1 $projectsdir
+   echo 
+   echo "Available info topics:"
+   ls $infodir 
+   echo 
+   echo "Available log topics:"
+   ls $logsdir
+}
+
+# Check Input
+if [ "$#" = "0" ] ; then
+    showhelp
+    exit
+fi
+
+while [ $# -gt 0 ]; do
+  case "$1" in
+    deploy|init|configure)
+      report="yes"
+      export action=$1
+      if [ -n "$2" ] ; then
+        echo "$2" | egrep -q "^-.$"
+        if [ "$?" != "0" ] ; then
+          export project=$(shell_filter_strict $2)
+          shift 2
+        else
+          shift
+        fi
+      else
+        showhelp
+        exit
+        shift
+      fi
+    ;;
+    rollback)
+      report="yes"
+      export action=$1
+      if [ -n "$3" ] ; then
+        echo "$3" | egrep -q "^-.$"
+        if [ "$?" != "0" ] ; then
+          export project=$(shell_filter_strict $2)
+          export rollbackversion=$(shell_filter_strict $3)
+          shift 3
+        else
+          shift 2
+        fi
+      elif [ -n "$2" ] ; then
+        echo "$2" | egrep -q "^-.$"
+        if [ "$?" != "0" ] ; then
+          export project=$(shell_filter_strict $2)
+          shift 2
+        else
+          shift
+        fi
+      else
+        showhelp
+        exit
+        shift
+      fi
+    ;;
+    check)
+      report="no"
+      export action="checkhost"
+      if [ -n "$2" ] ; then
+        echo "$2" | egrep -q "^-.$"
+        if [ "$?" != "0" ] ; then
+          export project=$(shell_filter_strict $2)
+          export action="check"
+          shift 2
+        else
+          shift
+        fi
+      else
+        shift
+      fi
+    ;;
+    log)
+      report="no"
+      export action="log"
+      if [ -n "$2" ] ; then
+        echo "$2" | egrep -q "^-.$"
+        if [ "$?" != "0" ] ; then
+          export project=$(shell_filter_strict $2)
+          shift 2
+        else 
+          shift
+        fi
+      else
+        shift
+      fi
+    ;;
+    info)
+      report="no"
+      export action="info"
+      if [ -n "$2" ] ; then
+        echo "$2" | egrep -q "^-.$"
+        if [ "$?" != "0" ] ; then
+          export project=$(shell_filter_strict $2)
+          shift 2
+        else
+          shift
+        fi
+      else
+        shift
+      fi
+    ;;
+    todo)
+      report="no"
+      export action="todo"
+      shift ;;
+    -i)
+      interactive="yes"
+      shift ;;
+    -f)
+      force="yes"
+      shift ;;
+    -t)
+      testmode="yes"
+      runcommand="cat"
+      shift ;;
+    -o)
+      options="$2"
+      shift 2;;
+    -d)
+      debug="$(shell_filter_strict $2)"
+      shift 2;;
+    -r)
+      report="$(shell_filter_strict $2)"
+      shift 2;;
+    -s)
+      show="$(shell_filter_strict $2)"
+      shift 2;;
+    -c)
+      counts="$(shell_filter_strict $2)"
+      shift 2;;
+    -g)
+      greppattern="$(shell_filter_strict $2)"
+      # greppattern="$(shell_filter $2)" # This allows partial regexp usage
+      # greppattern="$2" # This allows full regexp usage but is highly insecure if you sudo puppi
+      shift 2;;
+    *)
+      showhelp
+      exit
+      ;;
+  esac
+done
+
+# Action!
+case $action in 
+    check) check ;;
+    checkhost) check_host ;;
+    log) create_runtime_conf ; log ;;
+    info) create_runtime_conf ; info ;;
+    todo) create_runtime_conf ; todo ;;
+    rollback) create_runtime_conf ; rollback ;;
+    deploy) create_runtime_conf ; deploy ;;
+    init) create_runtime_conf ; initialize ;;
+    configure) create_runtime_conf ; configure ;;
+esac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/puppi_clean.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+#!/bin/bash
+# This scripts cleans puppi log files older than <%= scope.lookupvar('puppi::logs_retention_days') %> days
+seconds=$(( (RANDOM%60+1)*60 ))
+sleep $seconds
+
+if [ "<%= scope.lookupvar('puppi::params::logdir') %>" == "/" ] || [ "x<%= scope.lookupvar('puppi::params::logdir') %>" == "x" ]; then
+  exit 1
+fi
+find "<%= scope.lookupvar('puppi::params::logdir') %>" -type f -mtime +<%= scope.lookupvar('puppi::logs_retention_days') %> -exec rm '{}' '+' >/dev/null 2>&1
+find "<%= scope.lookupvar('puppi::params::logdir') %>" -mindepth 2 -type d -mtime +<%= scope.lookupvar('puppi::logs_retention_days') %> -exec rmdir '{}' '+' >/dev/null 2>&1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/puppi/templates/todo.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+#!/bin/bash
+# Script generated by Puppet. It's executed when you run:
+# puppi todo <%= @name %>
+#
+# Sources common header for Puppi scripts
+. <%= scope.lookupvar('puppi::params::scriptsdir') %>/header || exit 10
+
+echo_title "$HOSTNAME - <%= @name %>"
+
+<% if @description != "" -%>
+cat <<EOF
+<%= @description %>
+EOF
+<% end -%>
+
+<% if @notes != "" -%>
+cat <<EOF
+<%= @notes %>
+EOF
+<% end -%>
+
+<% if @run != "" -%>
+<% @array_run.each do |cmd| %>show_command "<%= cmd -%>"
+<% end -%>
+<% end -%>
+
+<% if @check_command != "" -%>
+<%= @check_command %>
+if [ "x$?" = "x0" ] ; then
+    echo_success
+    result="OK"
+else
+    echo_failure
+    result="CRITICAL"
+    EXITCRIT="1"
+fi
+<% else -%>
+echo_warning
+result="WARNING"
+EXITWARN="1"
+<% end -%>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/CHANGELOG.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,583 @@
+## Supported Release 4.9.1
+###Summary
+
+Small release for support of newer PE versions. This increments the version of PE in the metadata.json file.
+
+##2015-09-08 - Supported Release 4.9.0
+###Summary
+
+This release adds new features including the new functions dos2unix, unix2dos, try_get_value, convert_base as well as other features and improvements.
+
+####Features
+- (MODULES-2370) allow `match` parameter to influence `ensure => absent` behavior
+- (MODULES-2410) Add new functions dos2unix and unix2dos
+- (MODULE-2456) Modify union to accept more than two arrays
+- Adds a convert_base function, which can convert numbers between bases
+- Add a new function "try_get_value"
+
+####Bugfixes
+- n/a
+
+####Improvements
+- (MODULES-2478) Support root_home fact on AIX through "lsuser" command
+- Acceptance test improvements
+- Unit test improvements
+- Readme improvements
+
+## 2015-08-10 - Supported Release 4.8.0
+### Summary
+This release adds a function for reading metadata.json from any module, and expands file\_line's abilities.
+
+#### Features
+- New parameter `replace` on `file_line`
+- New function `load_module_metadata()` to load metadata.json and return the content as a hash.
+- Added hash support to `size()`
+
+#### Bugfixes
+- Fix various docs typos
+- Fix `file_line` resource on puppet < 3.3
+
+##2015-06-22 - Supported Release 4.7.0
+###Summary
+
+Adds Solaris 12 support along with improved Puppet 4 support. There are significant test improvements, and some minor fixes.
+
+####Features
+- Add support for Solaris 12
+
+####Bugfixes
+- Fix for AIO Puppet 4
+- Fix time for ruby 1.8.7
+- Specify rspec-puppet version
+- range() fix for typeerror and missing functionality
+- Fix pw_hash() on JRuby < 1.7.17
+- fqdn_rand_string: fix argument error message
+- catch and rescue from looking up non-existent facts
+- Use puppet_install_helper, for Puppet 4
+
+####Improvements
+- Enforce support for Puppet 4 testing
+- fqdn_rotate/fqdn_rand_string acceptance tests and implementation
+- Simplify mac address regex
+- validate_integer, validate_numeric: explicitely reject hashes in arrays
+- Readme edits
+- Remove all the pops stuff for rspec-puppet
+- Sync via modulesync
+- Add validate_slength optional 3rd arg
+- Move tests directory to examples directory
+
+##2015-04-14 - Supported Release 4.6.0
+###Summary
+
+Adds functions and function argument abilities, and improves compatibility with the new puppet parser
+
+####Features
+- MODULES-444: `concat()` can now take more than two arrays
+- `basename()` added to have Ruby File.basename functionality
+- `delete()` can now take an array of items to remove
+- `prefix()` can now take a hash
+- `upcase()` can now take a hash or array of upcaseable things
+- `validate_absolute_path()` can now take an array
+- `validate_cmd()` can now use % in the command to embed the validation file argument in the string
+- MODULES-1473: deprecate `type()` function in favor of `type3x()`
+- MODULES-1473: Add `type_of()` to give better type information on future parser
+- Deprecate `private()` for `assert_private()` due to future parser
+- Adds `ceiling()` to take the ceiling of a number
+- Adds `fqdn_rand_string()` to generate random string based on fqdn
+- Adds `pw_hash()` to generate password hashes
+- Adds `validate_integer()`
+- Adds `validate_numeric()` (like `validate_integer()` but also accepts floats)
+
+####Bugfixes
+- Fix seeding of `fqdn_rotate()`
+- `ensure_resource()` is more verbose on debug mode
+- Stricter argument checking for `dirname()`
+- Fix `is_domain_name()` to better match RFC
+- Fix `uriescape()` when called with array
+- Fix `file_line` resource when using the `after` attribute with `match`
+
+##2015-01-14 - Supported Release 4.5.1
+###Summary
+
+This release changes the temporary facter_dot_d cache locations outside of the /tmp directory due to a possible security vunerability. CVE-2015-1029
+
+####Bugfixes
+- Facter_dot_d cache will now be stored in puppet libdir instead of tmp
+
+##2014-12-15 - Supported Release 4.5.0
+###Summary
+
+This release improves functionality of the member function and adds improved future parser support.
+
+####Features
+- MODULES-1329: Update member() to allow the variable to be an array.
+- Sync .travis.yml, Gemfile, Rakefile, and CONTRIBUTING.md via modulesync
+
+####Bugfixes
+- Fix range() to work with numeric ranges with the future parser
+- Accurately express SLES support in metadata.json (was missing 10SP4 and 12)
+- Don't require `line` to match the `match` parameter
+
+##2014-11-10 - Supported Release 4.4.0
+###Summary
+This release has an overhauled readme, new private manifest function, and fixes many future parser bugs.
+
+####Features
+- All new shiny README
+- New `private()` function for making private manifests (yay!)
+
+####Bugfixes
+- Code reuse in `bool2num()` and `zip()`
+- Fix many functions to handle `generate()` no longer returning a string on new puppets
+- `concat()` no longer modifies the first argument (whoops)
+- strict variable support for `getvar()`, `member()`, `values_at`, and `has_interface_with()`
+- `to_bytes()` handles PB and EB now
+- Fix `tempfile` ruby requirement for `validate_augeas()` and `validate_cmd()`
+- Fix `validate_cmd()` for windows
+- Correct `validate_string()` docs to reflect non-handling of `undef`
+- Fix `file_line` matching on older rubies
+
+
+##2014-07-15 - Supported Release 4.3.2
+###Summary
+
+This release merely updates metadata.json so the module can be uninstalled and
+upgraded via the puppet module command.
+
+##2014-07-14 - Supported Release 4.3.1
+### Summary
+This supported release updates the metadata.json to work around upgrade behavior of the PMT.
+
+#### Bugfixes
+- Synchronize metadata.json with PMT-generated metadata to pass checksums
+
+##2014-06-27 - Supported Release 4.3.0
+### Summary
+This release is the first supported release of the stdlib 4 series. It remains
+backwards-compatible with the stdlib 3 series. It adds two new functions, one bugfix, and many testing updates.
+
+#### Features
+- New `bool2str()` function
+- New `camelcase()` function
+
+#### Bugfixes
+- Fix `has_interface_with()` when interfaces fact is nil
+
+##2014-06-04 - Release 4.2.2
+### Summary
+
+This release adds PE3.3 support in the metadata and fixes a few tests.
+
+## 2014-05-08 - Release - 4.2.1
+### Summary
+This release moves a stray symlink that can cause problems.
+
+## 2014-05-08 - Release - 4.2.0
+### Summary
+This release adds many new functions and fixes, and continues to be backwards compatible with stdlib 3.x
+
+#### Features
+- New `base64()` function
+- New `deep_merge()` function
+- New `delete_undef_values()` function
+- New `delete_values()` function
+- New `difference()` function
+- New `intersection()` function
+- New `is_bool()` function
+- New `pick_default()` function
+- New `union()` function
+- New `validate_ipv4_address` function
+- New `validate_ipv6_address` function
+- Update `ensure_packages()` to take an option hash as a second parameter.
+- Update `range()` to take an optional third argument for range step
+- Update `validate_slength()` to take an optional third argument for minimum length
+- Update `file_line` resource to take `after` and `multiple` attributes
+
+#### Bugfixes
+- Correct `is_string`, `is_domain_name`, `is_array`, `is_float`, and `is_function_available` for parsing odd types such as bools and hashes.
+- Allow facts.d facts to contain `=` in the value
+- Fix `root_home` fact on darwin systems
+- Fix `concat()` to work with a second non-array argument
+- Fix `floor()` to work with integer strings
+- Fix `is_integer()` to return true if passed integer strings
+- Fix `is_numeric()` to return true if passed integer strings
+- Fix `merge()` to work with empty strings
+- Fix `pick()` to raise the correct error type
+- Fix `uriescape()` to use the default URI.escape list
+- Add/update unit & acceptance tests.
+
+
+##2014-03-04 - Supported Release - 3.2.1
+###Summary
+This is a supported release
+
+####Bugfixes
+- Fixed `is_integer`/`is_float`/`is_numeric` for checking the value of arithmatic expressions.
+
+####Known bugs
+* No known bugs
+
+---
+
+##### 2013-05-06 - Jeff McCune <jeff@puppetlabs.com> - 4.1.0
+
+ * (#20582) Restore facter\_dot\_d to stdlib for PE users (3b887c8)
+ * (maint) Update Gemfile with GEM\_FACTER\_VERSION (f44d535)
+
+##### 2013-05-06 - Alex Cline <acline@us.ibm.com> - 4.1.0
+
+ * Terser method of string to array conversion courtesy of ethooz. (d38bce0)
+
+##### 2013-05-06 - Alex Cline <acline@us.ibm.com> 4.1.0
+
+ * Refactor ensure\_resource expectations (b33cc24)
+
+##### 2013-05-06 - Alex Cline <acline@us.ibm.com> 4.1.0
+
+ * Changed str-to-array conversion and removed abbreviation. (de253db)
+
+##### 2013-05-03 - Alex Cline <acline@us.ibm.com> 4.1.0
+
+ * (#20548) Allow an array of resource titles to be passed into the ensure\_resource function (e08734a)
+
+##### 2013-05-02 - Raphaël Pinson <raphael.pinson@camptocamp.com> - 4.1.0
+
+ * Add a dirname function (2ba9e47)
+
+##### 2013-04-29 - Mark Smith-Guerrero <msmithgu@gmail.com> - 4.1.0
+
+ * (maint) Fix a small typo in hash() description (928036a)
+
+##### 2013-04-12 - Jeff McCune <jeff@puppetlabs.com> - 4.0.2
+
+ * Update user information in gemspec to make the intent of the Gem clear.
+
+##### 2013-04-11 - Jeff McCune <jeff@puppetlabs.com> - 4.0.1
+
+ * Fix README function documentation (ab3e30c)
+
+##### 2013-04-11 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+
+ * stdlib 4.0 drops support with Puppet 2.7
+ * stdlib 4.0 preserves support with Puppet 3
+
+##### 2013-04-11 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+
+ * Add ability to use puppet from git via bundler (9c5805f)
+
+##### 2013-04-10 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+
+ * (maint) Make stdlib usable as a Ruby GEM (e81a45e)
+
+##### 2013-04-10 - Erik Dalén <dalen@spotify.com> - 4.0.0
+
+ * Add a count function (f28550e)
+
+##### 2013-03-31 - Amos Shapira <ashapira@atlassian.com> - 4.0.0
+
+ * (#19998) Implement any2array (7a2fb80)
+
+##### 2013-03-29 - Steve Huff <shuff@vecna.org> - 4.0.0
+
+ * (19864) num2bool match fix (8d217f0)
+
+##### 2013-03-20 - Erik Dalén <dalen@spotify.com> - 4.0.0
+
+ * Allow comparisons of Numeric and number as String (ff5dd5d)
+
+##### 2013-03-26 - Richard Soderberg <rsoderberg@mozilla.com> - 4.0.0
+
+ * add suffix function to accompany the prefix function (88a93ac)
+
+##### 2013-03-19 - Kristof Willaert <kristof.willaert@gmail.com> - 4.0.0
+
+ * Add floor function implementation and unit tests (0527341)
+
+##### 2012-04-03 - Eric Shamow <eric@puppetlabs.com> - 4.0.0
+
+ * (#13610) Add is\_function\_available to stdlib (961dcab)
+
+##### 2012-12-17 - Justin Lambert <jlambert@eml.cc> - 4.0.0
+
+ * str2bool should return a boolean if called with a boolean (5d5a4d4)
+
+##### 2012-10-23 - Uwe Stuehler <ustuehler@team.mobile.de> - 4.0.0
+
+ * Fix number of arguments check in flatten() (e80207b)
+
+##### 2013-03-11 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+
+ * Add contributing document (96e19d0)
+
+##### 2013-03-04 - Raphaël Pinson <raphael.pinson@camptocamp.com> - 4.0.0
+
+ * Add missing documentation for validate\_augeas and validate\_cmd to README.markdown (a1510a1)
+
+##### 2013-02-14 - Joshua Hoblitt <jhoblitt@cpan.org> - 4.0.0
+
+ * (#19272) Add has\_element() function (95cf3fe)
+
+##### 2013-02-07 - Raphaël Pinson <raphael.pinson@camptocamp.com> - 4.0.0
+
+ * validate\_cmd(): Use Puppet::Util::Execution.execute when available (69248df)
+
+##### 2012-12-06 - Raphaël Pinson <raphink@gmail.com> - 4.0.0
+
+ * Add validate\_augeas function (3a97c23)
+
+##### 2012-12-06 - Raphaël Pinson <raphink@gmail.com> - 4.0.0
+
+ * Add validate\_cmd function (6902cc5)
+
+##### 2013-01-14 - David Schmitt <david@dasz.at> - 4.0.0
+
+ * Add geppetto project definition (b3fc0a3)
+
+##### 2013-01-02 - Jaka Hudoklin <jakahudoklin@gmail.com> - 4.0.0
+
+ * Add getparam function to get defined resource parameters (20e0e07)
+
+##### 2013-01-05 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+
+ * (maint) Add Travis CI Support (d082046)
+
+##### 2012-12-04 - Jeff McCune <jeff@puppetlabs.com> - 4.0.0
+
+ * Clarify that stdlib 3 supports Puppet 3 (3a6085f)
+
+##### 2012-11-30 - Erik Dalén <dalen@spotify.com> - 4.0.0
+
+ * maint: style guideline fixes (7742e5f)
+
+##### 2012-11-09 - James Fryman <james@frymanet.com> - 4.0.0
+
+ * puppet-lint cleanup (88acc52)
+
+##### 2012-11-06 - Joe Julian <me@joejulian.name> - 4.0.0
+
+ * Add function, uriescape, to URI.escape strings. Redmine #17459 (fd52b8d)
+
+##### 2012-09-18 - Chad Metcalf <chad@wibidata.com> - 3.2.0
+
+ * Add an ensure\_packages function. (8a8c09e)
+
+##### 2012-11-23 - Erik Dalén <dalen@spotify.com> - 3.2.0
+
+ * (#17797) min() and max() functions (9954133)
+
+##### 2012-05-23 - Peter Meier <peter.meier@immerda.ch> - 3.2.0
+
+ * (#14670) autorequire a file\_line resource's path (dfcee63)
+
+##### 2012-11-19 - Joshua Harlan Lifton <lifton@puppetlabs.com> - 3.2.0
+
+ * Add join\_keys\_to\_values function (ee0f2b3)
+
+##### 2012-11-17 - Joshua Harlan Lifton <lifton@puppetlabs.com> - 3.2.0
+
+ * Extend delete function for strings and hashes (7322e4d)
+
+##### 2012-08-03 - Gary Larizza <gary@puppetlabs.com> - 3.2.0
+
+ * Add the pick() function (ba6dd13)
+
+##### 2012-03-20 - Wil Cooley <wcooley@pdx.edu> - 3.2.0
+
+ * (#13974) Add predicate functions for interface facts (f819417)
+
+##### 2012-11-06 - Joe Julian <me@joejulian.name> - 3.2.0
+
+ * Add function, uriescape, to URI.escape strings. Redmine #17459 (70f4a0e)
+
+##### 2012-10-25 - Jeff McCune <jeff@puppetlabs.com> - 3.1.1
+
+ * (maint) Fix spec failures resulting from Facter API changes (97f836f)
+
+##### 2012-10-23 - Matthaus Owens <matthaus@puppetlabs.com> - 3.1.0
+
+ * Add PE facts to stdlib (cdf3b05)
+
+##### 2012-08-16 - Jeff McCune <jeff@puppetlabs.com> - 3.0.1
+
+ * Fix accidental removal of facts\_dot\_d.rb in 3.0.0 release
+
+##### 2012-08-16 - Jeff McCune <jeff@puppetlabs.com> - 3.0.0
+
+ * stdlib 3.0 drops support with Puppet 2.6
+ * stdlib 3.0 preserves support with Puppet 2.7
+
+##### 2012-08-07 - Dan Bode <dan@puppetlabs.com> - 3.0.0
+
+ * Add function ensure\_resource and defined\_with\_params (ba789de)
+
+##### 2012-07-10 - Hailee Kenney <hailee@puppetlabs.com> - 3.0.0
+
+ * (#2157) Remove facter\_dot\_d for compatibility with external facts (f92574f)
+
+##### 2012-04-10 - Chris Price <chris@puppetlabs.com> - 3.0.0
+
+ * (#13693) moving logic from local spec\_helper to puppetlabs\_spec\_helper (85f96df)
+
+##### 2012-10-25 - Jeff McCune <jeff@puppetlabs.com> - 2.5.1
+
+ * (maint) Fix spec failures resulting from Facter API changes (97f836f)
+
+##### 2012-10-23 - Matthaus Owens <matthaus@puppetlabs.com> - 2.5.0
+
+ * Add PE facts to stdlib (cdf3b05)
+
+##### 2012-08-15 - Dan Bode <dan@puppetlabs.com> - 2.5.0
+
+ * Explicitly load functions used by ensure\_resource (9fc3063)
+
+##### 2012-08-13 - Dan Bode <dan@puppetlabs.com> - 2.5.0
+
+ * Add better docs about duplicate resource failures (97d327a)
+
+##### 2012-08-13 - Dan Bode <dan@puppetlabs.com> - 2.5.0
+
+ * Handle undef for parameter argument (4f8b133)
+
+##### 2012-08-07 - Dan Bode <dan@puppetlabs.com> - 2.5.0
+
+ * Add function ensure\_resource and defined\_with\_params (a0cb8cd)
+
+##### 2012-08-20 - Jeff McCune <jeff@puppetlabs.com> - 2.5.0
+
+ * Disable tests that fail on 2.6.x due to #15912 (c81496e)
+
+##### 2012-08-20 - Jeff McCune <jeff@puppetlabs.com> - 2.5.0
+
+ * (Maint) Fix mis-use of rvalue functions as statements (4492913)
+
+##### 2012-08-20 - Jeff McCune <jeff@puppetlabs.com> - 2.5.0
+
+ * Add .rspec file to repo root (88789e8)
+
+##### 2012-06-07 - Chris Price <chris@puppetlabs.com> - 2.4.0
+
+ * Add support for a 'match' parameter to file\_line (a06c0d8)
+
+##### 2012-08-07 - Erik Dalén <dalen@spotify.com> - 2.4.0
+
+ * (#15872) Add to\_bytes function (247b69c)
+
+##### 2012-07-19 - Jeff McCune <jeff@puppetlabs.com> - 2.4.0
+
+ * (Maint) use PuppetlabsSpec::PuppetInternals.scope (master) (deafe88)
+
+##### 2012-07-10 - Hailee Kenney <hailee@puppetlabs.com> - 2.4.0
+
+ * (#2157) Make facts\_dot\_d compatible with external facts (5fb0ddc)
+
+##### 2012-03-16 - Steve Traylen <steve.traylen@cern.ch> - 2.4.0
+
+ * (#13205) Rotate array/string randomley based on fqdn, fqdn\_rotate() (fef247b)
+
+##### 2012-05-22 - Peter Meier <peter.meier@immerda.ch> - 2.3.3
+
+ * fix regression in #11017 properly (f0a62c7)
+
+##### 2012-05-10 - Jeff McCune <jeff@puppetlabs.com> - 2.3.3
+
+ * Fix spec tests using the new spec\_helper (7d34333)
+
+##### 2012-05-10 - Puppet Labs <support@puppetlabs.com> - 2.3.2
+
+ * Make file\_line default to ensure => present (1373e70)
+ * Memoize file\_line spec instance variables (20aacc5)
+ * Fix spec tests using the new spec\_helper (1ebfa5d)
+ * (#13595) initialize\_everything\_for\_tests couples modules Puppet ver (3222f35)
+ * (#13439) Fix MRI 1.9 issue with spec\_helper (15c5fd1)
+ * (#13439) Fix test failures with Puppet 2.6.x (665610b)
+ * (#13439) refactor spec helper for compatibility with both puppet 2.7 and master (82194ca)
+ * (#13494) Specify the behavior of zero padded strings (61891bb)
+
+##### 2012-03-29 Puppet Labs <support@puppetlabs.com> - 2.1.3
+
+* (#11607) Add Rakefile to enable spec testing
+* (#12377) Avoid infinite loop when retrying require json
+
+##### 2012-03-13 Puppet Labs <support@puppetlabs.com> - 2.3.1
+
+* (#13091) Fix LoadError bug with puppet apply and puppet\_vardir fact
+
+##### 2012-03-12 Puppet Labs <support@puppetlabs.com> - 2.3.0
+
+* Add a large number of new Puppet functions
+* Backwards compatibility preserved with 2.2.x
+
+##### 2011-12-30 Puppet Labs <support@puppetlabs.com> - 2.2.1
+
+* Documentation only release for the Forge
+
+##### 2011-12-30 Puppet Labs <support@puppetlabs.com> - 2.1.2
+
+* Documentation only release for PE 2.0.x
+
+##### 2011-11-08 Puppet Labs <support@puppetlabs.com> - 2.2.0
+
+* #10285 - Refactor json to use pson instead.
+* Maint  - Add watchr autotest script
+* Maint  - Make rspec tests work with Puppet 2.6.4
+* #9859  - Add root\_home fact and tests
+
+##### 2011-08-18 Puppet Labs <support@puppetlabs.com> - 2.1.1
+
+* Change facts.d paths to match Facter 2.0 paths.
+* /etc/facter/facts.d
+* /etc/puppetlabs/facter/facts.d
+
+##### 2011-08-17 Puppet Labs <support@puppetlabs.com> - 2.1.0
+
+* Add R.I. Pienaar's facts.d custom facter fact
+* facts defined in /etc/facts.d and /etc/puppetlabs/facts.d are
+  automatically loaded now.
+
+##### 2011-08-04 Puppet Labs <support@puppetlabs.com> - 2.0.0
+
+* Rename whole\_line to file\_line
+* This is an API change and as such motivating a 2.0.0 release according to semver.org.
+
+##### 2011-08-04 Puppet Labs <support@puppetlabs.com> - 1.1.0
+
+* Rename append\_line to whole\_line
+* This is an API change and as such motivating a 1.1.0 release.
+
+##### 2011-08-04 Puppet Labs <support@puppetlabs.com> - 1.0.0
+
+* Initial stable release
+* Add validate\_array and validate\_string functions
+* Make merge() function work with Ruby 1.8.5
+* Add hash merging function
+* Add has\_key function
+* Add loadyaml() function
+* Add append\_line native
+
+##### 2011-06-21 Jeff McCune <jeff@puppetlabs.com> - 0.1.7
+
+* Add validate\_hash() and getvar() functions
+
+##### 2011-06-15 Jeff McCune <jeff@puppetlabs.com> - 0.1.6
+
+* Add anchor resource type to provide containment for composite classes
+
+##### 2011-06-03 Jeff McCune <jeff@puppetlabs.com> - 0.1.5
+
+* Add validate\_bool() function to stdlib
+
+##### 0.1.4 2011-05-26 Jeff McCune <jeff@puppetlabs.com>
+
+* Move most stages after main
+
+##### 0.1.3 2011-05-25 Jeff McCune <jeff@puppetlabs.com>
+
+* Add validate\_re() function
+
+##### 0.1.2 2011-05-24 Jeff McCune <jeff@puppetlabs.com>
+
+* Update to add annotated tag
+
+##### 0.1.1 2011-05-24 Jeff McCune <jeff@puppetlabs.com>
+
+* Add stdlib::stages class with a standard set of stages
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/CONTRIBUTING.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,220 @@
+Checklist (and a short version for the impatient)
+=================================================
+
+  * Commits:
+
+    - Make commits of logical units.
+
+    - Check for unnecessary whitespace with "git diff --check" before
+      committing.
+
+    - Commit using Unix line endings (check the settings around "crlf" in
+      git-config(1)).
+
+    - Do not check in commented out code or unneeded files.
+
+    - The first line of the commit message should be a short
+      description (50 characters is the soft limit, excluding ticket
+      number(s)), and should skip the full stop.
+
+    - Associate the issue in the message. The first line should include
+      the issue number in the form "(#XXXX) Rest of message".
+
+    - The body should provide a meaningful commit message, which:
+
+      - uses the imperative, present tense: "change", not "changed" or
+        "changes".
+
+      - includes motivation for the change, and contrasts its
+        implementation with the previous behavior.
+
+    - Make sure that you have tests for the bug you are fixing, or
+      feature you are adding.
+
+    - Make sure the test suites passes after your commit:
+      `bundle exec rspec spec/acceptance` More information on [testing](#Testing) below
+
+    - When introducing a new feature, make sure it is properly
+      documented in the README.md
+
+  * Submission:
+
+    * Pre-requisites:
+
+      - Make sure you have a [GitHub account](https://github.com/join)
+
+      - [Create a ticket](https://tickets.puppetlabs.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppetlabs.com/browse/) you are patching for.
+
+    * Preferred method:
+
+      - Fork the repository on GitHub.
+
+      - Push your changes to a topic branch in your fork of the
+        repository. (the format ticket/1234-short_description_of_change is
+        usually preferred for this project).
+
+      - Submit a pull request to the repository in the puppetlabs
+        organization.
+
+The long version
+================
+
+  1.  Make separate commits for logically separate changes.
+
+      Please break your commits down into logically consistent units
+      which include new or changed tests relevant to the rest of the
+      change.  The goal of doing this is to make the diff easier to
+      read for whoever is reviewing your code.  In general, the easier
+      your diff is to read, the more likely someone will be happy to
+      review it and get it into the code base.
+
+      If you are going to refactor a piece of code, please do so as a
+      separate commit from your feature or bug fix changes.
+
+      We also really appreciate changes that include tests to make
+      sure the bug is not re-introduced, and that the feature is not
+      accidentally broken.
+
+      Describe the technical detail of the change(s).  If your
+      description starts to get too long, that is a good sign that you
+      probably need to split up your commit into more finely grained
+      pieces.
+
+      Commits which plainly describe the things which help
+      reviewers check the patch and future developers understand the
+      code are much more likely to be merged in with a minimum of
+      bike-shedding or requested changes.  Ideally, the commit message
+      would include information, and be in a form suitable for
+      inclusion in the release notes for the version of Puppet that
+      includes them.
+
+      Please also check that you are not introducing any trailing
+      whitespace or other "whitespace errors".  You can do this by
+      running "git diff --check" on your changes before you commit.
+
+  2.  Sending your patches
+
+      To submit your changes via a GitHub pull request, we _highly_
+      recommend that you have them on a topic branch, instead of
+      directly on "master".
+      It makes things much easier to keep track of, especially if
+      you decide to work on another thing before your first change
+      is merged in.
+
+      GitHub has some pretty good
+      [general documentation](http://help.github.com/) on using
+      their site.  They also have documentation on
+      [creating pull requests](http://help.github.com/send-pull-requests/).
+
+      In general, after pushing your topic branch up to your
+      repository on GitHub, you can switch to the branch in the
+      GitHub UI and click "Pull Request" towards the top of the page
+      in order to open a pull request.
+
+
+  3.  Update the related GitHub issue.
+
+      If there is a GitHub issue associated with the change you
+      submitted, then you should update the ticket to include the
+      location of your branch, along with any other commentary you
+      may wish to make.
+
+Testing
+=======
+
+Getting Started
+---------------
+
+Our puppet modules provide [`Gemfile`](./Gemfile)s which can tell a ruby
+package manager such as [bundler](http://bundler.io/) what Ruby packages,
+or Gems, are required to build, develop, and test this software.
+
+Please make sure you have [bundler installed](http://bundler.io/#getting-started)
+on your system, then use it to install all dependencies needed for this project,
+by running
+
+```shell
+% bundle install
+Fetching gem metadata from https://rubygems.org/........
+Fetching gem metadata from https://rubygems.org/..
+Using rake (10.1.0)
+Using builder (3.2.2)
+-- 8><-- many more --><8 --
+Using rspec-system-puppet (2.2.0)
+Using serverspec (0.6.3)
+Using rspec-system-serverspec (1.0.0)
+Using bundler (1.3.5)
+Your bundle is complete!
+Use `bundle show [gemname]` to see where a bundled gem is installed.
+```
+
+NOTE some systems may require you to run this command with sudo.
+
+If you already have those gems installed, make sure they are up-to-date:
+
+```shell
+% bundle update
+```
+
+With all dependencies in place and up-to-date we can now run the tests:
+
+```shell
+% rake spec
+```
+
+This will execute all the [rspec tests](http://rspec-puppet.com/) tests
+under [spec/defines](./spec/defines), [spec/classes](./spec/classes),
+and so on. rspec tests may have the same kind of dependencies as the
+module they are testing. While the module defines in its [Modulefile](./Modulefile),
+rspec tests define them in [.fixtures.yml](./fixtures.yml).
+
+Some puppet modules also come with [beaker](https://github.com/puppetlabs/beaker)
+tests. These tests spin up a virtual machine under
+[VirtualBox](https://www.virtualbox.org/)) with, controlling it with
+[Vagrant](http://www.vagrantup.com/) to actually simulate scripted test
+scenarios. In order to run these, you will need both of those tools
+installed on your system.
+
+You can run them by issuing the following command
+
+```shell
+% rake spec_clean
+% rspec spec/acceptance
+```
+
+This will now download a pre-fabricated image configured in the [default node-set](./spec/acceptance/nodesets/default.yml),
+install puppet, copy this module and install its dependencies per [spec/spec_helper_acceptance.rb](./spec/spec_helper_acceptance.rb)
+and then run all the tests under [spec/acceptance](./spec/acceptance).
+
+Writing Tests
+-------------
+
+XXX getting started writing tests.
+
+If you have commit access to the repository
+===========================================
+
+Even if you have commit access to the repository, you will still need to
+go through the process above, and have someone else review and merge
+in your changes.  The rule is that all changes must be reviewed by a
+developer on the project (that did not write the code) to ensure that
+all changes go through a code review process.
+
+Having someone other than the author of the topic branch recorded as
+performing the merge is the record that they performed the code
+review.
+
+
+Additional Resources
+====================
+
+* [Getting additional help](http://puppetlabs.com/community/get-help)
+
+* [Writing tests](http://projects.puppetlabs.com/projects/puppet/wiki/Development_Writing_Tests)
+
+* [Patchwork](https://patchwork.puppetlabs.com)
+
+* [General GitHub documentation](http://help.github.com/)
+
+* [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/Gemfile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,55 @@
+source ENV['GEM_SOURCE'] || 'https://rubygems.org'
+
+def location_for(place, fake_version = nil)
+  if place =~ /^(git[:@][^#]*)#(.*)/
+    [fake_version, { :git => $1, :branch => $2, :require => false }].compact
+  elsif place =~ /^file:\/\/(.*)/
+    ['>= 0', { :path => File.expand_path($1), :require => false }]
+  else
+    [place, { :require => false }]
+  end
+end
+
+group :development, :unit_tests do
+  gem 'rake', '~> 10.1.0',       :require => false
+  gem 'rspec', '~> 3.1.0',       :require => false
+  gem 'rspec-puppet', '~> 2.2',  :require => false
+  gem 'mocha',                   :require => false
+  # keep for its rake task for now
+  gem 'puppetlabs_spec_helper',  :require => false
+  gem 'puppet-lint',             :require => false
+  gem 'metadata-json-lint',      :require => false
+  gem 'pry',                     :require => false
+  gem 'simplecov',               :require => false
+end
+
+beaker_version = ENV['BEAKER_VERSION']
+beaker_rspec_version = ENV['BEAKER_RSPEC_VERSION']
+group :system_tests do
+  if beaker_version
+    gem 'beaker', *location_for(beaker_version)
+  end
+  if beaker_rspec_version
+    gem 'beaker-rspec', *location_for(beaker_rspec_version)
+  else
+    gem 'beaker-rspec', :require => false
+  end
+  gem 'serverspec', :require => false
+  gem 'beaker-puppet_install_helper', :require => false
+end
+
+facterversion = ENV['GEM_FACTER_VERSION'] || ENV['FACTER_GEM_VERSION']
+if facterversion
+  gem 'facter', *location_for(facterversion)
+else
+  gem 'facter', :require => false
+end
+
+puppetversion = ENV['GEM_PUPPET_VERSION'] || ENV['PUPPET_GEM_VERSION']
+if puppetversion
+  gem 'puppet', *location_for(puppetversion)
+else
+  gem 'puppet', :require => false
+end
+
+# vim:ft=ruby
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/LICENSE	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+Copyright (C) 2011 Puppet Labs Inc
+
+and some parts:
+
+Copyright (C) 2011 Krzysztof Wilczynski
+
+Puppet Labs can be contacted at: info@puppetlabs.com
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/README.markdown	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1118 @@
+#stdlib
+
+####Table of Contents
+
+1. [Overview](#overview)
+2. [Module Description - What the module does and why it is useful](#module-description)
+3. [Setup - The basics of getting started with stdlib](#setup)
+4. [Usage - Configuration options and additional functionality](#usage)
+5. [Reference - An under-the-hood peek at what the module is doing and how](#reference)
+5. [Limitations - OS compatibility, etc.](#limitations)
+6. [Development - Guide for contributing to the module](#development)
+
+##Overview
+
+Adds a standard library of resources for Puppet modules.
+
+##Module Description
+
+This module provides a standard library of resources for the development of Puppet modules. Puppet modules make heavy use of this standard library. The stdlib module adds the following resources to Puppet:
+
+ * Stages
+ * Facts
+ * Functions
+ * Defined resource types
+ * Types
+ * Providers
+
+> *Note:* As of version 3.7, Puppet Enterprise no longer includes the stdlib module. If you're running Puppet Enterprise, you should install the most recent release of stdlib for compatibility with Puppet modules.
+
+##Setup
+
+Installing the stdlib module adds the functions, facts, and resources of this standard library to Puppet.
+
+##Usage
+
+After you've installed stdlib, all of its functions, facts, and resources are available for module use or development.
+
+If you want to use a standardized set of run stages for Puppet, `include stdlib` in your manifest.
+
+* `stdlib`: Most of stdlib's features are automatically loaded by Puppet. To use standardized run stages in Puppet, declare this class in your manifest with `include stdlib`.
+
+  When declared, stdlib declares all other classes in the module. The only other class currently included in the module is `stdlib::stages`.
+
+The `stdlib::stages` class declares various run stages for deploying infrastructure, language runtimes, and application layers. The high level stages are (in order):
+
+  * setup
+  * main
+  * runtime
+  * setup_infra
+  * deploy_infra
+  * setup_app
+  * deploy_app
+  * deploy
+
+  Sample usage:
+
+  ~~~
+  node default {
+    include stdlib
+    class { java: stage => 'runtime' }
+  }
+  ~~~
+
+## Reference
+
+### Classes
+
+#### Public Classes
+
+  The stdlib class has no parameters.
+
+#### Private Classes
+
+* `stdlib::stages`: Manages a standard set of run stages for Puppet. It is managed by the stdlib class and should not be declared independently.
+
+### Types
+
+#### `file_line`
+ Ensures that a given line, including whitespace at the beginning and end, is contained within a file. If the line is not contained in the given file, Puppet will add the line. Multiple resources can be declared to manage multiple lines in the same file. You can also use `match` to replace existing lines.
+
+  ~~~
+  file_line { 'sudo_rule':
+    path => '/etc/sudoers',
+    line => '%sudo ALL=(ALL) ALL',
+  }
+  file_line { 'sudo_rule_nopw':
+    path => '/etc/sudoers',
+    line => '%sudonopw ALL=(ALL) NOPASSWD: ALL',
+  }
+  ~~~
+
+##### Parameters
+All parameters are optional, unless otherwise noted.
+
+* `after`: Specifies the line after which Puppet will add any new lines. (Existing lines are added in place.) Valid options: String. Default: Undefined.
+* `ensure`: Ensures whether the resource is present. Valid options: 'present', 'absent'. Default: 'present'.
+* `line`: **Required.** Sets the line to be added to the file located by the `path` parameter. Valid options: String. Default: Undefined.
+* `match`: Specifies a regular expression to run against existing lines in the file; if a match is found, it is replaced rather than adding a new line. Valid options: String containing a regex. Default: Undefined.
+* `multiple`: Determines if `match` and/or `after` can change multiple lines. If set to false, an exception will be raised if more than one line matches. Valid options: 'true', 'false'. Default: Undefined.
+* `name`: Sets the name to use as the identity of the resource. This is necessary if you want the resource namevar to differ from the supplied `title` of the resource. Valid options: String. Default: Undefined.
+* `path`: **Required.** Defines the file in which Puppet will ensure the line specified by `line`. Must be an absolute path to the file.
+* `replace`: Defines whether the resource will overwrite an existing line that matches the `match` parameter. If set to false and a line is found matching the `match` param, the line will not be placed in the file. Valid options: true, false, yes, no. Default: true
+
+
+### Functions
+
+#### `abs`
+
+Returns the absolute value of a number; for example, '-34.56' becomes '34.56'. Takes a single integer and float value as an argument. *Type*: rvalue.
+
+#### `any2array`
+
+Converts any object to an array containing that object. Empty argument lists are converted to an empty array. Arrays are left untouched. Hashes are converted to arrays of alternating keys and values. *Type*: rvalue.
+
+#### `base64`
+
+Converts a string to and from base64 encoding. Requires an action ('encode', 'decode') and either a plain or base64-encoded string. *Type*: rvalue.
+
+#### `basename`
+
+Returns the `basename` of a path (optionally stripping an extension). For example:
+  * ('/path/to/a/file.ext') returns 'file.ext'
+  * ('relative/path/file.ext') returns 'file.ext'
+  * ('/path/to/a/file.ext', '.ext') returns 'file'
+
+*Type*: rvalue.
+
+#### `bool2num`
+
+Converts a boolean to a number. Converts values:
+  * 'false', 'f', '0', 'n', and 'no' to 0.
+  * 'true', 't', '1', 'y', and 'yes' to 1.
+  Requires a single boolean or string as an input. *Type*: rvalue.
+
+#### `capitalize`
+
+Capitalizes the first letter of a string or array of strings. Requires either a single string or an array as an input. *Type*: rvalue.
+
+#### `ceiling`
+
+Returns the smallest integer greater than or equal to the argument. Takes a single numeric value as an argument. *Type*: rvalue.
+
+#### `chomp`
+
+Removes the record separator from the end of a string or an array of strings; for example, 'hello\n' becomes 'hello'. Requires a single string or array as an input. *Type*: rvalue.
+
+#### `chop`
+
+Returns a new string with the last character removed. If the string ends with '\r\n', both characters are removed. Applying `chop` to an empty string returns an empty string. If you want to merely remove record separators, then you should use the `chomp` function. Requires a string or an array of strings as input. *Type*: rvalue.
+
+#### `concat`
+
+Appends the contents of multiple arrays onto the first array given. For example:
+  * `concat(['1','2','3'],'4')` returns ['1','2','3','4'].
+  * `concat(['1','2','3'],'4',['5','6','7'])` returns ['1','2','3','4','5','6','7'].
+  *Type*: rvalue.
+
+#### `convert_base`
+
+Converts a given integer or base 10 string representing an integer to a specified base, as a string. For example:
+  * `convert_base(5, 2)` results in: '101'
+  * `convert_base('254', '16')` results in: 'fe'
+
+#### `count`
+
+If called with only an array, it counts the number of elements that are **not** nil/undef. If called with a second argument, counts the number of elements in an array that matches the second argument. *Type*: rvalue.
+
+#### `defined_with_params`
+
+Takes a resource reference and an optional hash of attributes. Returns 'true' if a resource with the specified attributes has already been added to the catalog. Returns 'false' otherwise.
+
+  ~~~
+  user { 'dan':
+    ensure => present,
+  }
+
+  if ! defined_with_params(User[dan], {'ensure' => 'present' }) {
+    user { 'dan': ensure => present, }
+  }
+  ~~~
+
+*Type*: rvalue.
+
+#### `delete`
+
+Deletes all instances of a given element from an array, substring from a string, or key from a hash. For example, `delete(['a','b','c','b'], 'b')` returns ['a','c']; `delete('abracadabra', 'bra')` returns 'acada'. `delete({'a' => 1,'b' => 2,'c' => 3},['b','c'])` returns {'a'=> 1}. *Type*: rvalue.
+
+#### `delete_at`
+
+Deletes a determined indexed value from an array. For example, `delete_at(['a','b','c'], 1)` returns ['a','c']. *Type*: rvalue.
+
+#### `delete_values`
+
+Deletes all instances of a given value from a hash. For example, `delete_values({'a'=>'A','b'=>'B','c'=>'C','B'=>'D'}, 'B')` returns {'a'=>'A','c'=>'C','B'=>'D'} *Type*: rvalue.
+
+#### `delete_undef_values`
+
+Deletes all instances of the undef value from an array or hash. For example, `$hash = delete_undef_values({a=>'A', b=>'', c=>undef, d => false})` returns {a => 'A', b => '', d => false}. *Type*: rvalue.
+
+#### `difference`
+
+Returns the difference between two arrays. The returned array is a copy of the original array, removing any items that also appear in the second array. For example, `difference(["a","b","c"],["b","c","d"])` returns ["a"]. *Type*: rvalue.
+
+#### `dirname`
+
+Returns the `dirname` of a path. For example, `dirname('/path/to/a/file.ext')` returns '/path/to/a'. *Type*: rvalue.
+
+#### `dos2unix`
+
+Returns the Unix version of the given string. Very useful when using a File resource with a cross-platform template. *Type*: rvalue.
+
+~~~
+file{$config_file:
+  ensure  => file,
+  content => dos2unix(template('my_module/settings.conf.erb')),
+}
+~~~
+
+See also [unix2dos](#unix2dos).
+
+#### `downcase`
+
+Converts the case of a string or of all strings in an array to lowercase. *Type*: rvalue.
+
+#### `empty`
+
+Returns 'true' if the variable is empty. *Type*: rvalue.
+
+#### `ensure_packages`
+
+Takes a list of packages and only installs them if they don't already exist. It optionally takes a hash as a second parameter to be passed as the third argument to the `ensure_resource()` function. *Type*: statement.
+
+#### `ensure_resource`
+
+Takes a resource type, title, and a hash of attributes that describe the resource(s).
+
+~~~
+user { 'dan':
+  ensure => present,
+}
+~~~
+
+This example only creates the resource if it does not already exist:
+
+  `ensure_resource('user', 'dan', {'ensure' => 'present' })`
+
+If the resource already exists, but does not match the specified parameters, this function attempts to recreate the resource, leading to a duplicate resource definition error.
+
+An array of resources can also be passed in, and each will be created with the type and parameters specified if it doesn't already exist.
+
+  `ensure_resource('user', ['dan','alex'], {'ensure' => 'present'})`
+
+*Type*: statement.
+
+#### `flatten`
+
+Flattens deeply nested arrays and returns a single flat array as a result. For example, `flatten(['a', ['b', ['c']]])` returns ['a','b','c']. *Type*: rvalue.
+
+#### `floor`
+
+Takes a single numeric value as an argument, and returns the largest integer less than or equal to the argument. *Type*: rvalue.
+
+#### `fqdn_rand_string`
+
+Generates a random alphanumeric string using an optionally-specified character set (default is alphanumeric), combining the `$fqdn` fact and an optional seed for repeatable randomness.
+
+*Usage:*
+~~~
+fqdn_rand_string(LENGTH, [CHARSET], [SEED])
+~~~
+*Examples:*
+~~~
+fqdn_rand_string(10)
+fqdn_rand_string(10, 'ABCDEF!@#$%^')
+fqdn_rand_string(10, '', 'custom seed')
+~~~
+
+*Type*: rvalue.
+
+#### `fqdn_rotate`
+
+Rotates an array or string a random number of times, combining the `$fqdn` fact and an optional seed for repeatable randomness.
+
+*Usage:*
+~~~
+fqdn_rotate(VALUE, [SEED])
+~~~
+*Examples:*
+~~~
+fqdn_rotate(['a', 'b', 'c', 'd'])
+fqdn_rotate('abcd')
+fqdn_rotate([1, 2, 3], 'custom seed')
+~~~
+
+*Type*: rvalue.
+
+#### `get_module_path`
+
+Returns the absolute path of the specified module for the current environment.
+
+  `$module_path = get_module_path('stdlib')`
+
+*Type*: rvalue.
+
+#### `getparam`
+
+Takes a resource reference and the name of the parameter, and returns the value of the resource's parameter.
+
+For example, the following returns 'param_value':
+
+  ~~~
+  define example_resource($param) {
+  }
+
+  example_resource { "example_resource_instance":
+    param => "param_value"
+  }
+
+  getparam(Example_resource["example_resource_instance"], "param")
+  ~~~
+
+*Type*: rvalue.
+
+#### `getvar`
+
+Looks up a variable in a remote namespace.
+
+For example:
+
+  ~~~
+  $foo = getvar('site::data::foo')
+  # Equivalent to $foo = $site::data::foo
+  ~~~
+
+This is useful if the namespace itself is stored in a string:
+
+  ~~~
+  $datalocation = 'site::data'
+  $bar = getvar("${datalocation}::bar")
+  # Equivalent to $bar = $site::data::bar
+  ~~~
+
+*Type*: rvalue.
+
+#### `grep`
+
+Searches through an array and returns any elements that match the provided regular expression. For example, `grep(['aaa','bbb','ccc','aaaddd'], 'aaa')` returns ['aaa','aaaddd']. *Type*: rvalue.
+
+#### `has_interface_with`
+
+Returns a boolean based on kind and value:
+  * macaddress
+  * netmask
+  * ipaddress
+  * network
+
+*Examples:*
+
+  ~~~
+  has_interface_with("macaddress", "x:x:x:x:x:x")
+  has_interface_with("ipaddress", "127.0.0.1")    => true
+  ~~~
+
+If no kind is given, then the presence of the interface is checked:
+
+  ~~~
+  has_interface_with("lo")                        => true
+  ~~~
+
+*Type*: rvalue.
+
+#### `has_ip_address`
+
+Returns 'true' if the client has the requested IP address on some interface. This function iterates through the `interfaces` fact and checks the `ipaddress_IFACE` facts, performing a simple string comparison. *Type*: rvalue.
+
+#### `has_ip_network`
+
+Returns 'true' if the client has an IP address within the requested network. This function iterates through the `interfaces` fact and checks the `network_IFACE` facts, performing a simple string comparision. *Type*: rvalue.
+
+#### `has_key`
+
+Determines if a hash has a certain key value.
+
+*Example*:
+
+  ~~~
+  $my_hash = {'key_one' => 'value_one'}
+  if has_key($my_hash, 'key_two') {
+    notice('we will not reach here')
+  }
+  if has_key($my_hash, 'key_one') {
+    notice('this will be printed')
+  }
+  ~~~
+
+*Type*: rvalue.
+
+#### `hash`
+
+Converts an array into a hash. For example, `hash(['a',1,'b',2,'c',3])` returns {'a'=>1,'b'=>2,'c'=>3}. *Type*: rvalue.
+
+#### `intersection`
+
+Returns an array an intersection of two. For example, `intersection(["a","b","c"],["b","c","d"])` returns ["b","c"]. *Type*: rvalue.
+
+#### `is_array`
+
+Returns 'true' if the variable passed to this function is an array. *Type*: rvalue.
+
+#### `is_bool`
+
+Returns 'true' if the variable passed to this function is a boolean. *Type*: rvalue.
+
+#### `is_domain_name`
+
+Returns 'true' if the string passed to this function is a syntactically correct domain name. *Type*: rvalue.
+
+#### `is_float`
+
+Returns 'true' if the variable passed to this function is a float. *Type*: rvalue.
+
+#### `is_function_available`
+
+Accepts a string as an argument and determines whether the Puppet runtime has access to a function by that name. It returns 'true' if the function exists, 'false' if not. *Type*: rvalue.
+
+#### `is_hash`
+
+Returns 'true' if the variable passed to this function is a hash. *Type*: rvalue.
+
+#### `is_integer`
+
+Returns 'true' if the variable returned to this string is an integer. *Type*: rvalue.
+
+#### `is_ip_address`
+
+Returns 'true' if the string passed to this function is a valid IP address. *Type*: rvalue.
+
+#### `is_mac_address`
+
+Returns 'true' if the string passed to this function is a valid MAC address. *Type*: rvalue.
+
+#### `is_numeric`
+
+Returns 'true' if the variable passed to this function is a number. *Type*: rvalue.
+
+#### `is_string`
+
+Returns 'true' if the variable passed to this function is a string. *Type*: rvalue.
+
+#### `join`
+
+Joins an array into a string using a separator. For example, `join(['a','b','c'], ",")` results in: "a,b,c". *Type*: rvalue.
+
+#### `join_keys_to_values`
+
+Joins each key of a hash to that key's corresponding value with a separator. Keys and values are cast to strings. The return value is an array in which each element is one joined key/value pair. For example, `join_keys_to_values({'a'=>1,'b'=>2}, " is ")` results in ["a is 1","b is 2"]. *Type*: rvalue.
+
+#### `keys`
+
+Returns the keys of a hash as an array. *Type*: rvalue.
+
+#### `loadyaml`
+
+Loads a YAML file containing an array, string, or hash, and returns the data in the corresponding native data type. For example:
+
+  ~~~
+  $myhash = loadyaml('/etc/puppet/data/myhash.yaml')
+  ~~~
+
+*Type*: rvalue.
+
+#### `load_module_metadata`
+
+Loads the metadata.json of a target module. Can be used to determine module version and authorship for dynamic support of modules.
+
+  ~~~
+  $metadata = load_module_metadata('archive')
+  notify { $metadata['author']: }
+  ~~~
+
+*Type*: rvalue.
+
+#### `lstrip`
+
+Strips spaces to the left of a string. *Type*: rvalue.
+
+#### `max`
+
+Returns the highest value of all arguments. Requires at least one argument. *Type*: rvalue.
+
+#### `member`
+
+This function determines if a variable is a member of an array. The variable can be either a string, array, or fixnum. For example, `member(['a','b'], 'b')` and `member(['a','b','c'], ['b','c'])` return 'true', while `member(['a','b'], 'c')` and `member(['a','b','c'], ['c','d'])` return 'false'. *Note*: This function does not support nested arrays. If the first argument contains nested arrays, it will not recurse through them.
+
+*Type*: rvalue.
+
+#### `merge`
+
+Merges two or more hashes together and returns the resulting hash.
+
+*Example*:
+
+  ~~~
+  $hash1 = {'one' => 1, 'two' => 2}
+  $hash2 = {'two' => 'dos', 'three' => 'tres'}
+  $merged_hash = merge($hash1, $hash2)
+  # The resulting hash is equivalent to:
+  # $merged_hash =  {'one' => 1, 'two' => 'dos', 'three' => 'tres'}
+  ~~~
+
+When there is a duplicate key, the key in the rightmost hash "wins." *Type*: rvalue.
+
+#### `min`
+
+Returns the lowest value of all arguments. Requires at least one argument. *Type*: rvalue.
+
+#### `num2bool`
+
+Converts a number or a string representation of a number into a true boolean. Zero or anything non-numeric becomes 'false'. Numbers greater than 0 become 'true'. *Type*: rvalue.
+
+#### `parsejson`
+
+Converts a string of JSON into the correct Puppet structure. *Type*: rvalue.
+
+#### `parseyaml`
+
+Converts a string of YAML into the correct Puppet structure. *Type*: rvalue.
+
+#### `pick`
+
+From a list of values, returns the first value that is not undefined or an empty string. Takes any number of arguments, and raises an error if all values are undefined or empty.
+
+  ~~~
+  $real_jenkins_version = pick($::jenkins_version, '1.449')
+  ~~~
+
+*Type*: rvalue.
+
+#### `prefix`
+
+Applies a prefix to all elements in an array, or to the keys in a hash.
+For example:
+* `prefix(['a','b','c'], 'p')` returns ['pa','pb','pc']
+* `prefix({'a'=>'b','b'=>'c','c'=>'d'}, 'p')` returns {'pa'=>'b','pb'=>'c','pc'=>'d'}.
+
+*Type*: rvalue.
+
+#### `assert_private`
+
+Sets the current class or definition as private. Calling the class or definition from outside the current module will fail.
+
+For example, `assert_private()` called in class `foo::bar` outputs the following message if class is called from outside module `foo`:
+
+  ~~~
+  Class foo::bar is private
+  ~~~
+
+  To specify the error message you want to use:
+
+  ~~~
+  assert_private("You're not supposed to do that!")
+  ~~~
+
+*Type*: statement.
+
+#### `pw_hash`
+
+Hashes a password using the crypt function. Provides a hash usable on most POSIX systems.
+
+The first argument to this function is the password to hash. If it is undef or an empty string, this function returns undef.
+
+The second argument to this function is which type of hash to use. It will be converted into the appropriate crypt(3) hash specifier. Valid hash types are:
+
+|Hash type            |Specifier|
+|---------------------|---------|
+|MD5                  |1        |
+|SHA-256              |5        |
+|SHA-512 (recommended)|6        |
+
+The third argument to this function is the salt to use.
+
+*Type*: rvalue.
+
+**Note:** this uses the Puppet master's implementation of crypt(3). If your environment contains several different operating systems, ensure that they are compatible before using this function.
+
+#### `range`
+
+Extrapolates a range as an array when given in the form of '(start, stop)'. For example, `range("0", "9")` returns [0,1,2,3,4,5,6,7,8,9]. Zero-padded strings are converted to integers automatically, so `range("00", "09")` returns [0,1,2,3,4,5,6,7,8,9].
+
+Non-integer strings are accepted; `range("a", "c")` returns ["a","b","c"], and `range("host01", "host10")` returns ["host01", "host02", ..., "host09", "host10"].
+
+Passing a third argument will cause the generated range to step by that interval, e.g. `range("0", "9", "2")` returns ["0","2","4","6","8"].
+
+*Type*: rvalue.
+
+#### `reject`
+
+Searches through an array and rejects all elements that match the provided regular expression. For example, `reject(['aaa','bbb','ccc','aaaddd'], 'aaa')` returns ['bbb','ccc']. *Type*: rvalue.
+
+#### `reverse`
+
+Reverses the order of a string or array. *Type*: rvalue.
+
+#### `rstrip`
+
+Strips spaces to the right of the string. *Type*: rvalue.
+
+#### `shuffle`
+
+Randomizes the order of a string or array elements. *Type*: rvalue.
+
+#### `size`
+
+Returns the number of elements in a string, an array or a hash. *Type*: rvalue.
+
+#### `sort`
+
+Sorts strings and arrays lexically. *Type*: rvalue.
+
+#### `squeeze`
+
+Returns a new string where runs of the same character that occur in this set are replaced by a single character. *Type*: rvalue.
+
+#### `str2bool`
+
+Converts a string to a boolean. This attempts to convert strings that contain values such as '1', 't', 'y', and 'yes' to 'true' and strings that contain values such as '0', 'f', 'n', and 'no' to 'false'. *Type*: rvalue.
+
+#### `str2saltedsha512`
+
+Converts a string to a salted-SHA512 password hash, used for OS X versions >= 10.7. Given any string, this function returns a hex version of a salted-SHA512 password hash, which can be inserted into your Puppet
+manifests as a valid password attribute. *Type*: rvalue.
+
+#### `strftime`
+
+Returns formatted time. For example, `strftime("%s")` returns the time since Unix epoch, and `strftime("%Y-%m-%d")` returns the date. *Type*: rvalue.
+
+  *Format:*
+
+    * `%a`: The abbreviated weekday name ('Sun')
+    * `%A`: The full weekday name ('Sunday')
+    * `%b`: The abbreviated month name ('Jan')
+    * `%B`: The full month name ('January')
+    * `%c`: The preferred local date and time representation
+    * `%C`: Century (20 in 2009)
+    * `%d`: Day of the month (01..31)
+    * `%D`: Date (%m/%d/%y)
+    * `%e`: Day of the month, blank-padded ( 1..31)
+    * `%F`: Equivalent to %Y-%m-%d (the ISO 8601 date format)
+    * `%h`: Equivalent to %b
+    * `%H`: Hour of the day, 24-hour clock (00..23)
+    * `%I`: Hour of the day, 12-hour clock (01..12)
+    * `%j`: Day of the year (001..366)
+    * `%k`: Hour, 24-hour clock, blank-padded ( 0..23)
+    * `%l`: Hour, 12-hour clock, blank-padded ( 0..12)
+    * `%L`: Millisecond of the second (000..999)
+    * `%m`: Month of the year (01..12)
+    * `%M`: Minute of the hour (00..59)
+    * `%n`: Newline (\n)
+    * `%N`: Fractional seconds digits, default is 9 digits (nanosecond)
+      * `%3N`: Millisecond (3 digits)
+      * `%6N`: Microsecond (6 digits)
+      * `%9N`: Nanosecond (9 digits)
+    * `%p`: Meridian indicator ('AM' or 'PM')
+    * `%P`: Meridian indicator ('am' or 'pm')
+    * `%r`: Time, 12-hour (same as %I:%M:%S %p)
+    * `%R`: Time, 24-hour (%H:%M)
+    * `%s`: Number of seconds since the Unix epoch, 1970-01-01 00:00:00 UTC.
+    * `%S`: Second of the minute (00..60)
+    * `%t`: Tab character (	)
+    * `%T`: Time, 24-hour (%H:%M:%S)
+    * `%u`: Day of the week as a decimal, Monday being 1. (1..7)
+    * `%U`: Week number of the current year, starting with the first Sunday as the first day of the first week (00..53)
+    * `%v`: VMS date (%e-%b-%Y)
+    * `%V`: Week number of year according to ISO 8601 (01..53)
+    * `%W`: Week number of the current year, starting with the first Monday as the first day of the first week (00..53)
+    * `%w`: Day of the week (Sunday is 0, 0..6)
+    * `%x`: Preferred representation for the date alone, no time
+    * `%X`: Preferred representation for the time alone, no date
+    * `%y`: Year without a century (00..99)
+    * `%Y`: Year with century
+    * `%z`: Time zone as hour offset from UTC (e.g. +0900)
+    * `%Z`: Time zone name
+    * `%%`: Literal '%' character
+
+#### `strip`
+
+Removes leading and trailing whitespace from a string or from every string inside an array. For example, `strip("    aaa   ")` results in "aaa". *Type*: rvalue.
+
+#### `suffix`
+
+Applies a suffix to all elements in an array. For example, `suffix(['a','b','c'], 'p')` returns ['ap','bp','cp']. *Type*: rvalue.
+
+#### `swapcase`
+
+Swaps the existing case of a string. For example, `swapcase("aBcD")` results in "AbCd". *Type*: rvalue.
+
+#### `time`
+
+Returns the current Unix epoch time as an integer. For example, `time()` returns something like '1311972653'. *Type*: rvalue.
+
+#### `to_bytes`
+
+Converts the argument into bytes, for example "4 kB" becomes "4096". Takes a single string value as an argument. *Type*: rvalue.
+
+#### `try_get_value`
+
+*Type*: rvalue.
+
+Looks up into a complex structure of arrays and hashes and returns a value
+or the default value if nothing was found.
+
+Key can contain slashes to describe path components. The function will go down
+the structure and try to extract the required value.
+
+$data = {
+  'a' => {
+    'b' => [
+      'b1',
+      'b2',
+      'b3',
+    ]
+  }
+}
+
+$value = try_get_value($data, 'a/b/2', 'not_found', '/')
+=> $value = 'b3'
+
+a -> first hash key
+b -> second hash key
+2 -> array index starting with 0
+
+not_found -> (optional) will be returned if there is no value or the path did not match. Defaults to nil.
+/ -> (optional) path delimiter. Defaults to '/'.
+
+In addition to the required "key" argument, "try_get_value" accepts default
+argument. It will be returned if no value was found or a path component is
+missing. And the fourth argument can set a variable path separator.
+
+#### `type3x`
+
+Returns a string description of the type when passed a value. Type can be a string, array, hash, float, integer, or boolean. This function will be removed when Puppet 3 support is dropped and the new type system can be used. *Type*: rvalue.
+
+#### `type_of`
+
+Returns the literal type when passed a value. Requires the new parser. Useful for comparison of types with `<=` such as in `if type_of($some_value) <= Array[String] { ... }` (which is equivalent to `if $some_value =~ Array[String] { ... }`) *Type*: rvalue.
+
+#### `union`
+
+Returns a union of two or more arrays, without duplicates. For example, `union(["a","b","c"],["b","c","d"])` returns ["a","b","c","d"]. *Type*: rvalue.
+
+#### `unique`
+
+Removes duplicates from strings and arrays. For example, `unique("aabbcc")` returns 'abc', and `unique(["a","a","b","b","c","c"])` returns ["a","b","c"]. *Type*: rvalue.
+
+#### `unix2dos`
+
+Returns the DOS version of the given string. Very useful when using a File resource with a cross-platform template. *Type*: rvalue.
+
+~~~
+file{$config_file:
+  ensure  => file,
+  content => unix2dos(template('my_module/settings.conf.erb')),
+}
+~~~
+
+See also [dos2unix](#dos2unix).
+
+#### `upcase`
+
+Converts an object, array or hash of objects that respond to upcase to uppercase. For example, `upcase('abcd')` returns 'ABCD'. *Type*: rvalue.
+
+#### `uriescape`
+
+URLEncodes a string or array of strings. Requires either a single string or an array as an input. *Type*: rvalue.
+
+#### `validate_absolute_path`
+
+Validates that a given string represents an absolute path in the filesystem. Works for Windows and Unix style paths.
+
+The following values pass:
+
+~~~
+$my_path = 'C:/Program Files (x86)/Puppet Labs/Puppet'
+validate_absolute_path($my_path)
+$my_path2 = '/var/lib/puppet'
+validate_absolute_path($my_path2)
+$my_path3 = ['C:/Program Files (x86)/Puppet Labs/Puppet','C:/Program Files/Puppet Labs/Puppet']
+validate_absolute_path($my_path3)
+$my_path4 = ['/var/lib/puppet','/usr/share/puppet']
+validate_absolute_path($my_path4)
+~~~
+
+The following values fail, causing compilation to abort:
+
+~~~
+validate_absolute_path(true)
+validate_absolute_path('../var/lib/puppet')
+validate_absolute_path('var/lib/puppet')
+validate_absolute_path([ 'var/lib/puppet', '/var/foo' ])
+validate_absolute_path([ '/var/lib/puppet', 'var/foo' ])
+$undefined = undef
+validate_absolute_path($undefined)
+~~~
+
+*Type*: statement.
+
+#### `validate_array`
+
+Validates that all passed values are array data structures. Aborts catalog compilation if any value fails this check.
+
+The following values pass:
+
+~~~
+$my_array = [ 'one', 'two' ]
+validate_array($my_array)
+~~~
+
+The following values fail, causing compilation to abort:
+
+~~~
+validate_array(true)
+validate_array('some_string')
+$undefined = undef
+validate_array($undefined)
+~~~
+
+*Type*: statement.
+
+#### `validate_augeas`
+
+Performs validation of a string using an Augeas lens. The first argument of this function should be the string to test, and the second argument should be the name of the Augeas lens to use. If Augeas fails to parse the string with the lens, the compilation aborts with a parse error.
+
+A third optional argument lists paths which should **not** be found in the file. The `$file` variable points to the location of the temporary file being tested in the Augeas tree.
+
+For example, to make sure your $passwdcontent never contains user `foo`:
+
+~~~
+validate_augeas($passwdcontent, 'Passwd.lns', ['$file/foo'])
+~~~
+
+To ensure that no users use the '/bin/barsh' shell:
+
+~~~
+validate_augeas($passwdcontent, 'Passwd.lns', ['$file/*[shell="/bin/barsh"]']
+~~~
+
+You can pass a fourth argument as the error message raised and shown to the user:
+
+~~~
+validate_augeas($sudoerscontent, 'Sudoers.lns', [], 'Failed to validate sudoers content with Augeas')
+~~~
+
+*Type*: statement.
+
+#### `validate_bool`
+
+Validates that all passed values are either true or false. Aborts catalog compilation if any value fails this check.
+
+The following values will pass:
+
+~~~
+$iamtrue = true
+validate_bool(true)
+validate_bool(true, true, false, $iamtrue)
+~~~
+
+The following values will fail, causing compilation to abort:
+
+~~~
+$some_array = [ true ]
+validate_bool("false")
+validate_bool("true")
+validate_bool($some_array)
+~~~
+
+*Type*: statement.
+
+#### `validate_cmd`
+
+Performs validation of a string with an external command. The first argument of this function should be a string to test, and the second argument should be a path to a test command taking a % as a placeholder for the file path (will default to the end of the command if no % placeholder given). If the command is launched against a tempfile containing the passed string, or returns a non-null value, compilation will abort with a parse error.
+
+If a third argument is specified, this will be the error message raised and seen by the user.
+
+~~~
+# Defaults to end of path
+validate_cmd($sudoerscontent, '/usr/sbin/visudo -c -f', 'Visudo failed to validate sudoers content')
+~~~
+~~~
+# % as file location
+validate_cmd($haproxycontent, '/usr/sbin/haproxy -f % -c', 'Haproxy failed to validate config content')
+~~~
+
+*Type*: statement.
+
+#### `validate_hash`
+
+Validates that all passed values are hash data structures. Aborts catalog compilation if any value fails this check.
+
+  The following values will pass:
+
+  ~~~
+  $my_hash = { 'one' => 'two' }
+  validate_hash($my_hash)
+  ~~~
+
+  The following values will fail, causing compilation to abort:
+
+  ~~~
+  validate_hash(true)
+  validate_hash('some_string')
+  $undefined = undef
+  validate_hash($undefined)
+  ~~~
+
+*Type*: statement.
+
+#### `validate_integer`
+
+Validates that the first argument is an integer (or an array of integers). Aborts catalog compilation if any of the checks fail.
+
+  The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
+
+  The third argument is optional and passes a minimum. (All elements of) the first argument has to be greater or equal to this min.
+  If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
+  if (all elements of) the first argument are greater or equal to the given minimum.
+
+  It will fail if the first argument is not an integer or array of integers, and if arg 2 and arg 3 are not convertable to an integer.
+
+  The following values will pass:
+
+  ~~~
+  validate_integer(1)
+  validate_integer(1, 2)
+  validate_integer(1, 1)
+  validate_integer(1, 2, 0)
+  validate_integer(2, 2, 2)
+  validate_integer(2, '', 0)
+  validate_integer(2, undef, 0)
+  $foo = undef
+  validate_integer(2, $foo, 0)
+  validate_integer([1,2,3,4,5], 6)
+  validate_integer([1,2,3,4,5], 6, 0)
+  ~~~
+
+  * Plus all of the above, but any combination of values passed as strings ('1' or "1").
+  * Plus all of the above, but with (correct) combinations of negative integer values.
+
+  The following values will fail, causing compilation to abort:
+
+  ~~~
+  validate_integer(true)
+  validate_integer(false)
+  validate_integer(7.0)
+  validate_integer({ 1 => 2 })
+  $foo = undef
+  validate_integer($foo)
+  validate_integer($foobaridontexist)
+
+  validate_integer(1, 0)
+  validate_integer(1, true)
+  validate_integer(1, '')
+  validate_integer(1, undef)
+  validate_integer(1, , 0)
+  validate_integer(1, 2, 3)
+  validate_integer(1, 3, 2)
+  validate_integer(1, 3, true)
+  ~~~
+
+  * Plus all of the above, but any combination of values passed as strings ('false' or "false").
+  * Plus all of the above, but with incorrect combinations of negative integer values.
+  * Plus all of the above, but with non-integer items in arrays or maximum / minimum argument.
+
+  *Type*: statement.
+
+#### `validate_numeric`
+
+Validates that the first argument is a numeric value (or an array of numeric values). Aborts catalog compilation if any of the checks fail.
+
+  The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
+
+  The third argument is optional and passes a minimum. (All elements of) the first argument has to be greater or equal to this min.
+  If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
+  if (all elements of) the first argument are greater or equal to the given minimum.
+
+  It will fail if the first argument is not a numeric (Integer or Float) or array of numerics, and if arg 2 and arg 3 are not convertable to a numeric.
+
+  For passing and failing usage, see `validate_integer()`. It is all the same for validate_numeric, yet now floating point values are allowed, too.
+
+*Type*: statement.
+
+#### `validate_re`
+
+Performs simple validation of a string against one or more regular expressions. The first argument of this function should be the string to
+test, and the second argument should be a stringified regular expression (without the // delimiters) or an array of regular expressions. If none of the regular expressions match the string passed in, compilation aborts with a parse error.
+
+  You can pass a third argument as the error message raised and shown to the user.
+
+  The following strings validate against the regular expressions:
+
+  ~~~
+  validate_re('one', '^one$')
+  validate_re('one', [ '^one', '^two' ])
+  ~~~
+
+  The following string fails to validate, causing compilation to abort:
+
+  ~~~
+  validate_re('one', [ '^two', '^three' ])
+  ~~~
+
+  To set the error message:
+
+  ~~~
+  validate_re($::puppetversion, '^2.7', 'The $puppetversion fact value does not match 2.7')
+  ~~~
+
+*Type*: statement.
+
+#### `validate_slength`
+
+Validates that the first argument is a string (or an array of strings), and is less than or equal to the length of the second argument. It fails if the first argument is not a string or array of strings, or if arg 2 is not convertable to a number.  Optionally, a minimum string length can be given as the third argument.
+
+  The following values pass:
+
+  ~~~
+  validate_slength("discombobulate",17)
+  validate_slength(["discombobulate","moo"],17)
+  validate_slength(["discombobulate","moo"],17,3)
+  ~~~
+
+  The following values fail:
+
+  ~~~
+  validate_slength("discombobulate",1)
+  validate_slength(["discombobulate","thermometer"],5)
+  validate_slength(["discombobulate","moo"],17,10)
+  ~~~
+
+*Type*: statement.
+
+#### `validate_string`
+
+Validates that all passed values are string data structures. Aborts catalog compilation if any value fails this check.
+
+The following values pass:
+
+  ~~~
+  $my_string = "one two"
+  validate_string($my_string, 'three')
+  ~~~
+
+  The following values fail, causing compilation to abort:
+
+  ~~~
+  validate_string(true)
+  validate_string([ 'some', 'array' ])
+  ~~~
+
+*Note:* validate_string(undef) will not fail in this version of the functions API (incl. current and future parser).
+
+Instead, use:
+
+  ~~~
+  if $var == undef {
+    fail('...')
+  }
+  ~~~
+
+*Type*: statement.
+
+#### `values`
+
+Returns the values of a given hash. For example, given `$hash = {'a'=1, 'b'=2, 'c'=3} values($hash)` returns [1,2,3].
+
+*Type*: rvalue.
+
+#### `values_at`
+
+Finds values inside an array based on location. The first argument is the array you want to analyze, and the second argument can be a combination of:
+
+  * A single numeric index
+  * A range in the form of 'start-stop' (eg. 4-9)
+  * An array combining the above
+
+  For example, `values_at(['a','b','c'], 2)` returns ['c']; `values_at(['a','b','c'], ["0-1"])` returns ['a','b']; and `values_at(['a','b','c','d','e'], [0, "2-3"])` returns ['a','c','d'].
+
+*Type*: rvalue.
+
+#### `zip`
+
+Takes one element from first array given and merges corresponding elements from second array given. This generates a sequence of n-element arrays, where *n* is one more than the count of arguments. For example, `zip(['1','2','3'],['4','5','6'])` results in ["1", "4"], ["2", "5"], ["3", "6"]. *Type*: rvalue.
+
+##Limitations
+
+As of Puppet Enterprise 3.7, the stdlib module is no longer included in PE. PE users should install the most recent release of stdlib for compatibility with Puppet modules.
+
+###Version Compatibility
+
+Versions | Puppet 2.6 | Puppet 2.7 | Puppet 3.x | Puppet 4.x |
+:---------------|:-----:|:---:|:---:|:----:
+**stdlib 2.x**  | **yes** | **yes** | no | no
+**stdlib 3.x**  | no    | **yes**  | **yes** | no
+**stdlib 4.x**  | no    | **yes**  | **yes** | no
+**stdlib 4.6+**  | no    | **yes**  | **yes** | **yes**
+**stdlib 5.x**  | no    | no  | **yes**  | **yes**
+
+**stdlib 5.x**: When released, stdlib 5.x will drop support for Puppet 2.7.x. Please see [this discussion](https://github.com/puppetlabs/puppetlabs-stdlib/pull/176#issuecomment-30251414).
+
+##Development
+
+Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad hardware, software, and deployment configurations that Puppet is intended to serve. We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. For more information, see our [module contribution guide.](https://docs.puppetlabs.com/forge/contributing.html)
+
+To report or research a bug with any part of this module, please go to
+[http://tickets.puppetlabs.com/browse/PUP](http://tickets.puppetlabs.com/browse/PUP).
+
+##Contributors
+
+The list of contributors can be found at: https://github.com/puppetlabs/puppetlabs-stdlib/graphs/contributors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/README_DEVELOPER.markdown	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+Puppet Specific Facts
+=====================
+
+Facter is meant to stand alone and apart from Puppet.  However, Facter often
+runs inside Puppet and all custom facts included in the stdlib module will
+almost always be evaluated in the context of Puppet and Facter working
+together.
+
+Still, we don't want to write custom facts that blow up in the users face if
+Puppet is not loaded in memory.  This is often the case if the user runs
+`facter` without also supplying the `--puppet` flag.
+
+Ah! But Jeff, the custom fact won't be in the `$LOAD_PATH` unless the user
+supplies `--facter`! You might say...
+
+Not (always) true I say!  If the user happens to have a CWD of
+`<modulepath>/stdlib/lib` then the facts will automatically be evaluated and
+blow up.
+
+In any event, it's pretty easy to write a fact that has no value if Puppet is
+not loaded.  Simply do it like this:
+
+    Facter.add(:node_vardir) do
+      setcode do
+        # This will be nil if Puppet is not available.
+        Facter::Util::PuppetSettings.with_puppet do
+          Puppet[:vardir]
+        end
+      end
+    end
+
+The `Facter::Util::PuppetSettings.with_puppet` method accepts a block and
+yields to it only if the Puppet library is loaded.  If the Puppet library is
+not loaded, then the method silently returns `nil` which Facter interprets as
+an undefined fact value.  The net effect is that the fact won't be set.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/README_SPECS.markdown	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+NOTE
+====
+
+This project's specs depend on puppet core, and thus they require the
+`puppetlabs_spec_helper` project.  For more information please see the README
+in that project, which can be found here: [puppetlabs spec
+helper](https://github.com/puppetlabs/puppetlabs_spec_helper)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/RELEASE_PROCESS.markdown	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+# Contributing to this module #
+
+ * Work in a topic branch
+ * Submit a github pull request
+ * Address any comments / feeback
+ * Merge into master using --no-ff
+
+# Releasing this module #
+
+ * This module adheres to http://semver.org/
+ * Look for API breaking changes using git diff vX.Y.Z..master
+   * If no API breaking changes, the minor version may be bumped.
+   * If there are API breaking changes, the major version must be bumped.
+   * If there are only small minor changes, the patch version may be bumped.
+ * Update the CHANGELOG
+ * Update the Modulefile
+ * Commit these changes with a message along the lines of "Update CHANGELOG and
+   Modulefile for release"
+ * Create an annotated tag with git tag -a vX.Y.Z -m 'version X.Y.Z' (NOTE the
+   leading v as per semver.org)
+ * Push the tag with git push origin --tags
+ * Build a new package with puppet-module or the rake build task if it exists
+ * Publish the new package to the forge
+ * Bonus points for an announcement to puppet-users.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/Rakefile	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+require 'rubygems'
+# keep for compatibility for now
+require 'puppetlabs_spec_helper/rake_tasks'
+require 'puppet-lint/tasks/puppet-lint'
+PuppetLint.configuration.send('disable_80chars')
+PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"]
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/checksums.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,384 @@
+{
+  "CHANGELOG.md": "684f4b65583754d88ace0d93bcfc4889",
+  "CONTRIBUTING.md": "e2b8e8e433fc76b3798b7fe435f49375",
+  "Gemfile": "dcebff75dcc641a69ca89a5655c59bc3",
+  "LICENSE": "38a048b9d82e713d4e1b2573e370a756",
+  "README.markdown": "f0da8597fc6d0cacf01865cffc25e914",
+  "README_DEVELOPER.markdown": "220a8b28521b5c5d2ea87c4ddb511165",
+  "README_SPECS.markdown": "82bb4c6abbb711f40778b162ec0070c1",
+  "RELEASE_PROCESS.markdown": "94b92bc99ac4106ba1a74d5c04e520f9",
+  "Rakefile": "75050dfcd01aaa7d2ec03c5d80098d9c",
+  "examples/file_line.pp": "48f7f162127beffea8f8e3e58db2355a",
+  "examples/has_interface_with.pp": "d69d520cf3ff4d0b495480afaca359ef",
+  "examples/has_ip_address.pp": "32f42575e49aa66f0f2398a70ae2a9f4",
+  "examples/has_ip_network.pp": "bfb8db068c58d77c4dd7ae9697536537",
+  "examples/init.pp": "b52fd907330ddbd9c3e070cf39f7b317",
+  "lib/facter/facter_dot_d.rb": "878e161fc0c3682fb1a554fe28b8be60",
+  "lib/facter/pe_version.rb": "4a9353952963b011759f3e6652a10da5",
+  "lib/facter/puppet_vardir.rb": "c7ddc97e8a84ded3dd93baa5b9b3283d",
+  "lib/facter/root_home.rb": "4232c70191d50d408aa401b4067c66a8",
+  "lib/facter/util/puppet_settings.rb": "9f1d2593d0ae56bfca89d4b9266aeee1",
+  "lib/puppet/functions/type_of.rb": "71e19f89e167c45ec691ea6c7d319625",
+  "lib/puppet/parser/functions/abs.rb": "32161bd0435fdfc2aec2fc559d2b454b",
+  "lib/puppet/parser/functions/any2array.rb": "a81e71d6b67a551d38770ba9a1948a75",
+  "lib/puppet/parser/functions/assert_private.rb": "1365284f9e474ecec24cfe43ee8e7cf4",
+  "lib/puppet/parser/functions/base64.rb": "ae25adf92295df67ebd9edfabc9ecdd6",
+  "lib/puppet/parser/functions/basename.rb": "c61952b3f68fd86408c84fca2c3febb1",
+  "lib/puppet/parser/functions/bool2num.rb": "f953f5fc094c2ae3908a72d8840ba291",
+  "lib/puppet/parser/functions/bool2str.rb": "34497af8db94754542b9d4cfacc8a27f",
+  "lib/puppet/parser/functions/camelcase.rb": "71c67b71eac4b7f46a0dd22cb915d2e6",
+  "lib/puppet/parser/functions/capitalize.rb": "da131748a9d32da9eb0b6438e39377eb",
+  "lib/puppet/parser/functions/ceiling.rb": "dfa9b1c75ce89344026b3b5aed2d190f",
+  "lib/puppet/parser/functions/chomp.rb": "2b7dc42f9967edd34cfa0ba9a97229ca",
+  "lib/puppet/parser/functions/chop.rb": "0ec76f54afd94201f35785dfeb2092b5",
+  "lib/puppet/parser/functions/concat.rb": "2a12f95e94669129827ee2f2a26349c3",
+  "lib/puppet/parser/functions/convert_base.rb": "c3b3e59a49318af98dcb88aed7156629",
+  "lib/puppet/parser/functions/count.rb": "9eb74eccd93e2b3c87fd5ea14e329eba",
+  "lib/puppet/parser/functions/deep_merge.rb": "d83696855578fb81b64b9e92b9c7cc7c",
+  "lib/puppet/parser/functions/defined_with_params.rb": "ffab4433d03f32b551f2ea024a2948fc",
+  "lib/puppet/parser/functions/delete.rb": "cec92c5de6d748c8dc93ca7d25ac1c68",
+  "lib/puppet/parser/functions/delete_at.rb": "6bc24b79390d463d8be95396c963381a",
+  "lib/puppet/parser/functions/delete_undef_values.rb": "b32d4a3925753b2eb2c318cbd7f14404",
+  "lib/puppet/parser/functions/delete_values.rb": "39b147f7d369bb5f809044b6341954a2",
+  "lib/puppet/parser/functions/difference.rb": "e31b95fbaf974cf853a510177368bfb9",
+  "lib/puppet/parser/functions/dirname.rb": "8a5579f9a9a13fd737ba65eccf8e6d5a",
+  "lib/puppet/parser/functions/dos2unix.rb": "be8359a5106a7832be4180e8207dd586",
+  "lib/puppet/parser/functions/downcase.rb": "73121616d73339cf8dd10e0de61a6c50",
+  "lib/puppet/parser/functions/empty.rb": "0b6ca9d0550a39c1ca50fc3d1ecbc98c",
+  "lib/puppet/parser/functions/ensure_packages.rb": "fbed5c0c9bf82b7746e01f15f89d184f",
+  "lib/puppet/parser/functions/ensure_resource.rb": "de703fe63392b939fc2b4392975263de",
+  "lib/puppet/parser/functions/flatten.rb": "25777b76f9719162a8bab640e5595b7a",
+  "lib/puppet/parser/functions/floor.rb": "42cad4c689231a51526c55a6f0985d1f",
+  "lib/puppet/parser/functions/fqdn_rand_string.rb": "9ac5f18e563094aee62ef7586267025d",
+  "lib/puppet/parser/functions/fqdn_rotate.rb": "770d510a2e50d19b2dd42b6edef3fb1f",
+  "lib/puppet/parser/functions/get_module_path.rb": "d4bf50da25c0b98d26b75354fa1bcc45",
+  "lib/puppet/parser/functions/getparam.rb": "4dd7a0e35f4a3780dcfc9b19b4e0006e",
+  "lib/puppet/parser/functions/getvar.rb": "344f1ce85dcb7512d37e8702ccbabb66",
+  "lib/puppet/parser/functions/grep.rb": "5682995af458b05f3b53dd794c4bf896",
+  "lib/puppet/parser/functions/has_interface_with.rb": "e135f09dbecc038c3aa9ae03127617ef",
+  "lib/puppet/parser/functions/has_ip_address.rb": "ee207f47906455a5aa49c4fb219dd325",
+  "lib/puppet/parser/functions/has_ip_network.rb": "b4d726c8b2a0afac81ced8a3a28aa731",
+  "lib/puppet/parser/functions/has_key.rb": "7cd9728c38f0b0065f832dabd62b0e7e",
+  "lib/puppet/parser/functions/hash.rb": "9d072527dfc7354b69292e9302906530",
+  "lib/puppet/parser/functions/intersection.rb": "924ac4aceec7b896952166a7ec08fdb1",
+  "lib/puppet/parser/functions/is_array.rb": "875ca4356cb0d7a10606fb146b4a3d11",
+  "lib/puppet/parser/functions/is_bool.rb": "e693b7c4b5366cff1380b6e0c7dd7b11",
+  "lib/puppet/parser/functions/is_domain_name.rb": "6ca1f2708add756a6803b29d593d5830",
+  "lib/puppet/parser/functions/is_float.rb": "10e0d3ecf75fac15e415aee79acf70dc",
+  "lib/puppet/parser/functions/is_function_available.rb": "628428bbcd9313ce09783d9484330e09",
+  "lib/puppet/parser/functions/is_hash.rb": "8c7d9a05084dab0389d1b779c8a05b1a",
+  "lib/puppet/parser/functions/is_integer.rb": "c665be82686aa4729959bb42c66a7510",
+  "lib/puppet/parser/functions/is_ip_address.rb": "a714a736c1560e8739aaacd9030cca00",
+  "lib/puppet/parser/functions/is_mac_address.rb": "6dd3c96437d49e68630869b0b464e7f2",
+  "lib/puppet/parser/functions/is_numeric.rb": "93ddc9d4c0834a5e5e0562d7b3cdce91",
+  "lib/puppet/parser/functions/is_string.rb": "2bd9a652bbb2668323eee6c57729ff64",
+  "lib/puppet/parser/functions/join.rb": "a285a05c015ae278608f6454aef211ea",
+  "lib/puppet/parser/functions/join_keys_to_values.rb": "f29da49531228f6ca5b3aa0df00a14c2",
+  "lib/puppet/parser/functions/keys.rb": "eb6ac815ea14fbf423580ed903ef7bad",
+  "lib/puppet/parser/functions/load_module_metadata.rb": "5acfc279c52c4806bf6d4ddca6934fd0",
+  "lib/puppet/parser/functions/loadyaml.rb": "6da5dc9256c9e7a6549bb15c72cb9f9d",
+  "lib/puppet/parser/functions/lstrip.rb": "20a9b1fa077c16f34e0ef5448b895698",
+  "lib/puppet/parser/functions/max.rb": "f652fd0b46ef7d2fbdb42b141f8fdd1d",
+  "lib/puppet/parser/functions/member.rb": "2b5d7fb8f87f1c7d195933c57ca32e91",
+  "lib/puppet/parser/functions/merge.rb": "f3dcc5c83440cdda2036cce69b61a14b",
+  "lib/puppet/parser/functions/min.rb": "0d2a1b7e735ab251c5469e735fa3f4c6",
+  "lib/puppet/parser/functions/num2bool.rb": "605c12fa518c87ed2c66ae153e0686ce",
+  "lib/puppet/parser/functions/parsejson.rb": "e7f968c34928107b84cd0860daf50ab1",
+  "lib/puppet/parser/functions/parseyaml.rb": "00f10ec1e2b050e23d80c256061ebdd7",
+  "lib/puppet/parser/functions/pick.rb": "bf01f13bbfe2318e7f6a302ac7c4433f",
+  "lib/puppet/parser/functions/pick_default.rb": "ad3ea60262de408767786d37a54d45dc",
+  "lib/puppet/parser/functions/prefix.rb": "e377fd64bd63dde6c9660aa75aca4942",
+  "lib/puppet/parser/functions/private.rb": "1500a21d5cf19961c5b1d476df892d92",
+  "lib/puppet/parser/functions/pw_hash.rb": "d82221f667050026cd6d155432a31802",
+  "lib/puppet/parser/functions/range.rb": "76f693d1dd50ffee409e58ff6d9a58bb",
+  "lib/puppet/parser/functions/reject.rb": "689f6a7c961a55fe9dcd240921f4c7f9",
+  "lib/puppet/parser/functions/reverse.rb": "b234b54b8cd62b2d67ccd70489ffdccf",
+  "lib/puppet/parser/functions/rstrip.rb": "b4e4ada41f7c1d2fcad073ce6344980f",
+  "lib/puppet/parser/functions/shuffle.rb": "d50f72b0aeb921e64d2482f62488e2f3",
+  "lib/puppet/parser/functions/size.rb": "ab3b5b8cf2369d76969a7cb2564e018f",
+  "lib/puppet/parser/functions/sort.rb": "504b033b438461ca4f9764feeb017833",
+  "lib/puppet/parser/functions/squeeze.rb": "541f85b4203b55c9931d3d6ecd5c75f8",
+  "lib/puppet/parser/functions/str2bool.rb": "6320f1a50fd28ec027981cd1fb8ffdd0",
+  "lib/puppet/parser/functions/str2saltedsha512.rb": "49afad7b386be38ce53deaefef326e85",
+  "lib/puppet/parser/functions/strftime.rb": "e02e01a598ca5d7d6eee0ba22440304a",
+  "lib/puppet/parser/functions/strip.rb": "85d70ab95492e3e4ca5f0b5ec3f284a9",
+  "lib/puppet/parser/functions/suffix.rb": "109279db4180441e75545dbd5f273298",
+  "lib/puppet/parser/functions/swapcase.rb": "b17a9f3cb0271451d309e4b4f52dd651",
+  "lib/puppet/parser/functions/time.rb": "8cb0b8320c60b4a21725634154a9f1db",
+  "lib/puppet/parser/functions/to_bytes.rb": "65437027687b6172173b3a211a799e37",
+  "lib/puppet/parser/functions/try_get_value.rb": "2ef0cc8141dfd72f45b5e854dde26a0f",
+  "lib/puppet/parser/functions/type.rb": "4709f7ab8a8aad62d77a3c5d91a3aa08",
+  "lib/puppet/parser/functions/type3x.rb": "f9bf4de8341afb0c677c26b40ec8a2b2",
+  "lib/puppet/parser/functions/union.rb": "3cf57ea53f2522f586264feb67293cd6",
+  "lib/puppet/parser/functions/unique.rb": "c1bb4a8aeebd09ba3e4c8bc3702cfd60",
+  "lib/puppet/parser/functions/unix2dos.rb": "b1f5087fcaca69d9395094204cce887a",
+  "lib/puppet/parser/functions/upcase.rb": "8decededec9eb33e58f961eb86f0888f",
+  "lib/puppet/parser/functions/uriescape.rb": "d912ba09ba3f58c70988e662e05ffbe8",
+  "lib/puppet/parser/functions/validate_absolute_path.rb": "d229bb0ff30405f9c6f505dadfebdc34",
+  "lib/puppet/parser/functions/validate_array.rb": "72b29289b8af1cfc3662ef9be78911b8",
+  "lib/puppet/parser/functions/validate_augeas.rb": "61e828e7759ba3e1e563e1fdd68aa80f",
+  "lib/puppet/parser/functions/validate_bool.rb": "a712634a000024398b3c6cd4ecc46463",
+  "lib/puppet/parser/functions/validate_cmd.rb": "57b3b128c035802fb67754eed3a88475",
+  "lib/puppet/parser/functions/validate_hash.rb": "e9cfaca68751524efe16ecf2f958a9a0",
+  "lib/puppet/parser/functions/validate_integer.rb": "438c7fdd25f7f6a208ac48c9b75a390f",
+  "lib/puppet/parser/functions/validate_ipv4_address.rb": "a8fb6f0ca36aa460d462c07c2af5d5a2",
+  "lib/puppet/parser/functions/validate_ipv6_address.rb": "4699238e4cad60e7e1428905523eaeb7",
+  "lib/puppet/parser/functions/validate_numeric.rb": "60b0c6d5b8b170ea77498a8580bd3158",
+  "lib/puppet/parser/functions/validate_re.rb": "c6664b3943bc820415a43f16372dc2a9",
+  "lib/puppet/parser/functions/validate_slength.rb": "5f0db124caae4866f474a60c589ba632",
+  "lib/puppet/parser/functions/validate_string.rb": "cf6a20877a27b1073d63fdd522af50bb",
+  "lib/puppet/parser/functions/values.rb": "066a6e4170e5034edb9a80463dff2bb5",
+  "lib/puppet/parser/functions/values_at.rb": "325a899e0201e8df5bd483fec6f12d76",
+  "lib/puppet/parser/functions/zip.rb": "a89d5e802bc1e63e52020c2ddbaaca2c",
+  "lib/puppet/provider/file_line/ruby.rb": "0b7ed2917e70902b5c40362370edcbb0",
+  "lib/puppet/type/anchor.rb": "bbd36bb49c3b554f8602d8d3df366c0c",
+  "lib/puppet/type/file_line.rb": "584f6a6e188053ca1c60bdb1e4a4a3f2",
+  "manifests/init.pp": "9560a09f657d7eebbfdb920cefcc1d4f",
+  "manifests/stages.pp": "cc6ed1751d334b0ea278c0335c7f0b5a",
+  "metadata.json": "99f6a3f68fab6e09160c206a47ff0ac7",
+  "spec/acceptance/abs_spec.rb": "538db8d037db814b455a6d741e91bb8d",
+  "spec/acceptance/anchor_spec.rb": "3a366ecab2fda6c20acd70eeb57c5080",
+  "spec/acceptance/any2array_spec.rb": "de86ead0205acbb3eca3a8a4792bdac8",
+  "spec/acceptance/base64_spec.rb": "1684d5dd176dd5bbd4c3c6b1e64fbcea",
+  "spec/acceptance/bool2num_spec.rb": "bf53ceac40d0a67551c618b11809f3f8",
+  "spec/acceptance/build_csv.rb": "f28ef587de764ade1513091c4906412c",
+  "spec/acceptance/capitalize_spec.rb": "e77ea2c37144a75a67969c0d0839adfd",
+  "spec/acceptance/ceiling_spec.rb": "b2718dc74a39399e342ef96fe0d00fdc",
+  "spec/acceptance/chomp_spec.rb": "fb0862a6b7eeb3c290e280788e705061",
+  "spec/acceptance/chop_spec.rb": "4e7ab2d3a441b88b667a0d8ea5b174c1",
+  "spec/acceptance/concat_spec.rb": "6d88764fde8859e2db6b604f69fe2e17",
+  "spec/acceptance/count_spec.rb": "d82cfcad2461b16872455d6347a8b114",
+  "spec/acceptance/deep_merge_spec.rb": "c335a947f1666e185e0210e661f1c78a",
+  "spec/acceptance/defined_with_params_spec.rb": "f27c54ade9872c63c69316f62b03c119",
+  "spec/acceptance/delete_at_spec.rb": "9c028b703ee0286565c9877757678f3f",
+  "spec/acceptance/delete_spec.rb": "31e6dfcb9cc7c16b20d47c00e6a85a1d",
+  "spec/acceptance/delete_undef_values_spec.rb": "6e6a66aee0c383c843b5f92ef8c8410c",
+  "spec/acceptance/delete_values_spec.rb": "22c9b4914d4cbc0153aa3862cb4fb50e",
+  "spec/acceptance/difference_spec.rb": "289f4f1788feaacb304ffd54971c7e7e",
+  "spec/acceptance/dirname_spec.rb": "84db53878c4400a6c684c924cff05cfc",
+  "spec/acceptance/downcase_spec.rb": "0f094849b94a94df491ee01186473104",
+  "spec/acceptance/empty_spec.rb": "35c1f43e8a3e1fe7dd4335ef86e7efcc",
+  "spec/acceptance/ensure_resource_spec.rb": "adfd9e20b2d174bb4a1b241942e6f119",
+  "spec/acceptance/flatten_spec.rb": "83fb08cc168a105c1d5d0df66b1d9e84",
+  "spec/acceptance/floor_spec.rb": "d7267b2914b1da6406224abb7489ca86",
+  "spec/acceptance/fqdn_rand_string_spec.rb": "17b047b80e008b5eb45b4cbe64036983",
+  "spec/acceptance/fqdn_rotate_spec.rb": "b00226e2ae28acf4ffea8a96b6e64f01",
+  "spec/acceptance/get_module_path_spec.rb": "2658cdcd1abd4b7d20f53c4aced3c72a",
+  "spec/acceptance/getparam_spec.rb": "4d32dc5a0ee34d045242c36d77a3b482",
+  "spec/acceptance/getvar_spec.rb": "ba2f081a88be97c0e7004a6296294f23",
+  "spec/acceptance/grep_spec.rb": "98818b8b0557b80d6ff519f70ea7617c",
+  "spec/acceptance/has_interface_with_spec.rb": "30e27096050c43b7efdb5e6c0d54f53b",
+  "spec/acceptance/has_ip_address_spec.rb": "2812117ec4b88556039e8488d53c0cb0",
+  "spec/acceptance/has_ip_network_spec.rb": "ca75b43ff1256ead9052f2db7620db99",
+  "spec/acceptance/has_key_spec.rb": "6509a26a0886f7d591eaa926b2f92407",
+  "spec/acceptance/hash_spec.rb": "1c626457ba056bdd3936e28aa5bf503e",
+  "spec/acceptance/intersection_spec.rb": "40f586af7f95408a5d4a2882a4aa98f1",
+  "spec/acceptance/is_array_spec.rb": "c2ff70ce59b90b50a5aed67abaa5399d",
+  "spec/acceptance/is_bool_spec.rb": "c001fdecff6b0a3c9dc78774987a0b15",
+  "spec/acceptance/is_domain_name_spec.rb": "63e84285c26d8717fd5d4dda01e3f432",
+  "spec/acceptance/is_float_spec.rb": "2f0164b4d732166aa46055a2cf7b4ea9",
+  "spec/acceptance/is_function_available_spec.rb": "7745eba89f8719c9ca7ebf04d5b005f7",
+  "spec/acceptance/is_hash_spec.rb": "cff723cd8fddac45033af5dc8406d4e4",
+  "spec/acceptance/is_integer_spec.rb": "c09201d17d3914bba197872897fa3413",
+  "spec/acceptance/is_ip_address_spec.rb": "aa14cf9abf404c3fe1e761ea957871fe",
+  "spec/acceptance/is_mac_address_spec.rb": "30ff4c6a63be58daa3568305617ca2a7",
+  "spec/acceptance/is_numeric_spec.rb": "fb9829c7a1a8d4a58836df6ff4c3386d",
+  "spec/acceptance/is_string_spec.rb": "df3022de123b72f0022728eb2d8ce857",
+  "spec/acceptance/join_keys_to_values_spec.rb": "8aa128bbaeea65aab8d92badee3ca2b5",
+  "spec/acceptance/join_spec.rb": "c6378ed481265152bba9871fc5501ee6",
+  "spec/acceptance/keys_spec.rb": "20486e3ebee53e50dc9de3b78b9d6ae6",
+  "spec/acceptance/loadyaml_spec.rb": "bd440cb6779026bd07d83f1aceb2781b",
+  "spec/acceptance/lstrip_spec.rb": "e29ab4039b65660ec2bd76a298adcae0",
+  "spec/acceptance/max_spec.rb": "209cda4b83d677743afb1a8870330618",
+  "spec/acceptance/member_spec.rb": "d6088a4fa6321791a3067d9b9cf8914a",
+  "spec/acceptance/merge_spec.rb": "5f168188fa0d6b31ba5b3dac49fb609c",
+  "spec/acceptance/min_spec.rb": "152a7db28434a0d0378561d4f64cddcc",
+  "spec/acceptance/nodesets/centos-59-x64.yml": "57eb3e471b9042a8ea40978c467f8151",
+  "spec/acceptance/nodesets/centos-6-vcloud.yml": "bdf9ce9d3b0f0b4995666ae9d64d878d",
+  "spec/acceptance/nodesets/centos-64-x64-pe.yml": "ec075d95760df3d4702abea1ce0a829b",
+  "spec/acceptance/nodesets/centos-64-x64.yml": "092dd2c588a9f87fa1fb12997c0723ef",
+  "spec/acceptance/nodesets/centos-65-x64.yml": "3e5c36e6aa5a690229e720f4048bb8af",
+  "spec/acceptance/nodesets/default.yml": "3e5c36e6aa5a690229e720f4048bb8af",
+  "spec/acceptance/nodesets/fedora-18-x64.yml": "80e41b1ee16ea489f53164bfdae58855",
+  "spec/acceptance/nodesets/sles-11-x64.yml": "44e4c6c15c018333bfa9840a5e702f66",
+  "spec/acceptance/nodesets/ubuntu-server-10044-x64.yml": "75e86400b7889888dc0781c0ae1a1297",
+  "spec/acceptance/nodesets/ubuntu-server-12042-x64.yml": "d30d73e34cd50b043c7d14e305955269",
+  "spec/acceptance/nodesets/ubuntu-server-1404-x64.yml": "5f0aed10098ac5b78e4217bb27c7aaf0",
+  "spec/acceptance/nodesets/windows-2003-i386.yml": "b518fc01fab99ee6a9afccec5bc0c1c4",
+  "spec/acceptance/nodesets/windows-2003-x86_64.yml": "5c783eaa8ea4734edc836e89e923dfa1",
+  "spec/acceptance/nodesets/windows-2008-x86_64.yml": "3082234eafcfaf7a9579d9ebdb8bc409",
+  "spec/acceptance/nodesets/windows-2008r2-x86_64.yml": "dfeff32a4cc3fffa872c8281d990a840",
+  "spec/acceptance/nodesets/windows-2012-x86_64.yml": "8bed73362ee1f43d21ea1903a729f955",
+  "spec/acceptance/nodesets/windows-2012r2-x86_64.yml": "3f4f6112d24db02989b8ab79d3a1256f",
+  "spec/acceptance/num2bool_spec.rb": "e4a00b913b08c68a689837e9f9336cb2",
+  "spec/acceptance/parsejson_spec.rb": "ea3973d412ad6f72425fdfac6fbb2bb4",
+  "spec/acceptance/parseyaml_spec.rb": "7bbfeed73d0626f69daedfc151957967",
+  "spec/acceptance/pick_default_spec.rb": "1bc2562380ef6f6cded5ec90a03922be",
+  "spec/acceptance/pick_spec.rb": "272c54c8f9398f499768331bdb4276ee",
+  "spec/acceptance/prefix_spec.rb": "da620568c6771e7d492ec1ff697c531c",
+  "spec/acceptance/pw_hash_spec.rb": "721fe0da04d798a353799fd651bcd0fc",
+  "spec/acceptance/range_spec.rb": "65e5b98ceca257658604d988fbec7d03",
+  "spec/acceptance/reject_spec.rb": "b5185f1a6071c9bdc7aca92e6f899c3e",
+  "spec/acceptance/reverse_spec.rb": "7bdee543e82532e97bbf7a067140031c",
+  "spec/acceptance/rstrip_spec.rb": "28a64ceb7cb5ae8a93d31f49816190ab",
+  "spec/acceptance/shuffle_spec.rb": "8a8652e57d56f2b4946cdf4d20052b7a",
+  "spec/acceptance/size_spec.rb": "ae17d8a55921a0570972200c7c9327e1",
+  "spec/acceptance/sort_spec.rb": "d44b1b8c090f0f00a2f38515fda431ea",
+  "spec/acceptance/squeeze_spec.rb": "adcd65fa4e72203b97f1f14c8835c2cd",
+  "spec/acceptance/str2bool_spec.rb": "55ad165ceef6b9ba32bf20ca3b53b44c",
+  "spec/acceptance/str2saltedsha512_spec.rb": "b684c4214d06ae3d5bae055262a5ccaa",
+  "spec/acceptance/strftime_spec.rb": "0f4eadbd74445b35de4a42c9790fbcc1",
+  "spec/acceptance/strip_spec.rb": "6767da5bc735beb5362aeee6ff692c9e",
+  "spec/acceptance/suffix_spec.rb": "07dfc7eed48b75fcc1b93d0308243eda",
+  "spec/acceptance/swapcase_spec.rb": "5c3c1bc19a09fed6e01881f79b0b4ea5",
+  "spec/acceptance/time_spec.rb": "044b2f634a1fa6ecc735998d68a93b73",
+  "spec/acceptance/to_bytes_spec.rb": "f9df1f234b9409f5eaf56ef24e651c36",
+  "spec/acceptance/try_get_value_spec.rb": "db7c47f372f9d9725987ebe13e6039eb",
+  "spec/acceptance/type_spec.rb": "4297e038a8ff7e6ecb859b8b68c7b3a6",
+  "spec/acceptance/union_spec.rb": "f24e166bc838c9c8cbd75ad3f8f9d15b",
+  "spec/acceptance/unique_spec.rb": "9b00b21cefde3b5391f50eeb9cd2493b",
+  "spec/acceptance/unsupported_spec.rb": "09b9265ecb05252cd5e5a18327c7ae97",
+  "spec/acceptance/upcase_spec.rb": "ffd1d6f9e6ec24131fb78983c53a75f9",
+  "spec/acceptance/uriescape_spec.rb": "13daa387714cbfc63b587aaa8dbf7fcd",
+  "spec/acceptance/validate_absolute_path_spec.rb": "8b9ebfae80329231d84fcab606a3eeaf",
+  "spec/acceptance/validate_array_spec.rb": "382641719e754622ffae562d10e38bf7",
+  "spec/acceptance/validate_augeas_spec.rb": "c26b8ca2184a9dd87033a0c6f0553093",
+  "spec/acceptance/validate_bool_spec.rb": "08bc139459204cf0a35098a5bc30ab95",
+  "spec/acceptance/validate_cmd_spec.rb": "e9260c49d880e4de54f77bf4fd70cff4",
+  "spec/acceptance/validate_hash_spec.rb": "70ceacc18a0dee97b26ab2e50f925706",
+  "spec/acceptance/validate_ipv4_address_spec.rb": "dc901bbd05c3764a93cb49154cea6e4b",
+  "spec/acceptance/validate_ipv6_address_spec.rb": "c0872c56230ac2800cd5723eaa5bc53a",
+  "spec/acceptance/validate_re_spec.rb": "b289909078d6ae0d015419f518566698",
+  "spec/acceptance/validate_slength_spec.rb": "f0a05c1c2b895b096cb7326df4821594",
+  "spec/acceptance/validate_string_spec.rb": "6c9ced99fb1e263e66e25427d24f8f7b",
+  "spec/acceptance/values_at_spec.rb": "669b26c4d47742051472003518c3aa61",
+  "spec/acceptance/values_spec.rb": "9681223bb1bd755c28946ef0bcd6ece9",
+  "spec/acceptance/zip_spec.rb": "86d1b555745ee873da68c71f1e46ed21",
+  "spec/fixtures/dscacheutil/root": "e1a7622f55f3d1be258c9a5b16b474be",
+  "spec/fixtures/lsuser/root": "2ed657fa157372a81634539bb1a56be8",
+  "spec/functions/abs_spec.rb": "7c0ebbd787b788d32b9bb21fe9061a2f",
+  "spec/functions/any2array_spec.rb": "c5990164adbaaf4f6536df4022309176",
+  "spec/functions/assert_private_spec.rb": "3bf58bd53467248cc221b9f846b13d98",
+  "spec/functions/base64_spec.rb": "56e192ac379469d3cccd5cf73d41f4e5",
+  "spec/functions/basename_spec.rb": "9711895262a628309bb70e0fe69aa07e",
+  "spec/functions/bool2num_spec.rb": "6609136ff067b90d41cf27bf8838c3ea",
+  "spec/functions/bool2str_spec.rb": "b9b0fdcd312ac6d2e7768d7d42042773",
+  "spec/functions/camelcase_spec.rb": "4a13d3323535291fef3f40a96710acdb",
+  "spec/functions/capitalize_spec.rb": "31a8d497b274653d5ede70a0187d4053",
+  "spec/functions/ceiling_spec.rb": "47bd74569f8979d9195df06a863de93b",
+  "spec/functions/chomp_spec.rb": "6749a0b358b34e73843e1a284cead44a",
+  "spec/functions/chop_spec.rb": "6e33e61f50459191387c87e474d3d127",
+  "spec/functions/concat_spec.rb": "f2d83c38f9ac79b02285e056b3c52dd3",
+  "spec/functions/convert_base_spec.rb": "f031e84b18cb010bc6233be3e4bcff83",
+  "spec/functions/count_spec.rb": "d91a084665ecd902586d26c99d45beed",
+  "spec/functions/deep_merge_spec.rb": "d70a71c7e9363c75224fffd40fc5efdd",
+  "spec/functions/defined_with_params_spec.rb": "9185955113fd14a7b2fbaa0228669d00",
+  "spec/functions/delete_at_spec.rb": "a5443ac5879992af9c4470e59f0355cf",
+  "spec/functions/delete_spec.rb": "822310fa89d455233c32553660df67d3",
+  "spec/functions/delete_undef_values_spec.rb": "6bee6b89a507130a009a9e8b5ef3e130",
+  "spec/functions/delete_values_spec.rb": "0d2d17c0cacd7f3871ea7ab2f5b96d93",
+  "spec/functions/difference_spec.rb": "2caaab5edb42ddc426e65348b12ebcc3",
+  "spec/functions/dirname_spec.rb": "5c905655d551b1956b6c9eda4ee96569",
+  "spec/functions/dos2unix_spec.rb": "95c13597be9e67e79e69ed0e6c3d325a",
+  "spec/functions/downcase_spec.rb": "e2c24d41c6fb840f7b66c5205c942780",
+  "spec/functions/empty_spec.rb": "9de2e75514fd84f91eb4a50754fa1bbd",
+  "spec/functions/ensure_packages_spec.rb": "76e89bf81ae98e52d2a07263c0e8d4f4",
+  "spec/functions/ensure_resource_spec.rb": "57634d7b6f86ac77dc47fb5da36410c2",
+  "spec/functions/flatten_spec.rb": "6fb563c36daf40599a414c1f3af8dc0b",
+  "spec/functions/floor_spec.rb": "7d110b1f994432e1c6c7c004a3dedbe4",
+  "spec/functions/fqdn_rand_string_spec.rb": "2edaae1764df4d751684d8ceda7b9cda",
+  "spec/functions/fqdn_rotate_spec.rb": "e9b1ce122788f18611cf64696d666328",
+  "spec/functions/get_module_path_spec.rb": "e0b1664ce848a00f918b8fc3c8099be0",
+  "spec/functions/getparam_spec.rb": "dbbdde0a72653feb479e9fb971b94ec7",
+  "spec/functions/getvar_spec.rb": "18a9340442dd59cea8a6c98e95d38f4d",
+  "spec/functions/grep_spec.rb": "b9d0722e7708351b0114c46d4272f760",
+  "spec/functions/has_interface_with_spec.rb": "473c000e461c3497f8461eb17cf73430",
+  "spec/functions/has_ip_address_spec.rb": "7b36b993ea32757e74be9909906bd165",
+  "spec/functions/has_ip_network_spec.rb": "23021acd604dc4ca3a1fef62e8863d8e",
+  "spec/functions/has_key_spec.rb": "6bc81bc7d179d4b680e7065a60b76562",
+  "spec/functions/hash_spec.rb": "4519b75eeb8eb0bba80b4594c297cf5e",
+  "spec/functions/intersection_spec.rb": "fcd475963335b3efee99c3ddd0ddd969",
+  "spec/functions/is_array_spec.rb": "7ea00635b395f231fce6467c95410b05",
+  "spec/functions/is_bool_spec.rb": "9173b8fd7cb5aea4504f0fa860d883c9",
+  "spec/functions/is_domain_name_spec.rb": "4ea3825d5b77a5d75eab8228dcc738f9",
+  "spec/functions/is_float_spec.rb": "42b7f071e02af58e3154643b84445af1",
+  "spec/functions/is_function_available.rb": "f8ab234d536532c3629ff6a5068e7877",
+  "spec/functions/is_hash_spec.rb": "11563529f0f1f821769edb3131277100",
+  "spec/functions/is_integer_spec.rb": "799bef092df12fa590e71473db957d11",
+  "spec/functions/is_ip_address_spec.rb": "195e89d0c32eae24e4a51d12b8c59009",
+  "spec/functions/is_mac_address_spec.rb": "748b7e3dffae6d4097da9cc29a37e94d",
+  "spec/functions/is_numeric_spec.rb": "d131e94cf670075e8c46576b5109c2b6",
+  "spec/functions/is_string_spec.rb": "f41f332f93fc05b57ee9611cdbe73c11",
+  "spec/functions/join_keys_to_values_spec.rb": "b95f8f32888a96c4239c87cf9785d288",
+  "spec/functions/join_spec.rb": "2181956bf08efe90f932a17e5138a25c",
+  "spec/functions/keys_spec.rb": "8a6772daf2ae821e98d392f5266fdf67",
+  "spec/functions/load_module_metadata.rb": "e924fb4ab807305a99205996102c7297",
+  "spec/functions/loadyaml_spec.rb": "f4f50af8016ffd187a0358b78634a259",
+  "spec/functions/lstrip_spec.rb": "58644ca945b38ec8b3d8729423aacf69",
+  "spec/functions/max_spec.rb": "47de8d59070d8d51b2184731f5d1aa43",
+  "spec/functions/member_spec.rb": "02891f40caaca15a5aba43443c7d2ccb",
+  "spec/functions/merge_spec.rb": "56297527d192640bbe82c7ccf1e39815",
+  "spec/functions/min_spec.rb": "8b38e2a989912406cd2c57dcd3a460c4",
+  "spec/functions/num2bool_spec.rb": "7c4fd30e41a11b1bd0d9e5233340f16b",
+  "spec/functions/parsejson_spec.rb": "03b7928d99e46cd88a4e5c6c4caa35d8",
+  "spec/functions/parseyaml_spec.rb": "e9ab969d1d2f63903d1c0b968beded93",
+  "spec/functions/pick_default_spec.rb": "bef7bb2f755e665775aa0085c6897fb2",
+  "spec/functions/pick_spec.rb": "8fe02695ea909e993119254accc61f1a",
+  "spec/functions/prefix_spec.rb": "95956321291a0f6d1e2f45572569fe3b",
+  "spec/functions/private_spec.rb": "f404771c4590a0cd7ce61ddff8f3eb7b",
+  "spec/functions/pw_hash_spec.rb": "640609cc73b4c8bbcdfc88c3e9797664",
+  "spec/functions/range_spec.rb": "e73c3bb7f2c25540780c3bad19b30994",
+  "spec/functions/reject_spec.rb": "e0eb0546885dd0aef023dfa4694155db",
+  "spec/functions/reverse_spec.rb": "cb48f198c2a9efe224a00d67e68d978f",
+  "spec/functions/rstrip_spec.rb": "f0391a775d335e2a5c9335d50c657f4b",
+  "spec/functions/shuffle_spec.rb": "6ab6083720cfd4dfa99556e5ef81f576",
+  "spec/functions/size_spec.rb": "51495c464a203d9e1919008209f05cd5",
+  "spec/functions/sort_spec.rb": "d9533dd37c6263b92895f7eba8485248",
+  "spec/functions/squeeze_spec.rb": "549af334b7f9dd5f06d6b45c3e3e8303",
+  "spec/functions/str2bool_spec.rb": "061492577e9e7686dde01a29b8060cc8",
+  "spec/functions/str2saltedsha512_spec.rb": "07586b0026757cd39229c12c7221808b",
+  "spec/functions/strftime_spec.rb": "f1a34fc930940213abfba3095d5d8065",
+  "spec/functions/strip_spec.rb": "0cb8537f2e7df14f42247349ab3161a6",
+  "spec/functions/suffix_spec.rb": "599768b95090323b8046215d26597f3c",
+  "spec/functions/swapcase_spec.rb": "90bace1b004aa63d46eb6481c6dce2b1",
+  "spec/functions/time_spec.rb": "6dc8f5b42cf89345d2de424bfe19be90",
+  "spec/functions/to_bytes_spec.rb": "b771f8490d922de46a519e407d358139",
+  "spec/functions/try_get_value_spec.rb": "b917b899f5d29764dd4b1b07e07ec6ce",
+  "spec/functions/type3x_spec.rb": "eed4ce3a2bc92d14effedefef9690654",
+  "spec/functions/type_of_spec.rb": "2019419e5ee3643023b74e1bb1c1fb65",
+  "spec/functions/type_spec.rb": "7a61b4af7d3d83be590d783a7e5e80f8",
+  "spec/functions/union_spec.rb": "089b03e9a6ef25cdcf68157bb986d8a8",
+  "spec/functions/unique_spec.rb": "b793c531b4d227ae55d05a187b706fb8",
+  "spec/functions/unix2dos_spec.rb": "628c8a0c608d1fa0dd09bd1b5af97c1f",
+  "spec/functions/upcase_spec.rb": "4f0461a20c03d618f0c18da39bebcf65",
+  "spec/functions/uriescape_spec.rb": "1458afbe7e7e11dcaad8d295a7f2be59",
+  "spec/functions/validate_absolute_path_spec.rb": "26e00ce6122016b9b53797806e681682",
+  "spec/functions/validate_array_spec.rb": "df0bcf372b3efdd1f4de16b508987616",
+  "spec/functions/validate_augeas_spec.rb": "d598e89a23912be9f24d39b809f30b47",
+  "spec/functions/validate_bool_spec.rb": "93cfbecbe8cc4707ada13f48f5c8c8a6",
+  "spec/functions/validate_cmd_spec.rb": "05eb581532fc689ff91212413b2e678d",
+  "spec/functions/validate_hash_spec.rb": "56f4b7e42a4d3f62172982fa639f5cc3",
+  "spec/functions/validate_integer_spec.rb": "0a2677479c8bf0257bdd54c3d0db1f81",
+  "spec/functions/validate_ipv4_address_spec.rb": "dc1af709faa724ccc51d9c5aba1d6356",
+  "spec/functions/validate_ipv6_address_spec.rb": "5f27c395b286385c489df5ee119580bc",
+  "spec/functions/validate_numeric_spec.rb": "dd5fcc7421002c85252d0a9421a5a99b",
+  "spec/functions/validate_re_spec.rb": "52f9125188d7e452e747801e8b17c10c",
+  "spec/functions/validate_slength_spec.rb": "92252419e0d311a7bd6b426edb3c1040",
+  "spec/functions/validate_string_spec.rb": "779473e87660081e610c397f0157331a",
+  "spec/functions/values_at_spec.rb": "c318f66de43f8e6095d28f733f55ec5d",
+  "spec/functions/values_spec.rb": "5550da71a69514f8be87a12b575d5228",
+  "spec/functions/zip_spec.rb": "4c991f26985096b3e8b336cef528aa00",
+  "spec/monkey_patches/alias_should_to_must.rb": "b19ee31563afb91a72f9869f9d7362ff",
+  "spec/monkey_patches/publicize_methods.rb": "c690e444b77c871375d321e413e28ca1",
+  "spec/puppetlabs_spec_helper_clone.rb": "8ad7f8e9186fc52a1a35d6b5c07d2571",
+  "spec/spec.opts": "a600ded995d948e393fbe2320ba8e51c",
+  "spec/spec_helper.rb": "46e1ca48cf3f80d585bd9add370f1039",
+  "spec/spec_helper_acceptance.rb": "956fbc70662989add2e950c1e8cbfde9",
+  "spec/unit/facter/facter_dot_d_spec.rb": "420339a544851f2c7ee6fa4c651bdce8",
+  "spec/unit/facter/pe_version_spec.rb": "af4d4428a7625a19de1751ce1bb09d5c",
+  "spec/unit/facter/root_home_spec.rb": "aa88636dccb138fca60d61c14fa46b5d",
+  "spec/unit/facter/util/puppet_settings_spec.rb": "6f9df9b10a1b39245ecdf002616a4122",
+  "spec/unit/puppet/provider/file_line/ruby_spec.rb": "662ad5db7b02dbddbcc015d4a35ac5bc",
+  "spec/unit/puppet/type/anchor_spec.rb": "06a669dffa44d716bf19b4e7f5f1d75d",
+  "spec/unit/puppet/type/file_line_spec.rb": "e3e13f1b31c734e13e5198259efa8445"
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/examples/file_line.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+# This is a simple smoke test
+# of the file_line resource type.
+file { '/tmp/dansfile':
+  ensure => file,
+} ->
+file_line { 'dans_line':
+  line => 'dan is awesome',
+  path => '/tmp/dansfile',
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/examples/has_interface_with.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+include ::stdlib
+info('has_interface_with(\'lo\'):', has_interface_with('lo'))
+info('has_interface_with(\'loX\'):', has_interface_with('loX'))
+info('has_interface_with(\'ipaddress\', \'127.0.0.1\'):', has_interface_with('ipaddress', '127.0.0.1'))
+info('has_interface_with(\'ipaddress\', \'127.0.0.100\'):', has_interface_with('ipaddress', '127.0.0.100'))
+info('has_interface_with(\'network\', \'127.0.0.0\'):', has_interface_with('network', '127.0.0.0'))
+info('has_interface_with(\'network\', \'128.0.0.0\'):', has_interface_with('network', '128.0.0.0'))
+info('has_interface_with(\'netmask\', \'255.0.0.0\'):', has_interface_with('netmask', '255.0.0.0'))
+info('has_interface_with(\'netmask\', \'256.0.0.0\'):', has_interface_with('netmask', '256.0.0.0'))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/examples/has_ip_address.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+include ::stdlib
+info('has_ip_address(\'192.168.1.256\'):', has_ip_address('192.168.1.256'))
+info('has_ip_address(\'127.0.0.1\'):', has_ip_address('127.0.0.1'))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/examples/has_ip_network.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+include ::stdlib
+info('has_ip_network(\'127.0.0.0\'):', has_ip_network('127.0.0.0'))
+info('has_ip_network(\'128.0.0.0\'):', has_ip_network('128.0.0.0'))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/examples/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+include ::stdlib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/facter/facter_dot_d.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,202 @@
+# A Facter plugin that loads facts from /etc/facter/facts.d
+# and /etc/puppetlabs/facter/facts.d.
+#
+# Facts can be in the form of JSON, YAML or Text files
+# and any executable that returns key=value pairs.
+#
+# In the case of scripts you can also create a file that
+# contains a cache TTL.  For foo.sh store the ttl as just
+# a number in foo.sh.ttl
+#
+# The cache is stored in $libdir/facts_dot_d.cache as a mode
+# 600 file and will have the end result of not calling your
+# fact scripts more often than is needed
+
+class Facter::Util::DotD
+  require 'yaml'
+
+  def initialize(dir="/etc/facts.d", cache_file=File.join(Puppet[:libdir], "facts_dot_d.cache"))
+    @dir = dir
+    @cache_file = cache_file
+    @cache = nil
+    @types = {".txt" => :txt, ".json" => :json, ".yaml" => :yaml}
+  end
+
+  def entries
+    Dir.entries(@dir).reject { |f| f =~ /^\.|\.ttl$/ }.sort.map { |f| File.join(@dir, f) }
+  rescue
+    []
+  end
+
+  def fact_type(file)
+    extension = File.extname(file)
+
+    type = @types[extension] || :unknown
+
+    type = :script if type == :unknown && File.executable?(file)
+
+    return type
+  end
+
+  def txt_parser(file)
+    File.readlines(file).each do |line|
+      if line =~ /^([^=]+)=(.+)$/
+        var = $1; val = $2
+
+        Facter.add(var) do
+          setcode { val }
+        end
+      end
+    end
+  rescue Exception => e
+    Facter.warn("Failed to handle #{file} as text facts: #{e.class}: #{e}")
+  end
+
+  def json_parser(file)
+    begin
+      require 'json'
+    rescue LoadError
+      retry if require 'rubygems'
+      raise
+    end
+
+    JSON.load(File.read(file)).each_pair do |f, v|
+      Facter.add(f) do
+        setcode { v }
+      end
+    end
+  rescue Exception => e
+    Facter.warn("Failed to handle #{file} as json facts: #{e.class}: #{e}")
+  end
+
+  def yaml_parser(file)
+    require 'yaml'
+
+    YAML.load_file(file).each_pair do |f, v|
+      Facter.add(f) do
+        setcode { v }
+      end
+    end
+  rescue Exception => e
+    Facter.warn("Failed to handle #{file} as yaml facts: #{e.class}: #{e}")
+  end
+
+  def script_parser(file)
+    result = cache_lookup(file)
+    ttl = cache_time(file)
+
+    unless result
+      result = Facter::Util::Resolution.exec(file)
+
+      if ttl > 0
+        Facter.debug("Updating cache for #{file}")
+        cache_store(file, result)
+        cache_save!
+      end
+    else
+      Facter.debug("Using cached data for #{file}")
+    end
+
+    result.split("\n").each do |line|
+      if line =~ /^(.+)=(.+)$/
+        var = $1; val = $2
+
+        Facter.add(var) do
+          setcode { val }
+        end
+      end
+    end
+  rescue Exception => e
+    Facter.warn("Failed to handle #{file} as script facts: #{e.class}: #{e}")
+    Facter.debug(e.backtrace.join("\n\t"))
+  end
+
+  def cache_save!
+    cache = load_cache
+    File.open(@cache_file, "w", 0600) { |f| f.write(YAML.dump(cache)) }
+  rescue
+  end
+
+  def cache_store(file, data)
+    load_cache
+
+    @cache[file] = {:data => data, :stored => Time.now.to_i}
+  rescue
+  end
+
+  def cache_lookup(file)
+    cache = load_cache
+
+    return nil if cache.empty?
+
+    ttl = cache_time(file)
+
+    if cache[file]
+      now = Time.now.to_i
+
+      return cache[file][:data] if ttl == -1
+      return cache[file][:data] if (now - cache[file][:stored]) <= ttl
+      return nil
+    else
+      return nil
+    end
+  rescue
+    return nil
+  end
+
+  def cache_time(file)
+    meta = file + ".ttl"
+
+    return File.read(meta).chomp.to_i
+  rescue
+    return 0
+  end
+
+  def load_cache
+    unless @cache
+      if File.exist?(@cache_file)
+        @cache = YAML.load_file(@cache_file)
+      else
+        @cache = {}
+      end
+    end
+
+    return @cache
+  rescue
+    @cache = {}
+    return @cache
+  end
+
+  def create
+    entries.each do |fact|
+      type = fact_type(fact)
+      parser = "#{type}_parser"
+
+      if respond_to?("#{type}_parser")
+        Facter.debug("Parsing #{fact} using #{parser}")
+
+        send(parser, fact)
+      end
+    end
+  end
+end
+
+
+mdata = Facter.version.match(/(\d+)\.(\d+)\.(\d+)/)
+if mdata
+  (major, minor, patch) = mdata.captures.map { |v| v.to_i }
+  if major < 2
+    # Facter 1.7 introduced external facts support directly
+    unless major == 1 and minor > 6
+      Facter::Util::DotD.new("/etc/facter/facts.d").create
+      Facter::Util::DotD.new("/etc/puppetlabs/facter/facts.d").create
+
+      # Windows has a different configuration directory that defaults to a vendor
+      # specific sub directory of the %COMMON_APPDATA% directory.
+      if Dir.const_defined? 'COMMON_APPDATA' then
+        windows_facts_dot_d = File.join(Dir::COMMON_APPDATA, 'PuppetLabs', 'facter', 'facts.d')
+        Facter::Util::DotD.new(windows_facts_dot_d).create
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/facter/pe_version.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,53 @@
+# Fact: is_pe, pe_version, pe_major_version, pe_minor_version, pe_patch_version
+#
+# Purpose: Return various facts about the PE state of the system
+#
+# Resolution: Uses a regex match against puppetversion to determine whether the
+#   machine has Puppet Enterprise installed, and what version (overall, major,
+#   minor, patch) is installed.
+#
+# Caveats:
+#
+Facter.add("pe_version") do
+  setcode do
+    pe_ver = Facter.value("puppetversion").match(/Puppet Enterprise (\d+\.\d+\.\d+)/)
+    pe_ver[1] if pe_ver
+  end
+end
+
+Facter.add("is_pe") do
+  setcode do
+    if Facter.value(:pe_version).to_s.empty? then
+      false
+    else
+      true
+    end
+  end
+end
+
+Facter.add("pe_major_version") do
+  confine :is_pe => true
+  setcode do
+    if pe_version = Facter.value(:pe_version)
+      pe_version.to_s.split('.')[0]
+    end
+  end
+end
+
+Facter.add("pe_minor_version") do
+  confine :is_pe => true
+  setcode do
+    if pe_version = Facter.value(:pe_version)
+      pe_version.to_s.split('.')[1]
+    end
+  end
+end
+
+Facter.add("pe_patch_version") do
+  confine :is_pe => true
+  setcode do
+    if pe_version = Facter.value(:pe_version)
+      pe_version.to_s.split('.')[2]
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/facter/puppet_vardir.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+# This facter fact returns the value of the Puppet vardir setting for the node
+# running puppet or puppet agent.  The intent is to enable Puppet modules to
+# automatically have insight into a place where they can place variable data,
+# regardless of the node's platform.
+#
+# The value should be directly usable in a File resource path attribute.
+
+
+begin
+  require 'facter/util/puppet_settings'
+rescue LoadError => e
+  # puppet apply does not add module lib directories to the $LOAD_PATH (See
+  # #4248). It should (in the future) but for the time being we need to be
+  # defensive which is what this rescue block is doing.
+  rb_file = File.join(File.dirname(__FILE__), 'util', 'puppet_settings.rb')
+  load rb_file if File.exists?(rb_file) or raise e
+end
+
+Facter.add(:puppet_vardir) do
+  setcode do
+    # This will be nil if Puppet is not available.
+    Facter::Util::PuppetSettings.with_puppet do
+      Puppet[:vardir]
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/facter/root_home.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+# A facter fact to determine the root home directory.
+# This varies on PE supported platforms and may be
+# reconfigured by the end user.
+
+module Facter::Util::RootHome
+  class << self
+  def get_root_home
+    root_ent = Facter::Util::Resolution.exec("getent passwd root")
+    # The home directory is the sixth element in the passwd entry
+    # If the platform doesn't have getent, root_ent will be nil and we should
+    # return it straight away.
+    root_ent && root_ent.split(":")[5]
+  end
+  end
+end
+
+Facter.add(:root_home) do
+  setcode { Facter::Util::RootHome.get_root_home }
+end
+
+Facter.add(:root_home) do
+  confine :kernel => :darwin
+  setcode do
+    str = Facter::Util::Resolution.exec("dscacheutil -q user -a name root")
+    hash = {}
+    str.split("\n").each do |pair|
+      key,value = pair.split(/:/)
+      hash[key] = value
+    end
+    hash['dir'].strip
+  end
+end
+
+Facter.add(:root_home) do
+  confine :kernel => :aix
+  root_home = nil
+  setcode do
+    str = Facter::Util::Resolution.exec("lsuser -C -a home root")
+    str && str.split("\n").each do |line|
+      next if line =~ /^#/
+      root_home = line.split(/:/)[1]
+    end
+    root_home
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/facter/util/puppet_settings.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+module Facter
+  module Util
+    module PuppetSettings
+      # This method is intended to provide a convenient way to evaluate a
+      # Facter code block only if Puppet is loaded.  This is to account for the
+      # situation where the fact happens to be in the load path, but Puppet is
+      # not loaded for whatever reason.  Perhaps the user is simply running
+      # facter without the --puppet flag and they happen to be working in a lib
+      # directory of a module.
+      def self.with_puppet
+        begin
+          Module.const_get("Puppet")
+        rescue NameError
+          nil
+        else
+          yield
+        end
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/functions/type_of.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+# Returns the type when passed a value.
+#
+# @example how to compare values' types
+#   # compare the types of two values
+#   if type_of($first_value) != type_of($second_value) { fail("first_value and second_value are different types") }
+# @example how to compare against an abstract type
+#   unless type_of($first_value) <= Numeric { fail("first_value must be Numeric") }
+#   unless type_of{$first_value) <= Collection[1] { fail("first_value must be an Array or Hash, and contain at least one element") }
+#
+# See the documentation for "The Puppet Type System" for more information about types.
+# See the `assert_type()` function for flexible ways to assert the type of a value.
+#
+Puppet::Functions.create_function(:type_of) do
+  def type_of(value)
+    Puppet::Pops::Types::TypeCalculator.infer_set(value)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/abs.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+#
+# abs.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:abs, :type => :rvalue, :doc => <<-EOS
+    Returns the absolute value of a number, for example -34.56 becomes
+    34.56. Takes a single integer and float value as an argument.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "abs(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    # Numbers in Puppet are often string-encoded which is troublesome ...
+    if value.is_a?(String)
+      if value.match(/^-?(?:\d+)(?:\.\d+){1}$/)
+        value = value.to_f
+      elsif value.match(/^-?\d+$/)
+        value = value.to_i
+      else
+        raise(Puppet::ParseError, 'abs(): Requires float or ' +
+          'integer to work with')
+      end
+    end
+
+    # We have numeric value to handle ...
+    result = value.abs
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/any2array.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+#
+# any2array.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:any2array, :type => :rvalue, :doc => <<-EOS
+This converts any object to an array containing that object. Empty argument
+lists are converted to an empty array. Arrays are left untouched. Hashes are
+converted to arrays of alternating keys and values.
+    EOS
+  ) do |arguments|
+
+    if arguments.empty?
+        return []
+    end
+
+    if arguments.length == 1
+        if arguments[0].kind_of?(Array)
+            return arguments[0]
+        elsif arguments[0].kind_of?(Hash)
+            result = []
+            arguments[0].each do |key, value|
+                result << key << value
+            end
+            return result
+        end
+    end
+
+    return arguments
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/assert_private.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,29 @@
+#
+# assert_private.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:assert_private, :doc => <<-'EOS'
+    Sets the current class or definition as private.
+    Calling the class or definition from outside the current module will fail.
+    EOS
+  ) do |args|
+
+    raise(Puppet::ParseError, "assert_private(): Wrong number of arguments "+
+      "given (#{args.size}}) for 0 or 1)") if args.size > 1
+
+    scope = self
+    if scope.lookupvar('module_name') != scope.lookupvar('caller_module_name')
+      message = nil
+      if args[0] and args[0].is_a? String
+        message = args[0]
+      else
+        manifest_name = scope.source.name
+        manifest_type = scope.source.type
+        message = (manifest_type.to_s == 'hostclass') ? 'Class' : 'Definition'
+        message += " #{manifest_name} is private"
+      end
+      raise(Puppet::ParseError, message)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/base64.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+module Puppet::Parser::Functions
+
+  newfunction(:base64, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+
+    Base64 encode or decode a string based on the command and the string submitted
+
+    Usage:
+
+      $encodestring = base64('encode','thestring')
+      $decodestring = base64('decode','dGhlc3RyaW5n')
+
+    ENDHEREDOC
+
+    require 'base64'
+
+    raise Puppet::ParseError, ("base64(): Wrong number of arguments (#{args.length}; must be = 2)") unless args.length == 2
+
+    actions = ['encode','decode']
+
+    unless actions.include?(args[0])
+      raise Puppet::ParseError, ("base64(): the first argument must be one of 'encode' or 'decode'")
+    end
+
+    unless args[1].is_a?(String)
+      raise Puppet::ParseError, ("base64(): the second argument must be a string to base64")
+    end
+
+    case args[0]
+      when 'encode'
+        result = Base64.encode64(args[1])
+      when 'decode'
+        result = Base64.decode64(args[1])
+    end
+
+    return result
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/basename.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+module Puppet::Parser::Functions
+  newfunction(:basename, :type => :rvalue, :doc => <<-EOS
+    Strips directory (and optional suffix) from a filename
+    EOS
+  ) do |arguments|
+
+    if arguments.size < 1 then
+      raise(Puppet::ParseError, "basename(): No arguments given")
+    elsif arguments.size > 2 then
+      raise(Puppet::ParseError, "basename(): Too many arguments given (#{arguments.size})")
+    else
+
+      unless arguments[0].is_a?(String)
+        raise(Puppet::ParseError, 'basename(): Requires string as first argument')
+      end
+
+      if arguments.size == 1 then
+        rv = File.basename(arguments[0])
+      elsif arguments.size == 2 then
+
+        unless arguments[1].is_a?(String)
+          raise(Puppet::ParseError, 'basename(): Requires string as second argument')
+        end
+
+        rv = File.basename(arguments[0], arguments[1])
+      end
+
+    end
+
+    return rv
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/bool2num.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+#
+# bool2num.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:bool2num, :type => :rvalue, :doc => <<-EOS
+    Converts a boolean to a number. Converts the values:
+      false, f, 0, n, and no to 0
+      true, t, 1, y, and yes to 1
+    Requires a single boolean or string as an input.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "bool2num(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = function_str2bool([arguments[0]])
+
+    # We have real boolean values as well ...
+    result = value ? 1 : 0
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/bool2str.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+#
+# bool2str.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:bool2str, :type => :rvalue, :doc => <<-EOS
+    Converts a boolean to a string.
+    Requires a single boolean as an input.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "bool2str(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+    klass = value.class
+
+    # We can have either true or false, and nothing else
+    unless [FalseClass, TrueClass].include?(klass)
+      raise(Puppet::ParseError, 'bool2str(): Requires a boolean to work with')
+    end
+
+    return value.to_s
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/camelcase.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+#
+#  camelcase.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:camelcase, :type => :rvalue, :doc => <<-EOS
+Converts the case of a string or all strings in an array to camel case.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "camelcase(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+    klass = value.class
+
+    unless [Array, String].include?(klass)
+      raise(Puppet::ParseError, 'camelcase(): Requires either ' +
+        'array or string to work with')
+    end
+
+    if value.is_a?(Array)
+      # Numbers in Puppet are often string-encoded which is troublesome ...
+      result = value.collect { |i| i.is_a?(String) ? i.split('_').map{|e| e.capitalize}.join : i }
+    else
+      result = value.split('_').map{|e| e.capitalize}.join
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/capitalize.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+#
+#  capitalize.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:capitalize, :type => :rvalue, :doc => <<-EOS
+    Capitalizes the first letter of a string or array of strings.
+    Requires either a single string or an array as an input.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "capitalize(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'capitalize(): Requires either ' +
+        'array or string to work with')
+    end
+
+    if value.is_a?(Array)
+      # Numbers in Puppet are often string-encoded which is troublesome ...
+      result = value.collect { |i| i.is_a?(String) ? i.capitalize : i }
+    else
+      result = value.capitalize
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/ceiling.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+module Puppet::Parser::Functions
+  newfunction(:ceiling, :type => :rvalue, :doc => <<-EOS
+    Returns the smallest integer greater or equal to the argument.
+    Takes a single numeric value as an argument.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "ceiling(): Wrong number of arguments " +
+          "given (#{arguments.size} for 1)") if arguments.size != 1
+
+    begin
+      arg = Float(arguments[0])
+    rescue TypeError, ArgumentError => e
+      raise(Puppet::ParseError, "ceiling(): Wrong argument type " +
+            "given (#{arguments[0]} for Numeric)")
+    end
+
+    raise(Puppet::ParseError, "ceiling(): Wrong argument type " +
+          "given (#{arg.class} for Numeric)") if arg.is_a?(Numeric) == false
+
+    arg.ceil
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/chomp.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#
+#  chomp.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:chomp, :type => :rvalue, :doc => <<-'EOS'
+    Removes the record separator from the end of a string or an array of
+    strings, for example `hello\n` becomes `hello`.
+    Requires a single string or array as an input.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "chomp(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'chomp(): Requires either ' +
+        'array or string to work with')
+    end
+
+    if value.is_a?(Array)
+      # Numbers in Puppet are often string-encoded which is troublesome ...
+      result = value.collect { |i| i.is_a?(String) ? i.chomp : i }
+    else
+      result = value.chomp
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/chop.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+#
+#  chop.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:chop, :type => :rvalue, :doc => <<-'EOS'
+    Returns a new string with the last character removed. If the string ends
+    with `\r\n`, both characters are removed. Applying chop to an empty
+    string returns an empty string. If you wish to merely remove record
+    separators then you should use the `chomp` function.
+    Requires a string or array of strings as input.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "chop(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'chop(): Requires either an ' +
+        'array or string to work with')
+    end
+
+    if value.is_a?(Array)
+      # Numbers in Puppet are often string-encoded which is troublesome ...
+      result = value.collect { |i| i.is_a?(String) ? i.chop : i }
+    else
+      result = value.chop
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/concat.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,41 @@
+#
+# concat.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:concat, :type => :rvalue, :doc => <<-EOS
+Appends the contents of multiple arrays into array 1.
+
+*Example:*
+
+    concat(['1','2','3'],['4','5','6'],['7','8','9'])
+
+Would result in:
+
+  ['1','2','3','4','5','6','7','8','9']
+    EOS
+  ) do |arguments|
+
+    # Check that more than 2 arguments have been given ...
+    raise(Puppet::ParseError, "concat(): Wrong number of arguments " +
+      "given (#{arguments.size} for < 2)") if arguments.size < 2
+
+    a = arguments[0]
+
+    # Check that the first parameter is an array
+    unless a.is_a?(Array)
+      raise(Puppet::ParseError, 'concat(): Requires array to work with')
+    end
+
+    result = a
+    arguments.shift
+
+    arguments.each do |x|
+      result = result + Array(x)
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/convert_base.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+module Puppet::Parser::Functions
+
+  newfunction(:convert_base, :type => :rvalue, :arity => 2, :doc => <<-'ENDHEREDOC') do |args|
+
+    Converts a given integer or base 10 string representing an integer to a specified base, as a string.
+
+    Usage:
+
+      $binary_repr = convert_base(5, 2)  # $binary_repr is now set to "101"
+      $hex_repr = convert_base("254", "16")  # $hex_repr is now set to "fe"
+
+    ENDHEREDOC
+
+    raise Puppet::ParseError, ("convert_base(): First argument must be either a string or an integer") unless (args[0].is_a?(Integer) or args[0].is_a?(String))
+    raise Puppet::ParseError, ("convert_base(): Second argument must be either a string or an integer") unless (args[1].is_a?(Integer) or args[1].is_a?(String))
+
+    if args[0].is_a?(String)
+      raise Puppet::ParseError, ("convert_base(): First argument must be an integer or a string corresponding to an integer in base 10") unless args[0] =~ /^[0-9]+$/
+    end
+
+    if args[1].is_a?(String)
+      raise Puppet::ParseError, ("convert_base(): First argument must be an integer or a string corresponding to an integer in base 10") unless args[1] =~ /^[0-9]+$/
+    end
+
+    number_to_convert = args[0]
+    new_base = args[1]
+
+    number_to_convert = number_to_convert.to_i()
+    new_base = new_base.to_i()
+
+    raise Puppet::ParseError, ("convert_base(): base must be at least 2 and must not be greater than 36") unless new_base >= 2 and new_base <= 36
+
+    return number_to_convert.to_s(new_base)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/count.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+module Puppet::Parser::Functions
+  newfunction(:count, :type => :rvalue, :arity => -2, :doc => <<-EOS
+Takes an array as first argument and an optional second argument.
+Count the number of elements in array that matches second argument.
+If called with only an array it counts the number of elements that are not nil/undef.
+    EOS
+  ) do |args|
+
+    if (args.size > 2) then
+      raise(ArgumentError, "count(): Wrong number of arguments "+
+        "given #{args.size} for 1 or 2.")
+    end
+
+    collection, item = args
+
+    if item then
+      collection.count item
+    else
+      collection.count { |obj| obj != nil && obj != :undef && obj != '' }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/deep_merge.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,44 @@
+module Puppet::Parser::Functions
+  newfunction(:deep_merge, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+    Recursively merges two or more hashes together and returns the resulting hash.
+
+    For example:
+
+        $hash1 = {'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }
+        $hash2 = {'two' => 'dos', 'three' => { 'five' => 5 } }
+        $merged_hash = deep_merge($hash1, $hash2)
+        # The resulting hash is equivalent to:
+        # $merged_hash = { 'one' => 1, 'two' => 'dos', 'three' => { 'four' => 4, 'five' => 5 } }
+
+    When there is a duplicate key that is a hash, they are recursively merged.
+    When there is a duplicate key that is not a hash, the key in the rightmost hash will "win."
+
+    ENDHEREDOC
+
+    if args.length < 2
+      raise Puppet::ParseError, ("deep_merge(): wrong number of arguments (#{args.length}; must be at least 2)")
+    end
+
+    deep_merge = Proc.new do |hash1,hash2|
+      hash1.merge(hash2) do |key,old_value,new_value|
+        if old_value.is_a?(Hash) && new_value.is_a?(Hash)
+          deep_merge.call(old_value, new_value)
+        else
+          new_value
+        end
+      end
+    end
+
+    result = Hash.new
+    args.each do |arg|
+      next if arg.is_a? String and arg.empty? # empty string is synonym for puppet's undef
+      # If the argument was not a hash, skip it.
+      unless arg.is_a?(Hash)
+        raise Puppet::ParseError, "deep_merge: unexpected argument type #{arg.class}, only expects hash arguments"
+      end
+
+      result = deep_merge.call(result, arg)
+    end
+    return( result )
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/defined_with_params.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+# Test whether a given class or definition is defined
+require 'puppet/parser/functions'
+
+Puppet::Parser::Functions.newfunction(:defined_with_params,
+                                      :type => :rvalue,
+                                      :doc => <<-'ENDOFDOC'
+Takes a resource reference and an optional hash of attributes.
+
+Returns true if a resource with the specified attributes has already been added
+to the catalog, and false otherwise.
+
+    user { 'dan':
+      ensure => present,
+    }
+
+    if ! defined_with_params(User[dan], {'ensure' => 'present' }) {
+      user { 'dan': ensure => present, }
+    }
+ENDOFDOC
+) do |vals|
+  reference, params = vals
+  raise(ArgumentError, 'Must specify a reference') unless reference
+  if (! params) || params == ''
+    params = {}
+  end
+  ret = false
+  if resource = findresource(reference.to_s)
+    matches = params.collect do |key, value|
+      resource[key] == value
+    end
+    ret = params.empty? || !matches.include?(false)
+  end
+  Puppet.debug("Resource #{reference} was not determined to be defined")
+  ret
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/delete.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,49 @@
+#
+# delete.rb
+#
+
+# TODO(Krzysztof Wilczynski): We need to add support for regular expression ...
+
+module Puppet::Parser::Functions
+  newfunction(:delete, :type => :rvalue, :doc => <<-EOS
+Deletes all instances of a given element from an array, substring from a
+string, or key from a hash.
+
+*Examples:*
+
+    delete(['a','b','c','b'], 'b')
+    Would return: ['a','c']
+
+    delete({'a'=>1,'b'=>2,'c'=>3}, 'b')
+    Would return: {'a'=>1,'c'=>3}
+
+    delete({'a'=>1,'b'=>2,'c'=>3}, ['b','c'])
+    Would return: {'a'=>1}
+
+    delete('abracadabra', 'bra')
+    Would return: 'acada'
+  EOS
+  ) do |arguments|
+
+    if (arguments.size != 2) then
+      raise(Puppet::ParseError, "delete(): Wrong number of arguments "+
+                                  "given #{arguments.size} for 2.")
+    end
+
+    collection = arguments[0].dup
+    Array(arguments[1]).each do |item|
+      case collection
+        when Array, Hash
+          collection.delete item
+        when String
+          collection.gsub! item, ''
+        else
+          raise(TypeError, "delete(): First argument must be an Array, " +
+                             "String, or Hash. Given an argument of class #{collection.class}.")
+      end
+    end
+    collection
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/delete_at.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,49 @@
+#
+# delete_at.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:delete_at, :type => :rvalue, :doc => <<-EOS
+Deletes a determined indexed value from an array.
+
+*Examples:*
+
+    delete_at(['a','b','c'], 1)
+
+Would return: ['a','c']
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "delete_at(): Wrong number of arguments " +
+      "given (#{arguments.size} for 2)") if arguments.size < 2
+
+    array = arguments[0]
+
+    unless array.is_a?(Array)
+      raise(Puppet::ParseError, 'delete_at(): Requires array to work with')
+    end
+
+    index = arguments[1]
+
+    if index.is_a?(String) and not index.match(/^\d+$/)
+      raise(Puppet::ParseError, 'delete_at(): You must provide ' +
+        'non-negative numeric index')
+    end
+
+    result = array.clone
+
+    # Numbers in Puppet are often string-encoded which is troublesome ...
+    index = index.to_i
+
+    if index > result.size - 1 # First element is at index 0 is it not?
+      raise(Puppet::ParseError, 'delete_at(): Given index ' +
+        'exceeds size of array given')
+    end
+
+    result.delete_at(index) # We ignore the element that got deleted ...
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/delete_undef_values.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+module Puppet::Parser::Functions
+  newfunction(:delete_undef_values, :type => :rvalue, :doc => <<-EOS
+Returns a copy of input hash or array with all undefs deleted.
+
+*Examples:*
+
+    $hash = delete_undef_values({a=>'A', b=>'', c=>undef, d => false})
+
+Would return: {a => 'A', b => '', d => false}
+
+    $array = delete_undef_values(['A','',undef,false])
+
+Would return: ['A','',false]
+
+      EOS
+    ) do |args|
+
+    raise(Puppet::ParseError,
+          "delete_undef_values(): Wrong number of arguments given " +
+          "(#{args.size})") if args.size < 1
+
+    unless args[0].is_a? Array or args[0].is_a? Hash
+      raise(Puppet::ParseError,
+            "delete_undef_values(): expected an array or hash, got #{args[0]} type  #{args[0].class} ")
+    end
+    result = args[0].dup
+    if result.is_a?(Hash)
+      result.delete_if {|key, val| val.equal? :undef}
+    elsif result.is_a?(Array)
+      result.delete :undef
+    end
+    result
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/delete_values.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+module Puppet::Parser::Functions
+  newfunction(:delete_values, :type => :rvalue, :doc => <<-EOS
+Deletes all instances of a given value from a hash.
+
+*Examples:*
+
+    delete_values({'a'=>'A','b'=>'B','c'=>'C','B'=>'D'}, 'B')
+
+Would return: {'a'=>'A','c'=>'C','B'=>'D'}
+
+      EOS
+    ) do |arguments|
+
+    raise(Puppet::ParseError,
+          "delete_values(): Wrong number of arguments given " +
+          "(#{arguments.size} of 2)") if arguments.size != 2
+
+    hash, item = arguments
+
+    if not hash.is_a?(Hash)
+      raise(TypeError, "delete_values(): First argument must be a Hash. " + \
+                       "Given an argument of class #{hash.class}.")
+    end
+    hash.dup.delete_if { |key, val| item == val }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/difference.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+#
+# difference.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:difference, :type => :rvalue, :doc => <<-EOS
+This function returns the difference between two arrays.
+The returned array is a copy of the original array, removing any items that
+also appear in the second array.
+
+*Examples:*
+
+    difference(["a","b","c"],["b","c","d"])
+
+Would return: ["a"]
+    EOS
+  ) do |arguments|
+
+    # Two arguments are required
+    raise(Puppet::ParseError, "difference(): Wrong number of arguments " +
+      "given (#{arguments.size} for 2)") if arguments.size != 2
+
+    first = arguments[0]
+    second = arguments[1]
+
+    unless first.is_a?(Array) && second.is_a?(Array)
+      raise(Puppet::ParseError, 'difference(): Requires 2 arrays')
+    end
+
+    result = first - second
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/dirname.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+module Puppet::Parser::Functions
+  newfunction(:dirname, :type => :rvalue, :doc => <<-EOS
+    Returns the dirname of a path.
+    EOS
+  ) do |arguments|
+
+    if arguments.size < 1 then
+      raise(Puppet::ParseError, "dirname(): No arguments given")
+    end
+    if arguments.size > 1 then
+      raise(Puppet::ParseError, "dirname(): Too many arguments given (#{arguments.size})")
+    end
+    unless arguments[0].is_a?(String)
+      raise(Puppet::ParseError, 'dirname(): Requires string as argument')
+    end
+
+    return File.dirname(arguments[0])
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/dos2unix.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+# Custom Puppet function to convert dos to unix format
+module Puppet::Parser::Functions
+  newfunction(:dos2unix, :type => :rvalue, :arity => 1, :doc => <<-EOS
+    Returns the Unix version of the given string.
+    Takes a single string argument.
+    EOS
+  ) do |arguments|
+
+    unless arguments[0].is_a?(String)
+      raise(Puppet::ParseError, 'dos2unix(): Requires string as argument')
+    end
+
+    arguments[0].gsub(/\r\n/, "\n")
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/downcase.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+#
+#  downcase.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:downcase, :type => :rvalue, :doc => <<-EOS
+Converts the case of a string or all strings in an array to lower case.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "downcase(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'downcase(): Requires either ' +
+        'array or string to work with')
+    end
+
+    if value.is_a?(Array)
+      # Numbers in Puppet are often string-encoded which is troublesome ...
+      result = value.collect { |i| i.is_a?(String) ? i.downcase : i }
+    else
+      result = value.downcase
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/empty.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+#
+# empty.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:empty, :type => :rvalue, :doc => <<-EOS
+Returns true if the variable is empty.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "empty(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(Hash) || value.is_a?(String)
+      raise(Puppet::ParseError, 'empty(): Requires either ' +
+        'array, hash or string to work with')
+    end
+
+    result = value.empty?
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/ensure_packages.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+#
+# ensure_packages.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:ensure_packages, :type => :statement, :doc => <<-EOS
+Takes a list of packages and only installs them if they don't already exist.
+It optionally takes a hash as a second parameter that will be passed as the
+third argument to the ensure_resource() function.
+    EOS
+  ) do |arguments|
+
+    if arguments.size > 2 or arguments.size == 0
+      raise(Puppet::ParseError, "ensure_packages(): Wrong number of arguments " +
+        "given (#{arguments.size} for 1 or 2)")
+    elsif arguments.size == 2 and !arguments[1].is_a?(Hash) 
+      raise(Puppet::ParseError, 'ensure_packages(): Requires second argument to be a Hash')
+    end
+
+    packages = Array(arguments[0])
+
+    if arguments[1]
+      defaults = { 'ensure' => 'present' }.merge(arguments[1])
+    else
+      defaults = { 'ensure' => 'present' }
+    end
+
+    Puppet::Parser::Functions.function(:ensure_resource)
+    packages.each { |package_name|
+      function_ensure_resource(['package', package_name, defaults ])
+    }
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/ensure_resource.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+# Test whether a given class or definition is defined
+require 'puppet/parser/functions'
+
+Puppet::Parser::Functions.newfunction(:ensure_resource,
+                                      :type => :statement,
+                                      :doc => <<-'ENDOFDOC'
+Takes a resource type, title, and a list of attributes that describe a
+resource.
+
+    user { 'dan':
+      ensure => present,
+    }
+
+This example only creates the resource if it does not already exist:
+
+    ensure_resource('user', 'dan', {'ensure' => 'present' })
+
+If the resource already exists but does not match the specified parameters,
+this function will attempt to recreate the resource leading to a duplicate
+resource definition error.
+
+An array of resources can also be passed in and each will be created with
+the type and parameters specified if it doesn't already exist.
+
+    ensure_resource('user', ['dan','alex'], {'ensure' => 'present'})
+
+ENDOFDOC
+) do |vals|
+  type, title, params = vals
+  raise(ArgumentError, 'Must specify a type') unless type
+  raise(ArgumentError, 'Must specify a title') unless title
+  params ||= {}
+
+  items = [title].flatten
+
+  items.each do |item|
+    Puppet::Parser::Functions.function(:defined_with_params)
+    if function_defined_with_params(["#{type}[#{item}]", params])
+      Puppet.debug("Resource #{type}[#{item}] with params #{params} not created because it already exists")
+    else
+      Puppet.debug("Create new resource #{type}[#{item}] with params #{params}")
+      Puppet::Parser::Functions.function(:create_resources)
+      function_create_resources([type.capitalize, { item => params }])
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/flatten.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+#
+# flatten.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:flatten, :type => :rvalue, :doc => <<-EOS
+This function flattens any deeply nested arrays and returns a single flat array
+as a result.
+
+*Examples:*
+
+    flatten(['a', ['b', ['c']]])
+
+Would return: ['a','b','c']
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "flatten(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size != 1
+
+    array = arguments[0]
+
+    unless array.is_a?(Array)
+      raise(Puppet::ParseError, 'flatten(): Requires array to work with')
+    end
+
+    result = array.flatten
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/floor.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+module Puppet::Parser::Functions
+  newfunction(:floor, :type => :rvalue, :doc => <<-EOS
+    Returns the largest integer less or equal to the argument.
+    Takes a single numeric value as an argument.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "floor(): Wrong number of arguments " +
+          "given (#{arguments.size} for 1)") if arguments.size != 1
+
+    begin
+      arg = Float(arguments[0])
+    rescue TypeError, ArgumentError => e
+      raise(Puppet::ParseError, "floor(): Wrong argument type " +
+            "given (#{arguments[0]} for Numeric)")
+    end
+
+    raise(Puppet::ParseError, "floor(): Wrong argument type " +
+          "given (#{arg.class} for Numeric)") if arg.is_a?(Numeric) == false
+
+    arg.floor
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+Puppet::Parser::Functions::newfunction(
+  :fqdn_rand_string,
+  :arity => -2,
+  :type => :rvalue,
+  :doc => "Usage: `fqdn_rand_string(LENGTH, [CHARSET], [SEED])`. LENGTH is
+  required and must be a positive integer. CHARSET is optional and may be
+  `undef` or a string. SEED is optional and may be any number or string.
+
+  Generates a random string LENGTH characters long using the character set
+  provided by CHARSET, combining the `$fqdn` fact and the value of SEED for
+  repeatable randomness. (That is, each node will get a different random
+  string from this function, but a given node's result will be the same every
+  time unless its hostname changes.) Adding a SEED can be useful if you need
+  more than one unrelated string. CHARSET will default to alphanumeric if
+  `undef` or an empty string.") do |args|
+    raise(ArgumentError, "fqdn_rand_string(): wrong number of arguments (0 for 1)") if args.size == 0
+    Puppet::Parser::Functions.function('is_integer')
+    raise(ArgumentError, "fqdn_rand_string(): first argument must be a positive integer") unless function_is_integer([args[0]]) and args[0].to_i > 0
+    raise(ArgumentError, "fqdn_rand_string(): second argument must be undef or a string") unless args[1].nil? or args[1].is_a? String
+
+    Puppet::Parser::Functions.function('fqdn_rand')
+
+    length = args.shift.to_i
+    charset = args.shift.to_s.chars.to_a
+
+    charset = (0..9).map { |i| i.to_s } + ('A'..'Z').to_a + ('a'..'z').to_a if charset.empty?
+
+    rand_string = ''
+    for current in 1..length
+      rand_string << charset[function_fqdn_rand([charset.size, (args + [current.to_s]).join(':')]).to_i]
+    end
+
+    rand_string
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/fqdn_rotate.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,63 @@
+#
+# fqdn_rotate.rb
+#
+
+Puppet::Parser::Functions.newfunction(
+  :fqdn_rotate,
+  :type => :rvalue,
+  :doc => "Usage: `fqdn_rotate(VALUE, [SEED])`. VALUE is required and
+  must be an array or a string. SEED is optional and may be any number
+  or string.
+
+  Rotates VALUE a random number of times, combining the `$fqdn` fact and
+  the value of SEED for repeatable randomness. (That is, each node will
+  get a different random rotation from this function, but a given node's
+  result will be the same every time unless its hostname changes.) Adding
+  a SEED can be useful if you need more than one unrelated rotation.") do |args|
+
+    raise(Puppet::ParseError, "fqdn_rotate(): Wrong number of arguments " +
+      "given (#{args.size} for 1)") if args.size < 1
+
+    value = args.shift
+    require 'digest/md5'
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'fqdn_rotate(): Requires either ' +
+        'array or string to work with')
+    end
+
+    result = value.clone
+
+    string = value.is_a?(String) ? true : false
+
+    # Check whether it makes sense to rotate ...
+    return result if result.size <= 1
+
+    # We turn any string value into an array to be able to rotate ...
+    result = string ? result.split('') : result
+
+    elements = result.size
+
+    seed = Digest::MD5.hexdigest([lookupvar('::fqdn'),args].join(':')).hex
+    # deterministic_rand() was added in Puppet 3.2.0; reimplement if necessary
+    if Puppet::Util.respond_to?(:deterministic_rand)
+      offset = Puppet::Util.deterministic_rand(seed, elements).to_i
+    else
+      if defined?(Random) == 'constant' && Random.class == Class
+        offset = Random.new(seed).rand(elements)
+      else
+        old_seed = srand(seed)
+        offset = rand(elements)
+        srand(old_seed)
+      end
+    end
+    offset.times {
+       result.push result.shift
+    }
+
+    result = string ? result.join : result
+
+    return result
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/get_module_path.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+module Puppet::Parser::Functions
+  newfunction(:get_module_path, :type =>:rvalue, :doc => <<-EOT
+    Returns the absolute path of the specified module for the current
+    environment.
+
+    Example:
+      $module_path = get_module_path('stdlib')
+  EOT
+  ) do |args|
+    raise(Puppet::ParseError, "get_module_path(): Wrong number of arguments, expects one") unless args.size == 1
+    if module_path = Puppet::Module.find(args[0], compiler.environment.to_s)
+      module_path.path
+    else
+      raise(Puppet::ParseError, "Could not find module #{args[0]} in environment #{compiler.environment}")
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/getparam.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+# Test whether a given class or definition is defined
+require 'puppet/parser/functions'
+
+Puppet::Parser::Functions.newfunction(:getparam,
+                                      :type => :rvalue,
+                                      :doc => <<-'ENDOFDOC'
+Takes a resource reference and name of the parameter and
+returns value of resource's parameter.
+
+*Examples:*
+
+    define example_resource($param) {
+    }
+
+    example_resource { "example_resource_instance":
+        param => "param_value"
+    }
+
+    getparam(Example_resource["example_resource_instance"], "param")
+
+Would return: param_value
+ENDOFDOC
+) do |vals|
+  reference, param = vals
+  raise(ArgumentError, 'Must specify a reference') unless reference
+  raise(ArgumentError, 'Must specify name of a parameter') unless param and param.instance_of? String
+
+  return '' if param.empty?
+
+  if resource = findresource(reference.to_s)
+    return resource[param] if resource[param]
+  end
+
+  return ''
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/getvar.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+module Puppet::Parser::Functions
+
+  newfunction(:getvar, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+    Lookup a variable in a remote namespace.
+
+    For example:
+
+        $foo = getvar('site::data::foo')
+        # Equivalent to $foo = $site::data::foo
+
+    This is useful if the namespace itself is stored in a string:
+
+        $datalocation = 'site::data'
+        $bar = getvar("${datalocation}::bar")
+        # Equivalent to $bar = $site::data::bar
+    ENDHEREDOC
+
+    unless args.length == 1
+      raise Puppet::ParseError, ("getvar(): wrong number of arguments (#{args.length}; must be 1)")
+    end
+
+    begin
+      catch(:undefined_variable) do
+        self.lookupvar("#{args[0]}")
+      end
+    rescue Puppet::ParseError # Eat the exception if strict_variables = true is set
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/grep.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+#
+# grep.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:grep, :type => :rvalue, :doc => <<-EOS
+This function searches through an array and returns any elements that match
+the provided regular expression.
+
+*Examples:*
+
+    grep(['aaa','bbb','ccc','aaaddd'], 'aaa')
+
+Would return:
+
+    ['aaa','aaaddd']
+    EOS
+  ) do |arguments|
+
+    if (arguments.size != 2) then
+      raise(Puppet::ParseError, "grep(): Wrong number of arguments "+
+        "given #{arguments.size} for 2")
+    end
+
+    a = arguments[0]
+    pattern = Regexp.new(arguments[1])
+
+    a.grep(pattern)
+
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/has_interface_with.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,71 @@
+#
+# has_interface_with
+#
+
+module Puppet::Parser::Functions
+  newfunction(:has_interface_with, :type => :rvalue, :doc => <<-EOS
+Returns boolean based on kind and value:
+  * macaddress
+  * netmask
+  * ipaddress
+  * network
+
+has_interface_with("macaddress", "x:x:x:x:x:x")
+has_interface_with("ipaddress", "127.0.0.1")    => true
+etc.
+
+If no "kind" is given, then the presence of the interface is checked:
+has_interface_with("lo")                        => true
+    EOS
+  ) do |args|
+
+    raise(Puppet::ParseError, "has_interface_with(): Wrong number of arguments " +
+          "given (#{args.size} for 1 or 2)") if args.size < 1 or args.size > 2
+
+    interfaces = lookupvar('interfaces')
+
+    # If we do not have any interfaces, then there are no requested attributes
+    return false if (interfaces == :undefined || interfaces.nil?)
+
+    interfaces = interfaces.split(',')
+
+    if args.size == 1
+      return interfaces.member?(args[0])
+    end
+
+    kind, value = args
+
+    # Bug with 3.7.1 - 3.7.3  when using future parser throws :undefined_variable
+    # https://tickets.puppetlabs.com/browse/PUP-3597
+    factval = nil
+    begin
+      catch :undefined_variable do
+        factval = lookupvar(kind)
+      end
+    rescue Puppet::ParseError # Eat the exception if strict_variables = true is set
+    end
+    if factval == value
+      return true
+    end
+
+    result = false
+    interfaces.each do |iface|
+      iface.downcase!
+      factval = nil
+      begin
+        # Bug with 3.7.1 - 3.7.3 when using future parser throws :undefined_variable
+        # https://tickets.puppetlabs.com/browse/PUP-3597
+        catch :undefined_variable do
+          factval = lookupvar("#{kind}_#{iface}")
+        end
+      rescue Puppet::ParseError # Eat the exception if strict_variables = true is set
+      end
+      if value == factval
+        result = true
+        break
+      end
+    end
+
+    result
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/has_ip_address.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+#
+# has_ip_address
+#
+
+module Puppet::Parser::Functions
+  newfunction(:has_ip_address, :type => :rvalue, :doc => <<-EOS
+Returns true if the client has the requested IP address on some interface.
+
+This function iterates through the 'interfaces' fact and checks the
+'ipaddress_IFACE' facts, performing a simple string comparison.
+    EOS
+  ) do |args|
+
+    raise(Puppet::ParseError, "has_ip_address(): Wrong number of arguments " +
+          "given (#{args.size} for 1)") if args.size != 1
+
+    Puppet::Parser::Functions.autoloader.load(:has_interface_with) \
+      unless Puppet::Parser::Functions.autoloader.loaded?(:has_interface_with)
+
+    function_has_interface_with(['ipaddress', args[0]])
+
+  end
+end
+
+# vim:sts=2 sw=2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/has_ip_network.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+#
+# has_ip_network
+#
+
+module Puppet::Parser::Functions
+  newfunction(:has_ip_network, :type => :rvalue, :doc => <<-EOS
+Returns true if the client has an IP address within the requested network.
+
+This function iterates through the 'interfaces' fact and checks the
+'network_IFACE' facts, performing a simple string comparision.
+    EOS
+  ) do |args|
+
+    raise(Puppet::ParseError, "has_ip_network(): Wrong number of arguments " +
+          "given (#{args.size} for 1)") if args.size != 1
+
+    Puppet::Parser::Functions.autoloader.load(:has_interface_with) \
+      unless Puppet::Parser::Functions.autoloader.loaded?(:has_interface_with)
+
+    function_has_interface_with(['network', args[0]])
+
+  end
+end
+
+# vim:sts=2 sw=2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/has_key.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,28 @@
+module Puppet::Parser::Functions
+
+  newfunction(:has_key, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+    Determine if a hash has a certain key value.
+
+    Example:
+
+        $my_hash = {'key_one' => 'value_one'}
+        if has_key($my_hash, 'key_two') {
+          notice('we will not reach here')
+        }
+        if has_key($my_hash, 'key_one') {
+          notice('this will be printed')
+        }
+
+    ENDHEREDOC
+
+    unless args.length == 2
+      raise Puppet::ParseError, ("has_key(): wrong number of arguments (#{args.length}; must be 2)")
+    end
+    unless args[0].is_a?(Hash)
+      raise Puppet::ParseError, "has_key(): expects the first argument to be a hash, got #{args[0].inspect} which is of type #{args[0].class}"
+    end
+    args[0].has_key?(args[1])
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/hash.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,41 @@
+#
+# hash.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:hash, :type => :rvalue, :doc => <<-EOS
+This function converts an array into a hash.
+
+*Examples:*
+
+    hash(['a',1,'b',2,'c',3])
+
+Would return: {'a'=>1,'b'=>2,'c'=>3}
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "hash(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    array = arguments[0]
+
+    unless array.is_a?(Array)
+      raise(Puppet::ParseError, 'hash(): Requires array to work with')
+    end
+
+    result = {}
+
+    begin
+      # This is to make it compatible with older version of Ruby ...
+      array  = array.flatten
+      result = Hash[*array]
+    rescue Exception
+      raise(Puppet::ParseError, 'hash(): Unable to compute ' +
+        'hash from array given')
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/intersection.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#
+# intersection.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:intersection, :type => :rvalue, :doc => <<-EOS
+This function returns an array an intersection of two.
+
+*Examples:*
+
+    intersection(["a","b","c"],["b","c","d"])
+
+Would return: ["b","c"]
+    EOS
+  ) do |arguments|
+
+    # Two arguments are required
+    raise(Puppet::ParseError, "intersection(): Wrong number of arguments " +
+      "given (#{arguments.size} for 2)") if arguments.size != 2
+
+    first = arguments[0]
+    second = arguments[1]
+
+    unless first.is_a?(Array) && second.is_a?(Array)
+      raise(Puppet::ParseError, 'intersection(): Requires 2 arrays')
+    end
+
+    result = first & second
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_array.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#
+# is_array.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:is_array, :type => :rvalue, :doc => <<-EOS
+Returns true if the variable passed to this function is an array.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "is_array(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    type = arguments[0]
+
+    result = type.is_a?(Array)
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_bool.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#
+# is_bool.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:is_bool, :type => :rvalue, :doc => <<-EOS
+Returns true if the variable passed to this function is a boolean.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "is_bool(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size != 1
+
+    type = arguments[0]
+
+    result = type.is_a?(TrueClass) || type.is_a?(FalseClass)
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_domain_name.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,54 @@
+#
+# is_domain_name.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:is_domain_name, :type => :rvalue, :doc => <<-EOS
+Returns true if the string passed to this function is a syntactically correct domain name.
+    EOS
+  ) do |arguments|
+
+    if (arguments.size != 1) then
+      raise(Puppet::ParseError, "is_domain_name(): Wrong number of arguments "+
+        "given #{arguments.size} for 1")
+    end
+
+    # Only allow string types
+    return false unless arguments[0].is_a?(String)
+
+    domain = arguments[0].dup
+
+    # Limits (rfc1035, 3.1)
+    domain_max_length=255
+    label_min_length=1
+    label_max_length=63
+
+    # Allow ".", it is the top level domain
+    return true if domain == '.'
+
+    # Remove the final dot, if present.
+    domain.chomp!('.')
+
+    # Check the whole domain
+    return false if domain.empty?
+    return false if domain.length > domain_max_length
+
+    # The top level domain must be alphabetic if there are multiple labels.
+    # See rfc1123, 2.1
+    return false if domain.include? '.' and not /\.[A-Za-z]+$/.match(domain)
+
+    # Check each label in the domain
+    labels = domain.split('.')
+    vlabels = labels.each do |label|
+      break if label.length < label_min_length
+      break if label.length > label_max_length
+      break if label[-1..-1] == '-'
+      break if label[0..0] == '-'
+      break unless /^[a-z\d-]+$/i.match(label)
+    end
+    return vlabels == labels
+
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_float.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,30 @@
+#
+# is_float.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:is_float, :type => :rvalue, :doc => <<-EOS
+Returns true if the variable passed to this function is a float.
+    EOS
+  ) do |arguments|
+
+    if (arguments.size != 1) then
+      raise(Puppet::ParseError, "is_float(): Wrong number of arguments "+
+        "given #{arguments.size} for 1")
+    end
+
+    value = arguments[0]
+
+    # Only allow Numeric or String types
+    return false unless value.is_a?(Numeric) or value.is_a?(String)
+
+    if value != value.to_f.to_s and !value.is_a? Float then
+      return false
+    else
+      return true
+    end
+
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_function_available.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+#
+# is_function_available.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:is_function_available, :type => :rvalue, :doc => <<-EOS
+This function accepts a string as an argument, determines whether the
+Puppet runtime has access to a function by that name.  It returns a
+true if the function exists, false if not.
+    EOS
+  ) do |arguments|
+
+    if (arguments.size != 1) then
+      raise(Puppet::ParseError, "is_function_available?(): Wrong number of arguments "+
+        "given #{arguments.size} for 1")
+    end
+
+    # Only allow String types
+    return false unless arguments[0].is_a?(String)
+
+    function = Puppet::Parser::Functions.function(arguments[0].to_sym)
+    function.is_a?(String) and not function.empty?
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_hash.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#
+# is_hash.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:is_hash, :type => :rvalue, :doc => <<-EOS
+Returns true if the variable passed to this function is a hash.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "is_hash(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size != 1
+
+    type = arguments[0]
+
+    result = type.is_a?(Hash)
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_integer.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+#
+# is_integer.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:is_integer, :type => :rvalue, :doc => <<-EOS
+Returns true if the variable passed to this function is an Integer or
+a decimal (base 10) integer in String form. The string may
+start with a '-' (minus). A value of '0' is allowed, but a leading '0' digit may not
+be followed by other digits as this indicates that the value is octal (base 8).
+
+If given any other argument `false` is returned.
+    EOS
+  ) do |arguments|
+
+    if (arguments.size != 1) then
+      raise(Puppet::ParseError, "is_integer(): Wrong number of arguments "+
+        "given #{arguments.size} for 1")
+    end
+
+    value = arguments[0]
+
+    # Regex is taken from the lexer of puppet
+    # puppet/pops/parser/lexer.rb but modified to match also
+    # negative values and disallow numbers prefixed with multiple
+    # 0's
+    #
+    # TODO these parameter should be a constant but I'm not sure
+    # if there is no risk to declare it inside of the module
+    # Puppet::Parser::Functions
+
+    # Integer numbers like
+    # -1234568981273
+    # 47291
+    numeric = %r{^-?(?:(?:[1-9]\d*)|0)$}
+
+    if value.is_a? Integer or (value.is_a? String and value.match numeric)
+      return true
+    else
+      return false
+    end
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_ip_address.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+#
+# is_ip_address.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:is_ip_address, :type => :rvalue, :doc => <<-EOS
+Returns true if the string passed to this function is a valid IP address.
+    EOS
+  ) do |arguments|
+
+    require 'ipaddr'
+
+    if (arguments.size != 1) then
+      raise(Puppet::ParseError, "is_ip_address(): Wrong number of arguments "+
+        "given #{arguments.size} for 1")
+    end
+
+    begin
+      ip = IPAddr.new(arguments[0])
+    rescue ArgumentError
+      return false
+    end
+
+    if ip.ipv4? or ip.ipv6? then
+      return true
+    else
+      return false
+    end
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_mac_address.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+#
+# is_mac_address.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:is_mac_address, :type => :rvalue, :doc => <<-EOS
+Returns true if the string passed to this function is a valid mac address.
+    EOS
+  ) do |arguments|
+
+    if (arguments.size != 1) then
+      raise(Puppet::ParseError, "is_mac_address(): Wrong number of arguments "+
+        "given #{arguments.size} for 1")
+    end
+
+    mac = arguments[0]
+
+    if /^[a-f0-9]{1,2}(:[a-f0-9]{1,2}){5}$/i.match(mac) then
+      return true
+    else
+      return false
+    end
+
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_numeric.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,75 @@
+#
+# is_numeric.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:is_numeric, :type => :rvalue, :doc => <<-EOS
+Returns true if the given argument is a Numeric (Integer or Float),
+or a String containing either a valid integer in decimal base 10 form, or
+a valid floating point string representation.
+
+The function recognizes only decimal (base 10) integers and float but not
+integers in hex (base 16) or octal (base 8) form.
+
+The string representation may start with a '-' (minus). If a decimal '.' is used,
+it must be followed by at least one digit.
+
+Valid examples:
+
+  77435
+  10e-12
+  -8475
+  0.2343
+  -23.561e3
+    EOS
+  ) do |arguments|
+
+    if (arguments.size != 1) then
+      raise(Puppet::ParseError, "is_numeric(): Wrong number of arguments "+
+        "given #{arguments.size} for 1")
+    end
+
+    value = arguments[0]
+
+    # Regex is taken from the lexer of puppet
+    # puppet/pops/parser/lexer.rb but modified to match also
+    # negative values and disallow invalid octal numbers or
+    # numbers prefixed with multiple 0's (except in hex numbers)
+    #
+    # TODO these parameters should be constants but I'm not sure
+    # if there is no risk to declare them inside of the module
+    # Puppet::Parser::Functions
+
+    # TODO decide if this should be used
+    # HEX numbers like
+    # 0xaa230F
+    # 0X1234009C
+    # 0x0012
+    # -12FcD
+    #numeric_hex = %r{^-?0[xX][0-9A-Fa-f]+$}
+
+    # TODO decide if this should be used
+    # OCTAL numbers like
+    # 01234567
+    # -045372
+    #numeric_oct = %r{^-?0[1-7][0-7]*$}
+
+    # Integer/Float numbers like
+    # -0.1234568981273
+    # 47291
+    # 42.12345e-12
+    numeric = %r{^-?(?:(?:[1-9]\d*)|0)(?:\.\d+)?(?:[eE]-?\d+)?$}
+
+    if value.is_a? Numeric or (value.is_a? String and (
+      value.match(numeric) #or
+    #  value.match(numeric_hex) or
+    #  value.match(numeric_oct)
+    ))
+      return true
+    else
+      return false
+    end
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/is_string.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+#
+# is_string.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:is_string, :type => :rvalue, :doc => <<-EOS
+Returns true if the variable passed to this function is a string.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "is_string(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    type = arguments[0]
+
+    result = type.is_a?(String)
+
+    if result and (type == type.to_f.to_s or type == type.to_i.to_s) then
+      return false
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/join.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,41 @@
+#
+# join.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:join, :type => :rvalue, :doc => <<-EOS
+This function joins an array into a string using a separator.
+
+*Examples:*
+
+    join(['a','b','c'], ",")
+
+Would result in: "a,b,c"
+    EOS
+  ) do |arguments|
+
+    # Technically we support two arguments but only first is mandatory ...
+    raise(Puppet::ParseError, "join(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    array = arguments[0]
+
+    unless array.is_a?(Array)
+      raise(Puppet::ParseError, 'join(): Requires array to work with')
+    end
+
+    suffix = arguments[1] if arguments[1]
+
+    if suffix
+      unless suffix.is_a?(String)
+        raise(Puppet::ParseError, 'join(): Requires string to work with')
+      end
+    end
+
+    result = suffix ? array.join(suffix) : array.join
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/join_keys_to_values.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,47 @@
+#
+# join.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:join_keys_to_values, :type => :rvalue, :doc => <<-EOS
+This function joins each key of a hash to that key's corresponding value with a
+separator. Keys and values are cast to strings. The return value is an array in
+which each element is one joined key/value pair.
+
+*Examples:*
+
+    join_keys_to_values({'a'=>1,'b'=>2}, " is ")
+
+Would result in: ["a is 1","b is 2"]
+    EOS
+  ) do |arguments|
+
+    # Validate the number of arguments.
+    if arguments.size != 2
+      raise(Puppet::ParseError, "join_keys_to_values(): Takes exactly two " +
+            "arguments, but #{arguments.size} given.")
+    end
+
+    # Validate the first argument.
+    hash = arguments[0]
+    if not hash.is_a?(Hash)
+      raise(TypeError, "join_keys_to_values(): The first argument must be a " +
+            "hash, but a #{hash.class} was given.")
+    end
+
+    # Validate the second argument.
+    separator = arguments[1]
+    if not separator.is_a?(String)
+      raise(TypeError, "join_keys_to_values(): The second argument must be a " +
+            "string, but a #{separator.class} was given.")
+    end
+
+    # Join the keys to their values.
+    hash.map do |k,v|
+      String(k) + separator + String(v)
+    end
+
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/keys.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+#
+# keys.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:keys, :type => :rvalue, :doc => <<-EOS
+Returns the keys of a hash as an array.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "keys(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    hash = arguments[0]
+
+    unless hash.is_a?(Hash)
+      raise(Puppet::ParseError, 'keys(): Requires hash to work with')
+    end
+
+    result = hash.keys
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/load_module_metadata.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+module Puppet::Parser::Functions
+  newfunction(:load_module_metadata, :type => :rvalue, :doc => <<-EOT
+  EOT
+  ) do |args|
+    raise(Puppet::ParseError, "load_module_metadata(): Wrong number of arguments, expects one") unless args.size == 1
+    mod = args[0]
+    module_path = function_get_module_path([mod])
+    metadata_json = File.join(module_path, 'metadata.json')
+
+    raise(Puppet::ParseError, "load_module_metadata(): No metadata.json file for module #{mod}") unless File.exists?(metadata_json)
+
+    metadata = PSON.load(File.read(metadata_json))
+
+    return metadata
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/loadyaml.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+module Puppet::Parser::Functions
+
+  newfunction(:loadyaml, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+    Load a YAML file containing an array, string, or hash, and return the data
+    in the corresponding native data type.
+
+    For example:
+
+        $myhash = loadyaml('/etc/puppet/data/myhash.yaml')
+    ENDHEREDOC
+
+    unless args.length == 1
+      raise Puppet::ParseError, ("loadyaml(): wrong number of arguments (#{args.length}; must be 1)")
+    end
+
+    if File.exists?(args[0]) then
+      YAML.load_file(args[0])
+    else
+      warning("Can't load " + args[0] + ". File does not exist!")
+      nil
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/lstrip.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+#
+#  lstrip.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:lstrip, :type => :rvalue, :doc => <<-EOS
+Strips leading spaces to the left of a string.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "lstrip(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'lstrip(): Requires either ' +
+        'array or string to work with')
+    end
+
+    if value.is_a?(Array)
+      # Numbers in Puppet are often string-encoded which is troublesome ...
+      result = value.collect { |i| i.is_a?(String) ? i.lstrip : i }
+    else
+      result = value.lstrip
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/max.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+module Puppet::Parser::Functions
+  newfunction(:max, :type => :rvalue, :doc => <<-EOS
+    Returns the highest value of all arguments.
+    Requires at least one argument.
+    EOS
+  ) do |args|
+
+    raise(Puppet::ParseError, "max(): Wrong number of arguments " +
+          "need at least one") if args.size == 0
+
+    # Sometimes we get numbers as numerics and sometimes as strings.
+    # We try to compare them as numbers when possible
+    return args.max do |a,b|
+      if a.to_s =~ /\A-?\d+(.\d+)?\z/ and b.to_s =~ /\A-?\d+(.\d+)?\z/ then
+        a.to_f <=> b.to_f
+      else
+        a.to_s <=> b.to_s
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/member.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,62 @@
+#
+# member.rb
+#
+
+# TODO(Krzysztof Wilczynski): We need to add support for regular expression ...
+# TODO(Krzysztof Wilczynski): Support for strings and hashes too ...
+
+module Puppet::Parser::Functions
+  newfunction(:member, :type => :rvalue, :doc => <<-EOS
+This function determines if a variable is a member of an array.
+The variable can be a string, fixnum, or array.
+
+*Examples:*
+
+    member(['a','b'], 'b')
+
+Would return: true
+
+    member(['a', 'b', 'c'], ['a', 'b'])
+
+would return: true
+
+    member(['a','b'], 'c')
+
+Would return: false
+
+    member(['a', 'b', 'c'], ['d', 'b'])
+
+would return: false
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "member(): Wrong number of arguments " +
+      "given (#{arguments.size} for 2)") if arguments.size < 2
+
+    array = arguments[0]
+
+    unless array.is_a?(Array)
+      raise(Puppet::ParseError, 'member(): Requires array to work with')
+    end
+
+    unless arguments[1].is_a? String or arguments[1].is_a? Fixnum or arguments[1].is_a? Array
+      raise(Puppet::ParseError, 'member(): Item to search for must be a string, fixnum, or array')
+    end
+
+    if arguments[1].is_a? String or arguments[1].is_a? Fixnum
+      item = [arguments[1]]
+    else
+      item = arguments[1]
+    end
+
+
+    raise(Puppet::ParseError, 'member(): You must provide item ' +
+      'to search for within array given') if item.respond_to?('empty?') && item.empty?
+
+    result = (item - array).empty?
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/merge.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+module Puppet::Parser::Functions
+  newfunction(:merge, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args|
+    Merges two or more hashes together and returns the resulting hash.
+
+    For example:
+
+        $hash1 = {'one' => 1, 'two', => 2}
+        $hash2 = {'two' => 'dos', 'three', => 'tres'}
+        $merged_hash = merge($hash1, $hash2)
+        # The resulting hash is equivalent to:
+        # $merged_hash =  {'one' => 1, 'two' => 'dos', 'three' => 'tres'}
+
+    When there is a duplicate key, the key in the rightmost hash will "win."
+
+    ENDHEREDOC
+
+    if args.length < 2
+      raise Puppet::ParseError, ("merge(): wrong number of arguments (#{args.length}; must be at least 2)")
+    end
+
+    # The hash we accumulate into
+    accumulator = Hash.new
+    # Merge into the accumulator hash
+    args.each do |arg|
+      next if arg.is_a? String and arg.empty? # empty string is synonym for puppet's undef
+      unless arg.is_a?(Hash)
+        raise Puppet::ParseError, "merge: unexpected argument type #{arg.class}, only expects hash arguments"
+      end
+      accumulator.merge!(arg)
+    end
+    # Return the fully merged hash
+    accumulator
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/min.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+module Puppet::Parser::Functions
+  newfunction(:min, :type => :rvalue, :doc => <<-EOS
+    Returns the lowest value of all arguments.
+    Requires at least one argument.
+    EOS
+  ) do |args|
+
+    raise(Puppet::ParseError, "min(): Wrong number of arguments " +
+          "need at least one") if args.size == 0
+
+    # Sometimes we get numbers as numerics and sometimes as strings.
+    # We try to compare them as numbers when possible
+    return args.min do |a,b|
+      if a.to_s =~ /\A^-?\d+(.\d+)?\z/ and b.to_s =~ /\A-?\d+(.\d+)?\z/ then
+        a.to_f <=> b.to_f
+      else
+        a.to_s <=> b.to_s
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/num2bool.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,43 @@
+#
+# num2bool.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:num2bool, :type => :rvalue, :doc => <<-EOS
+This function converts a number or a string representation of a number into a
+true boolean. Zero or anything non-numeric becomes false. Numbers higher then 0
+become true.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "num2bool(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size != 1
+
+    number = arguments[0]
+
+    case number
+    when Numeric
+      # Yay, it's a number
+    when String
+      begin
+        number = Float(number)
+      rescue ArgumentError => ex
+        raise(Puppet::ParseError, "num2bool(): '#{number}' does not look like a number: #{ex.message}")
+      end
+    else
+      begin
+        number = number.to_s
+      rescue NoMethodError => ex
+        raise(Puppet::ParseError, "num2bool(): Unable to parse argument: #{ex.message}")
+      end
+    end
+
+    # Truncate Floats
+    number = number.to_i
+
+    # Return true for any positive number and false otherwise
+    return number > 0
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/parsejson.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+#
+# parsejson.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:parsejson, :type => :rvalue, :doc => <<-EOS
+This function accepts JSON as a string and converts into the correct Puppet
+structure.
+    EOS
+  ) do |arguments|
+
+    if (arguments.size != 1) then
+      raise(Puppet::ParseError, "parsejson(): Wrong number of arguments "+
+        "given #{arguments.size} for 1")
+    end
+
+    json = arguments[0]
+
+    # PSON is natively available in puppet
+    PSON.load(json)
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/parseyaml.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+#
+# parseyaml.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:parseyaml, :type => :rvalue, :doc => <<-EOS
+This function accepts YAML as a string and converts it into the correct
+Puppet structure.
+    EOS
+  ) do |arguments|
+
+    if (arguments.size != 1) then
+      raise(Puppet::ParseError, "parseyaml(): Wrong number of arguments "+
+        "given #{arguments.size} for 1")
+    end
+
+    require 'yaml'
+
+    YAML::load(arguments[0])
+
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/pick.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,29 @@
+module Puppet::Parser::Functions
+ newfunction(:pick, :type => :rvalue, :doc => <<-EOS
+
+This function is similar to a coalesce function in SQL in that it will return
+the first value in a list of values that is not undefined or an empty string
+(two things in Puppet that will return a boolean false value). Typically,
+this function is used to check for a value in the Puppet Dashboard/Enterprise
+Console, and failover to a default value like the following:
+
+  $real_jenkins_version = pick($::jenkins_version, '1.449')
+
+The value of $real_jenkins_version will first look for a top-scope variable
+called 'jenkins_version' (note that parameters set in the Puppet Dashboard/
+Enterprise Console are brought into Puppet as top-scope variables), and,
+failing that, will use a default value of 1.449.
+
+EOS
+) do |args|
+   args = args.compact
+   args.delete(:undef)
+   args.delete(:undefined)
+   args.delete("")
+   if args[0].to_s.empty? then
+     fail Puppet::ParseError, "pick(): must receive at least one non empty value"
+   else
+     return args[0]
+   end
+ end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/pick_default.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+module Puppet::Parser::Functions
+ newfunction(:pick_default, :type => :rvalue, :doc => <<-EOS
+
+This function is similar to a coalesce function in SQL in that it will return
+the first value in a list of values that is not undefined or an empty string
+(two things in Puppet that will return a boolean false value). If no value is
+found, it will return the last argument.
+
+Typically, this function is used to check for a value in the Puppet
+Dashboard/Enterprise Console, and failover to a default value like the
+following:
+
+  $real_jenkins_version = pick_default($::jenkins_version, '1.449')
+
+The value of $real_jenkins_version will first look for a top-scope variable
+called 'jenkins_version' (note that parameters set in the Puppet Dashboard/
+Enterprise Console are brought into Puppet as top-scope variables), and,
+failing that, will use a default value of 1.449.
+
+Note that, contrary to the pick() function, the pick_default does not fail if
+all arguments are empty. This allows pick_default to use an empty value as
+default.
+
+EOS
+) do |args|
+   fail "Must receive at least one argument." if args.empty?
+   default = args.last
+   args = args[0..-2].compact
+   args.delete(:undef)
+   args.delete(:undefined)
+   args.delete("")
+   args << default
+   return args[0]
+ end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/prefix.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,52 @@
+#
+# prefix.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:prefix, :type => :rvalue, :doc => <<-EOS
+This function applies a prefix to all elements in an array or a hash.
+
+*Examples:*
+
+    prefix(['a','b','c'], 'p')
+
+Will return: ['pa','pb','pc']
+    EOS
+  ) do |arguments|
+
+    # Technically we support two arguments but only first is mandatory ...
+    raise(Puppet::ParseError, "prefix(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    enumerable = arguments[0]
+
+    unless enumerable.is_a?(Array) or enumerable.is_a?(Hash)
+      raise Puppet::ParseError, "prefix(): expected first argument to be an Array or a Hash, got #{enumerable.inspect}"
+    end
+
+    prefix = arguments[1] if arguments[1]
+
+    if prefix
+      unless prefix.is_a?(String)
+        raise Puppet::ParseError, "prefix(): expected second argument to be a String, got #{prefix.inspect}"
+      end
+    end
+
+    if enumerable.is_a?(Array)
+      # Turn everything into string same as join would do ...
+      result = enumerable.collect do |i|
+        i = i.to_s
+        prefix ? prefix + i : i
+      end
+    else
+      result = Hash[enumerable.map do |k,v|
+        k = k.to_s
+        [ prefix ? prefix + k : k, v ]
+      end]
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/private.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+#
+# private.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:private, :doc => <<-'EOS'
+    DEPRECATED: Sets the current class or definition as private.
+    Calling the class or definition from outside the current module will fail.
+  EOS
+  ) do |args|
+    warning("private() DEPRECATED: This function will cease to function on Puppet 4; please use assert_private() before upgrading to puppet 4 for backwards-compatibility, or migrate to the new parser's typing system.")
+    if !Puppet::Parser::Functions.autoloader.loaded?(:assert_private)
+      Puppet::Parser::Functions.autoloader.load(:assert_private)
+    end
+    function_assert_private([(args[0] unless args.size < 1)])
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/pw_hash.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,56 @@
+Puppet::Parser::Functions::newfunction(
+  :pw_hash,
+  :type => :rvalue,
+  :arity => 3,
+  :doc => "Hashes a password using the crypt function. Provides a hash
+  usable on most POSIX systems.
+
+  The first argument to this function is the password to hash. If it is
+  undef or an empty string, this function returns undef.
+
+  The second argument to this function is which type of hash to use. It
+  will be converted into the appropriate crypt(3) hash specifier. Valid
+  hash types are:
+
+  |Hash type            |Specifier|
+  |---------------------|---------|
+  |MD5                  |1        |
+  |SHA-256              |5        |
+  |SHA-512 (recommended)|6        |
+
+  The third argument to this function is the salt to use.
+
+  Note: this uses the Puppet Master's implementation of crypt(3). If your
+  environment contains several different operating systems, ensure that they
+  are compatible before using this function.") do |args|
+    raise ArgumentError, "pw_hash(): wrong number of arguments (#{args.size} for 3)" if args.size != 3
+    raise ArgumentError, "pw_hash(): first argument must be a string" unless args[0].is_a? String or args[0].nil?
+    raise ArgumentError, "pw_hash(): second argument must be a string" unless args[1].is_a? String
+    hashes = { 'md5'     => '1',
+               'sha-256' => '5',
+               'sha-512' => '6' }
+    hash_type = hashes[args[1].downcase]
+    raise ArgumentError, "pw_hash(): #{args[1]} is not a valid hash type" if hash_type.nil?
+    raise ArgumentError, "pw_hash(): third argument must be a string" unless args[2].is_a? String
+    raise ArgumentError, "pw_hash(): third argument must not be empty" if args[2].empty?
+    raise ArgumentError, "pw_hash(): characters in salt must be in the set [a-zA-Z0-9./]" unless args[2].match(/\A[a-zA-Z0-9.\/]+\z/)
+
+    password = args[0]
+    return nil if password.nil? or password.empty?
+
+    salt = "$#{hash_type}$#{args[2]}"
+
+    # handle weak implementations of String#crypt
+    if 'test'.crypt('$1$1') != '$1$1$Bp8CU9Oujr9SSEw53WV6G.'
+      # JRuby < 1.7.17
+      if RUBY_PLATFORM == 'java'
+        # puppetserver bundles Apache Commons Codec
+        org.apache.commons.codec.digest.Crypt.crypt(password.to_java_bytes, salt)
+      else
+        # MS Windows and other systems that don't support enhanced salts
+        raise Puppet::ParseError, 'system does not support enhanced salts'
+      end
+    else
+      password.crypt(salt)
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/range.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,87 @@
+#
+# range.rb
+#
+
+# TODO(Krzysztof Wilczynski): We probably need to approach numeric values differently ...
+
+module Puppet::Parser::Functions
+  newfunction(:range, :type => :rvalue, :doc => <<-EOS
+When given range in the form of (start, stop) it will extrapolate a range as
+an array.
+
+*Examples:*
+
+    range("0", "9")
+
+Will return: [0,1,2,3,4,5,6,7,8,9]
+
+    range("00", "09")
+
+Will return: [0,1,2,3,4,5,6,7,8,9] (Zero padded strings are converted to
+integers automatically)
+
+    range("a", "c")
+
+Will return: ["a","b","c"]
+
+    range("host01", "host10")
+
+Will return: ["host01", "host02", ..., "host09", "host10"]
+
+Passing a third argument will cause the generated range to step by that
+interval, e.g.
+
+    range("0", "9", "2")
+
+Will return: [0,2,4,6,8]
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, 'range(): Wrong number of ' +
+      'arguments given (0 for 1)') if arguments.size == 0
+
+    if arguments.size > 1
+      start = arguments[0]
+      stop  = arguments[1]
+      step  = arguments[2].nil? ? 1 : arguments[2].to_i.abs
+
+      type = '..' # Use the simplest type of Range available in Ruby
+
+    else # arguments.size == 1
+      value = arguments[0]
+
+      if m = value.match(/^(\w+)(\.\.\.?|\-)(\w+)$/)
+        start = m[1]
+        stop  = m[3]
+
+        type = m[2]
+        step = 1
+      elsif value.match(/^.+$/)
+        raise(Puppet::ParseError, "range(): Unable to compute range " +
+          "from the value: #{value}")
+      else
+        raise(Puppet::ParseError, "range(): Unknown range format: #{value}")
+      end
+    end
+
+    # If we were given an integer, ensure we work with one
+    if start.to_s.match(/^\d+$/)
+      start = start.to_i
+      stop  = stop.to_i
+    else
+      start = start.to_s
+      stop  = stop.to_s
+    end
+
+    range = case type
+      when /^(\.\.|\-)$/ then (start .. stop)
+      when '...'         then (start ... stop) # Exclusive of last element
+    end
+
+    result = range.step(step).to_a
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/reject.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+#
+# reject.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:reject, :type => :rvalue, :doc => <<-EOS) do |args|
+This function searches through an array and rejects all elements that match
+the provided regular expression.
+
+*Examples:*
+
+    reject(['aaa','bbb','ccc','aaaddd'], 'aaa')
+
+Would return:
+
+    ['bbb','ccc']
+EOS
+
+    if (args.size != 2)
+      raise Puppet::ParseError,
+        "reject(): Wrong number of arguments given #{args.size} for 2"
+    end
+
+    ary = args[0]
+    pattern = Regexp.new(args[1])
+
+    ary.reject { |e| e =~ pattern }
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/reverse.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+#
+# reverse.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:reverse, :type => :rvalue, :doc => <<-EOS
+Reverses the order of a string or array.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "reverse(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'reverse(): Requires either ' +
+        'array or string to work with')
+    end
+
+    result = value.reverse
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/rstrip.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+#
+#  rstrip.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:rstrip, :type => :rvalue, :doc => <<-EOS
+Strips leading spaces to the right of the string.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "rstrip(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'rstrip(): Requires either ' +
+        'array or string to work with')
+    end
+
+    if value.is_a?(Array)
+      result = value.collect { |i| i.is_a?(String) ? i.rstrip : i }
+    else
+      result = value.rstrip
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/shuffle.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+#
+# shuffle.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:shuffle, :type => :rvalue, :doc => <<-EOS
+Randomizes the order of a string or array elements.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "shuffle(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'shuffle(): Requires either ' +
+        'array or string to work with')
+    end
+
+    result = value.clone
+
+    string = value.is_a?(String) ? true : false
+
+    # Check whether it makes sense to shuffle ...
+    return result if result.size <= 1
+
+    # We turn any string value into an array to be able to shuffle ...
+    result = string ? result.split('') : result
+
+    elements = result.size
+
+    # Simple implementation of Fisher–Yates in-place shuffle ...
+    elements.times do |i|
+      j = rand(elements - i) + i
+      result[j], result[i] = result[i], result[j]
+    end
+
+    result = string ? result.join : result
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/size.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+#
+# size.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:size, :type => :rvalue, :doc => <<-EOS
+Returns the number of elements in a string, an array or a hash
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "size(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    item = arguments[0]
+
+    if item.is_a?(String)
+
+      begin
+        #
+        # Check whether your item is a numeric value or not ...
+        # This will take care about positive and/or negative numbers
+        # for both integer and floating-point values ...
+        #
+        # Please note that Puppet has no notion of hexadecimal
+        # nor octal numbers for its DSL at this point in time ...
+        #
+        Float(item)
+
+        raise(Puppet::ParseError, 'size(): Requires either ' +
+          'string, array or hash to work with')
+
+      rescue ArgumentError
+        result = item.size
+      end
+
+    elsif item.is_a?(Array) || item.is_a?(Hash)
+      result = item.size
+    else
+      raise(Puppet::ParseError, 'size(): Unknown type given')
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/sort.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+#
+# sort.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:sort, :type => :rvalue, :doc => <<-EOS
+Sorts strings and arrays lexically.
+    EOS
+  ) do |arguments|
+
+    if (arguments.size != 1) then
+      raise(Puppet::ParseError, "sort(): Wrong number of arguments "+
+        "given #{arguments.size} for 1")
+    end
+
+    value = arguments[0]
+
+    if value.is_a?(Array) then
+      value.sort
+    elsif value.is_a?(String) then
+      value.split("").sort.join("")
+    end
+
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/squeeze.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+#
+# squeeze.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:squeeze, :type => :rvalue, :doc => <<-EOS
+Returns a new string where runs of the same character that occur in this set are replaced by a single character.
+    EOS
+  ) do |arguments|
+
+    if ((arguments.size != 2) and (arguments.size != 1)) then
+      raise(Puppet::ParseError, "squeeze(): Wrong number of arguments "+
+        "given #{arguments.size} for 2 or 1")
+    end
+
+    item = arguments[0]
+    squeezeval = arguments[1]
+
+    if item.is_a?(Array) then
+      if squeezeval then
+        item.collect { |i| i.squeeze(squeezeval) }
+      else
+        item.collect { |i| i.squeeze }
+      end
+    else
+      if squeezeval then
+        item.squeeze(squeezeval)
+      else
+        item.squeeze
+      end
+    end
+
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/str2bool.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+#
+# str2bool.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:str2bool, :type => :rvalue, :doc => <<-EOS
+This converts a string to a boolean. This attempt to convert strings that
+contain things like: y, 1, t, true to 'true' and strings that contain things
+like: 0, f, n, false, no to 'false'.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "str2bool(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    string = arguments[0]
+
+    # If string is already Boolean, return it
+    if !!string == string
+      return string
+    end
+
+    unless string.is_a?(String)
+      raise(Puppet::ParseError, 'str2bool(): Requires either ' +
+        'string to work with')
+    end
+
+    # We consider all the yes, no, y, n and so on too ...
+    result = case string
+      #
+      # This is how undef looks like in Puppet ...
+      # We yield false in this case.
+      #
+      when /^$/, '' then false # Empty string will be false ...
+      when /^(1|t|y|true|yes)$/  then true
+      when /^(0|f|n|false|no)$/  then false
+      when /^(undef|undefined)$/ then false # This is not likely to happen ...
+      else
+        raise(Puppet::ParseError, 'str2bool(): Unknown type of boolean given')
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/str2saltedsha512.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+#
+# str2saltedsha512.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:str2saltedsha512, :type => :rvalue, :doc => <<-EOS
+This converts a string to a salted-SHA512 password hash (which is used for
+OS X versions >= 10.7). Given any simple string, you will get a hex version
+of a salted-SHA512 password hash that can be inserted into your Puppet
+manifests as a valid password attribute.
+    EOS
+  ) do |arguments|
+    require 'digest/sha2'
+
+    raise(Puppet::ParseError, "str2saltedsha512(): Wrong number of arguments " +
+      "passed (#{arguments.size} but we require 1)") if arguments.size != 1
+
+    password = arguments[0]
+
+    unless password.is_a?(String)
+      raise(Puppet::ParseError, 'str2saltedsha512(): Requires a ' +
+        "String argument, you passed: #{password.class}")
+    end
+
+    seedint    = rand(2**31 - 1)
+    seedstring = Array(seedint).pack("L")
+    saltedpass = Digest::SHA512.digest(seedstring + password)
+    (seedstring + saltedpass).unpack('H*')[0]
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/strftime.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,107 @@
+#
+# strftime.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:strftime, :type => :rvalue, :doc => <<-EOS
+This function returns formatted time.
+
+*Examples:*
+
+To return the time since epoch:
+
+    strftime("%s")
+
+To return the date:
+
+    strftime("%Y-%m-%d")
+
+*Format meaning:*
+
+    %a - The abbreviated weekday name (``Sun'')
+    %A - The  full  weekday  name (``Sunday'')
+    %b - The abbreviated month name (``Jan'')
+    %B - The  full  month  name (``January'')
+    %c - The preferred local date and time representation
+    %C - Century (20 in 2009)
+    %d - Day of the month (01..31)
+    %D - Date (%m/%d/%y)
+    %e - Day of the month, blank-padded ( 1..31)
+    %F - Equivalent to %Y-%m-%d (the ISO 8601 date format)
+    %h - Equivalent to %b
+    %H - Hour of the day, 24-hour clock (00..23)
+    %I - Hour of the day, 12-hour clock (01..12)
+    %j - Day of the year (001..366)
+    %k - hour, 24-hour clock, blank-padded ( 0..23)
+    %l - hour, 12-hour clock, blank-padded ( 0..12)
+    %L - Millisecond of the second (000..999)
+    %m - Month of the year (01..12)
+    %M - Minute of the hour (00..59)
+    %n - Newline (\n)
+    %N - Fractional seconds digits, default is 9 digits (nanosecond)
+            %3N  millisecond (3 digits)
+            %6N  microsecond (6 digits)
+            %9N  nanosecond (9 digits)
+    %p - Meridian indicator (``AM''  or  ``PM'')
+    %P - Meridian indicator (``am''  or  ``pm'')
+    %r - time, 12-hour (same as %I:%M:%S %p)
+    %R - time, 24-hour (%H:%M)
+    %s - Number of seconds since 1970-01-01 00:00:00 UTC.
+    %S - Second of the minute (00..60)
+    %t - Tab character (\t)
+    %T - time, 24-hour (%H:%M:%S)
+    %u - Day of the week as a decimal, Monday being 1. (1..7)
+    %U - Week  number  of the current year,
+            starting with the first Sunday as the first
+            day of the first week (00..53)
+    %v - VMS date (%e-%b-%Y)
+    %V - Week number of year according to ISO 8601 (01..53)
+    %W - Week  number  of the current year,
+            starting with the first Monday as the first
+            day of the first week (00..53)
+    %w - Day of the week (Sunday is 0, 0..6)
+    %x - Preferred representation for the date alone, no time
+    %X - Preferred representation for the time alone, no date
+    %y - Year without a century (00..99)
+    %Y - Year with century
+    %z - Time zone as  hour offset from UTC (e.g. +0900)
+    %Z - Time zone name
+    %% - Literal ``%'' character
+    EOS
+  ) do |arguments|
+
+    # Technically we support two arguments but only first is mandatory ...
+    raise(Puppet::ParseError, "strftime(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    format = arguments[0]
+
+    raise(Puppet::ParseError, 'strftime(): You must provide ' +
+      'format for evaluation') if format.empty?
+
+    # The Time Zone argument is optional ...
+    time_zone = arguments[1] if arguments[1]
+
+    time = Time.new
+
+    # There is probably a better way to handle Time Zone ...
+    if time_zone and not time_zone.empty?
+      original_zone = ENV['TZ']
+
+      local_time = time.clone
+      local_time = local_time.utc
+
+      ENV['TZ'] = time_zone
+
+      time = local_time.localtime
+
+      ENV['TZ'] = original_zone
+    end
+
+    result = time.strftime(format)
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/strip.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,38 @@
+#
+#  strip.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:strip, :type => :rvalue, :doc => <<-EOS
+This function removes leading and trailing whitespace from a string or from
+every string inside an array.
+
+*Examples:*
+
+    strip("    aaa   ")
+
+Would result in: "aaa"
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "strip(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'strip(): Requires either ' +
+        'array or string to work with')
+    end
+
+    if value.is_a?(Array)
+      result = value.collect { |i| i.is_a?(String) ? i.strip : i }
+    else
+      result = value.strip
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/suffix.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+#
+# suffix.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:suffix, :type => :rvalue, :doc => <<-EOS
+This function applies a suffix to all elements in an array.
+
+*Examples:*
+
+    suffix(['a','b','c'], 'p')
+
+Will return: ['ap','bp','cp']
+    EOS
+  ) do |arguments|
+
+    # Technically we support two arguments but only first is mandatory ...
+    raise(Puppet::ParseError, "suffix(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    array = arguments[0]
+
+    unless array.is_a?(Array)
+      raise Puppet::ParseError, "suffix(): expected first argument to be an Array, got #{array.inspect}"
+    end
+
+    suffix = arguments[1] if arguments[1]
+
+    if suffix
+      unless suffix.is_a? String
+        raise Puppet::ParseError, "suffix(): expected second argument to be a String, got #{suffix.inspect}"
+      end
+    end
+
+    # Turn everything into string same as join would do ...
+    result = array.collect do |i|
+      i = i.to_s
+      suffix ? i + suffix : i
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/swapcase.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,38 @@
+#
+#  swapcase.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:swapcase, :type => :rvalue, :doc => <<-EOS
+This function will swap the existing case of a string.
+
+*Examples:*
+
+    swapcase("aBcD")
+
+Would result in: "AbCd"
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "swapcase(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'swapcase(): Requires either ' +
+        'array or string to work with')
+    end
+
+    if value.is_a?(Array)
+      # Numbers in Puppet are often string-encoded which is troublesome ...
+      result = value.collect { |i| i.is_a?(String) ? i.swapcase : i }
+    else
+      result = value.swapcase
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/time.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,50 @@
+#
+# time.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:time, :type => :rvalue, :doc => <<-EOS
+This function will return the current time since epoch as an integer.
+
+*Examples:*
+
+    time()
+
+Will return something like: 1311972653
+    EOS
+  ) do |arguments|
+
+    # The Time Zone argument is optional ...
+    time_zone = arguments[0] if arguments[0]
+
+    if (arguments.size != 0) and (arguments.size != 1) then
+      raise(Puppet::ParseError, "time(): Wrong number of arguments "+
+        "given #{arguments.size} for 0 or 1")
+    end
+
+    time = Time.new
+
+    # There is probably a better way to handle Time Zone ...
+    if time_zone and not time_zone.empty?
+      original_zone = ENV['TZ']
+
+      local_time = time.clone
+      local_time = local_time.utc
+
+      ENV['TZ'] = time_zone
+
+      result = local_time.localtime.strftime('%s')
+
+      ENV['TZ'] = original_zone
+    else
+      result = time.localtime.strftime('%s')
+    end
+
+    # Calling Time#to_i on a receiver changes it.  Trust me I am the Doctor.
+    result = result.to_i
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/to_bytes.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+module Puppet::Parser::Functions
+  newfunction(:to_bytes, :type => :rvalue, :doc => <<-EOS
+    Converts the argument into bytes, for example 4 kB becomes 4096.
+    Takes a single string value as an argument.
+    These conversions reflect a layperson's understanding of
+    1 MB = 1024 KB, when in fact 1 MB = 1000 KB, and 1 MiB = 1024 KiB.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "to_bytes(): Wrong number of arguments " +
+          "given (#{arguments.size} for 1)") if arguments.size != 1
+
+    arg = arguments[0]
+
+    return arg if arg.is_a? Numeric
+
+    value,prefix = */([0-9.e+-]*)\s*([^bB]?)/.match(arg)[1,2]
+
+    value = value.to_f
+    case prefix
+    when '' then return value.to_i
+    when 'k' then return (value*(1<<10)).to_i
+    when 'M' then return (value*(1<<20)).to_i
+    when 'G' then return (value*(1<<30)).to_i
+    when 'T' then return (value*(1<<40)).to_i
+    when 'P' then return (value*(1<<50)).to_i
+    when 'E' then return (value*(1<<60)).to_i
+    else raise Puppet::ParseError, "to_bytes(): Unknown prefix #{prefix}"
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/try_get_value.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,77 @@
+module Puppet::Parser::Functions
+  newfunction(
+      :try_get_value,
+      :type => :rvalue,
+      :arity => -2,
+      :doc => <<-eos
+Looks up into a complex structure of arrays and hashes and returns a value
+or the default value if nothing was found.
+
+Key can contain slashes to describe path components. The function will go down
+the structure and try to extract the required value.
+
+$data = {
+  'a' => {
+    'b' => [
+      'b1',
+      'b2',
+      'b3',
+    ]
+  }
+}
+
+$value = try_get_value($data, 'a/b/2', 'not_found', '/')
+=> $value = 'b3'
+
+a -> first hash key
+b -> second hash key
+2 -> array index starting with 0
+
+not_found -> (optional) will be returned if there is no value or the path did not match. Defaults to nil.
+/ -> (optional) path delimiter. Defaults to '/'.
+
+In addition to the required "key" argument, "try_get_value" accepts default
+argument. It will be returned if no value was found or a path component is
+missing. And the fourth argument can set a variable path separator.
+  eos
+  ) do |args|
+    path_lookup = lambda do |data, path, default|
+      debug "Try_get_value: #{path.inspect} from: #{data.inspect}"
+      if data.nil?
+        debug "Try_get_value: no data, return default: #{default.inspect}"
+        break default
+      end
+      unless path.is_a? Array
+        debug "Try_get_value: wrong path, return default: #{default.inspect}"
+        break default
+      end
+      unless path.any?
+        debug "Try_get_value: value found, return data: #{data.inspect}"
+        break data
+      end
+      unless data.is_a? Hash or data.is_a? Array
+        debug "Try_get_value: incorrect data, return default: #{default.inspect}"
+        break default
+      end
+
+      key = path.shift
+      if data.is_a? Array
+        begin
+          key = Integer key
+        rescue ArgumentError
+          debug "Try_get_value: non-numeric path for an array, return default: #{default.inspect}"
+          break default
+        end
+      end
+      path_lookup.call data[key], path, default
+    end
+
+    data = args[0]
+    path = args[1] || ''
+    default = args[2]
+    separator = args[3] || '/'
+
+    path = path.split separator
+    path_lookup.call data, path, default
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/type.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+#
+# type.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:type, :type => :rvalue, :doc => <<-EOS
+  DEPRECATED: This function will cease to function on Puppet 4; please use type3x() before upgrading to puppet 4 for backwards-compatibility, or migrate to the new parser's typing system.
+    EOS
+  ) do |args|
+
+    warning("type() DEPRECATED: This function will cease to function on Puppet 4; please use type3x() before upgrading to puppet 4 for backwards-compatibility, or migrate to the new parser's typing system.")
+    if ! Puppet::Parser::Functions.autoloader.loaded?(:type3x)
+      Puppet::Parser::Functions.autoloader.load(:type3x)
+    end
+    function_type3x(args + [false])
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/type3x.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,51 @@
+#
+# type3x.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:type3x, :type => :rvalue, :doc => <<-EOS
+DEPRECATED: This function will be removed when puppet 3 support is dropped; please migrate to the new parser's typing system.
+
+Returns the type when passed a value. Type can be one of:
+
+* string
+* array
+* hash
+* float
+* integer
+* boolean
+    EOS
+  ) do |args|
+    raise(Puppet::ParseError, "type3x(): Wrong number of arguments " +
+      "given (#{args.size} for 1)") if args.size < 1
+
+    value = args[0]
+
+    klass = value.class
+
+    if not [TrueClass, FalseClass, Array, Bignum, Fixnum, Float, Hash, String].include?(klass)
+      raise(Puppet::ParseError, 'type3x(): Unknown type')
+    end
+
+    klass = klass.to_s # Ugly ...
+
+    # We note that Integer is the parent to Bignum and Fixnum ...
+    result = case klass
+      when /^(?:Big|Fix)num$/ then 'integer'
+      when /^(?:True|False)Class$/ then 'boolean'
+      else klass
+    end
+
+    if result == "String" then
+      if value == value.to_i.to_s then
+        result = "Integer"
+      elsif value == value.to_f.to_s then
+        result = "Float"
+      end
+    end
+
+    return result.downcase
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/union.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,29 @@
+#
+# union.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:union, :type => :rvalue, :doc => <<-EOS
+This function returns a union of two or more arrays.
+
+*Examples:*
+
+    union(["a","b","c"],["b","c","d"])
+
+Would return: ["a","b","c","d"]
+    EOS
+  ) do |arguments|
+
+    # Check that 2 or more arguments have been given ...
+    raise(Puppet::ParseError, "union(): Wrong number of arguments " +
+      "given (#{arguments.size} for < 2)") if arguments.size < 2
+
+    arguments.each do |argument|
+      raise(Puppet::ParseError, 'union(): Every parameter must be an array') unless argument.is_a?(Array)
+    end
+
+    arguments.reduce(:|)
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/unique.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,50 @@
+#
+# unique.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:unique, :type => :rvalue, :doc => <<-EOS
+This function will remove duplicates from strings and arrays.
+
+*Examples:*
+
+    unique("aabbcc")
+
+Will return:
+
+    abc
+
+You can also use this with arrays:
+
+    unique(["a","a","b","b","c","c"])
+
+This returns:
+
+    ["a","b","c"]
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "unique(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'unique(): Requires either ' +
+        'array or string to work with')
+    end
+
+    result = value.clone
+
+    string = value.is_a?(String) ? true : false
+
+    # We turn any string value into an array to be able to shuffle ...
+    result = string ? result.split('') : result
+    result = result.uniq # Remove duplicates ...
+    result = string ? result.join : result
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/unix2dos.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+# Custom Puppet function to convert unix to dos format
+module Puppet::Parser::Functions
+  newfunction(:unix2dos, :type => :rvalue, :arity => 1, :doc => <<-EOS
+    Returns the DOS version of the given string.
+    Takes a single string argument.
+    EOS
+  ) do |arguments|
+
+    unless arguments[0].is_a?(String)
+      raise(Puppet::ParseError, 'unix2dos(): Requires string as argument')
+    end
+
+    arguments[0].gsub(/\r*\n/, "\r\n")
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/upcase.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+#
+# upcase.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:upcase, :type => :rvalue, :doc => <<-EOS
+Converts a string or an array of strings to uppercase.
+
+*Examples:*
+
+    upcase("abcd")
+
+Will return:
+
+    ABCD
+  EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "upcase(): Wrong number of arguments " +
+                                "given (#{arguments.size} for 1)") if arguments.size != 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(Hash) || value.respond_to?(:upcase)
+      raise(Puppet::ParseError, 'upcase(): Requires an ' +
+                                  'array, hash or object that responds to upcase in order to work')
+    end
+
+    if value.is_a?(Array)
+      # Numbers in Puppet are often string-encoded which is troublesome ...
+      result = value.collect { |i| function_upcase([i]) }
+    elsif value.is_a?(Hash)
+      result = {}
+      value.each_pair do |k, v|
+        result[function_upcase([k])] = function_upcase([v])
+      end
+    else
+      result = value.upcase
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/uriescape.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#
+#  uriescape.rb
+#
+require 'uri'
+
+module Puppet::Parser::Functions
+  newfunction(:uriescape, :type => :rvalue, :doc => <<-EOS
+    Urlencodes a string or array of strings.
+    Requires either a single string or an array as an input.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "uriescape(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    value = arguments[0]
+
+    unless value.is_a?(Array) || value.is_a?(String)
+      raise(Puppet::ParseError, 'uriescape(): Requires either ' +
+        'array or string to work with')
+    end
+
+    if value.is_a?(Array)
+      # Numbers in Puppet are often string-encoded which is troublesome ...
+      result = value.collect { |i| i.is_a?(String) ? URI.escape(i) : i }
+    else
+      result = URI.escape(value)
+    end
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_absolute_path.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,69 @@
+module Puppet::Parser::Functions
+  newfunction(:validate_absolute_path, :doc => <<-'ENDHEREDOC') do |args|
+    Validate the string represents an absolute path in the filesystem.  This function works
+    for windows and unix style paths.
+
+    The following values will pass:
+
+        $my_path = 'C:/Program Files (x86)/Puppet Labs/Puppet'
+        validate_absolute_path($my_path)
+        $my_path2 = '/var/lib/puppet'
+        validate_absolute_path($my_path2)
+        $my_path3 = ['C:/Program Files (x86)/Puppet Labs/Puppet','C:/Program Files/Puppet Labs/Puppet']
+        validate_absolute_path($my_path3)
+        $my_path4 = ['/var/lib/puppet','/usr/share/puppet']
+        validate_absolute_path($my_path4)
+
+    The following values will fail, causing compilation to abort:
+
+        validate_absolute_path(true)
+        validate_absolute_path('../var/lib/puppet')
+        validate_absolute_path('var/lib/puppet')
+        validate_absolute_path([ 'var/lib/puppet', '/var/foo' ])
+        validate_absolute_path([ '/var/lib/puppet', 'var/foo' ])
+        $undefined = undef
+        validate_absolute_path($undefined)
+
+    ENDHEREDOC
+
+    require 'puppet/util'
+
+    unless args.length > 0 then
+      raise Puppet::ParseError, ("validate_absolute_path(): wrong number of arguments (#{args.length}; must be > 0)")
+    end
+
+    args.each do |arg|
+      # put arg to candidate var to be able to replace it
+      candidates = arg
+      # if arg is just a string with a path to test, convert it to an array
+      # to avoid test code duplication
+      unless arg.is_a?(Array) then
+        candidates = Array.new(1,arg)
+      end
+      # iterate over all pathes within the candidates array
+      candidates.each do |path|
+        # This logic was borrowed from
+        # [lib/puppet/file_serving/base.rb](https://github.com/puppetlabs/puppet/blob/master/lib/puppet/file_serving/base.rb)
+        # Puppet 2.7 and beyond will have Puppet::Util.absolute_path? Fall back to a back-ported implementation otherwise.
+        if Puppet::Util.respond_to?(:absolute_path?) then
+          unless Puppet::Util.absolute_path?(path, :posix) or Puppet::Util.absolute_path?(path, :windows)
+            raise Puppet::ParseError, ("#{path.inspect} is not an absolute path.")
+          end
+        else
+          # This code back-ported from 2.7.x's lib/puppet/util.rb Puppet::Util.absolute_path?
+          # Determine in a platform-specific way whether a path is absolute. This
+          # defaults to the local platform if none is specified.
+          # Escape once for the string literal, and once for the regex.
+          slash = '[\\\\/]'
+          name = '[^\\\\/]+'
+          regexes = {
+            :windows => %r!^(([A-Z]:#{slash})|(#{slash}#{slash}#{name}#{slash}#{name})|(#{slash}#{slash}\?#{slash}#{name}))!i,
+            :posix => %r!^/!,
+          }
+          rval = (!!(path =~ regexes[:posix])) || (!!(path =~ regexes[:windows]))
+          rval or raise Puppet::ParseError, ("#{path.inspect} is not an absolute path.")
+        end
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_array.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+module Puppet::Parser::Functions
+
+  newfunction(:validate_array, :doc => <<-'ENDHEREDOC') do |args|
+    Validate that all passed values are array data structures. Abort catalog
+    compilation if any value fails this check.
+
+    The following values will pass:
+
+        $my_array = [ 'one', 'two' ]
+        validate_array($my_array)
+
+    The following values will fail, causing compilation to abort:
+
+        validate_array(true)
+        validate_array('some_string')
+        $undefined = undef
+        validate_array($undefined)
+
+    ENDHEREDOC
+
+    unless args.length > 0 then
+      raise Puppet::ParseError, ("validate_array(): wrong number of arguments (#{args.length}; must be > 0)")
+    end
+
+    args.each do |arg|
+      unless arg.is_a?(Array)
+        raise Puppet::ParseError, ("#{arg.inspect} is not an Array.  It looks to be a #{arg.class}")
+      end
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_augeas.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,83 @@
+require 'tempfile'
+
+module Puppet::Parser::Functions
+  newfunction(:validate_augeas, :doc => <<-'ENDHEREDOC') do |args|
+    Perform validation of a string using an Augeas lens
+    The first argument of this function should be a string to
+    test, and the second argument should be the name of the Augeas lens to use.
+    If Augeas fails to parse the string with the lens, the compilation will
+    abort with a parse error.
+
+    A third argument can be specified, listing paths which should
+    not be found in the file. The `$file` variable points to the location
+    of the temporary file being tested in the Augeas tree.
+
+    For example, if you want to make sure your passwd content never contains
+    a user `foo`, you could write:
+
+        validate_augeas($passwdcontent, 'Passwd.lns', ['$file/foo'])
+
+    Or if you wanted to ensure that no users used the '/bin/barsh' shell,
+    you could use:
+
+        validate_augeas($passwdcontent, 'Passwd.lns', ['$file/*[shell="/bin/barsh"]']
+
+    If a fourth argument is specified, this will be the error message raised and
+    seen by the user.
+
+    A helpful error message can be returned like this:
+
+        validate_augeas($sudoerscontent, 'Sudoers.lns', [], 'Failed to validate sudoers content with Augeas')
+
+    ENDHEREDOC
+    unless Puppet.features.augeas?
+      raise Puppet::ParseError, ("validate_augeas(): this function requires the augeas feature. See http://docs.puppetlabs.com/guides/augeas.html#pre-requisites for how to activate it.")
+    end
+
+    if (args.length < 2) or (args.length > 4) then
+      raise Puppet::ParseError, ("validate_augeas(): wrong number of arguments (#{args.length}; must be 2, 3, or 4)")
+    end
+
+    msg = args[3] || "validate_augeas(): Failed to validate content against #{args[1].inspect}"
+
+    require 'augeas'
+    aug = Augeas::open(nil, nil, Augeas::NO_MODL_AUTOLOAD)
+    begin
+      content = args[0]
+
+      # Test content in a temporary file
+      tmpfile = Tempfile.new("validate_augeas")
+      begin
+        tmpfile.write(content)
+      ensure
+        tmpfile.close
+      end
+
+      # Check for syntax
+      lens = args[1]
+      aug.transform(
+        :lens => lens,
+        :name => 'Validate_augeas',
+        :incl => tmpfile.path
+      )
+      aug.load!
+
+      unless aug.match("/augeas/files#{tmpfile.path}//error").empty?
+        error = aug.get("/augeas/files#{tmpfile.path}//error/message")
+        msg += " with error: #{error}"
+        raise Puppet::ParseError, (msg)
+      end
+
+      # Launch unit tests
+      tests = args[2] || []
+      aug.defvar('file', "/files#{tmpfile.path}")
+      tests.each do |t|
+        msg += " testing path #{t}"
+        raise Puppet::ParseError, (msg) unless aug.match(t).empty?
+      end
+    ensure
+      aug.close
+      tmpfile.unlink
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_bool.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+module Puppet::Parser::Functions
+
+  newfunction(:validate_bool, :doc => <<-'ENDHEREDOC') do |args|
+    Validate that all passed values are either true or false. Abort catalog
+    compilation if any value fails this check.
+
+    The following values will pass:
+
+        $iamtrue = true
+        validate_bool(true)
+        validate_bool(true, true, false, $iamtrue)
+
+    The following values will fail, causing compilation to abort:
+
+        $some_array = [ true ]
+        validate_bool("false")
+        validate_bool("true")
+        validate_bool($some_array)
+
+    ENDHEREDOC
+
+    unless args.length > 0 then
+      raise Puppet::ParseError, ("validate_bool(): wrong number of arguments (#{args.length}; must be > 0)")
+    end
+
+    args.each do |arg|
+      unless function_is_bool([arg])
+        raise Puppet::ParseError, ("#{arg.inspect} is not a boolean.  It looks to be a #{arg.class}")
+      end
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_cmd.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,63 @@
+require 'puppet/util/execution'
+require 'tempfile'
+
+module Puppet::Parser::Functions
+  newfunction(:validate_cmd, :doc => <<-'ENDHEREDOC') do |args|
+    Perform validation of a string with an external command.
+    The first argument of this function should be a string to
+    test, and the second argument should be a path to a test command
+    taking a % as a placeholder for the file path (will default to the end).
+    If the command, launched against a tempfile containing the passed string,
+    returns a non-null value, compilation will abort with a parse error.
+
+    If a third argument is specified, this will be the error message raised and
+    seen by the user.
+
+    A helpful error message can be returned like this:
+
+    Example:
+
+        # Defaults to end of path
+        validate_cmd($sudoerscontent, '/usr/sbin/visudo -c -f', 'Visudo failed to validate sudoers content')
+
+        # % as file location
+        validate_cmd($haproxycontent, '/usr/sbin/haproxy -f % -c', 'Haproxy failed to validate config content')
+
+    ENDHEREDOC
+    if (args.length < 2) or (args.length > 3) then
+      raise Puppet::ParseError, ("validate_cmd(): wrong number of arguments (#{args.length}; must be 2 or 3)")
+    end
+
+    msg = args[2] || "validate_cmd(): failed to validate content with command #{args[1].inspect}"
+
+    content = args[0]
+    checkscript = args[1]
+
+    # Test content in a temporary file
+    tmpfile = Tempfile.new("validate_cmd")
+    begin
+      tmpfile.write(content)
+      tmpfile.close
+
+      if checkscript =~ /\s%(\s|$)/
+        check_with_correct_location = checkscript.gsub(/%/,tmpfile.path)
+      else
+        check_with_correct_location = "#{checkscript} #{tmpfile.path}"
+      end
+
+      if Puppet::Util::Execution.respond_to?('execute')
+        Puppet::Util::Execution.execute(check_with_correct_location)
+      else
+        Puppet::Util.execute(check_with_correct_location)
+      end
+    rescue Puppet::ExecutionFailure => detail
+      msg += "\n#{detail}"
+      raise Puppet::ParseError, msg
+    rescue Exception => detail
+      msg += "\n#{detail.class.name} #{detail}"
+      raise Puppet::ParseError, msg
+    ensure
+      tmpfile.unlink
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_hash.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+module Puppet::Parser::Functions
+
+  newfunction(:validate_hash, :doc => <<-'ENDHEREDOC') do |args|
+    Validate that all passed values are hash data structures. Abort catalog
+    compilation if any value fails this check.
+
+    The following values will pass:
+
+        $my_hash = { 'one' => 'two' }
+        validate_hash($my_hash)
+
+    The following values will fail, causing compilation to abort:
+
+        validate_hash(true)
+        validate_hash('some_string')
+        $undefined = undef
+        validate_hash($undefined)
+
+    ENDHEREDOC
+
+    unless args.length > 0 then
+      raise Puppet::ParseError, ("validate_hash(): wrong number of arguments (#{args.length}; must be > 0)")
+    end
+
+    args.each do |arg|
+      unless arg.is_a?(Hash)
+        raise Puppet::ParseError, ("#{arg.inspect} is not a Hash.  It looks to be a #{arg.class}")
+      end
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_integer.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,132 @@
+module Puppet::Parser::Functions
+
+  newfunction(:validate_integer, :doc => <<-'ENDHEREDOC') do |args|
+    Validate that the first argument is an integer (or an array of integers). Abort catalog compilation if any of the checks fail.
+    
+    The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
+
+    The third argument is optional and passes a minimum.  (All elements of) the first argument has to be greater or equal to this min.
+    If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
+    if (all elements of) the first argument are greater or equal to the given minimum.
+
+    It will fail if the first argument is not an integer or array of integers, and if arg 2 and arg 3 are not convertable to an integer.
+
+    The following values will pass:
+
+      validate_integer(1)
+      validate_integer(1, 2)
+      validate_integer(1, 1)
+      validate_integer(1, 2, 0)
+      validate_integer(2, 2, 2)
+      validate_integer(2, '', 0)
+      validate_integer(2, undef, 0)
+      $foo = undef
+      validate_integer(2, $foo, 0)
+      validate_integer([1,2,3,4,5], 6)
+      validate_integer([1,2,3,4,5], 6, 0)
+
+    Plus all of the above, but any combination of values passed as strings ('1' or "1").
+    Plus all of the above, but with (correct) combinations of negative integer values.
+
+    The following values will not:
+
+      validate_integer(true)
+      validate_integer(false)
+      validate_integer(7.0)
+      validate_integer({ 1 => 2 })
+      $foo = undef
+      validate_integer($foo)
+      validate_integer($foobaridontexist)
+
+      validate_integer(1, 0)
+      validate_integer(1, true)
+      validate_integer(1, '')
+      validate_integer(1, undef)
+      validate_integer(1, , 0)
+      validate_integer(1, 2, 3)
+      validate_integer(1, 3, 2)
+      validate_integer(1, 3, true)
+
+    Plus all of the above, but any combination of values passed as strings ('false' or "false").
+    Plus all of the above, but with incorrect combinations of negative integer values.
+    Plus all of the above, but with non-integer items in arrays or maximum / minimum argument.
+
+    ENDHEREDOC
+
+    # tell the user we need at least one, and optionally up to two other parameters
+    raise Puppet::ParseError, "validate_integer(): Wrong number of arguments; must be 1, 2 or 3, got #{args.length}" unless args.length > 0 and args.length < 4
+
+    input, max, min = *args
+
+    # check maximum parameter
+    if args.length > 1
+      max = max.to_s
+      # allow max to be empty (or undefined) if we have a minimum set
+      if args.length > 2 and max == ''
+        max = nil
+      else
+        begin
+          max = Integer(max)
+        rescue TypeError, ArgumentError
+          raise Puppet::ParseError, "validate_integer(): Expected second argument to be unset or an Integer, got #{max}:#{max.class}"
+        end
+      end
+    else
+      max = nil
+    end
+
+    # check minimum parameter
+    if args.length > 2
+      begin
+        min = Integer(min.to_s)
+      rescue TypeError, ArgumentError
+        raise Puppet::ParseError, "validate_integer(): Expected third argument to be unset or an Integer, got #{min}:#{min.class}"
+      end
+    else
+      min = nil
+    end
+
+    # ensure that min < max
+    if min and max and min > max
+      raise Puppet::ParseError, "validate_integer(): Expected second argument to be larger than third argument, got #{max} < #{min}"
+    end
+
+    # create lamba validator function
+    validator = lambda do |num|
+      # check input < max
+      if max and num > max
+        raise Puppet::ParseError, "validate_integer(): Expected #{input.inspect} to be smaller or equal to #{max}, got #{input.inspect}."
+      end
+      # check input > min (this will only be checked if no exception has been raised before)
+      if min and num < min
+        raise Puppet::ParseError, "validate_integer(): Expected #{input.inspect} to be greater or equal to #{min}, got #{input.inspect}."
+      end
+    end
+
+    # if this is an array, handle it.
+    case input
+    when Array
+      # check every element of the array
+      input.each_with_index do |arg, pos|
+        begin
+          raise TypeError if arg.is_a?(Hash)
+          arg = Integer(arg.to_s)
+          validator.call(arg)
+        rescue TypeError, ArgumentError
+          raise Puppet::ParseError, "validate_integer(): Expected element at array position #{pos} to be an Integer, got #{arg.class}"
+        end
+      end
+    # for the sake of compatibility with ruby 1.8, we need extra handling of hashes
+    when Hash
+      raise Puppet::ParseError, "validate_integer(): Expected first argument to be an Integer or Array, got #{input.class}"
+    # check the input. this will also fail any stuff other than pure, shiny integers
+    else
+      begin
+        input = Integer(input.to_s)
+        validator.call(input)
+      rescue TypeError, ArgumentError
+        raise Puppet::ParseError, "validate_integer(): Expected first argument to be an Integer or Array, got #{input.class}"
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_ipv4_address.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,48 @@
+module Puppet::Parser::Functions
+
+  newfunction(:validate_ipv4_address, :doc => <<-ENDHEREDOC
+    Validate that all values passed are valid IPv4 addresses.
+    Fail compilation if any value fails this check.
+
+    The following values will pass:
+
+    $my_ip = "1.2.3.4"
+    validate_ipv4_address($my_ip)
+    validate_bool("8.8.8.8", "172.16.0.1", $my_ip)
+
+    The following values will fail, causing compilation to abort:
+
+    $some_array = [ 1, true, false, "garbage string", "3ffe:505:2" ]
+    validate_ipv4_address($some_array)
+
+    ENDHEREDOC
+  ) do |args|
+
+    require "ipaddr"
+    rescuable_exceptions = [ ArgumentError ]
+
+    if defined?(IPAddr::InvalidAddressError)
+      rescuable_exceptions << IPAddr::InvalidAddressError
+    end
+
+    unless args.length > 0 then
+      raise Puppet::ParseError, ("validate_ipv4_address(): wrong number of arguments (#{args.length}; must be > 0)")
+    end
+
+    args.each do |arg|
+      unless arg.is_a?(String)
+        raise Puppet::ParseError, "#{arg.inspect} is not a string."
+      end
+
+      begin
+        unless IPAddr.new(arg).ipv4?
+          raise Puppet::ParseError, "#{arg.inspect} is not a valid IPv4 address."
+        end
+      rescue *rescuable_exceptions
+        raise Puppet::ParseError, "#{arg.inspect} is not a valid IPv4 address."
+      end
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_ipv6_address.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,49 @@
+module Puppet::Parser::Functions
+
+  newfunction(:validate_ipv6_address, :doc => <<-ENDHEREDOC
+    Validate that all values passed are valid IPv6 addresses.
+    Fail compilation if any value fails this check.
+
+    The following values will pass:
+
+    $my_ip = "3ffe:505:2"
+    validate_ipv6_address(1)
+    validate_ipv6_address($my_ip)
+    validate_bool("fe80::baf6:b1ff:fe19:7507", $my_ip)
+
+    The following values will fail, causing compilation to abort:
+
+    $some_array = [ true, false, "garbage string", "1.2.3.4" ]
+    validate_ipv6_address($some_array)
+
+    ENDHEREDOC
+  ) do |args|
+
+    require "ipaddr"
+    rescuable_exceptions = [ ArgumentError ]
+
+    if defined?(IPAddr::InvalidAddressError)
+      rescuable_exceptions << IPAddr::InvalidAddressError
+    end
+
+    unless args.length > 0 then
+      raise Puppet::ParseError, ("validate_ipv6_address(): wrong number of arguments (#{args.length}; must be > 0)")
+    end
+
+    args.each do |arg|
+      unless arg.is_a?(String)
+        raise Puppet::ParseError, "#{arg.inspect} is not a string."
+      end
+
+      begin
+        unless IPAddr.new(arg).ipv6?
+          raise Puppet::ParseError, "#{arg.inspect} is not a valid IPv6 address."
+        end
+      rescue *rescuable_exceptions
+        raise Puppet::ParseError, "#{arg.inspect} is not a valid IPv6 address."
+      end
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_numeric.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,94 @@
+module Puppet::Parser::Functions
+
+  newfunction(:validate_numeric, :doc => <<-'ENDHEREDOC') do |args|
+    Validate that the first argument is a numeric value (or an array of numeric values). Abort catalog compilation if any of the checks fail.
+    
+    The second argument is optional and passes a maximum. (All elements of) the first argument has to be less or equal to this max.
+
+    The third argument is optional and passes a minimum.  (All elements of) the first argument has to be greater or equal to this min.
+    If, and only if, a minimum is given, the second argument may be an empty string or undef, which will be handled to just check
+    if (all elements of) the first argument are greater or equal to the given minimum.
+
+    It will fail if the first argument is not a numeric (Integer or Float) or array of numerics, and if arg 2 and arg 3 are not convertable to a numeric.
+
+    For passing and failing usage, see `validate_integer()`. It is all the same for validate_numeric, yet now floating point values are allowed, too.
+
+    ENDHEREDOC
+
+    # tell the user we need at least one, and optionally up to two other parameters
+    raise Puppet::ParseError, "validate_numeric(): Wrong number of arguments; must be 1, 2 or 3, got #{args.length}" unless args.length > 0 and args.length < 4
+
+    input, max, min = *args
+
+    # check maximum parameter
+    if args.length > 1
+      max = max.to_s
+      # allow max to be empty (or undefined) if we have a minimum set
+      if args.length > 2 and max == ''
+        max = nil
+      else
+        begin
+          max = Float(max)
+        rescue TypeError, ArgumentError
+          raise Puppet::ParseError, "validate_numeric(): Expected second argument to be unset or a Numeric, got #{max}:#{max.class}"
+        end
+      end
+    else
+      max = nil
+    end
+
+    # check minimum parameter
+    if args.length > 2
+      begin
+        min = Float(min.to_s)
+      rescue TypeError, ArgumentError
+        raise Puppet::ParseError, "validate_numeric(): Expected third argument to be unset or a Numeric, got #{min}:#{min.class}"
+      end
+    else
+      min = nil
+    end
+
+    # ensure that min < max
+    if min and max and min > max
+      raise Puppet::ParseError, "validate_numeric(): Expected second argument to be larger than third argument, got #{max} < #{min}"
+    end
+
+    # create lamba validator function
+    validator = lambda do |num|
+      # check input < max
+      if max and num > max
+        raise Puppet::ParseError, "validate_numeric(): Expected #{input.inspect} to be smaller or equal to #{max}, got #{input.inspect}."
+      end
+      # check input > min (this will only be checked if no exception has been raised before)
+      if min and num < min
+        raise Puppet::ParseError, "validate_numeric(): Expected #{input.inspect} to be greater or equal to #{min}, got #{input.inspect}."
+      end
+    end
+
+    # if this is an array, handle it.
+    case input
+    when Array
+      # check every element of the array
+      input.each_with_index do |arg, pos|
+        begin
+          raise TypeError if arg.is_a?(Hash)
+          arg = Float(arg.to_s)
+          validator.call(arg)
+        rescue TypeError, ArgumentError
+          raise Puppet::ParseError, "validate_numeric(): Expected element at array position #{pos} to be a Numeric, got #{arg.class}"
+        end
+      end
+    # for the sake of compatibility with ruby 1.8, we need extra handling of hashes
+    when Hash
+      raise Puppet::ParseError, "validate_integer(): Expected first argument to be a Numeric or Array, got #{input.class}"
+    # check the input. this will also fail any stuff other than pure, shiny integers
+    else
+      begin
+        input = Float(input.to_s)
+        validator.call(input)
+      rescue TypeError, ArgumentError
+        raise Puppet::ParseError, "validate_numeric(): Expected first argument to be a Numeric or Array, got #{input.class}"
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_re.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,40 @@
+module Puppet::Parser::Functions
+  newfunction(:validate_re, :doc => <<-'ENDHEREDOC') do |args|
+    Perform simple validation of a string against one or more regular
+    expressions. The first argument of this function should be a string to
+    test, and the second argument should be a stringified regular expression
+    (without the // delimiters) or an array of regular expressions.  If none
+    of the regular expressions match the string passed in, compilation will
+    abort with a parse error.
+
+    If a third argument is specified, this will be the error message raised and
+    seen by the user.
+
+    The following strings will validate against the regular expressions:
+
+        validate_re('one', '^one$')
+        validate_re('one', [ '^one', '^two' ])
+
+    The following strings will fail to validate, causing compilation to abort:
+
+        validate_re('one', [ '^two', '^three' ])
+
+    A helpful error message can be returned like this:
+
+        validate_re($::puppetversion, '^2.7', 'The $puppetversion fact value does not match 2.7')
+
+    ENDHEREDOC
+    if (args.length < 2) or (args.length > 3) then
+      raise Puppet::ParseError, ("validate_re(): wrong number of arguments (#{args.length}; must be 2 or 3)")
+    end
+
+    msg = args[2] || "validate_re(): #{args[0].inspect} does not match #{args[1].inspect}"
+
+    # We're using a flattened array here because we can't call String#any? in
+    # Ruby 1.9 like we can in Ruby 1.8
+    raise Puppet::ParseError, (msg) unless [args[1]].flatten.any? do |re_str|
+      args[0] =~ Regexp.compile(re_str)
+    end
+
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_slength.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,69 @@
+module Puppet::Parser::Functions
+
+  newfunction(:validate_slength, :doc => <<-'ENDHEREDOC') do |args|
+    Validate that the first argument is a string (or an array of strings), and
+    less/equal to than the length of the second argument. An optional third
+    parameter can be given the minimum length. It fails if the first
+    argument is not a string or array of strings, and if arg 2 and arg 3 are
+    not convertable to a number.
+
+    The following values will pass:
+
+      validate_slength("discombobulate",17)
+      validate_slength(["discombobulate","moo"],17)
+      validate_slength(["discombobulate","moo"],17,3)
+
+    The following valueis will not:
+
+      validate_slength("discombobulate",1)
+      validate_slength(["discombobulate","thermometer"],5)
+      validate_slength(["discombobulate","moo"],17,10)
+
+    ENDHEREDOC
+
+    raise Puppet::ParseError, "validate_slength(): Wrong number of arguments (#{args.length}; must be 2 or 3)" unless args.length == 2 or args.length == 3
+
+    input, max_length, min_length = *args
+
+    begin
+      max_length = Integer(max_length)
+      raise ArgumentError if max_length <= 0
+    rescue ArgumentError, TypeError
+      raise Puppet::ParseError, "validate_slength(): Expected second argument to be a positive Numeric, got #{max_length}:#{max_length.class}"
+    end
+
+    if min_length
+      begin
+        min_length = Integer(min_length)
+        raise ArgumentError if min_length < 0
+    rescue ArgumentError, TypeError
+        raise Puppet::ParseError, "validate_slength(): Expected third argument to be unset or a positive Numeric, got #{min_length}:#{min_length.class}"
+      end
+    else
+      min_length = 0
+    end
+
+    raise Puppet::ParseError, "validate_slength(): Expected second argument to be equal to or larger than third argument" unless max_length >= min_length
+
+    validator = lambda do |str|
+      unless str.length <= max_length and str.length >= min_length
+        raise Puppet::ParseError, "validate_slength(): Expected length of #{input.inspect} to be between #{min_length} and #{max_length}, was #{input.length}"
+      end
+    end
+
+    case input
+    when String
+      validator.call(input)
+    when Array
+      input.each_with_index do |arg, pos|
+        if arg.is_a? String
+          validator.call(arg)
+        else
+          raise Puppet::ParseError, "validate_slength(): Expected element at array position #{pos} to be a String, got #{arg.class}"
+        end
+      end
+    else
+      raise Puppet::ParseError, "validate_slength(): Expected first argument to be a String or Array, got #{input.class}"
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/validate_string.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,38 @@
+module Puppet::Parser::Functions
+
+  newfunction(:validate_string, :doc => <<-'ENDHEREDOC') do |args|
+    Validate that all passed values are string data structures. Abort catalog
+    compilation if any value fails this check.
+
+    The following values will pass:
+
+        $my_string = "one two"
+        validate_string($my_string, 'three')
+
+    The following values will fail, causing compilation to abort:
+
+        validate_string(true)
+        validate_string([ 'some', 'array' ])
+        
+    Note: validate_string(undef) will not fail in this version of the
+    functions API (incl. current and future parser). Instead, use:
+    
+        if $var == undef {
+          fail('...')
+        }
+    
+    ENDHEREDOC
+
+    unless args.length > 0 then
+      raise Puppet::ParseError, ("validate_string(): wrong number of arguments (#{args.length}; must be > 0)")
+    end
+
+    args.each do |arg|
+      unless arg.is_a?(String)
+        raise Puppet::ParseError, ("#{arg.inspect} is not a string.  It looks to be a #{arg.class}")
+      end
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/values.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+#
+# values.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:values, :type => :rvalue, :doc => <<-EOS
+When given a hash this function will return the values of that hash.
+
+*Examples:*
+
+    $hash = {
+      'a' => 1,
+      'b' => 2,
+      'c' => 3,
+    }
+    values($hash)
+
+This example would return:
+
+    [1,2,3]
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "values(): Wrong number of arguments " +
+      "given (#{arguments.size} for 1)") if arguments.size < 1
+
+    hash = arguments[0]
+
+    unless hash.is_a?(Hash)
+      raise(Puppet::ParseError, 'values(): Requires hash to work with')
+    end
+
+    result = hash.values
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/values_at.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,99 @@
+#
+# values_at.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:values_at, :type => :rvalue, :doc => <<-EOS
+Finds value inside an array based on location.
+
+The first argument is the array you want to analyze, and the second element can
+be a combination of:
+
+* A single numeric index
+* A range in the form of 'start-stop' (eg. 4-9)
+* An array combining the above
+
+*Examples*:
+
+    values_at(['a','b','c'], 2)
+
+Would return ['c'].
+
+    values_at(['a','b','c'], ["0-1"])
+
+Would return ['a','b'].
+
+    values_at(['a','b','c','d','e'], [0, "2-3"])
+
+Would return ['a','c','d'].
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "values_at(): Wrong number of " +
+      "arguments given (#{arguments.size} for 2)") if arguments.size < 2
+
+    array = arguments.shift
+
+    unless array.is_a?(Array)
+      raise(Puppet::ParseError, 'values_at(): Requires array to work with')
+    end
+
+    indices = [arguments.shift].flatten() # Get them all ... Pokemon ...
+
+    if not indices or indices.empty?
+      raise(Puppet::ParseError, 'values_at(): You must provide ' +
+        'at least one positive index to collect')
+    end
+
+    result       = []
+    indices_list = []
+
+    indices.each do |i|
+      i = i.to_s
+      if m = i.match(/^(\d+)(\.\.\.?|\-)(\d+)$/)
+        start = m[1].to_i
+        stop  = m[3].to_i
+
+        type = m[2]
+
+        if start > stop
+          raise(Puppet::ParseError, 'values_at(): Stop index in ' +
+            'given indices range is smaller than the start index')
+        elsif stop > array.size - 1 # First element is at index 0 is it not?
+          raise(Puppet::ParseError, 'values_at(): Stop index in ' +
+            'given indices range exceeds array size')
+        end
+
+        range = case type
+          when /^(\.\.|\-)$/ then (start .. stop)
+          when /^(\.\.\.)$/  then (start ... stop) # Exclusive of last element ...
+        end
+
+        range.each { |i| indices_list << i.to_i }
+      else
+        # Only positive numbers allowed in this case ...
+        if not i.match(/^\d+$/)
+          raise(Puppet::ParseError, 'values_at(): Unknown format ' +
+            'of given index')
+        end
+
+        # In Puppet numbers are often string-encoded ...
+        i = i.to_i
+
+        if i > array.size - 1 # Same story.  First element is at index 0 ...
+          raise(Puppet::ParseError, 'values_at(): Given index ' +
+            'exceeds array size')
+        end
+
+        indices_list << i
+      end
+    end
+
+    # We remove nil values as they make no sense in Puppet DSL ...
+    result = indices_list.collect { |i| array[i] }.compact
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/parser/functions/zip.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+#
+# zip.rb
+#
+
+module Puppet::Parser::Functions
+  newfunction(:zip, :type => :rvalue, :doc => <<-EOS
+Takes one element from first array and merges corresponding elements from second array. This generates a sequence of n-element arrays, where n is one more than the count of arguments.
+
+*Example:*
+
+    zip(['1','2','3'],['4','5','6'])
+
+Would result in:
+
+    ["1", "4"], ["2", "5"], ["3", "6"]
+    EOS
+  ) do |arguments|
+
+    # Technically we support three arguments but only first is mandatory ...
+    raise(Puppet::ParseError, "zip(): Wrong number of arguments " +
+      "given (#{arguments.size} for 2)") if arguments.size < 2
+
+    a = arguments[0]
+    b = arguments[1]
+
+    unless a.is_a?(Array) and b.is_a?(Array)
+      raise(Puppet::ParseError, 'zip(): Requires array to work with')
+    end
+
+    flatten = function_str2bool([arguments[2]]) if arguments[2]
+
+    result = a.zip(b)
+    result = flatten ? result.flatten : result
+
+    return result
+  end
+end
+
+# vim: set ts=2 sw=2 et :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/provider/file_line/ruby.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,128 @@
+Puppet::Type.type(:file_line).provide(:ruby) do
+  def exists?
+    if resource[:replace].to_s != 'true' and count_matches(match_regex) > 0
+      true
+    else
+      lines.find do |line|
+        line.chomp == resource[:line].chomp
+      end
+    end
+  end
+
+  def create
+    unless resource[:replace].to_s != 'true' and count_matches(match_regex) > 0
+      if resource[:match]
+        handle_create_with_match
+      elsif resource[:after]
+        handle_create_with_after
+      else
+        append_line
+      end
+    end
+  end
+
+  def destroy
+    if resource[:match_for_absence].to_s == 'true' and resource[:match]
+      handle_destroy_with_match
+    else
+      handle_destroy_line
+    end
+  end
+
+  private
+  def lines
+    # If this type is ever used with very large files, we should
+    #  write this in a different way, using a temp
+    #  file; for now assuming that this type is only used on
+    #  small-ish config files that can fit into memory without
+    #  too much trouble.
+    @lines ||= File.readlines(resource[:path])
+  end
+
+  def match_regex
+    resource[:match] ? Regexp.new(resource[:match]) : nil
+  end
+
+  def handle_create_with_match()
+    regex_after = resource[:after] ? Regexp.new(resource[:after]) : nil
+    match_count = count_matches(match_regex)
+
+    if match_count > 1 && resource[:multiple].to_s != 'true'
+     raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
+    end
+
+    File.open(resource[:path], 'w') do |fh|
+      lines.each do |l|
+        fh.puts(match_regex.match(l) ? resource[:line] : l)
+        if (match_count == 0 and regex_after)
+          if regex_after.match(l)
+            fh.puts(resource[:line])
+            match_count += 1 #Increment match_count to indicate that the new line has been inserted.
+          end
+        end
+      end
+
+      if (match_count == 0)
+        fh.puts(resource[:line])
+      end
+    end
+  end
+
+  def handle_create_with_after
+    regex = Regexp.new(resource[:after])
+    count = count_matches(regex)
+
+    if count > 1 && resource[:multiple].to_s != 'true'
+      raise Puppet::Error, "#{count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'.  One or no line must match the pattern."
+    end
+
+    File.open(resource[:path], 'w') do |fh|
+      lines.each do |l|
+        fh.puts(l)
+        if regex.match(l) then
+          fh.puts(resource[:line])
+        end
+      end
+    end
+
+    if (count == 0) # append the line to the end of the file
+      append_line
+    end
+  end
+
+  def count_matches(regex)
+    lines.select{|l| l.match(regex)}.size
+  end
+
+  def handle_destroy_with_match
+    match_count = count_matches(match_regex)
+    if match_count > 1 && resource[:multiple].to_s != 'true'
+     raise Puppet::Error, "More than one line in file '#{resource[:path]}' matches pattern '#{resource[:match]}'"
+    end
+
+    local_lines = lines
+    File.open(resource[:path],'w') do |fh|
+      fh.write(local_lines.reject{|l| match_regex.match(l) }.join(''))
+    end
+  end
+
+  def handle_destroy_line
+    local_lines = lines
+    File.open(resource[:path],'w') do |fh|
+      fh.write(local_lines.reject{|l| l.chomp == resource[:line] }.join(''))
+    end
+  end
+
+  ##
+  # append the line to the file.
+  #
+  # @api private
+  def append_line
+    File.open(resource[:path], 'w') do |fh|
+      lines.each do |l|
+        fh.puts(l)
+      end
+      fh.puts resource[:line]
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/type/anchor.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+Puppet::Type.newtype(:anchor) do
+  desc <<-'ENDOFDESC'
+  A simple resource type intended to be used as an anchor in a composite class.
+
+  In Puppet 2.6, when a class declares another class, the resources in the
+  interior class are not contained by the exterior class. This interacts badly
+  with the pattern of composing complex modules from smaller classes, as it
+  makes it impossible for end users to specify order relationships between the
+  exterior class and other modules.
+
+  The anchor type lets you work around this. By sandwiching any interior
+  classes between two no-op resources that _are_ contained by the exterior
+  class, you can ensure that all resources in the module are contained.
+
+      class ntp {
+        # These classes will have the correct order relationship with each
+        # other. However, without anchors, they won't have any order
+        # relationship to Class['ntp'].
+        class { 'ntp::package': }
+        -> class { 'ntp::config': }
+        -> class { 'ntp::service': }
+
+        # These two resources "anchor" the composed classes within the ntp
+        # class.
+        anchor { 'ntp::begin': } -> Class['ntp::package']
+        Class['ntp::service']    -> anchor { 'ntp::end': }
+      }
+
+  This allows the end user of the ntp module to establish require and before
+  relationships with Class['ntp']:
+
+      class { 'ntp': } -> class { 'mcollective': }
+      class { 'mcollective': } -> class { 'ntp': }
+
+  ENDOFDESC
+
+  newparam :name do
+    desc "The name of the anchor resource."
+  end
+
+  def refresh
+    # We don't do anything with them, but we need this to
+    #   show that we are "refresh aware" and not break the
+    #   chain of propagation.
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/lib/puppet/type/file_line.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,119 @@
+Puppet::Type.newtype(:file_line) do
+
+  desc <<-EOT
+    Ensures that a given line is contained within a file.  The implementation
+    matches the full line, including whitespace at the beginning and end.  If
+    the line is not contained in the given file, Puppet will append the line to
+    the end of the file to ensure the desired state.  Multiple resources may 
+    be declared to manage multiple lines in the same file.
+
+    Example:
+
+        file_line { 'sudo_rule':
+          path => '/etc/sudoers',
+          line => '%sudo ALL=(ALL) ALL',
+        }
+
+        file_line { 'sudo_rule_nopw':
+          path => '/etc/sudoers',
+          line => '%sudonopw ALL=(ALL) NOPASSWD: ALL',
+        }
+
+    In this example, Puppet will ensure both of the specified lines are
+    contained in the file /etc/sudoers.
+
+    Match Example:
+
+        file_line { 'bashrc_proxy':
+          ensure => present,
+          path   => '/etc/bashrc',
+          line   => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128',
+          match  => '^export\ HTTP_PROXY\=',
+        }
+
+    In this code example match will look for a line beginning with export 
+    followed by HTTP_PROXY and replace it with the value in line.
+
+    Match Example With `ensure => absent`:
+
+        file_line { 'bashrc_proxy':
+          ensure            => absent,
+          path              => '/etc/bashrc',
+          line              => 'export HTTP_PROXY=http://squid.puppetlabs.vm:3128',
+          match             => '^export\ HTTP_PROXY\=',
+          match_for_absence => true,
+        }
+
+    In this code example match will look for a line beginning with export
+    followed by HTTP_PROXY and delete it.  If multiple lines match, an
+    error will be raised unless the `multiple => true` parameter is set.
+
+    **Autorequires:** If Puppet is managing the file that will contain the line
+    being managed, the file_line resource will autorequire that file.
+
+  EOT
+
+  ensurable do
+    defaultvalues
+    defaultto :present
+  end
+
+  newparam(:name, :namevar => true) do
+    desc 'An arbitrary name used as the identity of the resource.'
+  end
+
+  newparam(:match) do
+    desc 'An optional ruby regular expression to run against existing lines in the file.' + 
+         ' If a match is found, we replace that line rather than adding a new line.' +
+         ' A regex comparisson is performed against the line value and if it does not' +
+         ' match an exception will be raised. '
+  end
+
+  newparam(:match_for_absence) do
+    desc 'An optional value to determine if match should be applied when ensure => absent.' +
+         ' If set to true and match is set, the line that matches match will be deleted.' +
+         ' If set to false (the default), match is ignored when ensure => absent.'
+    newvalues(true, false)
+    defaultto false
+  end
+
+  newparam(:multiple) do
+    desc 'An optional value to determine if match can change multiple lines.' +
+         ' If set to false, an exception will be raised if more than one line matches'
+    newvalues(true, false)
+  end
+
+  newparam(:after) do
+    desc 'An optional value used to specify the line after which we will add any new lines. (Existing lines are added in place)'
+  end
+
+  newparam(:line) do
+    desc 'The line to be appended to the file or used to replace matches found by the match attribute.'
+  end
+
+  newparam(:path) do
+    desc 'The file Puppet will ensure contains the line specified by the line parameter.'
+    validate do |value|
+      unless (Puppet.features.posix? and value =~ /^\//) or (Puppet.features.microsoft_windows? and (value =~ /^.:\// or value =~ /^\/\/[^\/]+\/[^\/]+/))
+        raise(Puppet::Error, "File paths must be fully qualified, not '#{value}'")
+      end
+    end
+  end
+
+  newparam(:replace) do
+    desc 'If true, replace line that matches. If false, do not write line if a match is found'
+    newvalues(true, false)
+    defaultto true
+  end
+
+  # Autorequire the file resource if it's being managed
+  autorequire(:file) do
+    self[:path]
+  end
+
+  validate do
+    unless self[:line] and self[:path]
+      raise(Puppet::Error, "Both line and path are required attributes")
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+# Class: stdlib
+#
+# This module manages stdlib. Most of stdlib's features are automatically
+# loaded by Puppet, but this class should be declared in order to use the
+# standardized run stages.
+#
+# Parameters: none
+#
+# Actions:
+#
+#   Declares all other classes in the stdlib module. Currently, this consists
+#   of stdlib::stages.
+#
+# Requires: nothing
+#
+class stdlib {
+  include ::stdlib::stages
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/manifests/stages.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,43 @@
+# Class: stdlib::stages
+#
+# This class manages a standard set of run stages for Puppet. It is managed by
+# the stdlib class, and should not be declared independently.
+#
+# The high level stages are (in order):
+#
+#  * setup
+#  * main
+#  * runtime
+#  * setup_infra
+#  * deploy_infra
+#  * setup_app
+#  * deploy_app
+#  * deploy
+#
+# Parameters: none
+#
+# Actions:
+#
+#   Declares various run-stages for deploying infrastructure,
+#   language runtimes, and application layers.
+#
+# Requires: nothing
+#
+# Sample Usage:
+#
+#  node default {
+#    include stdlib
+#    class { java: stage => 'runtime' }
+#  }
+#
+class stdlib::stages {
+
+  stage { 'setup':  before => Stage['main'] }
+  stage { 'runtime': require => Stage['main'] }
+  -> stage { 'setup_infra': }
+  -> stage { 'deploy_infra': }
+  -> stage { 'setup_app': }
+  -> stage { 'deploy_app': }
+  -> stage { 'deploy': }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/metadata.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,114 @@
+{
+  "name": "puppetlabs-stdlib",
+  "version": "4.9.1",
+  "author": "puppetlabs",
+  "summary": "Standard library of resources for Puppet modules.",
+  "license": "Apache-2.0",
+  "source": "https://github.com/puppetlabs/puppetlabs-stdlib",
+  "project_page": "https://github.com/puppetlabs/puppetlabs-stdlib",
+  "issues_url": "https://tickets.puppetlabs.com/browse/MODULES",
+  "operatingsystem_support": [
+    {
+      "operatingsystem": "RedHat",
+      "operatingsystemrelease": [
+        "4",
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "CentOS",
+      "operatingsystemrelease": [
+        "4",
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "OracleLinux",
+      "operatingsystemrelease": [
+        "4",
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Scientific",
+      "operatingsystemrelease": [
+        "4",
+        "5",
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "SLES",
+      "operatingsystemrelease": [
+        "10 SP4",
+        "11 SP1",
+        "12"
+      ]
+    },
+    {
+      "operatingsystem": "Debian",
+      "operatingsystemrelease": [
+        "6",
+        "7"
+      ]
+    },
+    {
+      "operatingsystem": "Ubuntu",
+      "operatingsystemrelease": [
+        "10.04",
+        "12.04",
+        "14.04"
+      ]
+    },
+    {
+      "operatingsystem": "Solaris",
+      "operatingsystemrelease": [
+        "10",
+        "11",
+        "12"
+      ]
+    },
+    {
+      "operatingsystem": "Windows",
+      "operatingsystemrelease": [
+        "Server 2003",
+        "Server 2003 R2",
+        "Server 2008",
+        "Server 2008 R2",
+        "Server 2012",
+        "Server 2012 R2",
+        "7",
+        "8"
+      ]
+    },
+    {
+      "operatingsystem": "AIX",
+      "operatingsystemrelease": [
+        "5.3",
+        "6.1",
+        "7.1"
+      ]
+    }
+  ],
+  "requirements": [
+    {
+      "name": "pe",
+      "version_requirement": ">= 3.0.0 < 2015.4.0"
+    },
+    {
+      "name": "puppet",
+      "version_requirement": ">=2.7.20 <5.0.0"
+    }
+  ],
+  "description": "Standard Library for Puppet Modules",
+  "dependencies": [
+  
+  ]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/abs_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,30 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'abs function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should accept a string' do
+      pp = <<-EOS
+      $input  = '-34.56'
+      $output = abs($input)
+      notify { "$output": }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: 34.56/)
+      end
+    end
+
+    it 'should accept a float' do
+      pp = <<-EOS
+      $input  = -34.56
+      $output = abs($input)
+      notify { "$output": }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: 34.56/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/anchor_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+require 'spec_helper_acceptance'
+
+describe 'anchor type', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should effect proper chaining of resources' do
+      pp = <<-EOS
+      class anchored {
+        anchor { 'anchored::begin': }
+        ~> anchor { 'anchored::end': }
+      }
+
+      class anchorrefresh {
+        notify { 'first': }
+        ~> class { 'anchored': }
+        ~> anchor { 'final': }
+      }
+
+      include anchorrefresh
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Anchor\[final\]: Triggered 'refresh'/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/any2array_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,49 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'any2array function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should create an empty array' do
+      pp = <<-EOS
+      $input = ''
+      $output = any2array($input)
+      validate_array($output)
+      notify { "Output: ${output}": }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: Output: /)
+      end
+    end
+
+    it 'should leave arrays modified' do
+      pp = <<-EOS
+      $input = ['test', 'array']
+      $output = any2array($input)
+      validate_array($output)
+      notify { "Output: ${output}": }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: Output: (\[|)test(,\s|)array(\]|)/)
+      end
+    end
+
+    it 'should turn a hash into an array' do
+      pp = <<-EOS
+      $input = {'test' => 'array'}
+      $output = any2array($input)
+
+      validate_array($output)
+      # Check each element of the array is a plain string.
+      validate_string($output[0])
+      validate_string($output[1])
+      notify { "Output: ${output}": }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: Output: (\[|)test(,\s|)array(\]|)/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/base64_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'base64 function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should encode then decode a string' do
+      pp = <<-EOS
+      $encodestring = base64('encode', 'thestring')
+      $decodestring = base64('decode', $encodestring)
+      notify { $decodestring: }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/thestring/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/bool2num_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'bool2num function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    ['false', 'f', '0', 'n', 'no'].each do |bool|
+      it "should convert a given boolean, #{bool}, to 0" do
+        pp = <<-EOS
+        $input = "#{bool}"
+        $output = bool2num($input)
+        notify { "$output": }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/Notice: 0/)
+        end
+      end
+    end
+
+    ['true', 't', '1', 'y', 'yes'].each do |bool|
+      it "should convert a given boolean, #{bool}, to 1" do
+        pp = <<-EOS
+        $input = "#{bool}"
+        $output = bool2num($input)
+        notify { "$output": }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/Notice: 1/)
+        end
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/build_csv.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,83 @@
+#!/usr/bin/env ruby
+# vim: set sw=2 sts=2 et tw=80 :
+require 'rspec'
+
+#XXX Super ugly hack to keep from starting beaker nodes
+module Kernel
+  # make an alias of the original require
+  alias_method :original_require, :require
+  # rewrite require
+  def require name
+    original_require name if name != 'spec_helper_acceptance'
+  end
+end
+UNSUPPORTED_PLATFORMS = []
+def fact(*args) [] end
+#XXX End hax
+
+# Get a list of functions for test coverage
+function_list = Dir[File.join(File.dirname(__FILE__),"..","..","lib","puppet","parser","functions","*.rb")].collect do |function_rb|
+  File.basename(function_rb,".rb")
+end
+
+## Configure rspec to parse tests
+options = RSpec::Core::ConfigurationOptions.new(['spec/acceptance'])
+configuration = RSpec::configuration
+world = RSpec::world
+options.parse_options
+options.configure(configuration)
+configuration.load_spec_files
+
+## Collect up tests and example groups into a hash
+def get_tests(children)
+  children.inject({}) do |memo,c|
+    memo[c.description] = Hash.new
+    memo[c.description]["groups"] = get_tests(c.children) unless c.children.empty?
+    memo[c.description]["tests"] = c.examples.collect { |e|
+      e.description unless e.pending?
+    }.compact unless c.examples.empty?
+    memo[c.description]["pending_tests"] = c.examples.collect { |e|
+      e.description if e.pending?
+    }.compact unless c.examples.empty?
+    memo
+  end
+end
+
+def count_test_types_in(type,group)
+  return 0 if group.nil?
+  group.inject(0) do |m,(k,v)|
+    m += v.length if k == type
+    m += count_tests_in(v) if v.is_a?(Hash)
+    m
+  end
+end
+def count_tests_in(group)
+  count_test_types_in('tests',group)
+end
+def count_pending_tests_in(group)
+  count_test_types_in('pending_tests',group)
+end
+
+# Convert tests hash to csv format
+def to_csv(function_list,tests)
+  function_list.collect do |function_name|
+    if v = tests["#{function_name} function"]
+      positive_tests = count_tests_in(v["groups"]["success"])
+      negative_tests = count_tests_in(v["groups"]["failure"])
+      pending_tests  =
+        count_pending_tests_in(v["groups"]["failure"]) +
+        count_pending_tests_in(v["groups"]["failure"])
+    else
+      positive_tests = 0
+      negative_tests = 0
+      pending_tests  = 0
+    end
+    sprintf("%-25s, %-9d, %-9d, %-9d", function_name,positive_tests,negative_tests,pending_tests)
+  end.compact
+end
+
+tests = get_tests(world.example_groups)
+csv = to_csv(function_list,tests)
+percentage_tested = "#{tests.count*100/function_list.count}%"
+printf("%-25s,  %-9s, %-9s, %-9s\n","#{percentage_tested} have tests.","Positive","Negative","Pending")
+puts csv
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/capitalize_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'capitalize function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should capitalize the first letter of a string' do
+      pp = <<-EOS
+      $input = 'this is a string'
+      $output = capitalize($input)
+      notify { $output: }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: This is a string/)
+      end
+    end
+
+    it 'should capitalize the first letter of an array of strings' do
+      pp = <<-EOS
+      $input = ['this', 'is', 'a', 'string']
+      $output = capitalize($input)
+      notify { $output: }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: This/)
+        expect(r.stdout).to match(/Notice: Is/)
+        expect(r.stdout).to match(/Notice: A/)
+        expect(r.stdout).to match(/Notice: String/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/ceiling_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'ceiling function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'ceilings floats' do
+      pp = <<-EOS
+      $a = 12.8
+      $b = 13
+      $o = ceiling($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'ceilings integers' do
+      pp = <<-EOS
+      $a = 7
+      $b = 7
+      $o = ceiling($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-numbers'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/chomp_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'chomp function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should eat the newline' do
+      pp = <<-EOS
+      $input = "test\n"
+      if size($input) != 5 {
+        fail("Size of ${input} is not 5.")
+      }
+      $output = chomp($input)
+      if size($output) != 4 {
+        fail("Size of ${input} is not 4.")
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/chop_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,45 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'chop function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should eat the last character' do
+      pp = <<-EOS
+      $input = "test"
+      if size($input) != 4 {
+        fail("Size of ${input} is not 4.")
+      }
+      $output = chop($input)
+      if size($output) != 3 {
+        fail("Size of ${input} is not 3.")
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should eat the last two characters of \r\n' do
+      pp = <<-'EOS'
+      $input = "test\r\n"
+      if size($input) != 6 {
+        fail("Size of ${input} is not 6.")
+      }
+      $output = chop($input)
+      if size($output) != 4 {
+        fail("Size of ${input} is not 4.")
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+
+    it 'should not fail on empty strings' do
+      pp = <<-EOS
+      $input = ""
+      $output = chop($input)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/concat_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,40 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'concat function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should concat one array to another' do
+      pp = <<-EOS
+      $output = concat(['1','2','3'],['4','5','6'])
+      validate_array($output)
+      if size($output) != 6 {
+        fail("${output} should have 6 elements.")
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'should concat arrays and primitives to array' do
+      pp = <<-EOS
+      $output = concat(['1','2','3'],'4','5','6',['7','8','9'])
+      validate_array($output)
+      if size($output) != 9 {
+        fail("${output} should have 9 elements.")
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'should concat multiple arrays to one' do
+      pp = <<-EOS
+      $output = concat(['1','2','3'],['4','5','6'],['7','8','9'])
+      validate_array($output)
+      if size($output) != 9 {
+        fail("${output} should have 9 elements.")
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/count_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,30 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'count function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should count elements in an array' do
+      pp = <<-EOS
+      $input = [1,2,3,4]
+      $output = count($input)
+      notify { "$output": }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: 4/)
+      end
+    end
+
+    it 'should count elements in an array that match a second argument' do
+      pp = <<-EOS
+      $input = [1,1,1,2]
+      $output = count($input, 1)
+      notify { "$output": }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: 3/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/deep_merge_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'deep_merge function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should deep merge two hashes' do
+      pp = <<-EOS
+      $hash1 = {'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }
+      $hash2 = {'two' => 'dos', 'three' => { 'five' => 5 } }
+      $merged_hash = deep_merge($hash1, $hash2)
+
+      if $merged_hash != { 'one' => 1, 'two' => 'dos', 'three' => { 'four' => 4, 'five' => 5 } } {
+        fail("Hash was incorrectly merged.")
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/defined_with_params_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'defined_with_params function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should successfully notify' do
+      pp = <<-EOS
+      user { 'dan':
+        ensure => present,
+      }
+
+      if defined_with_params(User[dan], {'ensure' => 'present' }) {
+        notify { 'User defined with ensure=>present': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: User defined with ensure=>present/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/delete_at_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'delete_at function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should delete elements of the array' do
+      pp = <<-EOS
+      $output = delete_at(['a','b','c','b'], 1)
+      if $output == ['a','c','b'] {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/delete_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'delete function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should delete elements of the array' do
+      pp = <<-EOS
+      $output = delete(['a','b','c','b'], 'b')
+      if $output == ['a','c'] {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/delete_undef_values_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'delete_undef_values function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should delete elements of the array' do
+      pp = <<-EOS
+      $output = delete_undef_values({a=>'A', b=>'', c=>undef, d => false})
+      if $output == { a => 'A', b => '', d => false } {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/delete_values_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'delete_values function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should delete elements of the hash' do
+      pp = <<-EOS
+      $a = { 'a' => 'A', 'b' => 'B', 'B' => 'C', 'd' => 'B' }
+      $b = { 'a' => 'A', 'B' => 'C' }
+      $o = delete_values($a, 'B')
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles non-hash arguments'
+    it 'handles improper argument counts'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/difference_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'difference function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'returns non-duplicates in the first array' do
+      pp = <<-EOS
+      $a = ['a','b','c']
+      $b = ['b','c','d']
+      $c = ['a']
+      $o = difference($a, $b)
+      if $o == $c {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles non-array arguments'
+    it 'handles improper argument counts'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/dirname_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'dirname function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    context 'absolute path' do
+      it 'returns the dirname' do
+        pp = <<-EOS
+        $a = '/path/to/a/file.txt'
+        $b = '/path/to/a'
+        $o = dirname($a)
+        if $o == $b {
+          notify { 'output correct': }
+        }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/Notice: output correct/)
+        end
+      end
+    end
+    context 'relative path' do
+      it 'returns the dirname' do
+        pp = <<-EOS
+        $a = 'path/to/a/file.txt'
+        $b = 'path/to/a'
+        $o = dirname($a)
+        if $o == $b {
+          notify { 'output correct': }
+        }
+        EOS
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/Notice: output correct/)
+        end
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/downcase_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'downcase function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'returns the downcase' do
+      pp = <<-EOS
+      $a = 'AOEU'
+      $b = 'aoeu'
+      $o = downcase($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'doesn\'t affect lowercase words' do
+      pp = <<-EOS
+      $a = 'aoeu aoeu'
+      $b = 'aoeu aoeu'
+      $o = downcase($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/empty_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'empty function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'recognizes empty strings' do
+      pp = <<-EOS
+      $a = ''
+      $b = true
+      $o = empty($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'recognizes non-empty strings' do
+      pp = <<-EOS
+      $a = 'aoeu'
+      $b = false
+      $o = empty($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/ensure_resource_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'ensure_resource function', :unless => fact('osfamily') =~ /(windows|Suse)/i do
+  describe 'success' do
+    it 'ensure_resource a package' do
+      apply_manifest('package { "rake": ensure => absent, provider => "gem", }')
+      pp = <<-EOS
+      $a = "rake"
+      ensure_resource('package', $a, {'provider' => 'gem'})
+      EOS
+
+      apply_manifest(pp, :expect_changes => true)
+    end
+    it 'ensures a resource already declared'
+    it 'takes defaults arguments'
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/flatten_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'flatten function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'flattens arrays' do
+      pp = <<-EOS
+      $a = ["a","b",["c",["d","e"],"f","g"]]
+      $b = ["a","b","c","d","e","f","g"]
+      $o = flatten($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'does not affect flat arrays' do
+      pp = <<-EOS
+      $a = ["a","b","c","d","e","f","g"]
+      $b = ["a","b","c","d","e","f","g"]
+      $o = flatten($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/floor_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'floor function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'floors floats' do
+      pp = <<-EOS
+      $a = 12.8
+      $b = 12
+      $o = floor($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'floors integers' do
+      pp = <<-EOS
+      $a = 7
+      $b = 7
+      $o = floor($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-numbers'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/fqdn_rand_string_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,66 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'fqdn_rand_string function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    include_context "with faked facts"
+    context "when the FQDN is 'fakehost.localdomain'" do
+      before :each do
+        fake_fact("fqdn", "fakehost.localdomain")
+      end
+
+      it 'generates random alphanumeric strings' do
+        pp = <<-eos
+        $l = 10
+        $o = fqdn_rand_string($l)
+        notice(inline_template('fqdn_rand_string is <%= @o.inspect %>'))
+        eos
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/fqdn_rand_string is "7oDp0KOr1b"/)
+        end
+      end
+      it 'generates random alphanumeric strings with custom charsets' do
+        pp = <<-eos
+        $l = 10
+        $c = '0123456789'
+        $o = fqdn_rand_string($l, $c)
+        notice(inline_template('fqdn_rand_string is <%= @o.inspect %>'))
+        eos
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/fqdn_rand_string is "7203048515"/)
+        end
+      end
+      it 'generates random alphanumeric strings with custom seeds' do
+        pp = <<-eos
+        $l = 10
+        $s = 'seed'
+        $o = fqdn_rand_string($l, undef, $s)
+        notice(inline_template('fqdn_rand_string is <%= @o.inspect %>'))
+        eos
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/fqdn_rand_string is "3HS4mbuI3E"/)
+        end
+      end
+      it 'generates random alphanumeric strings with custom charsets and seeds' do
+        pp = <<-eos
+        $l = 10
+        $c = '0123456789'
+        $s = 'seed'
+        $o = fqdn_rand_string($l, $c, $s)
+        notice(inline_template('fqdn_rand_string is <%= @o.inspect %>'))
+        eos
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/fqdn_rand_string is "3104058232"/)
+        end
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-numbers for length argument'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/fqdn_rotate_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,64 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'fqdn_rotate function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    include_context "with faked facts"
+    context "when the FQDN is 'fakehost.localdomain'" do
+      before :each do
+        fake_fact("fqdn", "fakehost.localdomain")
+      end
+
+      it 'rotates arrays' do
+        pp = <<-EOS
+        $a = ['a','b','c','d']
+        $o = fqdn_rotate($a)
+        notice(inline_template('fqdn_rotate is <%= @o.inspect %>'))
+        EOS
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/fqdn_rotate is \["d", "a", "b", "c"\]/)
+        end
+      end
+      it 'rotates arrays with custom seeds' do
+        pp = <<-EOS
+        $a = ['a','b','c','d']
+        $s = 'seed'
+        $o = fqdn_rotate($a, $s)
+        notice(inline_template('fqdn_rotate is <%= @o.inspect %>'))
+        EOS
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/fqdn_rotate is \["c", "d", "a", "b"\]/)
+        end
+      end
+      it 'rotates strings' do
+        pp = <<-EOS
+        $a = 'abcd'
+        $o = fqdn_rotate($a)
+        notice(inline_template('fqdn_rotate is <%= @o.inspect %>'))
+        EOS
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/fqdn_rotate is "dabc"/)
+        end
+      end
+      it 'rotates strings with custom seeds' do
+        pp = <<-EOS
+        $a = 'abcd'
+        $s = 'seed'
+        $o = fqdn_rotate($a, $s)
+        notice(inline_template('fqdn_rotate is <%= @o.inspect %>'))
+        EOS
+
+        apply_manifest(pp, :catch_failures => true) do |r|
+          expect(r.stdout).to match(/fqdn_rotate is "cdab"/)
+        end
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles invalid arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/get_module_path_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'get_module_path function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'get_module_paths dne' do
+      pp = <<-EOS
+      $a = $::is_pe ? {
+        'true'  => '/etc/puppetlabs/puppet/modules/dne',
+        'false' => '/etc/puppet/modules/dne',
+      }
+      $o = get_module_path('dne')
+      if $o == $a {
+        notify { 'output correct': }
+      } else {
+        notify { "failed; module path is '$o'": }
+      }
+      EOS
+
+      apply_manifest(pp, :expect_failures => true)
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-numbers'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/getparam_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'getparam function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'getparam a notify' do
+      pp = <<-EOS
+      notify { 'rspec':
+        message => 'custom rspec message',
+      }
+      $o = getparam(Notify['rspec'], 'message')
+      notice(inline_template('getparam is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/getparam is "custom rspec message"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/getvar_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'getvar function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'getvars from classes' do
+      pp = <<-EOS
+      class a::data { $foo = 'aoeu' }
+      include a::data
+      $b = 'aoeu'
+      $o = getvar("a::data::foo")
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-numbers'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/grep_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'grep function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'greps arrays' do
+      pp = <<-EOS
+      $a = ['aaabbb','bbbccc','dddeee']
+      $b = 'bbb'
+      $c = ['aaabbb','bbbccc']
+      $o = grep($a,$b)
+      if $o == $c {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/has_interface_with_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,54 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'has_interface_with function', :unless => ((UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem'))) or (fact('osfamily') == 'windows') or (fact('osfamily') == 'AIX')) do
+  describe 'success' do
+    it 'has_interface_with existing ipaddress' do
+      pp = <<-EOS
+      $a = $::ipaddress
+      $o = has_interface_with('ipaddress', $a)
+      notice(inline_template('has_interface_with is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/has_interface_with is true/)
+      end
+    end
+    it 'has_interface_with absent ipaddress' do
+      pp = <<-EOS
+      $a = '128.0.0.1'
+      $o = has_interface_with('ipaddress', $a)
+      notice(inline_template('has_interface_with is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/has_interface_with is false/)
+      end
+    end
+    it 'has_interface_with existing interface' do
+      pp = <<-EOS
+      if $osfamily == 'Solaris' or $osfamily == 'Darwin' {
+        $a = 'lo0'
+      }elsif $osfamily == 'windows' {
+        $a = $::kernelmajversion ? {
+          /6\.(2|3|4)/ => 'Ethernet0',
+          /6\.(0|1)/ => 'Local_Area_Connection',
+          /5\.(1|2)/  => undef, #Broken current in facter
+        }
+      }else {
+        $a = 'lo'
+      }
+      $o = has_interface_with($a)
+      notice(inline_template('has_interface_with is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/has_interface_with is true/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/has_ip_address_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'has_ip_address function', :unless => ((UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem'))) or (fact('osfamily') == 'windows') or (fact('osfamily') == 'AIX')) do
+  describe 'success' do
+    it 'has_ip_address existing ipaddress' do
+      pp = <<-EOS
+      $a = '127.0.0.1'
+      $o = has_ip_address($a)
+      notice(inline_template('has_ip_address is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/has_ip_address is true/)
+      end
+    end
+    it 'has_ip_address absent ipaddress' do
+      pp = <<-EOS
+      $a = '128.0.0.1'
+      $o = has_ip_address($a)
+      notice(inline_template('has_ip_address is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/has_ip_address is false/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/has_ip_network_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'has_ip_network function', :unless => ((UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem'))) or (fact('osfamily') == 'windows') or (fact('osfamily') == 'AIX')) do
+  describe 'success' do
+    it 'has_ip_network existing ipaddress' do
+      pp = <<-EOS
+      $a = '127.0.0.0'
+      $o = has_ip_network($a)
+      notice(inline_template('has_ip_network is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/has_ip_network is true/)
+      end
+    end
+    it 'has_ip_network absent ipaddress' do
+      pp = <<-EOS
+      $a = '128.0.0.0'
+      $o = has_ip_network($a)
+      notice(inline_template('has_ip_network is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/has_ip_network is false/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/has_key_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,41 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'has_key function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'has_keys in hashes' do
+      pp = <<-EOS
+      $a = { 'aaa' => 'bbb','bbb' => 'ccc','ddd' => 'eee' }
+      $b = 'bbb'
+      $c = true
+      $o = has_key($a,$b)
+      if $o == $c {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'has_keys not in hashes' do
+      pp = <<-EOS
+      $a = { 'aaa' => 'bbb','bbb' => 'ccc','ddd' => 'eee' }
+      $b = 'ccc'
+      $c = false
+      $o = has_key($a,$b)
+      if $o == $c {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-hashes'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/hash_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'hash function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'hashs arrays' do
+      pp = <<-EOS
+      $a = ['aaa','bbb','bbb','ccc','ddd','eee']
+      $b = { 'aaa' => 'bbb', 'bbb' => 'ccc', 'ddd' => 'eee' }
+      $o = hash($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'handles odd-length arrays'
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/intersection_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'intersection function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'intersections arrays' do
+      pp = <<-EOS
+      $a = ['aaa','bbb','ccc']
+      $b = ['bbb','ccc','ddd','eee']
+      $c = ['bbb','ccc']
+      $o = intersection($a,$b)
+      if $o == $c {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'intersections empty arrays'
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/is_array_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,67 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_array function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'is_arrays arrays' do
+      pp = <<-EOS
+      $a = ['aaa','bbb','ccc']
+      $b = true
+      $o = is_array($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_arrays empty arrays' do
+      pp = <<-EOS
+      $a = []
+      $b = true
+      $o = is_array($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_arrays strings' do
+      pp = <<-EOS
+      $a = "aoeu"
+      $b = false
+      $o = is_array($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_arrays hashes' do
+      pp = <<-EOS
+      $a = {'aaa'=>'bbb'}
+      $b = false
+      $o = is_array($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/is_bool_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,81 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_bool function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'is_bools arrays' do
+      pp = <<-EOS
+      $a = ['aaa','bbb','ccc']
+      $b = false
+      $o = is_bool($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_bools true' do
+      pp = <<-EOS
+      $a = true
+      $b = true
+      $o = is_bool($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_bools false' do
+      pp = <<-EOS
+      $a = false
+      $b = true
+      $o = is_bool($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_bools strings' do
+      pp = <<-EOS
+      $a = "true"
+      $b = false
+      $o = is_bool($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_bools hashes' do
+      pp = <<-EOS
+      $a = {'aaa'=>'bbb'}
+      $b = false
+      $o = is_bool($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/is_domain_name_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,83 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_domain_name function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'is_domain_names arrays' do
+      pp = <<-EOS
+      $a = ['aaa.com','bbb','ccc']
+      $o = is_domain_name($a)
+      notice(inline_template('is_domain_name is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_domain_name is false/)
+      end
+    end
+    it 'is_domain_names true' do
+      pp = <<-EOS
+      $a = true
+      $o = is_domain_name($a)
+      notice(inline_template('is_domain_name is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_domain_name is false/)
+      end
+    end
+    it 'is_domain_names false' do
+      pp = <<-EOS
+      $a = false
+      $o = is_domain_name($a)
+      notice(inline_template('is_domain_name is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_domain_name is false/)
+      end
+    end
+    it 'is_domain_names strings with hyphens' do
+      pp = <<-EOS
+      $a = "3foo-bar.2bar-fuzz.com"
+      $b = true
+      $o = is_domain_name($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_domain_names strings beginning with hyphens' do
+      pp = <<-EOS
+      $a = "-bar.2bar-fuzz.com"
+      $b = false
+      $o = is_domain_name($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_domain_names hashes' do
+      pp = <<-EOS
+      $a = {'aaa'=>'www.com'}
+      $o = is_domain_name($a)
+      notice(inline_template('is_domain_name is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_domain_name is false/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/is_float_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,86 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_float function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'is_floats arrays' do
+      pp = <<-EOS
+      $a = ['aaa.com','bbb','ccc']
+      $o = is_float($a)
+      notice(inline_template('is_float is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_float is false/)
+      end
+    end
+    it 'is_floats true' do
+      pp = <<-EOS
+      $a = true
+      $o = is_float($a)
+      notice(inline_template('is_float is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_float is false/)
+      end
+    end
+    it 'is_floats strings' do
+      pp = <<-EOS
+      $a = "3.5"
+      $b = true
+      $o = is_float($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_floats floats' do
+      pp = <<-EOS
+      $a = 3.5
+      $b = true
+      $o = is_float($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_floats integers' do
+      pp = <<-EOS
+      $a = 3
+      $b = false
+      $o = is_float($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_floats hashes' do
+      pp = <<-EOS
+      $a = {'aaa'=>'www.com'}
+      $o = is_float($a)
+      notice(inline_template('is_float is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_float is false/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/is_function_available_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,58 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_function_available function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'is_function_availables arrays' do
+      pp = <<-EOS
+      $a = ['fail','include','require']
+      $o = is_function_available($a)
+      notice(inline_template('is_function_available is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_function_available is false/)
+      end
+    end
+    it 'is_function_availables true' do
+      pp = <<-EOS
+      $a = true
+      $o = is_function_available($a)
+      notice(inline_template('is_function_available is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_function_available is false/)
+      end
+    end
+    it 'is_function_availables strings' do
+      pp = <<-EOS
+      $a = "fail"
+      $b = true
+      $o = is_function_available($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_function_availables function_availables' do
+      pp = <<-EOS
+      $a = "is_function_available"
+      $o = is_function_available($a)
+      notice(inline_template('is_function_available is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_function_available is true/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/is_hash_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,63 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_hash function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'is_hashs arrays' do
+      pp = <<-EOS
+      $a = ['aaa','bbb','ccc']
+      $o = is_hash($a)
+      notice(inline_template('is_hash is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_hash is false/)
+      end
+    end
+    it 'is_hashs empty hashs' do
+      pp = <<-EOS
+      $a = {}
+      $b = true
+      $o = is_hash($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_hashs strings' do
+      pp = <<-EOS
+      $a = "aoeu"
+      $b = false
+      $o = is_hash($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_hashs hashes' do
+      pp = <<-EOS
+      $a = {'aaa'=>'bbb'}
+      $b = true
+      $o = is_hash($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/is_integer_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,95 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_integer function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'is_integers arrays' do
+      pp = <<-EOS
+      $a = ['aaa.com','bbb','ccc']
+      $b = false
+      $o = is_integer($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_integers true' do
+      pp = <<-EOS
+      $a = true
+      $b = false
+      $o = is_integer($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_integers strings' do
+      pp = <<-EOS
+      $a = "3"
+      $b = true
+      $o = is_integer($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_integers floats' do
+      pp = <<-EOS
+      $a = 3.5
+      $b = false
+      $o = is_integer($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_integers integers' do
+      pp = <<-EOS
+      $a = 3
+      $b = true
+      $o = is_integer($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_integers hashes' do
+      pp = <<-EOS
+      $a = {'aaa'=>'www.com'}
+      $b = false
+      $o = is_integer($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/is_ip_address_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,80 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_ip_address function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'is_ip_addresss ipv4' do
+      pp = <<-EOS
+      $a = '1.2.3.4'
+      $b = true
+      $o = is_ip_address($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_ip_addresss ipv6' do
+      pp = <<-EOS
+      $a = "fe80:0000:cd12:d123:e2f8:47ff:fe09:dd74"
+      $b = true
+      $o = is_ip_address($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_ip_addresss ipv6 compressed' do
+      pp = <<-EOS
+      $a = "fe00::1"
+      $b = true
+      $o = is_ip_address($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_ip_addresss strings' do
+      pp = <<-EOS
+      $a = "aoeu"
+      $b = false
+      $o = is_ip_address($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_ip_addresss ipv4 out of range' do
+      pp = <<-EOS
+      $a = '1.2.3.400'
+      $b = false
+      $o = is_ip_address($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/is_mac_address_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,38 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_mac_address function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'is_mac_addresss a mac' do
+      pp = <<-EOS
+      $a = '00:a0:1f:12:7f:a0'
+      $b = true
+      $o = is_mac_address($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_mac_addresss a mac out of range' do
+      pp = <<-EOS
+      $a = '00:a0:1f:12:7f:g0'
+      $b = false
+      $o = is_mac_address($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/is_numeric_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,95 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_numeric function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'is_numerics arrays' do
+      pp = <<-EOS
+      $a = ['aaa.com','bbb','ccc']
+      $b = false
+      $o = is_numeric($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_numerics true' do
+      pp = <<-EOS
+      $a = true
+      $b = false
+      $o = is_numeric($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_numerics strings' do
+      pp = <<-EOS
+      $a = "3"
+      $b = true
+      $o = is_numeric($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_numerics floats' do
+      pp = <<-EOS
+      $a = 3.5
+      $b = true
+      $o = is_numeric($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_numerics integers' do
+      pp = <<-EOS
+      $a = 3
+      $b = true
+      $o = is_numeric($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_numerics hashes' do
+      pp = <<-EOS
+      $a = {'aaa'=>'www.com'}
+      $b = false
+      $o = is_numeric($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+    it 'handles non-arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/is_string_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,102 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'is_string function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'is_strings arrays' do
+      pp = <<-EOS
+      $a = ['aaa.com','bbb','ccc']
+      $b = false
+      $o = is_string($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_strings true' do
+      pp = <<-EOS
+      $a = true
+      $b = false
+      $o = is_string($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_strings strings' do
+      pp = <<-EOS
+      $a = "aoeu"
+      $o = is_string($a)
+      notice(inline_template('is_string is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_string is true/)
+      end
+    end
+    it 'is_strings number strings' do
+      pp = <<-EOS
+      $a = "3"
+      $o = is_string($a)
+      notice(inline_template('is_string is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/is_string is false/)
+      end
+    end
+    it 'is_strings floats' do
+      pp = <<-EOS
+      $a = 3.5
+      $b = false
+      $o = is_string($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_strings integers' do
+      pp = <<-EOS
+      $a = 3
+      $b = false
+      $o = is_string($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'is_strings hashes' do
+      pp = <<-EOS
+      $a = {'aaa'=>'www.com'}
+      $b = false
+      $o = is_string($a)
+      if $o == $b {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/join_keys_to_values_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'join_keys_to_values function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'join_keys_to_valuess hashes' do
+      pp = <<-EOS
+      $a = {'aaa'=>'bbb','ccc'=>'ddd'}
+      $b = ':'
+      $o = join_keys_to_values($a,$b)
+      notice(inline_template('join_keys_to_values is <%= @o.sort.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/join_keys_to_values is \["aaa:bbb", "ccc:ddd"\]/)
+      end
+    end
+    it 'handles non hashes'
+    it 'handles empty hashes'
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/join_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'join function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'joins arrays' do
+      pp = <<-EOS
+      $a = ['aaa','bbb','ccc']
+      $b = ':'
+      $c = 'aaa:bbb:ccc'
+      $o = join($a,$b)
+      if $o == $c {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    it 'handles non arrays'
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/keys_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'keys function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'keyss hashes' do
+      pp = <<-EOS
+      $a = {'aaa'=>'bbb','ccc'=>'ddd'}
+      $o = keys($a)
+      notice(inline_template('keys is <%= @o.sort.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/keys is \["aaa", "ccc"\]/)
+      end
+    end
+    it 'handles non hashes'
+    it 'handles empty hashes'
+  end
+  describe 'failure' do
+    it 'handles improper argument counts'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/loadyaml_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+tmpdir = default.tmpdir('stdlib')
+
+describe 'loadyaml function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'loadyamls array of values' do
+      shell("echo '---
+      aaa: 1
+      bbb: 2
+      ccc: 3
+      ddd: 4' > #{tmpdir}/testyaml.yaml")
+      pp = <<-EOS
+      $o = loadyaml('#{tmpdir}/testyaml.yaml')
+      notice(inline_template('loadyaml[aaa] is <%= @o["aaa"].inspect %>'))
+      notice(inline_template('loadyaml[bbb] is <%= @o["bbb"].inspect %>'))
+      notice(inline_template('loadyaml[ccc] is <%= @o["ccc"].inspect %>'))
+      notice(inline_template('loadyaml[ddd] is <%= @o["ddd"].inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/loadyaml\[aaa\] is 1/)
+        expect(r.stdout).to match(/loadyaml\[bbb\] is 2/)
+        expect(r.stdout).to match(/loadyaml\[ccc\] is 3/)
+        expect(r.stdout).to match(/loadyaml\[ddd\] is 4/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'fails with no arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/lstrip_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'lstrip function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'lstrips arrays' do
+      pp = <<-EOS
+      $a = ["  the   ","   public   ","   art","galleries   "]
+      # Anagram: Large picture halls, I bet
+      $o = lstrip($a)
+      notice(inline_template('lstrip is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/lstrip is \["the   ", "public   ", "art", "galleries   "\]/)
+      end
+    end
+    it 'lstrips strings' do
+      pp = <<-EOS
+      $a = "   blowzy night-frumps vex'd jack q   "
+      $o = lstrip($a)
+      notice(inline_template('lstrip is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/lstrip is "blowzy night-frumps vex'd jack q   "/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings or arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/max_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'max function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'maxs arrays' do
+      pp = <<-EOS
+      $o = max("the","public","art","galleries")
+      notice(inline_template('max is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/max is "the"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/member_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,54 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'member function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  shared_examples 'item found' do
+    it 'should output correctly' do
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+  end
+  describe 'success' do
+    it 'members arrays' do
+      pp = <<-EOS
+      $a = ['aaa','bbb','ccc']
+      $b = 'ccc'
+      $c = true
+      $o = member($a,$b)
+      if $o == $c {
+        notify { 'output correct': }
+      }
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/Notice: output correct/)
+      end
+    end
+    describe 'members array of integers' do
+      it_should_behave_like 'item found' do
+        let(:pp) { <<-EOS
+      if member( [1,2,3,4], 4 ){
+        notify { 'output correct': }
+      }
+        EOS
+        }
+      end
+    end
+    describe 'members of mixed array' do
+      it_should_behave_like 'item found' do
+        let(:pp) { <<-EOS
+      if member( ['a','4',3], 'a' ){
+        notify { 'output correct': }
+}
+        EOS
+        }
+      end
+    end
+    it 'members arrays without members'
+  end
+
+  describe 'failure' do
+    it 'handles improper argument counts'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/merge_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'merge function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'should merge two hashes' do
+      pp = <<-EOS
+      $a = {'one' => 1, 'two' => 2, 'three' => { 'four' => 4 } }
+      $b = {'two' => 'dos', 'three' => { 'five' => 5 } }
+      $o = merge($a, $b)
+      notice(inline_template('merge[one]   is <%= @o["one"].inspect %>'))
+      notice(inline_template('merge[two]   is <%= @o["two"].inspect %>'))
+      notice(inline_template('merge[three] is <%= @o["three"].inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/merge\[one\]   is ("1"|1)/)
+        expect(r.stdout).to match(/merge\[two\]   is "dos"/)
+        expect(r.stdout).to match(/merge\[three\] is {"five"=>("5"|5)}/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/min_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'min function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'mins arrays' do
+      pp = <<-EOS
+      $o = min("the","public","art","galleries")
+      notice(inline_template('min is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/min is "art"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/centos-59-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-59-x64:
+    roles:
+      - master
+    platform: el-5-x86_64
+    box : centos-59-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-59-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/centos-6-vcloud.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+HOSTS:
+  'centos-6-vcloud':
+    roles:
+      - master
+    platform: el-6-x86_64
+    hypervisor: vcloud
+    template: centos-6-x86_64
+CONFIG:
+  type: foss
+  ssh:
+    keys: "~/.ssh/id_rsa-acceptance"
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/centos-64-x64-pe.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+HOSTS:
+  centos-64-x64:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: el-6-x86_64
+    box : centos-64-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: pe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/centos-64-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-64-x64:
+    roles:
+      - master
+    platform: el-6-x86_64
+    box : centos-64-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/centos-65-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-65-x64:
+    roles:
+      - master
+    platform: el-6-x86_64
+    box : centos-65-x64-vbox436-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/default.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  centos-65-x64:
+    roles:
+      - master
+    platform: el-6-x86_64
+    box : centos-65-x64-vbox436-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/fedora-18-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  fedora-18-x64:
+    roles:
+      - master
+    platform: fedora-18-x86_64
+    box : fedora-18-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/fedora-18-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/sles-11-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  sles-11-x64.local:
+    roles:
+      - master
+    platform: sles-11-x64
+    box : sles-11sp1-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/sles-11sp1-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+    type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-server-10044-x64:
+    roles:
+      - master
+    platform: ubuntu-10.04-amd64
+    box : ubuntu-server-10044-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+HOSTS:
+  ubuntu-server-12042-x64:
+    roles:
+      - master
+    platform: ubuntu-12.04-amd64
+    box : ubuntu-server-12042-x64-vbox4210-nocm
+    box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box
+    hypervisor : vagrant
+CONFIG:
+  type: foss
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+HOSTS:
+  ubuntu-server-1404-x64:
+    roles:
+      - master
+    platform: ubuntu-14.04-amd64
+    box : puppetlabs/ubuntu-14.04-64-nocm
+    box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm
+    hypervisor : vagrant
+CONFIG:
+  log_level   : debug
+  type: git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2003-i386.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2003_i386:
+    roles:
+      - agent
+      - default
+    platform: windows-2003-i386
+    template: win-2003-i386
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  ssh:
+    keys: "~/.ssh/id_rsa-acceptance"
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2003-x86_64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2003_x86_64:
+    roles:
+      - agent
+      - default
+    platform: windows-2003-x86_64
+    template: win-2003-x86_64
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  ssh:
+    keys: "~/.ssh/id_rsa-acceptance"
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2008-x86_64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2008_x86_64:
+    roles:
+      - agent
+      - default
+    platform: windows-2008-x86_64
+    template: win-2008-x86_64
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  ssh:
+    keys: "~/.ssh/id_rsa-acceptance"
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2008r2-x86_64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2008r2:
+    roles:
+      - agent
+      - default
+    platform: windows-2008r2-x86_64
+    template: win-2008r2-x86_64
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  ssh:
+    keys: "~/.ssh/id_rsa-acceptance"
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2012-x86_64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2012:
+    roles:
+      - agent
+      - default
+    platform: windows-2012-x86_64
+    template: win-2012-x86_64
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  ssh:
+    keys: "~/.ssh/id_rsa-acceptance"
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/nodesets/windows-2012r2-x86_64.yml	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+HOSTS:
+  ubuntu1204:
+    roles:
+      - master
+      - database
+      - dashboard
+    platform: ubuntu-12.04-amd64
+    template: ubuntu-1204-x86_64
+    hypervisor: vcloud
+  win2012r2:
+    roles:
+      - agent
+      - default
+    platform: windows-2012r2-x86_64
+    template: win-2012r2-x86_64
+    hypervisor: vcloud
+CONFIG:
+  nfs_server: none
+  ssh:
+    keys: "~/.ssh/id_rsa-acceptance"
+  consoleport: 443
+  datastore: instance0
+  folder: Delivery/Quality Assurance/Enterprise/Dynamic
+  resourcepool: delivery/Quality Assurance/Enterprise/Dynamic
+  pooling_api: http://vcloud.delivery.puppetlabs.net/
+  pe_dir: http://neptune.puppetlabs.lan/3.2/ci-ready/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/num2bool_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,76 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'num2bool function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'bools positive numbers and numeric strings as true' do
+      pp = <<-EOS
+      $a = 1
+      $b = "1"
+      $c = "50"
+      $ao = num2bool($a)
+      $bo = num2bool($b)
+      $co = num2bool($c)
+      notice(inline_template('a is <%= @ao.inspect %>'))
+      notice(inline_template('b is <%= @bo.inspect %>'))
+      notice(inline_template('c is <%= @co.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/a is true/)
+        expect(r.stdout).to match(/b is true/)
+        expect(r.stdout).to match(/c is true/)
+      end
+    end
+    it 'bools negative numbers as false' do
+      pp = <<-EOS
+      $a = 0
+      $b = -0.1
+      $c = ["-50","1"]
+      $ao = num2bool($a)
+      $bo = num2bool($b)
+      $co = num2bool($c)
+      notice(inline_template('a is <%= @ao.inspect %>'))
+      notice(inline_template('b is <%= @bo.inspect %>'))
+      notice(inline_template('c is <%= @co.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/a is false/)
+        expect(r.stdout).to match(/b is false/)
+        expect(r.stdout).to match(/c is false/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'fails on words' do
+      pp = <<-EOS
+      $a = "a"
+      $ao = num2bool($a)
+      notice(inline_template('a is <%= @ao.inspect %>'))
+      EOS
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/not look like a number/)
+    end
+
+    it 'fails on numberwords' do
+      pp = <<-EOS
+      $b = "1b"
+      $bo = num2bool($b)
+      notice(inline_template('b is <%= @bo.inspect %>'))
+      EOS
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/not look like a number/)
+
+    end
+
+    it 'fails on non-numeric/strings' do
+      pending "The function will call .to_s.to_i on anything not a Numeric or
+      String, and results in 0. Is this intended?"
+      pp = <<-EOS
+      $c = {"c" => "-50"}
+      $co = num2bool($c)
+      notice(inline_template('c is <%= @co.inspect %>'))
+      EOS
+      expect(apply_manifest(ppc :expect_failures => true).stderr).to match(/Unable to parse/)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/parsejson_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'parsejson function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'parses valid json' do
+      pp = <<-EOS
+      $a = '{"hunter": "washere", "tests": "passing"}'
+      $ao = parsejson($a)
+      $tests = $ao['tests']
+      notice(inline_template('tests are <%= @tests.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/tests are "passing"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'raises error on incorrect json' do
+      pp = <<-EOS
+      $a = '{"hunter": "washere", "tests": "passing",}'
+      $ao = parsejson($a)
+      notice(inline_template('a is <%= @ao.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :expect_failures => true) do |r|
+        expect(r.stderr).to match(/expected next name/)
+      end
+    end
+
+    it 'raises error on incorrect number of arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/parseyaml_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'parseyaml function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'parses valid yaml' do
+      pp = <<-EOS
+      $a = "---\nhunter: washere\ntests: passing\n"
+      $o = parseyaml($a)
+      $tests = $o['tests']
+      notice(inline_template('tests are <%= @tests.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/tests are "passing"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'raises error on incorrect yaml' do
+      pp = <<-EOS
+      $a = "---\nhunter: washere\ntests: passing\n:"
+      $o = parseyaml($a)
+      $tests = $o['tests']
+      notice(inline_template('tests are <%= @tests.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :expect_failures => true) do |r|
+        expect(r.stderr).to match(/(syntax error|did not find expected key)/)
+      end
+    end
+
+    it 'raises error on incorrect number of arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/pick_default_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,54 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'pick_default function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'pick_defaults a default value' do
+      pp = <<-EOS
+      $a = undef
+      $o = pick_default($a, 'default')
+      notice(inline_template('picked is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/picked is "default"/)
+      end
+    end
+    it 'pick_defaults with no value' do
+      pp = <<-EOS
+      $a = undef
+      $b = undef
+      $o = pick_default($a,$b)
+      notice(inline_template('picked is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/picked is ""/)
+      end
+    end
+    it 'pick_defaults the first set value' do
+      pp = <<-EOS
+      $a = "something"
+      $b = "long"
+      $o = pick_default($a, $b, 'default')
+      notice(inline_template('picked is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/picked is "something"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'raises error with no values' do
+      pp = <<-EOS
+      $o = pick_default()
+      notice(inline_template('picked is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :expect_failures => true) do |r|
+        expect(r.stderr).to match(/Must receive at least one argument/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/pick_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,44 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'pick function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'picks a default value' do
+      pp = <<-EOS
+      $a = undef
+      $o = pick($a, 'default')
+      notice(inline_template('picked is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/picked is "default"/)
+      end
+    end
+    it 'picks the first set value' do
+      pp = <<-EOS
+      $a = "something"
+      $b = "long"
+      $o = pick($a, $b, 'default')
+      notice(inline_template('picked is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/picked is "something"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'raises error with all undef values' do
+      pp = <<-EOS
+      $a = undef
+      $b = undef
+      $o = pick($a, $b)
+      notice(inline_template('picked is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :expect_failures => true) do |r|
+        expect(r.stderr).to match(/must receive at least one non empty value/)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/prefix_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'prefix function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'prefixes array of values' do
+      pp = <<-EOS
+      $o = prefix(['a','b','c'],'p')
+      notice(inline_template('prefix is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/prefix is \["pa", "pb", "pc"\]/)
+      end
+    end
+    it 'prefixs with empty array' do
+      pp = <<-EOS
+      $o = prefix([],'p')
+      notice(inline_template('prefix is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/prefix is \[\]/)
+      end
+    end
+    it 'prefixs array of values with undef' do
+      pp = <<-EOS
+      $o = prefix(['a','b','c'], undef)
+      notice(inline_template('prefix is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/prefix is \["a", "b", "c"\]/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'fails with no arguments'
+    it 'fails when first argument is not array'
+    it 'fails when second argument is not string'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/pw_hash_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+# Windows and OS X do not have useful implementations of crypt(3)
+describe 'pw_hash function', :unless => (UNSUPPORTED_PLATFORMS + ['windows', 'Darwin', 'SLES']).include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'hashes passwords' do
+      pp = <<-EOS
+      $o = pw_hash('password', 'sha-512', 'salt')
+      notice(inline_template('pw_hash is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/pw_hash is "\$6\$salt\$IxDD3jeSOb5eB1CX5LBsqZFVkJdido3OUILO5Ifz5iwMuTS4XMS130MTSuDDl3aCI6WouIL9AjRbLCelDCy\.g\."/)
+      end
+    end
+
+    it 'returns nil if no password is provided' do
+      pp = <<-EOS
+      $o = pw_hash('', 'sha-512', 'salt')
+      notice(inline_template('pw_hash is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/pw_hash is nil/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles less than three arguments'
+    it 'handles more than three arguments'
+    it 'handles non strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/range_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'range function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'ranges letters' do
+      pp = <<-EOS
+      $o = range('a','d')
+      notice(inline_template('range is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/range is \["a", "b", "c", "d"\]/)
+      end
+    end
+    it 'ranges letters with a step' do
+      pp = <<-EOS
+      $o = range('a','d', '2')
+      notice(inline_template('range is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/range is \["a", "c"\]/)
+      end
+    end
+    it 'ranges letters with a negative step'
+    it 'ranges numbers'
+    it 'ranges numbers with a step'
+    it 'ranges numbers with a negative step'
+    it 'ranges numeric strings'
+    it 'ranges zero padded numbers'
+  end
+  describe 'failure' do
+    it 'fails with no arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/reject_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'reject function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'rejects array of values' do
+      pp = <<-EOS
+      $o = reject(['aaa','bbb','ccc','aaaddd'], 'aaa')
+      notice(inline_template('reject is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/reject is \["bbb", "ccc"\]/)
+      end
+    end
+    it 'rejects with empty array' do
+      pp = <<-EOS
+      $o = reject([],'aaa')
+      notice(inline_template('reject is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/reject is \[\]/)
+      end
+    end
+    it 'rejects array of values with undef' do
+      pp = <<-EOS
+      $o = reject(['aaa','bbb','ccc','aaaddd'], undef)
+      notice(inline_template('reject is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/reject is \[\]/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'fails with no arguments'
+    it 'fails when first argument is not array'
+    it 'fails when second argument is not string'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/reverse_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'reverse function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'reverses strings' do
+      pp = <<-EOS
+      $a = "the public art galleries"
+      # Anagram: Large picture halls, I bet
+      $o = reverse($a)
+      notice(inline_template('reverse is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/reverse is "seirellag tra cilbup eht"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings or arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/rstrip_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'rstrip function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'rstrips arrays' do
+      pp = <<-EOS
+      $a = ["  the   ","   public   ","   art","galleries   "]
+      # Anagram: Large picture halls, I bet
+      $o = rstrip($a)
+      notice(inline_template('rstrip is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/rstrip is \["  the", "   public", "   art", "galleries"\]/)
+      end
+    end
+    it 'rstrips strings' do
+      pp = <<-EOS
+      $a = "   blowzy night-frumps vex'd jack q   "
+      $o = rstrip($a)
+      notice(inline_template('rstrip is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/rstrip is "   blowzy night-frumps vex'd jack q"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings or arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/shuffle_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'shuffle function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'shuffles arrays' do
+      pp = <<-EOS
+      $a = ["1", "2", "3", "4", "5", "6", "7", "8", "the","public","art","galleries"]
+      # Anagram: Large picture halls, I bet
+      $o = shuffle($a)
+      notice(inline_template('shuffle is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to_not match(/shuffle is \["1", "2", "3", "4", "5", "6", "7", "8", "the", "public", "art", "galleries"\]/)
+      end
+    end
+    it 'shuffles strings' do
+      pp = <<-EOS
+      $a = "blowzy night-frumps vex'd jack q"
+      $o = shuffle($a)
+      notice(inline_template('shuffle is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to_not match(/shuffle is "blowzy night-frumps vex'd jack q"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings or arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/size_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,55 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'size function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'single string size' do
+      pp = <<-EOS
+      $a = 'discombobulate'
+      $o = size($a)
+      notice(inline_template('size is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/size is 14/)
+      end
+    end
+    it 'with empty string' do
+      pp = <<-EOS
+      $a = ''
+      $o = size($a)
+      notice(inline_template('size is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/size is 0/)
+      end
+    end
+    it 'with undef' do
+      pp = <<-EOS
+      $a = undef
+      $o = size($a)
+      notice(inline_template('size is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/size is 0/)
+      end
+    end
+    it 'strings in array' do
+      pp = <<-EOS
+      $a = ['discombobulate', 'moo']
+      $o = size($a)
+      notice(inline_template('size is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/size is 2/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings or arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/sort_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'sort function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'sorts arrays' do
+      pp = <<-EOS
+      $a = ["the","public","art","galleries"]
+      # Anagram: Large picture halls, I bet
+      $o = sort($a)
+      notice(inline_template('sort is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/sort is \["art", "galleries", "public", "the"\]/)
+      end
+    end
+    it 'sorts strings' do
+      pp = <<-EOS
+      $a = "blowzy night-frumps vex'd jack q"
+      $o = sort($a)
+      notice(inline_template('sort is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/sort is "    '-abcdefghijklmnopqrstuvwxyz"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings or arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/squeeze_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,47 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'squeeze function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'squeezes arrays' do
+      pp = <<-EOS
+      # Real words!
+      $a = ["wallless", "laparohysterosalpingooophorectomy", "brrr", "goddessship"]
+      $o = squeeze($a)
+      notice(inline_template('squeeze is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/squeeze is \["wales", "laparohysterosalpingophorectomy", "br", "godeship"\]/)
+      end
+    end
+    it 'squeezez arrays with an argument'
+    it 'squeezes strings' do
+      pp = <<-EOS
+      $a = "wallless laparohysterosalpingooophorectomy brrr goddessship"
+      $o = squeeze($a)
+      notice(inline_template('squeeze is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/squeeze is "wales laparohysterosalpingophorectomy br godeship"/)
+      end
+    end
+
+    it 'squeezes strings with an argument' do
+      pp = <<-EOS
+      $a = "countessship duchessship governessship hostessship"
+      $o = squeeze($a, 's')
+      notice(inline_template('squeeze is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/squeeze is "counteship ducheship governeship hosteship"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings or arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/str2bool_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'str2bool function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'works with "y"' do
+      pp = <<-EOS
+      $o = str2bool('y')
+      notice(inline_template('str2bool is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/str2bool is true/)
+      end
+    end
+    it 'works with "Y"'
+    it 'works with "yes"'
+    it 'works with "1"'
+    it 'works with "true"'
+    it 'works with "n"'
+    it 'works with "N"'
+    it 'works with "no"'
+    it 'works with "0"'
+    it 'works with "false"'
+    it 'works with undef'
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non arrays or strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/str2saltedsha512_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'str2saltedsha512 function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'works with "y"' do
+      pp = <<-EOS
+      $o = str2saltedsha512('password')
+      notice(inline_template('str2saltedsha512 is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/str2saltedsha512 is "[a-f0-9]{136}"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles more than one argument'
+    it 'handles non strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/strftime_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'strftime function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'gives the Century' do
+      pp = <<-EOS
+      $o = strftime('%C')
+      notice(inline_template('strftime is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/strftime is "20"/)
+      end
+    end
+    it 'takes a timezone argument'
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles invalid format strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/strip_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'strip function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'strips arrays' do
+      pp = <<-EOS
+      $a = ["  the   ","   public   ","   art","galleries   "]
+      # Anagram: Large picture halls, I bet
+      $o = strip($a)
+      notice(inline_template('strip is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/strip is \["the", "public", "art", "galleries"\]/)
+      end
+    end
+    it 'strips strings' do
+      pp = <<-EOS
+      $a = "   blowzy night-frumps vex'd jack q   "
+      $o = strip($a)
+      notice(inline_template('strip is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/strip is "blowzy night-frumps vex'd jack q"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings or arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/suffix_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'suffix function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'suffixes array of values' do
+      pp = <<-EOS
+      $o = suffix(['a','b','c'],'p')
+      notice(inline_template('suffix is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/suffix is \["ap", "bp", "cp"\]/)
+      end
+    end
+    it 'suffixs with empty array' do
+      pp = <<-EOS
+      $o = suffix([],'p')
+      notice(inline_template('suffix is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/suffix is \[\]/)
+      end
+    end
+    it 'suffixs array of values with undef' do
+      pp = <<-EOS
+      $o = suffix(['a','b','c'], undef)
+      notice(inline_template('suffix is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/suffix is \["a", "b", "c"\]/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'fails with no arguments'
+    it 'fails when first argument is not array'
+    it 'fails when second argument is not string'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/swapcase_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'swapcase function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'works with strings' do
+      pp = <<-EOS
+      $o = swapcase('aBcD')
+      notice(inline_template('swapcase is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/swapcase is "AbCd"/)
+      end
+    end
+    it 'works with arrays'
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non arrays or strings'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/time_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'time function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'gives the time' do
+      pp = <<-EOS
+      $o = time()
+      notice(inline_template('time is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        m = r.stdout.match(/time is (\d+)\D/)
+
+        # When I wrote this test
+        expect(Integer(m[1])).to be > 1398894170
+      end
+    end
+    it 'takes a timezone argument' do
+      pp = <<-EOS
+      $o = time('UTC')
+      notice(inline_template('time is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        m = r.stdout.match(/time is (\d+)\D/)
+
+        expect(Integer(m[1])).to be > 1398894170
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles more arguments'
+    it 'handles invalid timezones'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/to_bytes_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'to_bytes function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'converts kB to B' do
+      pp = <<-EOS
+      $o = to_bytes('4 kB')
+      notice(inline_template('to_bytes is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        m = r.stdout.match(/to_bytes is (\d+)\D/)
+        expect(m[1]).to eq("4096")
+      end
+    end
+    it 'works without the B in unit'
+    it 'works without a space before unit'
+    it 'works without a unit'
+    it 'converts fractions'
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non integer arguments'
+    it 'handles unknown units like uB'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/try_get_value_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,47 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'try_get_value function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'gets a value' do
+      pp = <<-EOS
+      $data = {
+        'a' => { 'b' => 'passing'}
+      }
+
+      $tests = try_get_value($data, 'a/b')
+      notice(inline_template('tests are <%= @tests.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/tests are "passing"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'uses a default value' do
+      pp = <<-EOS
+      $data = {
+        'a' => { 'b' => 'passing'}
+      }
+
+      $tests = try_get_value($data, 'c/d', 'using the default value')
+      notice(inline_template('tests are <%= @tests.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/using the default value/)
+      end
+    end
+
+    it 'raises error on incorrect number of arguments' do
+      pp = <<-EOS
+      $o = try_get_value()
+      EOS
+
+      apply_manifest(pp, :expect_failures => true) do |r|
+        expect(r.stderr).to match(/wrong number of arguments/i)
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/type_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'type function', :unless => (UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) || is_future_parser_enabled?) do
+  describe 'success' do
+    it 'types arrays' do
+      pp = <<-EOS
+      $a = ["the","public","art","galleries"]
+      # Anagram: Large picture halls, I bet
+      $o = type($a)
+      notice(inline_template('type is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/type is "array"/)
+      end
+    end
+    it 'types strings' do
+      pp = <<-EOS
+      $a = "blowzy night-frumps vex'd jack q"
+      $o = type($a)
+      notice(inline_template('type is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/type is "string"/)
+      end
+    end
+    it 'types hashes'
+    it 'types integers'
+    it 'types floats'
+    it 'types booleans'
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/union_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'union function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'unions arrays' do
+      pp = <<-EOS
+      $a = ["the","public"]
+      $b = ["art"]
+      $c = ["galleries"]
+      # Anagram: Large picture halls, I bet
+      $o = union($a,$b,$c)
+      notice(inline_template('union is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/union is \["the", "public", "art", "galleries"\]/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/unique_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'unique function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'uniques arrays' do
+      pp = <<-EOS
+      $a = ["wallless", "wallless", "brrr", "goddessship"]
+      $o = unique($a)
+      notice(inline_template('unique is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/unique is \["wallless", "brrr", "goddessship"\]/)
+      end
+    end
+    it 'uniques strings' do
+      pp = <<-EOS
+      $a = "wallless laparohysterosalpingooophorectomy brrr goddessship"
+      $o = unique($a)
+      notice(inline_template('unique is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/unique is "wales prohytingcmbd"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings or arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/unsupported_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'unsupported distributions and OSes', :if => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  it 'should fail' do
+    pp = <<-EOS
+    class { 'mysql::server': }
+    EOS
+    expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/unsupported osfamily/i)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/upcase_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'upcase function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'upcases arrays' do
+      pp = <<-EOS
+      $a = ["wallless", "laparohysterosalpingooophorectomy", "brrr", "goddessship"]
+      $o = upcase($a)
+      notice(inline_template('upcase is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/upcase is \["WALLLESS", "LAPAROHYSTEROSALPINGOOOPHORECTOMY", "BRRR", "GODDESSSHIP"\]/)
+      end
+    end
+    it 'upcases strings' do
+      pp = <<-EOS
+      $a = "wallless laparohysterosalpingooophorectomy brrr goddessship"
+      $o = upcase($a)
+      notice(inline_template('upcase is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/upcase is "WALLLESS LAPAROHYSTEROSALPINGOOOPHORECTOMY BRRR GODDESSSHIP"/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings or arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/uriescape_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'uriescape function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'uriescape strings' do
+      pp = <<-EOS
+      $a = ":/?#[]@!$&'()*+,;= \\\"{}"
+      $o = uriescape($a)
+      notice(inline_template('uriescape is <%= @o.inspect %>'))
+      EOS
+
+      apply_manifest(pp, :catch_failures => true) do |r|
+        expect(r.stdout).to match(/uriescape is ":\/\?%23\[\]@!\$&'\(\)\*\+,;=%20%22%7B%7D"/)
+      end
+    end
+    it 'does nothing if a string is already safe'
+  end
+  describe 'failure' do
+    it 'handles no arguments'
+    it 'handles non strings or arrays'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/validate_absolute_path_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'validate_absolute_path function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    %w{
+      C:/
+      C:\\\\
+      C:\\\\WINDOWS\\\\System32
+      C:/windows/system32
+      X:/foo/bar
+      X:\\\\foo\\\\bar
+      /var/tmp
+      /var/lib/puppet
+      /var/opt/../lib/puppet
+    }.each do |path|
+      it "validates a single argument #{path}" do
+        pp = <<-EOS
+        $one = '#{path}'
+        validate_absolute_path($one)
+        EOS
+
+        apply_manifest(pp, :catch_failures => true)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments'
+    it 'handles relative paths'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/validate_array_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'validate_array function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'validates a single argument' do
+      pp = <<-EOS
+      $one = ['a', 'b']
+      validate_array($one)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates an multiple arguments' do
+      pp = <<-EOS
+      $one = ['a', 'b']
+      $two = [['c'], 'd']
+      validate_array($one,$two)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates a non-array' do
+      {
+        %{validate_array({'a' => 'hash' })} => "Hash",
+        %{validate_array('string')}         => "String",
+        %{validate_array(false)}            => "FalseClass",
+        %{validate_array(undef)}            => "String"
+      }.each do |pp,type|
+        expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/a #{type}/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/validate_augeas_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,63 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'validate_augeas function', :unless => ((UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem'))) or (fact('osfamily') == 'windows')) do
+  describe 'prep' do
+    it 'installs augeas for tests'
+  end
+  describe 'success' do
+    context 'valid inputs with no 3rd argument' do
+      {
+        'root:x:0:0:root:/root:/bin/bash\n'                        => 'Passwd.lns',
+        'proc /proc   proc    nodev,noexec,nosuid     0       0\n' => 'Fstab.lns'
+      }.each do |line,lens|
+        it "validates a single argument for #{lens}" do
+          pp = <<-EOS
+          $line = "#{line}"
+          $lens = "#{lens}"
+          validate_augeas($line, $lens)
+          EOS
+
+          apply_manifest(pp, :catch_failures => true)
+        end
+      end
+    end
+    context 'valid inputs with 3rd and 4th arguments' do
+      it "validates a restricted value" do
+        line        = 'root:x:0:0:root:/root:/bin/barsh\n'
+        lens        = 'Passwd.lns'
+        restriction = '$file/*[shell="/bin/barsh"]'
+        pp = <<-EOS
+        $line        = "#{line}"
+        $lens        = "#{lens}"
+        $restriction = ['#{restriction}']
+        validate_augeas($line, $lens, $restriction, "my custom failure message")
+        EOS
+
+        expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/my custom failure message/)
+      end
+    end
+    context 'invalid inputs' do
+      {
+        'root:x:0:0:root' => 'Passwd.lns',
+        '127.0.1.1'       => 'Hosts.lns'
+      }.each do |line,lens|
+        it "validates a single argument for #{lens}" do
+          pp = <<-EOS
+          $line = "#{line}"
+          $lens = "#{lens}"
+          validate_augeas($line, $lens)
+          EOS
+
+          apply_manifest(pp, :expect_failures => true)
+        end
+      end
+    end
+    context 'garbage inputs' do
+      it 'raises an error on invalid inputs'
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/validate_bool_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'validate_bool function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'validates a single argument' do
+      pp = <<-EOS
+      $one = true
+      validate_bool($one)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates an multiple arguments' do
+      pp = <<-EOS
+      $one = true
+      $two = false
+      validate_bool($one,$two)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates a non-bool' do
+      {
+        %{validate_bool('true')}  => "String",
+        %{validate_bool('false')} => "String",
+        %{validate_bool([true])}  => "Array",
+        %{validate_bool(undef)}   => "String",
+      }.each do |pp,type|
+        expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/a #{type}/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/validate_cmd_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,52 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'validate_cmd function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'validates a true command' do
+      pp = <<-EOS
+      $one = 'foo'
+      if $::osfamily == 'windows' {
+        $two = 'echo' #shell built-in
+      } else {
+        $two = '/bin/echo'
+      }
+      validate_cmd($one,$two)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates a fail command' do
+      pp = <<-EOS
+      $one = 'foo'
+      if $::osfamily == 'windows' {
+        $two = 'C:/aoeu'
+      } else {
+        $two = '/bin/aoeu'
+      }
+      validate_cmd($one,$two)
+      EOS
+
+      apply_manifest(pp, :expect_failures => true)
+    end
+    it 'validates a fail command with a custom error message' do
+      pp = <<-EOS
+      $one = 'foo'
+      if $::osfamily == 'windows' {
+        $two = 'C:/aoeu'
+      } else {
+        $two = '/bin/aoeu'
+      }
+      validate_cmd($one,$two,"aoeu is dvorak")
+      EOS
+
+      apply_manifest(pp, :expect_failures => true) do |output|
+        expect(output.stderr).to match(/aoeu is dvorak/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments'
+    it 'handles improper argument types'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/validate_hash_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'validate_hash function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'validates a single argument' do
+      pp = <<-EOS
+      $one = { 'a' => 1 }
+      validate_hash($one)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates an multiple arguments' do
+      pp = <<-EOS
+      $one = { 'a' => 1 }
+      $two = { 'b' => 2 }
+      validate_hash($one,$two)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates a non-hash' do
+      {
+        %{validate_hash('{ "not" => "hash" }')} => "String",
+        %{validate_hash('string')}              => "String",
+        %{validate_hash(["array"])}             => "Array",
+        %{validate_hash(undef)}                 => "String",
+      }.each do |pp,type|
+        expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/a #{type}/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/validate_ipv4_address_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'validate_ipv4_address function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'validates a single argument' do
+      pp = <<-EOS
+      $one = '1.2.3.4'
+      validate_ipv4_address($one)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates an multiple arguments' do
+      pp = <<-EOS
+      $one = '1.2.3.4'
+      $two = '5.6.7.8'
+      validate_ipv4_address($one,$two)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments'
+    it 'handles ipv6 addresses'
+    it 'handles non-ipv4 strings'
+    it 'handles numbers'
+    it 'handles no arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/validate_ipv6_address_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'validate_ipv6_address function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'validates a single argument' do
+      pp = <<-EOS
+      $one = '3ffe:0505:0002::'
+      validate_ipv6_address($one)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates an multiple arguments' do
+      pp = <<-EOS
+      $one = '3ffe:0505:0002::'
+      $two = '3ffe:0505:0001::'
+      validate_ipv6_address($one,$two)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments'
+    it 'handles ipv6 addresses'
+    it 'handles non-ipv6 strings'
+    it 'handles numbers'
+    it 'handles no arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/validate_re_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,47 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'validate_re function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'validates a string' do
+      pp = <<-EOS
+      $one = 'one'
+      $two = '^one$'
+      validate_re($one,$two)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates an array' do
+      pp = <<-EOS
+      $one = 'one'
+      $two = ['^one$', '^two']
+      validate_re($one,$two)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates a failed array' do
+      pp = <<-EOS
+      $one = 'one'
+      $two = ['^two$', '^three']
+      validate_re($one,$two)
+      EOS
+
+      apply_manifest(pp, :expect_failures => true)
+    end
+    it 'validates a failed array with a custom error message' do
+      pp = <<-EOS
+      $one = '3.4.3'
+      $two = '^2.7'
+      validate_re($one,$two,"The $puppetversion fact does not match 2.7")
+      EOS
+
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/does not match/)
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments'
+    it 'handles improper argument types'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/validate_slength_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,72 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'validate_slength function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'validates a single string max' do
+      pp = <<-EOS
+      $one = 'discombobulate'
+      $two = 17
+      validate_slength($one,$two)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates multiple string maxes' do
+      pp = <<-EOS
+      $one = ['discombobulate', 'moo']
+      $two = 17
+      validate_slength($one,$two)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates min/max of  strings in array' do
+      pp = <<-EOS
+      $one = ['discombobulate', 'moo']
+      $two = 17
+      $three = 3
+      validate_slength($one,$two,$three)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates a single string max of incorrect length' do
+      pp = <<-EOS
+      $one = 'discombobulate'
+      $two = 1
+      validate_slength($one,$two)
+      EOS
+
+      apply_manifest(pp, :expect_failures => true)
+    end
+    it 'validates multiple string maxes of incorrect length' do
+      pp = <<-EOS
+      $one = ['discombobulate', 'moo']
+      $two = 3
+      validate_slength($one,$two)
+      EOS
+
+      apply_manifest(pp, :expect_failures => true)
+    end
+    it 'validates multiple strings min/maxes of incorrect length' do
+      pp = <<-EOS
+      $one = ['discombobulate', 'moo']
+      $two = 17
+      $three = 10
+      validate_slength($one,$two,$three)
+      EOS
+
+      apply_manifest(pp, :expect_failures => true)
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments'
+    it 'handles improper first argument type'
+    it 'handles non-strings in array of first argument'
+    it 'handles improper second argument type'
+    it 'handles improper third argument type'
+    it 'handles negative ranges'
+    it 'handles improper ranges'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/validate_string_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'validate_string function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'validates a single argument' do
+      pp = <<-EOS
+      $one = 'string'
+      validate_string($one)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates an multiple arguments' do
+      pp = <<-EOS
+      $one = 'string'
+      $two = 'also string'
+      validate_string($one,$two)
+      EOS
+
+      apply_manifest(pp, :catch_failures => true)
+    end
+    it 'validates a non-string' do
+      {
+        %{validate_string({ 'a' => 'hash' })} => "Hash",
+        %{validate_string(['array'])}         => "Array",
+        %{validate_string(false)}             => "FalseClass",
+      }.each do |pp,type|
+        expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/a #{type}/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/values_at_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,73 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'values_at function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'returns a specific value' do
+      pp = <<-EOS
+      $one = ['a','b','c','d','e']
+      $two = 1
+      $output = values_at($one,$two)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+
+      expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\["b"\]/)
+    end
+    it 'returns a specific negative index value' do
+      pending("negative numbers don't work")
+      pp = <<-EOS
+      $one = ['a','b','c','d','e']
+      $two = -1
+      $output = values_at($one,$two)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+
+      expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\["e"\]/)
+    end
+    it 'returns a range of values' do
+      pp = <<-EOS
+      $one = ['a','b','c','d','e']
+      $two = "1-3"
+      $output = values_at($one,$two)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+
+      expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\["b", "c", "d"\]/)
+    end
+    it 'returns a negative specific value and range of values' do
+      pp = <<-EOS
+      $one = ['a','b','c','d','e']
+      $two = ["1-3",0]
+      $output = values_at($one,$two)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+
+      expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\["b", "c", "d", "a"\]/)
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments' do
+      pp = <<-EOS
+      $one = ['a','b','c','d','e']
+      $output = values_at($one)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/Wrong number of arguments/)
+    end
+    it 'handles non-indicies arguments' do
+      pp = <<-EOS
+      $one = ['a','b','c','d','e']
+      $two = []
+      $output = values_at($one,$two)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/at least one positive index/)
+    end
+
+    it 'detects index ranges smaller than the start range'
+    it 'handles index ranges larger than array'
+    it 'handles non-integer indicies'
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/values_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+
+describe 'values function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'returns an array of values' do
+      pp = <<-EOS
+      $arg = {
+        'a' => 1,
+        'b' => 2,
+        'c' => 3,
+      }
+      $output = values($arg)
+      notice(inline_template('<%= @output.sort.inspect %>'))
+      EOS
+      if is_future_parser_enabled?
+        expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\[1, 2, 3\]/)
+      else
+        expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\["1", "2", "3"\]/)
+      end
+
+    end
+  end
+  describe 'failure' do
+    it 'handles non-hash arguments' do
+      pp = <<-EOS
+      $arg = "foo"
+      $output = values($arg)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/Requires hash/)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/acceptance/zip_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,86 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper_acceptance'
+require 'puppet'
+
+describe 'zip function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do
+  describe 'success' do
+    it 'zips two arrays of numbers together' do
+      pp = <<-EOS
+      $one = [1,2,3,4]
+      $two = [5,6,7,8]
+      $output = zip($one,$two)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+      if is_future_parser_enabled?
+        expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\[\[1, 5\], \[2, 6\], \[3, 7\], \[4, 8\]\]/)
+      else
+        expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\[\["1", "5"\], \["2", "6"\], \["3", "7"\], \["4", "8"\]\]/)
+      end
+    end
+    it 'zips two arrays of numbers & bools together' do
+      pp = <<-EOS
+      $one = [1,2,"three",4]
+      $two = [true,true,false,false]
+      $output = zip($one,$two)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+      if is_future_parser_enabled?
+        expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\[\[1, true\], \[2, true\], \["three", false\], \[4, false\]\]/)
+      else
+        expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\[\["1", true\], \["2", true\], \["three", false\], \["4", false\]\]/)
+      end
+    end
+    it 'zips two arrays of numbers together and flattens them' do
+      # XXX This only tests the argument `true`, even though the following are valid:
+      # 1 t y true yes
+      # 0 f n false no
+      # undef undefined
+      pp = <<-EOS
+      $one = [1,2,3,4]
+      $two = [5,6,7,8]
+      $output = zip($one,$two,true)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+      if is_future_parser_enabled?
+        expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\[1, 5, 2, 6, 3, 7, 4, 8\]/)
+      else
+        expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\["1", "5", "2", "6", "3", "7", "4", "8"\]/)
+      end
+    end
+    it 'handles unmatched length' do
+      # XXX Is this expected behavior?
+      pp = <<-EOS
+      $one = [1,2]
+      $two = [5,6,7,8]
+      $output = zip($one,$two)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+      if is_future_parser_enabled?
+        expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\[\[1, 5\], \[2, 6\]\]/)
+      else
+        expect(apply_manifest(pp, :catch_failures => true).stdout).to match(/\[\["1", "5"\], \["2", "6"\]\]/)
+      end
+    end
+  end
+  describe 'failure' do
+    it 'handles improper number of arguments' do
+      pp = <<-EOS
+      $one = [1,2]
+      $output = zip($one)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/Wrong number of arguments/)
+    end
+    it 'handles improper argument types' do
+      pp = <<-EOS
+      $one = "a string"
+      $two = [5,6,7,8]
+      $output = zip($one,$two)
+      notice(inline_template('<%= @output.inspect %>'))
+      EOS
+
+      expect(apply_manifest(pp, :expect_failures => true).stderr).to match(/Requires array/)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/fixtures/dscacheutil/root	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+name: root
+password: *
+uid: 0
+gid: 0
+dir: /var/root
+shell: /bin/bash
+gecos: rawr Root
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/fixtures/lsuser/root	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,2 @@
+#name:home
+root:/root
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/abs_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe 'abs' do
+  it { is_expected.not_to eq(nil) }
+
+  describe 'signature validation in puppet3', :unless => RSpec.configuration.puppet_future do
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it {
+      pending("Current implementation ignores parameters after the first.")
+      is_expected.to run.with_params(1, 2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+    }
+  end
+
+  describe 'signature validation in puppet4', :if => RSpec.configuration.puppet_future do
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params().and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params(1, 2).and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params([]).and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params({}).and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params(true).and_raise_error(ArgumentError) }
+  end
+
+  it { is_expected.to run.with_params(-34).and_return(34) }
+  it { is_expected.to run.with_params("-34").and_return(34) }
+  it { is_expected.to run.with_params(34).and_return(34) }
+  it { is_expected.to run.with_params("34").and_return(34) }
+  it { is_expected.to run.with_params(-34.5).and_return(34.5) }
+  it { is_expected.to run.with_params("-34.5").and_return(34.5) }
+  it { is_expected.to run.with_params(34.5).and_return(34.5) }
+  it { is_expected.to run.with_params("34.5").and_return(34.5) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/any2array_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe "any2array" do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_return([]) }
+  it { is_expected.to run.with_params(true).and_return([true]) }
+  it { is_expected.to run.with_params('one').and_return(['one']) }
+  it { is_expected.to run.with_params('one', 'two').and_return(['one', 'two']) }
+  it { is_expected.to run.with_params([]).and_return([]) }
+  it { is_expected.to run.with_params(['one']).and_return(['one']) }
+  it { is_expected.to run.with_params(['one', 'two']).and_return(['one', 'two']) }
+  it { is_expected.to run.with_params({}).and_return([]) }
+  it { is_expected.to run.with_params({ 'key' => 'value' }).and_return(['key', 'value']) }
+  it { is_expected.to run.with_params({ 'key' => 'value' }).and_return(['key', 'value']) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/assert_private_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe 'assert_private' do
+  context 'when called from inside module' do
+    it "should not fail" do
+      scope.expects(:lookupvar).with('module_name').returns('foo')
+      scope.expects(:lookupvar).with('caller_module_name').returns('foo')
+      expect {
+        subject.call []
+      }.not_to raise_error
+    end
+  end
+
+  context "with an explicit failure message" do
+    it "prints the failure message on error" do
+      scope.expects(:lookupvar).with('module_name').returns('foo')
+      scope.expects(:lookupvar).with('caller_module_name').returns('bar')
+      expect {
+        subject.call ['failure message!']
+      }.to raise_error Puppet::ParseError, /failure message!/
+    end
+  end
+
+  context "when called from private class" do
+    it "should fail with a class error message" do
+      scope.expects(:lookupvar).with('module_name').returns('foo')
+      scope.expects(:lookupvar).with('caller_module_name').returns('bar')
+      scope.source.expects(:name).returns('foo::baz')
+      scope.source.expects(:type).returns('hostclass')
+      expect {
+        subject.call []
+      }.to raise_error Puppet::ParseError, /Class foo::baz is private/
+    end
+  end
+
+  context "when called from private definition" do
+    it "should fail with a class error message" do
+      scope.expects(:lookupvar).with('module_name').returns('foo')
+      scope.expects(:lookupvar).with('caller_module_name').returns('bar')
+      scope.source.expects(:name).returns('foo::baz')
+      scope.source.expects(:type).returns('definition')
+      expect {
+        subject.call []
+      }.to raise_error Puppet::ParseError, /Definition foo::baz is private/
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/base64_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe 'base64' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params("one").and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params("one", "two", "three").and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params("one", "two").and_raise_error(Puppet::ParseError, /first argument must be one of/) }
+  it { is_expected.to run.with_params("encode", ["two"]).and_raise_error(Puppet::ParseError, /second argument must be a string/) }
+  it { is_expected.to run.with_params("encode", 2).and_raise_error(Puppet::ParseError, /second argument must be a string/) }
+
+  it { is_expected.to run.with_params("encode", "thestring").and_return("dGhlc3RyaW5n\n") }
+  it { is_expected.to run.with_params("encode", "a very long string that will cause the base64 encoder to produce output with multiple lines").and_return("YSB2ZXJ5IGxvbmcgc3RyaW5nIHRoYXQgd2lsbCBjYXVzZSB0aGUgYmFzZTY0\nIGVuY29kZXIgdG8gcHJvZHVjZSBvdXRwdXQgd2l0aCBtdWx0aXBsZSBsaW5l\ncw==\n") }
+  it { is_expected.to run.with_params("decode", "dGhlc3RyaW5n").and_return("thestring") }
+  it { is_expected.to run.with_params("decode", "dGhlc3RyaW5n\n").and_return("thestring") }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/basename_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+describe 'basename' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('/path/to/a/file.ext', []).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('/path/to/a/file.ext').and_return('file.ext') }
+  it { is_expected.to run.with_params('relative_path/to/a/file.ext').and_return('file.ext') }
+  it { is_expected.to run.with_params('/path/to/a/file.ext', '.ext').and_return('file') }
+  it { is_expected.to run.with_params('relative_path/to/a/file.ext', '.ext').and_return('file') }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/bool2num_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe 'bool2num' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+
+  [ true, 'true', AlsoString.new('true') ].each do |truthy|
+    it { is_expected.to run.with_params(truthy).and_return(1) }
+  end
+
+  [ false, 'false', AlsoString.new('false') ].each do |falsey|
+    it { is_expected.to run.with_params(falsey).and_return(0) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/bool2str_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe 'bool2str' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  [ 'true', 'false', nil, :undef, ''].each do |invalid|
+    it { is_expected.to run.with_params(invalid).and_raise_error(Puppet::ParseError) }
+  end
+  it { is_expected.to run.with_params(true).and_return("true") }
+  it { is_expected.to run.with_params(false).and_return("false") }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/camelcase_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe 'camelcase' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(100).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params("abc").and_return("Abc") }
+  it { is_expected.to run.with_params("aa_bb_cc").and_return("AaBbCc") }
+  it { is_expected.to run.with_params("_aa__bb__cc_").and_return("AaBbCc") }
+  it { is_expected.to run.with_params("100").and_return("100") }
+  it { is_expected.to run.with_params("1_00").and_return("100") }
+  it { is_expected.to run.with_params("_").and_return("") }
+  it { is_expected.to run.with_params("").and_return("") }
+  it { is_expected.to run.with_params([]).and_return([]) }
+  it { is_expected.to run.with_params(["abc", "aa_bb_cc"]).and_return(["Abc", "AaBbCc"]) }
+  it { is_expected.to run.with_params(["abc", 1, "aa_bb_cc"]).and_return(["Abc", 1, "AaBbCc"]) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/capitalize_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe 'capitalize' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(100).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params("one").and_return("One") }
+  it { is_expected.to run.with_params("one two").and_return("One two") }
+  it { is_expected.to run.with_params("ONE TWO").and_return("One two") }
+
+  it { is_expected.to run.with_params(AlsoString.new("one")).and_return("One") }
+  it { is_expected.to run.with_params([]).and_return([]) }
+  it { is_expected.to run.with_params(["one", "two"]).and_return(["One", "Two"]) }
+  it { is_expected.to run.with_params(["one", 1, "two"]).and_return(["One", 1, "Two"]) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/ceiling_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+describe 'ceiling' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params("foo").and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(34).and_return(34) }
+  it { is_expected.to run.with_params(-34).and_return(-34) }
+  it { is_expected.to run.with_params(33.1).and_return(34) }
+  it { is_expected.to run.with_params(-33.1).and_return(-33) }
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/chomp_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe 'chomp' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params("a", "b").and_raise_error(Puppet::ParseError)
+  }
+  it { is_expected.to run.with_params("one").and_return("one") }
+  it { is_expected.to run.with_params("one\n").and_return("one") }
+  it { is_expected.to run.with_params("one\n\n").and_return("one\n") }
+  it { is_expected.to run.with_params(["one\n", "two", "three\n"]).and_return(["one", "two", "three"]) }
+
+  it { is_expected.to run.with_params(AlsoString.new("one")).and_return("one") }
+  it { is_expected.to run.with_params(AlsoString.new("one\n")).and_return("one") }
+  it { is_expected.to run.with_params(AlsoString.new("one\n\n")).and_return("one\n") }
+  it { is_expected.to run.with_params([AlsoString.new("one\n"), AlsoString.new("two"), "three\n"]).and_return(["one", "two", "three"]) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/chop_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe 'chop' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params("a", "b").and_raise_error(Puppet::ParseError)
+  }
+  it { is_expected.to run.with_params("one").and_return("on") }
+  it { is_expected.to run.with_params("one\n").and_return("one") }
+  it { is_expected.to run.with_params("one\n\n").and_return("one\n") }
+  it { is_expected.to run.with_params(["one\n", "two", "three\n"]).and_return(["one", "tw", "three"]) }
+
+  it { is_expected.to run.with_params(AlsoString.new("one")).and_return("on") }
+  it { is_expected.to run.with_params(AlsoString.new("one\n")).and_return("one") }
+  it { is_expected.to run.with_params(AlsoString.new("one\n\n")).and_return("one\n") }
+  it { is_expected.to run.with_params([AlsoString.new("one\n"), AlsoString.new("two"), "three\n"]).and_return(["one", "tw", "three"]) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/concat_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'concat' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([1]).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(1, [2]).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([1], [2], [3]).and_return([1, 2, 3]) }
+  it { is_expected.to run.with_params(['1','2','3'],['4','5','6']).and_return(['1','2','3','4','5','6']) }
+  it { is_expected.to run.with_params(['1','2','3'],'4').and_return(['1','2','3','4']) }
+  it { is_expected.to run.with_params(['1','2','3'],[['4','5'],'6']).and_return(['1','2','3',['4','5'],'6']) }
+  it { is_expected.to run.with_params(['1','2'],['3','4'],['5','6']).and_return(['1','2','3','4','5','6']) }
+  it { is_expected.to run.with_params(['1','2'],'3','4',['5','6']).and_return(['1','2','3','4','5','6']) }
+
+  it "should leave the original array intact" do
+    argument1 = ['1','2','3']
+    original1 = argument1.dup
+    argument2 = ['4','5','6']
+    original2 = argument2.dup
+    result = subject.call([argument1,argument2])
+    expect(argument1).to eq(original1)
+    expect(argument2).to eq(original2)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/convert_base_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'convert_base' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(ArgumentError) }
+  it { is_expected.to run.with_params("asdf").and_raise_error(ArgumentError) }
+  it { is_expected.to run.with_params("asdf","moo","cow").and_raise_error(ArgumentError) }
+  it { is_expected.to run.with_params(["1"],"2").and_raise_error(Puppet::ParseError, /argument must be either a string or an integer/) }
+  it { is_expected.to run.with_params("1",["2"]).and_raise_error(Puppet::ParseError, /argument must be either a string or an integer/) }
+  it { is_expected.to run.with_params("1",1).and_raise_error(Puppet::ParseError, /base must be at least 2 and must not be greater than 36/) }
+  it { is_expected.to run.with_params("1",37).and_raise_error(Puppet::ParseError, /base must be at least 2 and must not be greater than 36/) }
+
+  it "should raise a ParseError if argument 1 is a string that does not correspond to an integer in base 10" do
+    is_expected.to run.with_params("ten",6).and_raise_error(Puppet::ParseError, /argument must be an integer or a string corresponding to an integer in base 10/)
+  end
+
+  it "should raise a ParseError if argument 2 is a string and does not correspond to an integer in base 10" do
+    is_expected.to run.with_params(100,"hex").and_raise_error(Puppet::ParseError, /argument must be an integer or a string corresponding to an integer in base 10/)
+  end
+
+  it { is_expected.to run.with_params("11",'16').and_return('b') }
+  it { is_expected.to run.with_params("35",'36').and_return('z') }
+  it { is_expected.to run.with_params(5, 2).and_return('101') }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/count_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+describe 'count' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(ArgumentError) }
+  it { is_expected.to run.with_params("one").and_raise_error(ArgumentError) }
+  it { is_expected.to run.with_params("one", "two").and_return(1) }
+  it {
+    pending("should actually be like this, and not like above")
+    is_expected.to run.with_params("one", "two").and_raise_error(ArgumentError)
+  }
+  it { is_expected.to run.with_params("one", "two", "three").and_raise_error(ArgumentError) }
+  it { is_expected.to run.with_params(["one", "two", "three"]).and_return(3) }
+  it { is_expected.to run.with_params(["one", "two", "two"], "two").and_return(2) }
+  it { is_expected.to run.with_params(["one", nil, "two"]).and_return(2) }
+  it { is_expected.to run.with_params(["one", "", "two"]).and_return(2) }
+  it { is_expected.to run.with_params(["one", :undef, "two"]).and_return(2) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/deep_merge_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe 'deep_merge' do
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params({ 'key' => 'value' }).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params({}, '2').and_raise_error(Puppet::ParseError, /unexpected argument type String/) }
+  it { is_expected.to run.with_params({}, 2).and_raise_error(Puppet::ParseError, /unexpected argument type Fixnum/) }
+  it { is_expected.to run.with_params({}, '').and_return({}) }
+  it { is_expected.to run.with_params({}, {}).and_return({}) }
+  it { is_expected.to run.with_params({}, {}, {}).and_return({}) }
+  it { is_expected.to run.with_params({}, {}, {}, {}).and_return({}) }
+  it { is_expected.to run.with_params({'key' => 'value'}, '').and_return({'key' => 'value'}) }
+  it { is_expected.to run.with_params({'key1' => 'value1'}, {'key2' => 'value2' }).and_return({'key1' => 'value1', 'key2' => 'value2'}) }
+
+  describe 'when arguments have key collisions' do
+    it 'should prefer values from the last hash' do
+      is_expected.to run \
+        .with_params(
+          {'key1' => 'value1', 'key2' => 'value2' },
+          {'key2' => 'replacement_value', 'key3' => 'value3'}) \
+        .and_return(
+          {'key1' => 'value1', 'key2' => 'replacement_value', 'key3' => 'value3'})
+    end
+    it { is_expected.to run \
+      .with_params({'key1' => 'value1'}, {'key1' => 'value2'}, {'key1' => 'value3'}) \
+      .and_return({'key1' => 'value3' })
+    }
+  end
+
+  describe 'when arguments have subhashes' do
+    it { is_expected.to run \
+      .with_params({'key1' => 'value1'}, {'key2' => 'value2', 'key3' => {'subkey1' => 'value4'}}) \
+      .and_return( {'key1' => 'value1', 'key2' => 'value2', 'key3' => {'subkey1' => 'value4'}})
+    }
+    it { is_expected.to run \
+      .with_params({'key1' => {'subkey1' => 'value1'}}, {'key1' => {'subkey2' => 'value2'}}) \
+      .and_return( {'key1' => {'subkey1' => 'value1', 'subkey2' => 'value2'}})
+    }
+    it { is_expected.to run \
+      .with_params({'key1' => {'subkey1' => {'subsubkey1' => 'value1'}}}, {'key1' => {'subkey1' => {'subsubkey1' => 'value2'}}}) \
+      .and_return( {'key1' => {'subkey1' => {'subsubkey1' => 'value2'}}})
+    }
+  end
+
+  it 'should not change the original hashes' do
+    argument1 = { 'key1' => 'value1' }
+    original1 = argument1.dup
+    argument2 = { 'key2' => 'value2' }
+    original2 = argument2.dup
+
+    subject.call([argument1, argument2])
+    expect(argument1).to eq(original1)
+    expect(argument2).to eq(original2)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/defined_with_params_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe 'defined_with_params' do
+  describe 'when no resource is specified' do
+    it { is_expected.to run.with_params().and_raise_error(ArgumentError) }
+  end
+  describe 'when compared against a resource with no attributes' do
+    let :pre_condition do
+      'user { "dan": }'
+    end
+    it { is_expected.to run.with_params('User[dan]', {}).and_return(true) }
+    it { is_expected.to run.with_params('User[bob]', {}).and_return(false) }
+    it { is_expected.to run.with_params('User[dan]', {'foo' => 'bar'}).and_return(false) }
+  end
+
+  describe 'when compared against a resource with attributes' do
+    let :pre_condition do
+      'user { "dan": ensure => present, shell => "/bin/csh", managehome => false}'
+    end
+    it { is_expected.to run.with_params('User[dan]', {}).and_return(true) }
+    it { is_expected.to run.with_params('User[dan]', '').and_return(true) }
+    it { is_expected.to run.with_params('User[dan]', {'ensure' => 'present'}).and_return(true) }
+    it { is_expected.to run.with_params('User[dan]', {'ensure' => 'present', 'managehome' => false}).and_return(true) }
+    it { is_expected.to run.with_params('User[dan]', {'ensure' => 'absent', 'managehome' => false}).and_return(false) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/delete_at_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe 'delete_at' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one', 1).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(1, 1).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(['one'], 'two').and_raise_error(Puppet::ParseError) }
+  it {
+    pending("Current implementation ignores parameters after the first two.")
+    is_expected.to run.with_params(['one'], 0, 1).and_raise_error(Puppet::ParseError)
+  }
+
+  describe 'argument validation' do
+    it { is_expected.to run.with_params([0, 1, 2], 3).and_raise_error(Puppet::ParseError) }
+  end
+
+  it { is_expected.to run.with_params([0, 1, 2], 1).and_return([0, 2]) }
+  it { is_expected.to run.with_params([0, 1, 2], -1).and_return([0, 1]) }
+  it { is_expected.to run.with_params([0, 1, 2], -4).and_return([0, 1, 2]) }
+
+  it "should leave the original array intact" do
+    argument = [1, 2, 3]
+    original = argument.dup
+    result = subject.call([argument,2])
+    expect(argument).to eq(original)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/delete_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,67 @@
+require 'spec_helper'
+
+describe 'delete' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([], 'two', 'three').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(1, 'two').and_raise_error(TypeError) }
+
+  describe 'deleting from an array' do
+    it { is_expected.to run.with_params([], '').and_return([]) }
+    it { is_expected.to run.with_params([], 'two').and_return([]) }
+    it { is_expected.to run.with_params(['two'], 'two').and_return([]) }
+    it { is_expected.to run.with_params(['two', 'two'], 'two').and_return([]) }
+    it { is_expected.to run.with_params(['one', 'two', 'three'], 'four').and_return(['one', 'two', 'three']) }
+    it { is_expected.to run.with_params(['one', 'two', 'three'], 'two').and_return(['one', 'three']) }
+    it { is_expected.to run.with_params(['two', 'one', 'two', 'three', 'two'], 'two').and_return(['one', 'three']) }
+    it { is_expected.to run.with_params(['one', 'two', 'three', 'two'], ['one', 'two']).and_return(['three']) }
+  end
+
+  describe 'deleting from a string' do
+    it { is_expected.to run.with_params('', '').and_return('') }
+    it { is_expected.to run.with_params('bar', '').and_return('bar') }
+    it { is_expected.to run.with_params('', 'bar').and_return('') }
+    it { is_expected.to run.with_params('bar', 'bar').and_return('') }
+    it { is_expected.to run.with_params('barbar', 'bar').and_return('') }
+    it { is_expected.to run.with_params('barfoobar', 'bar').and_return('foo') }
+    it { is_expected.to run.with_params('foobarbabarz', 'bar').and_return('foobaz') }
+    it { is_expected.to run.with_params('foobarbabarz', ['foo', 'bar']).and_return('baz') }
+    # this is so sick
+    it { is_expected.to run.with_params('barfoobar', ['barbar', 'foo']).and_return('barbar') }
+    it { is_expected.to run.with_params('barfoobar', ['foo', 'barbar']).and_return('') }
+  end
+
+  describe 'deleting from an array' do
+    it { is_expected.to run.with_params({}, '').and_return({}) }
+    it { is_expected.to run.with_params({}, 'key').and_return({}) }
+    it { is_expected.to run.with_params({'key' => 'value'}, 'key').and_return({}) }
+    it { is_expected.to run \
+      .with_params({'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}, 'key2') \
+      .and_return( {'key1' => 'value1', 'key3' => 'value3'})
+    }
+    it { is_expected.to run \
+      .with_params({'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}, ['key1', 'key2']) \
+      .and_return( {'key3' => 'value3'})
+    }
+  end
+
+  it "should leave the original array intact" do
+    argument1 = ['one','two','three']
+    original1 = argument1.dup
+    result = subject.call([argument1,'two'])
+    expect(argument1).to eq(original1)
+  end
+  it "should leave the original string intact" do
+    argument1 = 'onetwothree'
+    original1 = argument1.dup
+    result = subject.call([argument1,'two'])
+    expect(argument1).to eq(original1)
+  end
+  it "should leave the original hash intact" do
+    argument1 = {'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'}
+    original1 = argument1.dup
+    result = subject.call([argument1,'key2'])
+    expect(argument1).to eq(original1)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/delete_undef_values_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+describe 'delete_undef_values' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError) }
+
+  describe 'when deleting from an array' do
+    [ :undef, '', nil ].each do |undef_value|
+      describe "when undef is represented by #{undef_value.inspect}" do
+        before do
+          pending("review behaviour when being passed undef as #{undef_value.inspect}") if undef_value == ''
+          pending("review behaviour when being passed undef as #{undef_value.inspect}") if undef_value == nil
+        end
+        it { is_expected.to run.with_params([undef_value]).and_return([]) }
+        it { is_expected.to run.with_params(['one',undef_value,'two','three']).and_return(['one','two','three']) }
+      end
+
+      it "should leave the original argument intact" do
+        argument = ['one',undef_value,'two']
+        original = argument.dup
+        result = subject.call([argument,2])
+        expect(argument).to eq(original)
+      end
+    end
+
+    it { is_expected.to run.with_params(['undef']).and_return(['undef']) }
+  end
+
+  describe 'when deleting from a hash' do
+    [ :undef, '', nil ].each do |undef_value|
+      describe "when undef is represented by #{undef_value.inspect}" do
+        before do
+          pending("review behaviour when being passed undef as #{undef_value.inspect}") if undef_value == ''
+          pending("review behaviour when being passed undef as #{undef_value.inspect}") if undef_value == nil
+        end
+        it { is_expected.to run.with_params({'key' => undef_value}).and_return({}) }
+        it { is_expected.to run \
+          .with_params({'key1' => 'value1', 'undef_key' => undef_value, 'key2' => 'value2'}) \
+          .and_return({'key1' => 'value1', 'key2' => 'value2'})
+        }
+      end
+
+      it "should leave the original argument intact" do
+        argument = { 'key1' => 'value1', 'key2' => undef_value }
+        original = argument.dup
+        result = subject.call([argument,2])
+        expect(argument).to eq(original)
+      end
+    end
+
+    it { is_expected.to run.with_params({'key' => 'undef'}).and_return({'key' => 'undef'}) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/delete_values_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe 'delete_values' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError) }
+  describe 'when the first argument is not a hash' do
+    it { is_expected.to run.with_params(1, 'two').and_raise_error(TypeError) }
+    it { is_expected.to run.with_params('one', 'two').and_raise_error(TypeError) }
+    it { is_expected.to run.with_params([], 'two').and_raise_error(TypeError) }
+  end
+
+  describe 'when deleting from a hash' do
+    it { is_expected.to run.with_params({}, 'value').and_return({}) }
+    it { is_expected.to run \
+      .with_params({'key1' => 'value1'}, 'non-existing value') \
+      .and_return({'key1' => 'value1'})
+    }
+    it { is_expected.to run \
+      .with_params({'key1' => 'value1', 'key2' => 'value to delete'}, 'value to delete') \
+      .and_return({'key1' => 'value1'})
+    }
+    it { is_expected.to run \
+      .with_params({'key1' => 'value1', 'key2' => 'value to delete', 'key3' => 'value to delete'}, 'value to delete') \
+      .and_return({'key1' => 'value1'})
+    }
+  end
+
+  it "should leave the original argument intact" do
+    argument = { 'key1' => 'value1', 'key2' => 'value2' }
+    original = argument.dup
+    result = subject.call([argument, 'value2'])
+    expect(argument).to eq(original)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/difference_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe 'difference' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one', []).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([], 'two').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params({}, {}).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([], []).and_return([]) }
+  it { is_expected.to run.with_params([], ['one']).and_return([]) }
+  it { is_expected.to run.with_params(['one'], ['one']).and_return([]) }
+  it { is_expected.to run.with_params(['one'], []).and_return(['one']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'three']).and_return(['one']) }
+  it { is_expected.to run.with_params(['one', 'two', 'two', 'three'], ['two', 'three']).and_return(['one']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'two', 'three']).and_return(['one']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'three', 'four']).and_return(['one']) }
+  it 'should not confuse types' do is_expected.to run.with_params(['1', '2', '3'], [1, 2]).and_return(['1', '2', '3']) end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/dirname_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+describe 'dirname' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('/path/to/a/file.ext', []).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('/path/to/a/file.ext').and_return('/path/to/a') }
+  it { is_expected.to run.with_params('relative_path/to/a/file.ext').and_return('relative_path/to/a') }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/dos2unix_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe 'dos2unix' do
+  context 'Checking parameter validity' do
+    it { is_expected.not_to eq(nil) }
+    it do
+      is_expected.to run.with_params.and_raise_error(ArgumentError, /Wrong number of arguments/)
+    end
+    it do
+      is_expected.to run.with_params('one', 'two').and_raise_error(ArgumentError, /Wrong number of arguments/)
+    end
+    it do
+      is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError)
+    end
+    it do
+      is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError)
+    end
+    it do
+      is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError)
+    end
+  end
+
+  context 'Converting from dos to unix format' do
+    sample_text    = "Hello\r\nWorld\r\n"
+    desired_output = "Hello\nWorld\n"
+
+    it 'should output unix format' do
+      should run.with_params(sample_text).and_return(desired_output)
+    end
+  end
+
+  context 'Converting from unix to unix format' do
+    sample_text    = "Hello\nWorld\n"
+    desired_output = "Hello\nWorld\n"
+
+    it 'should output unix format' do
+      should run.with_params(sample_text).and_return(desired_output)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/downcase_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe 'downcase' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(100).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params("abc").and_return("abc") }
+  it { is_expected.to run.with_params("Abc").and_return("abc") }
+  it { is_expected.to run.with_params("ABC").and_return("abc") }
+
+  it { is_expected.to run.with_params(AlsoString.new("ABC")).and_return("abc") }
+  it { is_expected.to run.with_params([]).and_return([]) }
+  it { is_expected.to run.with_params(["ONE", "TWO"]).and_return(["one", "two"]) }
+  it { is_expected.to run.with_params(["One", 1, "Two"]).and_return(["one", 1, "two"]) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/empty_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe 'empty' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(0).and_raise_error(Puppet::ParseError) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError)
+  }
+  it { is_expected.to run.with_params('').and_return(true) }
+  it { is_expected.to run.with_params('one').and_return(false) }
+
+  it { is_expected.to run.with_params(AlsoString.new('')).and_return(true) }
+  it { is_expected.to run.with_params(AlsoString.new('one')).and_return(false) }
+
+  it { is_expected.to run.with_params([]).and_return(true) }
+  it { is_expected.to run.with_params(['one']).and_return(false) }
+
+  it { is_expected.to run.with_params({}).and_return(true) }
+  it { is_expected.to run.with_params({'key' => 'value'}).and_return(false) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/ensure_packages_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+require 'spec_helper'
+
+describe 'ensure_packages' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it {
+    pending("should not accept numbers as arguments")
+    is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError)
+  }
+  it {
+    pending("should not accept numbers as arguments")
+    is_expected.to run.with_params(["packagename", 1]).and_raise_error(Puppet::ParseError)
+  }
+  it { is_expected.to run.with_params("packagename") }
+  it { is_expected.to run.with_params(["packagename1", "packagename2"]) }
+
+  context 'given a catalog with "package { puppet: ensure => absent }"' do
+    let(:pre_condition) { 'package { puppet: ensure => absent }' }
+
+    describe 'after running ensure_package("facter")' do
+      before { subject.call(['facter']) }
+
+      # this lambda is required due to strangeness within rspec-puppet's expectation handling
+      it { expect(lambda { catalogue }).to contain_package('puppet').with_ensure('absent') }
+      it { expect(lambda { catalogue }).to contain_package('facter').with_ensure('present') }
+    end
+
+    describe 'after running ensure_package("facter", { "provider" => "gem" })' do
+      before { subject.call(['facter', { "provider" => "gem" }]) }
+
+      # this lambda is required due to strangeness within rspec-puppet's expectation handling
+      it { expect(lambda { catalogue }).to contain_package('puppet').with_ensure('absent').without_provider() }
+      it { expect(lambda { catalogue }).to contain_package('facter').with_ensure('present').with_provider("gem") }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/ensure_resource_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe 'ensure_resource' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(ArgumentError, /Must specify a type/) }
+  it { is_expected.to run.with_params('type').and_raise_error(ArgumentError, /Must specify a title/) }
+  it { is_expected.to run.with_params('type', 'title', {}, 'extras').and_raise_error(Puppet::ParseError) }
+  it {
+    pending("should not accept numbers as arguments")
+    is_expected.to run.with_params(1,2,3).and_raise_error(Puppet::ParseError)
+  }
+
+  context 'given a catalog with "user { username1: ensure => present }"' do
+    let(:pre_condition) { 'user { username1: ensure => present }' }
+
+    describe 'after running ensure_resource("user", "username1", {})' do
+      before { subject.call(['User', 'username1', {}]) }
+
+      # this lambda is required due to strangeness within rspec-puppet's expectation handling
+      it { expect(lambda { catalogue }).to contain_user('username1').with_ensure('present') }
+    end
+
+    describe 'after running ensure_resource("user", "username2", {})' do
+      before { subject.call(['User', 'username2', {}]) }
+
+      # this lambda is required due to strangeness within rspec-puppet's expectation handling
+      it { expect(lambda { catalogue }).to contain_user('username1').with_ensure('present') }
+      it { expect(lambda { catalogue }).to contain_user('username2').without_ensure }
+    end
+
+    describe 'after running ensure_resource("user", ["username1", "username2"], {})' do
+      before { subject.call(['User', ['username1', 'username2'], {}]) }
+
+      # this lambda is required due to strangeness within rspec-puppet's expectation handling
+      it { expect(lambda { catalogue }).to contain_user('username1').with_ensure('present') }
+      it { expect(lambda { catalogue }).to contain_user('username2').without_ensure }
+    end
+
+    describe 'when providing already set params' do
+      let(:params) { { 'ensure' => 'present' } }
+      before { subject.call(['User', ['username2', 'username3'], params]) }
+
+      # this lambda is required due to strangeness within rspec-puppet's expectation handling
+      it { expect(lambda { catalogue }).to contain_user('username1').with(params) }
+      it { expect(lambda { catalogue }).to contain_user('username2').with(params) }
+    end
+
+    context 'when trying to add params' do
+      it { is_expected.to run \
+        .with_params('User', 'username1', { 'ensure' => 'present', 'shell' => true }) \
+        .and_raise_error(Puppet::Resource::Catalog::DuplicateResourceError, /User\[username1\] is already declared/)
+      }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/flatten_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe 'flatten' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([], []).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([]).and_return([]) }
+  it { is_expected.to run.with_params(['one']).and_return(['one']) }
+  it { is_expected.to run.with_params([['one']]).and_return(['one']) }
+  it { is_expected.to run.with_params(["a","b","c","d","e","f","g"]).and_return(["a","b","c","d","e","f","g"]) }
+  it { is_expected.to run.with_params([["a","b",["c",["d","e"],"f","g"]]]).and_return(["a","b","c","d","e","f","g"]) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/floor_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+require 'spec_helper'
+
+describe 'floor' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params("foo").and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params(34).and_return(34) }
+  it { is_expected.to run.with_params(-34).and_return(-34) }
+  it { is_expected.to run.with_params(33.1).and_return(33) }
+  it { is_expected.to run.with_params(-33.1).and_return(-34) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/fqdn_rand_string_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,65 @@
+require 'spec_helper'
+
+describe 'fqdn_rand_string' do
+  let(:default_charset) { %r{\A[a-zA-Z0-9]{100}\z} }
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(ArgumentError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(0).and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+  it { is_expected.to run.with_params(1.5).and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+  it { is_expected.to run.with_params(-10).and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+  it { is_expected.to run.with_params("-10").and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+  it { is_expected.to run.with_params("string").and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+  it { is_expected.to run.with_params([]).and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+  it { is_expected.to run.with_params({}).and_raise_error(ArgumentError, /first argument must be a positive integer/) }
+  it { is_expected.to run.with_params(1, 1).and_raise_error(ArgumentError, /second argument must be undef or a string/) }
+  it { is_expected.to run.with_params(1, []).and_raise_error(ArgumentError, /second argument must be undef or a string/) }
+  it { is_expected.to run.with_params(1, {}).and_raise_error(ArgumentError, /second argument must be undef or a string/) }
+  it { is_expected.to run.with_params(100).and_return(default_charset) }
+  it { is_expected.to run.with_params("100").and_return(default_charset) }
+  it { is_expected.to run.with_params(100, nil).and_return(default_charset) }
+  it { is_expected.to run.with_params(100, '').and_return(default_charset) }
+  it { is_expected.to run.with_params(100, 'a').and_return(/\Aa{100}\z/) }
+  it { is_expected.to run.with_params(100, 'ab').and_return(/\A[ab]{100}\z/) }
+
+  it "provides the same 'random' value on subsequent calls for the same host" do
+    expect(fqdn_rand_string(10)).to eql(fqdn_rand_string(10))
+  end
+
+  it "considers the same host and same extra arguments to have the same random sequence" do
+    first_random = fqdn_rand_string(10, :extra_identifier => [1, "same", "host"])
+    second_random = fqdn_rand_string(10, :extra_identifier => [1, "same", "host"])
+
+    expect(first_random).to eql(second_random)
+  end
+
+  it "allows extra arguments to control the random value on a single host" do
+    first_random = fqdn_rand_string(10, :extra_identifier => [1, "different", "host"])
+    second_different_random = fqdn_rand_string(10, :extra_identifier => [2, "different", "host"])
+
+    expect(first_random).not_to eql(second_different_random)
+  end
+
+  it "should return different strings for different hosts" do
+    val1 = fqdn_rand_string(10, :host => "first.host.com")
+    val2 = fqdn_rand_string(10, :host => "second.host.com")
+
+    expect(val1).not_to eql(val2)
+  end
+
+  def fqdn_rand_string(max, args = {})
+    host = args[:host] || '127.0.0.1'
+    charset = args[:charset]
+    extra = args[:extra_identifier] || []
+
+    # workaround not being able to use let(:facts) because some tests need
+    # multiple different hostnames in one context
+    scope.stubs(:lookupvar).with("::fqdn", {}).returns(host)
+
+    function_args = [max]
+    if args.has_key?(:charset) or !extra.empty?
+      function_args << charset
+    end
+    function_args += extra
+    scope.function_fqdn_rand_string(function_args)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/fqdn_rotate_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,75 @@
+require 'spec_helper'
+
+describe 'fqdn_rotate' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(0).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+  it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+  it { is_expected.to run.with_params('').and_return('') }
+  it { is_expected.to run.with_params('a').and_return('a') }
+
+  it { is_expected.to run.with_params([]).and_return([]) }
+  it { is_expected.to run.with_params(['a']).and_return(['a']) }
+
+  it "should rotate a string and the result should be the same size" do
+    expect(fqdn_rotate("asdf").size).to eq(4)
+  end
+
+  it "should rotate a string to give the same results for one host" do
+    val1 = fqdn_rotate("abcdefg", :host => 'one')
+    val2 = fqdn_rotate("abcdefg", :host => 'one')
+    expect(val1).to eq(val2)
+  end
+
+  it "allows extra arguments to control the random rotation on a single host" do
+    val1 = fqdn_rotate("abcdefg", :extra_identifier => [1, "different", "host"])
+    val2 = fqdn_rotate("abcdefg", :extra_identifier => [2, "different", "host"])
+    expect(val1).not_to eq(val2)
+  end
+
+  it "considers the same host and same extra arguments to have the same random rotation" do
+    val1 = fqdn_rotate("abcdefg", :extra_identifier => [1, "same", "host"])
+    val2 = fqdn_rotate("abcdefg", :extra_identifier => [1, "same", "host"])
+    expect(val1).to eq(val2)
+  end
+
+  it "should rotate a string to give different values on different hosts" do
+    val1 = fqdn_rotate("abcdefg", :host => 'one')
+    val2 = fqdn_rotate("abcdefg", :host => 'two')
+    expect(val1).not_to eq(val2)
+  end
+
+  it "should accept objects which extend String" do
+    result = fqdn_rotate(AlsoString.new('asdf'))
+    expect(result).to eq('dfas')
+  end
+
+  it "should use the Puppet::Util.deterministic_rand function" do
+    if Puppet::Util.respond_to?(:deterministic_rand)
+      Puppet::Util.expects(:deterministic_rand).with(44489829212339698569024999901561968770,4)
+      fqdn_rotate("asdf")
+    else
+      skip 'Puppet::Util#deterministic_rand not available'
+    end
+  end
+
+  it "should not leave the global seed in a deterministic state" do
+    fqdn_rotate("asdf")
+    rand1 = rand()
+    fqdn_rotate("asdf")
+    rand2 = rand()
+    expect(rand1).not_to eql(rand2)
+  end
+
+  def fqdn_rotate(value, args = {})
+    host = args[:host] || '127.0.0.1'
+    extra = args[:extra_identifier] || []
+
+    # workaround not being able to use let(:facts) because some tests need
+    # multiple different hostnames in one context
+    scope.stubs(:lookupvar).with("::fqdn").returns(host)
+
+    function_args = [value] + extra
+    scope.function_fqdn_rotate(function_args)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/get_module_path_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,52 @@
+require 'spec_helper'
+
+describe 'get_module_path' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) }
+  it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) }
+  it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) }
+  if Puppet.version.to_f >= 4.0
+    it { is_expected.to run.with_params('one').and_raise_error(Puppet::Environments::EnvironmentNotFound, /Could not find a directory environment/) }
+  else
+    it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /Could not find module/) }
+  end
+
+  class StubModule
+    attr_reader :path
+    def initialize(path)
+      @path = path
+    end
+  end
+
+  describe 'when locating a module' do
+    let(:modulepath) { "/tmp/does_not_exist" }
+    let(:path_of_module_foo) { StubModule.new("/tmp/does_not_exist/foo") }
+
+    before(:each) { Puppet[:modulepath] = modulepath }
+
+    context 'in the default environment' do
+      before(:each) { Puppet::Module.expects(:find).with('foo', 'rp_env').returns(path_of_module_foo) }
+
+      it { is_expected.to run.with_params('foo').and_return(path_of_module_foo.path) }
+
+      context 'when the modulepath is a list' do
+        before(:each) { Puppet[:modulepath] = modulepath + 'tmp/something_else' }
+
+        it { is_expected.to run.with_params('foo').and_return(path_of_module_foo.path) }
+      end
+    end
+
+    context 'in a non-default default environment' do
+      let(:environment) { 'test' }
+      before(:each) { Puppet::Module.expects(:find).with('foo', 'test').returns(path_of_module_foo) }
+
+      it { is_expected.to run.with_params('foo').and_return(path_of_module_foo.path) }
+
+      context 'when the modulepath is a list' do
+        before(:each) { Puppet[:modulepath] = modulepath + 'tmp/something_else' }
+
+        it { is_expected.to run.with_params('foo').and_return(path_of_module_foo.path) }
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/getparam_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe 'getparam' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(ArgumentError, /Must specify a reference/) }
+  it { is_expected.to run.with_params('User[one]').and_raise_error(ArgumentError, /Must specify name of a parameter/) }
+  it { is_expected.to run.with_params('User[one]', 2).and_raise_error(ArgumentError, /Must specify name of a parameter/) }
+  it { is_expected.to run.with_params('User[one]', []).and_raise_error(ArgumentError, /Must specify name of a parameter/) }
+  it { is_expected.to run.with_params('User[one]', {}).and_raise_error(ArgumentError, /Must specify name of a parameter/) }
+
+  describe 'when compared against a user resource with no params' do
+    let(:pre_condition) { 'user { "one": }' }
+
+    it { is_expected.to run.with_params('User[one]', 'ensure').and_return('') }
+    it { is_expected.to run.with_params('User[two]', 'ensure').and_return('') }
+    it { is_expected.to run.with_params('User[one]', 'shell').and_return('') }
+  end
+
+  describe 'when compared against a user resource with params' do
+    let(:pre_condition) { 'user { "one": ensure => present, shell => "/bin/sh", managehome => false, }' }
+
+    it { is_expected.to run.with_params('User[one]', 'ensure').and_return('present') }
+    it { is_expected.to run.with_params('User[two]', 'ensure').and_return('') }
+    it { is_expected.to run.with_params('User[one]', 'shell').and_return('/bin/sh') }
+    it {
+      pending("both rspec-puppet as well as the function do the wrong thing here.")
+      is_expected.to run.with_params('User[one]', 'managehome').and_return(false)
+    }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/getvar_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe 'getvar' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+  context 'given variables in namespaces' do
+    let(:pre_condition) {
+      <<-'ENDofPUPPETcode'
+      class site::data { $foo = 'baz' }
+      include site::data
+      ENDofPUPPETcode
+    }
+
+    it { is_expected.to run.with_params('site::data::foo').and_return('baz') }
+    it { is_expected.to run.with_params('::site::data::foo').and_return('baz') }
+    it { is_expected.to run.with_params('::site::data::bar').and_return(nil) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/grep_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe 'grep' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("grep does not actually check this, and raises NoMethodError instead")
+    is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, /first argument not an array/)
+  }
+  it {
+    pending("grep does not actually check this, and raises NoMethodError instead")
+    is_expected.to run.with_params(1, 'two').and_raise_error(Puppet::ParseError, /first argument not an array/)
+  }
+  it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params([], 'two').and_return([]) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], 'two').and_return(['two']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], 't(wo|hree)').and_return(['two', 'three']) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/has_interface_with_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe 'has_interface_with' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params("one", "two", "three").and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+  # We need to mock out the Facts so we can specify how we expect this function
+  # to behave on different platforms.
+  context "On Mac OS X Systems" do
+    let(:facts) { { :interfaces => 'lo0,gif0,stf0,en1,p2p0,fw0,en0,vmnet1,vmnet8,utun0' } }
+    it { is_expected.to run.with_params('lo0').and_return(true) }
+    it { is_expected.to run.with_params('lo').and_return(false) }
+  end
+
+  context "On Linux Systems" do
+    let(:facts) do
+      {
+        :interfaces => 'eth0,lo',
+        :ipaddress => '10.0.0.1',
+        :ipaddress_lo => '127.0.0.1',
+        :ipaddress_eth0 => '10.0.0.1',
+        :muppet => 'kermit',
+        :muppet_lo => 'mspiggy',
+        :muppet_eth0 => 'kermit',
+      }
+    end
+
+    it { is_expected.to run.with_params('lo').and_return(true) }
+    it { is_expected.to run.with_params('lo0').and_return(false) }
+    it { is_expected.to run.with_params('ipaddress', '127.0.0.1').and_return(true) }
+    it { is_expected.to run.with_params('ipaddress', '10.0.0.1').and_return(true) }
+    it { is_expected.to run.with_params('ipaddress', '8.8.8.8').and_return(false) }
+    it { is_expected.to run.with_params('muppet', 'kermit').and_return(true) }
+    it { is_expected.to run.with_params('muppet', 'mspiggy').and_return(true) }
+    it { is_expected.to run.with_params('muppet', 'bigbird').and_return(false) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/has_ip_address_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe 'has_ip_address' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params("one", "two").and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+  context "On Linux Systems" do
+    let(:facts) do
+      {
+        :interfaces => 'eth0,lo',
+        :ipaddress => '10.0.0.1',
+        :ipaddress_lo => '127.0.0.1',
+        :ipaddress_eth0 => '10.0.0.1',
+      }
+    end
+
+    it { is_expected.to run.with_params('127.0.0.1').and_return(true) }
+    it { is_expected.to run.with_params('10.0.0.1').and_return(true) }
+    it { is_expected.to run.with_params('8.8.8.8').and_return(false) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/has_ip_network_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe 'has_ip_network' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params("one", "two").and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+  context "On Linux Systems" do
+    let(:facts) do
+      {
+        :interfaces => 'eth0,lo',
+        :network => :undefined,
+        :network_lo => '127.0.0.0',
+        :network_eth0 => '10.0.0.0',
+      }
+    end
+
+    it { is_expected.to run.with_params('127.0.0.0').and_return(true) }
+    it { is_expected.to run.with_params('10.0.0.0').and_return(true) }
+    it { is_expected.to run.with_params('8.8.8.0').and_return(false) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/has_key_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe 'has_key' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params("one").and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params("one", "two", "three").and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params("one", "two").and_raise_error(Puppet::ParseError, /expects the first argument to be a hash/) }
+  it { is_expected.to run.with_params(1, "two").and_raise_error(Puppet::ParseError, /expects the first argument to be a hash/) }
+  it { is_expected.to run.with_params([], "two").and_raise_error(Puppet::ParseError, /expects the first argument to be a hash/) }
+
+  it { is_expected.to run.with_params({ 'key' => 'value' }, "key").and_return(true) }
+  it { is_expected.to run.with_params({}, "key").and_return(false) }
+  it { is_expected.to run.with_params({ 'key' => 'value'}, "not a key").and_return(false) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/hash_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe 'hash' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params([], 'two').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params(['one']).and_raise_error(Puppet::ParseError, /Unable to compute/) }
+  it { is_expected.to run.with_params([]).and_return({}) }
+  it { is_expected.to run.with_params(['key1', 'value1']).and_return({ 'key1' => 'value1' }) }
+  it { is_expected.to run.with_params(['key1', 'value1', 'key2', 'value2']).and_return({ 'key1' => 'value1', 'key2' => 'value2' }) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/intersection_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe 'intersection' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one', 'two', 'three').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params('one', []).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([], 'two').and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params({}, {}).and_raise_error(Puppet::ParseError) }
+  it { is_expected.to run.with_params([], []).and_return([]) }
+  it { is_expected.to run.with_params([], ['one']).and_return([]) }
+  it { is_expected.to run.with_params(['one'], []).and_return([]) }
+  it { is_expected.to run.with_params(['one'], ['one']).and_return(['one']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'three']).and_return(['two', 'three']) }
+  it { is_expected.to run.with_params(['one', 'two', 'two', 'three'], ['two', 'three']).and_return(['two', 'three']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'two', 'three']).and_return(['two', 'three']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'three', 'four']).and_return(['two', 'three']) }
+  it 'should not confuse types' do is_expected.to run.with_params(['1', '2', '3'], [1, 2]).and_return([]) end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/is_array_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe 'is_array' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params([], []).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params([]).and_return(true) }
+  it { is_expected.to run.with_params(['one']).and_return(true) }
+  it { is_expected.to run.with_params([1]).and_return(true) }
+  it { is_expected.to run.with_params([{}]).and_return(true) }
+  it { is_expected.to run.with_params([[]]).and_return(true) }
+  it { is_expected.to run.with_params('').and_return(false) }
+  it { is_expected.to run.with_params('one').and_return(false) }
+  it { is_expected.to run.with_params(1).and_return(false) }
+  it { is_expected.to run.with_params({}).and_return(false) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/is_bool_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe 'is_bool' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(true, false).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(true).and_return(true) }
+  it { is_expected.to run.with_params(false).and_return(true) }
+  it { is_expected.to run.with_params([1]).and_return(false) }
+  it { is_expected.to run.with_params([{}]).and_return(false) }
+  it { is_expected.to run.with_params([[]]).and_return(false) }
+  it { is_expected.to run.with_params([true]).and_return(false) }
+  it { is_expected.to run.with_params('true').and_return(false) }
+  it { is_expected.to run.with_params('false').and_return(false) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/is_domain_name_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe 'is_domain_name' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(1).and_return(false) }
+  it { is_expected.to run.with_params([]).and_return(false) }
+  it { is_expected.to run.with_params({}).and_return(false) }
+  it { is_expected.to run.with_params('').and_return(false) }
+  it { is_expected.to run.with_params('.').and_return(true) }
+  it { is_expected.to run.with_params('com').and_return(true) }
+  it { is_expected.to run.with_params('com.').and_return(true) }
+  it { is_expected.to run.with_params('x.com').and_return(true) }
+  it { is_expected.to run.with_params('x.com.').and_return(true) }
+  it { is_expected.to run.with_params('foo.example.com').and_return(true) }
+  it { is_expected.to run.with_params('foo.example.com.').and_return(true) }
+  it { is_expected.to run.with_params('2foo.example.com').and_return(true) }
+  it { is_expected.to run.with_params('2foo.example.com.').and_return(true) }
+  it { is_expected.to run.with_params('www.2foo.example.com').and_return(true) }
+  it { is_expected.to run.with_params('www.2foo.example.com.').and_return(true) }
+  describe 'inputs with spaces' do
+    it { is_expected.to run.with_params('invalid domain').and_return(false) }
+  end
+  describe 'inputs with hyphens' do
+    it { is_expected.to run.with_params('foo-bar.example.com').and_return(true) }
+    it { is_expected.to run.with_params('foo-bar.example.com.').and_return(true) }
+    it { is_expected.to run.with_params('www.foo-bar.example.com').and_return(true) }
+    it { is_expected.to run.with_params('www.foo-bar.example.com.').and_return(true) }
+    it { is_expected.to run.with_params('-foo.example.com').and_return(false) }
+    it { is_expected.to run.with_params('-foo.example.com').and_return(false) }
+  end
+  # Values obtained from Facter values will be frozen strings
+  # in newer versions of Facter:
+  it { is_expected.to run.with_params('www.example.com'.freeze).and_return(true) }
+  describe 'top level domain must be alphabetic if there are multiple labels' do
+    it { is_expected.to run.with_params('2com').and_return(true) }
+    it { is_expected.to run.with_params('www.example.2com').and_return(false) }
+  end
+  describe 'IP addresses are not domain names' do
+    it { is_expected.to run.with_params('192.168.1.1').and_return(false) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/is_float_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe 'is_float' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(0.1, 0.2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+  describe 'passing a string' do
+    it { is_expected.to run.with_params('0.1').and_return(true) }
+    it { is_expected.to run.with_params('1.0').and_return(true) }
+    it { is_expected.to run.with_params('1').and_return(false) }
+    it { is_expected.to run.with_params('one').and_return(false) }
+    it { is_expected.to run.with_params('one 1.0').and_return(false) }
+    it { is_expected.to run.with_params('1.0 one').and_return(false) }
+  end
+
+  describe 'passing numbers' do
+    it { is_expected.to run.with_params(0.1).and_return(true) }
+    it { is_expected.to run.with_params(1.0).and_return(true) }
+    it { is_expected.to run.with_params(1).and_return(false) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/is_function_available.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+require 'spec_helper'
+
+describe 'is_function_available' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('include').and_return(true) }
+  it { is_expected.to run.with_params('no_such_function').and_return(false) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/is_hash_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe 'is_hash' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params({}, {}).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('').and_return(false) }
+  it { is_expected.to run.with_params({}).and_return(true) }
+  it { is_expected.to run.with_params([]).and_return(false) }
+  it { is_expected.to run.with_params(1).and_return(false) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/is_integer_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe 'is_integer' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(1, 2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+  it { is_expected.to run.with_params(3).and_return(true) }
+  it { is_expected.to run.with_params('3').and_return(true) }
+  it { is_expected.to run.with_params(-3).and_return(true) }
+  it { is_expected.to run.with_params('-3').and_return(true) }
+  
+  it { is_expected.to run.with_params(3.7).and_return(false) }
+  it { is_expected.to run.with_params('3.7').and_return(false) }
+  it { is_expected.to run.with_params(-3.7).and_return(false) }
+  it { is_expected.to run.with_params('3.7').and_return(false) }
+
+  it { is_expected.to run.with_params('one').and_return(false) }
+  it { is_expected.to run.with_params([]).and_return(false) }
+  it { is_expected.to run.with_params([1]).and_return(false) }
+  it { is_expected.to run.with_params({}).and_return(false) }
+  it { is_expected.to run.with_params(true).and_return(false) }
+  it { is_expected.to run.with_params(false).and_return(false) }
+  it { is_expected.to run.with_params('0001234').and_return(false) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/is_ip_address_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe 'is_ip_address' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params([], []).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('1.2.3.4').and_return(true) }
+  it { is_expected.to run.with_params('1.2.3.255').and_return(true) }
+  it { is_expected.to run.with_params('1.2.3.256').and_return(false) }
+  it { is_expected.to run.with_params('1.2.3').and_return(false) }
+  it { is_expected.to run.with_params('1.2.3.4.5').and_return(false) }
+  it { is_expected.to run.with_params('fe00::1').and_return(true) }
+  it { is_expected.to run.with_params('fe80:0000:cd12:d123:e2f8:47ff:fe09:dd74').and_return(true) }
+  it { is_expected.to run.with_params('FE80:0000:CD12:D123:E2F8:47FF:FE09:DD74').and_return(true) }
+  it { is_expected.to run.with_params('fe80:0000:cd12:d123:e2f8:47ff:fe09:zzzz').and_return(false) }
+  it { is_expected.to run.with_params('fe80:0000:cd12:d123:e2f8:47ff:fe09').and_return(false) }
+  it { is_expected.to run.with_params('fe80:0000:cd12:d123:e2f8:47ff:fe09:dd74:dd74').and_return(false) }
+  it { is_expected.to run.with_params('').and_return(false) }
+  it { is_expected.to run.with_params('one').and_return(false) }
+  it { is_expected.to run.with_params(1).and_return(false) }
+  it { is_expected.to run.with_params({}).and_return(false) }
+  it { is_expected.to run.with_params([]).and_return(false) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/is_mac_address_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'is_mac_address' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params([], []).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('00:a0:1f:12:7f:a0').and_return(true) }
+  it { is_expected.to run.with_params('00:A0:1F:12:7F:A0').and_return(true) }
+  it { is_expected.to run.with_params('00:00:00:00:00:0g').and_return(false) }
+  it { is_expected.to run.with_params('').and_return(false) }
+  it { is_expected.to run.with_params('one').and_return(false) }
+  it {
+    pending "should properly typecheck its arguments"
+    is_expected.to run.with_params(1).and_return(false)
+  }
+  it {
+    pending "should properly typecheck its arguments"
+    is_expected.to run.with_params({}).and_return(false)
+  }
+  it {
+    pending "should properly typecheck its arguments"
+    is_expected.to run.with_params([]).and_return(false)
+  }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/is_numeric_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe 'is_numeric' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(1, 2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+  it { is_expected.to run.with_params(3).and_return(true) }
+  it { is_expected.to run.with_params('3').and_return(true) }
+  it { is_expected.to run.with_params(-3).and_return(true) }
+  it { is_expected.to run.with_params('-3').and_return(true) }
+  
+  it { is_expected.to run.with_params(3.7).and_return(true) }
+  it { is_expected.to run.with_params('3.7').and_return(true) }
+  it { is_expected.to run.with_params(-3.7).and_return(true) }
+  it { is_expected.to run.with_params('3.7').and_return(true) }
+
+  it { is_expected.to run.with_params('-342.2315e-12').and_return(true) }
+
+  it { is_expected.to run.with_params('one').and_return(false) }
+  it { is_expected.to run.with_params([]).and_return(false) }
+  it { is_expected.to run.with_params([1]).and_return(false) }
+  it { is_expected.to run.with_params({}).and_return(false) }
+  it { is_expected.to run.with_params(true).and_return(false) }
+  it { is_expected.to run.with_params(false).and_return(false) }
+  it { is_expected.to run.with_params('0001234').and_return(false) }
+  it { is_expected.to run.with_params(' - 1234').and_return(false) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/is_string_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe 'is_string' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+
+  it { is_expected.to run.with_params(3).and_return(false) }
+  it { is_expected.to run.with_params('3').and_return(false) }
+  it { is_expected.to run.with_params(-3).and_return(false) }
+  it { is_expected.to run.with_params('-3').and_return(false) }
+
+  it { is_expected.to run.with_params(3.7).and_return(false) }
+  it { is_expected.to run.with_params('3.7').and_return(false) }
+  it { is_expected.to run.with_params(-3.7).and_return(false) }
+  it { is_expected.to run.with_params('3.7').and_return(false) }
+
+  it { is_expected.to run.with_params([]).and_return(false) }
+  it { is_expected.to run.with_params([1]).and_return(false) }
+  it { is_expected.to run.with_params({}).and_return(false) }
+  it { is_expected.to run.with_params(true).and_return(false) }
+  it { is_expected.to run.with_params(false).and_return(false) }
+  it { is_expected.to run.with_params('one').and_return(true) }
+  it { is_expected.to run.with_params('0001234').and_return(true) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/join_keys_to_values_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe 'join_keys_to_values' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /Takes exactly two arguments/) }
+  it { is_expected.to run.with_params({}, '', '').and_raise_error(Puppet::ParseError, /Takes exactly two arguments/) }
+  it { is_expected.to run.with_params('one', '').and_raise_error(TypeError, /The first argument must be a hash/) }
+  it { is_expected.to run.with_params({}, 2).and_raise_error(TypeError, /The second argument must be a string/) }
+
+  it { is_expected.to run.with_params({}, '').and_return([]) }
+  it { is_expected.to run.with_params({}, ':').and_return([]) }
+  it { is_expected.to run.with_params({ 'key' => 'value' }, '').and_return(['keyvalue']) }
+  it { is_expected.to run.with_params({ 'key' => 'value' }, ':').and_return(['key:value']) }
+  it { is_expected.to run.with_params({ 'key' => nil }, ':').and_return(['key:']) }
+  it 'should run join_keys_to_values(<hash with multiple keys>, ":") and return the proper array' do
+    result = subject.call([{ 'key1' => 'value1', 'key2' => 'value2' }, ':'])
+    expect(result.sort).to eq(['key1:value1', 'key2:value2'].sort)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/join_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe 'join' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the second.")
+    is_expected.to run.with_params([], '', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /Requires array to work with/) }
+  it { is_expected.to run.with_params([], 2).and_raise_error(Puppet::ParseError, /Requires string to work with/) }
+
+  it { is_expected.to run.with_params([]).and_return('') }
+  it { is_expected.to run.with_params([], ':').and_return('') }
+  it { is_expected.to run.with_params(['one']).and_return('one') }
+  it { is_expected.to run.with_params(['one'], ':').and_return('one') }
+  it { is_expected.to run.with_params(['one', 'two', 'three']).and_return('onetwothree') }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], ':').and_return('one:two:three') }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/keys_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe 'keys' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params({}, {}).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params('').and_raise_error(Puppet::ParseError, /Requires hash to work with/) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires hash to work with/) }
+  it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /Requires hash to work with/) }
+  it { is_expected.to run.with_params({}).and_return([]) }
+  it { is_expected.to run.with_params({ 'key' => 'value' }).and_return(['key']) }
+  it 'should return the array of keys' do
+    result = subject.call([{ 'key1' => 'value1', 'key2' => 'value2' }])
+    expect(result).to match_array(['key1', 'key2'])
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/load_module_metadata.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe 'load_module_metadata' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params("one", "two").and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+  it "should json parse the file" do
+     allow(scope).to receive(:function_get_module_path).with(['science']).and_return('/path/to/module/')
+     allow(File).to receive(:exists?).with(/metadata.json/).and_return(true)
+     allow(File).to receive(:read).with(/metadata.json/).and_return('{"name": "spencer-science"}')
+
+     result = subject.call(['science'])
+     expect(result['name']).to eq('spencer-science')
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/loadyaml_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'loadyaml' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  context 'when a non-existing file is specified' do
+    let(:filename) { '/tmp/doesnotexist' }
+    before {
+      File.expects(:exists?).with(filename).returns(false).once
+      YAML.expects(:load_file).never
+    }
+    it { is_expected.to run.with_params(filename).and_return(nil) }
+  end
+  context 'when an existing file is specified' do
+    let(:filename) { '/tmp/doesexist' }
+    let(:data) { { 'key' => 'value' } }
+    before {
+      File.expects(:exists?).with(filename).returns(true).once
+      YAML.expects(:load_file).with(filename).returns(data).once
+    }
+    it { is_expected.to run.with_params(filename).and_return(data) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/lstrip_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+describe 'lstrip' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+  it { is_expected.to run.with_params('').and_return('') }
+  it { is_expected.to run.with_params(' ').and_return('') }
+  it { is_expected.to run.with_params('     ').and_return('') }
+  it { is_expected.to run.with_params("\t").and_return('') }
+  it { is_expected.to run.with_params("\t ").and_return('') }
+  it { is_expected.to run.with_params('one').and_return('one') }
+  it { is_expected.to run.with_params(' one').and_return('one') }
+  it { is_expected.to run.with_params('     one').and_return('one') }
+  it { is_expected.to run.with_params("\tone").and_return('one') }
+  it { is_expected.to run.with_params("\t one").and_return('one') }
+  it { is_expected.to run.with_params('one ').and_return('one ') }
+  it { is_expected.to run.with_params(' one ').and_return('one ') }
+  it { is_expected.to run.with_params('     one ').and_return('one ') }
+  it { is_expected.to run.with_params("\tone ").and_return('one ') }
+  it { is_expected.to run.with_params("\t one ").and_return('one ') }
+  it { is_expected.to run.with_params("one \t").and_return("one \t") }
+  it { is_expected.to run.with_params(" one \t").and_return("one \t") }
+  it { is_expected.to run.with_params("     one \t").and_return("one \t") }
+  it { is_expected.to run.with_params("\tone \t").and_return("one \t") }
+  it { is_expected.to run.with_params("\t one \t").and_return("one \t") }
+  it { is_expected.to run.with_params(' o n e ').and_return('o n e ') }
+  it { is_expected.to run.with_params(AlsoString.new(' one ')).and_return('one ') }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/max_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe 'max' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(1).and_return(1) }
+  it { is_expected.to run.with_params(1, 2).and_return(2) }
+  it { is_expected.to run.with_params(1, 2, 3).and_return(3) }
+  it { is_expected.to run.with_params(3, 2, 1).and_return(3) }
+  it { is_expected.to run.with_params('one').and_return('one') }
+  it { is_expected.to run.with_params('one', 'two').and_return('two') }
+  it { is_expected.to run.with_params('one', 'two', 'three').and_return('two') }
+  it { is_expected.to run.with_params('three', 'two', 'one').and_return('two') }
+
+  describe 'implementation artifacts' do
+    it { is_expected.to run.with_params(1, 'one').and_return('one') }
+    it { is_expected.to run.with_params('1', 'one').and_return('one') }
+    it { is_expected.to run.with_params('1.3e1', '1.4e0').and_return('1.4e0') }
+    it { is_expected.to run.with_params(1.3e1, 1.4e0).and_return(1.3e1) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/member_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe 'member' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params([], [], []).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params([], '').and_return(false) }
+  it { is_expected.to run.with_params([], ['']).and_return(false) }
+  it { is_expected.to run.with_params([''], '').and_return(true) }
+  it { is_expected.to run.with_params([''], ['']).and_return(true) }
+  it { is_expected.to run.with_params([], 'one').and_return(false) }
+  it { is_expected.to run.with_params([], ['one']).and_return(false) }
+  it { is_expected.to run.with_params(['one'], 'one').and_return(true) }
+  it { is_expected.to run.with_params(['one'], ['one']).and_return(true) }
+  it { is_expected.to run.with_params(['one', 'two', 'three', 'four'], ['four', 'two']).and_return(true) }
+  it { is_expected.to run.with_params(['one', 'two', 'three', 'four'], ['four', 'five']).and_return(false) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/merge_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe 'merge' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params({}, 'two').and_raise_error(Puppet::ParseError, /unexpected argument type String/) }
+  it { is_expected.to run.with_params({}, 1).and_raise_error(Puppet::ParseError, /unexpected argument type Fixnum/) }
+  it {
+    pending 'should not special case this'
+    is_expected.to run.with_params({}).and_return({})
+  }
+  it { is_expected.to run.with_params({}, {}).and_return({}) }
+  it { is_expected.to run.with_params({}, {}, {}).and_return({}) }
+  describe 'should accept empty strings as puppet undef' do
+    it { is_expected.to run.with_params({}, '').and_return({}) }
+  end
+  it { is_expected.to run.with_params({ 'key' => 'value' }, {}).and_return({ 'key' => 'value' }) }
+  it { is_expected.to run.with_params({}, { 'key' => 'value' }).and_return({ 'key' => 'value' }) }
+  it { is_expected.to run.with_params({ 'key' => 'value1' }, { 'key' => 'value2' }).and_return({ 'key' => 'value2' }) }
+  it {
+    is_expected.to run \
+      .with_params({ 'key1' => 'value1' }, { 'key2' => 'value2' }, { 'key3' => 'value3' }) \
+      .and_return({ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3' })
+  }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/min_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe 'min' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(1).and_return(1) }
+  it { is_expected.to run.with_params(1, 2).and_return(1) }
+  it { is_expected.to run.with_params(1, 2, 3).and_return(1) }
+  it { is_expected.to run.with_params(3, 2, 1).and_return(1) }
+  it { is_expected.to run.with_params('one').and_return('one') }
+  it { is_expected.to run.with_params('one', 'two').and_return('one') }
+  it { is_expected.to run.with_params('one', 'two', 'three').and_return('one') }
+  it { is_expected.to run.with_params('three', 'two', 'one').and_return('one') }
+
+  describe 'implementation artifacts' do
+    it { is_expected.to run.with_params(1, 'one').and_return(1) }
+    it { is_expected.to run.with_params('1', 'one').and_return('1') }
+    it { is_expected.to run.with_params('1.3e1', '1.4e0').and_return('1.3e1') }
+    it { is_expected.to run.with_params(1.3e1, 1.4e0).and_return(1.4e0) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/num2bool_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe 'num2bool' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(1, 2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('abc').and_raise_error(Puppet::ParseError, /does not look like a number/) }
+  it { is_expected.to run.with_params(1).and_return(true) }
+  it { is_expected.to run.with_params('1').and_return(true) }
+  it { is_expected.to run.with_params(1.5).and_return(true) }
+  it { is_expected.to run.with_params('1.5').and_return(true) }
+  it { is_expected.to run.with_params(-1).and_return(false) }
+  it { is_expected.to run.with_params('-1').and_return(false) }
+  it { is_expected.to run.with_params(-1.5).and_return(false) }
+  it { is_expected.to run.with_params('-1.5').and_return(false) }
+  it { is_expected.to run.with_params(0).and_return(false) }
+  it { is_expected.to run.with_params('0').and_return(false) }
+  it { is_expected.to run.with_params([]).and_return(false) }
+  it { is_expected.to run.with_params('[]').and_raise_error(Puppet::ParseError, /does not look like a number/) }
+  it { is_expected.to run.with_params({}).and_return(false) }
+  it { is_expected.to run.with_params('{}').and_raise_error(Puppet::ParseError, /does not look like a number/) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/parsejson_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+require 'spec_helper'
+
+describe 'parsejson' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('["one"').and_raise_error(PSON::ParserError) }
+  it { is_expected.to run.with_params('["one", "two", "three"]').and_return(['one', 'two', 'three']) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/parseyaml_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe 'parseyaml' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('["one", "two", "three"]').and_return(['one', 'two', 'three']) }
+  context 'when running on modern rubies', :unless => RUBY_VERSION == '1.8.7' do
+    it { is_expected.to run.with_params('["one"').and_raise_error(Psych::SyntaxError) }
+  end
+  context 'when running on ruby 1.8.7, which does not have Psych', :if => RUBY_VERSION == '1.8.7' do
+    it { is_expected.to run.with_params('["one"').and_raise_error(ArgumentError) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/pick_default_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'pick_default' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::Error, /Must receive at least one argument/) }
+
+  it { is_expected.to run.with_params('one', 'two').and_return('one') }
+  it { is_expected.to run.with_params('', 'two').and_return('two') }
+  it { is_expected.to run.with_params(:undef, 'two').and_return('two') }
+  it { is_expected.to run.with_params(:undefined, 'two').and_return('two') }
+  it { is_expected.to run.with_params(nil, 'two').and_return('two') }
+
+  [ '', :undef, :undefined, nil, {}, [], 1, 'default' ].each do |value|
+    describe "when providing #{value.inspect} as default" do
+      it { is_expected.to run.with_params('one', value).and_return('one') }
+      it { is_expected.to run.with_params([], value).and_return([]) }
+      it { is_expected.to run.with_params({}, value).and_return({}) }
+      it { is_expected.to run.with_params(value, value).and_return(value) }
+      it { is_expected.to run.with_params(:undef, value).and_return(value) }
+      it { is_expected.to run.with_params(:undefined, value).and_return(value) }
+      it { is_expected.to run.with_params(nil, value).and_return(value) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/pick_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+require 'spec_helper'
+
+describe 'pick' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /must receive at least one non empty value/) }
+  it { is_expected.to run.with_params('', nil, :undef, :undefined).and_raise_error(Puppet::ParseError, /must receive at least one non empty value/) }
+  it { is_expected.to run.with_params('one', 'two').and_return('one') }
+  it { is_expected.to run.with_params('', 'two').and_return('two') }
+  it { is_expected.to run.with_params(:undef, 'two').and_return('two') }
+  it { is_expected.to run.with_params(:undefined, 'two').and_return('two') }
+  it { is_expected.to run.with_params(nil, 'two').and_return('two') }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/prefix_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe 'prefix' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the second.")
+    is_expected.to run.with_params([], 'a', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /expected first argument to be an Array or a Hash/) }
+  it { is_expected.to run.with_params([], 2).and_raise_error(Puppet::ParseError, /expected second argument to be a String/) }
+  it { is_expected.to run.with_params([]).and_return([]) }
+  it { is_expected.to run.with_params(['one', 2]).and_return(['one', '2']) }
+  it { is_expected.to run.with_params([], '').and_return([]) }
+  it { is_expected.to run.with_params([''], '').and_return(['']) }
+  it { is_expected.to run.with_params(['one'], 'pre').and_return(['preone']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], 'pre').and_return(['preone', 'pretwo', 'prethree']) }
+  it { is_expected.to run.with_params({}).and_return({}) }
+  it { is_expected.to run.with_params({ 'key1' => 'value1', 2 => 3}).and_return({ 'key1' => 'value1', '2' => 3 }) }
+  it { is_expected.to run.with_params({}, '').and_return({}) }
+  it { is_expected.to run.with_params({ 'key' => 'value' }, '').and_return({ 'key' => 'value' }) }
+  it { is_expected.to run.with_params({ 'key' => 'value' }, 'pre').and_return({ 'prekey' => 'value' }) }
+  it {
+    is_expected.to run \
+      .with_params({ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3' }, 'pre') \
+      .and_return({ 'prekey1' => 'value1', 'prekey2' => 'value2', 'prekey3' => 'value3' })
+  }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/private_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+describe 'private' do
+  it 'should issue a warning' do
+    scope.expects(:warning).with("private() DEPRECATED: This function will cease to function on Puppet 4; please use assert_private() before upgrading to puppet 4 for backwards-compatibility, or migrate to the new parser's typing system.")
+    begin
+      subject.call []
+    rescue
+      # ignore this
+    end
+  end
+
+  context "when called from inside module" do
+    it "should not fail" do
+      scope.expects(:lookupvar).with('module_name').returns('foo')
+      scope.expects(:lookupvar).with('caller_module_name').returns('foo')
+      expect {
+        subject.call []
+      }.not_to raise_error
+    end
+  end
+
+  context "with an explicit failure message" do
+    it "prints the failure message on error" do
+      scope.expects(:lookupvar).with('module_name').returns('foo')
+      scope.expects(:lookupvar).with('caller_module_name').returns('bar')
+      expect {
+        subject.call ['failure message!']
+      }.to raise_error Puppet::ParseError, /failure message!/
+    end
+  end
+
+  context "when called from private class" do
+    it "should fail with a class error message" do
+      scope.expects(:lookupvar).with('module_name').returns('foo')
+      scope.expects(:lookupvar).with('caller_module_name').returns('bar')
+      scope.source.expects(:name).returns('foo::baz')
+      scope.source.expects(:type).returns('hostclass')
+      expect {
+        subject.call []
+      }.to raise_error Puppet::ParseError, /Class foo::baz is private/
+    end
+  end
+
+  context "when called from private definition" do
+    it "should fail with a class error message" do
+      scope.expects(:lookupvar).with('module_name').returns('foo')
+      scope.expects(:lookupvar).with('caller_module_name').returns('bar')
+      scope.source.expects(:name).returns('foo::baz')
+      scope.source.expects(:type).returns('definition')
+      expect {
+        subject.call []
+      }.to raise_error Puppet::ParseError, /Definition foo::baz is private/
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/pw_hash_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,69 @@
+require 'spec_helper'
+
+describe 'pw_hash' do
+
+  it { is_expected.not_to eq(nil) }
+
+  context 'when there are less than 3 arguments' do
+    it { is_expected.to run.with_params().and_raise_error(ArgumentError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('password').and_raise_error(ArgumentError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('password', 'sha-256').and_raise_error(ArgumentError, /wrong number of arguments/i) }
+  end
+
+  context 'when there are more than 3 arguments' do
+    it { is_expected.to run.with_params('password', 'sha-256', 'salt', 'extra').and_raise_error(ArgumentError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('password', 'sha-256', 'salt', 'extra', 'extra').and_raise_error(ArgumentError, /wrong number of arguments/i) }
+  end
+
+  context 'when the first argument is not a string' do
+    it { is_expected.to run.with_params([], 'sha-256', 'salt').and_raise_error(ArgumentError, /first argument must be a string/) }
+    it { is_expected.to run.with_params({}, 'sha-256', 'salt').and_raise_error(ArgumentError, /first argument must be a string/) }
+    it { is_expected.to run.with_params(1, 'sha-256', 'salt').and_raise_error(ArgumentError, /first argument must be a string/) }
+    it { is_expected.to run.with_params(true, 'sha-256', 'salt').and_raise_error(ArgumentError, /first argument must be a string/) }
+  end
+
+  context 'when the first argument is undefined' do
+    it { is_expected.to run.with_params('', 'sha-256', 'salt').and_return(nil) }
+    it { is_expected.to run.with_params(nil, 'sha-256', 'salt').and_return(nil) }
+  end
+
+  context 'when the second argument is not a string' do
+    it { is_expected.to run.with_params('password', [], 'salt').and_raise_error(ArgumentError, /second argument must be a string/) }
+    it { is_expected.to run.with_params('password', {}, 'salt').and_raise_error(ArgumentError, /second argument must be a string/) }
+    it { is_expected.to run.with_params('password', 1, 'salt').and_raise_error(ArgumentError, /second argument must be a string/) }
+    it { is_expected.to run.with_params('password', true, 'salt').and_raise_error(ArgumentError, /second argument must be a string/) }
+  end
+
+  context 'when the second argument is not one of the supported hashing algorithms' do
+    it { is_expected.to run.with_params('password', 'no such algo', 'salt').and_raise_error(ArgumentError, /is not a valid hash type/) }
+  end
+
+  context 'when the third argument is not a string' do
+    it { is_expected.to run.with_params('password', 'sha-256', []).and_raise_error(ArgumentError, /third argument must be a string/) }
+    it { is_expected.to run.with_params('password', 'sha-256', {}).and_raise_error(ArgumentError, /third argument must be a string/) }
+    it { is_expected.to run.with_params('password', 'sha-256', 1).and_raise_error(ArgumentError, /third argument must be a string/) }
+    it { is_expected.to run.with_params('password', 'sha-256', true).and_raise_error(ArgumentError, /third argument must be a string/) }
+  end
+
+  context 'when the third argument is empty' do
+    it { is_expected.to run.with_params('password', 'sha-512', '').and_raise_error(ArgumentError, /third argument must not be empty/) }
+  end
+
+  context 'when the third argument contains invalid characters' do
+    it { is_expected.to run.with_params('password', 'sha-512', 'one%').and_raise_error(ArgumentError, /characters in salt must be in the set/) }
+  end
+
+  context 'when running on a platform with a weak String#crypt implementation' do
+    before(:each) { allow_any_instance_of(String).to receive(:crypt).with('$1$1').and_return('a bad hash') }
+
+    it { is_expected.to run.with_params('password', 'sha-512', 'salt').and_raise_error(Puppet::ParseError, /system does not support enhanced salts/) }
+  end
+
+  if RUBY_PLATFORM == 'java' or 'test'.crypt('$1$1') == '$1$1$Bp8CU9Oujr9SSEw53WV6G.'
+    describe "on systems with enhanced salts support" do
+      it { is_expected.to run.with_params('password', 'md5', 'salt').and_return('$1$salt$qJH7.N4xYta3aEG/dfqo/0') }
+      it { is_expected.to run.with_params('password', 'sha-256', 'salt').and_return('$5$salt$Gcm6FsVtF/Qa77ZKD.iwsJlCVPY0XSMgLJL0Hnww/c1') }
+      it { is_expected.to run.with_params('password', 'sha-512', 'salt').and_return('$6$salt$IxDD3jeSOb5eB1CX5LBsqZFVkJdido3OUILO5Ifz5iwMuTS4XMS130MTSuDDl3aCI6WouIL9AjRbLCelDCy.g.') }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/range_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,118 @@
+require 'spec_helper'
+
+describe 'range' do
+  it { is_expected.not_to eq(nil) }
+
+  describe 'signature validation in puppet3', :unless => RSpec.configuration.puppet_future do
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it {
+      pending("Current implementation ignores parameters after the third.")
+      is_expected.to run.with_params(1, 2, 3, 4).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+    }
+    it { is_expected.to run.with_params('1..2..3').and_raise_error(Puppet::ParseError, /Unable to compute range/i) }
+    it { is_expected.to run.with_params('').and_raise_error(Puppet::ParseError, /Unknown range format/i) }
+  end
+
+  describe 'signature validation in puppet4', :if => RSpec.configuration.puppet_future do
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params().and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params('').and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params({}).and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params([]).and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params(true).and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params(true).and_raise_error(ArgumentError) }
+    it {                                        is_expected.to run.with_params(1, 2, 'foo').and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params(1, 2, []).and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params(1, 2, {}).and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params(1, 2, true).and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params(1, 2, 3, 4).and_raise_error(ArgumentError) }
+    it { pending "the puppet 4 implementation"; is_expected.to run.with_params('1..2..3').and_raise_error(ArgumentError) }
+  end
+
+  context 'with characters as bounds' do
+    it { is_expected.to run.with_params('d', 'a').and_return([]) }
+    it { is_expected.to run.with_params('a', 'a').and_return(['a']) }
+    it { is_expected.to run.with_params('a', 'b').and_return(['a', 'b']) }
+    it { is_expected.to run.with_params('a', 'd').and_return(['a', 'b', 'c', 'd']) }
+    it { is_expected.to run.with_params('a', 'd', 1).and_return(['a', 'b', 'c', 'd']) }
+    it { is_expected.to run.with_params('a', 'd', '1').and_return(['a', 'b', 'c', 'd']) }
+    it { is_expected.to run.with_params('a', 'd', 2).and_return(['a', 'c']) }
+    it { is_expected.to run.with_params('a', 'd', -2).and_return(['a', 'c']) }
+    it { is_expected.to run.with_params('a', 'd', 3).and_return(['a', 'd']) }
+    it { is_expected.to run.with_params('a', 'd', 4).and_return(['a']) }
+  end
+
+  context 'with strings as bounds' do
+    it { is_expected.to run.with_params('onea', 'oned').and_return(['onea', 'oneb', 'onec', 'oned']) }
+    it { is_expected.to run.with_params('two', 'one').and_return([]) }
+    it { is_expected.to run.with_params('true', 'false').and_return([]) }
+    it { is_expected.to run.with_params('false', 'true').and_return(['false']) }
+  end
+
+  context 'with integers as bounds' do
+    it { is_expected.to run.with_params(4, 1).and_return([]) }
+    it { is_expected.to run.with_params(1, 1).and_return([1]) }
+    it { is_expected.to run.with_params(1, 2).and_return([1, 2]) }
+    it { is_expected.to run.with_params(1, 4).and_return([1, 2, 3, 4]) }
+    it { is_expected.to run.with_params(1, 4, 1).and_return([1, 2, 3, 4]) }
+    it { is_expected.to run.with_params(1, 4, '1').and_return([1, 2, 3, 4]) }
+    it { is_expected.to run.with_params(1, 4, 2).and_return([1, 3]) }
+    it { is_expected.to run.with_params(1, 4, -2).and_return([1, 3]) }
+    it { is_expected.to run.with_params(1, 4, 3).and_return([1, 4]) }
+    it { is_expected.to run.with_params(1, 4, 4).and_return([1]) }
+  end
+
+  context 'with integers as strings as bounds' do
+    it { is_expected.to run.with_params('4', '1').and_return([]) }
+    it { is_expected.to run.with_params('1', '1').and_return([1]) }
+    it { is_expected.to run.with_params('1', '2').and_return([1, 2]) }
+    it { is_expected.to run.with_params('1', '4').and_return([1, 2, 3, 4]) }
+    it { is_expected.to run.with_params('1', '4', 1).and_return([1, 2, 3, 4]) }
+    it { is_expected.to run.with_params('1', '4', '1').and_return([1, 2, 3, 4]) }
+    it { is_expected.to run.with_params('1', '4', 2).and_return([1, 3]) }
+    it { is_expected.to run.with_params('1', '4', -2).and_return([1, 3]) }
+    it { is_expected.to run.with_params('1', '4', 3).and_return([1, 4]) }
+    it { is_expected.to run.with_params('1', '4', 4).and_return([1]) }
+  end
+
+  context 'with prefixed numbers as strings as bounds' do
+    it { is_expected.to run.with_params('host01', 'host04').and_return(['host01', 'host02', 'host03', 'host04']) }
+    it { is_expected.to run.with_params('01', '04').and_return([1, 2, 3, 4]) }
+  end
+
+  context 'with dash-range syntax' do
+    it { is_expected.to run.with_params('4-1').and_return([]) }
+    it { is_expected.to run.with_params('1-1').and_return([1]) }
+    it { is_expected.to run.with_params('1-2').and_return([1, 2]) }
+    it { is_expected.to run.with_params('1-4').and_return([1, 2, 3, 4]) }
+  end
+
+  context 'with two-dot-range syntax' do
+    it { is_expected.to run.with_params('4..1').and_return([]) }
+    it { is_expected.to run.with_params('1..1').and_return([1]) }
+    it { is_expected.to run.with_params('1..2').and_return([1, 2]) }
+    it { is_expected.to run.with_params('1..4').and_return([1, 2, 3, 4]) }
+  end
+
+  context 'with three-dot-range syntax' do
+    it { is_expected.to run.with_params('4...1').and_return([]) }
+    it { is_expected.to run.with_params('1...1').and_return([]) }
+    it { is_expected.to run.with_params('1...2').and_return([1]) }
+    it { is_expected.to run.with_params('1...3').and_return([1, 2]) }
+    it { is_expected.to run.with_params('1...5').and_return([1, 2, 3, 4]) }
+  end
+
+  describe 'when passing mixed arguments as bounds' do
+    it {
+      pending('these bounds should not be allowed as ruby will OOM hard. e.g. `(\'host0\'..\'hosta\').to_a` has 3239930 elements on ruby 1.9, adding more \'0\'s and \'a\'s increases that exponentially')
+      is_expected.to run.with_params('0', 'a').and_raise_error(Puppet::ParseError, /cannot interpolate between numeric and non-numeric bounds/)
+    }
+    it {
+      pending('these bounds should not be allowed as ruby will OOM hard. e.g. `(\'host0\'..\'hosta\').to_a` has 3239930 elements on ruby 1.9, adding more \'0\'s and \'a\'s increases that exponentially')
+      is_expected.to run.with_params(0, 'a').and_raise_error(Puppet::ParseError, /cannot interpolate between numeric and non-numeric bounds/)
+    }
+    it {
+      pending('these bounds should not be allowed as ruby will OOM hard. e.g. `(\'host0\'..\'hosta\').to_a` has 3239930 elements on ruby 1.9, adding more \'0\'s and \'a\'s increases that exponentially')
+      is_expected.to run.with_params('h0', 'ha').and_raise_error(Puppet::ParseError, /cannot interpolate between numeric and non-numeric bounds/)
+    }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/reject_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe 'reject' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params([], 'pattern', 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+  it {
+    pending("reject does not actually check this, and raises NoMethodError instead")
+    is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, /first argument not an array/)
+  }
+  it {
+    pending("reject does not actually check this, and raises NoMethodError instead")
+    is_expected.to run.with_params(1, 'two').and_raise_error(Puppet::ParseError, /first argument not an array/)
+  }
+  it { is_expected.to run.with_params([], 'two').and_return([]) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], 'two').and_return(['one', 'three']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], 't(wo|hree)').and_return(['one']) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/reverse_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+require 'spec_helper'
+
+describe 'reverse' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params([], 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+  it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+  it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+  it { is_expected.to run.with_params([]).and_return([]) }
+  it { is_expected.to run.with_params(['a']).and_return(['a']) }
+  it { is_expected.to run.with_params(['one']).and_return(['one']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three']).and_return(['three', 'two', 'one']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three', 'four']).and_return(['four', 'three', 'two', 'one']) }
+
+  it { is_expected.to run.with_params('').and_return('') }
+  it { is_expected.to run.with_params('a').and_return('a') }
+  it { is_expected.to run.with_params('abc').and_return('cba') }
+  it { is_expected.to run.with_params('abcd').and_return('dcba') }
+
+  context 'when using a class extending String' do
+    it 'should call its reverse method' do
+      value = AlsoString.new('asdfghjkl')
+      value.expects(:reverse).returns('foo')
+      expect(subject).to run.with_params(value).and_return('foo')
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/rstrip_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+describe 'rstrip' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+  it { is_expected.to run.with_params('').and_return('') }
+  it { is_expected.to run.with_params(' ').and_return('') }
+  it { is_expected.to run.with_params('     ').and_return('') }
+  it { is_expected.to run.with_params("\t").and_return('') }
+  it { is_expected.to run.with_params("\t ").and_return('') }
+  it { is_expected.to run.with_params('one').and_return('one') }
+  it { is_expected.to run.with_params(' one').and_return(' one') }
+  it { is_expected.to run.with_params('     one').and_return('     one') }
+  it { is_expected.to run.with_params("\tone").and_return("\tone") }
+  it { is_expected.to run.with_params("\t one").and_return("\t one") }
+  it { is_expected.to run.with_params('one ').and_return('one') }
+  it { is_expected.to run.with_params(' one ').and_return(' one') }
+  it { is_expected.to run.with_params('     one ').and_return('     one') }
+  it { is_expected.to run.with_params("\tone ").and_return("\tone") }
+  it { is_expected.to run.with_params("\t one ").and_return("\t one") }
+  it { is_expected.to run.with_params("one\t").and_return('one') }
+  it { is_expected.to run.with_params(" one\t").and_return(' one') }
+  it { is_expected.to run.with_params("     one\t").and_return('     one') }
+  it { is_expected.to run.with_params("\tone\t").and_return("\tone") }
+  it { is_expected.to run.with_params("\t one\t").and_return("\t one") }
+  it { is_expected.to run.with_params(' o n e ').and_return(' o n e') }
+  it { is_expected.to run.with_params(AlsoString.new(' one ')).and_return(' one') }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/shuffle_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,33 @@
+require 'spec_helper'
+
+describe 'shuffle' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params([], 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+  it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+  it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+
+  context 'when running with a specific seed' do
+    # make tests deterministic
+    before(:each) { srand(2) }
+
+    it { is_expected.to run.with_params([]).and_return([]) }
+    it { is_expected.to run.with_params(['a']).and_return(['a']) }
+    it { is_expected.to run.with_params(['one']).and_return(['one']) }
+    it { is_expected.to run.with_params(['one', 'two', 'three']).and_return(['two', 'one', 'three']) }
+    it { is_expected.to run.with_params(['one', 'two', 'three', 'four']).and_return(['four', 'three', 'two', 'one']) }
+
+    it { is_expected.to run.with_params('').and_return('') }
+    it { is_expected.to run.with_params('a').and_return('a') }
+    it { is_expected.to run.with_params('abc').and_return('bac') }
+    it { is_expected.to run.with_params('abcd').and_return('dcba') }
+
+    context 'when using a class extending String' do
+      it { is_expected.to run.with_params(AlsoString.new('asdfghjkl')).and_return('lkhdsfajg') }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/size_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+require 'spec_helper'
+
+describe 'size' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params([], 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Unknown type given/) }
+  it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Unknown type given/) }
+  it { is_expected.to run.with_params('1').and_raise_error(Puppet::ParseError, /Requires either string, array or hash to work/) }
+  it { is_expected.to run.with_params('1.0').and_raise_error(Puppet::ParseError, /Requires either string, array or hash to work/) }
+  it { is_expected.to run.with_params([]).and_return(0) }
+  it { is_expected.to run.with_params(['a']).and_return(1) }
+  it { is_expected.to run.with_params(['one', 'two', 'three']).and_return(3) }
+  it { is_expected.to run.with_params(['one', 'two', 'three', 'four']).and_return(4) }
+
+  it { is_expected.to run.with_params({}).and_return(0) }
+  it { is_expected.to run.with_params({'1' => '2'}).and_return(1) }
+  it { is_expected.to run.with_params({'1' => '2', '4' => '4'}).and_return(2) }
+
+  it { is_expected.to run.with_params('').and_return(0) }
+  it { is_expected.to run.with_params('a').and_return(1) }
+  it { is_expected.to run.with_params('abc').and_return(3) }
+  it { is_expected.to run.with_params('abcd').and_return(4) }
+
+  context 'when using a class extending String' do
+    it 'should call its size method' do
+      value = AlsoString.new('asdfghjkl')
+      value.expects(:size).returns('foo')
+      expect(subject).to run.with_params(value).and_return('foo')
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/sort_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'sort' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params([], 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { pending('stricter input checking'); is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /requires string or array/) }
+    it { pending('stricter input checking'); is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /requires string or array/) }
+    it { pending('stricter input checking'); is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /requires string or array/) }
+  end
+
+  context 'when called with an array' do
+    it { is_expected.to run.with_params([]).and_return([]) }
+    it { is_expected.to run.with_params(['a']).and_return(['a']) }
+    it { is_expected.to run.with_params(['c', 'b', 'a']).and_return(['a', 'b', 'c']) }
+  end
+
+  context 'when called with a string' do
+    it { is_expected.to run.with_params('').and_return('') }
+    it { is_expected.to run.with_params('a').and_return('a') }
+    it { is_expected.to run.with_params('cbda').and_return('abcd') }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/squeeze_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe 'squeeze' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('', '', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(1).and_raise_error(NoMethodError) }
+  it { is_expected.to run.with_params({}).and_raise_error(NoMethodError) }
+  it { is_expected.to run.with_params(true).and_raise_error(NoMethodError) }
+
+  context 'when squeezing a single string' do
+    it { is_expected.to run.with_params('').and_return('') }
+    it { is_expected.to run.with_params('a').and_return('a') }
+    it { is_expected.to run.with_params('aaaaaaaaa').and_return('a') }
+    it { is_expected.to run.with_params('aaaaaaaaa', 'a').and_return('a') }
+    it { is_expected.to run.with_params('aaaaaaaaabbbbbbbbbbcccccccccc', 'b-c').and_return('aaaaaaaaabc') }
+  end
+
+  context 'when squeezing values in an array' do
+    it {
+      is_expected.to run \
+        .with_params(['', 'a', 'aaaaaaaaa', 'aaaaaaaaabbbbbbbbbbcccccccccc']) \
+        .and_return( ['', 'a', 'a',         'abc'])
+    }
+    it {
+      is_expected.to run \
+        .with_params(['', 'a', 'aaaaaaaaa', 'aaaaaaaaabbbbbbbbbbcccccccccc'], 'a') \
+        .and_return( ['', 'a', 'a',         'abbbbbbbbbbcccccccccc'])
+    }
+    it {
+      is_expected.to run \
+        .with_params(['', 'a', 'aaaaaaaaa', 'aaaaaaaaabbbbbbbbbbcccccccccc'], 'b-c') \
+        .and_return( ['', 'a', 'aaaaaaaaa', 'aaaaaaaaabc'])
+    }
+  end
+
+  context 'when using a class extending String' do
+    it 'should call its squeeze method' do
+      value = AlsoString.new('aaaaaaaaa')
+      value.expects(:squeeze).returns('foo')
+      expect(subject).to run.with_params(value).and_return('foo')
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/str2bool_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe 'str2bool' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params('true', 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /Unknown type of boolean given/) }
+
+  describe 'when testing values that mean "true"' do
+    [ '1', 't', 'y', 'true', 'yes', true ].each do |value|
+      it { is_expected.to run.with_params(value).and_return(true) }
+    end
+  end
+
+  describe 'when testing values that mean "false"' do
+    [ '', '0', 'f', 'n', 'false', 'no', false, 'undef', 'undefined' ].each do |value|
+      it { is_expected.to run.with_params(value).and_return(false) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/str2saltedsha512_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe 'str2saltedsha512' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('password', 2).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires a String argument/) }
+
+  context 'when running with a specific seed' do
+    # make tests deterministic
+    before(:each) { srand(2) }
+
+    it { is_expected.to run.with_params('').and_return('0f8a612f4eeed08e47b3875d00f33c5688f7926298f2d9b5fe19d1323f910bc78b6f7b5892596d2fabaa65e7a8d99b3768c102610cf0432c4827eee01f09451e3fae4f7a') }
+    it { is_expected.to run.with_params('password').and_return('0f8a612f43134376566c5707718d600effcfb17581fc9d3fa64d7f447dfda317c174ffdb498d2c5bd5c2075dab41c9d7ada5afbdc6b55354980eb5ba61802371e6b64956') }
+    it { is_expected.to run.with_params('verylongpassword').and_return('0f8a612f7a448537540e062daa8621f9bae326ca8ccb899e1bdb10e7c218cebfceae2530b856662565fdc4d81e986fc50cfbbc46d50436610ed9429ff5e43f2c45b5d039') }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/strftime_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe 'strftime' do
+  it "should exist" do
+    expect(Puppet::Parser::Functions.function("strftime")).to eq("function_strftime")
+  end
+
+  it "should raise a ParseError if there is less than 1 arguments" do
+    expect { scope.function_strftime([]) }.to( raise_error(Puppet::ParseError))
+  end
+
+  it "using %s should be higher then when I wrote this test" do
+    result = scope.function_strftime(["%s"])
+    expect(result.to_i).to(be > 1311953157)
+  end
+
+  it "using %s should be lower then 1.5 trillion" do
+    result = scope.function_strftime(["%s"])
+    expect(result.to_i).to(be < 1500000000)
+  end
+
+  it "should return a date when given %Y-%m-%d" do
+    result = scope.function_strftime(["%Y-%m-%d"])
+    expect(result).to match(/^\d{4}-\d{2}-\d{2}$/)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/strip_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+describe 'strip' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work with/) }
+  it { is_expected.to run.with_params('').and_return('') }
+  it { is_expected.to run.with_params(' ').and_return('') }
+  it { is_expected.to run.with_params('     ').and_return('') }
+  it { is_expected.to run.with_params("\t").and_return('') }
+  it { is_expected.to run.with_params("\t ").and_return('') }
+  it { is_expected.to run.with_params('one').and_return('one') }
+  it { is_expected.to run.with_params(' one').and_return('one') }
+  it { is_expected.to run.with_params('     one').and_return('one') }
+  it { is_expected.to run.with_params("\tone").and_return('one') }
+  it { is_expected.to run.with_params("\t one").and_return('one') }
+  it { is_expected.to run.with_params('one ').and_return('one') }
+  it { is_expected.to run.with_params(' one ').and_return('one') }
+  it { is_expected.to run.with_params('     one ').and_return('one') }
+  it { is_expected.to run.with_params("\tone ").and_return('one') }
+  it { is_expected.to run.with_params("\t one ").and_return('one') }
+  it { is_expected.to run.with_params("one \t").and_return('one') }
+  it { is_expected.to run.with_params(" one \t").and_return('one') }
+  it { is_expected.to run.with_params("     one \t").and_return('one') }
+  it { is_expected.to run.with_params("\tone \t").and_return('one') }
+  it { is_expected.to run.with_params("\t one \t").and_return('one') }
+  it { is_expected.to run.with_params(' o n e ').and_return('o n e') }
+  it { is_expected.to run.with_params(AlsoString.new(' one ')).and_return('one') }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/suffix_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe 'suffix' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the second.")
+    is_expected.to run.with_params([], 'a', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /expected first argument to be an Array/) }
+  it { is_expected.to run.with_params([], 2).and_raise_error(Puppet::ParseError, /expected second argument to be a String/) }
+  it { is_expected.to run.with_params([]).and_return([]) }
+  it { is_expected.to run.with_params(['one', 2]).and_return(['one', '2']) }
+  it { is_expected.to run.with_params([], '').and_return([]) }
+  it { is_expected.to run.with_params([''], '').and_return(['']) }
+  it { is_expected.to run.with_params(['one'], 'post').and_return(['onepost']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], 'post').and_return(['onepost', 'twopost', 'threepost']) }
+  it {
+    pending("implementation of Hash functionality matching prefix")
+    is_expected.to run.with_params({}).and_return({})
+  }
+  it {
+    pending("implementation of Hash functionality matching prefix")
+    is_expected.to run.with_params({ 'key1' => 'value1', 2 => 3}).and_return({ 'key1' => 'value1', '2' => 3 })
+  }
+  it {
+    pending("implementation of Hash functionality matching prefix")
+    is_expected.to run.with_params({}, '').and_return({})
+  }
+  it {
+    pending("implementation of Hash functionality matching prefix")
+    is_expected.to run.with_params({ 'key' => 'value' }, '').and_return({ 'key' => 'value' })
+  }
+  it {
+    pending("implementation of Hash functionality matching prefix")
+    is_expected.to run.with_params({ 'key' => 'value' }, 'post').and_return({ 'keypost' => 'value' })
+  }
+  it {
+    pending("implementation of Hash functionality matching prefix")
+    is_expected.to run \
+      .with_params({ 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3' }, 'pre') \
+      .and_return({ 'key1post' => 'value1', 'key2post' => 'value2', 'key3post' => 'value3' })
+  }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/swapcase_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe 'swapcase' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params('a', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+  it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+  it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+  describe 'with strings as inputs' do
+    it { is_expected.to run.with_params('').and_return('') }
+    it { is_expected.to run.with_params('one').and_return('ONE') }
+    it { is_expected.to run.with_params('ONE').and_return('one') }
+    it { is_expected.to run.with_params('oNe').and_return('OnE') }
+  end
+  describe 'with arrays as inputs' do
+    it { is_expected.to run.with_params([]).and_return([]) }
+    describe 'only containing strings' do
+      it { is_expected.to run.with_params(['']).and_return(['']) }
+      it { is_expected.to run.with_params(['one']).and_return(['ONE']) }
+      it { is_expected.to run.with_params(['ONE']).and_return(['one']) }
+      it { is_expected.to run.with_params(['oNe']).and_return(['OnE']) }
+      it { is_expected.to run.with_params(['one', 'ONE']).and_return(['ONE', 'one']) }
+      it { is_expected.to run.with_params(['ONE', 'OnE']).and_return(['one', 'oNe']) }
+      it { is_expected.to run.with_params(['oNe', 'one']).and_return(['OnE', 'ONE']) }
+    end
+    describe 'containing mixed types' do
+      it { is_expected.to run.with_params(['OnE', {}]).and_return(['oNe', {}]) }
+      it { is_expected.to run.with_params(['OnE', 1]).and_return(['oNe', 1]) }
+      it { is_expected.to run.with_params(['OnE', []]).and_return(['oNe', []]) }
+      it { is_expected.to run.with_params(['OnE', ['two']]).and_return(['oNe', ['two']]) }
+    end
+  end
+  it "should accept objects which extend String" do
+    is_expected.to run.with_params(AlsoString.new("OnE")).and_return('oNe')
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/time_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe 'time' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params('a', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+  context 'when running at a specific time' do
+    before(:each) {
+      # get a value before stubbing the function
+      test_time = Time.utc(2006, 10, 13, 8, 15, 11)
+      Time.expects(:new).with().returns(test_time).once
+    }
+    it { is_expected.to run.with_params().and_return(1160727311) }
+    it { is_expected.to run.with_params('').and_return(1160727311) }
+    it { is_expected.to run.with_params([]).and_return(1160727311) }
+    it { is_expected.to run.with_params({}).and_return(1160727311) }
+    it { is_expected.to run.with_params('foo').and_return(1160727311) }
+    it { is_expected.to run.with_params('UTC').and_return(1160727311) }
+    it { is_expected.to run.with_params('America/New_York').and_return(1160727311) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/to_bytes_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,72 @@
+require 'spec_helper'
+
+describe 'to_bytes' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params('1', 'extras').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params([]).and_raise_error(TypeError, /(can't convert|no implicit conversion of) Array (in)?to String/) }
+  it { is_expected.to run.with_params({}).and_raise_error(TypeError, /(can't convert|no implicit conversion of) Hash (in)?to String/) }
+  it { is_expected.to run.with_params(true).and_raise_error(TypeError, /(can't convert|no implicit conversion of) (TrueClass|true) (in)?to String/) }
+
+  describe 'when passing numbers' do
+    it { is_expected.to run.with_params(0).and_return(0) }
+    it { is_expected.to run.with_params(1).and_return(1) }
+    it { is_expected.to run.with_params(-1).and_return(-1) }
+    it { is_expected.to run.with_params(1.1).and_return(1.1) }
+    it { is_expected.to run.with_params(-1.1).and_return(-1.1) }
+  end
+
+  describe 'when passing numbers as strings' do
+    describe 'without a unit' do
+      it { is_expected.to run.with_params('1').and_return(1) }
+      it { is_expected.to run.with_params('-1').and_return(-1) }
+      # these are so wrong
+      it { is_expected.to run.with_params('1.1').and_return(1) }
+      it { is_expected.to run.with_params('-1.1').and_return(-1) }
+    end
+
+    describe 'with a unit' do
+      it { is_expected.to run.with_params('1k').and_return(1024) }
+      it { is_expected.to run.with_params('-1kB').and_return(-1024) }
+      it { is_expected.to run.with_params('1k').and_return(1024) }
+      it { is_expected.to run.with_params('1M').and_return(1024*1024) }
+      it { is_expected.to run.with_params('1G').and_return(1024*1024*1024) }
+      it { is_expected.to run.with_params('1T').and_return(1024*1024*1024*1024) }
+      it { is_expected.to run.with_params('1P').and_return(1024*1024*1024*1024*1024) }
+      it { is_expected.to run.with_params('1E').and_return(1024*1024*1024*1024*1024*1024) }
+      it { is_expected.to run.with_params('1.5e3M').and_return(1572864000) }
+
+      it { is_expected.to run.with_params('4k').and_return(4*1024) }
+      it { is_expected.to run.with_params('-4kB').and_return(4*-1024) }
+      it { is_expected.to run.with_params('4k').and_return(4*1024) }
+      it { is_expected.to run.with_params('4M').and_return(4*1024*1024) }
+      it { is_expected.to run.with_params('4G').and_return(4*1024*1024*1024) }
+      it { is_expected.to run.with_params('4T').and_return(4*1024*1024*1024*1024) }
+      it { is_expected.to run.with_params('4P').and_return(4*1024*1024*1024*1024*1024) }
+      it { is_expected.to run.with_params('4E').and_return(4*1024*1024*1024*1024*1024*1024) }
+
+      # these are so wrong
+      it { is_expected.to run.with_params('1.0001 k').and_return(1024) }
+      it { is_expected.to run.with_params('-1.0001 kB').and_return(-1024) }
+    end
+
+    describe 'with a unknown unit' do
+      it { is_expected.to run.with_params('1KB').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+      it { is_expected.to run.with_params('1K').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+      it { is_expected.to run.with_params('1mb').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+      it { is_expected.to run.with_params('1m').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+      it { is_expected.to run.with_params('1%').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+      it { is_expected.to run.with_params('1 p').and_raise_error(Puppet::ParseError, /Unknown prefix/) }
+    end
+  end
+
+  # these are so wrong
+  describe 'when passing random stuff' do
+    it { is_expected.to run.with_params('-1....1').and_return(-1) }
+    it { is_expected.to run.with_params('-1.e.e.e.1').and_return(-1) }
+    it { is_expected.to run.with_params('-1+1').and_return(-1) }
+    it { is_expected.to run.with_params('1-1').and_return(1) }
+    it { is_expected.to run.with_params('1 kaboom').and_return(1024) }
+    it { is_expected.to run.with_params('kaboom').and_return(0) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/try_get_value_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,100 @@
+require 'spec_helper'
+
+describe 'try_get_value' do
+
+  let(:data) do
+    {
+        'a' => {
+            'g' => '2',
+            'e' => [
+                'f0',
+                'f1',
+                {
+                    'x' => {
+                        'y' => 'z'
+                    }
+                },
+                'f3',
+            ]
+        },
+        'b' => true,
+        'c' => false,
+        'd' => '1',
+    }
+  end
+
+  context 'single values' do
+    it 'should exist' do
+      is_expected.not_to eq(nil)
+    end
+
+    it 'should be able to return a single value' do
+      is_expected.to run.with_params('test').and_return('test')
+    end
+
+    it 'should use the default value if data is a single value and path is present' do
+      is_expected.to run.with_params('test', 'path', 'default').and_return('default')
+    end
+
+    it 'should return default if there is no data' do
+      is_expected.to run.with_params(nil, nil, 'default').and_return('default')
+    end
+
+    it 'should be able to use data structures as default values' do
+      is_expected.to run.with_params('test', 'path', data).and_return(data)
+    end
+  end
+
+  context 'structure values' do
+    it 'should be able to extracts a single hash value' do
+      is_expected.to run.with_params(data, 'd', 'default').and_return('1')
+    end
+
+    it 'should be able to extract a deeply nested hash value' do
+      is_expected.to run.with_params(data, 'a/g', 'default').and_return('2')
+    end
+
+    it 'should return the default value if the path is not found' do
+      is_expected.to run.with_params(data, 'missing', 'default').and_return('default')
+    end
+
+    it 'should return the default value if the path is too long' do
+      is_expected.to run.with_params(data, 'a/g/c/d', 'default').and_return('default')
+    end
+
+    it 'should support an array index in the path' do
+      is_expected.to run.with_params(data, 'a/e/1', 'default').and_return('f1')
+    end
+
+    it 'should return the default value if an array index is not a number' do
+      is_expected.to run.with_params(data, 'a/b/c', 'default').and_return('default')
+    end
+
+    it 'should return the default value if and index is out of array length' do
+      is_expected.to run.with_params(data, 'a/e/5', 'default').and_return('default')
+    end
+
+    it 'should be able to path though both arrays and hashes' do
+      is_expected.to run.with_params(data, 'a/e/2/x/y', 'default').and_return('z')
+    end
+
+    it 'should be able to return "true" value' do
+      is_expected.to run.with_params(data, 'b', 'default').and_return(true)
+      is_expected.to run.with_params(data, 'm', true).and_return(true)
+    end
+
+    it 'should be able to return "false" value' do
+      is_expected.to run.with_params(data, 'c', 'default').and_return(false)
+      is_expected.to run.with_params(data, 'm', false).and_return(false)
+    end
+
+    it 'should return "nil" if value is not found and no default value is provided' do
+      is_expected.to run.with_params(data, 'a/1').and_return(nil)
+    end
+
+    it 'should be able to use a custom path separator' do
+      is_expected.to run.with_params(data, 'a::g', 'default', '::').and_return('2')
+      is_expected.to run.with_params(data, 'a::c', 'default', '::').and_return('default')
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/type3x_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+describe 'type3x' do
+  it "should exist" do
+    expect(Puppet::Parser::Functions.function("type3x")).to eq("function_type3x")
+  end
+
+  it "should raise a ParseError if there is less than 1 arguments" do
+    expect { scope.function_type3x([]) }.to( raise_error(Puppet::ParseError))
+  end
+
+  it "should return string when given a string" do
+    result = scope.function_type3x(["aaabbbbcccc"])
+    expect(result).to(eq('string'))
+  end
+
+  it "should return array when given an array" do
+    result = scope.function_type3x([["aaabbbbcccc","asdf"]])
+    expect(result).to(eq('array'))
+  end
+
+  it "should return hash when given a hash" do
+    result = scope.function_type3x([{"a"=>1,"b"=>2}])
+    expect(result).to(eq('hash'))
+  end
+
+  it "should return integer when given an integer" do
+    result = scope.function_type3x(["1"])
+    expect(result).to(eq('integer'))
+  end
+
+  it "should return float when given a float" do
+    result = scope.function_type3x(["1.34"])
+    expect(result).to(eq('float'))
+  end
+
+  it "should return boolean when given a boolean" do
+    result = scope.function_type3x([true])
+    expect(result).to(eq('boolean'))
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/type_of_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+if ENV["FUTURE_PARSER"] == 'yes'
+  describe 'type_of' do
+    pending 'teach rspec-puppet to load future-only functions under 3.7.5'
+  end
+end
+
+if Puppet.version.to_f >= 4.0
+  describe 'type_of' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(ArgumentError) }
+    it { is_expected.to run.with_params('', '').and_raise_error(ArgumentError) }
+
+    it 'gives the type of a string' do
+      expect(subject.call({}, 'hello world')).to be_kind_of(Puppet::Pops::Types::PStringType)
+    end
+
+    it 'gives the type of an integer' do
+      expect(subject.call({}, 5)).to be_kind_of(Puppet::Pops::Types::PIntegerType)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/type_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+require 'spec_helper'
+
+describe 'type' do
+  it "should exist" do
+    expect(Puppet::Parser::Functions.function("type")).to eq("function_type")
+  end
+
+  it "should give a deprecation warning when called" do
+    scope.expects(:warning).with("type() DEPRECATED: This function will cease to function on Puppet 4; please use type3x() before upgrading to puppet 4 for backwards-compatibility, or migrate to the new parser's typing system.")
+    scope.function_type(["aoeu"])
+  end
+
+  it "should return string when given a string" do
+    result = scope.function_type(["aaabbbbcccc"])
+    expect(result).to(eq('string'))
+  end
+
+  it "should return array when given an array" do
+    result = scope.function_type([["aaabbbbcccc","asdf"]])
+    expect(result).to(eq('array'))
+  end
+
+  it "should return hash when given a hash" do
+    result = scope.function_type([{"a"=>1,"b"=>2}])
+    expect(result).to(eq('hash'))
+  end
+
+  it "should return integer when given an integer" do
+    result = scope.function_type(["1"])
+    expect(result).to(eq('integer'))
+  end
+
+  it "should return float when given a float" do
+    result = scope.function_type(["1.34"])
+    expect(result).to(eq('float'))
+  end
+
+  it "should return boolean when given a boolean" do
+    result = scope.function_type([true])
+    expect(result).to(eq('boolean'))
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/union_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'union' do
+  describe 'argument checking' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('one', []).and_raise_error(Puppet::ParseError, /Every parameter must be an array/) }
+    it { is_expected.to run.with_params([], 'two').and_raise_error(Puppet::ParseError, /Every parameter must be an array/) }
+    it { is_expected.to run.with_params({}, {}).and_raise_error(Puppet::ParseError, /Every parameter must be an array/) }
+  end
+
+  it { is_expected.to run.with_params([], []).and_return([]) }
+  it { is_expected.to run.with_params([], ['one']).and_return(['one']) }
+  it { is_expected.to run.with_params(['one'], []).and_return(['one']) }
+  it { is_expected.to run.with_params(['one'], ['one']).and_return(['one']) }
+  it { is_expected.to run.with_params(['one'], ['two']).and_return(['one', 'two']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'three']).and_return(['one', 'two', 'three']) }
+  it { is_expected.to run.with_params(['one', 'two', 'two', 'three'], ['two', 'three']).and_return(['one', 'two', 'three']) }
+  it { is_expected.to run.with_params(['one', 'two', 'three'], ['two', 'two', 'three']).and_return(['one', 'two', 'three']) }
+  it { is_expected.to run.with_params(['one', 'two'], ['two', 'three'], ['one', 'three']).and_return(['one', 'two', 'three']) }
+  it { is_expected.to run.with_params(['one', 'two'], ['three', 'four'], ['one', 'two', 'three'], ['four']).and_return(['one', 'two', 'three', 'four']) }
+  it 'should not confuse types' do is_expected.to run.with_params(['1', '2', '3'], [1, 2]).and_return(['1', '2', '3', 1, 2]) end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/unique_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe 'unique' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it {
+      pending("Current implementation ignores parameters after the first.")
+      is_expected.to run.with_params([], 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+    }
+    it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+    it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+    it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+  end
+
+  context 'when called with an array' do
+    it { is_expected.to run.with_params([]).and_return([]) }
+    it { is_expected.to run.with_params(['a']).and_return(['a']) }
+    it { is_expected.to run.with_params(['a', 'b', 'a']).and_return(['a', 'b']) }
+  end
+
+  context 'when called with a string' do
+    it { is_expected.to run.with_params('').and_return('') }
+    it { is_expected.to run.with_params('a').and_return('a') }
+    it { is_expected.to run.with_params('aaba').and_return('ab') }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/unix2dos_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe 'unix2dos' do
+  context 'Checking parameter validity' do
+    it { is_expected.not_to eq(nil) }
+    it do
+      is_expected.to run.with_params.and_raise_error(ArgumentError, /Wrong number of arguments/)
+    end
+    it do
+      is_expected.to run.with_params('one', 'two').and_raise_error(ArgumentError, /Wrong number of arguments/)
+    end
+    it do
+      is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError)
+    end
+    it do
+      is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError)
+    end
+    it do
+      is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError)
+    end
+  end
+
+  context 'Converting from unix to dos format' do
+    sample_text    = "Hello\nWorld\n"
+    desired_output = "Hello\r\nWorld\r\n"
+
+    it 'should output dos format' do
+      should run.with_params(sample_text).and_return(desired_output)
+    end
+  end
+
+  context 'Converting from dos to dos format' do
+    sample_text    = "Hello\r\nWorld\r\n"
+    desired_output = "Hello\r\nWorld\r\n"
+
+    it 'should output dos format' do
+      should run.with_params(sample_text).and_return(desired_output)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/upcase_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe 'upcase' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires an array, hash or object that responds to upcase/) }
+    it { is_expected.to run.with_params([1]).and_raise_error(Puppet::ParseError, /Requires an array, hash or object that responds to upcase/) }
+  end
+
+  describe 'normal string handling' do
+    it { is_expected.to run.with_params("abc").and_return("ABC") }
+    it { is_expected.to run.with_params("Abc").and_return("ABC") }
+    it { is_expected.to run.with_params("ABC").and_return("ABC") }
+  end
+
+  describe 'handling classes derived from String' do
+    it { is_expected.to run.with_params(AlsoString.new("ABC")).and_return("ABC") }
+  end
+
+  describe 'strings in arrays handling' do
+    it { is_expected.to run.with_params([]).and_return([]) }
+    it { is_expected.to run.with_params(["One", "twO"]).and_return(["ONE", "TWO"]) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/uriescape_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,36 @@
+require 'spec_helper'
+
+describe 'uriescape' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it {
+      pending("Current implementation ignores parameters after the first.")
+      is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+    }
+    it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+    it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+    it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /Requires either array or string to work/) }
+  end
+
+  describe 'handling normal strings' do
+    it 'should call ruby\'s URI.escape function' do
+      URI.expects(:escape).with('uri_string').returns('escaped_uri_string').once
+      is_expected.to run.with_params('uri_string').and_return('escaped_uri_string') 
+    end
+  end
+
+  describe 'handling classes derived from String' do
+    it 'should call ruby\'s URI.escape function' do
+      uri_string = AlsoString.new('uri_string')
+      URI.expects(:escape).with(uri_string).returns('escaped_uri_string').once
+      is_expected.to run.with_params(uri_string).and_return("escaped_uri_string") 
+    end
+  end
+
+  describe 'strings in arrays handling' do
+    it { is_expected.to run.with_params([]).and_return([]) }
+    it { is_expected.to run.with_params(["one}", "two"]).and_return(["one%7D", "two"]) }
+    it { is_expected.to run.with_params(["one}", 1, true, {}, "two"]).and_return(["one%7D", 1, true, {}, "two"]) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_absolute_path_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,62 @@
+require 'spec_helper'
+
+describe 'validate_absolute_path' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  end
+
+  describe "valid paths handling" do
+    %w{
+      C:/
+      C:\\
+      C:\\WINDOWS\\System32
+      C:/windows/system32
+      X:/foo/bar
+      X:\\foo\\bar
+      \\\\host\\windows
+      //host/windows
+      /
+      /var/tmp
+      /var/opt/../lib/puppet
+    }.each do |path|
+      it { is_expected.to run.with_params(path) }
+      it { is_expected.to run.with_params(['/tmp', path]) }
+    end
+  end
+
+  describe 'invalid path handling' do
+    context 'garbage inputs' do
+      [
+        nil,
+        [ nil ],
+        [ nil, nil ],
+        { 'foo' => 'bar' },
+        { },
+        '',
+      ].each do |path|
+        it { is_expected.to run.with_params(path).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
+        it { is_expected.to run.with_params([path]).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
+        it { is_expected.to run.with_params(['/tmp', path]).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
+      end
+    end
+
+    context 'relative paths' do
+      %w{
+        relative1
+        .
+        ..
+        ./foo
+        ../foo
+        etc/puppetlabs/puppet
+        opt/puppet/bin
+        relative\\windows
+      }.each do |path|
+        it { is_expected.to run.with_params(path).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
+        it { is_expected.to run.with_params([path]).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
+        it { is_expected.to run.with_params(['/tmp', path]).and_raise_error(Puppet::ParseError, /is not an absolute path/) }
+      end
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_array_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe 'validate_array' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+    describe 'valid inputs' do
+      it { is_expected.to run.with_params([]) }
+      it { is_expected.to run.with_params(['one']) }
+      it { is_expected.to run.with_params([], ['two']) }
+      it { is_expected.to run.with_params(['one'], ['two']) }
+    end
+
+    describe 'invalid inputs' do
+      it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /is not an Array/) }
+      it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not an Array/) }
+      it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not an Array/) }
+      it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not an Array/) }
+      it { is_expected.to run.with_params([], {}).and_raise_error(Puppet::ParseError, /is not an Array/) }
+      it { is_expected.to run.with_params([], 1).and_raise_error(Puppet::ParseError, /is not an Array/) }
+      it { is_expected.to run.with_params([], true).and_raise_error(Puppet::ParseError, /is not an Array/) }
+      it { is_expected.to run.with_params([], 'one').and_raise_error(Puppet::ParseError, /is not an Array/) }
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_augeas_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,75 @@
+require 'spec_helper'
+
+describe 'validate_augeas' do
+  unless Puppet.features.augeas?
+    skip "ruby-augeas not installed"
+  else
+    describe 'signature validation' do
+      it { is_expected.not_to eq(nil) }
+      it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+      it { is_expected.to run.with_params('').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+      it { is_expected.to run.with_params('', '', [], '', 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+      it { is_expected.to run.with_params('one', 'one', 'MSG to User', '4th arg').and_raise_error(NoMethodError) }
+    end
+
+    describe 'valid inputs' do
+      inputs = [
+        [ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns' ],
+        [ "proc /proc   proc    nodev,noexec,nosuid     0       0\n", 'Fstab.lns'],
+      ]
+
+      inputs.each do |input|
+        it { is_expected.to run.with_params(*input) }
+      end
+    end
+
+    describe 'valid inputs which fail augeas validation' do
+      # The intent here is to make sure valid inputs raise exceptions when they
+      # don't specify an error message to display.  This is the behvior in
+      # 2.2.x and prior.
+      inputs = [
+        [ "root:x:0:0:root\n", 'Passwd.lns' ],
+        [ "127.0.1.1\n", 'Hosts.lns' ],
+      ]
+
+      inputs.each do |input|
+        it { is_expected.to run.with_params(*input).and_raise_error(Puppet::ParseError, /validate_augeas.*?matched less than it should/) }
+      end
+    end
+
+    describe "when specifying nice error messages" do
+      # The intent here is to make sure the function returns the 4th argument
+      # in the exception thrown
+      inputs = [
+        [ "root:x:0:0:root\n", 'Passwd.lns', [], 'Failed to validate passwd content' ],
+        [ "127.0.1.1\n", 'Hosts.lns', [], 'Wrong hosts content' ],
+      ]
+
+      inputs.each do |input|
+        it { is_expected.to run.with_params(*input).and_raise_error(Puppet::ParseError, /#{input[3]}/) }
+      end
+    end
+
+    describe "matching additional tests" do
+      inputs = [
+        [ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/foobar']],
+        [ "root:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/root/shell[.="/bin/sh"]', 'foobar']],
+      ]
+
+      inputs.each do |input|
+        it { is_expected.to run.with_params(*input) }
+      end
+    end
+
+    describe "failing additional tests" do
+      inputs = [
+        [ "foobar:x:0:0:root:/root:/bin/bash\n", 'Passwd.lns', ['$file/foobar']],
+        [ "root:x:0:0:root:/root:/bin/sh\n", 'Passwd.lns', ['$file/root/shell[.="/bin/sh"]', 'foobar']],
+      ]
+
+      inputs.each do |input|
+        it { is_expected.to run.with_params(*input).and_raise_error(Puppet::ParseError, /testing path/) }
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_bool_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe 'validate_bool' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  end
+
+  describe 'acceptable values' do
+    it { is_expected.to run.with_params(true) }
+    it { is_expected.to run.with_params(false) }
+    it { is_expected.to run.with_params(true, false, false, true) }
+  end
+
+  describe 'validation failures' do
+    it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not a boolean/) }
+    it { is_expected.to run.with_params(true, 'one').and_raise_error(Puppet::ParseError, /is not a boolean/) }
+    it { is_expected.to run.with_params('one', false).and_raise_error(Puppet::ParseError, /is not a boolean/) }
+    it { is_expected.to run.with_params("true").and_raise_error(Puppet::ParseError, /is not a boolean/) }
+    it { is_expected.to run.with_params("false").and_raise_error(Puppet::ParseError, /is not a boolean/) }
+    it { is_expected.to run.with_params(true, "false").and_raise_error(Puppet::ParseError, /is not a boolean/) }
+    it { is_expected.to run.with_params("true", false).and_raise_error(Puppet::ParseError, /is not a boolean/) }
+    it { is_expected.to run.with_params("true", false, false, false, false, false).and_raise_error(Puppet::ParseError, /is not a boolean/) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_cmd_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,35 @@
+require 'spec_helper'
+
+describe 'validate_cmd' do
+  let(:touch) { File.exists?('/usr/bin/touch') ? '/usr/bin/touch' : '/bin/touch' }
+
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('', '', '', 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it {
+      pending('should implement stricter type checking')
+      is_expected.to run.with_params([], '', '').and_raise_error(Puppet::ParseError, /content must be a string/)
+    }
+    it {
+      pending('should implement stricter type checking')
+      is_expected.to run.with_params('', [], '').and_raise_error(Puppet::ParseError, /checkscript must be a string/)
+    }
+    it {
+      pending('should implement stricter type checking')
+      is_expected.to run.with_params('', '', []).and_raise_error(Puppet::ParseError, /custom error message must be a string/)
+    }
+  end
+
+  context 'when validation fails' do
+    context 'with % placeholder' do
+      it { is_expected.to run.with_params('', "#{touch} % /no/such/file").and_raise_error(Puppet::ParseError, /Execution of '#{touch} \S+ \/no\/such\/file' returned 1:.*(cannot touch|o such file or)/) }
+      it { is_expected.to run.with_params('', "#{touch} % /no/such/file", 'custom error').and_raise_error(Puppet::ParseError, /custom error/) }
+    end
+    context 'without % placeholder' do
+      it { is_expected.to run.with_params('', "#{touch} /no/such/file").and_raise_error(Puppet::ParseError, /Execution of '#{touch} \/no\/such\/file \S+' returned 1:.*(cannot touch|o such file or)/) }
+      it { is_expected.to run.with_params('', "#{touch} /no/such/file", 'custom error').and_raise_error(Puppet::ParseError, /custom error/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_hash_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+describe 'validate_hash' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+    describe 'valid inputs' do
+      it { is_expected.to run.with_params({}) }
+      it { is_expected.to run.with_params({'key' => 'value'}) }
+      it { is_expected.to run.with_params({}, {'key' => 'value'}) }
+      it { is_expected.to run.with_params({'key1' => 'value1'}, {'key2' => 'value2'}) }
+    end
+
+    describe 'invalid inputs' do
+      it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+      it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+      it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+      it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not a Hash/) }
+      it { is_expected.to run.with_params({}, []).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+      it { is_expected.to run.with_params({}, 1).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+      it { is_expected.to run.with_params({}, true).and_raise_error(Puppet::ParseError, /is not a Hash/) }
+      it { is_expected.to run.with_params({}, 'one').and_raise_error(Puppet::ParseError, /is not a Hash/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_integer_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,90 @@
+require 'spec_helper'
+
+describe 'validate_integer' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params(1, 2, 3, 4).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+    [ true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', 7.0, -7.0, {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x'].each do |invalid|
+      it { is_expected.to run.with_params(invalid).and_raise_error(Puppet::ParseError, /to be an Integer/) }
+      it { is_expected.to run.with_params(invalid, 10).and_raise_error(Puppet::ParseError, /to be an Integer/) }
+      it { is_expected.to run.with_params(invalid, 10, -10).and_raise_error(Puppet::ParseError, /to be an Integer/) }
+      it { is_expected.to run.with_params([0, 1, 2, invalid, 3, 4], 10, -10).and_raise_error(Puppet::ParseError, /to be an Integer/) }
+    end
+
+    context 'when running on modern rubies', :unless => RUBY_VERSION == '1.8.7' do
+      it { is_expected.to run.with_params([0, 1, 2, {1=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError, /to be an Integer/) }
+    end
+
+    context 'when running on ruby, which munges hashes weirdly', :if => RUBY_VERSION == '1.8.7' do
+      it { is_expected.to run.with_params([0, 1, 2, {1=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError) }
+      it { is_expected.to run.with_params([0, 1, 2, {0=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError) }
+    end
+
+    it { is_expected.to run.with_params(1, '').and_raise_error(Puppet::ParseError, /to be unset or an Integer/) }
+    it { is_expected.to run.with_params(1, 2, '').and_raise_error(Puppet::ParseError, /to be unset or an Integer/) }
+    it { is_expected.to run.with_params(1, 2, 3).and_raise_error(Puppet::ParseError, /second argument to be larger than third argument/) }
+  end
+
+  context 'with no range constraints' do
+    it { is_expected.to run.with_params(1) }
+    it { is_expected.to run.with_params(-1) }
+    it { is_expected.to run.with_params('1') }
+    it { is_expected.to run.with_params('-1') }
+    it { is_expected.to run.with_params([1, 2, 3, 4]) }
+    it { is_expected.to run.with_params([1, '2', '3', 4]) }
+  end
+
+  context "with a maximum limit of 10" do
+    describe 'rejects numbers greater than the limit' do
+      it { is_expected.to run.with_params(11, 10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+      it { is_expected.to run.with_params(100, 10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+      it { is_expected.to run.with_params(2**65, 10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+      it { is_expected.to run.with_params([1,2,10,100], 10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+    end
+
+    describe 'accepts numbers less or equal to the limit' do
+      it { is_expected.to run.with_params(10, 10) }
+      it { is_expected.to run.with_params(1, 10) }
+      it { is_expected.to run.with_params(-1, 10) }
+      it { is_expected.to run.with_params('1', 10) }
+      it { is_expected.to run.with_params('-1', 10) }
+      it { is_expected.to run.with_params([1, 2, 3, 4], 10) }
+      it { is_expected.to run.with_params([1, '2', '3', 4], 10) }
+    end
+
+    context "with a minimum limit of -10" do
+      describe 'rejects numbers greater than the upper limit' do
+        it { is_expected.to run.with_params(11, 10, -10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+        it { is_expected.to run.with_params(100, 10, -10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+        it { is_expected.to run.with_params(2**65, 10, -10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+        it { is_expected.to run.with_params([1,2,10,100], 10, -10).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+      end
+
+      describe 'rejects numbers smaller than the lower limit' do
+        it { is_expected.to run.with_params(-11, 10, -10).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+        it { is_expected.to run.with_params(-100, 10, -10).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+        it { is_expected.to run.with_params(-2**65, 10, -10).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+        it { is_expected.to run.with_params([-10, 1,2,10,-100], 10, -10).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+      end
+
+      describe 'accepts numbers between and including the limits' do
+        it { is_expected.to run.with_params(10, 10, -10) }
+        it { is_expected.to run.with_params(-10, 10, -10) }
+        it { is_expected.to run.with_params(1, 10, -10) }
+        it { is_expected.to run.with_params(-1, 10, -10) }
+        it { is_expected.to run.with_params('1', 10, -10) }
+        it { is_expected.to run.with_params('-1', 10, -10) }
+        it { is_expected.to run.with_params([1, 2, 3, 4], 10, -10) }
+        it { is_expected.to run.with_params([1, '2', '3', 4], 10, -10) }
+      end
+    end
+  end
+
+  it { is_expected.to run.with_params(10, 10, 10) }
+
+  describe 'empty upper limit is interpreted as infinity' do
+    it { is_expected.to run.with_params(11, '', 10) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_ipv4_address_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe 'validate_ipv4_address' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+    describe 'valid inputs' do
+      it { is_expected.to run.with_params('0.0.0.0') }
+      it { is_expected.to run.with_params('8.8.8.8') }
+      it { is_expected.to run.with_params('127.0.0.1') }
+      it { is_expected.to run.with_params('10.10.10.10') }
+      it { is_expected.to run.with_params('194.232.104.150') }
+      it { is_expected.to run.with_params('244.24.24.24') }
+      it { is_expected.to run.with_params('255.255.255.255') }
+      it { is_expected.to run.with_params('1.2.3.4', '5.6.7.8') }
+      context 'with netmasks' do
+        it { is_expected.to run.with_params('8.8.8.8/0') }
+        it { is_expected.to run.with_params('8.8.8.8/16') }
+        it { is_expected.to run.with_params('8.8.8.8/32') }
+        it { is_expected.to run.with_params('8.8.8.8/255.255.0.0') }
+      end
+    end
+
+    describe 'invalid inputs' do
+      it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not a valid IPv4/) }
+      it { is_expected.to run.with_params('0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IPv4/) }
+      it { is_expected.to run.with_params('0.0.0.256').and_raise_error(Puppet::ParseError, /is not a valid IPv4/) }
+      it { is_expected.to run.with_params('0.0.0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IPv4/) }
+      it { is_expected.to run.with_params('affe::beef').and_raise_error(Puppet::ParseError, /is not a valid IPv4/) }
+      it { is_expected.to run.with_params('1.2.3.4', {}).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params('1.2.3.4', 1).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params('1.2.3.4', true).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params('1.2.3.4', 'one').and_raise_error(Puppet::ParseError, /is not a valid IPv4/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_ipv6_address_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe 'validate_ipv6_address' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+    describe 'valid inputs' do
+      it { is_expected.to run.with_params('3ffe:0505:0002::') }
+      it { is_expected.to run.with_params('3ffe:0505:0002::', '3ffe:0505:0002::2') }
+      it { is_expected.to run.with_params('::1/64') }
+      it { is_expected.to run.with_params('fe80::a00:27ff:fe94:44d6/64') }
+    end
+
+    describe 'invalid inputs' do
+      it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params('one').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+      it { is_expected.to run.with_params('0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+      it { is_expected.to run.with_params('0.0.0.256').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+      it { is_expected.to run.with_params('0.0.0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+      it { is_expected.to run.with_params('affe:beef').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+      it { is_expected.to run.with_params('::1', {}).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params('::1', true).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params('::1', 'one').and_raise_error(Puppet::ParseError, /is not a valid IPv6/) }
+      context 'unless running on ruby 1.8.7', :if => RUBY_VERSION != '1.8.7' do
+        it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not a string/) }
+        it { is_expected.to run.with_params('::1', 1).and_raise_error(Puppet::ParseError, /is not a string/) }
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_numeric_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,89 @@
+require 'spec_helper'
+
+describe 'validate_numeric' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params(1, 2, 3, 4).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+    [ true, 'true', false, 'false', 'iAmAString', '1test', '1 test', 'test 1', 'test 1 test', {}, { 'key' => 'value' }, { 1=> 2 }, '', :undef , 'x'].each do |invalid|
+      it { is_expected.to run.with_params(invalid).and_raise_error(Puppet::ParseError, /to be a Numeric/) }
+      it { is_expected.to run.with_params(invalid, 10.0).and_raise_error(Puppet::ParseError, /to be a Numeric/) }
+      it { is_expected.to run.with_params(invalid, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be a Numeric/) }
+    end
+
+    context 'when running on modern rubies', :unless => RUBY_VERSION == '1.8.7' do
+      it { is_expected.to run.with_params([0, 1, 2, {1=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError, /to be a Numeric/) }
+    end
+
+    context 'when running on ruby, which munges hashes weirdly', :if => RUBY_VERSION == '1.8.7' do
+      it { is_expected.to run.with_params([0, 1, 2, {1=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError) }
+      it { is_expected.to run.with_params([0, 1, 2, {0=>2}, 3, 4], 10, -10).and_raise_error(Puppet::ParseError) }
+    end
+
+    it { is_expected.to run.with_params(1, '').and_raise_error(Puppet::ParseError, /to be unset or a Numeric/) }
+    it { is_expected.to run.with_params(1, 2, '').and_raise_error(Puppet::ParseError, /to be unset or a Numeric/) }
+    it { is_expected.to run.with_params(1, 2, 3).and_raise_error(Puppet::ParseError, /second argument to be larger than third argument/) }
+  end
+
+  context 'with no range constraints' do
+    it { is_expected.to run.with_params(1) }
+    it { is_expected.to run.with_params(-1) }
+    it { is_expected.to run.with_params('1') }
+    it { is_expected.to run.with_params('-1') }
+    it { is_expected.to run.with_params([1, 2, 3, 4]) }
+    it { is_expected.to run.with_params([1, '2', '3', 4]) }
+  end
+
+  context "with a maximum limit of 10.0" do
+    describe 'rejects numbers greater than the limit' do
+      it { is_expected.to run.with_params(11, 10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+      it { is_expected.to run.with_params(100, 10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+      it { is_expected.to run.with_params(2**65, 10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+      it { is_expected.to run.with_params([1,2,10.0,100], 10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+    end
+
+    describe 'accepts numbers less or equal to the limit' do
+      it { is_expected.to run.with_params(10.0, 10.0) }
+      it { is_expected.to run.with_params(1, 10.0) }
+      it { is_expected.to run.with_params(-1, 10.0) }
+      it { is_expected.to run.with_params('1', 10.0) }
+      it { is_expected.to run.with_params('-1', 10.0) }
+      it { is_expected.to run.with_params([1, 2, 3, 4], 10.0) }
+      it { is_expected.to run.with_params([1, '2', '3', 4], 10.0) }
+    end
+
+    context "with a minimum limit of -10.0" do
+      describe 'rejects numbers greater than the upper limit' do
+        it { is_expected.to run.with_params(11, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+        it { is_expected.to run.with_params(100, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+        it { is_expected.to run.with_params(2**65, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+        it { is_expected.to run.with_params([1,2,10.0,100], 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be smaller or equal/) }
+      end
+
+      describe 'rejects numbers smaller than the lower limit' do
+        it { is_expected.to run.with_params(-11, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+        it { is_expected.to run.with_params(-100, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+        it { is_expected.to run.with_params(-2**65, 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+        it { is_expected.to run.with_params([-10.0, 1,2,10.0,-100], 10.0, -10.0).and_raise_error(Puppet::ParseError, /to be greater or equal/) }
+      end
+
+      describe 'accepts numbers between and including the limits' do
+        it { is_expected.to run.with_params(10.0, 10.0, -10.0) }
+        it { is_expected.to run.with_params(-10.0, 10.0, -10.0) }
+        it { is_expected.to run.with_params(1, 10.0, -10.0) }
+        it { is_expected.to run.with_params(-1, 10.0, -10.0) }
+        it { is_expected.to run.with_params('1', 10.0, -10.0) }
+        it { is_expected.to run.with_params('-1', 10.0, -10.0) }
+        it { is_expected.to run.with_params([1, 2, 3, 4], 10.0, -10.0) }
+        it { is_expected.to run.with_params([1, '2', '3', 4], 10.0, -10.0) }
+      end
+    end
+  end
+
+  it { is_expected.to run.with_params(10.0, 10.0, 10.0) }
+
+  describe 'empty upper limit is interpreted as infinity' do
+    it { is_expected.to run.with_params(11, '', 10.0) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_re_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+require 'spec_helper'
+
+describe 'validate_re' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('', '', '', 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+    describe 'valid inputs' do
+      it { is_expected.to run.with_params('', '') }
+      it { is_expected.to run.with_params('', ['']) }
+      it { is_expected.to run.with_params('', [''], 'custom error') }
+      it { is_expected.to run.with_params('one', '^one') }
+      it { is_expected.to run.with_params('one', [ '^one', '^two' ]) }
+      it { is_expected.to run.with_params('one', [ '^one', '^two' ], 'custom error') }
+    end
+
+    describe 'invalid inputs' do
+      it {
+        pending('should implement stricter type checking')
+        is_expected.to run.with_params([], '').and_raise_error(Puppet::ParseError, /is not a String/)
+      }
+      it {
+        pending('should implement stricter type checking')
+        is_expected.to run.with_params('', {}).and_raise_error(Puppet::ParseError, /is not an Array/)
+      }
+      it {
+        pending('should implement stricter type checking')
+        is_expected.to run.with_params('', '', []).and_raise_error(Puppet::ParseError, /is not a String/)
+      }
+      it {
+        pending('should implement stricter type checking')
+        is_expected.to run.with_params(nil, nil).and_raise_error(Puppet::ParseError, /is not a String/)
+      }
+      it { is_expected.to run.with_params('', []).and_raise_error(Puppet::ParseError, /does not match/) }
+      it { is_expected.to run.with_params('one', 'two').and_raise_error(Puppet::ParseError, /does not match/) }
+      it { is_expected.to run.with_params('', 'two').and_raise_error(Puppet::ParseError, /does not match/) }
+      it { is_expected.to run.with_params('', ['two']).and_raise_error(Puppet::ParseError, /does not match/) }
+      it { is_expected.to run.with_params('', ['two'], 'custom error').and_raise_error(Puppet::ParseError, /custom error/) }
+      it { is_expected.to run.with_params('notone', '^one').and_raise_error(Puppet::ParseError, /does not match/) }
+      it { is_expected.to run.with_params('notone', [ '^one', '^two' ]).and_raise_error(Puppet::ParseError, /does not match/) }
+      it { is_expected.to run.with_params('notone', [ '^one', '^two' ], 'custom error').and_raise_error(Puppet::ParseError, /custom error/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_slength_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,61 @@
+require 'spec_helper'
+
+describe 'validate_slength' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('', 2, 3, 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params('', '').and_raise_error(Puppet::ParseError, /second argument to be a positive Numeric/) }
+    it { is_expected.to run.with_params('', -1).and_raise_error(Puppet::ParseError, /second argument to be a positive Numeric/) }
+    it { is_expected.to run.with_params('', 1, '').and_raise_error(Puppet::ParseError, /third argument to be unset or a positive Numeric/) }
+    it { is_expected.to run.with_params('', 1, -1).and_raise_error(Puppet::ParseError, /third argument to be unset or a positive Numeric/) }
+    it { is_expected.to run.with_params('', 1, 2).and_raise_error(Puppet::ParseError, /argument to be equal to or larger than third argument/) }
+  end
+
+  context "with a maximum length of 10" do
+    describe 'rejects strings longer than the limit' do
+      it { is_expected.to run.with_params('1234567890a', 10).and_raise_error(Puppet::ParseError, /Expected length/) }
+      it { is_expected.to run.with_params('1234567890abcdef', 10).and_raise_error(Puppet::ParseError, /Expected length/) }
+      it { is_expected.to run.with_params([ 'one', '1234567890abcdef' ], 10).and_raise_error(Puppet::ParseError, /Expected length/) }
+    end
+
+    describe 'accepts strings shorter or equal to the limit' do
+      it { is_expected.to run.with_params('1234567890', 10) }
+      it { is_expected.to run.with_params('12345', 10) }
+      it { is_expected.to run.with_params([ 'one', 'two' ], 10) }
+    end
+
+    context "with a minimum length of 5" do
+      describe 'rejects strings longer than the upper limit' do
+        it { is_expected.to run.with_params('1234567890a', 10, 5).and_raise_error(Puppet::ParseError, /Expected length/) }
+        it { is_expected.to run.with_params('1234567890abcdef', 10, 5).and_raise_error(Puppet::ParseError, /Expected length/) }
+      end
+
+      describe 'rejects numbers shorter than the lower limit' do
+        it { is_expected.to run.with_params('one', 10, 5).and_raise_error(Puppet::ParseError, /Expected length/) }
+        it { is_expected.to run.with_params(['12345678', 'two'], 10, 5).and_raise_error(Puppet::ParseError, /Expected length/) }
+      end
+
+      describe 'accepts strings of length between and including the limits' do
+        it { is_expected.to run.with_params('12345', 10, 5) }
+        it { is_expected.to run.with_params('123456', 10, 5) }
+        it { is_expected.to run.with_params('1234567', 10, 5) }
+        it { is_expected.to run.with_params('12345678', 10, 5) }
+        it { is_expected.to run.with_params('123456789', 10, 5) }
+        it { is_expected.to run.with_params('1234567890', 10, 5) }
+        it { is_expected.to run.with_params(['1233456', '12345678'], 10, 5) }
+      end
+    end
+  end
+
+  describe 'corner cases' do
+    it { pending('this should work'); is_expected.to run.with_params('', 0, 0) }
+    it { is_expected.to run.with_params('1234567890', 10, 10) }
+  end
+
+  describe 'empty upper limit is interpreted as infinity' do
+    it { pending('not implemented'); is_expected.to run.with_params('1234567890ab', '', 10) }
+    it { pending('not implemented'); is_expected.to run.with_params('12345678', '', 10).and_raise_error(Puppet::ParseError, /Expected length/) }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/validate_string_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe 'validate_string' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+
+    describe 'valid inputs' do
+      it { is_expected.to run.with_params('') }
+      it { is_expected.to run.with_params('one') }
+      it { is_expected.to run.with_params('one', 'two') }
+    end
+
+    describe 'invalid inputs' do
+      it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params({}).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /is not a string/) }
+      it { is_expected.to run.with_params(true).and_raise_error(Puppet::ParseError, /is not a string/) }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/values_at_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,49 @@
+require 'spec_helper'
+
+describe 'values_at' do
+  describe 'signature validation' do
+    it { is_expected.not_to eq(nil) }
+    it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+    it {
+      pending("Current implementation ignores parameters after the first two.")
+      is_expected.to run.with_params([], 0, 1).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+    }
+    it { is_expected.to run.with_params('', 1).and_raise_error(Puppet::ParseError, /Requires array/i) }
+    it { is_expected.to run.with_params({}, 1).and_raise_error(Puppet::ParseError, /Requires array/i) }
+    it { is_expected.to run.with_params(true, 1).and_raise_error(Puppet::ParseError, /Requires array/i) }
+    it { is_expected.to run.with_params(1, 1).and_raise_error(Puppet::ParseError, /Requires array/i) }
+    it { is_expected.to run.with_params([0,1,2], 'two').and_raise_error(Puppet::ParseError, /Unknown format of given index/) }
+    it { is_expected.to run.with_params([0,1,2], []).and_raise_error(Puppet::ParseError, /provide at least one positive index/) }
+    it { is_expected.to run.with_params([0,1,2], '-1-1').and_raise_error(Puppet::ParseError, /Unknown format of given index/) }
+    it { is_expected.to run.with_params([0,1,2], '2-1').and_raise_error(Puppet::ParseError, /Stop index in given indices range is smaller than the start index/) }
+  end
+
+  context 'when requesting a single item' do
+    it { is_expected.to run.with_params([0, 1, 2], -1).and_raise_error(Puppet::ParseError, /Unknown format of given index/) }
+    it { is_expected.to run.with_params([0, 1, 2], 0).and_return([0]) }
+    it { is_expected.to run.with_params([0, 1, 2], 1).and_return([1]) }
+    it { is_expected.to run.with_params([0, 1, 2], [1]).and_return([1]) }
+    it { is_expected.to run.with_params([0, 1, 2], '1').and_return([1]) }
+    it { is_expected.to run.with_params([0, 1, 2], '1-1').and_return([1]) }
+    it { is_expected.to run.with_params([0, 1, 2], 2).and_return([2]) }
+    it { is_expected.to run.with_params([0, 1, 2], 3).and_raise_error(Puppet::ParseError, /index exceeds array size/) }
+  end
+
+  context 'when requesting multiple items' do
+    it { is_expected.to run.with_params([0, 1, 2], [1, -1]).and_raise_error(Puppet::ParseError, /Unknown format of given index/) }
+    it { is_expected.to run.with_params([0, 1, 2], [0, 2]).and_return([0, 2]) }
+    it { is_expected.to run.with_params([0, 1, 2], ['0-2', 1, 2]).and_return([0, 1, 2, 1, 2]) }
+    it { is_expected.to run.with_params([0, 1, 2], [3, 2]).and_raise_error(Puppet::ParseError, /index exceeds array size/) }
+
+    describe 'different range syntaxes' do
+      it { is_expected.to run.with_params([0, 1, 2], '0-2').and_return([0, 1, 2]) }
+      it { is_expected.to run.with_params([0, 1, 2], '0..2').and_return([0, 1, 2]) }
+      it { is_expected.to run.with_params([0, 1, 2], '0...2').and_return([0, 1]) }
+      it {
+        pending('fix this bounds check')
+        is_expected.to run.with_params([0, 1, 2], '0...3').and_return([0, 1, 2])
+      }
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/values_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe 'values' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the first.")
+    is_expected.to run.with_params({}, 'extra').and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params('').and_raise_error(Puppet::ParseError, /Requires hash to work with/) }
+  it { is_expected.to run.with_params(1).and_raise_error(Puppet::ParseError, /Requires hash to work with/) }
+  it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /Requires hash to work with/) }
+  it { is_expected.to run.with_params({}).and_return([]) }
+  it { is_expected.to run.with_params({ 'key' => 'value' }).and_return(['value']) }
+  it 'should return the array of values' do
+    result = subject.call([{ 'key1' => 'value1', 'key2' => 'value2', 'duplicate_value_key' => 'value2' }])
+    expect(result).to match_array(['value1', 'value2', 'value2'])
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/functions/zip_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe 'zip' do
+  it { is_expected.not_to eq(nil) }
+  it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it { is_expected.to run.with_params([]).and_raise_error(Puppet::ParseError, /wrong number of arguments/i) }
+  it {
+    pending("Current implementation ignores parameters after the third.")
+    is_expected.to run.with_params([], [], true, []).and_raise_error(Puppet::ParseError, /wrong number of arguments/i)
+  }
+  it { is_expected.to run.with_params([], []).and_return([]) }
+  it { is_expected.to run.with_params([1,2,3], [4,5,6]).and_return([[1,4], [2,5], [3,6]]) }
+  it { is_expected.to run.with_params([1,2,3], [4,5,6], false).and_return([[1,4], [2,5], [3,6]]) }
+  it { is_expected.to run.with_params([1,2,3], [4,5,6], true).and_return([1, 4, 2, 5, 3, 6]) }
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/monkey_patches/alias_should_to_must.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+#! /usr/bin/env ruby -S rspec
+require 'rspec'
+
+class Object
+  # This is necessary because the RAL has a 'should'
+  # method.
+  alias :must :should
+  alias :must_not :should_not
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/monkey_patches/publicize_methods.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+#! /usr/bin/env ruby -S rspec
+# Some monkey-patching to allow us to test private methods.
+class Class
+    def publicize_methods(*methods)
+        saved_private_instance_methods = methods.empty? ? self.private_instance_methods : methods
+
+        self.class_eval { public(*saved_private_instance_methods) }
+        yield
+        self.class_eval { private(*saved_private_instance_methods) }
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/puppetlabs_spec_helper_clone.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,34 @@
+#This file pulls in only the minimum necessary to let unmigrated specs still work
+
+# Define the main module namespace for use by the helper modules
+module PuppetlabsSpec
+  # FIXTURE_DIR represents the standard locations of all fixture data. Normally
+  # this represents <project>/spec/fixtures. This will be used by the fixtures
+  # library to find relative fixture data.
+  FIXTURE_DIR = File.join("spec", "fixtures") unless defined?(FIXTURE_DIR)
+end
+
+# Require all necessary helper libraries so they can be used later
+require 'puppetlabs_spec_helper/puppetlabs_spec/files'
+require 'puppetlabs_spec_helper/puppetlabs_spec/fixtures'
+#require 'puppetlabs_spec_helper/puppetlabs_spec/puppet_internals'
+require 'puppetlabs_spec_helper/puppetlabs_spec/matchers'
+
+RSpec.configure do |config|
+  # Include PuppetlabsSpec helpers so they can be called at convenience
+  config.extend PuppetlabsSpec::Files
+  config.extend PuppetlabsSpec::Fixtures
+  config.include PuppetlabsSpec::Fixtures
+
+  config.parser = 'future' if ENV['FUTURE_PARSER'] == 'yes'
+  config.strict_variables = true if ENV['STRICT_VARIABLES'] == 'yes'
+  config.stringify_facts = false if ENV['STRINGIFY_FACTS'] == 'no'
+  config.trusted_node_data = true if ENV['TRUSTED_NODE_DATA'] == 'yes'
+  config.ordering = ENV['ORDERING'] if ENV['ORDERING']
+
+  # This will cleanup any files that were created with tmpdir or tmpfile
+  config.after :each do
+    PuppetlabsSpec::Files.cleanup
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/spec.opts	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+--format
+s
+--colour
+--loadby
+mtime
+--backtrace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/spec_helper.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,49 @@
+#! /usr/bin/env ruby -S rspec
+dir = File.expand_path(File.dirname(__FILE__))
+$LOAD_PATH.unshift File.join(dir, 'lib')
+
+# So everyone else doesn't have to include this base constant.
+module PuppetSpec
+  FIXTURE_DIR = File.join(dir = File.expand_path(File.dirname(__FILE__)), "fixtures") unless defined?(FIXTURE_DIR)
+end
+
+require 'puppet'
+require 'rspec-puppet'
+require 'puppetlabs_spec_helper/module_spec_helper'
+require 'monkey_patches/alias_should_to_must'
+require 'mocha/api'
+#require 'puppetlabs_spec_helper/module_spec_helper'
+require 'puppetlabs_spec_helper_clone'
+
+# hack to enable all the expect syntax (like allow_any_instance_of) in rspec-puppet examples
+RSpec::Mocks::Syntax.enable_expect(RSpec::Puppet::ManifestMatchers)
+
+RSpec.configure do |config|
+  config.module_path = File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'modules')
+  config.manifest_dir = File.join(File.dirname(File.expand_path(__FILE__)), 'fixtures', 'manifests')
+  config.environmentpath = spec_path = File.expand_path(File.join(Dir.pwd, 'spec'))
+
+  config.add_setting :puppet_future
+  #config.puppet_future = (ENV['FUTURE_PARSER'] == 'yes' or Puppet.version.to_f >= 4.0)
+  config.puppet_future = Puppet.version.to_f >= 4.0
+
+  config.before :each do
+    # Ensure that we don't accidentally cache facts and environment between
+    # test cases.  This requires each example group to explicitly load the
+    # facts being exercised with something like
+    # Facter.collection.loader.load(:ipaddress)
+    Facter.clear
+    Facter.clear_messages
+
+    RSpec::Mocks.setup
+  end
+
+  config.after :each do
+    RSpec::Mocks.verify
+    RSpec::Mocks.teardown
+  end
+end
+
+# Helper class to test handling of arguments which are derived from string
+class AlsoString < String
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/spec_helper_acceptance.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,66 @@
+#! /usr/bin/env ruby -S rspec
+require 'beaker-rspec'
+require 'beaker/puppet_install_helper'
+
+UNSUPPORTED_PLATFORMS = []
+
+run_puppet_install_helper
+
+RSpec.configure do |c|
+  # Project root
+  proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+  # Readable test descriptions
+  c.formatter = :documentation
+
+  # Configure all nodes in nodeset
+  c.before :suite do
+    if ENV['FUTURE_PARSER'] == 'yes'
+      default[:default_apply_opts] ||= {}
+      default[:default_apply_opts].merge!({:parser => 'future'})
+    end
+
+    copy_root_module_to(default, :source => proj_root, :module_name => 'stdlib')
+  end
+end
+
+def is_future_parser_enabled?
+  if default[:type] == 'aio'
+    return true
+  elsif default[:default_apply_opts]
+    return default[:default_apply_opts][:parser] == 'future'
+  end
+  return false
+end
+
+RSpec.shared_context "with faked facts" do
+  let(:facts_d) do
+    puppet_version = (on default, puppet('--version')).output.chomp
+    if fact('osfamily') =~ /windows/i
+      if fact('kernelmajversion').to_f < 6.0
+        'C:/Documents and Settings/All Users/Application Data/PuppetLabs/facter/facts.d'
+      else
+        'C:/ProgramData/PuppetLabs/facter/facts.d'
+      end
+    elsif Puppet::Util::Package.versioncmp(puppet_version, '4.0.0') < 0 and fact('is_pe', '--puppet') == "true"
+      '/etc/puppetlabs/facter/facts.d'
+    else
+      '/etc/facter/facts.d'
+    end
+  end
+
+  before :each do
+    #No need to create on windows, PE creates by default
+    if fact('osfamily') !~ /windows/i
+      shell("mkdir -p '#{facts_d}'")
+    end
+  end
+
+  after :each do
+    shell("rm -f '#{facts_d}/fqdn.txt'", :acceptable_exit_codes => [0,1])
+  end
+
+  def fake_fact(name, value)
+    shell("echo #{name}=#{value} > '#{facts_d}/#{name}.txt'")
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/unit/facter/facter_dot_d_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+require 'facter/facter_dot_d'
+
+describe Facter::Util::DotD do
+
+  context 'returns a simple fact' do
+    before :each do
+      Facter.stubs(:version).returns('1.6.1')
+      subject.stubs(:entries).returns(['/etc/facter/facts.d/fake_fact.txt'])
+      File.stubs(:readlines).with('/etc/facter/facts.d/fake_fact.txt').returns(['fake_fact=fake fact'])
+      subject.create
+    end
+
+    it 'should return successfully' do
+      expect(Facter.fact(:fake_fact).value).to eq('fake fact')
+    end
+  end
+
+  context 'returns a fact with equals signs' do
+    before :each do
+      Facter.stubs(:version).returns('1.6.1')
+      subject.stubs(:entries).returns(['/etc/facter/facts.d/foo.txt'])
+      File.stubs(:readlines).with('/etc/facter/facts.d/foo.txt').returns(['foo=1+1=2'])
+      subject.create
+    end
+
+    it 'should return successfully' do
+      expect(Facter.fact(:foo).value).to eq('1+1=2')
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/unit/facter/pe_version_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,76 @@
+#!/usr/bin/env rspec
+
+require 'spec_helper'
+
+describe "PE Version specs" do
+  before :each do
+    # Explicitly load the pe_version.rb file which contains generated facts
+    # that cannot be automatically loaded.  Puppet 2.x implements
+    # Facter.collection.load while Facter 1.x markes Facter.collection.load as
+    # a private method.
+    if Facter.collection.respond_to? :load
+      Facter.collection.load(:pe_version)
+    else
+      Facter.collection.loader.load(:pe_version)
+    end
+  end
+
+  context "If PE is installed" do
+    %w{ 2.6.1 2.10.300 }.each do |version|
+      puppetversion = "2.7.19 (Puppet Enterprise #{version})"
+      context "puppetversion => #{puppetversion}" do
+        before :each do
+          Facter.fact(:puppetversion).stubs(:value).returns(puppetversion)
+        end
+
+        (major,minor,patch) = version.split(".")
+
+        it "Should return true" do
+          expect(Facter.fact(:is_pe).value).to eq(true)
+        end
+
+        it "Should have a version of #{version}" do
+          expect(Facter.fact(:pe_version).value).to eq(version)
+        end
+
+        it "Should have a major version of #{major}" do
+          expect(Facter.fact(:pe_major_version).value).to eq(major)
+        end
+
+        it "Should have a minor version of #{minor}" do
+          expect(Facter.fact(:pe_minor_version).value).to eq(minor)
+        end
+
+        it "Should have a patch version of #{patch}" do
+          expect(Facter.fact(:pe_patch_version).value).to eq(patch)
+        end
+      end
+    end
+  end
+
+  context "When PE is not installed" do
+    before :each do
+      Facter.fact(:puppetversion).stubs(:value).returns("2.7.19")
+    end
+
+    it "is_pe is false" do
+      expect(Facter.fact(:is_pe).value).to eq(false)
+    end
+
+    it "pe_version is nil" do
+      expect(Facter.fact(:pe_version).value).to be_nil
+    end
+
+    it "pe_major_version is nil" do
+      expect(Facter.fact(:pe_major_version).value).to be_nil
+    end
+
+    it "pe_minor_version is nil" do
+      expect(Facter.fact(:pe_minor_version).value).to be_nil
+    end
+
+    it "Should have a patch version" do
+      expect(Facter.fact(:pe_patch_version).value).to be_nil
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/unit/facter/root_home_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,65 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+require 'facter/root_home'
+
+describe Facter::Util::RootHome do
+  context "solaris" do
+    let(:root_ent) { "root:x:0:0:Super-User:/:/sbin/sh" }
+    let(:expected_root_home) { "/" }
+
+    it "should return /" do
+      Facter::Util::Resolution.expects(:exec).with("getent passwd root").returns(root_ent)
+      expect(Facter::Util::RootHome.get_root_home).to eq(expected_root_home)
+    end
+  end
+  context "linux" do
+    let(:root_ent) { "root:x:0:0:root:/root:/bin/bash" }
+    let(:expected_root_home) { "/root" }
+
+    it "should return /root" do
+      Facter::Util::Resolution.expects(:exec).with("getent passwd root").returns(root_ent)
+      expect(Facter::Util::RootHome.get_root_home).to eq(expected_root_home)
+    end
+  end
+  context "windows" do
+    before :each do
+      Facter::Util::Resolution.expects(:exec).with("getent passwd root").returns(nil)
+    end
+    it "should be nil on windows" do
+      expect(Facter::Util::RootHome.get_root_home).to be_nil
+    end
+  end
+end
+
+describe 'root_home', :type => :fact do
+  before { Facter.clear }
+  after { Facter.clear }
+
+  context "macosx" do
+    before do
+      Facter.fact(:kernel).stubs(:value).returns("Darwin")
+      Facter.fact(:osfamily).stubs(:value).returns("Darwin")
+    end
+    let(:expected_root_home) { "/var/root" }
+    sample_dscacheutil = File.read(fixtures('dscacheutil','root'))
+
+    it "should return /var/root" do
+      Facter::Util::Resolution.stubs(:exec).with("dscacheutil -q user -a name root").returns(sample_dscacheutil)
+      expect(Facter.fact(:root_home).value).to eq(expected_root_home)
+    end
+  end
+
+  context "aix" do
+    before do
+      Facter.fact(:kernel).stubs(:value).returns("AIX")
+      Facter.fact(:osfamily).stubs(:value).returns("AIX")
+    end
+    let(:expected_root_home) { "/root" }
+    sample_lsuser = File.read(fixtures('lsuser','root'))
+
+    it "should return /root" do
+      Facter::Util::Resolution.stubs(:exec).with("lsuser -C -a home root").returns(sample_lsuser)
+      expect(Facter.fact(:root_home).value).to eq(expected_root_home)
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/unit/facter/util/puppet_settings_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+require 'facter/util/puppet_settings'
+
+describe Facter::Util::PuppetSettings do
+
+  describe "#with_puppet" do
+    context "Without Puppet loaded" do
+      before(:each) do
+        Module.expects(:const_get).with("Puppet").raises(NameError)
+      end
+
+      it 'should be nil' do
+        expect(subject.with_puppet { Puppet[:vardir] }).to be_nil
+      end
+      it 'should not yield to the block' do
+        Puppet.expects(:[]).never
+        expect(subject.with_puppet { Puppet[:vardir] }).to be_nil
+      end
+    end
+    context "With Puppet loaded" do
+      module Puppet; end
+      let(:vardir) { "/var/lib/puppet" }
+
+      before :each do
+        Puppet.expects(:[]).with(:vardir).returns vardir
+      end
+
+      it 'should yield to the block' do
+        subject.with_puppet { Puppet[:vardir] }
+      end
+      it 'should return the nodes vardir' do
+        expect(subject.with_puppet { Puppet[:vardir] }).to eq vardir
+      end
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/unit/puppet/provider/file_line/ruby_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,440 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+require 'tempfile'
+provider_class = Puppet::Type.type(:file_line).provider(:ruby)
+describe provider_class do
+  context "when adding" do
+    let :tmpfile do
+      tmp = Tempfile.new('tmp')
+      path = tmp.path
+      tmp.close!
+      path
+    end
+    let :resource do
+      Puppet::Type::File_line.new(
+        {:name => 'foo', :path => tmpfile, :line => 'foo'}
+      )
+    end
+    let :provider do
+      provider_class.new(resource)
+    end
+
+    it 'should detect if the line exists in the file' do
+      File.open(tmpfile, 'w') do |fh|
+        fh.write('foo')
+      end
+      expect(provider.exists?).to be_truthy
+    end
+    it 'should detect if the line does not exist in the file' do
+      File.open(tmpfile, 'w') do |fh|
+        fh.write('foo1')
+      end
+      expect(provider.exists?).to be_nil
+    end
+    it 'should append to an existing file when creating' do
+      provider.create
+      expect(File.read(tmpfile).chomp).to eq('foo')
+    end
+  end
+  context 'when using replace' do
+    before :each do
+      # TODO: these should be ported over to use the PuppetLabs spec_helper
+      #  file fixtures once the following pull request has been merged:
+      # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
+      tmp = Tempfile.new('tmp')
+      @tmpfile = tmp.path
+      tmp.close!
+      @resource = Puppet::Type::File_line.new(
+        {
+          :name    => 'foo',
+          :path    => @tmpfile,
+          :line    => 'foo = bar',
+          :match   => '^foo\s*=.*$',
+          :replace => false,
+        }
+      )
+      @provider = provider_class.new(@resource)
+    end
+
+    it 'should not replace the matching line' do
+      File.open(@tmpfile, 'w') do |fh|
+        fh.write("foo1\nfoo=blah\nfoo2\nfoo3")
+      end
+      expect(@provider.exists?).to be_truthy
+      @provider.create
+      expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo=blah\nfoo2\nfoo3")
+    end
+
+    it 'should append the line if no matches are found' do
+      File.open(@tmpfile, 'w') do |fh|
+        fh.write("foo1\nfoo2")
+      end
+      expect(@provider.exists?).to be_nil
+      @provider.create
+      expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo2\nfoo = bar")
+    end
+
+    it 'should raise an error with invalid values' do
+      expect {
+        @resource = Puppet::Type::File_line.new(
+          {
+            :name     => 'foo',
+            :path     => @tmpfile,
+            :line     => 'foo = bar',
+            :match    => '^foo\s*=.*$',
+            :replace  => 'asgadga',
+          }
+        )
+      }.to raise_error(Puppet::Error, /Invalid value "asgadga"\. Valid values are true, false\./)
+    end
+  end
+  context "when matching" do
+    before :each do
+      # TODO: these should be ported over to use the PuppetLabs spec_helper
+      #  file fixtures once the following pull request has been merged:
+      # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
+      tmp = Tempfile.new('tmp')
+      @tmpfile = tmp.path
+      tmp.close!
+      @resource = Puppet::Type::File_line.new(
+        {
+          :name  => 'foo',
+          :path  => @tmpfile,
+          :line  => 'foo = bar',
+          :match => '^foo\s*=.*$',
+        }
+      )
+      @provider = provider_class.new(@resource)
+    end
+
+    describe 'using match' do
+      it 'should raise an error if more than one line matches, and should not have modified the file' do
+        File.open(@tmpfile, 'w') do |fh|
+          fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz")
+        end
+        expect(@provider.exists?).to be_nil
+        expect { @provider.create }.to raise_error(Puppet::Error, /More than one line.*matches/)
+        expect(File.read(@tmpfile)).to eql("foo1\nfoo=blah\nfoo2\nfoo=baz")
+      end
+
+      it 'should replace all lines that matches' do
+        @resource = Puppet::Type::File_line.new(
+          {
+            :name     => 'foo',
+            :path     => @tmpfile,
+            :line     => 'foo = bar',
+            :match    => '^foo\s*=.*$',
+            :multiple => true,
+          }
+        )
+        @provider = provider_class.new(@resource)
+        File.open(@tmpfile, 'w') do |fh|
+          fh.write("foo1\nfoo=blah\nfoo2\nfoo=baz")
+        end
+        expect(@provider.exists?).to be_nil
+        @provider.create
+        expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2\nfoo = bar")
+      end
+
+      it 'should raise an error with invalid values' do
+        expect {
+          @resource = Puppet::Type::File_line.new(
+            {
+              :name     => 'foo',
+              :path     => @tmpfile,
+              :line     => 'foo = bar',
+              :match    => '^foo\s*=.*$',
+              :multiple => 'asgadga',
+            }
+          )
+        }.to raise_error(Puppet::Error, /Invalid value "asgadga"\. Valid values are true, false\./)
+      end
+
+      it 'should replace a line that matches' do
+        File.open(@tmpfile, 'w') do |fh|
+          fh.write("foo1\nfoo=blah\nfoo2")
+        end
+        expect(@provider.exists?).to be_nil
+        @provider.create
+        expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2")
+      end
+      it 'should add a new line if no lines match' do
+        File.open(@tmpfile, 'w') do |fh|
+          fh.write("foo1\nfoo2")
+        end
+        expect(@provider.exists?).to be_nil
+        @provider.create
+        expect(File.read(@tmpfile)).to eql("foo1\nfoo2\nfoo = bar\n")
+      end
+      it 'should do nothing if the exact line already exists' do
+        File.open(@tmpfile, 'w') do |fh|
+          fh.write("foo1\nfoo = bar\nfoo2")
+        end
+        expect(@provider.exists?).to be_truthy
+        @provider.create
+        expect(File.read(@tmpfile).chomp).to eql("foo1\nfoo = bar\nfoo2")
+      end
+    end
+
+    describe 'using after' do
+      let :resource do
+        Puppet::Type::File_line.new(
+          {
+            :name  => 'foo',
+            :path  => @tmpfile,
+            :line  => 'inserted = line',
+            :after => '^foo1',
+          }
+        )
+      end
+
+      let :provider do
+        provider_class.new(resource)
+      end
+      context 'match and after set' do
+        shared_context 'resource_create' do
+          let(:match) { '^foo2$' }
+          let(:after) { '^foo1$' }
+          let(:resource) {
+            Puppet::Type::File_line.new(
+              {
+                :name  => 'foo',
+                :path  => @tmpfile,
+                :line  => 'inserted = line',
+                :after => after,
+                :match => match,
+              }
+            )
+          }
+        end
+        before :each do
+          File.open(@tmpfile, 'w') do |fh|
+            fh.write("foo1\nfoo2\nfoo = baz")
+          end
+        end
+        describe 'inserts at match' do
+          include_context 'resource_create'
+          it {
+            provider.create
+            expect(File.read(@tmpfile).chomp).to eq("foo1\ninserted = line\nfoo = baz")
+          }
+        end
+        describe 'inserts a new line after when no match' do
+          include_context 'resource_create' do
+            let(:match) { '^nevergoingtomatch$' }
+          end
+          it {
+            provider.create
+            expect(File.read(@tmpfile).chomp).to eq("foo1\ninserted = line\nfoo2\nfoo = baz")
+          }
+        end
+        describe 'append to end of file if no match for both after and match' do
+          include_context 'resource_create' do
+            let(:match) { '^nevergoingtomatch$' }
+            let(:after) { '^stillneverafter' }
+          end
+          it {
+            provider.create
+            expect(File.read(@tmpfile).chomp).to eq("foo1\nfoo2\nfoo = baz\ninserted = line")
+          }
+        end
+      end
+      context 'with one line matching the after expression' do
+        before :each do
+          File.open(@tmpfile, 'w') do |fh|
+            fh.write("foo1\nfoo = blah\nfoo2\nfoo = baz")
+          end
+        end
+
+        it 'inserts the specified line after the line matching the "after" expression' do
+          provider.create
+          expect(File.read(@tmpfile).chomp).to eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo = baz")
+        end
+      end
+
+      context 'with multiple lines matching the after expression' do
+        before :each do
+          File.open(@tmpfile, 'w') do |fh|
+            fh.write("foo1\nfoo = blah\nfoo2\nfoo1\nfoo = baz")
+          end
+        end
+
+        it 'errors out stating "One or no line must match the pattern"' do
+          expect { provider.create }.to raise_error(Puppet::Error, /One or no line must match the pattern/)
+        end
+
+        it 'adds the line after all lines matching the after expression' do
+          @resource = Puppet::Type::File_line.new(
+            {
+              :name     => 'foo',
+              :path     => @tmpfile,
+              :line     => 'inserted = line',
+              :after    => '^foo1$',
+              :multiple => true,
+            }
+          )
+          @provider = provider_class.new(@resource)
+          expect(@provider.exists?).to be_nil
+          @provider.create
+          expect(File.read(@tmpfile).chomp).to eql("foo1\ninserted = line\nfoo = blah\nfoo2\nfoo1\ninserted = line\nfoo = baz")
+        end
+      end
+
+      context 'with no lines matching the after expression' do
+        let :content do
+          "foo3\nfoo = blah\nfoo2\nfoo = baz\n"
+        end
+
+        before :each do
+          File.open(@tmpfile, 'w') do |fh|
+            fh.write(content)
+          end
+        end
+
+        it 'appends the specified line to the file' do
+          provider.create
+          expect(File.read(@tmpfile)).to eq(content << resource[:line] << "\n")
+        end
+      end
+    end
+  end
+
+  context "when removing" do
+    before :each do
+      # TODO: these should be ported over to use the PuppetLabs spec_helper
+      #  file fixtures once the following pull request has been merged:
+      # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
+      tmp = Tempfile.new('tmp')
+      @tmpfile = tmp.path
+      tmp.close!
+      @resource = Puppet::Type::File_line.new(
+        {
+          :name   => 'foo',
+          :path   => @tmpfile,
+          :line   => 'foo',
+          :ensure => 'absent',
+        }
+      )
+      @provider = provider_class.new(@resource)
+    end
+    it 'should remove the line if it exists' do
+      File.open(@tmpfile, 'w') do |fh|
+        fh.write("foo1\nfoo\nfoo2")
+      end
+      @provider.destroy
+      expect(File.read(@tmpfile)).to eql("foo1\nfoo2")
+    end
+
+    it 'should remove the line without touching the last new line' do
+      File.open(@tmpfile, 'w') do |fh|
+        fh.write("foo1\nfoo\nfoo2\n")
+      end
+      @provider.destroy
+      expect(File.read(@tmpfile)).to eql("foo1\nfoo2\n")
+    end
+
+    it 'should remove any occurence of the line' do
+      File.open(@tmpfile, 'w') do |fh|
+        fh.write("foo1\nfoo\nfoo2\nfoo\nfoo")
+      end
+      @provider.destroy
+      expect(File.read(@tmpfile)).to eql("foo1\nfoo2\n")
+    end
+  end
+
+  context "when removing with a match" do
+    before :each do
+      # TODO: these should be ported over to use the PuppetLabs spec_helper
+      #  file fixtures once the following pull request has been merged:
+      # https://github.com/puppetlabs/puppetlabs-stdlib/pull/73/files
+      tmp = Tempfile.new('tmp')
+      @tmpfile = tmp.path
+      tmp.close!
+      @resource = Puppet::Type::File_line.new(
+        {
+          :name              => 'foo',
+          :path              => @tmpfile,
+          :line              => 'foo2',
+          :ensure            => 'absent',
+          :match             => 'o$',
+          :match_for_absence => true,
+        }
+      )
+      @provider = provider_class.new(@resource)
+    end
+
+    it 'should remove one line if it matches' do
+      File.open(@tmpfile, 'w') do |fh|
+        fh.write("foo1\nfoo\nfoo2")
+      end
+      @provider.destroy
+      expect(File.read(@tmpfile)).to eql("foo1\nfoo2")
+    end
+
+    it 'should raise an error if more than one line matches' do
+      File.open(@tmpfile, 'w') do |fh|
+        fh.write("foo1\nfoo\nfoo2\nfoo\nfoo")
+      end
+      expect { @provider.destroy }.to raise_error(Puppet::Error, /More than one line/)
+    end
+
+    it 'should remove multiple lines if :multiple is true' do
+      @resource = Puppet::Type::File_line.new(
+        {
+          :name              => 'foo',
+          :path              => @tmpfile,
+          :line              => 'foo2',
+          :ensure            => 'absent',
+          :match             => 'o$',
+          :multiple          => true,
+          :match_for_absence => true,
+        }
+      )
+      @provider = provider_class.new(@resource)
+      File.open(@tmpfile, 'w') do |fh|
+        fh.write("foo1\nfoo\nfoo2\nfoo\nfoo")
+      end
+      @provider.destroy
+      expect(File.read(@tmpfile)).to eql("foo1\nfoo2\n")
+    end
+
+    it 'should ignore the match if match_for_absense is not specified' do
+      @resource = Puppet::Type::File_line.new(
+        {
+          :name     => 'foo',
+          :path     => @tmpfile,
+          :line     => 'foo2',
+          :ensure   => 'absent',
+          :match    => 'o$',
+        }
+      )
+      @provider = provider_class.new(@resource)
+      File.open(@tmpfile, 'w') do |fh|
+        fh.write("foo1\nfoo\nfoo2")
+      end
+      @provider.destroy
+      expect(File.read(@tmpfile)).to eql("foo1\nfoo\n")
+    end
+
+    it 'should ignore the match if match_for_absense is false' do
+      @resource = Puppet::Type::File_line.new(
+        {
+          :name              => 'foo',
+          :path              => @tmpfile,
+          :line              => 'foo2',
+          :ensure            => 'absent',
+          :match             => 'o$',
+          :match_for_absence => false,
+        }
+      )
+      @provider = provider_class.new(@resource)
+      File.open(@tmpfile, 'w') do |fh|
+        fh.write("foo1\nfoo\nfoo2")
+      end
+      @provider.destroy
+      expect(File.read(@tmpfile)).to eql("foo1\nfoo\n")
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/unit/puppet/type/anchor_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+#!/usr/bin/env ruby
+
+require 'spec_helper'
+
+anchor = Puppet::Type.type(:anchor).new(:name => "ntp::begin")
+
+describe anchor do
+  it "should stringify normally" do
+    expect(anchor.to_s).to eq("Anchor[ntp::begin]")
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/stdlib/spec/unit/puppet/type/file_line_spec.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,73 @@
+#! /usr/bin/env ruby -S rspec
+require 'spec_helper'
+require 'tempfile'
+describe Puppet::Type.type(:file_line) do
+  let :file_line do
+    Puppet::Type.type(:file_line).new(:name => 'foo', :line => 'line', :path => '/tmp/path')
+  end
+  it 'should accept a line and path' do
+    file_line[:line] = 'my_line'
+    expect(file_line[:line]).to eq('my_line')
+    file_line[:path] = '/my/path'
+    expect(file_line[:path]).to eq('/my/path')
+  end
+  it 'should accept a match regex' do
+    file_line[:match] = '^foo.*$'
+    expect(file_line[:match]).to eq('^foo.*$')
+  end
+  it 'should accept a match regex that does not match the specified line' do
+    expect {
+      Puppet::Type.type(:file_line).new(
+          :name   => 'foo',
+          :path   => '/my/path',
+          :line   => 'foo=bar',
+          :match  => '^bar=blah$'
+    )}.not_to raise_error
+  end
+  it 'should accept a match regex that does match the specified line' do
+    expect {
+      Puppet::Type.type(:file_line).new(
+          :name   => 'foo',
+          :path   => '/my/path',
+          :line   => 'foo=bar',
+          :match  => '^\s*foo=.*$'
+      )}.not_to raise_error
+  end
+  it 'should accept posix filenames' do
+    file_line[:path] = '/tmp/path'
+    expect(file_line[:path]).to eq('/tmp/path')
+  end
+  it 'should not accept unqualified path' do
+    expect { file_line[:path] = 'file' }.to raise_error(Puppet::Error, /File paths must be fully qualified/)
+  end
+  it 'should require that a line is specified' do
+    expect { Puppet::Type.type(:file_line).new(:name => 'foo', :path => '/tmp/file') }.to raise_error(Puppet::Error, /Both line and path are required attributes/)
+  end
+  it 'should require that a file is specified' do
+    expect { Puppet::Type.type(:file_line).new(:name => 'foo', :line => 'path') }.to raise_error(Puppet::Error, /Both line and path are required attributes/)
+  end
+  it 'should default to ensure => present' do
+    expect(file_line[:ensure]).to eq :present
+  end
+  it 'should default to replace => true' do
+    expect(file_line[:replace]).to eq :true
+  end
+
+  it "should autorequire the file it manages" do
+    catalog = Puppet::Resource::Catalog.new
+    file = Puppet::Type.type(:file).new(:name => "/tmp/path")
+    catalog.add_resource file
+    catalog.add_resource file_line
+
+    relationship = file_line.autorequire.find do |rel|
+      (rel.source.to_s == "File[/tmp/path]") and (rel.target.to_s == file_line.to_s)
+    end
+    expect(relationship).to be_a Puppet::Relationship
+  end
+
+  it "should not autorequire the file it manages if it is not managed" do
+    catalog = Puppet::Resource::Catalog.new
+    catalog.add_resource file_line
+    expect(file_line.autorequire).to be_empty
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/files/httpd/httpd.conf	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,364 @@
+#
+# This is the main Apache HTTP server configuration file.  It contains the
+# configuration directives that give the server its instructions.
+# See <URL:http://httpd.apache.org/docs/2.4/> for detailed information.
+# In particular, see
+# <URL:http://httpd.apache.org/docs/2.4/mod/directives.html>
+# for a discussion of each configuration directive.
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do.  They're here only as hints or reminders.  If you are unsure
+# consult the online docs. You have been warned.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path.  If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so 'log/access_log'
+# with ServerRoot set to '/www' will be interpreted by the
+# server as '/www/log/access_log', where as '/log/access_log' will be
+# interpreted as '/log/access_log'.
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# Do not add a slash at the end of the directory path.  If you point
+# ServerRoot at a non-local disk, be sure to specify a local disk on the
+# Mutex directive, if file-based mutexes are used.  If you wish to share the
+# same ServerRoot for multiple httpd daemons, you will need to change at
+# least PidFile.
+#
+ServerRoot "/etc/httpd"
+
+Timeout 120
+KeepAlive Off
+MaxKeepAliveRequests 100
+KeepAliveTimeout 15
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+# Change this to Listen on specific IP addresses as shown below to
+# prevent Apache from glomming onto all bound IP addresses.
+#
+#Listen 12.34.56.78:80
+Listen 80
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Statically compiled modules (those listed by `httpd -l') do not need
+# to be loaded here.
+#
+# Example:
+# LoadModule foo_module modules/mod_foo.so
+#
+Include conf.modules.d/*.conf
+
+#
+# If you wish httpd to run as a different user or group, you must run
+# httpd as root initially and it will switch.
+#
+# User/Group: The name (or #number) of the user/group to run httpd as.
+# It is usually good practice to create a dedicated user and group for
+# running httpd, as with most system services.
+#
+User apache
+Group apache
+
+# 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition.  These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerAdmin: Your address, where problems with the server should be
+# e-mailed.  This address appears on some server-generated pages, such
+# as error documents.  e.g. admin@your-domain.com
+#
+ServerAdmin root@localhost
+
+#
+# ServerName gives the name and port that the server uses to identify itself.
+# This can often be determined automatically, but we recommend you specify
+# it explicitly to prevent problems during startup.
+#
+# If your host doesn't have a registered DNS name, enter its IP address here.
+#
+#ServerName www.example.com:80
+
+#
+# Deny access to the entirety of your server's filesystem. You must
+# explicitly permit access to web content directories in other
+# <Directory> blocks below.
+#
+<Directory />
+    AllowOverride none
+    Require all denied
+</Directory>
+
+#
+# Note that from this point forward you must specifically allow
+# particular features to be enabled - so if something's not working as
+# you might expect, make sure that you have specifically enabled it
+# below.
+#
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+# DocumentRoot "/var/www/html"
+
+#
+# Relax access to content within /var/www.
+#
+# <Directory "/var/www">
+#     AllowOverride None
+#     # Allow open access:
+#     Require all granted
+# </Directory>
+
+# Further relax access to the default document root:
+# <Directory "/var/www/html">
+#     #
+#     # Possible values for the Options directive are "None", "All",
+#     # or any combination of:
+#     #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
+#     #
+#     # Note that "MultiViews" must be named *explicitly* --- "Options All"
+#     # doesn't give it to you.
+#     #
+#     # The Options directive is both complicated and important.  Please see
+#     # http://httpd.apache.org/docs/2.4/mod/core.html#options
+#     # for more information.
+#     #
+#     Options Indexes FollowSymLinks
+#
+#     #
+#     # AllowOverride controls what directives may be placed in .htaccess files.
+#     # It can be "All", "None", or any combination of the keywords:
+#     #   Options FileInfo AuthConfig Limit
+#     #
+#     AllowOverride None
+#
+#     #
+#     # Controls who can get stuff from this server.
+#     #
+#     Require all granted
+# </Directory>
+
+#
+# DirectoryIndex: sets the file that Apache will serve if a directory
+# is requested.
+#
+<IfModule dir_module>
+    DirectoryIndex index.html
+</IfModule>
+
+AccessFileName .htaccess
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<Files ".ht*">
+    Require all denied
+</Files>
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here.  If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+ErrorLog "logs/error_log"
+
+HostnameLookups Off
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+<IfModule log_config_module>
+    #
+    # The following directives define some format nicknames for use with
+    # a CustomLog directive (see below).
+    #
+    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+    LogFormat "%h %l %u %t \"%r\" %>s %b" common
+
+    <IfModule logio_module>
+      # You need to enable mod_logio.c to use %I and %O
+      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
+    </IfModule>
+
+    #
+    # The location and format of the access logfile (Common Logfile Format).
+    # If you do not define any access logfiles within a <VirtualHost>
+    # container, they will be logged here.  Contrariwise, if you *do*
+    # define per-<VirtualHost> access logfiles, transactions will be
+    # logged therein and *not* in this file.
+    #
+    #CustomLog "logs/access_log" common
+
+    #
+    # If you prefer a logfile with access, agent, and referer information
+    # (Combined Logfile Format) you can use the following directive.
+    #
+    CustomLog "logs/access_log" combined
+</IfModule>
+
+# <IfModule alias_module>
+#     #
+#     # Redirect: Allows you to tell clients about documents that used to
+#     # exist in your server's namespace, but do not anymore. The client
+#     # will make a new request for the document at its new location.
+#     # Example:
+#     # Redirect permanent /foo http://www.example.com/bar
+#
+#     #
+#     # Alias: Maps web paths into filesystem paths and is used to
+#     # access content that does not live under the DocumentRoot.
+#     # Example:
+#     # Alias /webpath /full/filesystem/path
+#     #
+#     # If you include a trailing / on /webpath then the server will
+#     # require it to be present in the URL.  You will also likely
+#     # need to provide a <Directory> section to allow access to
+#     # the filesystem path.
+#
+#     #
+#     # ScriptAlias: This controls which directories contain server scripts.
+#     # ScriptAliases are essentially the same as Aliases, except that
+#     # documents in the target directory are treated as applications and
+#     # run by the server when requested rather than as documents sent to the
+#     # client.  The same rules about trailing "/" apply to ScriptAlias
+#     # directives as to Alias.
+#     #
+#     ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
+#
+# </IfModule>
+
+#
+# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
+# CGI directory exists, if you have that configured.
+#
+# <Directory "/var/www/cgi-bin">
+#     AllowOverride None
+#     Options None
+#     Require all granted
+# </Directory>
+
+<IfModule mime_module>
+    #
+    # TypesConfig points to the file containing the list of mappings from
+    # filename extension to MIME-type.
+    #
+    TypesConfig /etc/mime.types
+
+    #
+    # AddType allows you to add to or override the MIME configuration
+    # file specified in TypesConfig for specific file types.
+    #
+    #AddType application/x-gzip .tgz
+    #
+    # AddEncoding allows you to have certain browsers uncompress
+    # information on the fly. Note: Not all browsers support this.
+    #
+    #AddEncoding x-compress .Z
+    #AddEncoding x-gzip .gz .tgz
+    #
+    # If the AddEncoding directives above are commented-out, then you
+    # probably should define those extensions to indicate media types:
+    #
+    AddType application/x-compress .Z
+    AddType application/x-gzip .gz .tgz
+
+    #
+    # AddHandler allows you to map certain file extensions to "handlers":
+    # actions unrelated to filetype. These can be either built into the server
+    # or added with the Action directive (see below)
+    #
+    # To use CGI scripts outside of ScriptAliased directories:
+    # (You will also need to add "ExecCGI" to the "Options" directive.)
+    #
+    #AddHandler cgi-script .cgi
+
+    # For type maps (negotiated resources):
+    #AddHandler type-map var
+
+    #
+    # Filters allow you to process content before it is sent to the client.
+    #
+    # To parse .shtml files for server-side includes (SSI):
+    # (You will also need to add "Includes" to the "Options" directive.)
+    #
+    AddType text/html .shtml
+    AddOutputFilter INCLUDES .shtml
+</IfModule>
+
+#
+# Specify a default charset for all content served; this enables
+# interpretation of all content as UTF-8 by default.  To use the
+# default browser choice (ISO-8859-1), or to allow the META tags
+# in HTML content to override this choice, comment out this
+# directive:
+#
+AddDefaultCharset UTF-8
+
+<IfModule mime_magic_module>
+    #
+    # The mod_mime_magic module allows the server to use various hints from the
+    # contents of the file itself to determine its type.  The MIMEMagicFile
+    # directive tells the module where the hint definitions are located.
+    #
+    MIMEMagicFile conf/magic
+</IfModule>
+
+#
+# Customizable error responses come in three flavors:
+# 1) plain text 2) local redirects 3) external redirects
+#
+# Some examples:
+#ErrorDocument 500 "The server made a boo boo."
+#ErrorDocument 404 /missing.html
+#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
+#ErrorDocument 402 http://www.example.com/subscription_info.html
+#
+
+#
+# EnableMMAP and EnableSendfile: On systems that support it,
+# memory-mapping or the sendfile syscall may be used to deliver
+# files.  This usually improves server performance, but must
+# be turned off when serving from networked-mounted
+# filesystems or if support for these functions is otherwise
+# broken on your system.
+# Defaults if commented: EnableMMAP On, EnableSendfile Off
+#
+#EnableMMAP off
+EnableSendfile on
+
+ServerTokens prod
+ServerSignature off
+TraceEnable On
+
+# Supplemental configuration
+#
+# Load config files in the "/etc/httpd/conf.d" directory, if any.
+IncludeOptional conf.d/*.conf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/files/httpd/welcome.conf	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+#
+# This configuration file enables the default "Welcome" page if there
+# is no default index page present for the root URL.  To disable the
+# Welcome page, comment out all the lines below.
+#
+# NOTE: if this file is removed, it will be restored on upgrades.
+#
+# <LocationMatch "^/+$">
+#     Options -Indexes
+#     ErrorDocument 403 /.noindex.html
+# </LocationMatch>
+#
+# <Directory /usr/share/httpd/noindex>
+#     AllowOverride None
+#     Require all granted
+# </Directory>
+#
+# Alias /.noindex.html /usr/share/httpd/noindex/index.html
+# Alias /noindex/css/bootstrap.min.css /usr/share/httpd/noindex/css/bootstrap.min.css
+# Alias /noindex/css/open-sans.css /usr/share/httpd/noindex/css/open-sans.css
+# Alias /images/apache_pb.gif /usr/share/httpd/noindex/images/apache_pb.gif
+# Alias /images/poweredby.png /usr/share/httpd/noindex/images/poweredby.png
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/files/memcached_socket_dir.conf	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+[Service]
+ExecStartPre=-/usr/bin/mkdir -p /var/run/memcached
+ExecStartPre=-/usr/bin/chown :memcached /var/run/memcached
+ExecStartPre=-/usr/bin/chmod g+w /var/run/memcached
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/files/phpinfo.php	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+<?php
+phpinfo();
+ ?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/files/sesame/console_commands.txt	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+connect http://localhost:8080/openrdf-sesame
+create native
+corpus
+Corpus repo
+
+
+create native
+corpus_raw
+Corpus raw repo
+
+
+create native
+lexvo
+Lexvo
+
+
+open lexvo
+load file:///tmp/lexvo/lexvo.rdf
+quit
Binary file dev/provisioning/modules/sysconfig/files/sesame/lexvo_2013-02-09_cleaned.rdf.bz2 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/lib/puppet/parser/functions/memcached_max_memory.rb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,39 @@
+# Taken from saz/memcached : https://forge.puppetlabs.com/saz/memcached
+module Puppet::Parser::Functions
+  newfunction(:memcached_max_memory, :type => :rvalue, :doc => <<-EOS
+    Calculate max_memory size from fact 'memsize' and passed argument.
+    EOS
+  ) do |arguments|
+
+    raise(Puppet::ParseError, "memcached_max_memory(): " +
+          "Wrong number of arguments given " +
+          "(#{arguments.size} for 1)") if arguments.size != 1
+
+    arg = arguments[0]
+    memsize = lookupvar('memorysize')
+
+    if arg and !arg.to_s.end_with?('%')
+      result_in_mb = arg.to_i
+    else
+      max_memory_percent = arg ? arg : '95%'
+
+      # Taken from puppetlabs-stdlib to_bytes() function
+      value,prefix = */([0-9.e+-]*)\s*([^bB]?)/.match(memsize)[1,2]
+
+      value = value.to_f
+      case prefix
+        when '' then value = value
+        when 'k' then value *= (1<<10)
+        when 'M' then value *= (1<<20)
+        when 'G' then value *= (1<<30)
+        when 'T' then value *= (1<<40)
+        when 'E' then value *= (1<<50)
+        else raise Puppet::ParseError, "memcached_max_memory(): Unknown prefix #{prefix}"
+      end
+      value = value.to_i
+      result_in_mb = ( (value / (1 << 20) ) * (max_memory_percent.to_f / 100.0) ).floor
+    end
+
+    return result_in_mb
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/apache.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,131 @@
+class sysconfig::apache (
+    $vhost = hiera('sysconfig::params::vhost', $sysconfig::params::vhost),
+) inherits sysconfig::params {
+    notify {'apache': name => "\$vhost : ${vhost}", withpath => true }
+
+    #remove system apache
+    # package { "audit-libs":
+    #     ensure => present
+    # }->
+    # package {"rhscl-httpd24-epel-7-x86_64":
+    #     ensure => present,
+    #     source => "https://www.softwarecollections.org/en/scls/rhscl/httpd24/epel-7-x86_64/download/rhscl-httpd24-epel-7-x86_64.noarch.rpm",
+    #     provider => rpm,
+    # }->
+    # class { '::apache':
+    #     default_vhost => false,
+    #     apache_name => 'httpd24-httpd',
+    #     service_name => 'httpd24-httpd',
+    #     httpd_dir => "/opt/rh/httpd24/root/etc/httpd",
+    #     server_root => "/opt/rh/httpd24/root/etc/httpd",
+    #     conf_dir => "/opt/rh/httpd24/root/etc/httpd/conf",
+    #     confd_dir => "/opt/rh/httpd24/root/etc/httpd/conf.d",
+    #     mod_dir => "/opt/rh/httpd24/root/etc/httpd/conf.d",
+    #     vhost_dir => "/opt/rh/httpd24/root/etc/httpd/conf.d",
+    #     ports_file => "/opt/rh/httpd24/root/etc/httpd/conf.d/ports.conf"
+    # }
+    # class { '::apache':
+    #     default_vhost => false,
+    #     server_signature => 'off',
+    #     server_tokens => 'prod'
+    # }
+    # file {[ "/var/www/corpusdelaparole",
+    #         "/var/www/corpusdelaparole/corpus",
+    #         "/var/www/corpusdelaparole/drupal"]:
+    #     ensure => directory,
+    #     owner => 'apache',
+    #     group => 'apache'
+    # }->
+    # file { "/etc/www":
+    #     ensure => directory,
+    # }->
+    # ::apache::vhost { $vhost:
+    #     port    => '80',
+    #     docroot => "/var/www/corpusdelaparole/drupal",
+    #     options => ['-indexes'],
+    #     aliases => [
+    #         { alias => '/corpus', path => "/var/www/corpusdelaparole/corpus/public" },
+    #     ],
+    #     use_optional_includes => true,
+    #     directories => [
+    #         {
+    #             path => "/var/www/corpusdelaparole/drupal",
+    #             allow_override => ['all',]
+    #         },
+    #         {
+    #             path => "/var/www/corpusdelaparole/corpus/public",
+    #             allow_override => ['all',],
+    #         }
+    #     ],
+    #     custom_fragment => "  <Location /corpus>\n    IncludeOptional /etc/www/corpus_env.con[f]\n  </Location>",
+    # }
+
+    $apache_packages = [
+        'httpd'
+    ]
+    $corpus_folders = [
+        "/var/www/corpusdelaparole",
+        "/var/www/corpusdelaparole/corpus",
+        "/var/www/corpusdelaparole/drupal"
+    ]
+
+    package { $apache_packages:
+        ensure => present,
+    }
+
+    service { "httpd":
+        ensure => running,
+        enable => true,
+        require => Package['httpd']
+    }
+
+    file { $corpus_folders:
+        ensure => directory,
+        owner => 'apache',
+        group => 'apache',
+        require => Package['httpd']
+    }
+
+    file { "/etc/www":
+        ensure => directory,
+    }
+
+    file { ["/etc/httpd/conf.d/userdir.conf", "/etc/httpd/conf.d/autoindex.conf"]:
+        ensure => absent,
+        require => Package['httpd'],
+        notify => Service['httpd']
+    }
+    file { "/etc/httpd/conf/httpd.conf":
+        ensure => file,
+        source => "puppet:///modules/sysconfig/httpd/httpd.conf",
+        require => Package['httpd'],
+        notify => Service['httpd']
+    }
+    file { "/etc/httpd/conf.d/welcome.conf":
+        ensure => file,
+        source => "puppet:///modules/sysconfig/httpd/welcome.conf",
+        require => Package['httpd'],
+        notify => Service['httpd']
+    }
+    file { "/etc/httpd/conf.d/10-corpusdelaparole.conf":
+        ensure => file,
+        content => template("sysconfig/httpd/vhost.conf.erb"),
+        require => [Package['httpd'], File['/etc/www'], File[$corpus_folders]],
+        notify => Service['httpd']
+    }
+
+    exec { "open-http-port":
+        command => "firewall-cmd --permanent --add-port=80/tcp",
+        path => [ '/bin', '/usr/bin', '/usr/local/bin' ]
+    }->
+    exec { "open-http-port-reload":
+        command => "firewall-cmd --reload",
+        path => [ '/bin', '/usr/bin', '/usr/local/bin' ]
+    }
+
+    #remove
+    #/etc/httpd/conf.d/userdir.conf
+    #/etc/httpd/conf.d/autotindex.conf
+    #/etc/httpd/conf.d/welcome.conf
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/corpus.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+class sysconfig::corpus (
+    $vhost          = hiera('sysconfig::params::vhost',          $sysconfig::params::vhost),
+    $corpus_app_key = hiera('sysconfig::params::corpus_app_key', $sysconfig::params::corpus_app_key),
+    $db_name        = hiera('sysconfig::params::db_name',        $sysconfig::params::db_name),
+    $db_drpl_name   = hiera('sysconfig::params::db_drpl_name',   $sysconfig::params::db_drpl_name),
+    $db_user        = hiera('sysconfig::params::db_user',        $sysconfig::params::db_user),
+    $db_pw          = hiera('sysconfig::params::db_pw',          $sysconfig::params::db_pw),
+    $db_host        = hiera('sysconfig::params::db_host',        $sysconfig::params::db_host),
+    $db_port        = hiera('sysconfig::params::db_port',        $sysconfig::params::db_port),
+) inherits sysconfig::params {
+
+    file { "/etc/www/corpus_env.conf":
+        ensure => file,
+        content => template("sysconfig/corpus/corpus_env.conf.erb"),
+        require => [Package['httpd'], File['/etc/www']],
+        notify => Service['httpd']
+    }
+
+    file { "/var/www/corpusdelaparole/corpus/.env":
+        ensure => file,
+        owner => 'apache',
+        group => 'apache',
+        content => template("sysconfig/corpus/local.env.erb"),
+        require=>File["/var/www/corpusdelaparole/corpus"]
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/elasticsearch.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,16 @@
+class sysconfig::elasticsearch (
+    $es_host     = hiera('sysconfig::params::es_host', $sysconfig::params::es_host),
+    $es_port     = hiera('sysconfig::params::es_port', $sysconfig::params::es_port),
+    $es_instance = hiera('sysconfig::params::es_instance', $sysconfig::params::es_instance),
+) inherits sysconfig::params {
+
+    notify {'elasticsearch': name => "\$es_host : ${es_host}, \$es_port : ${es_port}, \$es_instance : ${es_instance}", withpath => true }
+
+
+    class { '::elasticsearch':
+      manage_repo  => true,
+      autoupgrade => true,
+      repo_version => '2.x',
+    }->
+    elasticsearch::instance { $es_instance: }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+class sysconfig {
+    include augeas
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/mariadb.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,93 @@
+class sysconfig::mariadb (
+    $db_name      = hiera('sysconfig::params::db_name',      sysconfig::params::db_name),
+    $db_drpl_name = hiera('sysconfig::params::db_drpl_name', $sysconfig::params::db_drpl_name),
+    $db_user      = hiera('sysconfig::params::db_user',      $sysconfig::params::db_user),
+    $db_pw        = hiera('sysconfig::params::db_pw',        $sysconfig::params::db_pw),
+    $db_host      = hiera('sysconfig::params::db_host',      $sysconfig::params::db_host),
+    $db_port      = hiera('sysconfig::params::db_port',      $sysconfig::params::db_port),
+) inherits sysconfig::params {
+
+    $mariadb_packages = [
+        'mariadb-server'
+    ]
+
+    package { $mariadb_packages:
+        ensure => present,
+        notify  => Service["mariadb"]
+    }
+
+    service { "mariadb":
+        ensure => running,
+        enable => true
+    }
+
+    augeas { "mariadb_server_cnf/max_allowed_packet":
+        lens    => "MySQL.lns",
+        incl    => "/etc/my.cnf.d/server.cnf",
+        changes => "set target[.='mysqld']/max_allowed_packet 16M",
+        notify  => Service["mariadb"],
+        require => Package["mariadb-server"]
+    }
+
+    augeas { "mariadb_server_cnf/collation-server":
+        lens    => "MySQL.lns",
+        incl    => "/etc/my.cnf.d/server.cnf",
+        changes => "set target[.='mysqld']/collation-server utf8mb4_general_ci",
+        notify  => Service["mariadb"],
+        require => Package["mariadb-server"]
+    }
+
+    augeas { "mariadb_server_cnf/character-set-server":
+        lens    => "MySQL.lns",
+        incl    => "/etc/my.cnf.d/server.cnf",
+        changes => "set target[.='mysqld']/character-set-server utf8mb4",
+        notify  => Service["mariadb"],
+        require => Package["mariadb-server"]
+    }
+
+    augeas { "mariadb_client_cnf/default-character-set":
+        lens    => "MySQL.lns",
+        incl    => "/etc/my.cnf.d/client.cnf",
+        changes => "set target[.='client']/default-character-set utf8mb4",
+        notify  => Service["mariadb"],
+        require => Package["mariadb-server"]
+    }
+
+    augeas { "mariadb_mysql-client_cnf/default-character-set":
+        lens    => "MySQL.lns",
+        incl    => "/etc/my.cnf.d/mysql-clients.cnf",
+        changes => "set target[.='mysql']/default-character-set utf8mb4",
+        notify  => Service["mariadb"],
+        require => Package["mariadb-server"]
+    }
+
+    mysql::db { "drupal_db":
+        dbname => $db_drpl_name,
+        user => $db_user,
+        password => $db_pw,
+        host => $db_host,
+        charset => 'utf8mb4',
+        collate => 'utf8mb4_general_ci',
+        require => Service["mariadb"],
+    }
+    mysql::db { "corpus_db":
+        dbname => $db_name,
+        user => $db_user,
+        password => $db_pw,
+        host => $db_host,
+        charset => 'utf8mb4',
+        collate => 'utf8mb4_general_ci',
+        require => Service["mariadb"],
+    }
+
+    #TODO: create user
+
+    #TODO: create databases
+
+    # max_allowed_packet : > 16M ->
+    # [mysqld]
+    # collation-server     = utf8mb4_general_ci
+    # character-set-server = utf8mb4
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/memcached.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,38 @@
+class sysconfig::memcached (
+    $memcached_max_memory     = hiera('sysconfig::params::memcached_max_memory', $sysconfig::params::memcached_max_memory),
+) inherits sysconfig::params {
+
+    notify {'memcached': name => "\$memcached_max_memory : ${memcached_max_memory}", withpath => true }
+
+    package { 'memcached':
+        ensure => present,
+    }->
+    service { 'memcached':
+        ensure => running,
+        enable => true
+    }
+
+    $max_memory = memcached_max_memory($memcached_max_memory)
+    file { "/etc/systemd/system/memcached.service.d":
+        ensure => 'directory'
+    }->
+    file { "/etc/systemd/system/memcached.service.d/memcached_socket_dir.conf":
+        mode   => 755,
+        source => "puppet:///modules/sysconfig/memcached_socket_dir.conf",
+        require => Package['memcached']
+    }->
+    exec { 'systemctl-daemon-reload':
+      command => '/usr/bin/systemctl daemon-reload',
+    }->
+    augeas { 'etc-sysconfig/memcached':
+        context => "/files/etc/sysconfig/memcached",
+        changes => [
+            "set PORT '\"0\"'",
+            "set CACHESIZE '\"$max_memory\"'",
+            "set OPTIONS '\"-s /var/run/memcached/memcached.sock -a 0766\"'"
+        ],
+        notify => Service['memcached'],
+        require => Package['memcached']
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/packages.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+class sysconfig::packages {
+
+    $package_list = [
+        'scl-utils',
+        'libmcrypt',
+        'java-1.8.0-openjdk-headless',
+    ]
+
+    package { $package_list:
+        ensure => present,
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/params.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+class sysconfig::params {
+
+    $db_name = hiera('sysconfig::params::db_name','corpus')
+    $db_drpl_name = hiera('sysconfig::params::db_drpl_name','corpusdelaparole')
+    $db_user = hiera('sysconfig::params::db_user','corpus_user')
+    $db_pw   = hiera('sysconfig::params::db_pw','corpus')
+    $db_host = hiera('sysconfig::params::db_host','127.0.0.1')
+    $db_port = hiera('sysconfig::params::db_port','3306')
+
+    $es_host     = hiera('sysconfig::params::es_host', '127.0.0.1')
+    $es_port     = hiera('sysconfig::params::es_port', '9200')
+    $es_instance = hiera('sysconfig::params::es_instance', 'es_01')
+
+    $tomcat_open_port = hiera('sysconfig::params::tomcat_open_port', false)
+
+    $vhost = hiera('sysconfig::params::vhost', $::ipaddress)
+
+    $memcached_max_memory = hiera('sysconfig::params::memcached_max_memory','25%')
+
+    $corpus_app_key = hiera('sysconfig::params::corpus_app_key', 'TO_BE_DEFINED')
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/php.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,64 @@
+class sysconfig::php (
+) inherits sysconfig::params {
+
+    $php_packages = [
+        'php56',
+        'php56-php',
+        'php56-php-common',
+        'php56-php-mbstring',
+        'php56-php-mcrypt',
+        'php56-php-pdo',
+        'php56-php-pecl-memcache',
+        'php56-php-gd',
+        'php56-php-mysqlnd',
+        'php56-php-pecl-imagick'
+    ]
+
+    package { $php_packages:
+        ensure => present,
+        require => Package["httpd"]
+    }
+
+    file { '/var/log/php':
+        ensure => directory,
+        owner => 'apache',
+        group => 'apache'
+    }
+
+    augeas { "php_ini/memory_limit":
+        lens    => "PHP.lns",
+        incl    => "/opt/remi/php56/root/etc/php.ini",
+        changes => "set PHP/memory_limit 128M",
+        notify => Service['httpd'],
+        require => Package["php56"]
+    }->
+    augeas { "php_ini/max_execution_time":
+        lens    => "PHP.lns",
+        incl    => "/opt/remi/php56/root/etc/php.ini",
+        changes => "set PHP/max_execution_time 50",
+        notify => Service['httpd'],
+        require => Package["php56"]
+    }->
+    augeas { "php_ini/upload_max_filesize":
+        lens    => "PHP.lns",
+        incl    => "/opt/remi/php56/root/etc/php.ini",
+        changes => "set PHP/upload_max_filesize 50M",
+        notify => Service['httpd'],
+        require => Package["php56"]
+    }->
+    augeas { "php_ini/error_log":
+        lens    => "PHP.lns",
+        incl    => "/opt/remi/php56/root/etc/php.ini",
+        changes => "set PHP/error_log /var/log/php/php_errors.log",
+        notify => Service['httpd'],
+        require => [Package["php56"], File['/var/log/php']]
+    }
+#TODO : set php log
+    file { "/var/www/html/phpinfo.php":
+        mode   => 440,
+        owner  => 'apache',
+        group  => 'apache',
+        source => "puppet:///modules/sysconfig/phpinfo.php"
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/sesame.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,84 @@
+class sysconfig::sesame (
+) inherits sysconfig::params {
+
+    define create_lexvo_repository($unless = undef) {
+
+        file { "lexvo_tmp_dir":
+            path => "/tmp/lexvo",
+            ensure => directory,
+        }->
+        file { "lexvo_data_archive":
+            path => "/tmp/lexvo/lexvo.rdf.bz2",
+            ensure => present,
+            source => "puppet:///modules/sysconfig/sesame/lexvo_2013-02-09_cleaned.rdf.bz2",
+        }->
+        exec { "lexvo_data_extract":
+            command => "/usr/bin/bunzip2 /tmp/lexvo/lexvo.rdf.bz2",
+            unless => $unless,
+            creates => "/tmp/lexvo/lexvo.rdf"
+        }->
+        file { "lexvo_commands":
+            path => "/tmp/lexvo/console_commands.txt",
+            ensure => present,
+            source => "puppet:///modules/sysconfig/sesame/console_commands.txt",
+        }->
+        exec { "lexvo_console":
+            command => "/opt/sesame/bin/console.sh < /tmp/lexvo/console_commands.txt",
+            cwd => "/opt/sesame/bin",
+            unless => $unless
+        }->
+        exec { "lexvo_data_archive_delete":
+            command => "/usr/bin/rm -fr /tmp/lexvo"
+        }
+
+        #->
+        # File <| title == "lexvo_tmp_dir" |> {
+        #     path => "/tmp/lexvo",
+        #     ensure => absent,
+        # }
+    }
+
+    file { "/opt/sesame":
+        ensure => directory,
+    }->
+    archive { 'openrdf-sesame-4':
+        ensure => present,
+        url => "http://sourceforge.net/projects/sesame/files/Sesame%204/4.0.1/openrdf-sesame-4.0.1-sdk.tar.gz/download",
+        checksum => false,
+        follow_redirects => true,
+        strip_components => 1,
+        target => "/opt/sesame",
+        src_target => '/tmp',
+        timeout => 500,
+    }->
+    file { [ "/var/lib/sesame",
+             "/var/lib/sesame/data" ]:
+        ensure => directory,
+        owner => "tomcat",
+        group => "tomcat",
+        require => Package['tomcat']
+    }->
+    augeas { "etc-sysconfig/tomcat":
+        context => "/files/etc/sysconfig/tomcat",
+        changes => [
+            "set JAVA_OPTS '\"-Dinfo.aduna.platform.appdata.basedir=/var/lib/sesame/data -Xms512m -Xmx512m\"'"
+        ],
+        notify => Service['tomcat']
+    }->
+    exec { "copy-sesame-tomcat":
+         command => "/usr/bin/cp /opt/sesame/war/*.war /var/lib/tomcat/webapps",
+         notify => Service['tomcat']
+    }->
+    create_lexvo_repository { "create-lexvo-repository":
+        unless => '/usr/bin/curl -s -f -I http://localhost:8080/openrdf-sesame/repositories/lexvo/statements'
+    }
+
+
+#
+#download archive
+
+#put war at the right place
+
+#create the repository if not exists
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/sys_upgrade.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+class sysconfig::sys_upgrade {
+    package { 'epel':
+        name => 'epel-release',
+        ensure => present,
+    }->
+    yumrepo { 'remi':
+        descr      => 'Les RPM de remi pour Enterpise Linux $releasever - $basearch',
+        mirrorlist => 'http://rpms.famillecollet.com/enterprise/$releasever/remi/mirror',
+        gpgcheck   => 1,
+        gpgkey     => 'http://rpms.remirepo.net/RPM-GPG-KEY-remi',
+        enabled    => 1,
+        priority   => 1,
+    }->
+    exec { "yum-update":
+        command => "yum clean all; yum -q -y update",
+        timeout => 1800,
+        onlyif => "/usr/bin/test `stat --format=%Y /var/lib/yum/rpmdb-indexes` -le $(( `date +%s` - 86400 )) -o ! -e /var/lib/puppet/state/first_run ",
+        #onlyif => "/usr/bin/test `stat --format=%Y /var/lib/yum/rpmdb-indexes` -le $(( `date +%s` ))",
+        path => [ '/bin', '/usr/bin', '/uhttp://rpms.remirepo.net/RPM-GPG-KEY-remisr/local/bin' ]
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/manifests/tomcat.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+class sysconfig::tomcat (
+    $tomcat_open_port = hiera('sysconfig::params::tomcat_open_port', sysconfig::params::tomcat_open_port),
+) inherits sysconfig::params {
+
+    $package_list = [
+        'tomcat'
+    ]
+
+    package { $package_list:
+        ensure => present,
+        require => Package['java-1.8.0-openjdk-headless']
+    }
+
+    if any2bool($tomcat_open_port) {
+        exec { "open-tomcat-port":
+            command => "firewall-cmd --permanent --add-port=8080/tcp",
+            path => [ '/bin', '/usr/bin', '/usr/local/bin' ]
+        }->
+        exec { "open-tomcat-port-reload":
+            command => "firewall-cmd --reload",
+            path => [ '/bin', '/usr/bin', '/usr/local/bin' ]
+        }
+    }
+
+    service { "tomcat":
+        ensure => running,
+        enable => true,
+        require => Package['tomcat']
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/templates/corpus/corpus_env.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,29 @@
+SetEnv APP_ENV local
+SetEnv APP_DEBUG false
+SetEnv APP_KEY <%= @corpus_app_key %>
+SetEnv APP_URL http://<%= @vhost %>/corpus/
+
+SetEnv DATABASE_DRIVER mysql
+SetEnv DB_HOST localhost
+SetEnv DB_DATABASE <%= @db_name %>
+SetEnv DB_USERNAME <%= @db_user %>
+SetEnv DB_PASSWORD <%= @db_pw %>
+
+SetEnv CACHE_DRIVER file
+SetEnv SESSION_DRIVER file
+SetEnv QUEUE_DRIVER sync
+
+SetEnv MAIL_DRIVER smtp
+SetEnv MAIL_HOST mailtrap.io
+SetEnv MAIL_PORT 2525
+SetEnv MAIL_USERNAME null
+SetEnv MAIL_PASSWORD null
+
+SetEnv CORPUSPAROLE_COCOON_RDF_BASE_URI http://cocoon.huma-num.fr/exist/crdo/rdf/
+SetEnv CORPUSPAROLE_COCOON_OAIPMH_URL http://cocoon.huma-num.fr/crdo_servlet/oai-pmh
+SetEnv CORPUSPAROLE_SESAME_BASE_URL http://127.0.0.1:8080/openrdf-sesame
+SetEnv CORPUSPAROLE_SESAME_REPOSITORY corpus
+SetEnv CORPUSPAROLE_SESAME_REPOSITORY_RAW corpus_raw
+SetEnv CORPUSPAROLE_SESAME_LEXVO_REPOSITORY lexvo
+
+SetEnv EASYRDF_HTTP_CLIENT_TIMEOUT 5000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/templates/corpus/local.env.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,29 @@
+APP_ENV=local
+APP_DEBUG=true
+APP_KEY=<%= @corpus_app_key %>
+APP_URL=http://<%= @vhost %>/corpus/
+
+DATABASE_DRIVER=mysql
+DB_HOST=localhost
+DB_DATABASE=<%= @db_name %>
+DB_USERNAME=<%= @db_user %>
+DB_PASSWORD=<%= @db_pw %>
+
+CACHE_DRIVER=file
+SESSION_DRIVER=file
+QUEUE_DRIVER=sync
+
+MAIL_DRIVER=smtp
+MAIL_HOST=mailtrap.io
+MAIL_PORT=2525
+MAIL_USERNAME=null
+MAIL_PASSWORD=null
+
+CORPUSPAROLE_COCOON_RDF_BASE_URI=http://cocoon.huma-num.fr/exist/crdo/rdf/
+CORPUSPAROLE_COCOON_OAIPMH_URL=http://cocoon.huma-num.fr/crdo_servlet/oai-pmh
+CORPUSPAROLE_SESAME_BASE_URL=http://172.16.1.6:8080/openrdf-sesame/
+CORPUSPAROLE_SESAME_REPOSITORY=corpus
+CORPUSPAROLE_SESAME_REPOSITORY_RAW=corpus_raw
+CORPUSPAROLE_SESAME_LEXVO_REPOSITORY=lexvo
+
+EASYRDF_HTTP_CLIENT_TIMEOUT=5000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/sysconfig/templates/httpd/vhost.conf.erb	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,48 @@
+# ************************************
+# Vhost template in module sysconfig
+# Managed by Puppet
+# ************************************
+
+<VirtualHost *:80>
+  ServerName <%= @vhost %>
+
+  ## Vhost docroot
+  DocumentRoot "/var/www/corpusdelaparole/drupal"
+
+  ## Alias declarations for resources outside the DocumentRoot
+  Alias /corpus "/var/www/corpusdelaparole/corpus/public"
+
+  <Directory "/var/www/corpusdelaparole/drupal">
+    AllowOverride all
+    Require all granted
+  </Directory>
+
+
+  <Directory "/var/www/corpusdelaparole/corpus/public">
+    AllowOverride None
+    Require all granted
+    IncludeOptional /etc/www/corpus_env.con[f]
+    <IfModule mod_rewrite.c>
+      <IfModule mod_negotiation.c>
+        Options -MultiViews
+      </IfModule>
+
+      RewriteEngine On
+      RewriteBase /corpus/
+
+      # Redirect Trailing Slashes...
+      RewriteRule ^(.*)/$ /corpus/$1 [L,R=301]
+
+      # Handle Front Controller...
+      RewriteCond %{REQUEST_FILENAME} !-d
+      RewriteCond %{REQUEST_FILENAME} !-f
+      RewriteRule ^ index.php [L]
+    </IfModule>
+  </Directory>
+
+  ## Logging
+  ErrorLog "/var/log/httpd/corpusdelaparole_error.log"
+  ServerSignature Off
+  CustomLog "/var/log/httpd/corpusdelaparole_access.log" combined
+
+</VirtualHost>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/CHANGELOG.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,58 @@
+## 2015-05-29 - Release 0.9.6
+
+Fixed check for installed YUM group on RHEL 7.
+
+#### Bugfixes
+
+- Fixed check for installed YUM group on RHEL/CentOS 7
+
+## 2015-04-07 - Release 0.9.5
+
+New class yum, defined resource yum::config. Trigger old kernels purge.
+
+#### Features
+
+- New defined resource yum::config to allow changes in /etc/yum.conf.
+- New class yum to set common global parameters
+- If installonly_limit is changed, old kernels above the limit are purged.
+
+## 2014-12-08 - Release 0.9.4
+
+Fix file/directory permissions.
+
+#### Bugfixes
+
+- Fix PF module archive file/directory permissions.
+
+## 2014-11-06 - Release 0.9.3
+
+Enable yum.conf plugins if disabled.
+
+#### Bugfixes
+
+- Enable yum.conf plugins (if disabled) when we
+  install plugin via yum::plugin.
+
+## 2014-09-02 - Release 0.9.2
+
+Fix metadata.json
+
+#### Bugfixes
+
+- Fix metadata.json module dependencies
+
+## 2014-08-20 - Release 0.9.1
+
+### Summary
+
+Fix GPG key import check when key is specified in $content.
+
+#### Bugfixes
+
+- Fix GPG key import check when key is specified in $content.
+
+## 2014-08-07 - Release 0.9.0
+
+### Summary
+
+Initial release.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/LICENSE	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-15 Institute of Computer Science, Masaryk University
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/README.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,118 @@
+# Puppet yum module
+
+This module provides helpful definitions for dealing with *yum*.
+
+### Requirements
+
+Module has been tested on:
+
+* Puppet 3.7.x
+* CentOS 6, 7
+
+# Usage
+
+### yum
+
+Manage main Yum configuration.
+
+```puppet
+class { 'yum':
+  keepcache         => false|true,
+  debuglevel        => number,
+  exactarch         => false|true,
+  obsoletes         => false|true,
+  gpgcheck          => false|true,
+  installonly_limit => number,
+  keep_kernel_devel => false|true,
+}
+```
+
+If `installonly_limit` is changed, purging of old kernel packages is triggered.
+
+### yum::config
+
+Manage yum.conf.
+
+```puppet
+yum::config { 'installonly_limit':
+  ensure => 2,
+}
+
+yum::config { 'debuglevel':
+  ensure => absent,
+}
+```
+
+### yum::gpgkey
+
+Import/remove GPG RPM signing key.
+
+Key defined in recipe (inline):
+
+```puppet
+yum::gpgkey { '/etc/pki/rpm-gpg/RPM-GPG-KEY-puppet-smoketest1':
+  ensure  => present,
+  content => '-----BEGIN PGP PUBLIC KEY BLOCK-----
+...
+-----END PGP PUBLIC KEY BLOCK-----',
+}
+```
+
+Key stored on Puppet fileserver:
+
+```puppet
+yum::gpgkey { '/etc/pki/rpm-gpg/RPM-GPG-KEY-elrepo.org':
+  ensure => present,
+  source => 'puppet:///modules/elrepo/RPM-GPG-KEY-elrepo.org',
+}
+```
+
+### yum::plugin
+
+Install or remove *yum* plugin:
+
+```puppet
+yum::plugin { 'versionlock':
+  ensure => present,
+}
+```
+
+### yum::versionlock
+
+Locks explicitly specified packages from updates. Package name must
+be precisely specified in format *`EPOCH:NAME-VERSION-RELEASE.ARCH`*.
+Wild card in package name is allowed or automatically appended,
+but be careful and always first check on target machine if your
+package is matched correctly! Following definitions create same
+configuration lines:
+
+```puppet
+yum::versionlock { '0:bash-4.1.2-9.el6_2.*':
+  ensure => present,
+}
+
+yum::versionlock { '0:bash-4.1.2-9.el6_2.':
+  ensure => present,
+}
+```
+
+Correct name for installed package can be easily get by running e.g.:
+
+```bash
+$ rpm -q bash --qf '%|EPOCH?{%{EPOCH}}:{0}|:%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n'
+0:bash-4.2.45-5.el7_0.4.x86_64
+```
+
+### yum::group
+
+Install or remove *yum* package group:
+
+```puppet
+yum::group { 'X Window System':
+  ensure => present,
+}
+```
+
+***
+
+CERIT Scientific Cloud, <support@cerit-sc.cz>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/checksums.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,18 @@
+{
+  "CHANGELOG.md": "0b88f028270dc08cc5657b2d08692ffc",
+  "LICENSE": "ae049f0feee6dd1ea35761d62e3cb270",
+  "README.md": "386a9df1dd6f3ccca059ec34e3b73d8e",
+  "manifests/config.pp": "d3a5658b2eccaf9a4f16e87d2050cd6f",
+  "manifests/gpgkey.pp": "9e718f190372ed8bf43c76f0f9764cfc",
+  "manifests/group.pp": "e74b339ed1df6ccf4ba0cec7d9571683",
+  "manifests/init.pp": "e712c77a491b2c4129d1b5f10517498c",
+  "manifests/params.pp": "132523805b400dda5d05ec8496f5f4c7",
+  "manifests/plugin/versionlock.pp": "4e211ab903b849b62e9f3676d0b5239d",
+  "manifests/plugin.pp": "1524e4b5f95bf55eade9980f790facb4",
+  "manifests/versionlock.pp": "da7302493f18346419cb41715e6ddc34",
+  "metadata.json": "1b99301faaa3307c8ae9317699963bc1",
+  "tests/gpgkey.pp": "9f1adecd3c79452762f5d6eb334c4ba2",
+  "tests/group.pp": "594975a6b5b6be1a301236970dd0be7e",
+  "tests/plugin.pp": "685dfad0d335956cb3448a99d7f9a944",
+  "tests/versionlock.pp": "7123d994a637a3ac339b9a3bb24c0ac6"
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/manifests/config.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+# Define: yum::config
+#
+# This definition manages yum.conf
+#
+# Parameters:
+#   [*key*]      - alternative conf. key (defaults to name)
+#   [*ensure*]   - specifies value or absent keyword
+#   [*section*]  - config section (default to main)
+#
+# Actions:
+#
+# Requires:
+#   RPM based system
+#
+# Sample usage:
+#   yum::config { 'installonly_limit':
+#     ensure => 2,
+#   }
+#
+#   yum::config { 'debuglevel':
+#     ensure => absent,
+#   }
+#
+define yum::config (
+  $ensure,
+  $key     = $title,
+  $section = 'main'
+) {
+  validate_string($key, $section)
+
+  unless is_integer($ensure) {
+    validate_string($ensure)
+  }
+
+  $_changes = $ensure ? {
+    absent  => "rm  ${key}",
+    default => "set ${key} ${ensure}",
+  }
+
+  augeas { "yum.conf_${section}_${key}":
+    incl    => '/etc/yum.conf',
+    lens    => 'Yum.lns',
+    context => "/files/etc/yum.conf/${section}/",
+    changes => $_changes,
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/manifests/gpgkey.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,87 @@
+# Define: yum::gpgkey
+#
+# This definition saves and imports public GPG key for RPM. Key can
+# be stored on Puppet's fileserver or as inline content. Key can be
+# also removed from system.
+#
+# Parameters:
+#   [*path*]     - alternative file location (defaults to name)
+#   [*ensure*]   - specifies if key should be present or absent
+#   [*content*]  - content
+#   [*source*]   - source (e.g.: puppet:///)
+#   [*owner*]    - file owner
+#   [*group*]    - file group
+#   [*mode*]     - file mode
+#
+# Actions:
+#
+# Requires:
+#   RPM based system
+#
+# Sample usage:
+#   yum::gpgkey { '/etc/pki/rpm-gpg/RPM-GPG-KEY-puppet-smoketest1':
+#     ensure  => present,
+#     content => '-----BEGIN PGP PUBLIC KEY BLOCK-----
+#   ...
+#   -----END PGP PUBLIC KEY BLOCK-----';
+#   }
+#
+define yum::gpgkey (
+  $path    = $name,
+  $ensure  = present,
+  $content = '',
+  $source  = '',
+  $owner   = 'root',
+  $group   = 'root',
+  $mode    = '0644'
+) {
+  validate_absolute_path($path)
+  validate_string($owner, $group, $mode)
+
+  file { $path:
+    ensure => $ensure,
+    owner  => $owner,
+    group  => $group,
+    mode   => $mode,
+  }
+
+  if ($content == '') and ($source == '') {
+    fail('Missing params: $content or $source must be specified')
+  } elsif $content {
+    File[$path] {
+      content => $content
+    }
+  } else {
+    File[$path] {
+      source => $source
+    }
+  }
+
+  $rpmname = "gpg-pubkey-$( \
+gpg --quiet --with-colon --homedir=/root --throw-keyids <${path} | \
+cut -d: -f5 | cut -c9- | tr '[A-Z]' '[a-z]' | head -1)"
+
+  case $ensure {
+    present: {
+      exec { "rpm-import-${name}":
+        path    => '/bin:/usr/bin:/sbin/:/usr/sbin',
+        command => "rpm --import ${path}",
+        unless  => "rpm -q ${rpmname}",
+        require => File[$path],
+      }
+    }
+
+    absent: {
+      exec { "rpm-delete-${name}":
+        path    => '/bin:/usr/bin:/sbin/:/usr/sbin',
+        command => "rpm -e ${rpmname}",
+        onlyif  => ["test -f ${path}", "rpm -q ${rpmname}"],
+        before  => File[$path],
+      }
+    }
+
+    default: {
+      fail("Invalid ensure state: ${ensure}")
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/manifests/group.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,46 @@
+# Define: yum::group
+#
+# This definition installs or removes yum package group.
+#
+# Parameters:
+#   [*ensure*]   - specifies if package group should be
+#                  present (installed) or absent (purged)
+#
+# Actions:
+#
+# Requires:
+#   RPM based system
+#
+# Sample usage:
+#   yum::group { 'X Window System':
+#     ensure  => present,
+#   }
+#
+define yum::group (
+  $ensure = present
+) {
+  Exec {
+    path        => '/bin:/usr/bin:/sbin:/usr/sbin',
+    environment => 'LC_ALL=C'
+  }
+
+  case $ensure {
+    present,installed: {
+      exec { "yum-groupinstall-${name}":
+        command => "yum -y groupinstall '${name}'",
+        unless  => "yum grouplist '${name}' | egrep -i '^Installed.+Groups:$'",
+      }
+    }
+
+    absent,purged: {
+      exec { "yum-groupremove-${name}":
+        command => "yum -y groupremove '${name}'",
+        onlyif  => "yum grouplist '${name}' | egrep -i '^Installed.+Groups:$'",
+      }
+    }
+
+    default: {
+      fail("Invalid ensure state: ${ensure}")
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/manifests/init.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,90 @@
+# Class: yum
+#
+# Manage Yum configuration.
+#
+# Parameters:
+#   [*keepcache*]         - Yum option keepcache
+#   [*debuglevel*]        - Yum option debuglevel
+#   [*exactarch*]         - Yum option exactarch
+#   [*obsoletes*]         - Yum option obsoletes
+#   [*gpgcheck*]          - Yum option gpgcheck
+#   [*installonly_limit*] - Yum option installonly_limit
+#   [*keep_kernel_devel*] - On old kernels purge keep devel packages.
+#
+# Actions:
+#
+# Requires:
+#   RPM based system
+#
+# Sample usage:
+#   class { 'yum':
+#     installonly_limit => 2,
+#   }
+#
+class yum (
+  $keepcache         = $yum::params::keepcache,
+  $debuglevel        = $yum::params::debuglevel,
+  $exactarch         = $yum::params::exactarch,
+  $obsoletes         = $yum::params::obsoletes,
+  $gpgcheck          = $yum::params::gpgcheck,
+  $installonly_limit = $yum::params::installonly_limit,
+  $keep_kernel_devel = $yum::params::keep_kernel_devel
+) inherits yum::params {
+
+  validate_bool($keepcache, $exactarch, $obsoletes, $gpgcheck)
+  validate_bool($keep_kernel_devel)
+
+  unless is_integer($installonly_limit) {
+    validate_string($installonly_limit)
+  }
+
+  unless is_integer($debuglevel) {
+    validate_string($debuglevel)
+  }
+
+  # configure Yum
+  yum::config { 'keepcache':
+    ensure => bool2num($keepcache),
+  }
+
+  yum::config { 'debuglevel':
+    ensure => $debuglevel,
+  }
+
+  yum::config { 'exactarch':
+    ensure => bool2num($exactarch)
+  }
+
+  yum::config { 'obsoletes':
+    ensure => bool2num($obsoletes)
+  }
+
+  yum::config { 'gpgcheck':
+    ensure => bool2num($gpgcheck)
+  }
+
+  yum::config { 'installonly_limit':
+    ensure => $installonly_limit,
+    notify => Exec['package-cleanup_oldkernels'],
+  }
+
+  # cleanup old kernels
+  ensure_packages(['yum-utils'])
+
+  $_pc_cmd = delete_undef_values([
+    '/usr/bin/package-cleanup',
+    '--oldkernels',
+    "--count=${installonly_limit}",
+    '-y',
+    $keep_kernel_devel ? {
+      true    => '--keepdevel',
+      default => undef,
+    },
+  ])
+
+  exec { 'package-cleanup_oldkernels':
+    command     => shellquote($_pc_cmd),
+    refreshonly => true,
+    require     => Package['yum-utils'],
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/manifests/params.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,17 @@
+class yum::params {
+  case $::osfamily {
+    redhat: {
+      $keepcache = false
+      $debuglevel = 2
+      $exactarch = true
+      $obsoletes = true
+      $gpgcheck = true
+      $installonly_limit = 5
+      $keep_kernel_devel = false
+    }
+
+    default: {
+      fail("Unsupported OS family: ${::osfamily}")
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/manifests/plugin.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+# Define: yum::plugin
+#
+# This definition installs Yum plugin.
+#
+# Parameters:
+#   [*ensure*]   - specifies if plugin should be present or absent
+#
+# Actions:
+#
+# Requires:
+#   RPM based system
+#
+# Sample usage:
+#   yum::plugin { 'versionlock':
+#     ensure  => present,
+#   }
+#
+define yum::plugin (
+  $ensure     = present,
+  $pkg_prefix = 'yum-plugin',
+  $pkg_name   = ''
+) {
+  $_pkg_name = $pkg_name ? {
+    ''      => "${pkg_prefix}-${name}",
+    default => "${pkg_prefix}-${pkg_name}"
+  }
+
+  package { $_pkg_name:
+    ensure  => $ensure,
+  }
+
+  if ! defined(Yum::Config['plugins']) {
+    yum::config { 'plugins':
+      ensure => 1,
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/manifests/plugin/versionlock.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,21 @@
+# Class: yum::plugin::versionlock
+#
+# This class installs versionlock plugin
+#
+# Parameters:
+#   [*ensure*] - specifies if versionlock should be present or absent
+#
+# Actions:
+#
+# Requires:
+#
+# Sample usage:
+#   include yum::plugin::versionlock
+#
+class yum::plugin::versionlock (
+  $ensure = present
+) {
+  yum::plugin { 'versionlock':
+    ensure  => $ensure,
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/manifests/versionlock.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,56 @@
+# Define: yum::versionlock
+#
+# This definition locks package from updates.
+#
+# Parameters:
+#   [*ensure*] - specifies if versionlock should be present, absent or exclude
+#   [*path*]   - configuration of Yum plugin versionlock
+#
+# Actions:
+#
+# Requires:
+#   RPM based system, Yum versionlock plugin
+#
+# Sample usage:
+#   yum::versionlock { '0:bash-4.1.2-9.el6_2.*':
+#     ensure  => present,
+#   }
+#
+define yum::versionlock (
+  $ensure = present,
+  $path   = '/etc/yum/pluginconf.d/versionlock.list'
+) {
+  require yum::plugin::versionlock
+
+  if ($name =~ /^[0-9]+:.+\*$/) {
+    $_name = $name
+  } elsif ($name =~ /^[0-9]+:.+-.+-.+\./) {
+    $_name= "${name}*"
+  } else {
+    fail('Package name must be formated as \'EPOCH:NAME-VERSION-RELEASE.ARCH\'')
+  }
+
+  case $ensure {
+    present,absent,exclude: {
+      if ($ensure == present) or ($ensure == absent) {
+        file_line { "versionlock.list-${name}":
+          ensure => $ensure,
+          line   => $_name,
+          path   => $path,
+        }
+      }
+
+      if ($ensure == exclude) or ($ensure == absent) {
+        file_line { "versionlock.list-!${name}":
+          ensure => $ensure,
+          line   => "!${_name}",
+          path   => $path,
+        }
+      }
+    }
+
+    default: {
+      fail("Invalid ensure state: ${ensure}")
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/metadata.json	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,47 @@
+{
+  "name": "ceritsc-yum",
+  "version": "0.9.6",
+  "author": "ceritsc",
+  "summary": "YUM utilities",
+  "license": "MIT",
+  "source": "https://github.com/CERIT-SC/puppet-yum.git",
+  "project_page": "https://github.com/CERIT-SC/puppet-yum",
+  "issues_url": "https://github.com/CERIT-SC/puppet-yum/issues",
+  "tags": [
+    "yum",
+    "package"
+  ],
+  "operatingsystem_support": [
+    {
+      "operatingsystem": "RedHat"
+    },
+    {
+      "operatingsystem": "CentOS"
+    },
+    {
+      "operatingsystem": "OracleLinux"
+    },
+    {
+      "operatingsystem": "Scientific"
+    },
+    {
+      "operatingsystem": "SLES"
+    },
+    {
+      "operatingsystem": "SLED"
+    }
+  ],
+  "requirements": [
+    {
+      "name": "pe",
+      "version_requirement": "3.3.x"
+    },
+    {
+      "name": "puppet",
+      "version_requirement": "3.3"
+    }
+  ],
+  "dependencies": [
+    {"name":"puppetlabs/stdlib","version_requirement":">= 4.0.0"}
+  ]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/tests/gpgkey.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+yum::gpgkey { '/etc/pki/rpm-gpg/RPM-GPG-KEY-puppet-smoketest1':
+  ensure  => absent,
+  content => '-----BEGIN PGP PUBLIC KEY BLOCK-----...',
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/tests/group.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+yum::group { 'X Window System':
+  ensure => present,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/tests/plugin.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+yum::plugin { 'versionlock':
+  ensure => present,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dev/provisioning/modules/yum/tests/versionlock.pp	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+yum::versionlock { '0:bash-4.1.2-9.el6_2.*':
+  ensure  => present,
+}
--- a/dev/provisioning/playbook.yml	Fri Jan 15 15:27:56 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,387 +0,0 @@
----
-- hosts: all
-
-  vars:
-
-    # These are the Wordpress database settings
-    db_name: corpus
-    db_user: corpus
-    db_password: md5bf687edf8c06f3f1aa3759c82c1217a0
-
-  tasks:
-#   - name: install language pack
-#     command: localedef -v -c -i en_US -f UTF-8 en_US.UTF-8
-
-    - name: set hostname
-      hostname: name={{site_name}}
-    - name: set hosts IPv4
-      lineinfile:
-        dest: /etc/hosts
-        line: 127.0.0.1   corpus-parole corpus-parole.local
-    - name: set hosts IPv6
-      lineinfile:
-        dest: /etc/hosts
-        line: ::1         corpus-parole corpus-parole.local
-
-    - name: ensure correct locale LC_ALL
-      lineinfile: dest=/etc/sysconfig/i18n regexp=^LC_ALL= line=LC_ALL="en_US.UTF-8"
-    - name: ensure correct locale LANG
-      lineinfile: dest=/etc/sysconfig/i18n regexp=^LANG= line=LANG="en_US.UTF-8"
-
-    # - name: set .bashrc
-    #   copy: src=files/.bashrc dest=/home/vagrant/.bashrc force=yes
-    # - name: set .profile
-    #   copy: src=files/.profile dest=/home/vagrant/.profile force=yes
-
-    - name: check yum base last update
-      stat: path=/var/cache/yum/x86_64/6/base/cachecookie
-      register: yum_cache_stat_base
-
-    - name: yum update
-      yum: name=* update_cache=yes state=latest
-#      when: ansible_date_time.epoch|float - yum_cache_stat_base.stat.mtime > 60*60*12*24
-
-    - name: repo ignore outdated postgres base
-      ini_file:
-        dest: /etc/yum.repos.d/CentOS-Base.repo
-        section: base
-        option: exclude=postgresql*
-
-    - name: repo ignore outdated postgres update
-      ini_file:
-        dest: /etc/yum.repos.d/CentOS-Base.repo
-        section: updates
-        option: exclude=postgresql*
-
-    - name: additional repos install
-      yum: name={{item}} state=latest
-      with_items:
-        - epel-release
-        - centos-release-SCL
-
-    # Remi yum repository.
-    - stat: path=/etc/yum.repos.d/remi.repo
-      register: remi_repo
-
-    - name: Download Remi repo.
-      get_url: url=http://rpms.famillecollet.com/enterprise/remi-release-6.rpm dest=/tmp/
-      when: remi_repo.stat.exists == False
-
-    - name: Install Remi repo.
-      command: rpm -Uvh --force /tmp/remi-release-6.rpm creates=/etc/yum.repos.d/remi.repo
-      when: remi_repo.stat.exists == False
-
-    - name : delete remi rpm
-      file: path=/tmp/remi-release-6.rpm state=absent
-
-    # postgres yum repository.
-    - stat: path=/etc/yum.repos.d/pgdg-94-centos.repo
-      register: postgres_repo
-
-    - name: Download Postgres repo.
-      get_url: url=http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/pgdg-centos94-9.4-1.noarch.rpm dest=/tmp/
-      when: postgres_repo.stat.exists == False
-
-    - name: Install postgres repo.
-      command: rpm -Uvh --force /tmp/pgdg-centos94-9.4-1.noarch.rpm creates=/etc/yum.repos.d/pgdg-94-centos.repo
-      when: postgres_repo.stat.exists == False
-
-    - name : delete postgres rpm
-      file: path=/tmp/pgdg-centos94-9.4-1.noarch.rpm state=absent
-
-    - name: additional repos install epel
-      ini_file:
-        dest: /etc/yum.repos.d/epel.repo
-        section: epel
-        option: enabled
-        value: 1
-
-    - name: check yum epel last update
-      stat: path=/var/cache/yum/x86_64/6/epel/cachecookie
-      register: yum_cache_stat_epel
-
-    - name: yum update after repos
-      yum: name=* update_cache=yes state=latest
-#      when: ansible_date_time.epoch|float - yum_cache_stat_epel.stat.mtime > 60*60*12*24
-
-    #TODO install alternative packages
-    - name: install libs
-      yum: name={{item}} state=latest enablerepo=remi
-      with_items:
-        - nginx
-        - postgresql94-server
-        - python-psycopg2
-        - htop
-        - openssl
-        - php56
-        - php56-php-fpm
-        - php56-php-mbstring
-        - php56-php-mcrypt
-        - php56-php-gd
-        - php56-php-pgsql
-        - java-1.8.0-openjdk
-        - tomcat
-
-
-## php-fpm config
-
-# set fpm user to nginx
-# authorize /var/log/php-fpm
-    - name: copy sysconfig for php-fpm
-      copy: src=files/sysconfig_php-fpm dest=/opt/remi/php56/root/etc/sysconfig/php-fpm
-    - name: set /opt/remi/php56/root/var/log/php-fpm permission
-      file: path=/opt/remi/php56/root/var/log/php-fpm/ state=directory owner=nginx group=nginx
-
-    - name: set php-fpm listen to socket
-      lineinfile:
-        dest: /opt/remi/php56/root/etc/php-fpm.d/www.conf
-        regexp: '^listen\s*='
-        line: 'listen = /opt/remi/php56/root/var/run/php-fpm/php-fpm.sock'
-        state: present
-
-    - name: set php-fpm user
-      lineinfile:
-        dest: /opt/remi/php56/root/etc/php-fpm.d/www.conf
-        regexp: '^user\s*='
-        line: 'user = nginx'
-        state: present
-
-    - name: set php-fpm group
-      lineinfile:
-        dest: /opt/remi/php56/root/etc/php-fpm.d/www.conf
-        regexp: '^group\s*='
-        line: 'group = nginx'
-        state: present
-
-    - name: set php-fpm user
-      lineinfile:
-        dest: /opt/remi/php56/root/etc/php-fpm.d/www.conf
-        regexp: '^;listen.owner\s*='
-        line: 'listen.owner = nginx'
-        state: present
-
-    - name: set php-fpm group
-      lineinfile:
-        dest: /opt/remi/php56/root/etc/php-fpm.d/www.conf
-        regexp: '^;listen.group\s*='
-        line: 'listen.group = nginx'
-        state: present
-
-    - name: set php-fpm permission
-      lineinfile:
-        dest: /opt/remi/php56/root/etc/php-fpm.d/www.conf
-        regexp: '^;listen.mode\s*='
-        line: 'listen.mode = 0660'
-        state: present
-
-    - name: add link to php56 fpm log
-      file: path=/var/log/php56-php-fpm src=/opt/remi/php56/root/var/log/php-fpm state=link
-
-    - name: restart php-fpm
-      service: name=php56-php-fpm state=restarted enabled=yes
-
-
-## nginx config
-
-    - name: create ssl folder
-      file: path=/etc/nginx/ssl state=directory mode=0700
-    - name: generate ssl key
-      command: openssl genrsa -out "/etc/nginx/ssl/{{ site_name }}.key" 1024
-      args:
-        creates: /etc/nginx/ssl/{{ site_name }}.key
-    - name: generate ssl csr
-      command: openssl req -new -key /etc/nginx/ssl/{{ site_name }}.key -out /etc/nginx/ssl/{{ site_name }}.csr -subj "/CN={{ site_name }}/O=MCC/C=FR"
-      args:
-        creates: /etc/nginx/ssl/{{ site_name }}.csr
-    - name: generate ssl certificate
-      command: openssl x509 -req -days 365 -in /etc/nginx/ssl/{{ site_name }}.csr -signkey /etc/nginx/ssl/{{ site_name }}.key -out /etc/nginx/ssl/{{ site_name }}.crt
-      args:
-        creates: /etc/nginx/ssl/{{ site_name }}.crt
-
-    - name: change nginx default
-      template: src=files/site.j2 dest=/etc/nginx/nginx.conf mode=0644 force=yes
-
-    - name: restart nginx
-      service: name=nginx state=restarted enabled=yes
-
-
-## postgres
-    - name: set postgresql to start
-      service: name=postgresql-9.4 enabled=yes
-
-    - name: postgresql initdb
-      command: service postgresql-9.4 initdb
-      args:
-        creates: /var/lib/pgsql/9.4/data/postgresql.conf
-
-## configure tomcat
-
-    - name: set JAVA_HOME
-      lineinfile:
-        dest: /etc/tomcat/tomcat.conf
-        regexp: '^\#?JAVA_HOME='
-        line: JAVA_HOME="/etc/alternatives/jre_1.8.0"
-        state: present
-
-    - name: set parseBodyMethods to add POST
-      lineinfile:
-        dest: /etc/tomcat/server.xml
-        regexp: '^\s+\<Connector\s+port=\"8080\"\s+protocol=\"HTTP\/1.1\"\s*$'
-        line: '    <Connector port="8080" protocol="HTTP/1.1" parseBodyMethods="POST,PUT"'
-        state: present
-
-## Install sesame
-    - stat: path=/var/lib/tomcat/webapps/openrdf-sesame.war
-      register: sesame_jar
-
-    - name: download sesame
-      get_url: url=http://sourceforge.net/projects/sesame/files/Sesame%204/4.0.0/openrdf-sesame-4.0.0-sdk.tar.gz/download dest=/tmp/openrdf-sesame-4.0.0-sdk.tar.gz
-      when: sesame_jar.stat.exists == False
-
-    - name: create sesame untar dest
-      file: path=/tmp/openrdf-sesame-4.0.0-sdk state=directory
-      when: sesame_jar.stat.exists == False
-
-    - name: unarchive sesame
-      unarchive: src=/tmp/openrdf-sesame-4.0.0-sdk.tar.gz dest=/tmp/openrdf-sesame-4.0.0-sdk copy=false
-      when: sesame_jar.stat.exists == False
-
-    - name: deploy sesame jar
-      shell: cp /tmp/openrdf-sesame-4.0.0-sdk/openrdf-sesame-4.0.0/war/*.war /var/lib/tomcat/webapps/
-      when: sesame_jar.stat.exists == False
-
-    - name: create sesame data folder
-      file: path=/var/lib/sesame/data state=directory owner=tomcat group=tomcat
-      when: sesame_jar.stat.exists == False
-
-    - name: update tomcat config
-      lineinfile:
-        dest: /etc/tomcat/tomcat.conf
-        line: 'JAVA_OPTS=\"${JAVA_OPTS} -Dinfo.aduna.platform.appdata.basedir=/var/lib/sesame/data -Xms512m -Xmx512m\"'
-        state: present
-      when: sesame_jar.stat.exists == False
-
-    - name: restart tomcat
-      service: name=tomcat state=restarted enabled=yes
-      when: sesame_jar.stat.exists == False
-
-    - name : delete sesame archive
-      file: path=/tmp/openrdf-sesame-4.0.0-sdk.tar.gz state=absent
-
-    - name : delete sesame untar
-      file: path=/tmp/openrdf-sesame-4.0.0-sdk state=absent
-
-
-#set postgresql local access to trust
-    - name: add trust access for postgresql user
-      lineinfile:
-        dest: /var/lib/pgsql/9.4/data/pg_hba.conf
-        regexp: '^host\s+all\s+postgres\s+.127\.0\.0\.1\/32\s+trust$'
-        insertafter: '^#\sIPv4\slocal.+'
-        line: 'host   all             postgres        127.0.0.1/32            trust'
-
-    - name: postgresql start
-      service: name=postgresql-9.4 state=started
-
-    - name: Create database user
-      postgresql_user: name={{ db_user }} password={{ db_password }} state=present
-      sudo: yes
-      sudo_user: postgres
-
-    - name: create database
-      postgresql_db: name={{ db_name }} encoding=utf8 owner={{ db_user }} state=present
-      sudo: yes
-      sudo_user: postgres
-
-    - name: restart postgres
-      service: name=postgresql-9.4 state=restarted
-
-## Install dev dependencies
-
-    - name: install dev tools
-      yum: name="{{item}}" state=latest
-      with_items:
-        - "@Development tools"
-
-    #install composer
-    - stat: path=/usr/local/bin/composer
-      register: composer_bin
-
-    - name: install composer
-      shell: curl -sS https://getcomposer.org/installer | scl enable php56 'php -- --install-dir=/usr/local/bin'
-      when: composer_bin.stat.exists == False
-    - name: link composer
-      file: path=/usr/local/bin/composer src=/usr/local/bin/composer.phar state=link
-      when: composer_bin.stat.exists == False
-
-    #install node
-    - stat: path=/usr/bin/node
-      register: node_bin
-
-    - name: install node rpm
-      shell: curl -sL https://rpm.nodesource.com/setup | bash -
-      when: node_bin.stat.exists == False
-    - name: install node
-      yum: name=nodejs state=latest
-      when: node_bin.stat.exists == False
-
-## open ports
-    - name: get iptables rules
-      shell: iptables -L
-      register: iptablesrules
-      always_run: yes
-      sudo: true
-
-    - name: add nginx http iptable rule
-      command: /sbin/iptables -I INPUT 1 -p tcp --dport http -j ACCEPT -m comment --comment "nginx 80"
-      sudo: true
-      when: iptablesrules.stdout.find("nginx 80") == -1
-
-    - name: add nginx http iptable rule
-      command: /sbin/iptables -I INPUT 1 -p tcp --dport https -j ACCEPT -m comment --comment "nginx 443"
-      sudo: true
-      when: iptablesrules.stdout.find("nginx 443") == -1
-
-    - name: add postgresql iptable rule
-      command: /sbin/iptables -I INPUT 1 -p tcp --dport 5432 -j ACCEPT -m comment --comment "postgresql"
-      sudo: true
-      when: iptablesrules.stdout.find("postgresql") == -1
-
-    - name: add tomcat iptable rule
-      command: /sbin/iptables -I INPUT 1 -p tcp --dport 8080 -j ACCEPT -m comment --comment "tomcat"
-      sudo: true
-      when: iptablesrules.stdout.find("tomcat") == -1
-
-    - name: save iptables
-      command: service iptables save
-      sudo: true
-
-    - name: restart iptables
-      service: name=iptables state=restarted
-      sudo: true
-
-# - name: install nginx
-#   apt: name=nginx
-#
-# - name: change nginx default
-#   copy: src=files/default dest=/etc/nginx/sites-available/ mode=0644 force=yes
-#
-# - name: install software-properties-common
-#   apt: name=software-properties-common
-#
-# - name: add repo
-#   copy: src=files/mariadb.list dest=/etc/apt/sources.list.d/
-#   register: mariadb_repo_present
-#
-# - name: add repokey
-#   command: apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xcbcb082a1bb943db
-#   when: mariadb_repo_present.changed
-#
-# - name: apt install mariadb
-#   apt: name={{item}} update_cache=yes
-#   with_items:
-#     - mysql-common=5.1.67-mariadb122~precise
-#     - libmariadbclient16=5.1.67-mariadb122~precise
-#     - mariadb-client-core-5.1=5.1.67-mariadb122~precise
-#     -
-#     - mariadb-server
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readme.md	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,53 @@
+# Projet Corpus de la parole
+
+## Prérequis
+- Vagrant
+- Ansible
+- node
+
+## Lancement VM dev
+- `cd /dev`
+- `cp provisioning/custom.yaml.tmpl provisioning/custom.yaml`
+- édition de `provisioning/custom.yaml`
+- `vagrant up` (nécessite une connexion internet)
+- url : http://vhost/corpus
+- accès sesame workbench : http://vhost:8080/openrdf-workbench
+- chargement des données dans `corpus` et `corpus_raw`
+
+## Lancement VM de build
+- Activation Ansible
+- `cd /build`
+- `vagrant up`
+
+## Initialisation env de dev
+- `cd /server/bo_client`
+- `npm install`
+- `bower install`
+- `cd /server/src`
+- télécharger composer.phar (https://getcomposer.org/) et le mettre dans le répertoire server/src
+- `php composer.phar install`
+- `npm install`
+- `bower install`
+
+## Commandes bo_client
+- `ember serve`
+- `ember build` -> résultat dans `server/bo_client/dist`
+
+## Commandes serveur php
+- Compilation css/js : `gulp` -> cette commande lance `ember build` de `/server/bo_client`
+- `php artisan serve`
+
+## Creation de version
+- mettre à jour le fichier version `/server/src/config/config/version.php`
+- `cd /server/src`
+- s'assurer que les sources sont à jour: `php composer.phar install` + `npm install` + `bower install`
+- `gulp`
+- `gulp copy-to-build`
+- `cd /build`
+- `vagrant ssh -c "/vagrant/build_rpm.sh"`
+- le fichier rpm se trouvera dans `/build`
+
+## installation rpm sur serveur
+- 1ère installation: `rpm -i /path/to/corpusdelaparole-<version>-<build>.rpm`
+- Mise à jour: `rpm -U /path/to/corpusdelaparole-<version>-<build>.rpm`
+- ensuite : création diu fichier `/etc/www/corpus_env.conf`
--- a/server/bo_client/.ember-cli	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/.ember-cli	Fri Jan 15 15:35:00 2016 +0100
@@ -5,5 +5,6 @@
 
     Setting `disableAnalytics` to true will prevent any data from being sent.
   */
-  "disableAnalytics": false
+  "disableAnalytics": true,
+  "usePods": true
 }
--- a/server/bo_client/app/adapters/application.js	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/app/adapters/application.js	Fri Jan 15 15:35:00 2016 +0100
@@ -1,5 +1,6 @@
 import DS from 'ember-data';
+import ENV from 'bo-client/config/environment';
 
 export default DS.RESTAdapter.extend({
-  namespace: 'api/v1',
+  namespace: ENV.baseURL.replace(/\/$/,"")+'/api/v1',
 });
--- a/server/bo_client/app/components/bo-doc-contributors.js	Fri Jan 15 15:27:56 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-import Ember from 'ember';
-import _ from 'lodash/lodash';
-
-export default Ember.Component.extend({
-
-  actions: {
-    toggleEditContributors : function() {
-      console.log("EDIT CONTRIBUTORS");
-      // var contributors = _.clone(this.get('document').get('contributors'));
-      // console.log("EDIT CONTRIBUTPRS", contributors);
-      // contributors.push({
-      //   name: "Hello world",
-      //   url: null,
-      //   role: 'http://www.language-archives.org/OLAC/1.1/annotator'
-      // });
-      // this.get('document').set('contributors', contributors);
-      Ember.$('#doc-contributors-table-pane').slideToggle();
-      Ember.$('#doc-contributors-list-pane').slideToggle();
-    }
-  }
-});
--- a/server/bo_client/app/index.html	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/app/index.html	Fri Jan 15 15:35:00 2016 +0100
@@ -9,7 +9,8 @@
     {{content-for 'head'}}
 
     <!-- Fonts -->
-    <link href='//fonts.googleapis.com/css?family=Roboto:400,300' rel='stylesheet' type='text/css'>
+    <link rel="stylesheet" href="assets/css/fonts.css">
+    <!--link href='//fonts.googleapis.com/css?family=Roboto:400,300' rel='stylesheet' type='text/css'-->
 
     <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
     <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
@@ -20,7 +21,6 @@
     <![endif]-->
     <link rel="stylesheet" href="assets/bo-client-vendor.css">
     <link rel="stylesheet" href="assets/bo-client.css">
-
     {{content-for 'head-footer'}}
   </head>
   <body>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/initializers/constants.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+export function initialize(application) {
+  application.inject('route', 'constants', 'service:constants');
+  application.inject('controller', 'constants', 'service:constants');
+  application.inject('component', 'constants', 'service:constants');
+}
+
+export default {
+  name: 'constants',
+  initialize
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/initializers/options.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,43 @@
+// Copied and modified from https://gist.github.com/walter/3e852e8ebc87535a3c91
+import Ember from 'ember';
+import config from 'bo-client/config/environment';
+
+
+
+export function initialize(application) {
+    var OptionsReader = function OptionsReader() {
+    this.readOptionsKeys = function() {
+      var _mapType = function(val) {
+        return "" === val ? null : "true" === val ? true : "false" === val ? false : (-1 !== val.indexOf(",") && (val = val.split(",")), val);
+      };
+
+      // Grab all the meta tags from the DOM.
+      var metaTags = Ember.$("meta");
+      var options = Ember.Object.create();
+      var re = new RegExp(config.modulePrefix + '\.');
+
+      // Process each of the discovered meta tags.
+      for(var i=0; i < metaTags.length; i++) {
+        var key = Ember.$(metaTags[i]).attr('name');
+        var value = Ember.$(metaTags[i]).attr('content');
+
+        // Does the meta tag start with our MODULE_PREFIX?
+        if (re.test(key)) {
+          var propertyName = Ember.String.camelize(key.substring(config.modulePrefix.length+1));
+          options[propertyName] = _mapType(value);
+        }
+      }
+      return options;
+    };
+  };
+
+  var optionsReader = new OptionsReader();
+
+  application.register('service:options', optionsReader.readOptionsKeys(), {singleton: true, instantiate: false});
+
+}
+
+export default {
+  name: 'options',
+  initialize
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/instance-initializers/i18n.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+export default {
+  name: 'i18n',
+  initialize: function( instance ) {
+    instance.lookup('service:i18n').set('locale', calculateLocale());
+  }
+};
+
+function calculateLocale() {
+  // whatever you do to pick a locale for the user:
+  return navigator.language || navigator.userLanguage || 'fr-FR';
+}
--- a/server/bo_client/app/locales/en/translations.js	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/app/locales/en/translations.js	Fri Jan 15 15:35:00 2016 +0100
@@ -12,11 +12,13 @@
     "document_audio": "Audio:",
     "document_content": "Content",
     "document_title": "Title:",
+    "document_language": "Language:",
     "document_editors": "Editor(s):",
     "document_contributors": "Contributor(s):",
     "contributors_th_name": "Name",
     "contributors_th_url": "URL",
     "contributors_th_role": "Role",
+    "contributors_th_actions": "Actions",
     "olac_role_annotator": "annotator",
     "olac_role_author": "author",
     "olac_role_compiler": "compiler",
@@ -41,6 +43,10 @@
     "olac_role_sponsor": "sponsor",
     "olac_role_transcriber": "transcriber",
     "olac_role_translator": "translator",
+
+    "button_save" : "Save",
+    "button_cancel" : "Cancel",
+
   }
 
   // "some.translation.key": "Text for some.translation.key",
--- a/server/bo_client/app/locales/fr/translations.js	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/app/locales/fr/translations.js	Fri Jan 15 15:35:00 2016 +0100
@@ -11,11 +11,13 @@
     "document_audio": "Audio :",
     "document_content": "Contenu",
     "document_title": "Titre :",
+    "document_language": "Langage :",
     "document_editors": "Editeur(s) :",
     "document_contributors": "Contributeur(s) :",
     "contributors_th_name": "Nom",
     "contributors_th_url": "URL",
     "contributors_th_role": "Role",
+    "contributors_th_actions": "Actions",
     "olac_role_annotator": "annotateur",
     "olac_role_author": "auteur",
     "olac_role_compiler": "compilateur",
@@ -40,6 +42,9 @@
     "olac_role_sponsor": "sponsor",
     "olac_role_transcriber": "transcripteur",
     "olac_role_translator": "traducteur",
+
+    "button_save" : "Sauvegarder",
+    "button_cancel" : "Annuler",
   },
   // "some.translation.key": "Text for some.translation.key",
   //
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/mixins/cell-editing-mixin.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+import Ember from 'ember';
+import ClickOutsideMixin from 'bo-client/mixins/click-outside-mixin';
+
+export default Ember.Mixin.create(ClickOutsideMixin, {
+  isEditing: false,
+  // override from ClickOutsideMixin
+  onOutsideClickEnabled: Ember.computed.bool('isEditing'),
+
+  onOutsideClick() {
+    this.set('isEditing', false);
+  },
+  click() {
+    var _this = this;
+    setTimeout(() => {
+      _this.set('isEditing', true);
+    }, 200);
+  },
+  keyDown(event) {
+    if(event.which === this.get('constants').KEY_CODES.ESCAPE) {
+      this.set('isEditing', false);
+    }
+  },
+
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/mixins/click-outside-mixin.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,56 @@
+import Ember from 'ember';
+
+/**
+ * Mixin to detect outside click for a component.
+ * taken from http://stackoverflow.com/a/32115231
+ */
+export default Ember.Mixin.create({
+  onOutsideClick: Ember.K,
+  onOutsideClickEnabled: true,
+
+  handleOutsideClick: function(event) {
+    var element = this.$();
+    var target = Ember.$(event.target);
+    if(element && target) {
+      console.log("OUTSIDE CLICK", element.has(target).length, element.is(target));
+      if (!(element.has(target).length || element.is(target))) {
+        this.onOutsideClick();
+      }
+    }
+  },
+
+  _registerOutsideClickListener() {
+    let clickHandler = this.get('handleOutsideClick').bind(this);
+
+    return Ember.$(document).on('click', clickHandler);
+  },
+
+  _unregisterOutsideClickListener() {
+    let clickHandler = this.get('handleOutsideClick').bind(this);
+
+    return Ember.$(document).off('click', clickHandler);
+  },
+
+  _onOutsideClickEnabledChanged: Ember.observer('onOutsideClickEnabled', function() {
+    if(this.get('onOutsideClickEnabled')) {
+      this._registerOutsideClickListener();
+    }
+    else {
+      this._unregisterOutsideClickListener();
+    }
+  }),
+
+  setupOutsideClickListener: Ember.on('didInsertElement', function() {
+    this._super(...arguments);
+    if(this.get('onOutsideClickEnabled')) {
+      return this._registerOutsideClickListener();
+    }
+    else {
+      return Ember.$(document);
+    }
+  }),
+
+  removeOutsideClickListener: Ember.on('willDestroyElement', function() {
+    return this._unregisterOutsideClickListener();
+  })
+});
--- a/server/bo_client/app/models/document.js	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/app/models/document.js	Fri Jan 15 15:35:00 2016 +0100
@@ -8,6 +8,8 @@
 
   title: DS.attr('string'),
 
+  language: DS.attr('string'),
+
   publishers: DS.attr({defaultValue: []}),
 
   contributors: DS.attr({defaultValue: []}),
@@ -29,4 +31,43 @@
     }
     return res;
   }),
+
+  addContributor: function(contrib_def) {
+    var contributors = this.get('contributors');
+    if(_.findIndex(contributors, function(c) { return _.isEqual(c, contrib_def);}) < 0) {
+      contributors.pushObject(contrib_def);
+    }
+    // must set dirty
+    this.set('contributors', _.clone(this.get('contributors')));
+  },
+  removeContributor: function(contrib_def) {
+    var contributors = this.get('contributors');
+    var index = _.findIndex(contributors, function(c) { return _.isEqual(c, contrib_def);});
+    if(index >= 0) {
+      contributors.removeAt(index);
+    }
+    //must set dirty
+    this.set('contributors', _.clone(this.get('contributors')));
+  },
+  saveContributor: function(contrib_def, index) {
+    var contributors = this.get('contributors');
+    if(index < 0 || index >= contributors.length) {
+      return;
+    }
+
+    var contrib_def_map = {name: contrib_def.name||"", url: contrib_def.url||"", role: contrib_def.role||""};
+    var existingContribs = _.filter(contributors, function(c, i) {
+      return (i!==index && _.isEqual({name: c.name||"", url: c.url||"", role: c.role||""}, contrib_def_map));
+    });
+    if(existingContribs.length > 0) {
+      // contributor exists, remove contributor @ index
+      contributors.removeAt(index);
+    }
+    else {
+      contributors[index] = contrib_def;
+    }
+    //must set dirty only if needed
+    this.set('contributors', _.clone(this.get('contributors')));
+  }
+
 });
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-list-item/component.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  tagName: "span",
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-list-item/template.hbs	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+{{if index " ; "}}{{#if contrib.name }}{{#if contrib.url }}<a target="_blank" href="{{contrib.url}}" class="bo-doc-ref-link">{{contrib.name}}</a>{{ else }}{{contrib.name}}{{/if}}{{else}}<a target="_blank" href="{{contrib.url}}" class="bo-doc-ref-link">{{contrib.url}}</a>{{/if}} ({{ t (document-contributor-role-translation-tag contrib.role)}})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-nameurl-cell/component.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,44 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+
+  tagName: "td",
+  _colspan: 2,
+  attributeBindings: [ '_colspan:colspan'],
+  viafId: null,
+  isEditing: false,
+  valueChanged: Ember.K,
+
+  urlPresent: Ember.computed.bool('url'),
+
+  initialViafId: Ember.computed('url', 'name', function() {
+    let name = this.get('name');
+    let url = this.get('url');
+    return {
+      label: name,
+      value: name,
+      id: "",
+      url: url,
+      nametype: ""
+    };
+  }),
+
+  _nameurlChanged: Ember.observer('name', 'url', function() {
+    this.get('valueChanged')();
+  }),
+
+  _autocompleteComponentChanged: Ember.observer('autocompleteComponent', function() {
+    if(this.get('isEditing') && this.get('autocompleteComponent')) {
+      this.get('autocompleteComponent').$('input').focus();
+    }
+  }),
+
+  _viafIdChanged: Ember.observer('viafId', function() {
+    let viafId = this.get('viafId');
+    if(viafId) {
+      this.set('url', viafId.url);
+      this.set('name', viafId.value);
+    }
+  }),
+
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-nameurl-cell/styles.scss	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+$nameurl-gutter: 10px;
+
+.row {
+  margin-left: -($nameurl-gutter / 2);
+  margin-right: -($nameurl-gutter / 2);
+}
+.nameurl-col {
+  position: static;
+  float: left;
+  display: table-cell;
+  min-height: 1px;
+  padding: 0 (($nameurl-gutter / 2)-2 ) 0 (($nameurl-gutter / 2)-2);
+}
+
+.nameurl-col-name {
+  @extend .nameurl-col;
+  width: percentage(4.5 / 8);
+}
+
+.nameurl-col-url {
+  @extend .nameurl-col;
+  width: percentage(3.5 / 8);
+}
+
+.nameurl-col-autocomplete {
+  @extend .nameurl-col;
+  width: percentage(11/12);
+}
+
+.nameurl-col-icon {
+  @extend .nameurl-col;
+  width: percentage(1/12);
+}
+
+.nameurl-col-icon:focus {
+  outline: 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-nameurl-cell/template.hbs	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,19 @@
+<div class="row">
+{{#if isEditing}}
+  {{ bo-doc-viaf-autocomplete
+      inputclass="form-control"
+      placeholder=(t 'bo.contributors_th_name')
+      viafId=viafId
+      class='nameurl-col-autocomplete'
+      registerAs=autocompleteComponent
+      initialViafId=(readonly initialViafId)}}
+  {{#if urlPresent }}
+    <a target="_blank" href="{{url}}" class="bo-client-viaf-32x32-icon bo-client-force-block nameurl-col-icon" title="{{url}}">&nbsp;</a>
+  {{ else }}
+    <div class="nameurl-col-icon bo-client-blank-32x32-icon">&nbsp;</div>
+  {{/if}}
+{{ else }}
+  <div class="nameurl-col-name nameurl-prop">{{name}}</div>
+  <div class="nameurl-col-url nameurl-prop">{{#if url}}<a href="{{url}}" class='bo-doc-ref-link' target='_blank'>{{url}}</a>{{/if}}</div>
+{{/if}}
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-role-cell/component.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+import Ember from 'ember';
+import { documentContributorRoleTranslationTag } from 'bo-client/helpers/document-contributor-role-translation-tag';
+
+export default Ember.Component.extend({
+  i18n: Ember.inject.service(),
+  tagName: "td",
+  isEditing: false,
+  valueChanged: Ember.K,
+
+  translatedRole: Ember.computed('role', function() {
+    var role = this.get('role');
+    return role?this.get('i18n').t(documentContributorRoleTranslationTag([role,])):'';
+  }),
+
+  _roleChanged: Ember.observer('role', function() {
+    this.get('valueChanged')();
+  }),
+
+  _selectComponentChanged: Ember.observer('selectComponent', function() {
+    if(this.get('isEditing') && this.get('selectComponent')) {
+      this.get('selectComponent').$().focus();
+    }
+  }),
+
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-role-cell/template.hbs	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,5 @@
+{{#if isEditing}}
+  {{bo-doc-contributor-role-select class="form-control" role=role registerAs=selectComponent }}
+{{else}}
+  {{translatedRole}}
+{{/if}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-role-select/component.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  tagName : 'select',
+  change(event) {
+    this.set('role', event.target.value);
+  },
+  _registerAfterRender: function() {
+    Ember.run.schedule('afterRender', this, function () {
+      this.set('registerAs', this);
+    });
+  }.on('init'),
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-role-select/template.hbs	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,4 @@
+<option value="" selected={{eq role ""}}>----------</option>
+{{#each-in constants.OLAC_ROLES as |role_value role_disp|}}
+  <option value="{{role_value}}" selected={{eq role role_value}}>{{t role_disp}}</option>
+{{/each-in}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-row/component.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+import Ember from 'ember';
+import CellEditingMixin from 'bo-client/mixins/cell-editing-mixin';
+
+export default Ember.Component.extend(CellEditingMixin, {
+  tagName: "tr",
+  actions: {
+    removeContributor: function(contributor) {
+      console.log("REMOVE CONTRIBUTOR", contributor);
+      this.get('removeContributor')(contributor);
+    },
+    saveContributor: function(contributor, index) {
+      this.get('saveContributor')(contributor, index);
+      this.set('isEditing', false);
+    },
+    valueChanged: function() {
+      this.$(".bo-doc-edit-icons-save").addClass("bo-doc-edit-icons-save-dirty bo-doc-edit-icons");
+    }
+  },
+  click: undefined,
+  _setupClickListener: Ember.on('didInsertElement', function() {
+    this._super(...arguments);
+    if(!this.get('isEditing')) {
+      this.$('.bo-doc-contrib-edit').click(Ember.run.bind(this,() => {
+        var _this = this;
+        setTimeout(() => {
+          _this.set('isEditing', true);
+        }, 200);
+      }));
+    }
+  }),
+
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-row/styles.scss	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,3 @@
+.bo-doc-edit-icons-save-dirty {
+	color: red;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributor-row/template.hbs	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+<td class="col-md-1 bo-doc-contrib-edit">{{add-one index}}</td>
+{{ bo-doc-contributor-nameurl-cell name=contrib.name url=contrib.url isEditing=isEditing class="bo-doc-contrib-edit" valueChanged=(action 'valueChanged')}}
+{{ bo-doc-contributor-role-cell role=contrib.role  class="col-md-2" isEditing=isEditing class="bo-doc-contrib-edit" valueChanged=(action 'valueChanged')}}
+<td class='bo-doc-actions-col col-md-1'>
+  {{#if isEditing }}
+    {{fa-icon "floppy-o" class="bo-doc-edit-icons-save" click=(action "saveContributor" contrib index)}}
+  {{ else }}
+    {{fa-icon "trash-o" class="bo-doc-edit-icons" click=(action "removeContributor" contrib)}}
+  {{/if}}
+</td>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributors/component.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,51 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+
+  isEditing: false,
+  viafResolver: Ember.inject.service(),
+  document: null,
+  i18n: Ember.inject.service(),
+
+  _resolveViafIds: Ember.on('init', Ember.observer('document.contributors.[]', function() {
+    this.get('document.contributors').forEach(function(contrib/*, index, coll*/) {
+      if(contrib.url &&  !contrib.name) {
+        this.get('viafResolver').getName(contrib.url).then( function(str) {
+          Ember.set(contrib, 'name', str);
+        }.bind(this), function(message) {
+          console.error("viaf resolver error : ", message);
+        });
+      }
+    }, this);
+  })),
+
+  actions: {
+    toggleEditContributors: function() {
+      // var contributors = _.clone(this.get('document').get('contributors'));
+      // console.log("EDIT CONTRIBUTPRS", contributors);
+      // contributors.push({
+      //   name: "Hello world",
+      //   url: null,
+      //   role: 'http://www.language-archives.org/OLAC/1.1/annotator'
+      // });
+      // this.get('document').set('contributors', contributors);
+      this.set('isEditing', !this.get('isEditing'));
+      this.$('#doc-contributors-table-pane').slideToggle();
+      this.$('#doc-contributors-list-pane').slideToggle();
+    },
+    addNewContributor: function(contrib_def) {
+      if(contrib_def.name || contrib_def.url || contrib_def.role) {
+        this.get('document').addContributor(contrib_def);
+      }
+    },
+    removeContributor: function(contrib_def) {
+      this.get("document").removeContributor(contrib_def);
+    },
+    saveContributor: function(contrib_def, index) {
+      if(contrib_def.name || contrib_def.url || contrib_def.role) {
+        this.get('document').saveContributor(contrib_def, index);
+      }
+    }
+  },
+
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-contributors/template.hbs	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,37 @@
+<div class="col-md-1">
+    {{ fa-icon "pencil" class='bo-doc-edit-icons' click=(action "toggleEditContributors")}}
+    <!--span class="glyphicon glyphicon-pencil bo-doc-edit-icons"></span-->
+</div>
+<div class="col-md-11">
+  <div class="row">
+    <div class="col-md-12 content-title">{{t 'bo.document_contributors'}}</div>
+  </div>
+  <div class="row" id="doc-contributors-list-pane">
+    <div class="col-md-12 content-value">{{#each document.contributors as |contrib index|}}{{bo-doc-contributor-list-item contrib=contrib index=index}}{{/each}}</div>
+  </div>
+  <div class="row" id="doc-contributors-table-pane">
+    <div class="col-md-12 panel panel-default">
+      {{#if isEditing}}
+      <table class="table table-striped table-condensed">
+        <thead>
+          <tr>
+            <th class="col-md-1">#</th>
+            <th class="col-md-5">{{t 'bo.contributors_th_name'}}</th>
+            <th class="col-md-3">{{t 'bo.contributors_th_url'}}</th>
+            <th class="col-md-2">{{t 'bo.contributors_th_role'}}</th>
+            <th class="col-md-1">{{t 'bo.contributors_th_actions'}}</th>
+          </tr>
+        </thead>
+        <tbody>
+        {{#each document.contributors as |contrib index|}}
+          {{bo-doc-contributor-row removeContributor=(action 'removeContributor') saveContributor=(action 'saveContributor') contrib=contrib index=index}}
+        {{/each}}
+        </tbody>
+        <tfoot>
+          {{bo-doc-new-contributor onAdd=(action 'addNewContributor')}}
+        </tfoot>
+      </table>
+      {{/if}}
+    </div>
+  </div>
+</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-language/component.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+    tagName: "span",
+
+    lexvoResolver: Ember.inject.service(),
+
+    _resolveLexvoIds: Ember.on('init', Ember.observer('language', function() {
+      this.get('lexvoResolver').getName(this.get('language')).then(function(str) {
+          this.set('resolvedName', str);
+      }.bind(this));
+    })),
+
+    code: Ember.computed('language', function() {
+      var rawLanguage = this.get('language');
+      if(rawLanguage && rawLanguage.startsWith(this.get('constants').LEXVO_BASE_URL) ) {
+        return rawLanguage.substr(this.get('constants').LEXVO_BASE_URL.length);
+      }
+      return rawLanguage;
+    }),
+    isLanguageLink: Ember.computed.match('language', /^http\:\/\//)
+
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-language/template.hbs	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,7 @@
+{{#if isLanguageLink}}
+<a href="{{language}}" target="_blank" title={{resolvedName}} class="bo-doc-ref-link">
+  {{#if resolvedName}}{{resolvedName}}{{else}}{{code}}{{/if}}
+</a>
+{{else}}
+{{#if resolvedName}}{{resolvedName}}{{else}}{{code}}{{/if}}
+{{/if}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-new-contributor/component.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,47 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  tagName: "tr",
+  viafId: null,
+  initialViafId: null,
+  actions: {
+    addNewContributor: function() {
+      if(!this.get('valuesNotSet')) {
+        this.get('onAdd')(this.getProperties('name','url','role'));
+        this.clearProperties();
+      }
+    }
+  },
+  clearProperties: function() {
+    var contribDef = {
+      viafId: null,
+      role:'',
+    };
+    this.setProperties(contribDef);
+    //clear typeahead
+    this.$('.aupac-typeahead').typeahead('val','');
+  },
+
+  _clearAfterRender: function() {
+    Ember.run.schedule('afterRender', this, function () {
+      this.clearProperties();
+    });
+  }.on('init'),
+
+  valuesNotSet: Ember.computed('name','url','role', function() {
+    return !(this.get('name') || this.get('url') || this.get('role'));
+  }),
+
+  name: Ember.computed('viafId', function() {
+    var viafId = this.get('viafId');
+    return (viafId == null)?"":viafId.value;
+  }),
+
+  url: Ember.computed('viafId', function() {
+    var viafId = this.get('viafId');
+    return (viafId == null)?"":viafId.url;
+  }),
+
+  urlPresent: Ember.computed.bool('url'),
+
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-new-contributor/template.hbs	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+<td class="col-md-1">&nbsp;</td>
+<td class="col-md-8" colspan="2">
+  <div class='row'>
+    {{bo-doc-viaf-autocomplete inputclass="form-control" placeholder=(t 'bo.contributors_th_name') viafId=viafId initialViafId=initialViafId class='col-md-11'}}
+    {{#if urlPresent }}
+    <a target="_blank" href="{{url}}" class="col-md-1 bo-client-viaf-32x32-icon bo-client-force-block" title="{{url}}">&nbsp;</a>
+    {{ else }}
+    <div class="col-md-1 bo-client-blank-32x32-icon">&nbsp;</div>
+    {{/if}}
+  </div>
+</td>
+<td class="col-md-2">{{bo-doc-contributor-role-select class="form-control" role=role}}</td>
+<td class='bo-doc-actions-col col-md-1'>{{fa-icon "plus" class=(if valuesNotSet "bo-doc-no-edit-icons" "bo-doc-edit-icons") click=(action "addNewContributor")}}</td>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-viaf-autocomplete/component.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,100 @@
+import config from 'bo-client/config/environment';
+import Ember from 'ember';
+import URI from 'urijs';
+import suggestionTemplate from 'bo-client/templates/components/bo-doc-viaf-autocomplete/suggestion';
+import _ from 'lodash/lodash';
+
+
+// inspired by https://github.com/oclc-developer-house/jquery-viaf-autocomplete/blob/master/src/jquery.viafauto.js
+/*jshint unused:false*/
+export default Ember.Component.extend({
+
+  actions: {
+    setViafId: function(value) {
+      console.log('setViafId',value);
+      if(_.isString(value)) {
+        this.set('viafId', {
+          label: value,
+          value: value,
+          id: "",
+          url: "",
+          nametype: "" }
+        );
+      }
+      else {
+        this.set('viafId', value);
+      }
+    },
+  },
+
+  limit: 15,
+
+  display(selection) {
+    console.log('DISPLAY',selection);
+    return selection.value;
+  },
+
+  setValue(selection) {
+    console.log('setValue',selection);
+    let typeahead = Ember.$(this.$(), ".aupac-typeahead");
+    if(selection) {
+      if(_.isString(selection)) {
+        typeahead.typeahead('val', selection);
+      } else {
+        typeahead.typeahead('val', selection.value);
+      }
+
+    } else {
+      typeahead.typeahead('val', '');
+    }
+  },
+
+  keyDown(event) {
+    if(event.which === this.get('constants').KEY_CODES.RETURN) {
+      Ember.$(this.$(), ".aupac-typeahead").typeahead('close');
+    }
+  },
+
+  suggestionTemplate: suggestionTemplate,
+
+  _registerAfterRender: function() {
+    Ember.run.schedule('afterRender', this, function () {
+      this.set('registerAs', this);
+    });
+  }.on('init'),
+
+
+  viafSource : function(query, syncResults, asyncResults) {
+    var url = URI(config.APP['bo-doc-viaf-autocomplete'].viafQueryUrl).query({query: query}).toString();
+    Ember.$.ajax({
+      url: url,
+      dataType: "jsonp",
+      success: function(data) {
+        var queryTextRes = {
+          label: query,
+          value: query,
+          id: "",
+          url: "",
+          nametype: ""
+        };
+        if (data.result) {
+          var results = Ember.$.map( data.result, function(item) {
+            var retLbl = item.term + " [" + item.nametype + "]",
+                viafurl = config.APP['bo-doc-viaf-autocomplete'].viafBaseUrl + item.viafid;
+            return {
+              label: retLbl,
+              value: item.term,
+              id: item.viafid,
+              url: viafurl,
+              nametype: item.nametype
+            };
+          });
+          results.unshift(queryTextRes);
+          asyncResults( results );
+        } else {
+          asyncResults([queryTextRes]);
+        }
+      },
+    });
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-viaf-autocomplete/template.hbs	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,13 @@
+{{aupac-typeahead action=(action 'setViafId')
+    class=(if inputclass inputclass)
+    source=viafSource
+    placeholder=(if placeholder placeholder)
+    display=display
+    async=true
+    hint=false
+    suggestionTemplate=suggestionTemplate
+    selection=(readonly initialViafId)
+    allowFreeInput=false
+    limit=15
+    setValue=setValue
+}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/pods/components/bo-doc-viaf-autocomplete/template.hbs.old	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,11 @@
+{{aupac-typeahead action=(action 'setViafId')
+    class=(if inputclass inputclass)
+    source=viafSource
+    placeholder=(if placeholder placeholder)
+    display='value'
+    async=true
+    hint=false
+    suggestionTemplate=suggestionTemplate
+    selection=(readonly viafId.value)
+    allowFreeInput=true
+}}
--- a/server/bo_client/app/routes/doc.js	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/app/routes/doc.js	Fri Jan 15 15:35:00 2016 +0100
@@ -1,7 +1,23 @@
 import Ember from 'ember';
 
 export default Ember.Route.extend({
+  options: Ember.inject.service(),
   model(params) {
     return this.store.findRecord('document', params.doc_id);
   },
+  actions: {
+    saveDocument: function(doc) {
+      doc.save();
+      if(this.get('options').backurl) {
+        window.location.replace(this.get('options').backurl);
+      }
+      else {
+        this.transitionTo('index');
+      }
+    },
+    cancelDocument: function(doc) {
+      doc.rollbackAttributes();
+      doc.reload();
+    }
+  }
 });
--- a/server/bo_client/app/routes/index.js	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/app/routes/index.js	Fri Jan 15 15:35:00 2016 +0100
@@ -1,6 +1,13 @@
 import Ember from 'ember';
 
 export default Ember.Route.extend({
+  options: Ember.inject.service(),
+  beforeModel: function(/*transition*/) {
+    var options = this.get('options');
+    if(options.docid) {
+      return this.transitionTo('doc', {doc_id: options.docid});
+    }
+  },
   model: function() {
     return this.store.findAll('document');
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/services/constants.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,42 @@
+import Ember from 'ember';
+
+const OLAC_ROLES = {
+  'http://www.language-archives.org/OLAC/1.1/annotator': 'bo.olac_role_annotator',
+  'http://www.language-archives.org/OLAC/1.1/author': 'bo.olac_role_author',
+  'http://www.language-archives.org/OLAC/1.1/compiler': 'bo.olac_role_compiler',
+  'http://www.language-archives.org/OLAC/1.1/consultant': 'bo.olac_role_consultant',
+  'http://www.language-archives.org/OLAC/1.1/data_inputter': 'bo.olac_role_data_inputter',
+  'http://www.language-archives.org/OLAC/1.1/depositor': 'bo.olac_role_depositor',
+  'http://www.language-archives.org/OLAC/1.1/developer': 'bo.olac_role_developer',
+  'http://www.language-archives.org/OLAC/1.1/editor': 'bo.olac_role_editor',
+  'http://www.language-archives.org/OLAC/1.1/illustrator': 'bo.olac_role_illustrator',
+  'http://www.language-archives.org/OLAC/1.1/interpreter': 'bo.olac_role_interpreter',
+  'http://www.language-archives.org/OLAC/1.1/interviewer': 'bo.olac_role_interviewer',
+  'http://www.language-archives.org/OLAC/1.1/participant': 'bo.olac_role_participant',
+  'http://www.language-archives.org/OLAC/1.1/performer': 'bo.olac_role_performer',
+  'http://www.language-archives.org/OLAC/1.1/photographer': 'bo.olac_role_photographer',
+  'http://www.language-archives.org/OLAC/1.1/recorder': 'bo.olac_role_recorder',
+  'http://www.language-archives.org/OLAC/1.1/researcher': 'bo.olac_role_researcher',
+  'http://www.language-archives.org/OLAC/1.1/research_participant': 'bo.olac_role_research_participant',
+  'http://www.language-archives.org/OLAC/1.1/responder': 'bo.olac_role_responder',
+  'http://www.language-archives.org/OLAC/1.1/signer': 'bo.olac_role_signer',
+  'http://www.language-archives.org/OLAC/1.1/singer': 'bo.olac_role_singer',
+  'http://www.language-archives.org/OLAC/1.1/speaker': 'bo.olac_role_speaker',
+  'http://www.language-archives.org/OLAC/1.1/sponsor': 'bo.olac_role_sponsor',
+  'http://www.language-archives.org/OLAC/1.1/transcriber': 'bo.olac_role_transcriber',
+  'http://www.language-archives.org/OLAC/1.1/translator': 'bo.olac_role_translator',
+};
+
+const KEY_CODES = {
+  BACKSPACE : 8,
+  DELETE : 46,
+  ESCAPE: 27,
+  RETURN: 13,
+};
+
+export default Ember.Service.extend({
+  OLAC_ROLES: OLAC_ROLES,
+  KEY_CODES: KEY_CODES,
+  VIAF_BASE_URL: "http://viaf.org/viaf/",
+  LEXVO_BASE_URL: "http://lexvo.org/id/iso639-3/",
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/services/lexvo-resolver.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,51 @@
+import Ember from 'ember';
+import store from 'store';
+
+import ENV from 'bo-client/config/environment';
+
+export default Ember.Service.extend({
+  constants: Ember.inject.service(),
+  _getStoreKey: function(id) {
+    return 'lexvo:'+id;
+  },
+  getName: function(id) {
+    var lexvoId = id;
+    if(id.startsWith(this.get('constants').LEXVO_BASE_URL)) {
+      lexvoId = id.slice(this.get('constants').LEXVO_BASE_URL.length);
+    }
+    var storeKey = this._getStoreKey(id);
+    var namePromise = null;
+
+    var name = store.get(storeKey);
+    if(!name) {
+      //TODO: handle error !!!
+      namePromise = this.queryName(lexvoId)
+        .then( function(response) {
+            return store.set(storeKey, response);
+        });
+    }
+    else {
+      namePromise = new Ember.RSVP.Promise(function(resolve/*, reject*/) {
+        resolve(name);
+      });
+    }
+    return namePromise;
+  },
+  // make the query for the name.
+  // return a Promise
+  queryName: function(id) {
+    return new Ember.RSVP.Promise(function(resolve, reject) {
+      Ember.$.ajax({
+        //TODO Configuration ?
+        url: ENV.baseURL.replace(/\/$/,"") + "/api/v1/lexvo/"+id,
+        success: function(lexvoDoc) {
+          var names = lexvoDoc.lexvoids;
+          resolve((id in names)?names[id]:null);
+        },
+        error: function(req, status, error) {
+          reject(status + ":" + error);
+        }
+      });
+    }.bind(this));
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/services/viaf-resolver.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,51 @@
+import Ember from 'ember';
+import store from 'store';
+import ENV from 'bo-client/config/environment';
+
+// TODO: implement store layer with auto-expiration : c.f. https://github.com/marcuswestin/store.js/#no-sessionstorageauto-expiration
+export default Ember.Service.extend({
+  constants: Ember.inject.service(),
+  _getStoreKey: function(id) {
+    return 'viaf:'+id;
+  },
+  getName: function(id) {
+    var viafId = id;
+    if(id.startsWith(this.get('constants').VIAF_BASE_URL)) {
+      viafId = id.slice(this.get('constants').VIAF_BASE_URL.length);
+    }
+    var storeKey = this._getStoreKey(id);
+    var namePromise = null;
+
+    var name = store.get(storeKey);
+    if(!name) {
+      //TODO: handle error !!!
+      namePromise = this.queryName(viafId)
+        .then( function(response) {
+            return store.set(storeKey, response);
+        });
+    }
+    else {
+      namePromise = new Ember.RSVP.Promise(function(resolve/*, reject*/) {
+        resolve(name);
+      });
+    }
+    return namePromise;
+  },
+  // make the query for the name.
+  // return a Promise
+  queryName: function(id) {
+    return new Ember.RSVP.Promise(function(resolve, reject) {
+      Ember.$.ajax({
+        //TODO Configuration ?
+        url:  ENV.baseURL.replace(/\/$/,"") + "/api/v1/viaf/"+id,
+        success: function(viafDoc) {
+          var names = viafDoc.viafids;
+          resolve((id in names)?names[id]:null);
+        },
+        error: function(req, status, error) {
+          reject(status + ":" + error);
+        }
+      });
+    }.bind(this));
+  }
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/styles/_icons.scss	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+
+.bo-client-force-block {
+  display: block;
+}
+
+%bo-client-icon {
+  & {
+    text-decoration: none !important;
+    background-repeat: no-repeat;
+  }
+  &:hover { text-decoration: none !important; }
+}
+
+.bo-client-blank-32x32-icon {
+  @extend %bo-client-icon;
+  width: 32px;
+  height: 32px;
+  background-size: 32px 32px;
+}
+
+.bo-client-viaf-32x32-icon {
+  @extend %bo-client-icon;
+  width: 32px;
+  height: 32px;
+  background-image: url('img/viaf-logo-32x32.gif');
+  background-size: 32px 32px;
+}
--- a/server/bo_client/app/styles/app.scss	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/app/styles/app.scss	Fri Jan 15 15:35:00 2016 +0100
@@ -1,17 +1,23 @@
+$btn-font-weight: 300;
+$font-family-sans-serif: "Roboto", Helvetica, Arial, sans-serif;
+
+
 @import 'bower_components/bootstrap-sass/assets/stylesheets/_bootstrap';
 @import 'bower_components/font-awesome/scss/font-awesome';
 
-$btn-font-weight: 300;
-$font-family-sans-serif: "Roboto", Helvetica, Arial, sans-serif;
+@import 'icons';
+
+@import "pod-styles";
 
 body, label, .checkbox label {
 	font-weight: 300;
 }
 
-.doc_details_title {
+.doc-details-title {
 	@extend .h3;
 	margin-top: 0;
 }
+
 .content-main-title {
 	@extend .h4;
 }
@@ -28,7 +34,35 @@
   cursor: pointer;
 }
 
+.bo-doc-no-edit-icons {
+	cursor: not-allowed;
+}
+
 #doc-contributors-table-pane {
 	display: none;
 	margin-top: 20px;
 }
+
+.bo-doc-actions-col {
+	@extend .text-center;
+}
+
+.bo-doc-ref-link, .bo-doc-ref-link:hover, .bo-doc-ref-link:active, .bo-doc-ref-link:visited {
+	color: $text-color;
+}
+
+.bo-doc-ref-link:after {
+	@extend .#{$fa-css-prefix}-external-link:before;
+	font-family: FontAwesome;
+	font-size: 0.5em;
+	padding-left: 3px;
+	vertical-align: top;
+	display: inline-block;
+}
+.bo-doc-ref-link:hover:after, .bo-doc-ref-link:active:after, .bo-doc-ref-link:visited:after {
+		text-decoration: none;
+}
+
+.doc-buttons {
+	margin-top: 1em;
+}
--- a/server/bo_client/app/templates/components/bo-doc-contributors.hbs	Fri Jan 15 15:27:56 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-<div class="col-md-1">
-    {{ fa-icon "pencil" class='bo-doc-edit-icons' click=(action "toggleEditContributors")}}
-    <!--span class="glyphicon glyphicon-pencil bo-doc-edit-icons"></span-->
-</div>
-<div class="col-md-11">
-  <div class="row">
-    <div class="col-md-12 content-title">{{t 'bo.document_contributors'}}</div>
-  </div>
-  <div class="row" id="doc-contributors-list-pane">
-    <div class="col-md-12 content-value">{{#each document.contributors as |contrib index|}}{{if index " ; "}}{{#if contrib.name}}{{contrib.name}}{{else}}{{contrib.url}}{{/if}} ({{t (document-contributor-role-translation-tag contrib.role)}}){{/each}}</div>
-  </div>
-  <div class="row" id="doc-contributors-table-pane">
-    <div class="col-md-12 panel panel-default">
-      <table class="table table-striped table-condensed">
-        <thead>
-          <tr>
-            <th>#</th>
-            <th>{{t 'bo.contributors_th_name'}}</th>
-            <th>{{t 'bo.contributors_th_url'}}</th>
-            <th>{{t 'bo.contributors_th_role'}}</th>
-          </tr>
-        </thead>
-        <tbody>
-        {{#each document.contributors as |contrib index|}}
-          <tr>
-            <td>{{add-one index}}</td>
-            <td>{{contrib.name}}</td>
-            <td>{{contrib.url}}</td>
-            <td>{{contrib.role}}</td>
-          </tr>
-        {{/each}}
-      </tbody>
-      </table>
-    </div>
-  </div>
-</div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/app/templates/components/bo-doc-viaf-autocomplete/suggestion.hbs	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,1 @@
+<div class='typeahead-suggestion'>{{#if model}}{{model.label}} - {{model.url}}{{/if}}</div>
--- a/server/bo_client/app/templates/doc.hbs	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/app/templates/doc.hbs	Fri Jan 15 15:35:00 2016 +0100
@@ -1,7 +1,7 @@
 <div class="row">
   <div class="col-md-12">
     <div class="panel panel-default">
-      <div class="panel-heading doc_details_title">{{t 'bo.document_detail'}}</div>
+      <div class="panel-heading doc-details-title">{{t 'bo.document_detail'}}</div>
 
       <div class="panel-body">
         <div class="doc_details row">
@@ -17,6 +17,15 @@
                 </div>
               </div>
               <div class="row">
+                <div class="col-md-1">
+                  &nbsp;
+                </div>
+                <div class="col-md-11">
+                  <div class="content-title">{{t 'bo.document_language'}}</div>
+                  <div class="content-value">{{bo-doc-language language=model.language}}</div>
+                </div>
+              </div>
+              <div class="row">
                 {{bo-doc-contributors document=model}}
               </div>
               <div class="row">
@@ -45,6 +54,12 @@
           <div class="content">
           </div>
         </div>
+        <div class="doc-buttons row">
+          <div class="col-md-12">
+            <button type="button" class="btn btn-primary" {{action 'saveDocument' model }} disabled={{not model.currentState.isDirty}}>{{t 'bo.button_save'}}</button>
+            <button type="button" class="btn btn-primary" {{action 'cancelDocument' model }} disabled={{not model.currentState.isDirty}}>{{t 'bo.button_cancel'}}</button>
+          </div>
+        </div>
       </div>
     </div>
   </div>
--- a/server/bo_client/bower.json	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/bower.json	Fri Jan 15 15:35:00 2016 +0100
@@ -13,7 +13,10 @@
     "loader.js": "ember-cli/loader.js#3.5.0",
     "qunit": "~1.18.0",
     "bootstrap-sass": "bootstrap-sass-official#~3.3.6",
-    "font-awesome": "~4.4.0"
+    "font-awesome": "~4.4.0",
+    "typeahead.js": "~0.11.1",
+    "urijs": "URIjs#~1.17.0",
+    "store": "https://github.com/marcuswestin/store.js.git#master"
   },
   "resolutions": {
     "ember-cli-shims": "0.0.6",
--- a/server/bo_client/config/environment.js	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/config/environment.js	Fri Jan 15 15:35:00 2016 +0100
@@ -3,10 +3,14 @@
 module.exports = function(environment) {
   var ENV = {
     modulePrefix: 'bo-client',
+    podModulePrefix: 'bo-client/pods',
     environment: environment,
     baseURL: '/',
     //locationType: 'auto',
     locationType: 'auto',
+    i18n : {
+      defaultLocale: 'fr'
+    },
     EmberENV: {
       FEATURES: {
         // Here you can enable experimental features on an ember canary build
@@ -17,7 +21,11 @@
     APP: {
       // Here you can pass flags/options to your application instance
       // when it is created
-    }
+      'bo-doc-viaf-autocomplete' : {
+          viafQueryUrl: "http://viaf.org/viaf/AutoSuggest?query=",
+          viafBaseUrl: "http://viaf.org/viaf/",
+      }
+    },
   };
 
   if (environment === 'development') {
@@ -26,6 +34,15 @@
     ENV.APP.LOG_TRANSITIONS = true;
     ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
     ENV.APP.LOG_VIEW_LOOKUPS = true;
+    ENV.contentSecurityPolicy = {
+      'default-src': "'none'",
+      'script-src': "'self'",
+      'font-src': "'self'",
+      'connect-src': "'self' *",
+      'img-src': "'self'",
+      'style-src': "'self' *",
+      'media-src': "'self'"
+    };
   }
 
   if (environment === 'test') {
--- a/server/bo_client/ember-cli-build.js	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/ember-cli-build.js	Fri Jan 15 15:35:00 2016 +0100
@@ -15,7 +15,7 @@
     fingerprint: {
       enabled: false
     },
-    storeConfigInMeta: false,
+    //storeConfigInMeta: false,
     // Add options here
     emberCliFontAwesome: {
       useScss: true
@@ -34,6 +34,24 @@
     destDir: '/fonts'
   });
 
+  app.import({
+      development: 'bower_components/urijs/src/URI.js',
+      production:  'bower_components/urijs/src/URI.min.js'
+  });
+  app.import('vendor/shims/urijs.js', {
+    exports: {
+      'urijs': [ 'default' ]
+    }
+  });
+  app.import({
+      development: 'bower_components/store/store.js',
+      production:  'bower_components/store/store.min.js'
+  });
+  app.import('vendor/shims/store.js', {
+    exports: {
+      'store': ['default']
+    }
+  });
 
   // app.import('../src/vendor/bower_components/bootstrap-sass/assets/fonts/bootstrap/glyphicons-halflings-regular.woff', {
   //   destDir: 'fonts'
--- a/server/bo_client/package.json	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/package.json	Fri Jan 15 15:35:00 2016 +0100
@@ -23,6 +23,7 @@
     "broccoli-asset-rev": "^2.3.0",
     "broccoli-funnel": "^1.0.1",
     "broccoli-merge-trees": "^1.0.0",
+    "ember-aupac-typeahead": "2.0.4",
     "ember-cli": "1.13.13",
     "ember-cli-app-version": "1.0.0",
     "ember-cli-babel": "^5.1.6",
@@ -38,13 +39,16 @@
     "ember-cli-sass": "5.2.0",
     "ember-cli-sri": "^1.2.1",
     "ember-cli-uglify": "^1.2.0",
+    "ember-component-css": "0.1.6",
     "ember-data": "2.2.1",
     "ember-disable-proxy-controllers": "^1.0.1",
     "ember-export-application-global": "^1.0.5",
     "ember-i18n": "4.2.0",
     "ember-lodash": "0.0.6",
+    "ember-truth-helpers": "1.2.0",
     "express": "^4.13.3",
     "glob": "^6.0.1",
+    "http-proxy": "^1.12.0",
     "morgan": "^1.6.1",
     "npm-check-updates": "^2.5.1",
     "walk-sync": "^0.2.6"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/public/assets/css/fonts.css	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,27 @@
+@font-face {
+  font-family: 'Roboto';
+  font-weight: 300;
+  font-style: normal;
+  src: url('../fonts/Roboto-300/Roboto-300.eot');
+  src: url('../fonts/Roboto-300/Roboto-300.eot?#iefix') format('embedded-opentype'),
+       local('Roboto Light'),
+       local('Roboto-300'),
+       url('../fonts/Roboto-300/Roboto-300.woff2') format('woff2'),
+       url('../fonts/Roboto-300/Roboto-300.woff') format('woff'),
+       url('../fonts/Roboto-300/Roboto-300.ttf') format('truetype'),
+       url('../fonts/Roboto-300/Roboto-300.svg#Roboto') format('svg');
+}
+
+@font-face {
+  font-family: 'Roboto';
+  font-weight: 400;
+  font-style: normal;
+  src: url('../fonts/Roboto-regular/Roboto-regular.eot');
+  src: url('../fonts/Roboto-regular/Roboto-regular.eot?#iefix') format('embedded-opentype'),
+       local('Roboto'),
+       local('Roboto-regular'),
+       url('../fonts/Roboto-regular/Roboto-regular.woff2') format('woff2'),
+       url('../fonts/Roboto-regular/Roboto-regular.woff') format('woff'),
+       url('../fonts/Roboto-regular/Roboto-regular.ttf') format('truetype'),
+       url('../fonts/Roboto-regular/Roboto-regular.svg#Roboto') format('svg');
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/public/assets/fonts/Roboto-300/LICENSE.txt	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
Binary file server/bo_client/public/assets/fonts/Roboto-300/Roboto-300.eot has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/public/assets/fonts/Roboto-300/Roboto-300.svg	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,314 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg">
+<defs >
+<font id="Roboto" horiz-adv-x="1137" ><font-face
+    font-family="Roboto Light"
+    units-per-em="2048"
+    panose-1="2 0 0 0 0 0 0 0 0 0"
+    ascent="1900"
+    descent="-500"
+    alphabetic="0" />
+<glyph unicode=" " horiz-adv-x="498" />
+<glyph unicode="!" horiz-adv-x="462" d="M284 405H173L167 1456H291L284 405ZM153 70Q153 104 175 127T235 151T295 128T318 70Q318 37 296 15T235 -8T175 14T153 70Z" />
+<glyph unicode="&quot;" horiz-adv-x="588" d="M243 1396L223 1083H143L146 1536H243V1396ZM479 1396L459 1083H378L382 1536H479V1396Z" />
+<glyph unicode="#" horiz-adv-x="1191" d="M753 410H439L362 0H263L340 410H85V503H357L440 944H161V1040H458L537 1456H636L557 1040H872L951 1456H1051L972 1040H1201V944H954L871 503H1126V410H853L776 0H676L753 410ZM456 503H771L854 944H539L456 503Z" />
+<glyph unicode="$" horiz-adv-x="1135" d="M901 359Q901 470 829 540T575 674Q349 745 258 842T167 1095Q167 1258 267 1359T539 1475V1677H641V1475Q817 1459 913 1343T1010 1028H891Q891 1185 810 1277T587 1370Q445 1370 366 1296T286 1097Q286 977 359 910T607
+783T862 669T981 540T1021 361Q1021 197 919 97T637 -18V-208H536V-19Q335 -6 225 107T115 418H235Q235 262 326 174T580 85Q722 85 811 161T901 359Z" />
+<glyph unicode="%" horiz-adv-x="1513" d="M109 1176Q109 1306 189 1391T394 1477T598 1392T679 1170V1099Q679 971 600 886T396 800Q273 800 191 884T109 1106V1176ZM206 1099Q206 1006 257 946T396 886Q481 886 531 946T582 1103V1176Q582 1269 530 1329T394
+1390Q311 1390 259 1330T206 1170V1099ZM842 357Q842 487 922 572T1126 657T1330 573T1412 350V279Q1412 149 1332 64T1128 -21T924 63T842 284V357ZM938 279Q938 185 989 125T1128 65Q1214 65 1264 125T1315 284V357Q1315 453 1264 511T1126 570Q1042 570 990
+511T938 353V279ZM434 121L359 169L1070 1307L1145 1259L434 121Z" />
+<glyph unicode="&amp;" horiz-adv-x="1260" d="M404 794Q317 899 278 981T238 1145Q238 1298 329 1387T573 1476Q712 1476 798 1396T884 1191Q884 1047 718 908L558 784L958 318Q1049 465 1049 651H1160Q1160 403 1032 232L1231 0H1087L961 146Q882 68 779 24T560
+-20Q352 -20 230 86T108 371Q108 477 170 571T390 784L404 794ZM560 81Q651 81 736 119T890 229L483 701L469 716L423 681Q227 521 227 371Q227 240 317 161T560 81ZM358 1149Q358 1027 493 861L624 961Q688 1007 729 1062T770 1191Q770 1269 716 1321T572 1374Q474
+1374 416 1311T358 1149Z" />
+<glyph unicode="&apos;" horiz-adv-x="348" d="M226 1395L209 1090H119Q124 1386 124 1536H226V1395Z" />
+<glyph unicode="(" horiz-adv-x="653" d="M140 588Q140 806 196 1011T360 1387T592 1632L621 1551Q555 1504 490 1414T374 1200T292 922T260 571Q260 362 307 169T438 -171T621 -393L592 -470Q465 -394 357 -225T195 148T140 588Z" />
+<glyph unicode=")" horiz-adv-x="667" d="M514 573Q514 353 460 150T298 -223T62 -470L33 -393Q131 -323 214 -176T346 166T394 591Q394 798 346 990T214 1334T33 1555L62 1632Q188 1555 295 1386T458 1011T514 573Z" />
+<glyph unicode="*" horiz-adv-x="869" d="M361 1000L29 1108L61 1209L393 1086L389 1456H493L485 1083L809 1210L842 1109L509 994L732 700L647 637L433 942L229 639L144 700L361 1000Z" />
+<glyph unicode="+" horiz-adv-x="1156" d="M630 740H1073V628H630V146H509V628H75V740H509V1206H630V740Z" />
+<glyph unicode="," horiz-adv-x="392" d="M131 -272L60 -220Q151 -98 154 33V188H271V63Q271 -145 131 -272Z" />
+<glyph unicode="-" horiz-adv-x="586" d="M528 592H49V693H528V592Z" />
+<glyph unicode="." horiz-adv-x="489" d="M145 72Q145 107 167 131T230 156T293 132T316 72T293 15T230 -8T168 14T145 72Z" />
+<glyph unicode="/" horiz-adv-x="813" d="M139 -125H30L638 1456H746L139 -125Z" />
+<glyph unicode="0" horiz-adv-x="1135" d="M1015 607Q1015 299 902 140T569 -20Q353 -20 238 136T120 592V853Q120 1160 234 1318T567 1476Q783 1476 897 1324T1015 874V607ZM895 868Q895 1118 814 1246T567 1374Q405 1374 323 1249T239 880V594Q239 345 323 213T569
+81Q729 81 811 210T895 588V868Z" />
+<glyph unicode="1" horiz-adv-x="1135" d="M694 0H574V1312L178 1165V1277L674 1461H694V0Z" />
+<glyph unicode="2" horiz-adv-x="1135" d="M1049 0H137V92L636 658Q760 801 808 894T856 1075Q856 1213 775 1293T552 1374Q405 1374 315 1280T224 1036H105Q105 1159 160 1260T318 1418T552 1476Q752 1476 864 1371T977 1085Q977 983 914 862T690 560L284 101H1049V0Z" />
+<glyph unicode="3" horiz-adv-x="1135" d="M403 793H527Q630 793 707 829T824 929T865 1076Q865 1216 786 1295T559 1374Q419 1374 330 1292T240 1074H120Q120 1187 177 1280T335 1425T559 1476Q757 1476 871 1368T985 1072Q985 967 919 879T736 746Q872 708 942
+616T1012 395Q1012 208 890 94T564 -20Q434 -20 326 32T158 177T98 395H218Q218 256 315 169T564 81Q719 81 805 160T892 391Q892 537 799 614T523 691H403V793Z" />
+<glyph unicode="4" horiz-adv-x="1135" d="M872 469H1099V368H872V0H752V368H67V436L741 1456H872V469ZM214 469H752V1301L699 1209L214 469Z" />
+<glyph unicode="5" horiz-adv-x="1135" d="M218 746L289 1456H1017V1345H392L341 853Q458 933 615 933Q812 933 929 805T1046 464Q1046 234 932 107T611 -20Q421 -20 303 86T168 383H283Q300 234 384 158T611 81Q767 81 846 180T926 462Q926 622 837 723T594 824Q509
+824 446 803T313 719L218 746Z" />
+<glyph unicode="6" horiz-adv-x="1135" d="M843 1467V1362H829Q568 1362 418 1209T252 782Q312 865 405 910T613 956Q805 956 918 824T1032 477Q1032 335 979 221T827 44T601 -20Q392 -20 261 131T130 523V643Q130 1034 308 1248T813 1467H843ZM594 853Q480 853
+382 786T250 614V512Q250 322 347 202T601 82Q741 82 827 193T914 473Q914 645 828 749T594 853Z" />
+<glyph unicode="7" horiz-adv-x="1135" d="M1034 1387L412 0H287L905 1354H77V1456H1034V1387Z" />
+<glyph unicode="8" horiz-adv-x="1135" d="M995 1081Q995 968 929 879T755 747Q881 704 957 608T1033 386Q1033 199 906 90T570 -20Q359 -20 233 89T106 386Q106 510 179 607T379 747Q271 789 207 878T143 1081Q143 1262 259 1369T568 1476T877 1368T995 1081ZM913
+385Q913 521 816 608T568 696T321 610T225 385T318 164T570 81Q725 81 819 163T913 385ZM875 1082Q875 1207 789 1290T568 1374Q432 1374 348 1294T263 1082Q263 954 347 876T569 798Q704 798 789 876T875 1082Z" />
+<glyph unicode="9" horiz-adv-x="1135" d="M884 674Q820 580 725 529T519 477Q395 477 300 541T153 718T101 965Q101 1109 156 1227T311 1410T541 1476Q760 1476 882 1323T1004 887V779Q1004 385 836 187T323 -11H301L302 93H344Q605 97 741 241T884 674ZM534
+580Q654 580 749 651T885 837V906Q885 1128 793 1250T543 1373Q401 1373 310 1259T219 970Q219 803 306 692T534 580Z" />
+<glyph unicode=":" horiz-adv-x="430" d="M383 72Q383 107 405 131T468 156T531 132T554 72T531 15T468 -8T406 14T383 72ZM129 995Q129 1030 151 1054T214 1079T277 1055T300 995T277 938T214 915T152 937T129 995Z" />
+<glyph unicode=";" horiz-adv-x="399" d="M118 995Q118 1030 140 1054T203 1079T266 1055T289 995T266 938T203 915T141 937T118 995ZM131 -272L60 -220Q151 -98 154 33V188H271V63Q271 -145 131 -272Z" />
+<glyph unicode="&lt;" horiz-adv-x="1047" d="M208 655L904 355V229L77 608V705L904 1083V957L208 655Z" />
+<glyph unicode="=" horiz-adv-x="1133" d="M983 829H149V935H983V829ZM983 418H149V524H983V418Z" />
+<glyph unicode="&gt;" horiz-adv-x="1061" d="M835 659L124 962V1085L969 707V610L124 231V355L835 659Z" />
+<glyph unicode="?" horiz-adv-x="930" d="M376 404Q378 522 408 594T537 763T664 901T708 990T724 1101Q724 1226 658 1297T472 1369Q352 1369 279 1301T203 1115H84Q86 1279 195 1377T472 1476Q644 1476 743 1376T843 1103Q843 995 794 901T608 680Q495 585 495
+404H376ZM360 70Q360 104 381 127T442 151Q480 151 502 128T525 70Q525 37 503 15T442 -8Q403 -8 382 14T360 70Z" />
+<glyph unicode="@" horiz-adv-x="1870" d="M1754 513Q1749 366 1700 241T1565 48T1364 -20Q1267 -20 1206 31T1125 174Q1017 -20 827 -20Q687 -20 618 101T567 427Q582 590 641 717T796 916T1001 988Q1078 988 1136 967T1271 880L1220 310Q1210 194 1249 130T1376
+66Q1499 66 1575 186T1661 513Q1680 918 1507 1122T983 1327Q772 1327 603 1222T335 923T225 478T291 35T528 -260T906 -363Q998 -363 1087 -341T1236 -284L1267 -364Q1210 -402 1108 -427T902 -453Q652 -453 472 -341T203 -17T125 478Q137 756 247 970T550 1302T987
+1420Q1242 1420 1419 1314T1681 1002T1754 513ZM673 286Q684 186 729 132T848 77Q1033 77 1121 332L1166 848Q1099 897 1008 897Q897 897 816 809T696 565T673 286Z" />
+<glyph unicode="A" horiz-adv-x="1279" d="M970 408H309L159 0H30L581 1456H698L1249 0H1121L970 408ZM347 513H931L639 1306L347 513Z" />
+<glyph unicode="B" horiz-adv-x="1255" d="M184 0V1456H614Q848 1456 969 1360T1090 1075Q1090 962 1029 879T860 759Q987 731 1064 634T1142 410Q1142 217 1018 109T671 0H184ZM307 700V104H676Q834 104 926 184T1019 408Q1019 543 931 621T686 700H307ZM307
+803H643Q797 806 881 875T966 1078Q966 1218 879 1284T614 1351H307V803Z" />
+<glyph unicode="C" horiz-adv-x="1330" d="M1215 454Q1190 224 1051 102T679 -20Q517 -20 393 61T200 290T131 630V819Q131 1013 199 1163T394 1394T688 1476Q922 1476 1057 1350T1215 1000H1091Q1045 1371 688 1371Q490 1371 373 1223T255 814V636Q255 384 369
+234T679 84Q872 84 970 176T1091 454H1215Z" />
+<glyph unicode="D" horiz-adv-x="1341" d="M184 0V1456H591Q770 1456 912 1375T1133 1141T1213 795V661Q1213 466 1134 315T912 82T582 0H184ZM307 1351V104H583Q813 104 952 256T1091 669V797Q1091 1048 954 1199T593 1351H307Z" />
+<glyph unicode="E" horiz-adv-x="1165" d="M988 698H307V104H1090V0H184V1456H1085V1351H307V802H988V698Z" />
+<glyph unicode="F" horiz-adv-x="1152" d="M986 680H307V0H184V1456H1086V1351H307V785H986V680Z" />
+<glyph unicode="G" horiz-adv-x="1400" d="M1235 173Q1171 82 1035 31T729 -20Q558 -20 425 62T219 294T145 638V822Q145 1125 298 1300T709 1476Q934 1476 1071 1362T1234 1046H1111Q1084 1206 981 1288T710 1371Q506 1371 387 1226T268 817V645Q268 479 324
+352T486 154T729 84Q888 84 1002 134Q1076 167 1112 211V587H721V691H1235V173Z" />
+<glyph unicode="H" horiz-adv-x="1449" d="M1263 0H1139V698H307V0H184V1456H307V802H1139V1456H1263V0Z" />
+<glyph unicode="I" horiz-adv-x="545" d="M334 0H211V1456H334V0Z" />
+<glyph unicode="J" horiz-adv-x="1127" d="M827 1456H951V433Q951 226 832 103T511 -20Q299 -20 185 91T71 401H194Q194 243 277 164T511 84Q650 84 737 176T827 426V1456Z" />
+<glyph unicode="K" horiz-adv-x="1292" d="M512 723L307 521V0H184V1456H307V671L1053 1456H1208L598 808L1255 0H1105L512 723Z" />
+<glyph unicode="L" horiz-adv-x="1079" d="M308 104H1027V0H184V1456H308V104Z" />
+<glyph unicode="M" horiz-adv-x="1772" d="M347 1456L884 171L1423 1456H1587V0H1464V634L1474 1284L932 0H837L297 1279L307 638V0H184V1456H347Z" />
+<glyph unicode="N" horiz-adv-x="1454" d="M1268 0H1145L308 1246V0H184V1456H308L1146 209V1456H1268V0Z" />
+<glyph unicode="O" horiz-adv-x="1386" d="M1260 649Q1260 448 1191 296T992 62T694 -20Q439 -20 282 162T125 655V805Q125 1004 195 1157T395 1393T692 1476T988 1395T1187 1166T1260 823V649ZM1137 807Q1137 1070 1018 1219T692 1368Q489 1368 369 1219T248
+801V649Q248 390 368 239T694 87Q903 87 1020 236T1137 653V807Z" />
+<glyph unicode="P" horiz-adv-x="1261" d="M307 593V0H184V1456H680Q907 1456 1038 1340T1170 1021Q1170 816 1044 705T677 593H307ZM307 697H680Q859 697 953 782T1047 1019Q1047 1170 954 1259T688 1351H307V697Z" />
+<glyph unicode="Q" horiz-adv-x="1386" d="M1256 649Q1256 441 1183 287T973 53L1238 -178L1153 -254L856 3Q774 -20 689 -20Q523 -20 394 62T193 294T121 642V805Q121 1004 191 1157T391 1393T687 1476Q857 1476 986 1394T1185 1159T1256 806V649ZM1133 807Q1133
+1070 1014 1219T687 1368Q485 1368 365 1219T244 801V649Q244 390 363 239T689 87Q897 87 1015 236T1133 652V807Z" />
+<glyph unicode="R" horiz-adv-x="1300" d="M728 606H305V0H181V1456H654Q887 1456 1018 1343T1149 1027Q1149 887 1067 780T847 632L1211 13V0H1080L728 606ZM305 711H682Q837 711 931 799T1025 1027Q1025 1181 927 1266T652 1351H305V711Z" />
+<glyph unicode="S" horiz-adv-x="1213" d="M1008 358Q1008 479 923 549T612 683T282 822Q134 928 134 1100Q134 1267 271 1371T623 1476Q768 1476 882 1420T1060 1264T1123 1041H999Q999 1190 897 1280T623 1371Q456 1371 357 1297T258 1102Q258 991 347 921T632
+798T929 687T1081 549T1132 360Q1132 188 995 84T632 -20Q478 -20 350 35T155 189T88 416H211Q211 262 326 173T632 84Q802 84 905 159T1008 358Z" />
+<glyph unicode="T" horiz-adv-x="1223" d="M1172 1351H673V0H550V1351H52V1456H1172V1351Z" />
+<glyph unicode="U" horiz-adv-x="1346" d="M1187 1456V462Q1186 315 1122 206T942 39T674 -20Q444 -20 306 105T162 453V1456H284V471Q284 287 389 186T674 84T958 186T1063 470V1456H1187Z" />
+<glyph unicode="V" horiz-adv-x="1263" d="M623 180L631 149L640 180L1098 1456H1233L691 0H573L31 1456H165L623 180Z" />
+<glyph unicode="W" horiz-adv-x="1836" d="M453 393L498 167L553 383L869 1456H980L1292 383L1346 165L1394 393L1657 1456H1783L1410 0H1292L962 1139L925 1283L889 1139L551 0H433L61 1456H187L453 393Z" />
+<glyph unicode="X" horiz-adv-x="1253" d="M627 840L1037 1456H1184L702 738L1199 0H1051L627 636L201 0H55L553 738L70 1456H217L627 840Z" />
+<glyph unicode="Y" horiz-adv-x="1226" d="M611 662L1056 1456H1198L672 548V0H549V548L24 1456H170L611 662Z" />
+<glyph unicode="Z" horiz-adv-x="1225" d="M239 104H1138V0H90V93L954 1351H116V1456H1106V1368L239 104Z" />
+<glyph unicode="[" horiz-adv-x="491" d="M493 1562H283V-210H493V-312H163V1664H493V1562Z" />
+<glyph unicode="\" horiz-adv-x="807" d="M48 1456H165L773 -125H656L48 1456Z" />
+<glyph unicode="]" horiz-adv-x="491" d="M0 1664H331V-312H0V-210H211V1562H0V1664Z" />
+<glyph unicode="^" horiz-adv-x="852" d="M421 1298L193 729H77L376 1456H466L764 729H648L421 1298Z" />
+<glyph unicode="_" horiz-adv-x="884" d="M882 -101H1V0H882V-101Z" />
+<glyph unicode="`" horiz-adv-x="585" d="M438 1245H329L103 1524H247L438 1245Z" />
+<glyph unicode="a" horiz-adv-x="1097" d="M839 0Q821 51 816 151Q753 69 656 25T449 -20Q293 -20 197 67T100 287Q100 445 231 537T598 629H815V752Q815 868 744 934T535 1001Q410 1001 328 937T246 783L126 784Q126 913 246 1007T541 1102Q722 1102 826 1012T934
+759V247Q934 90 967 12V0H839ZM463 86Q583 86 677 144T815 299V537H601Q422 535 321 472T220 297Q220 206 287 146T463 86Z" />
+<glyph unicode="b" horiz-adv-x="1135" d="M1027 530Q1027 277 915 129T614 -20Q388 -20 272 148L267 0H155V1536H274V925Q388 1102 612 1102Q804 1102 915 956T1027 548V530ZM907 551Q907 765 824 881T590 998Q475 998 395 942T274 776V288Q364 84 592 84Q740
+84 823 201T907 551Z" />
+<glyph unicode="c" horiz-adv-x="1055" d="M556 81Q681 81 765 151T857 334H972Q967 235 910 154T759 26T556 -20Q343 -20 219 128T94 526V562Q94 722 150 845T310 1035T555 1102Q733 1102 848 996T972 717H857Q849 844 766 922T555 1000Q393 1000 304 883T214
+555V520Q214 313 303 197T556 81Z" />
+<glyph unicode="d" horiz-adv-x="1138" d="M108 551Q108 803 220 952T526 1102Q745 1102 860 929V1536H979V0H867L862 144Q747 -20 524 -20Q337 -20 223 130T108 537V551ZM229 530Q229 323 312 204T546 84Q767 84 860 279V787Q767 998 548 998Q397 998 313 880T229 530Z" />
+<glyph unicode="e" horiz-adv-x="1058" d="M575 -20Q437 -20 326 48T152 237T90 510V553Q90 709 150 834T319 1030T553 1102Q750 1102 865 968T981 600V533H209V510Q209 326 314 204T580 81Q676 81 749 116T883 228L958 171Q826 -20 575 -20ZM553 1000Q418 1000
+326 901T213 635H862V648Q857 804 773 902T553 1000Z" />
+<glyph unicode="f" horiz-adv-x="678" d="M242 0V984H63V1082H242V1213Q242 1379 326 1468T562 1557Q630 1557 689 1540L680 1440Q630 1452 571 1452Q472 1452 417 1391T362 1216V1082H620V984H362V0H242Z" />
+<glyph unicode="g" horiz-adv-x="1136" d="M108 551Q108 805 220 953T526 1102Q747 1102 862 926L868 1082H980V22Q980 -187 863 -309T546 -431Q433 -431 331 -381T169 -246L236 -174Q363 -330 538 -330Q688 -330 772 -242T859 4V140Q744 -20 524 -20Q336 -20
+222 130T108 535V551ZM229 530Q229 323 312 204T546 84Q767 84 859 282V785Q817 889 738 943T548 998Q397 998 313 880T229 530Z" />
+<glyph unicode="h" horiz-adv-x="1124" d="M275 899Q334 996 426 1049T627 1102Q801 1102 886 1004T972 710V0H853V711Q852 856 792 927T598 998Q487 998 402 929T275 741V0H156V1536H275V899Z" />
+<glyph unicode="i" horiz-adv-x="459" d="M290 0H170V1082H290V0ZM149 1395Q149 1429 171 1452T231 1476T291 1453T314 1395T292 1338T231 1315T171 1338T149 1395Z" />
+<glyph unicode="j" horiz-adv-x="467" d="M285 1082V-129Q285 -279 213 -358T1 -437Q-53 -437 -104 -418L-102 -319Q-58 -332 -12 -332Q166 -332 166 -127V1082H285ZM226 1476Q265 1476 287 1453T309 1395T287 1338T226 1315Q188 1315 167 1338T145 1395T166 1452T226
+1476Z" />
+<glyph unicode="k" horiz-adv-x="1003" d="M413 545L276 413V0H156V1536H276V553L389 675L803 1082H954L495 626L994 0H851L413 545Z" />
+<glyph unicode="l" horiz-adv-x="459" d="M290 0H170V1536H290V0Z" />
+<glyph unicode="m" horiz-adv-x="1815" d="M265 1082L269 906Q329 1004 419 1053T619 1102Q875 1102 944 892Q1002 993 1099 1047T1313 1102Q1661 1102 1668 722V0H1548V713Q1547 858 1486 928T1285 998Q1156 996 1067 915T968 716V0H848V722Q847 861 783 929T584
+998Q471 998 390 934T270 742V0H150V1082H265Z" />
+<glyph unicode="n" horiz-adv-x="1125" d="M270 1082L274 897Q335 997 426 1049T627 1102Q801 1102 886 1004T972 710V0H853V711Q852 856 792 927T598 998Q487 998 402 929T275 741V0H156V1082H270Z" />
+<glyph unicode="o" horiz-adv-x="1147" d="M90 557Q90 713 150 838T321 1032T572 1102Q788 1102 922 951T1056 549V524Q1056 367 996 242T825 48T574 -20Q359 -20 225 131T90 533V557ZM210 524Q210 330 310 206T574 81Q736 81 836 205T937 534V557Q937 681 891
+784T762 943T572 1000Q412 1000 311 875T210 546V524Z" />
+<glyph unicode="p" horiz-adv-x="1135" d="M1026 530Q1026 277 914 129T614 -20Q392 -20 274 136V-416H155V1082H266L272 929Q389 1102 611 1102Q805 1102 915 955T1026 547V530ZM906 551Q906 758 821 878T584 998Q474 998 395 945T274 791V272Q317 179 397 130T586
+81Q737 81 821 201T906 551Z" />
+<glyph unicode="q" horiz-adv-x="1142" d="M108 551Q108 805 220 953T528 1102Q747 1102 861 935L867 1082H979V-416H859V134Q741 -20 526 -20Q336 -20 222 130T108 535V551ZM229 530Q229 320 313 201T548 81Q763 81 859 268V798Q814 895 735 947T550 1000Q399
+1000 314 881T229 530Z" />
+<glyph unicode="r" horiz-adv-x="689" d="M656 980Q618 987 575 987Q463 987 386 925T275 743V0H156V1082H273L275 910Q370 1102 580 1102Q630 1102 659 1089L656 980Z" />
+<glyph unicode="s" horiz-adv-x="1037" d="M804 275Q804 364 733 418T517 502T294 572T176 669T137 807Q137 935 244 1018T518 1102Q699 1102 808 1013T918 779H798Q798 874 719 937T518 1000Q400 1000 329 948T257 811Q257 730 316 686T533 604T769 525T886 424T924
+281Q924 144 814 62T525 -20Q336 -20 219 71T101 303H221Q228 198 309 140T525 81Q650 81 727 136T804 275Z" />
+<glyph unicode="t" horiz-adv-x="658" d="M342 1359V1082H566V984H342V263Q342 173 374 129T483 85Q513 85 580 95L585 -3Q538 -20 457 -20Q334 -20 278 51T222 262V984H23V1082H222V1359H342Z" />
+<glyph unicode="u" horiz-adv-x="1125" d="M852 137Q744 -20 507 -20Q334 -20 244 80T152 378V1082H271V393Q271 84 521 84Q781 84 850 299V1082H970V0H854L852 137Z" />
+<glyph unicode="v" horiz-adv-x="985" d="M493 165L822 1082H945L541 0H444L38 1082H161L493 165Z" />
+<glyph unicode="w" horiz-adv-x="1544" d="M415 249L433 156L457 254L717 1082H819L1076 261L1104 147L1127 252L1349 1082H1473L1158 0H1056L778 858L765 917L752 857L479 0H377L63 1082H186L415 249Z" />
+<glyph unicode="x" horiz-adv-x="996" d="M496 643L788 1082H930L563 551L946 0H805L497 458L189 0H48L430 551L63 1082H204L496 643Z" />
+<glyph unicode="y" horiz-adv-x="973" d="M499 172L815 1082H944L482 -184L458 -240Q369 -437 183 -437Q140 -437 91 -423L90 -324L152 -330Q240 -330 294 -287T387 -137L440 9L32 1082H163L499 172Z" />
+<glyph unicode="z" horiz-adv-x="996" d="M235 101H938V0H87V88L743 979H107V1082H894V993L235 101Z" />
+<glyph unicode="{" horiz-adv-x="676" d="M637 -404Q469 -354 384 -241T299 59V280Q299 543 68 543V647Q299 647 299 908V1137Q300 1320 384 1433T637 1597L663 1518Q419 1440 419 1127V914Q419 668 235 595Q419 518 419 277V49Q423 -243 666 -324L637 -404Z" />
+<glyph unicode="|" horiz-adv-x="452" d="M279 -270H178V1456H279V-270Z" />
+<glyph unicode="}" horiz-adv-x="676" d="M9 -324Q252 -243 256 49V273Q256 526 449 594Q256 662 256 913V1126Q256 1442 12 1518L38 1597Q209 1546 292 1432T376 1131V908Q376 647 607 647V543Q376 543 376 280V59Q376 -128 291 -241T38 -404L9 -324Z" />
+<glyph unicode="~" horiz-adv-x="1402" d="M1254 764Q1254 615 1171 519T958 423Q886 423 824 450T670 558T535 659T441 680Q352 680 303 621T253 450L145 449Q145 598 226 692T441 787Q515 787 581 756T740 643Q807 580 855 555T958 529Q1046 529 1098 592T1150
+764H1254Z" />
+<glyph unicode="&#xa0;" horiz-adv-x="498" />
+<glyph unicode="&#xa1;" horiz-adv-x="452" d="M174 690H285L292 -359H168L174 690ZM305 1022Q305 988 283 965T223 942T163 965T140 1022T162 1079T223 1102T283 1079T305 1022Z" />
+<glyph unicode="&#xa2;" horiz-adv-x="1115" d="M581 81Q704 81 788 150T882 334H997Q989 195 887 97T636 -17V-245H516V-16Q331 7 225 150T119 526V562Q119 784 224 929T516 1098V1318H636V1099Q791 1083 891 978T997 717H882Q874 844 791 922T580 1000Q418 1000
+329 883T239 555V520Q239 313 328 197T581 81Z" />
+<glyph unicode="&#xa3;" horiz-adv-x="1170" d="M404 645L413 368Q415 194 349 104H1094V0H97V104H195Q246 117 272 211Q292 285 290 367L281 645H93V749H277L268 1039Q268 1239 378 1357T674 1476Q856 1476 961 1371T1067 1088H944Q944 1223 869 1297T665 1371Q540
+1371 466 1283T392 1039L401 749H745V645H404Z" />
+<glyph unicode="&#xa4;" horiz-adv-x="1481" d="M1131 133Q1053 61 953 21T740 -20Q514 -20 349 132L194 -26L109 60L268 221Q144 389 144 608Q144 835 277 1006L109 1177L194 1264L361 1094Q526 1234 740 1234T1119 1092L1289 1265L1375 1177L1204 1002Q1334
+832 1334 608Q1334 393 1212 224L1375 60L1289 -27L1131 133ZM257 608Q257 470 321 350T499 161T740 91Q869 91 981 161T1157 350T1221 608Q1221 747 1156 866T979 1054T740 1122T500 1054T323 867T257 608Z" />
+<glyph unicode="&#xa5;" horiz-adv-x="1223" d="M607 734L1028 1456H1171L718 705H1085V616H667V412H1085V324H667V0H544V324H130V412H544V616H130V705H496L44 1456H187L607 734Z" />
+<glyph unicode="&#xa6;" horiz-adv-x="444" d="M159 -270V501H279V-270H159ZM279 698H159V1456H279V698Z" />
+<glyph unicode="&#xa7;" horiz-adv-x="1239" d="M1119 431Q1119 331 1058 262T887 159Q978 111 1026 41T1075 -139Q1075 -303 949 -399T606 -495Q497 -495 401 -467T236 -382Q102 -268 102 -64L222 -62Q222 -218 325 -305T606 -393Q766 -393 860 -324T954 -141Q954
+-64 920 -17T805 69T548 156T284 255T153 378T108 551Q108 651 166 721T331 825Q245 872 199 942T153 1120Q153 1281 282 1378T624 1476Q848 1476 972 1363T1097 1045H977Q977 1191 881 1282T624 1374Q459 1374 366 1306T273 1122Q273 1043 304 996T411 911T646
+828Q842 777 936 726T1075 603T1119 431ZM454 771Q346 758 287 700T228 553Q228 470 263 422T379 336T663 242L755 214Q867 227 933 284T999 428Q999 526 932 585T692 700L454 771Z" />
+<glyph unicode="&#xa8;" horiz-adv-x="881" d="M143 1396Q143 1430 164 1453T225 1477Q263 1477 285 1454T308 1396Q308 1363 286 1340T225 1317Q186 1317 165 1340T143 1396ZM580 1395Q580 1429 602 1452T662 1476Q701 1476 723 1453T745 1395Q745 1362 723 1339T662
+1316Q624 1316 602 1339T580 1395Z" />
+<glyph unicode="&#xa9;" horiz-adv-x="1637" d="M1121 607Q1121 455 1039 374T807 293T566 399T474 686V776Q474 950 566 1056T807 1163T1039 1083T1122 850H1023Q1023 1074 807 1074Q701 1074 637 993T573 771V680Q573 546 636 465T807 383Q913 383 967 436T1022
+607H1121ZM192 729Q192 553 273 399T502 155T817 65Q984 65 1129 154T1357 396T1441 729Q1441 907 1358 1059T1130 1300T817 1389Q646 1389 499 1298T272 1055T192 729ZM107 729Q107 931 200 1104T459 1376T817 1476T1174 1377T1432 1104T1526 729Q1526 532 1436
+360T1181 84T817 -21Q620 -21 455 82T198 358T107 729Z" />
+<glyph unicode="&#xaa;" horiz-adv-x="906" d="M649 705Q634 748 628 799Q541 691 406 691Q289 691 223 749T157 908Q157 1018 240 1079T486 1140H625V1201Q625 1286 585 1333T464 1380Q374 1380 323 1345T271 1237L164 1243Q164 1345 247 1410T464 1476Q588 1476
+661 1405T734 1199V884Q734 792 760 705H649ZM426 786Q479 786 536 816T625 890V1058H496Q266 1058 266 912Q266 786 426 786Z" />
+<glyph unicode="&#xab;" horiz-adv-x="933" d="M247 792L523 404H418L123 783V802L418 1181H523L247 792ZM556 536L832 148H727L432 527V546L727 925H832L556 536Z" />
+<glyph unicode="&#xac;" horiz-adv-x="1117" d="M936 386H816V670H124V776H936V386Z" />
+<glyph unicode="&#xad;" horiz-adv-x="586" d="M528 592H49V693H528V592Z" />
+<glyph unicode="&#xae;" horiz-adv-x="1642" d="M102 729Q102 931 195 1104T454 1376T812 1476T1169 1377T1428 1104T1522 729Q1522 530 1431 358T1175 83T812 -21T450 82T193 358T102 729ZM187 729Q187 550 270 396T499 154T812 65T1125 153T1353 396T1436 729Q1436
+905 1355 1057T1129 1299T812 1389Q644 1389 499 1301T270 1060T187 729ZM650 666V321H552V1160H810Q957 1160 1036 1099T1115 912Q1115 779 974 715Q1046 689 1074 635T1102 504T1106 394T1119 337V321H1017Q1003 357 1003 503Q1003 592 966 629T838 666H650ZM650
+757H831Q912 757 964 799T1017 910Q1017 995 974 1031T824 1070H650V757Z" />
+<glyph unicode="&#xaf;" horiz-adv-x="874" d="M776 1359H106V1456H776V1359Z" />
+<glyph unicode="&#xb0;" horiz-adv-x="774" d="M630 1226Q630 1122 559 1051T388 980Q287 980 215 1051T143 1226T216 1402T388 1476T558 1403T630 1226ZM233 1226Q233 1159 277 1115T388 1071T497 1115T540 1226Q540 1295 497 1340T388 1385Q323 1385 278 1340T233
+1226Z" />
+<glyph unicode="&#xb1;" horiz-adv-x="1085" d="M609 829H1000V727H609V289H498V727H84V829H498V1267H609V829ZM963 0H128V101H963V0Z" />
+<glyph unicode="&#xb2;" horiz-adv-x="740" d="M667 665H96V740L416 1054Q522 1164 522 1237Q522 1300 482 1338T362 1377Q275 1377 228 1333T181 1215H76Q76 1323 155 1394T360 1465T557 1403T628 1239Q628 1138 510 1016L455 961L229 752H667V665Z" />
+<glyph unicode="&#xb3;" horiz-adv-x="740" d="M267 1107H353Q434 1109 481 1145T529 1241Q529 1303 486 1340T362 1377Q286 1377 238 1340T190 1245H85Q85 1341 163 1403T361 1465Q489 1465 562 1405T635 1243Q635 1187 597 1140T489 1069Q651 1027 651 880Q651
+778 572 716T363 654Q234 654 153 717T71 884H177Q177 822 229 782T366 741Q453 741 499 779T546 883Q546 1025 340 1025H267V1107Z" />
+<glyph unicode="&#xb4;" horiz-adv-x="576" d="M315 1524H460L229 1245H124L315 1524Z" />
+<glyph unicode="&#xb5;" horiz-adv-x="1140" d="M281 1082V446Q281 266 344 174T544 81Q676 81 753 138T859 312V1082H979V0H870L863 154Q765 -20 552 -20Q368 -20 281 105V-416H162V1082H281Z" />
+<glyph unicode="&#xb6;" horiz-adv-x="973" d="M681 0V520H573Q423 520 312 578T142 742T83 988Q83 1201 216 1328T577 1456H801V0H681Z" />
+<glyph unicode="&#xb7;" horiz-adv-x="503" d="M163 717Q163 752 185 776T247 800T310 776T333 717T310 659T247 635T185 658T163 717Z" />
+<glyph unicode="&#xb8;" horiz-adv-x="498" d="M246 0L234 -64Q399 -85 399 -235Q399 -327 320 -381T105 -435L98 -357Q187 -357 243 -325T300 -237Q300 -179 257 -157T124 -127L153 0H246Z" />
+<glyph unicode="&#xb9;" horiz-adv-x="740" d="M464 669H358V1332L126 1262V1352L450 1459H464V669Z" />
+<glyph unicode="&#xba;" horiz-adv-x="922" d="M135 1132Q135 1285 223 1380T458 1476Q605 1476 693 1381T782 1127V1033Q782 880 694 785T460 690Q313 690 224 784T135 1038V1132ZM243 1033Q243 919 299 852T460 785Q559 785 616 851T674 1037V1132Q674 1247
+616 1313T458 1380T301 1312T243 1127V1033Z" />
+<glyph unicode="&#xbb;" horiz-adv-x="928" d="M221 944L516 560V541L221 162H115L391 550L115 944H221ZM540 944L835 560V541L540 162H434L710 550L434 944H540Z" />
+<glyph unicode="&#xbc;" horiz-adv-x="1484" d="M453 664H347V1327L115 1257V1347L439 1454H453V664ZM414 129L340 177L1051 1315L1125 1267L414 129ZM1272 275H1399V187H1272V0H1167V187H768L764 253L1161 789H1272V275ZM878 275H1167V659L1136 609L878 275Z" />
+<glyph unicode="&#xbd;" horiz-adv-x="1548" d="M370 129L296 177L1007 1315L1081 1267L370 129ZM438 664H332V1327L100 1257V1347L424 1454H438V664ZM1436 0H865V75L1185 389Q1291 499 1291 572Q1291 635 1251 673T1131 712Q1044 712 997 668T950 550H845Q845
+658 924 729T1129 800T1326 738T1397 574Q1397 473 1279 351L1224 296L998 87H1436V0Z" />
+<glyph unicode="&#xbe;" horiz-adv-x="1590" d="M558 129L484 177L1195 1315L1269 1267L558 129ZM1387 275H1514V187H1387V0H1282V187H883L879 253L1276 789H1387V275ZM993 275H1282V659L1251 609L993 275ZM314 1107H400Q481 1109 528 1145T576 1241Q576 1303
+533 1340T409 1377Q333 1377 285 1340T237 1245H132Q132 1341 210 1403T408 1465Q536 1465 609 1405T682 1243Q682 1187 644 1140T536 1069Q698 1027 698 880Q698 778 619 716T410 654Q281 654 200 717T118 884H224Q224 822 276 782T413 741Q500 741 546 779T593
+883Q593 1025 387 1025H314V1107Z" />
+<glyph unicode="&#xbf;" horiz-adv-x="940" d="M551 687Q549 564 524 505T405 352T288 228Q207 123 207 -8Q207 -137 274 -207T469 -277Q588 -277 659 -207T732 -20H852Q850 -186 745 -284T469 -383Q291 -383 190 -283T88 -10Q88 101 141 202T337 438Q422 509
+429 618L431 687H551ZM567 1022Q567 988 545 965T485 941T425 964T402 1022Q402 1055 424 1078T485 1101T545 1078T567 1022Z" />
+<glyph unicode="&#xc0;" horiz-adv-x="1279" d="M970 408H309L159 0H30L581 1456H698L1249 0H1121L970 408ZM347 513H931L639 1306L347 513ZM716 1560H607L381 1839H525L716 1560Z" />
+<glyph unicode="&#xc1;" horiz-adv-x="1279" d="M970 408H309L159 0H30L581 1456H698L1249 0H1121L970 408ZM347 513H931L639 1306L347 513ZM762 1839H907L676 1560H571L762 1839Z" />
+<glyph unicode="&#xc2;" horiz-adv-x="1279" d="M970 408H309L159 0H30L581 1456H698L1249 0H1121L970 408ZM347 513H931L639 1306L347 513ZM921 1583V1573H810L642 1756L475 1573H366V1586L604 1841H680L921 1583Z" />
+<glyph unicode="&#xc3;" horiz-adv-x="1279" d="M970 408H309L159 0H30L581 1456H698L1249 0H1121L970 408ZM347 513H931L639 1306L347 513ZM983 1809Q983 1713 927 1655T788 1596Q712 1596 640 1651T510 1706Q463 1706 432 1675T400 1588L310 1591Q310 1683 364
+1743T505 1803Q553 1803 587 1786T651 1748T711 1710T783 1693Q829 1693 861 1726T894 1815L983 1809Z" />
+<glyph unicode="&#xc4;" horiz-adv-x="1279" d="M970 408H309L159 0H30L581 1456H698L1249 0H1121L970 408ZM347 513H931L639 1306L347 513ZM349 1711Q349 1745 370 1768T431 1792Q469 1792 491 1769T514 1711Q514 1678 492 1655T431 1632Q392 1632 371 1655T349
+1711ZM786 1710Q786 1744 808 1767T868 1791Q907 1791 929 1768T951 1710Q951 1677 929 1654T868 1631Q830 1631 808 1654T786 1710Z" />
+<glyph unicode="&#xc5;" horiz-adv-x="1279" d="M970 408H309L159 0H30L581 1456H698L1249 0H1121L970 408ZM347 513H931L639 1306L347 513ZM450 1715Q450 1795 506 1850T643 1905Q722 1905 779 1850T836 1715Q836 1636 781 1582T643 1528T505 1582T450 1715ZM527
+1715Q527 1665 560 1632T643 1599Q692 1599 726 1631T760 1715Q760 1768 725 1801T643 1834Q594 1834 561 1800T527 1715Z" />
+<glyph unicode="&#xc6;" horiz-adv-x="1865" d="M1823 0H1006L989 389H393L163 0H17L898 1456H1762V1354H1068L1091 809H1680V707H1095L1121 101H1823V0ZM460 502H985L950 1331L460 502Z" />
+<glyph unicode="&#xc7;" horiz-adv-x="1330" d="M1215 454Q1190 224 1051 102T679 -20Q517 -20 393 61T200 290T131 630V819Q131 1013 199 1163T394 1394T688 1476Q922 1476 1057 1350T1215 1000H1091Q1045 1371 688 1371Q490 1371 373 1223T255 814V636Q255 384
+369 234T679 84Q872 84 970 176T1091 454H1215ZM728 -9L716 -73Q881 -94 881 -244Q881 -336 802 -390T587 -444L580 -366Q669 -366 725 -334T782 -246Q782 -188 739 -166T606 -136L635 -9H728Z" />
+<glyph unicode="&#xc8;" horiz-adv-x="1165" d="M988 698H307V104H1090V0H184V1456H1085V1351H307V802H988V698ZM693 1566H584L358 1845H502L693 1566Z" />
+<glyph unicode="&#xc9;" horiz-adv-x="1165" d="M988 698H307V104H1090V0H184V1456H1085V1351H307V802H988V698ZM739 1845H884L653 1566H548L739 1845Z" />
+<glyph unicode="&#xca;" horiz-adv-x="1165" d="M988 698H307V104H1090V0H184V1456H1085V1351H307V802H988V698ZM898 1589V1579H787L619 1762L452 1579H343V1592L581 1847H657L898 1589Z" />
+<glyph unicode="&#xcb;" horiz-adv-x="1165" d="M988 698H307V104H1090V0H184V1456H1085V1351H307V802H988V698ZM326 1717Q326 1751 347 1774T408 1798Q446 1798 468 1775T491 1717Q491 1684 469 1661T408 1638Q369 1638 348 1661T326 1717ZM763 1716Q763 1750
+785 1773T845 1797Q884 1797 906 1774T928 1716Q928 1683 906 1660T845 1637Q807 1637 785 1660T763 1716Z" />
+<glyph unicode="&#xcc;" horiz-adv-x="545" d="M334 0H211V1456H334V0ZM348 1566H239L13 1845H157L348 1566Z" />
+<glyph unicode="&#xcd;" horiz-adv-x="545" d="M334 0H211V1456H334V0ZM393 1845H538L307 1566H202L393 1845Z" />
+<glyph unicode="&#xce;" horiz-adv-x="545" d="M334 0H211V1456H334V0ZM553 1589V1579H442L274 1762L107 1579H-2V1592L236 1847H312L553 1589Z" />
+<glyph unicode="&#xcf;" horiz-adv-x="545" d="M334 0H211V1456H334V0ZM-19 1717Q-19 1751 2 1774T63 1798Q101 1798 123 1775T146 1717Q146 1684 124 1661T63 1638Q24 1638 3 1661T-19 1717ZM418 1716Q418 1750 440 1773T500 1797Q539 1797 561 1774T583 1716Q583
+1683 561 1660T500 1637Q462 1637 440 1660T418 1716Z" />
+<glyph unicode="&#xd0;" horiz-adv-x="1371" d="M214 0V689H33V791H214V1456H621Q800 1456 942 1375T1163 1141T1243 795V661Q1243 466 1164 315T942 82T612 0H214ZM645 689H337V104H608Q843 104 982 256T1121 669V797Q1121 1048 984 1199T623 1351H337V791H645V689Z" />
+<glyph unicode="&#xd1;" horiz-adv-x="1454" d="M1268 0H1145L308 1246V0H184V1456H308L1146 209V1456H1268V0ZM1067 1809Q1067 1713 1011 1655T872 1596Q796 1596 724 1651T594 1706Q547 1706 516 1675T484 1588L394 1591Q394 1683 448 1743T589 1803Q637 1803
+671 1786T735 1748T795 1710T867 1693Q913 1693 945 1726T978 1815L1067 1809Z" />
+<glyph unicode="&#xd2;" horiz-adv-x="1386" d="M1260 649Q1260 448 1191 296T992 62T694 -20Q439 -20 282 162T125 655V805Q125 1004 195 1157T395 1393T692 1476T988 1395T1187 1166T1260 823V649ZM1137 807Q1137 1070 1018 1219T692 1368Q489 1368 369 1219T248
+801V649Q248 390 368 239T694 87Q903 87 1020 236T1137 653V807ZM765 1572H656L430 1851H574L765 1572Z" />
+<glyph unicode="&#xd3;" horiz-adv-x="1386" d="M1260 649Q1260 448 1191 296T992 62T694 -20Q439 -20 282 162T125 655V805Q125 1004 195 1157T395 1393T692 1476T988 1395T1187 1166T1260 823V649ZM1137 807Q1137 1070 1018 1219T692 1368Q489 1368 369 1219T248
+801V649Q248 390 368 239T694 87Q903 87 1020 236T1137 653V807ZM811 1851H956L725 1572H620L811 1851Z" />
+<glyph unicode="&#xd4;" horiz-adv-x="1386" d="M1260 649Q1260 448 1191 296T992 62T694 -20Q439 -20 282 162T125 655V805Q125 1004 195 1157T395 1393T692 1476T988 1395T1187 1166T1260 823V649ZM1137 807Q1137 1070 1018 1219T692 1368Q489 1368 369 1219T248
+801V649Q248 390 368 239T694 87Q903 87 1020 236T1137 653V807ZM970 1595V1585H859L691 1768L524 1585H415V1598L653 1853H729L970 1595Z" />
+<glyph unicode="&#xd5;" horiz-adv-x="1386" d="M1260 649Q1260 448 1191 296T992 62T694 -20Q439 -20 282 162T125 655V805Q125 1004 195 1157T395 1393T692 1476T988 1395T1187 1166T1260 823V649ZM1137 807Q1137 1070 1018 1219T692 1368Q489 1368 369 1219T248
+801V649Q248 390 368 239T694 87Q903 87 1020 236T1137 653V807ZM1032 1821Q1032 1725 976 1667T837 1608Q761 1608 689 1663T559 1718Q512 1718 481 1687T449 1600L359 1603Q359 1695 413 1755T554 1815Q602 1815 636 1798T700 1760T760 1722T832 1705Q878 1705
+910 1738T943 1827L1032 1821Z" />
+<glyph unicode="&#xd6;" horiz-adv-x="1386" d="M1260 649Q1260 448 1191 296T992 62T694 -20Q439 -20 282 162T125 655V805Q125 1004 195 1157T395 1393T692 1476T988 1395T1187 1166T1260 823V649ZM1137 807Q1137 1070 1018 1219T692 1368Q489 1368 369 1219T248
+801V649Q248 390 368 239T694 87Q903 87 1020 236T1137 653V807ZM398 1723Q398 1757 419 1780T480 1804Q518 1804 540 1781T563 1723Q563 1690 541 1667T480 1644Q441 1644 420 1667T398 1723ZM835 1722Q835 1756 857 1779T917 1803Q956 1803 978 1780T1000 1722Q1000
+1689 978 1666T917 1643Q879 1643 857 1666T835 1722Z" />
+<glyph unicode="&#xd7;" horiz-adv-x="1072" d="M93 179L451 544L108 894L187 974L529 624L872 974L951 894L608 544L966 179L887 100L529 464L172 100L93 179Z" />
+<glyph unicode="&#xd8;" horiz-adv-x="1386" d="M1260 649Q1260 448 1191 296T992 62T694 -20Q508 -20 375 77L274 -83H170L307 134Q125 318 125 658V805Q125 1004 195 1157T395 1393T692 1476Q916 1476 1064 1336L1171 1505H1274L1125 1268Q1259 1088 1260 807V649ZM248
+649Q248 388 370 235L1002 1237Q883 1368 692 1368Q489 1368 369 1219T248 801V649ZM1137 807Q1137 1018 1057 1160L434 171Q541 87 694 87Q903 87 1020 236T1137 653V807Z" />
+<glyph unicode="&#xd9;" horiz-adv-x="1346" d="M1187 1456V462Q1186 315 1122 206T942 39T674 -20Q444 -20 306 105T162 453V1456H284V471Q284 287 389 186T674 84T958 186T1063 470V1456H1187ZM756 1560H647L421 1839H565L756 1560Z" />
+<glyph unicode="&#xda;" horiz-adv-x="1346" d="M1187 1456V462Q1186 315 1122 206T942 39T674 -20Q444 -20 306 105T162 453V1456H284V471Q284 287 389 186T674 84T958 186T1063 470V1456H1187ZM802 1839H947L716 1560H611L802 1839Z" />
+<glyph unicode="&#xdb;" horiz-adv-x="1346" d="M1187 1456V462Q1186 315 1122 206T942 39T674 -20Q444 -20 306 105T162 453V1456H284V471Q284 287 389 186T674 84T958 186T1063 470V1456H1187ZM961 1583V1573H850L682 1756L515 1573H406V1586L644 1841H720L961 1583Z" />
+<glyph unicode="&#xdc;" horiz-adv-x="1346" d="M1187 1456V462Q1186 315 1122 206T942 39T674 -20Q444 -20 306 105T162 453V1456H284V471Q284 287 389 186T674 84T958 186T1063 470V1456H1187ZM389 1711Q389 1745 410 1768T471 1792Q509 1792 531 1769T554 1711Q554
+1678 532 1655T471 1632Q432 1632 411 1655T389 1711ZM826 1710Q826 1744 848 1767T908 1791Q947 1791 969 1768T991 1710Q991 1677 969 1654T908 1631Q870 1631 848 1654T826 1710Z" />
+<glyph unicode="&#xdd;" horiz-adv-x="1226" d="M611 662L1056 1456H1198L672 548V0H549V548L24 1456H170L611 662ZM732 1833H877L646 1554H541L732 1833Z" />
+<glyph unicode="&#xde;" horiz-adv-x="1214" d="M303 1456V1152H628Q771 1152 877 1101T1039 956T1096 738Q1096 553 974 441T641 324H303V0H183V1456H303ZM303 1051V425H627Q784 425 880 510T976 736T885 961T642 1051H303Z" />
+<glyph unicode="&#xdf;" horiz-adv-x="1200" d="M271 0H151V1127Q151 1327 246 1435T512 1544Q665 1544 760 1460T856 1237Q856 1179 843 1131T794 1019T746 913T733 824Q733 768 774 716T911 593T1051 454T1096 306Q1096 160 990 70T720 -20Q636 -20 545 4T414
+60L448 161Q485 132 562 106T706 80Q828 80 902 144T976 306Q976 367 932 423T797 547T659 681T613 826Q613 922 676 1034T739 1230Q739 1323 676 1382T522 1442Q275 1442 271 1136V0Z" />
+<glyph unicode="&#xe0;" horiz-adv-x="1097" d="M839 0Q821 51 816 151Q753 69 656 25T449 -20Q293 -20 197 67T100 287Q100 445 231 537T598 629H815V752Q815 868 744 934T535 1001Q410 1001 328 937T246 783L126 784Q126 913 246 1007T541 1102Q722 1102 826
+1012T934 759V247Q934 90 967 12V0H839ZM463 86Q583 86 677 144T815 299V537H601Q422 535 321 472T220 297Q220 206 287 146T463 86ZM653 1245H544L318 1524H462L653 1245Z" />
+<glyph unicode="&#xe1;" horiz-adv-x="1097" d="M839 0Q821 51 816 151Q753 69 656 25T449 -20Q293 -20 197 67T100 287Q100 445 231 537T598 629H815V752Q815 868 744 934T535 1001Q410 1001 328 937T246 783L126 784Q126 913 246 1007T541 1102Q722 1102 826
+1012T934 759V247Q934 90 967 12V0H839ZM463 86Q583 86 677 144T815 299V537H601Q422 535 321 472T220 297Q220 206 287 146T463 86ZM699 1524H844L613 1245H508L699 1524Z" />
+<glyph unicode="&#xe2;" horiz-adv-x="1097" d="M839 0Q821 51 816 151Q753 69 656 25T449 -20Q293 -20 197 67T100 287Q100 445 231 537T598 629H815V752Q815 868 744 934T535 1001Q410 1001 328 937T246 783L126 784Q126 913 246 1007T541 1102Q722 1102 826
+1012T934 759V247Q934 90 967 12V0H839ZM463 86Q583 86 677 144T815 299V537H601Q422 535 321 472T220 297Q220 206 287 146T463 86ZM858 1268V1258H747L579 1441L412 1258H303V1271L541 1526H617L858 1268Z" />
+<glyph unicode="&#xe3;" horiz-adv-x="1097" d="M839 0Q821 51 816 151Q753 69 656 25T449 -20Q293 -20 197 67T100 287Q100 445 231 537T598 629H815V752Q815 868 744 934T535 1001Q410 1001 328 937T246 783L126 784Q126 913 246 1007T541 1102Q722 1102 826
+1012T934 759V247Q934 90 967 12V0H839ZM463 86Q583 86 677 144T815 299V537H601Q422 535 321 472T220 297Q220 206 287 146T463 86ZM920 1494Q920 1398 864 1340T725 1281Q649 1281 577 1336T447 1391Q400 1391 369 1360T337 1273L247 1276Q247 1368 301 1428T442
+1488Q490 1488 524 1471T588 1433T648 1395T720 1378Q766 1378 798 1411T831 1500L920 1494Z" />
+<glyph unicode="&#xe4;" horiz-adv-x="1097" d="M839 0Q821 51 816 151Q753 69 656 25T449 -20Q293 -20 197 67T100 287Q100 445 231 537T598 629H815V752Q815 868 744 934T535 1001Q410 1001 328 937T246 783L126 784Q126 913 246 1007T541 1102Q722 1102 826
+1012T934 759V247Q934 90 967 12V0H839ZM463 86Q583 86 677 144T815 299V537H601Q422 535 321 472T220 297Q220 206 287 146T463 86ZM286 1396Q286 1430 307 1453T368 1477Q406 1477 428 1454T451 1396Q451 1363 429 1340T368 1317Q329 1317 308 1340T286 1396ZM723
+1395Q723 1429 745 1452T805 1476Q844 1476 866 1453T888 1395Q888 1362 866 1339T805 1316Q767 1316 745 1339T723 1395Z" />
+<glyph unicode="&#xe5;" horiz-adv-x="1097" d="M839 0Q821 51 816 151Q753 69 656 25T449 -20Q293 -20 197 67T100 287Q100 445 231 537T598 629H815V752Q815 868 744 934T535 1001Q410 1001 328 937T246 783L126 784Q126 913 246 1007T541 1102Q722 1102 826
+1012T934 759V247Q934 90 967 12V0H839ZM463 86Q583 86 677 144T815 299V537H601Q422 535 321 472T220 297Q220 206 287 146T463 86ZM387 1400Q387 1480 443 1535T580 1590Q659 1590 716 1535T773 1400Q773 1321 718 1267T580 1213T442 1267T387 1400ZM464 1400Q464
+1350 497 1317T580 1284Q629 1284 663 1316T697 1400Q697 1453 662 1486T580 1519Q531 1519 498 1485T464 1400Z" />
+<glyph unicode="&#xe6;" horiz-adv-x="1732" d="M1265 -20Q1126 -20 1027 34T867 186Q807 88 693 34T440 -20Q271 -20 178 64T85 293Q85 450 195 539T511 632H781V720Q781 852 718 926T528 1000Q398 1000 315 935T232 765L113 778Q113 922 229 1012T528 1102Q653
+1102 741 1049T870 889Q930 989 1024 1045T1235 1102Q1431 1102 1543 982T1658 644V538H901V509Q901 308 997 195T1265 81Q1450 81 1589 199L1636 112Q1491 -20 1265 -20ZM458 80Q549 80 642 126T781 236V536H525Q388 536 302 475T207 309L206 289Q206 192 271
+136T458 80ZM1235 1000Q1103 1000 1013 902T904 636H1539V667Q1539 821 1459 910T1235 1000Z" />
+<glyph unicode="&#xe7;" horiz-adv-x="1055" d="M556 81Q681 81 765 151T857 334H972Q967 235 910 154T759 26T556 -20Q343 -20 219 128T94 526V562Q94 722 150 845T310 1035T555 1102Q733 1102 848 996T972 717H857Q849 844 766 922T555 1000Q393 1000 304 883T214
+555V520Q214 313 303 197T556 81ZM589 -9L577 -73Q742 -94 742 -244Q742 -336 663 -390T448 -444L441 -366Q530 -366 586 -334T643 -246Q643 -188 600 -166T467 -136L496 -9H589Z" />
+<glyph unicode="&#xe8;" horiz-adv-x="1058" d="M575 -20Q437 -20 326 48T152 237T90 510V553Q90 709 150 834T319 1030T553 1102Q750 1102 865 968T981 600V533H209V510Q209 326 314 204T580 81Q676 81 749 116T883 228L958 171Q826 -20 575 -20ZM553 1000Q418
+1000 326 901T213 635H862V648Q857 804 773 902T553 1000ZM640 1245H531L305 1524H449L640 1245Z" />
+<glyph unicode="&#xe9;" horiz-adv-x="1058" d="M575 -20Q437 -20 326 48T152 237T90 510V553Q90 709 150 834T319 1030T553 1102Q750 1102 865 968T981 600V533H209V510Q209 326 314 204T580 81Q676 81 749 116T883 228L958 171Q826 -20 575 -20ZM553 1000Q418
+1000 326 901T213 635H862V648Q857 804 773 902T553 1000ZM686 1524H831L600 1245H495L686 1524Z" />
+<glyph unicode="&#xea;" horiz-adv-x="1058" d="M575 -20Q437 -20 326 48T152 237T90 510V553Q90 709 150 834T319 1030T553 1102Q750 1102 865 968T981 600V533H209V510Q209 326 314 204T580 81Q676 81 749 116T883 228L958 171Q826 -20 575 -20ZM553 1000Q418
+1000 326 901T213 635H862V648Q857 804 773 902T553 1000ZM845 1268V1258H734L566 1441L399 1258H290V1271L528 1526H604L845 1268Z" />
+<glyph unicode="&#xeb;" horiz-adv-x="1058" d="M575 -20Q437 -20 326 48T152 237T90 510V553Q90 709 150 834T319 1030T553 1102Q750 1102 865 968T981 600V533H209V510Q209 326 314 204T580 81Q676 81 749 116T883 228L958 171Q826 -20 575 -20ZM553 1000Q418
+1000 326 901T213 635H862V648Q857 804 773 902T553 1000ZM273 1396Q273 1430 294 1453T355 1477Q393 1477 415 1454T438 1396Q438 1363 416 1340T355 1317Q316 1317 295 1340T273 1396ZM710 1395Q710 1429 732 1452T792 1476Q831 1476 853 1453T875 1395Q875 1362
+853 1339T792 1316Q754 1316 732 1339T710 1395Z" />
+<glyph unicode="&#xec;" horiz-adv-x="456" d="M288 0H168V1082H288V0ZM305 1233H196L-30 1512H114L305 1233Z" />
+<glyph unicode="&#xed;" horiz-adv-x="456" d="M288 0H168V1082H288V0ZM350 1768H495L264 1489H159L350 1768Z" />
+<glyph unicode="&#xee;" horiz-adv-x="456" d="M288 0H168V1082H288V0ZM510 1256V1246H399L231 1429L64 1246H-45V1259L193 1514H269L510 1256Z" />
+<glyph unicode="&#xef;" horiz-adv-x="456" d="M288 0H168V1082H288V0ZM-62 1384Q-62 1418 -41 1441T20 1465Q58 1465 80 1442T103 1384Q103 1351 81 1328T20 1305Q-19 1305 -40 1328T-62 1384ZM375 1383Q375 1417 397 1440T457 1464Q496 1464 518 1441T540 1383Q540
+1350 518 1327T457 1304Q419 1304 397 1327T375 1383Z" />
+<glyph unicode="&#xf0;" horiz-adv-x="1191" d="M811 1303Q1049 1053 1055 645V535Q1055 376 999 249T842 51T615 -20Q485 -20 379 41T211 216T149 466Q149 695 268 830T587 965Q687 965 773 927T919 821Q877 1072 709 1240L484 1101L433 1174L639 1302Q502 1408
+296 1475L335 1578Q577 1506 744 1366L938 1487L989 1414L811 1303ZM935 625L933 682Q894 765 807 813T609 861Q448 861 359 756T269 466Q269 363 314 274T438 134T619 83Q760 83 847 207T935 543V625Z" />
+<glyph unicode="&#xf1;" horiz-adv-x="1125" d="M270 1082L274 897Q335 997 426 1049T627 1102Q801 1102 886 1004T972 710V0H853V711Q852 856 792 927T598 998Q487 998 402 929T275 741V0H156V1082H270ZM916 1493Q916 1397 860 1339T721 1280Q645 1280 573 1335T443
+1390Q396 1390 365 1359T333 1272L243 1275Q243 1367 297 1427T438 1487Q486 1487 520 1470T584 1432T644 1394T716 1377Q762 1377 794 1410T827 1499L916 1493Z" />
+<glyph unicode="&#xf2;" horiz-adv-x="1147" d="M90 557Q90 713 150 838T321 1032T572 1102Q788 1102 922 951T1056 549V524Q1056 367 996 242T825 48T574 -20Q359 -20 225 131T90 533V557ZM210 524Q210 330 310 206T574 81Q736 81 836 205T937 534V557Q937 681
+891 784T762 943T572 1000Q412 1000 311 875T210 546V524ZM645 1245H536L310 1524H454L645 1245Z" />
+<glyph unicode="&#xf3;" horiz-adv-x="1147" d="M90 557Q90 713 150 838T321 1032T572 1102Q788 1102 922 951T1056 549V524Q1056 367 996 242T825 48T574 -20Q359 -20 225 131T90 533V557ZM210 524Q210 330 310 206T574 81Q736 81 836 205T937 534V557Q937 681
+891 784T762 943T572 1000Q412 1000 311 875T210 546V524ZM691 1524H836L605 1245H500L691 1524Z" />
+<glyph unicode="&#xf4;" horiz-adv-x="1147" d="M90 557Q90 713 150 838T321 1032T572 1102Q788 1102 922 951T1056 549V524Q1056 367 996 242T825 48T574 -20Q359 -20 225 131T90 533V557ZM210 524Q210 330 310 206T574 81Q736 81 836 205T937 534V557Q937 681
+891 784T762 943T572 1000Q412 1000 311 875T210 546V524ZM850 1268V1258H739L571 1441L404 1258H295V1271L533 1526H609L850 1268Z" />
+<glyph unicode="&#xf5;" horiz-adv-x="1147" d="M90 557Q90 713 150 838T321 1032T572 1102Q788 1102 922 951T1056 549V524Q1056 367 996 242T825 48T574 -20Q359 -20 225 131T90 533V557ZM210 524Q210 330 310 206T574 81Q736 81 836 205T937 534V557Q937 681
+891 784T762 943T572 1000Q412 1000 311 875T210 546V524ZM912 1493Q912 1397 856 1339T717 1280Q641 1280 569 1335T439 1390Q392 1390 361 1359T329 1272L239 1275Q239 1367 293 1427T434 1487Q482 1487 516 1470T580 1432T640 1394T712 1377Q758 1377 790 1410T823
+1499L912 1493Z" />
+<glyph unicode="&#xf6;" horiz-adv-x="1147" d="M90 557Q90 713 150 838T321 1032T572 1102Q788 1102 922 951T1056 549V524Q1056 367 996 242T825 48T574 -20Q359 -20 225 131T90 533V557ZM210 524Q210 330 310 206T574 81Q736 81 836 205T937 534V557Q937 681
+891 784T762 943T572 1000Q412 1000 311 875T210 546V524ZM278 1396Q278 1430 299 1453T360 1477Q398 1477 420 1454T443 1396Q443 1363 421 1340T360 1317Q321 1317 300 1340T278 1396ZM715 1395Q715 1429 737 1452T797 1476Q836 1476 858 1453T880 1395Q880 1362
+858 1339T797 1316Q759 1316 737 1339T715 1395Z" />
+<glyph unicode="&#xf7;" horiz-adv-x="1164" d="M1070 644H72V760H1070V644ZM495 1088Q495 1123 517 1147T579 1171T642 1147T665 1088T642 1030T579 1006T517 1029T495 1088ZM495 291Q495 326 517 350T579 374T642 350T665 291T642 233T579 210T517 233T495 291Z" />
+<glyph unicode="&#xf8;" horiz-adv-x="1140" d="M89 557Q89 713 149 838T320 1032T571 1102Q685 1102 785 1054L863 1214H957L857 1010Q951 938 1003 821T1055 557V524Q1055 368 994 242T823 48T573 -20Q465 -20 373 21L294 -140H200L299 63Q199 134 144 253T89
+524V557ZM208 524Q208 414 243 319T348 163L737 957Q662 1000 571 1000Q410 1000 309 875T208 546V524ZM935 557Q935 660 902 751T806 905L419 115Q487 81 573 81Q734 81 834 205T935 534V557Z" />
+<glyph unicode="&#xf9;" horiz-adv-x="1125" d="M852 137Q744 -20 507 -20Q334 -20 244 80T152 378V1082H271V393Q271 84 521 84Q781 84 850 299V1082H970V0H854L852 137ZM647 1245H538L312 1524H456L647 1245Z" />
+<glyph unicode="&#xfa;" horiz-adv-x="1125" d="M852 137Q744 -20 507 -20Q334 -20 244 80T152 378V1082H271V393Q271 84 521 84Q781 84 850 299V1082H970V0H854L852 137ZM693 1524H838L607 1245H502L693 1524Z" />
+<glyph unicode="&#xfb;" horiz-adv-x="1125" d="M852 137Q744 -20 507 -20Q334 -20 244 80T152 378V1082H271V393Q271 84 521 84Q781 84 850 299V1082H970V0H854L852 137ZM852 1268V1258H741L573 1441L406 1258H297V1271L535 1526H611L852 1268Z" />
+<glyph unicode="&#xfc;" horiz-adv-x="1125" d="M852 137Q744 -20 507 -20Q334 -20 244 80T152 378V1082H271V393Q271 84 521 84Q781 84 850 299V1082H970V0H854L852 137ZM280 1396Q280 1430 301 1453T362 1477Q400 1477 422 1454T445 1396Q445 1363 423 1340T362
+1317Q323 1317 302 1340T280 1396ZM717 1395Q717 1429 739 1452T799 1476Q838 1476 860 1453T882 1395Q882 1362 860 1339T799 1316Q761 1316 739 1339T717 1395Z" />
+<glyph unicode="&#xfd;" horiz-adv-x="973" d="M499 172L815 1082H944L482 -184L458 -240Q369 -437 183 -437Q140 -437 91 -423L90 -324L152 -330Q240 -330 294 -287T387 -137L440 9L32 1082H163L499 172ZM633 1524H778L547 1245H442L633 1524Z" />
+<glyph unicode="&#xfe;" horiz-adv-x="1150" d="M1031 530Q1031 277 919 129T618 -20Q397 -20 279 136V-416H159V1536H279V932Q396 1102 616 1102Q808 1102 919 956T1031 548V530ZM911 551Q911 758 826 878T589 998Q479 998 400 945T279 791V270Q321 180 400 131T591
+81Q742 81 826 201T911 551Z" />
+<glyph unicode="&#xff;" horiz-adv-x="973" d="M499 172L815 1082H944L482 -184L458 -240Q369 -437 183 -437Q140 -437 91 -423L90 -324L152 -330Q240 -330 294 -287T387 -137L440 9L32 1082H163L499 172ZM220 1396Q220 1430 241 1453T302 1477Q340 1477 362 1454T385
+1396Q385 1363 363 1340T302 1317Q263 1317 242 1340T220 1396ZM657 1395Q657 1429 679 1452T739 1476Q778 1476 800 1453T822 1395Q822 1362 800 1339T739 1316Q701 1316 679 1339T657 1395Z" />
+<glyph unicode="&#x2013;" horiz-adv-x="1334" d="M1417 686H415V788H1417V686Z" />
+<glyph unicode="&#x2014;" horiz-adv-x="1580" d="M1462 686H126V788H1462V686Z" />
+<glyph unicode="&#x2018;" horiz-adv-x="364" d="M238 1554L310 1503Q220 1385 217 1249V1121H98V1233Q98 1325 135 1410T238 1554Z" />
+<glyph unicode="&#x2019;" horiz-adv-x="364" d="M133 1099L62 1151Q152 1272 155 1405V1536H273V1435Q273 1226 133 1099Z" />
+<glyph unicode="&#x201a;" horiz-adv-x="353" d="M112 -231L41 -179Q124 -68 132 51L133 205H252V104Q252 -104 112 -231Z" />
+<glyph unicode="&#x201c;" horiz-adv-x="612" d="M239 1554L311 1503Q221 1385 218 1249V1121H99V1233Q99 1325 136 1410T239 1554ZM490 1554L562 1503Q472 1385 469 1249V1121H350V1233Q350 1325 387 1410T490 1554Z" />
+<glyph unicode="&#x201d;" horiz-adv-x="617" d="M139 1099L68 1151Q158 1272 161 1405V1536H279V1435Q279 1226 139 1099ZM383 1099L312 1151Q402 1272 405 1405V1536H523V1435Q523 1226 383 1099Z" />
+<glyph unicode="&#x201e;" horiz-adv-x="593" d="M112 -240L41 -188Q130 -65 133 73V236H252V106Q252 -111 112 -240ZM346 -240L275 -188Q363 -66 366 73V236H486V106Q486 -111 346 -240Z" />
+<glyph unicode="&#x2022;" horiz-adv-x="662" d="M146 752Q146 831 197 881T331 931Q413 931 464 883T517 757V717Q517 636 466 588T332 540Q248 540 197 589T146 719V752Z" />
+<glyph unicode="&#x2039;" horiz-adv-x="609" d="M232 555L508 167H403L108 546V565L403 944H508L232 555Z" />
+<glyph unicode="&#x203a;" horiz-adv-x="609" d="M203 944L498 560V541L203 162H97L373 550L97 944H203Z" />
+</font>
+</defs>
+</svg>
Binary file server/bo_client/public/assets/fonts/Roboto-300/Roboto-300.ttf has changed
Binary file server/bo_client/public/assets/fonts/Roboto-300/Roboto-300.woff has changed
Binary file server/bo_client/public/assets/fonts/Roboto-300/Roboto-300.woff2 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/public/assets/fonts/Roboto-regular/LICENSE.txt	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
Binary file server/bo_client/public/assets/fonts/Roboto-regular/Roboto-regular.eot has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/public/assets/fonts/Roboto-regular/Roboto-regular.svg	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,308 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg">
+<defs >
+<font id="Roboto" horiz-adv-x="1157" ><font-face
+    font-family="Roboto"
+    units-per-em="2048"
+    panose-1="2 0 0 0 0 0 0 0 0 0"
+    ascent="1900"
+    descent="-500"
+    alphabetic="0" />
+<glyph unicode=" " horiz-adv-x="507" />
+<glyph unicode="!" horiz-adv-x="527" d="M347 411H180L167 1456H361L347 411ZM160 93Q160 138 187 168T269 199T351 169T379 93T351 19T269 -11T188 18T160 93Z" />
+<glyph unicode="&quot;" horiz-adv-x="655" d="M277 1400L247 1042H136L137 1536H277V1400ZM547 1400L517 1042H406L407 1536H547V1400Z" />
+<glyph unicode="#" horiz-adv-x="1261" d="M765 410H501L421 0H278L358 410H119V547H384L453 901H195V1040H480L562 1456H705L623 1040H887L969 1456H1113L1031 1040H1235V901H1004L935 547H1160V410H909L829 0H685L765 410ZM527 547H791L860 901H596L527 547Z" />
+<glyph unicode="$" horiz-adv-x="1150" d="M856 375Q856 467 792 530T574 644Q361 709 264 813T166 1079Q166 1243 261 1348T524 1473V1692H673V1472Q841 1449 934 1331T1028 1008H844Q844 1149 777 1232T596 1315Q477 1315 414 1254T351 1082Q351 980 417 920T636
+810T874 701T1000 562T1041 377Q1041 208 940 105T655 -17V-208H507V-17Q321 0 216 115T110 429H295Q295 290 368 215T575 140Q706 140 781 203T856 375Z" />
+<glyph unicode="%" horiz-adv-x="1500" d="M105 1176Q105 1307 188 1392T403 1477Q536 1477 618 1392T701 1170V1099Q701 967 618 884T405 800Q275 800 190 883T105 1106V1176ZM243 1099Q243 1021 287 971T405 920Q476 920 519 969T563 1103V1176Q563 1254 520
+1305T403 1356T286 1305T243 1172V1099ZM814 357Q814 488 897 572T1112 657T1327 573T1411 350V279Q1411 148 1328 64T1114 -21T899 62T814 285V357ZM952 279Q952 200 996 150T1114 99Q1186 99 1229 148T1272 283V357Q1272 436 1229 486T1112 536Q1041 536 997
+487T952 353V279ZM447 110L342 176L1053 1314L1158 1248L447 110Z" />
+<glyph unicode="&amp;" horiz-adv-x="1273" d="M101 391Q101 496 159 584T383 789Q286 907 253 979T220 1122Q220 1288 318 1382T584 1476Q734 1476 832 1389T930 1168Q930 1080 886 1006T730 849L623 770L947 383Q1015 513 1015 672H1182Q1182 417 1059 249L1267
+0H1045L948 115Q874 49 775 15T572 -20Q359 -20 230 93T101 391ZM572 131Q719 131 841 243L486 668L453 644Q286 521 286 391Q286 273 362 202T572 131ZM405 1128Q405 1032 523 888L641 971Q709 1019 734 1062T759 1168Q759 1235 709 1279T583 1324Q501 1324 453
+1269T405 1128Z" />
+<glyph unicode="&apos;" horiz-adv-x="357" d="M253 1425L232 1057H103L104 1536H253V1425Z" />
+<glyph unicode="(" horiz-adv-x="700" d="M133 591Q133 817 193 1025T374 1403T623 1643L661 1521Q515 1409 422 1179T319 664L318 579Q318 193 459 -91Q544 -261 661 -357L623 -470Q490 -396 369 -222Q133 118 133 591Z" />
+<glyph unicode=")" horiz-adv-x="712" d="M567 581Q567 358 509 154T330 -224T77 -470L38 -357Q192 -239 285 9T381 561V593Q381 803 337 983T215 1307T38 1530L77 1643Q209 1570 328 1399T507 1022T567 581Z" />
+<glyph unicode="*" horiz-adv-x="882" d="M330 983L28 1073L74 1224L376 1112L367 1456H520L510 1107L807 1217L853 1065L546 974L744 703L620 609L434 897L254 616L129 707L330 983Z" />
+<glyph unicode="+" horiz-adv-x="1161" d="M670 781H1076V606H670V146H484V606H78V781H484V1206H670V781Z" />
+<glyph unicode="," horiz-adv-x="402" d="M134 -290L29 -218Q123 -87 127 52V219H308V74Q308 -27 259 -128T134 -290Z" />
+<glyph unicode="-" horiz-adv-x="565" d="M525 543H37V694H525V543Z" />
+<glyph unicode="." horiz-adv-x="539" d="M144 97Q144 145 172 177T258 209T344 177T374 97Q374 51 345 20T258 -11T173 20T144 97Z" />
+<glyph unicode="/" horiz-adv-x="844" d="M177 -125H18L626 1456H784L177 -125Z" />
+<glyph unicode="0" horiz-adv-x="1150" d="M1034 621Q1034 296 923 138T576 -20Q343 -20 231 134T115 596V843Q115 1164 226 1320T574 1476Q809 1476 920 1326T1034 861V621ZM849 874Q849 1109 783 1216T574 1324Q432 1324 367 1217T300 888V592Q300 356 368 244T576
+131Q713 131 779 237T849 571V874Z" />
+<glyph unicode="1" horiz-adv-x="1150" d="M729 0H543V1233L170 1096V1264L700 1463H729V0Z" />
+<glyph unicode="2" horiz-adv-x="1150" d="M1075 0H121V133L625 693Q737 820 779 899T822 1064Q822 1178 753 1251T569 1324Q431 1324 355 1246T278 1027H93Q93 1228 222 1352T569 1476Q772 1476 890 1370T1008 1086Q1008 871 734 574L344 151H1075V0Z" />
+<glyph unicode="3" horiz-adv-x="1150" d="M390 818H529Q660 820 735 887T810 1068Q810 1324 555 1324Q435 1324 364 1256T292 1074H107Q107 1247 233 1361T555 1476Q761 1476 878 1367T995 1064Q995 969 934 880T766 747Q886 709 951 621T1017 406Q1017 210 889
+95T556 -20T223 91T94 384H280Q280 269 355 200T556 131Q690 131 761 201T832 402Q832 529 754 597T529 667H390V818Z" />
+<glyph unicode="4" horiz-adv-x="1150" d="M902 489H1104V338H902V0H716V338H53V447L705 1456H902V489ZM263 489H716V1203L694 1163L263 489Z" />
+<glyph unicode="5" horiz-adv-x="1150" d="M206 730L280 1456H1026V1285H437L393 888Q500 951 636 951Q835 951 952 820T1069 464Q1069 239 948 110T608 -20Q415 -20 293 87T154 383H329Q346 258 418 195T608 131Q737 131 810 219T884 462Q884 608 805 696T593
+785Q472 785 403 732L354 692L206 730Z" />
+<glyph unicode="6" horiz-adv-x="1150" d="M847 1457V1300H813Q597 1296 469 1172T321 823Q436 955 635 955Q825 955 938 821T1052 475Q1052 250 930 115T601 -20Q392 -20 262 140T132 554V625Q132 1027 303 1239T814 1457H847ZM604 801Q509 801 429 744T318 601V533Q318
+353 399 243T601 133Q726 133 797 225T869 466Q869 616 797 708T604 801Z" />
+<glyph unicode="7" horiz-adv-x="1150" d="M1061 1352L458 0H264L865 1304H77V1456H1061V1352Z" />
+<glyph unicode="8" horiz-adv-x="1150" d="M1004 1076Q1004 967 947 882T791 749Q905 700 971 606T1038 393Q1038 204 911 92T575 -20Q365 -20 239 92T112 393Q112 511 176 606T355 750Q258 798 202 883T146 1076Q146 1260 264 1368T575 1476Q767 1476 885 1368T1004
+1076ZM853 397Q853 519 776 596T573 673T373 597T297 397T370 202T575 131Q705 131 779 202T853 397ZM575 1324Q466 1324 399 1257T331 1073Q331 962 397 894T575 825T752 893T819 1073T750 1254T575 1324Z" />
+<glyph unicode="9" horiz-adv-x="1150" d="M830 640Q772 571 692 529T515 487Q389 487 296 549T151 723T100 972Q100 1118 155 1235T313 1414T551 1476Q767 1476 891 1315T1016 874V820Q1016 395 848 200T341 -1H305V155H344Q573 159 696 274T830 640ZM545 640Q638
+640 716 697T831 838V912Q831 1094 752 1208T552 1322Q430 1322 356 1229T282 982Q282 833 353 737T545 640Z" />
+<glyph unicode=":" horiz-adv-x="496" d="M390 97Q390 145 418 177T504 209T590 177T620 97Q620 51 591 20T504 -11T419 20T390 97ZM135 980Q135 1028 163 1060T249 1092T335 1060T365 980Q365 934 336 903T249 872T164 903T135 980Z" />
+<glyph unicode=";" horiz-adv-x="433" d="M111 980Q111 1028 139 1060T225 1092T311 1060T341 980Q341 934 312 903T225 872T140 903T111 980ZM146 -290L41 -218Q135 -87 139 52V219H320V74Q320 -27 271 -128T146 -290Z" />
+<glyph unicode="&lt;" horiz-adv-x="1041" d="M264 644L890 391V195L72 574V720L890 1098V902L264 644Z" />
+<glyph unicode="=" horiz-adv-x="1124" d="M986 814H152V975H986V814ZM986 399H152V559H986V399Z" />
+<glyph unicode="&gt;" horiz-adv-x="1070" d="M795 650L134 909V1099L988 721V575L134 196V388L795 650Z" />
+<glyph unicode="?" horiz-adv-x="967" d="M357 410Q359 529 384 598T486 751L617 886Q701 981 701 1090Q701 1195 646 1254T486 1314Q384 1314 322 1260T260 1115H75Q77 1277 190 1376T486 1476Q675 1476 780 1375T886 1096Q886 921 724 751L615 643Q542 562 542
+410H357ZM349 93Q349 138 376 168T458 199T540 169T568 93T540 19T458 -11T377 18T349 93Z" />
+<glyph unicode="@" horiz-adv-x="1839" d="M1738 502Q1726 260 1618 120T1329 -20Q1142 -20 1089 148Q1035 63 966 22T822 -20Q680 -20 607 96T553 417Q568 582 628 711T784 915T985 989Q1066 989 1130 968T1274 883L1222 329Q1203 98 1350 98Q1463 98 1533 210T1609
+502Q1628 891 1465 1095T967 1299Q766 1299 610 1200T364 912T263 478Q251 230 323 48T542 -231T899 -328Q989 -328 1079 -306T1230 -249L1267 -364Q1205 -403 1103 -428T895 -453Q645 -453 465 -341T196 -17T118 478Q130 753 241 972T542 1311T971 1431Q1220 1431
+1398 1319T1663 996T1738 502ZM712 417Q698 275 738 199T867 123Q927 123 982 174T1074 320L1075 329L1121 832Q1065 861 1001 861Q884 861 808 742T712 417Z" />
+<glyph unicode="A" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538Z" />
+<glyph unicode="B" horiz-adv-x="1275" d="M169 0V1456H645Q882 1456 1001 1358T1121 1068Q1121 966 1063 888T905 766Q1023 733 1091 641T1160 420Q1160 224 1033 112T674 0H169ZM361 681V157H678Q812 157 889 226T967 418Q967 681 681 681H361ZM361 835H651Q777
+835 852 898T928 1069Q928 1189 858 1243T645 1298H361V835Z" />
+<glyph unicode="C" horiz-adv-x="1333" d="M1240 462Q1213 231 1070 106T688 -20Q430 -20 275 165T119 660V800Q119 1003 191 1157T397 1393T705 1476Q937 1476 1077 1347T1240 988H1047Q1022 1162 939 1240T705 1318Q521 1318 417 1182T312 795V654Q312 417 411
+277T688 137Q848 137 933 209T1047 462H1240Z" />
+<glyph unicode="D" horiz-adv-x="1343" d="M169 0V1456H580Q770 1456 916 1372T1141 1133T1222 777V684Q1222 478 1143 323T916 85T572 0H169ZM361 1298V157H563Q785 157 908 295T1032 688V773Q1032 1021 916 1158T585 1298H361Z" />
+<glyph unicode="E" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673Z" />
+<glyph unicode="F" horiz-adv-x="1132" d="M972 643H361V0H169V1456H1071V1298H361V800H972V643Z" />
+<glyph unicode="G" horiz-adv-x="1395" d="M1244 191Q1170 85 1038 33T729 -20Q551 -20 413 63T200 301T122 658V785Q122 1114 275 1295T707 1476Q935 1476 1074 1360T1244 1029H1052Q998 1318 708 1318Q515 1318 416 1183T315 790V671Q315 426 427 282T730 137Q838
+137 919 161T1053 242V569H716V725H1244V191Z" />
+<glyph unicode="H" horiz-adv-x="1460" d="M1288 0H1095V673H361V0H169V1456H361V830H1095V1456H1288V0Z" />
+<glyph unicode="I" horiz-adv-x="557" d="M375 0H183V1456H375V0Z" />
+<glyph unicode="J" horiz-adv-x="1130" d="M779 1456H972V425Q972 216 847 98T512 -20Q295 -20 174 91T53 402H245Q245 277 313 207T512 137Q631 137 704 212T779 422V1456Z" />
+<glyph unicode="K" horiz-adv-x="1284" d="M539 677L361 492V0H169V1456H361V736L1008 1456H1240L667 813L1285 0H1055L539 677Z" />
+<glyph unicode="L" horiz-adv-x="1102" d="M362 157H1052V0H169V1456H362V157Z" />
+<glyph unicode="M" horiz-adv-x="1788" d="M417 1456L893 268L1369 1456H1618V0H1426V567L1444 1179L966 0H819L342 1176L361 567V0H169V1456H417Z" />
+<glyph unicode="N" horiz-adv-x="1460" d="M1288 0H1095L362 1122V0H169V1456H362L1097 329V1456H1288V0Z" />
+<glyph unicode="O" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521 1311
+417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775Z" />
+<glyph unicode="P" horiz-adv-x="1292" d="M361 570V0H169V1456H706Q945 1456 1080 1334T1216 1011Q1216 799 1084 685T704 570H361ZM361 727H706Q860 727 942 799T1024 1009Q1024 1139 942 1217T717 1298H361V727Z" />
+<glyph unicode="Q" horiz-adv-x="1408" d="M1281 681Q1281 470 1214 318T1026 79L1286 -125L1155 -246L848 -2Q776 -20 696 -20Q524 -20 391 64T185 305T109 668V773Q109 983 182 1144T388 1390T694 1476Q870 1476 1003 1391T1209 1147T1281 774V681ZM1089 775Q1089
+1032 987 1171T694 1311Q513 1311 409 1173T301 788V681Q301 431 405 287T696 143T984 278T1089 667V775Z" />
+<glyph unicode="R" horiz-adv-x="1261" d="M703 589H361V0H168V1456H650Q896 1456 1028 1344T1161 1018Q1161 882 1088 781T883 630L1225 12V0H1019L703 589ZM361 746H656Q799 746 883 820T968 1018Q968 1153 888 1225T655 1298H361V746Z" />
+<glyph unicode="S" horiz-adv-x="1215" d="M598 649Q351 720 239 823T126 1079Q126 1251 263 1363T621 1476Q771 1476 888 1418T1070 1258T1135 1035H942Q942 1167 858 1242T621 1318Q479 1318 400 1256T320 1082Q320 993 395 932T652 819T936 707T1088 563T1138
+370Q1138 193 1000 87T631 -20Q481 -20 351 37T151 195T80 422H273Q273 290 370 214T631 137Q783 137 864 199T945 368T870 533T598 649Z" />
+<glyph unicode="T" horiz-adv-x="1222" d="M1175 1298H707V0H516V1298H49V1456H1175V1298Z" />
+<glyph unicode="U" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194Z" />
+<glyph unicode="V" horiz-adv-x="1303" d="M651 255L1067 1456H1277L737 0H567L28 1456H237L651 255Z" />
+<glyph unicode="W" horiz-adv-x="1817" d="M483 459L511 267L552 440L840 1456H1002L1283 440L1323 264L1354 460L1580 1456H1773L1420 0H1245L945 1061L922 1172L899 1061L588 0H413L61 1456H253L483 459Z" />
+<glyph unicode="X" horiz-adv-x="1284" d="M644 898L993 1456H1219L759 734L1230 0H1002L644 568L284 0H57L529 734L68 1456H293L644 898Z" />
+<glyph unicode="Y" horiz-adv-x="1230" d="M613 725L993 1456H1211L709 543V0H517V543L15 1456H235L613 725Z" />
+<glyph unicode="Z" horiz-adv-x="1226" d="M313 157H1146V0H86V144L884 1298H99V1456H1114V1315L313 157Z" />
+<glyph unicode="[" horiz-adv-x="543" d="M523 1512H332V-160H523V-312H146V1664H523V1512Z" />
+<glyph unicode="\" horiz-adv-x="840" d="M40 1456H216L824 -125H648L40 1456Z" />
+<glyph unicode="]" horiz-adv-x="543" d="M9 1664H387V-312H9V-160H202V1512H9V1664Z" />
+<glyph unicode="^" horiz-adv-x="856" d="M426 1211L236 729H64L363 1456H490L788 729H617L426 1211Z" />
+<glyph unicode="_" horiz-adv-x="924" d="M920 -151H4V0H920V-151Z" />
+<glyph unicode="`" horiz-adv-x="633" d="M474 1240H315L57 1534H280L474 1240Z" />
+<glyph unicode="a" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964
+751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141Z" />
+<glyph unicode="b" horiz-adv-x="1149" d="M1056 529Q1056 281 942 131T636 -20Q431 -20 319 125L310 0H140V1536H325V963Q437 1102 634 1102T943 953T1056 545V529ZM871 550Q871 739 798 842T588 945Q405 945 325 775V307Q410 137 590 137Q723 137 797 240T871 550Z" />
+<glyph unicode="c" horiz-adv-x="1072" d="M574 131Q673 131 747 191T829 341H1004Q999 248 940 164T783 30T574 -20Q353 -20 223 127T92 531V562Q92 720 150 843T316 1034T573 1102Q755 1102 875 993T1004 710H829Q821 815 750 882T573 950Q432 950 355 849T277
+555V520Q277 333 354 232T574 131Z" />
+<glyph unicode="d" horiz-adv-x="1155" d="M95 550Q95 799 213 950T522 1102Q712 1102 823 972V1536H1008V0H838L829 116Q718 -20 520 -20Q332 -20 214 134T95 536V550ZM280 529Q280 345 356 241T566 137Q742 137 823 295V792Q740 945 568 945Q432 945 356 840T280 529Z" />
+<glyph unicode="e" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378 869T284
+640H826V654Q818 795 750 872T566 950Z" />
+<glyph unicode="f" horiz-adv-x="711" d="M231 0V939H60V1082H231V1193Q231 1367 324 1462T587 1557Q651 1557 714 1540L704 1390Q657 1399 604 1399Q514 1399 465 1347T416 1196V1082H647V939H416V0H231Z" />
+<glyph unicode="g" horiz-adv-x="1149" d="M96 550Q96 803 213 952T523 1102Q721 1102 832 962L841 1082H1010V26Q1010 -184 886 -305T551 -426Q434 -426 322 -376T151 -239L247 -128Q366 -275 538 -275Q673 -275 748 -199T824 15V108Q713 -20 521 -20Q331 -20
+214 133T96 550ZM282 529Q282 346 357 242T567 137Q742 137 824 296V790Q739 945 569 945Q434 945 358 840T282 529Z" />
+<glyph unicode="h" horiz-adv-x="1128" d="M325 951Q448 1102 645 1102Q988 1102 991 715V0H806V716Q805 833 753 889T589 945Q499 945 431 897T325 771V0H140V1536H325V951Z" />
+<glyph unicode="i" horiz-adv-x="497" d="M341 0H156V1082H341V0ZM141 1369Q141 1414 168 1445T250 1476T332 1445T360 1369T332 1294T250 1264T169 1294T141 1369Z" />
+<glyph unicode="j" horiz-adv-x="489" d="M331 1082V-125Q331 -437 48 -437Q-13 -437 -65 -419V-271Q-33 -279 19 -279Q81 -279 113 -246T146 -129V1082H331ZM127 1369Q127 1413 154 1444T235 1476Q289 1476 317 1445T345 1369T317 1294T235 1264T154 1294T127 1369Z" />
+<glyph unicode="k" horiz-adv-x="1038" d="M442 501L326 380V0H141V1536H326V607L425 726L762 1082H987L566 630L1036 0H819L442 501Z" />
+<glyph unicode="l" horiz-adv-x="497" d="M341 0H156V1536H341V0Z" />
+<glyph unicode="m" horiz-adv-x="1795" d="M314 1082L319 962Q438 1102 640 1102Q867 1102 949 928Q1003 1006 1089 1054T1294 1102Q1650 1102 1656 725V0H1471V714Q1471 830 1418 887T1240 945Q1137 945 1069 884T990 718V0H804V709Q804 945 573 945Q391 945
+324 790V0H139V1082H314Z" />
+<glyph unicode="n" horiz-adv-x="1130" d="M315 1082L321 946Q445 1102 645 1102Q988 1102 991 715V0H806V716Q805 833 753 889T589 945Q499 945 431 897T325 771V0H140V1082H315Z" />
+<glyph unicode="o" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729 807
+839T582 950Q445 950 361 841T277 529Z" />
+<glyph unicode="p" horiz-adv-x="1149" d="M1054 529Q1054 282 941 131T635 -20Q438 -20 325 105V-416H140V1082H309L318 962Q431 1102 632 1102Q827 1102 940 955T1054 546V529ZM869 550Q869 733 791 839T577 945Q409 945 325 796V279Q408 131 579 131Q712 131
+790 236T869 550Z" />
+<glyph unicode="q" horiz-adv-x="1164" d="M95 550Q95 805 212 953T526 1102Q718 1102 829 973L837 1082H1007V-416H822V100Q710 -20 524 -20Q328 -20 212 132T95 537V550ZM280 529Q280 343 358 237T570 131Q735 131 822 277V807Q734 950 572 950Q438 950 359
+844T280 529Z" />
+<glyph unicode="r" horiz-adv-x="693" d="M663 916Q621 923 572 923Q390 923 325 768V0H140V1082H320L323 957Q414 1102 581 1102Q635 1102 663 1088V916Z" />
+<glyph unicode="s" horiz-adv-x="1056" d="M770 287Q770 362 714 403T517 475T294 547T172 647T132 785Q132 918 244 1010T532 1102Q716 1102 830 1007T945 764H759Q759 840 695 895T532 950Q431 950 374 906T317 791Q317 724 370 690T561 625T786 551T913 448T955
+300Q955 155 839 68T538 -20Q408 -20 308 26T152 154T95 333H280Q285 240 354 186T538 131Q643 131 706 173T770 287Z" />
+<glyph unicode="t" horiz-adv-x="669" d="M391 1344V1082H593V939H391V268Q391 203 418 171T510 138Q542 138 598 150V0Q525 -20 456 -20Q332 -20 269 55T206 268V939H9V1082H206V1344H391Z" />
+<glyph unicode="u" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107Z" />
+<glyph unicode="v" horiz-adv-x="992" d="M497 251L765 1082H954L566 0H425L33 1082H222L497 251Z" />
+<glyph unicode="w" horiz-adv-x="1539" d="M1098 255L1306 1082H1491L1176 0H1026L763 820L507 0H357L43 1082H227L440 272L692 1082H841L1098 255Z" />
+<glyph unicode="x" horiz-adv-x="1015" d="M503 687L743 1082H959L605 547L970 0H756L506 405L256 0H41L406 547L52 1082H266L503 687Z" />
+<glyph unicode="y" horiz-adv-x="969" d="M494 271L746 1082H944L509 -167Q408 -437 188 -437L153 -434L84 -421V-271L134 -275Q228 -275 280 -237T367 -98L408 12L22 1082H224L494 271Z" />
+<glyph unicode="z" horiz-adv-x="1015" d="M314 151H947V0H88V136L685 929H97V1082H917V951L314 151Z" />
+<glyph unicode="{" horiz-adv-x="693" d="M632 -366Q455 -316 366 -202T276 101V300Q276 543 64 543V688Q276 688 276 930V1138Q278 1321 365 1433T632 1597L670 1482Q461 1415 461 1133V931Q461 704 294 615Q461 525 461 296V90Q464 -185 670 -251L632 -366Z" />
+<glyph unicode="|" horiz-adv-x="499" d="M324 -270H175V1456H324V-270Z" />
+<glyph unicode="}" horiz-adv-x="693" d="M19 -251Q222 -186 229 80V300Q229 531 410 615Q229 697 229 930V1133Q229 1415 20 1482L58 1597Q235 1547 324 1435T414 1137V927Q414 688 626 688V543Q414 543 414 300V98Q414 -90 324 -203T58 -366L19 -251Z" />
+<glyph unicode="~" horiz-adv-x="1393" d="M1263 777Q1263 619 1170 511T939 402Q867 402 803 428T655 529T533 621T454 639Q376 639 334 586T292 438L131 436Q131 596 223 699T454 802Q530 802 600 770T758 658T910 567L939 565Q1015 565 1062 623T1110 776L1263 777Z" />
+<glyph unicode="&#xa0;" horiz-adv-x="507" />
+<glyph unicode="&#xa1;" horiz-adv-x="499" d="M170 684H338L351 -360H157L170 684ZM358 996Q358 951 331 920T249 889T167 920T139 996T167 1071T249 1101T330 1071T358 996Z" />
+<glyph unicode="&#xa2;" horiz-adv-x="1120" d="M586 131Q686 131 760 191T842 341H1017Q1011 215 912 115T669 -12V-245H484V-11Q305 23 205 165T105 527V562Q105 774 206 916T484 1092V1318H669V1095Q819 1072 915 966T1017 710H842Q834 815 763 882T586 950Q445
+950 368 849T290 555V520Q290 333 367 232T586 131Z" />
+<glyph unicode="&#xa3;" horiz-adv-x="1190" d="M449 622L457 402Q457 248 395 157H1128L1127 0H95V157H172Q212 166 237 231T264 393V401L256 622H91V779H251L242 1039Q242 1238 364 1357T687 1476Q877 1476 988 1370T1099 1087H908Q908 1194 845 1256T670 1318Q565
+1318 500 1241T435 1039L444 779H763V622H449Z" />
+<glyph unicode="&#xa4;" horiz-adv-x="1460" d="M1103 112Q944 -20 735 -20Q528 -20 369 110L235 -26L105 109L244 250Q140 406 140 608Q140 814 252 977L105 1128L235 1264L382 1114Q540 1234 735 1234Q931 1234 1090 1113L1239 1265L1371 1128L1220 974Q1330
+811 1330 608Q1330 412 1228 253L1371 109L1239 -27L1103 112ZM311 608Q311 485 368 379T524 212T735 151T946 212T1100 379T1157 608Q1157 730 1101 835T946 1001T735 1062Q622 1062 524 1002T369 836T311 608Z" />
+<glyph unicode="&#xa5;" horiz-adv-x="1240" d="M614 782L978 1456H1197L779 736H1091V611H707V446H1091V322H707V0H514V322H136V446H514V611H136V736H449L31 1456H251L614 782Z" />
+<glyph unicode="&#xa6;" horiz-adv-x="491" d="M147 -270V521H333V-270H147ZM333 698H147V1456H333V698Z" />
+<glyph unicode="&#xa7;" horiz-adv-x="1256" d="M1145 431Q1145 242 959 157Q1028 108 1064 40T1100 -128Q1100 -296 970 -395T612 -495Q500 -495 400 -467T229 -382Q90 -269 90 -64L276 -62Q276 -192 366 -267T612 -343Q748 -343 831 -285T914 -130Q914 -41 843
+11T563 126Q381 174 285 229T143 362T96 551Q96 737 278 825Q212 874 177 942T141 1110Q141 1276 274 1376T630 1476Q862 1476 992 1363T1122 1045H937Q937 1170 853 1247T630 1325Q488 1325 408 1268T327 1112Q327 1043 355 1003T450 931T661 858T889 782T1030
+698T1116 585T1145 431ZM602 691Q512 715 437 742Q357 723 320 673T282 553Q282 483 309 443T402 370T611 296T797 238Q875 258 917 308T959 428Q959 516 890 570T602 691Z" />
+<glyph unicode="&#xa8;" horiz-adv-x="856" d="M102 1371Q102 1416 129 1446T211 1477T293 1447T321 1371T293 1296T211 1266T130 1296T102 1371ZM532 1369Q532 1414 559 1445T641 1476T723 1445T751 1369T723 1294T641 1264T560 1294T532 1369Z" />
+<glyph unicode="&#xa9;" horiz-adv-x="1609" d="M1119 597Q1119 444 1033 364T788 283Q631 283 537 388T442 676V786Q442 962 537 1067T788 1173Q948 1173 1034 1091T1120 860H974Q974 959 927 1001T788 1044Q694 1044 640 975T586 783V670Q586 550 640 481T788
+412Q880 412 926 454T973 597H1119ZM206 729Q206 557 286 411T503 181T801 98T1098 181T1315 410T1395 729Q1395 899 1316 1044T1100 1272T801 1356Q641 1356 503 1274T286 1045T206 729ZM91 729Q91 931 184 1104T443 1376T801 1476T1158 1377T1416 1104T1510 729Q1510
+532 1420 360T1165 84T801 -21Q604 -21 439 82T182 358T91 729Z" />
+<glyph unicode="&#xaa;" horiz-adv-x="915" d="M618 705Q606 739 600 777Q524 691 396 691Q277 691 212 753T147 918Q147 1029 230 1089T486 1149H594V1201Q594 1336 470 1336Q401 1336 362 1309T322 1231L161 1243Q161 1346 247 1411T470 1476Q603 1476 680 1405T757
+1199V883Q757 786 783 705H618ZM435 828Q478 828 522 848T594 895V1037H482Q399 1036 355 1005T310 922Q310 828 435 828Z" />
+<glyph unicode="&#xab;" horiz-adv-x="961" d="M536 804L794 407H653L358 795V814L653 1203H794L536 804ZM610 548L868 151H727L432 539V558L727 947H868L610 548Z" />
+<glyph unicode="&#xac;" horiz-adv-x="1134" d="M958 375H772V639H127V800H958V375Z" />
+<glyph unicode="&#xad;" horiz-adv-x="565" d="M525 543H37V694H525V543Z" />
+<glyph unicode="&#xae;" horiz-adv-x="1610" d="M90 729Q90 931 183 1104T442 1376T800 1476T1157 1377T1415 1104T1509 729Q1509 532 1419 360T1164 84T800 -21Q603 -21 438 82T181 358T90 729ZM205 729Q205 557 285 411T502 181T800 98Q961 98 1099 182T1315
+412T1394 729Q1394 900 1316 1044T1099 1272T800 1356Q640 1356 502 1274T285 1045T205 729ZM653 654V316H512V1165H788Q941 1165 1025 1100T1110 909Q1110 786 982 721Q1104 671 1105 517V456Q1105 370 1122 332V316H977Q963 352 963 444T960 554Q944 650 829
+654H653ZM653 782H809Q881 784 925 817T969 904Q969 977 930 1007T791 1038H653V782Z" />
+<glyph unicode="&#xaf;" horiz-adv-x="938" d="M834 1313H120V1456H834V1313Z" />
+<glyph unicode="&#xb0;" horiz-adv-x="765" d="M130 1216Q130 1320 204 1398T385 1476Q489 1476 562 1399T636 1216Q636 1110 563 1035T385 960Q280 960 205 1035T130 1216ZM385 1088Q439 1088 476 1123T513 1216Q513 1274 476 1311T385 1349Q330 1349 293 1310T255
+1216T292 1125T385 1088Z" />
+<glyph unicode="&#xb1;" horiz-adv-x="1094" d="M649 854H1013V703H649V289H482V703H97V854H482V1267H649V854ZM970 0H135V152H970V0Z" />
+<glyph unicode="&#xb2;" horiz-adv-x="751" d="M683 667H84V775L384 1057Q493 1159 493 1228Q493 1277 461 1307T369 1338Q294 1338 259 1300T223 1205H66Q66 1319 149 1393T365 1467T574 1404T651 1230Q651 1126 544 1019L460 940L284 795H683V667Z" />
+<glyph unicode="&#xb3;" horiz-adv-x="751" d="M265 1125H349Q423 1125 459 1155T495 1234Q495 1279 464 1308T362 1337Q305 1337 268 1312T230 1245H73Q73 1343 154 1404T360 1466Q497 1466 575 1406T653 1241Q653 1186 618 1141T517 1070Q666 1029 666 886Q666
+780 581 718T360 655Q228 655 145 718T62 888H220Q220 843 259 813T366 783Q436 783 472 813T509 894Q509 1007 353 1009H265V1125Z" />
+<glyph unicode="&#xb4;" horiz-adv-x="642" d="M316 1534H540L272 1240H123L316 1534Z" />
+<glyph unicode="&#xb5;" horiz-adv-x="1160" d="M339 1082V449Q340 286 391 208T559 130Q758 130 820 282V1082H1006V0H839L830 115Q737 -20 567 -20Q420 -20 339 53V-416H154V1082H339Z" />
+<glyph unicode="&#xb6;" horiz-adv-x="1001" d="M646 0V520H562Q332 520 200 647T67 988Q67 1201 200 1328T563 1456H832V0H646Z" />
+<glyph unicode="&#xb7;" horiz-adv-x="534" d="M147 729Q147 777 175 809T261 841T347 809T377 729Q377 682 348 651T261 619T176 650T147 729Z" />
+<glyph unicode="&#xb8;" horiz-adv-x="507" d="M285 0L273 -52Q426 -79 426 -225Q426 -322 346 -378T123 -435L116 -328Q195 -328 238 -302T282 -229Q282 -185 250 -164T120 -134L152 0H285Z" />
+<glyph unicode="&#xb9;" horiz-adv-x="751" d="M495 674H338V1275L122 1218V1346L477 1463H495V674Z" />
+<glyph unicode="&#xba;" horiz-adv-x="931" d="M122 1123Q122 1281 216 1378T464 1476Q619 1476 713 1380T807 1117V1043Q807 884 714 787T466 690T217 787T122 1049V1123ZM285 1043Q285 943 333 886T466 829Q549 829 596 886T644 1045V1123Q644 1222 596 1279T464
+1336Q383 1336 335 1281T285 1129V1043Z" />
+<glyph unicode="&#xbb;" horiz-adv-x="960" d="M244 949L539 560V541L244 152H102L360 550L102 949H244ZM593 949L888 560V541L593 152H451L709 550L451 949H593Z" />
+<glyph unicode="&#xbc;" horiz-adv-x="1500" d="M458 664H301V1265L85 1208V1336L440 1453H458V664ZM443 118L339 184L1050 1322L1154 1256L443 118ZM1318 299H1425V169H1318V0H1161V169H786L780 271L1157 789H1318V299ZM938 299H1161V588L1144 560L938 299Z" />
+<glyph unicode="&#xbd;" horiz-adv-x="1589" d="M399 118L295 184L1006 1322L1110 1256L399 118ZM453 664H296V1265L80 1208V1336L435 1453H453V664ZM1481 0H882V108L1182 390Q1291 492 1291 561Q1291 610 1259 640T1167 671Q1092 671 1057 633T1021 538H864Q864
+652 947 726T1163 800T1372 737T1449 563Q1449 459 1342 352L1258 273L1082 128H1481V0Z" />
+<glyph unicode="&#xbe;" horiz-adv-x="1593" d="M570 118L466 184L1177 1322L1281 1256L570 118ZM1410 299H1517V169H1410V0H1253V169H878L872 271L1249 789H1410V299ZM1030 299H1253V588L1236 560L1030 299ZM314 1126H398Q472 1126 508 1156T544 1235Q544 1280
+513 1309T411 1338Q354 1338 317 1313T279 1246H122Q122 1344 203 1405T409 1467Q546 1467 624 1407T702 1242Q702 1187 667 1142T566 1071Q715 1030 715 887Q715 781 630 719T409 656Q277 656 194 719T111 889H269Q269 844 308 814T415 784Q485 784 521 814T558
+895Q558 1008 402 1010H314V1126Z" />
+<glyph unicode="&#xbf;" horiz-adv-x="969" d="M588 680Q587 574 567 511T498 388T358 233T255 37L253 0Q253 -109 311 -166T478 -224Q578 -224 640 -168T703 -20H888Q886 -181 774 -283T478 -385Q282 -385 175 -285T68 -5Q68 168 228 343L337 456Q403 534 403
+680H588ZM596 997Q596 952 569 921T487 890T405 921T377 997Q377 1041 405 1071T487 1101T568 1071T596 997Z" />
+<glyph unicode="&#xc0;" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM778 1550H619L361 1844H584L778 1550Z" />
+<glyph unicode="&#xc1;" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM763 1844H987L719 1550H570L763 1844Z" />
+<glyph unicode="&#xc2;" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM975 1572V1562H822L672 1732L523 1562H370V1574L616 1846H728L975 1572Z" />
+<glyph unicode="&#xc3;" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM1027 1814Q1027 1706 966 1639T812 1572Q771 1572 741 1582T663 1623T593 1660T543 1667Q502 1667 473 1636T444 1555L320
+1562Q320 1669 380 1739T534 1809Q569 1809 597 1799T673 1760T746 1722T803 1713Q846 1713 874 1747T903 1826L1027 1814Z" />
+<glyph unicode="&#xc4;" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM351 1681Q351 1726 378 1756T460 1787T542 1757T570 1681T542 1606T460 1576T379 1606T351 1681ZM781 1679Q781 1724
+808 1755T890 1786T972 1755T1000 1679T972 1604T890 1574T809 1604T781 1679Z" />
+<glyph unicode="&#xc5;" horiz-adv-x="1336" d="M973 380H363L226 0H28L584 1456H752L1309 0H1112L973 380ZM421 538H916L668 1219L421 538ZM887 1729Q887 1642 825 1584T672 1525Q580 1525 519 1584T457 1729T518 1876T672 1937T825 1876T887 1729ZM556 1729Q556
+1682 589 1648T672 1614Q720 1614 754 1647T788 1729T755 1812T672 1847Q622 1847 589 1812T556 1729Z" />
+<glyph unicode="&#xc6;" horiz-adv-x="1914" d="M1879 0H996L981 353H417L212 0H-14L866 1456H1817V1304H1126L1146 833H1736V682H1152L1174 151H1879V0ZM518 527H974L943 1260L518 527Z" />
+<glyph unicode="&#xc7;" horiz-adv-x="1333" d="M1240 462Q1213 231 1070 106T688 -20Q430 -20 275 165T119 660V800Q119 1003 191 1157T397 1393T705 1476Q937 1476 1077 1347T1240 988H1047Q1022 1162 939 1240T705 1318Q521 1318 417 1182T312 795V654Q312
+417 411 277T688 137Q848 137 933 209T1047 462H1240ZM751 -9L739 -61Q892 -88 892 -234Q892 -331 812 -387T589 -444L582 -337Q661 -337 704 -311T748 -238Q748 -194 716 -173T586 -143L618 -9H751Z" />
+<glyph unicode="&#xc8;" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM725 1562H566L308 1856H531L725 1562Z" />
+<glyph unicode="&#xc9;" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM710 1856H934L666 1562H517L710 1856Z" />
+<glyph unicode="&#xca;" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM922 1584V1574H769L619 1744L470 1574H317V1586L563 1858H675L922 1584Z" />
+<glyph unicode="&#xcb;" horiz-adv-x="1164" d="M992 673H361V157H1094V0H169V1456H1084V1298H361V830H992V673ZM298 1693Q298 1738 325 1768T407 1799T489 1769T517 1693T489 1618T407 1588T326 1618T298 1693ZM728 1691Q728 1736 755 1767T837 1798T919 1767T947
+1691T919 1616T837 1586T756 1616T728 1691Z" />
+<glyph unicode="&#xcc;" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM385 1562H226L-32 1856H191L385 1562Z" />
+<glyph unicode="&#xcd;" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM369 1856H593L325 1562H176L369 1856Z" />
+<glyph unicode="&#xce;" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM582 1584V1574H429L279 1744L130 1574H-23V1586L223 1858H335L582 1584Z" />
+<glyph unicode="&#xcf;" horiz-adv-x="557" d="M375 0H183V1456H375V0ZM-42 1693Q-42 1738 -15 1768T67 1799T149 1769T177 1693T149 1618T67 1588T-14 1618T-42 1693ZM388 1691Q388 1736 415 1767T497 1798T579 1767T607 1691T579 1616T497 1586T416 1616T388 1691Z" />
+<glyph unicode="&#xd0;" horiz-adv-x="1373" d="M199 0V666H37V817H199V1456H610Q800 1456 946 1372T1171 1133T1252 777V684Q1252 478 1173 323T946 85T602 0H199ZM673 666H391V157H592Q814 157 937 294T1062 680V773Q1062 1021 946 1158T615 1298H391V817H673V666Z" />
+<glyph unicode="&#xd1;" horiz-adv-x="1460" d="M1288 0H1095L362 1122V0H169V1456H362L1097 329V1456H1288V0ZM1081 1814Q1081 1706 1020 1639T866 1572Q825 1572 795 1582T717 1623T647 1660T597 1667Q556 1667 527 1636T498 1555L374 1562Q374 1669 434 1739T588
+1809Q623 1809 651 1799T727 1760T800 1722T857 1713Q900 1713 928 1747T957 1826L1081 1814Z" />
+<glyph unicode="&#xd2;" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521
+1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM812 1552H653L395 1846H618L812 1552Z" />
+<glyph unicode="&#xd3;" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521
+1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM797 1846H1021L753 1552H604L797 1846Z" />
+<glyph unicode="&#xd4;" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521
+1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM1009 1574V1564H856L706 1734L557 1564H404V1576L650 1848H762L1009 1574Z" />
+<glyph unicode="&#xd5;" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521
+1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM1061 1816Q1061 1708 1000 1641T846 1574Q805 1574 775 1584T697 1625T627 1662T577 1669Q536 1669 507 1638T478 1557L354 1564Q354 1671 414 1741T568 1811Q603 1811 631 1801T707
+1762T780 1724T837 1715Q880 1715 908 1749T937 1828L1061 1816Z" />
+<glyph unicode="&#xd6;" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q533 -20 400 64T194 305T118 668V773Q118 983 191 1144T397 1390T703 1476Q878 1476 1011 1392T1217 1147T1289 773V681ZM1098 775Q1098 1034 994 1172T703 1311Q521
+1311 417 1173T309 788V681Q309 430 414 287T705 143Q891 143 993 278T1098 667V775ZM385 1683Q385 1728 412 1758T494 1789T576 1759T604 1683T576 1608T494 1578T413 1608T385 1683ZM815 1681Q815 1726 842 1757T924 1788T1006 1757T1034 1681T1006 1606T924
+1576T843 1606T815 1681Z" />
+<glyph unicode="&#xd7;" horiz-adv-x="1092" d="M89 329L419 665L91 1000L210 1123L539 788L868 1123L987 1000L659 665L989 329L870 206L539 543L208 206L89 329Z" />
+<glyph unicode="&#xd8;" horiz-adv-x="1408" d="M1289 681Q1289 467 1217 308T1013 64T705 -20Q534 -20 403 62L306 -93H164L308 138Q118 330 118 690V773Q118 983 191 1144T397 1390T703 1476Q917 1476 1065 1351L1168 1516H1309L1150 1261Q1287 1074 1289 780V681ZM309
+681Q309 437 407 296L971 1200Q869 1311 703 1311Q521 1311 417 1173T309 788V681ZM1098 775Q1098 957 1042 1088L493 207Q584 143 705 143Q891 143 993 278T1098 667V775Z" />
+<glyph unicode="&#xd9;" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM773 1550H614L356 1844H579L773 1550Z" />
+<glyph unicode="&#xda;" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM758 1844H982L714 1550H565L758 1844Z" />
+<glyph unicode="&#xdb;" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM970 1572V1562H817L667 1732L518 1562H365V1574L611
+1846H723L970 1572Z" />
+<glyph unicode="&#xdc;" horiz-adv-x="1328" d="M1194 1456V466Q1193 260 1065 129T716 -18L665 -20Q426 -20 284 109T140 464V1456H330V470Q330 312 417 225T665 137Q828 137 914 224T1001 469V1456H1194ZM346 1681Q346 1726 373 1756T455 1787T537 1757T565
+1681T537 1606T455 1576T374 1606T346 1681ZM776 1679Q776 1724 803 1755T885 1786T967 1755T995 1679T967 1604T885 1574T804 1604T776 1679Z" />
+<glyph unicode="&#xdd;" horiz-adv-x="1230" d="M613 725L993 1456H1211L709 543V0H517V543L15 1456H235L613 725ZM708 1844H932L664 1550H515L708 1844Z" />
+<glyph unicode="&#xde;" horiz-adv-x="1210" d="M352 1456V1163H631Q778 1163 888 1111T1057 961T1117 738Q1117 544 985 429T626 313H352V0H166V1456H352ZM352 1011V465H629Q771 465 851 540T931 736Q931 859 851 934T635 1011H352Z" />
+<glyph unicode="&#xdf;" horiz-adv-x="1218" d="M324 0H139V1111Q139 1319 242 1436T532 1554Q712 1554 810 1465T909 1216Q909 1091 845 990T781 819Q781 768 818 721T950 601T1087 461T1130 317Q1130 158 1029 69T745 -20Q664 -20 574 2T445 52L488 207Q537
+175 604 153T725 131Q832 131 888 178T945 307Q945 359 908 407T777 528T639 671T595 821Q595 910 664 1013T734 1201Q734 1295 682 1348T542 1402Q324 1402 324 1109V0Z" />
+<glyph unicode="&#xe0;" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964
+751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM687 1240H528L270 1534H493L687 1240Z" />
+<glyph unicode="&#xe1;" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964
+751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM672 1534H896L628 1240H479L672 1534Z" />
+<glyph unicode="&#xe2;" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964
+751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM884 1262V1252H731L581 1422L432 1252H279V1264L525 1536H637L884 1262Z" />
+<glyph unicode="&#xe3;" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964
+751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM936 1504Q936 1396 875 1329T721 1262Q680 1262 650 1272T572 1313T502 1350T452 1357Q411 1357 382 1326T353 1245L229 1252Q229 1359 289
+1429T443 1499Q478 1499 506 1489T582 1450T655 1412T712 1403Q755 1403 783 1437T812 1516L936 1504Z" />
+<glyph unicode="&#xe4;" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964
+751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM260 1371Q260 1416 287 1446T369 1477T451 1447T479 1371T451 1296T369 1266T288 1296T260 1371ZM690 1369Q690 1414 717 1445T799 1476T881
+1445T909 1369T881 1294T799 1264T718 1294T690 1369Z" />
+<glyph unicode="&#xe5;" horiz-adv-x="1114" d="M808 0Q792 32 782 114Q653 -20 474 -20Q314 -20 212 70T109 300Q109 469 237 562T599 656H779V741Q779 838 721 895T550 953Q451 953 384 903T317 782H131Q131 863 188 938T344 1058T561 1102Q748 1102 854 1009T964
+751V253Q964 104 1002 16V0H808ZM501 141Q588 141 666 186T779 303V525H634Q294 525 294 326Q294 239 352 190T501 141ZM796 1419Q796 1332 734 1274T581 1215Q489 1215 428 1274T366 1419T427 1566T581 1627T734 1566T796 1419ZM465 1419Q465 1372 498 1338T581
+1304Q629 1304 663 1337T697 1419T664 1502T581 1537Q531 1537 498 1502T465 1419Z" />
+<glyph unicode="&#xe6;" horiz-adv-x="1729" d="M1262 -20Q1001 -20 865 160Q800 74 687 27T433 -20Q266 -20 172 66T78 304Q78 461 191 548T526 635H749V720Q749 827 694 888T535 950Q430 950 360 895T290 759L106 778Q106 921 227 1011T535 1102Q650 1102 738
+1061T876 936Q939 1015 1026 1058T1218 1102Q1428 1102 1544 974T1660 612V497H932Q939 321 1026 226T1262 130Q1410 130 1531 206L1578 237L1642 101Q1484 -20 1262 -20ZM469 130Q541 130 620 167T749 258V495H521Q404 493 334 438T264 300Q264 223 317 177T469
+130ZM1218 950Q1103 950 1029 865T937 640H1475V671Q1475 803 1408 876T1218 950Z" />
+<glyph unicode="&#xe7;" horiz-adv-x="1072" d="M574 131Q673 131 747 191T829 341H1004Q999 248 940 164T783 30T574 -20Q353 -20 223 127T92 531V562Q92 720 150 843T316 1034T573 1102Q755 1102 875 993T1004 710H829Q821 815 750 882T573 950Q432 950 355
+849T277 555V520Q277 333 354 232T574 131ZM604 -9L592 -61Q745 -88 745 -234Q745 -331 665 -387T442 -444L435 -337Q514 -337 557 -311T601 -238Q601 -194 569 -173T439 -143L471 -9H604Z" />
+<glyph unicode="&#xe8;" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378
+869T284 640H826V654Q818 795 750 872T566 950ZM671 1240H512L254 1534H477L671 1240Z" />
+<glyph unicode="&#xe9;" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378
+869T284 640H826V654Q818 795 750 872T566 950ZM656 1534H880L612 1240H463L656 1534Z" />
+<glyph unicode="&#xea;" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378
+869T284 640H826V654Q818 795 750 872T566 950ZM868 1262V1252H715L565 1422L416 1252H263V1264L509 1536H621L868 1262Z" />
+<glyph unicode="&#xeb;" horiz-adv-x="1085" d="M589 -20Q369 -20 231 124T93 511V545Q93 706 154 832T326 1030T566 1102Q777 1102 894 963T1011 565V488H278Q282 328 371 230T599 131Q697 131 765 171T884 277L997 189Q861 -20 589 -20ZM566 950Q454 950 378
+869T284 640H826V654Q818 795 750 872T566 950ZM244 1371Q244 1416 271 1446T353 1477T435 1447T463 1371T435 1296T353 1266T272 1296T244 1371ZM674 1369Q674 1414 701 1445T783 1476T865 1445T893 1369T865 1294T783 1264T702 1294T674 1369Z" />
+<glyph unicode="&#xec;" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM615 1495H456L198 1789H421L615 1495Z" />
+<glyph unicode="&#xed;" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM343 1789H567L299 1495H150L343 1789Z" />
+<glyph unicode="&#xee;" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM556 1261V1251H403L253 1421L104 1251H-49V1263L197 1535H309L556 1261Z" />
+<glyph unicode="&#xef;" horiz-adv-x="506" d="M341 0H155V1082H341V0ZM-68 1370Q-68 1415 -41 1445T41 1476T123 1446T151 1370T123 1295T41 1265T-40 1295T-68 1370ZM362 1368Q362 1413 389 1444T471 1475T553 1444T581 1368T553 1293T471 1263T390 1293T362 1368Z" />
+<glyph unicode="&#xf0;" horiz-adv-x="1200" d="M820 1301Q1069 1037 1069 628V535Q1069 377 1011 251T844 52T602 -20Q467 -20 357 44T187 221T126 467Q126 614 182 730T341 912T574 977Q737 977 858 863Q810 1058 669 1199L451 1051L378 1150L570 1281Q438 1372
+255 1421L312 1580Q551 1526 726 1387L915 1516L988 1416L820 1301ZM884 635L882 691Q849 752 780 788T618 825Q473 825 392 730T311 467Q311 327 394 229T606 131Q731 131 807 244T884 541V635Z" />
+<glyph unicode="&#xf1;" horiz-adv-x="1130" d="M315 1082L321 946Q445 1102 645 1102Q988 1102 991 715V0H806V716Q805 833 753 889T589 945Q499 945 431 897T325 771V0H140V1082H315ZM927 1504Q927 1396 866 1329T712 1262Q671 1262 641 1272T563 1313T493 1350T443
+1357Q402 1357 373 1326T344 1245L220 1252Q220 1359 280 1429T434 1499Q469 1499 497 1489T573 1450T646 1412T703 1403Q746 1403 774 1437T803 1516L927 1504Z" />
+<glyph unicode="&#xf2;" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729
+807 839T582 950Q445 950 361 841T277 529ZM681 1240H522L264 1534H487L681 1240Z" />
+<glyph unicode="&#xf3;" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729
+807 839T582 950Q445 950 361 841T277 529ZM666 1534H890L622 1240H473L666 1534Z" />
+<glyph unicode="&#xf4;" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729
+807 839T582 950Q445 950 361 841T277 529ZM878 1262V1252H725L575 1422L426 1252H273V1264L519 1536H631L878 1262Z" />
+<glyph unicode="&#xf5;" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729
+807 839T582 950Q445 950 361 841T277 529ZM930 1504Q930 1396 869 1329T715 1262Q674 1262 644 1272T566 1313T496 1350T446 1357Q405 1357 376 1326T347 1245L223 1252Q223 1359 283 1429T437 1499Q472 1499 500 1489T576 1450T649 1412T706 1403Q749 1403 777
+1437T806 1516L930 1504Z" />
+<glyph unicode="&#xf6;" horiz-adv-x="1168" d="M91 551Q91 710 153 837T327 1033T582 1102Q803 1102 939 949T1076 542V529Q1076 371 1016 246T843 50T584 -20Q364 -20 228 133T91 538V551ZM277 529Q277 349 360 240T584 131Q725 131 808 241T891 551Q891 729
+807 839T582 950Q445 950 361 841T277 529ZM254 1371Q254 1416 281 1446T363 1477T445 1447T473 1371T445 1296T363 1266T282 1296T254 1371ZM684 1369Q684 1414 711 1445T793 1476T875 1445T903 1369T875 1294T793 1264T712 1294T684 1369Z" />
+<glyph unicode="&#xf7;" horiz-adv-x="1169" d="M1069 600H71V784H1069V600ZM461 1098Q461 1146 489 1178T575 1210T661 1178T691 1098Q691 1051 662 1020T575 989T490 1020T461 1098ZM461 281Q461 329 489 361T575 393T661 361T691 281Q691 235 662 204T575 172T490
+203T461 281Z" />
+<glyph unicode="&#xf8;" horiz-adv-x="1160" d="M91 551Q91 710 152 836T326 1032T582 1102Q692 1102 786 1060L859 1208H983L881 1003Q1076 849 1076 529Q1076 371 1014 244T840 49T584 -20Q480 -20 394 15L320 -134H196L296 69Q91 218 91 551ZM276 529Q276 335
+373 224L716 918Q654 950 582 950Q444 950 360 841T276 529ZM890 551Q890 733 803 844L463 156Q518 131 584 131Q723 131 806 240T890 535V551Z" />
+<glyph unicode="&#xf9;" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM673 1240H514L256 1534H479L673 1240Z" />
+<glyph unicode="&#xfa;" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM658 1534H882L614 1240H465L658 1534Z" />
+<glyph unicode="&#xfb;" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM870 1262V1252H717L567 1422L418 1252H265V1264L511 1536H623L870 1262Z" />
+<glyph unicode="&#xfc;" horiz-adv-x="1129" d="M808 107Q700 -20 491 -20Q318 -20 228 80T136 378V1082H321V383Q321 137 521 137Q733 137 803 295V1082H988V0H812L808 107ZM246 1371Q246 1416 273 1446T355 1477T437 1447T465 1371T437 1296T355 1266T274 1296T246
+1371ZM676 1369Q676 1414 703 1445T785 1476T867 1445T895 1369T867 1294T785 1264T704 1294T676 1369Z" />
+<glyph unicode="&#xfd;" horiz-adv-x="969" d="M494 271L746 1082H944L509 -167Q408 -437 188 -437L153 -434L84 -421V-271L134 -275Q228 -275 280 -237T367 -98L408 12L22 1082H224L494 271ZM599 1534H823L555 1240H406L599 1534Z" />
+<glyph unicode="&#xfe;" horiz-adv-x="1180" d="M1063 529Q1063 282 950 131T644 -20Q447 -20 334 105V-416H149V1536H334V970Q447 1102 641 1102Q836 1102 949 955T1063 546V529ZM878 550Q878 733 800 839T586 945Q418 945 334 796V279Q417 131 588 131Q721 131
+799 236T878 550Z" />
+<glyph unicode="&#xff;" horiz-adv-x="969" d="M494 271L746 1082H944L509 -167Q408 -437 188 -437L153 -434L84 -421V-271L134 -275Q228 -275 280 -237T367 -98L408 12L22 1082H224L494 271ZM187 1371Q187 1416 214 1446T296 1477T378 1447T406 1371T378 1296T296
+1266T215 1296T187 1371ZM617 1369Q617 1414 644 1445T726 1476T808 1445T836 1369T808 1294T726 1264T645 1294T617 1369Z" />
+<glyph unicode="&#x2013;" horiz-adv-x="1344" d="M1421 651H419V802H1421V651Z" />
+<glyph unicode="&#x2014;" horiz-adv-x="1599" d="M1737 651H401V802H1737V651Z" />
+<glyph unicode="&#x2018;" horiz-adv-x="409" d="M270 1555L376 1483Q283 1356 280 1209V1073H96V1189Q96 1291 144 1391T270 1555Z" />
+<glyph unicode="&#x2019;" horiz-adv-x="409" d="M153 1046L48 1118Q141 1248 144 1392V1536H327V1406Q326 1306 278 1207T153 1046Z" />
+<glyph unicode="&#x201a;" horiz-adv-x="407" d="M141 -283L36 -210Q127 -83 130 63V181H315V81Q315 -20 266 -121T141 -283Z" />
+<glyph unicode="&#x201c;" horiz-adv-x="724" d="M278 1555L384 1483Q291 1356 288 1209V1073H104V1189Q104 1291 152 1391T278 1555ZM593 1555L699 1483Q606 1356 603 1209V1073H419V1189Q419 1291 467 1391T593 1555Z" />
+<glyph unicode="&#x201d;" horiz-adv-x="731" d="M165 1046L60 1118Q153 1248 156 1392V1536H339V1406Q338 1306 290 1207T165 1046ZM472 1046L367 1118Q460 1248 463 1392V1536H646V1406Q645 1306 597 1207T472 1046Z" />
+<glyph unicode="&#x201e;" horiz-adv-x="705" d="M141 -301L36 -229Q127 -92 130 61V246H315V82Q315 -26 266 -131T141 -301ZM437 -301L332 -229Q423 -92 426 61V246H612V82Q612 -25 564 -129T437 -301Z" />
+<glyph unicode="&#x2022;" horiz-adv-x="690" d="M138 772Q138 859 193 915T341 971Q432 971 489 917T546 769V732Q546 645 491 590T342 535Q249 535 194 590T138 734V772Z" />
+<glyph unicode="&#x2039;" horiz-adv-x="614" d="M286 550L544 153H403L108 541V560L403 949H544L286 550Z" />
+<glyph unicode="&#x203a;" horiz-adv-x="614" d="M231 949L526 560V541L231 152H89L347 550L89 949H231Z" />
+</font>
+</defs>
+</svg>
Binary file server/bo_client/public/assets/fonts/Roboto-regular/Roboto-regular.ttf has changed
Binary file server/bo_client/public/assets/fonts/Roboto-regular/Roboto-regular.woff has changed
Binary file server/bo_client/public/assets/fonts/Roboto-regular/Roboto-regular.woff2 has changed
Binary file server/bo_client/public/assets/img/viaf-logo-32x32.gif has changed
Binary file server/bo_client/public/assets/img/viaf-logo-64x64.gif has changed
--- a/server/bo_client/server/index.js	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/server/index.js	Fri Jan 15 15:35:00 2016 +0100
@@ -1,3 +1,5 @@
+/*jshint node:true*/
+
 // To use it create some files under `mocks/`
 // e.g. `server/mocks/ember-hamsters.js`
 //
--- a/server/bo_client/server/mocks/documents.js	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/bo_client/server/mocks/documents.js	Fri Jan 15 15:35:00 2016 +0100
@@ -9,6 +9,7 @@
     "id": "crdo-09-CAYCHAX_SOUND",
     "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-09-CAYCHAX_SOUND",
     "title": "ALLOc : Caychax : Parabole",
+    "language": "http://lexvo.org/id/iso639-3/gsw",
     "modified": "2010-10-25T18:16:38+02:00",
     "publishers": [
       "Équipe de Recherche en Syntaxe et Sémantique",
@@ -103,6 +104,7 @@
     "id": "crdo-ALA_177",
     "uri": "http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-ALA_177",
     "title": "Atlas Linguistique et ethnographique de l'Alsace - Enquêtes linguistiques - Cleebourg: 04",
+    "language": "http://lexvo.org/id/iso639-3/fra",
     "modified": "2014-12-01T18:34:43+01:00",
     "publishers": [
       "Atlas linguistiques, cultures et parlers régionaux de France"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/server/mocks/lexvo.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,28 @@
+/*jshint node:true*/
+module.exports = function(app) {
+  var express = require('express');
+  var _ = require('lodash');
+
+  var v1LexvoRouter = express.Router();
+
+  var lexvoMappings = {
+    "fra": "français",
+    "gsw": "alémanique",
+    "oci": "occitan"
+  };
+
+  v1LexvoRouter.get('/:id', function(req, res) {
+    var idList = req.params.id.split(',');
+    var resMap = _.reduce(idList, function(r, id) {
+      r[id] = (id in lexvoMappings)?lexvoMappings[id]:null;
+    }, {});
+    res.send({
+      'lexvoids': _.reduce(idList, function(r, id) {
+        r[id] = (id in lexvoMappings)?lexvoMappings[id]:null;
+        return r;
+      }, {}),
+    });
+  });
+
+  app.use('/api/v1/lexvo', v1LexvoRouter);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/server/mocks/viaf.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,31 @@
+/*jshint node:true*/
+module.exports = function(app) {
+  var express = require('express');
+  var _ = require('lodash');
+
+  var v1ViafRouter = express.Router();
+
+  var viafMappings = {
+    "93752300": "Sonia Branca-Rosoff",
+    "9122216": "Dominique Huck",
+    "51700729": "Patrick Sauzet",
+    "56666014": "Guylaine Brun-Trigaud",
+    "61542329": "Arlette Bothorel",
+    "91792187": "Xavier Ravier"
+  };
+
+  v1ViafRouter.get('/:id', function(req, res) {
+    var idList = req.params.id.split(',');
+    var resMap = _.reduce(idList, function(r, id) {
+      r[id] = (id in viafMappings)?viafMappings[id]:null;
+    }, {});
+    res.send({
+      'viafids': _.reduce(idList, function(r, id) {
+        r[id] = (id in viafMappings)?viafMappings[id]:null;
+        return r;
+      }, {}),
+    });
+  });
+
+  app.use('/api/v1/viaf', v1ViafRouter);
+};
--- a/server/bo_client/tests/integration/components/bo-doc-contributors-test.js	Fri Jan 15 15:27:56 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-import { moduleForComponent, test } from 'ember-qunit';
-import hbs from 'htmlbars-inline-precompile';
-
-moduleForComponent('bo-doc-contributors', 'Integration | Component | bo doc contributors', {
-  integration: true
-});
-
-test('it renders', function(assert) {
-  
-  // Set any properties with this.set('myProperty', 'value');
-  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
-
-  this.render(hbs`{{bo-doc-contributors}}`);
-
-  assert.equal(this.$().text().trim(), '');
-
-  // Template block usage:" + EOL +
-  this.render(hbs`
-    {{#bo-doc-contributors}}
-      template block text
-    {{/bo-doc-contributors}}
-  `);
-
-  assert.equal(this.$().text().trim(), 'template block text');
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/integration/pods/components/bo-doc-contributor-editpanel/component-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bo-doc-contributor-editpanel', 'Integration | Component | bo doc contributor editpanel', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
+
+  this.render(hbs`{{bo-doc-contributor-editpanel}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#bo-doc-contributor-editpanel}}
+      template block text
+    {{/bo-doc-contributor-editpanel}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/integration/pods/components/bo-doc-contributor-list-item/component-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bo-doc-contributor-list-item', 'Integration | Component | bo doc contributor list item', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
+
+  this.render(hbs`{{bo-doc-contributor-list-item}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#bo-doc-contributor-list-item}}
+      template block text
+    {{/bo-doc-contributor-list-item}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/integration/pods/components/bo-doc-contributor-nameurl-cell/component-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bo-doc-contributor-nameurl-cell', 'Integration | Component | bo doc contributor nameurl cell', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
+
+  this.render(hbs`{{bo-doc-contributor-nameurl-cell}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#bo-doc-contributor-nameurl-cell}}
+      template block text
+    {{/bo-doc-contributor-nameurl-cell}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/integration/pods/components/bo-doc-contributor-role-cell/component-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bo-doc-contributor-role-cell', 'Integration | Component | bo doc contributor role cell', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
+
+  this.render(hbs`{{bo-doc-contributor-role-cell}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#bo-doc-contributor-role-cell}}
+      template block text
+    {{/bo-doc-contributor-role-cell}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/integration/pods/components/bo-doc-contributor-role-select/component-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bo-doc-contributor-role-select', 'Integration | Component | bo doc contributor role select', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
+
+  this.render(hbs`{{bo-doc-contributor-role-select}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#bo-doc-contributor-role-select}}
+      template block text
+    {{/bo-doc-contributor-role-select}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/integration/pods/components/bo-doc-contributor-row/component-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bo-doc-contributor-row', 'Integration | Component | bo doc contributor row', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
+
+  this.render(hbs`{{bo-doc-contributor-row}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#bo-doc-contributor-row}}
+      template block text
+    {{/bo-doc-contributor-row}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/integration/pods/components/bo-doc-contributors/component-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bo-doc-contributors', 'Integration | Component | bo doc contributors', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
+
+  this.render(hbs`{{bo-doc-contributors}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#bo-doc-contributors}}
+      template block text
+    {{/bo-doc-contributors}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/integration/pods/components/bo-doc-language/component-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bo-doc-language', 'Integration | Component | bo doc language', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
+
+  this.render(hbs`{{bo-doc-language}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#bo-doc-language}}
+      template block text
+    {{/bo-doc-language}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/integration/pods/components/bo-doc-new-contributor/component-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bo-doc-new-contributor', 'Integration | Component | bo doc new contributor', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
+
+  this.render(hbs`{{bo-doc-new-contributor}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#bo-doc-new-contributor}}
+      template block text
+    {{/bo-doc-new-contributor}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/integration/pods/components/bo-doc-viaf-autocomplete/component-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,25 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bo-doc-viaf-autocomplete', 'Integration | Component | bo doc viaf autocomplete', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
+
+  this.render(hbs`{{bo-doc-viaf-autocomplete}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:" + EOL +
+  this.render(hbs`
+    {{#bo-doc-viaf-autocomplete}}
+      template block text
+    {{/bo-doc-viaf-autocomplete}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/unit/initializers/constants-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+import Ember from 'ember';
+import ConstantsInitializer from '../../../initializers/constants';
+import { module, test } from 'qunit';
+
+let application;
+
+module('Unit | Initializer | constants', {
+  beforeEach() {
+    Ember.run(function() {
+      application = Ember.Application.create();
+      application.deferReadiness();
+    });
+  }
+});
+
+// Replace this with your real tests.
+test('it works', function(assert) {
+  ConstantsInitializer.initialize(application);
+
+  // you would normally confirm the results of the initializer here
+  assert.ok(true);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/unit/initializers/options-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,22 @@
+import Ember from 'ember';
+import OptionsInitializer from '../../../initializers/options';
+import { module, test } from 'qunit';
+
+let application;
+
+module('Unit | Initializer | options', {
+  beforeEach() {
+    Ember.run(function() {
+      application = Ember.Application.create();
+      application.deferReadiness();
+    });
+  }
+});
+
+// Replace this with your real tests.
+test('it works', function(assert) {
+  OptionsInitializer.initialize(application);
+
+  // you would normally confirm the results of the initializer here
+  assert.ok(true);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/unit/mixins/cell-editing-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+import Ember from 'ember';
+import CellEditingMixin from '../../../mixins/cell-editing';
+import { module, test } from 'qunit';
+
+module('Unit | Mixin | cell editing');
+
+// Replace this with your real tests.
+test('it works', function(assert) {
+  let CellEditingObject = Ember.Object.extend(CellEditingMixin);
+  let subject = CellEditingObject.create();
+  assert.ok(subject);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/unit/mixins/click-outside-mixin-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+import Ember from 'ember';
+import ClickOutsideMixinMixin from '../../../mixins/click-outside-mixin';
+import { module, test } from 'qunit';
+
+module('Unit | Mixin | click outside mixin');
+
+// Replace this with your real tests.
+test('it works', function(assert) {
+  let ClickOutsideMixinObject = Ember.Object.extend(ClickOutsideMixinMixin);
+  let subject = ClickOutsideMixinObject.create();
+  assert.ok(subject);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/unit/services/constants-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('service:constants', 'Unit | Service | constants', {
+  // Specify the other units that are required for this test.
+  // needs: ['service:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+  let service = this.subject();
+  assert.ok(service);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/unit/services/lexvo-resolver-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('service:lexvo-resolver', 'Unit | Service | lexvo resolver', {
+  // Specify the other units that are required for this test.
+  // needs: ['service:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+  let service = this.subject();
+  assert.ok(service);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/tests/unit/services/viaf-resolver-test.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('service:viaf-resolver', 'Unit | Service | viaf resolver', {
+  // Specify the other units that are required for this test.
+  // needs: ['service:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+  let service = this.subject();
+  assert.ok(service);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/vendor/shims/store.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+(function() {
+  function vendorModule() {
+    'use strict';
+
+    return { 'default': self['store'] };
+  }
+
+  define('store', [], vendorModule);
+})();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/bo_client/vendor/shims/urijs.js	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,9 @@
+(function() {
+  function vendorModule() {
+    'use strict';
+
+    return { 'default': self['URI'] };
+  }
+
+  define('urijs', [], vendorModule);
+})();
--- a/server/src/.env.example	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/.env.example	Fri Jan 15 15:35:00 2016 +0100
@@ -21,8 +21,11 @@
 
 CORPUSPAROLE_COCOON_RDF_BASE_URI=
 CORPUSPAROLE_COCOON_OAIPMH_URL=
-CORPUSPAROLE_SESAME_QUERY_URL=http://172.16.1.5:8080/openrdf-sesame
-CORPUSPAROLE_SESAME_UPDATE_URL=
+CORPUSPAROLE_SESAME_BASE_URL=http://172.16.1.5:8080/openrdf-sesame
+CORPUSPAROLE_SESAME_REPOSITORY=
+CORPUSPAROLE_SESAME_REPOSITORY_RAW=
+CORPUSPAROLE_SESAME_LEXVO_REPOSITORY=
+
 
 EASYRDF_HTTP_CLIENT_TIMEOUT=20
 
--- a/server/src/app/Http/Controllers/Api/DocumentController.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/app/Http/Controllers/Api/DocumentController.php	Fri Jan 15 15:35:00 2016 +0100
@@ -3,6 +3,7 @@
 namespace CorpusParole\Http\Controllers\Api;
 
 use Illuminate\Http\Request;
+//use Illuminate\Http\Response;
 
 use CorpusParole\Http\Requests;
 use CorpusParole\Http\Controllers\Controller;
@@ -80,7 +81,7 @@
     }
 
     /**
-     * Update the specified resource in storage.
+     * Update the specified document in storage.
      *
      * @param  Request  $request
      * @param  int  $id
@@ -88,7 +89,19 @@
      */
     public function update(Request $request, $id)
     {
-        //
+        $data = $request->json();
+        $document = $data->get('document');
+        $doc = $this->documentRepository->get($id);
+        if(is_null($doc)) {
+            abort(404);
+        }
+
+        //for now, update contributors only
+        $doc->setContributors($document['contributors']);
+
+        $this->documentRepository->save($doc);
+
+        return response('', 204);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Http/Controllers/Api/LexvoController.php	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,32 @@
+<?php
+
+namespace CorpusParole\Http\Controllers\Api;
+
+use Illuminate\Http\Request;
+use CorpusParole\Http\Requests;
+use CorpusParole\Http\Controllers\Controller;
+use CorpusParole\Services\LexvoResolverInterface;
+use CorpusParole\Services\LexvoResolverException;
+
+class LexvoController extends Controller
+{
+    public function __construct(LexvoResolverInterface $lexvoResolver) {
+        $this->lexvoResolver = $lexvoResolver;
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  int  $id od comma separatedlist of ids
+     * @return \Illuminate\Http\Response
+     */
+    public function show($id)
+    {
+        try {
+            return response()->json(['lexvoids' => $this->lexvoResolver->getNames(explode(",", $id))]);
+        } catch (LexvoResolverException $e) {
+            abort(500, $e->getMessage());
+        }
+    }
+
+}
--- a/server/src/app/Http/Controllers/Bo/DocumentListController.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/app/Http/Controllers/Bo/DocumentListController.php	Fri Jan 15 15:35:00 2016 +0100
@@ -7,6 +7,7 @@
 
 use CorpusParole\Http\Controllers\Controller;
 use CorpusParole\Repositories\DocumentRepository;
+use CorpusParole\Services\LexvoResolverInterface;
 
 use Illuminate\Http\Request;
 
@@ -15,8 +16,9 @@
     /**
      * Create a new controller instance.
      */
-    public function __construct(DocumentRepository $documentRepo) {
+    public function __construct(DocumentRepository $documentRepo, LexvoResolverInterface $lexvoResolver) {
         $this->documentRepository = $documentRepo;
+        $this->lexvoResolver = $lexvoResolver;
     }
 
     /**
@@ -25,7 +27,13 @@
      * @return Response
      */
     public function index() {
-        return view('bo.docList', ['docs' => $this->documentRepository->paginateAll()]);
+        $docs = $this->documentRepository->paginateAll();
+        $languageIds = [];
+        foreach ($docs as $doc) {
+            array_push($languageIds, $doc->getLanguageValue());
+        }
+        $languageNames = $this->lexvoResolver->getNames(array_unique($languageIds));
+        return view('bo.docList', ['docs' => $docs, 'languageNames' => $languageNames]);
     }
 
     /**
@@ -77,15 +85,7 @@
      */
     public function getClient($id)
     {
-        //$doc->add("<$doc_uri>");
-        $doc = $this->documentRepository->get($id);
-
-        if(is_null($doc)) {
-            abort(404);
-        }
-
-        return view('bo.docDetailClient', ['doc' => $doc]);
-
+        return view('bo.docDetailClient', ['docid' => $id, 'boClientEnv' => json_encode(config('corpusparole.bo_client_environment'), JSON_UNESCAPED_SLASHES)]);
     }
 
 
--- a/server/src/app/Http/Middleware/VerifyCsrfToken.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/app/Http/Middleware/VerifyCsrfToken.php	Fri Jan 15 15:35:00 2016 +0100
@@ -19,4 +19,13 @@
     {
         return parent::handle($request, $next);
     }
+
+    /**
+     * The URIs that should be excluded from CSRF verification.
+     *
+     * @var array
+     */
+    protected $except = [
+        'api/*',
+    ];
 }
--- a/server/src/app/Http/routes.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/app/Http/routes.php	Fri Jan 15 15:35:00 2016 +0100
@@ -37,7 +37,9 @@
 
 Route::group(['prefix' => 'api/v1'] , function() {
     Route::resource('documents', 'Api\DocumentController',
-                    ['only' => ['index', 'show']]);
+                    ['only' => ['index', 'show', 'update']]);
     Route::resource('viaf', 'Api\ViafController',
                     ['only' => ['show']]);
+    Route::resource('lexvo', 'Api\LexvoController',
+                    ['only' => ['show']]);
 });
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Libraries/Mergers/JsonDocumentMerger.php	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,10 @@
+<?php
+namespace CorpusParole\Libraries\Mergers;
+
+class JsonDocumentMerger {
+
+    public function mergeJSON($doc, $jsonDoc) {
+
+        return $doc;
+    }
+}
--- a/server/src/app/Libraries/RdfModel/RdfModelResource.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/app/Libraries/RdfModel/RdfModelResource.php	Fri Jan 15 15:35:00 2016 +0100
@@ -34,9 +34,22 @@
         return $this->uri;
     }
 
+    public function getCurrentDelta() {
+        return $this->getCurrentDelta;
+    }
+
     public function startDelta() {
         $this->currentDelta = new RdfModelDelta($this->getGraph()->getUri());
         array_push($this->deltaList, $this->currentDelta);
+        return $this->currentDelta;
+    }
+
+    protected function setSimpleProperty($baseNode, $property, $oldValue, $newValue) {
+        $delta = $this->startDelta();
+        $baseNode->delete($property, $oldValue);
+        $delta->getDeletedGraph()->add($baseNode, $property, $oldValue);
+        $baseNode->add($property, $newValue);
+        $delta->getAddedGraph()->add($baseNode, $property, $newValue);
     }
 
 
--- a/server/src/app/Libraries/Sparql/SparqlClient.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/app/Libraries/Sparql/SparqlClient.php	Fri Jan 15 15:35:00 2016 +0100
@@ -116,7 +116,8 @@
         if($resp->getStatusCode() != 204) {
             throw new CorpusParoleException("Could not update in transaction with operation $operation: "
                 . $resp->getStatusCode() . " - "
-                . $resp->getReasonPhrase() . " : " . $resp->getBody(), 1);
+                . $resp->getReasonPhrase() . " : " . $resp->getBody()
+                . " : $query" , 1);
         }
     }
 
--- a/server/src/app/Models/Document.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/app/Models/Document.php	Fri Jan 15 15:35:00 2016 +0100
@@ -28,10 +28,12 @@
     // memoization
     private $providedCHO = null;
     private $title = false;
+    private $lang = null;
     private $publishers = null;
     private $mediaArray = null;
     private $issued = null;
     private $modified = null;
+    private $contributors = null;
 
     public function getProvidedCHO() {
         if(is_null($this->providedCHO)) {
@@ -43,10 +45,12 @@
     private function clearMemoizationCache() {
         $this->providedCHO = null;
         $this->title = false;
+        $this->lang = null;
         $this->publishers = null;
         $this->mediaArray = null;
         $this->issued = null;
         $this->modified = null;
+        $this->contributors = null;
     }
 
     public function getId() {
@@ -56,6 +60,30 @@
         return $this->id;
     }
 
+    public function getLanguage() {
+        if(is_null($this->lang)) {
+            try {
+                $langs = $this->getProvidedCHO()->all('<http://purl.org/dc/elements/1.1/language>');
+                if(count($langs) > 0) {
+                    $this->lang = $langs[0];
+                }
+            } catch(\Exception $e) {
+                $this->lang = null;
+            }
+        }
+        return $this->lang;
+    }
+
+    public function getLanguageValue() {
+        $lang = $this->getLanguage();
+        if($lang instanceof Resource) {
+            return $lang->getUri();
+        } else if($lan instanceof Literal) {
+            return $lang->getValue();
+        }
+        return null;
+    }
+
     public function getTitle() {
         if($this->title === false) {
             try {
@@ -67,6 +95,16 @@
         return $this->title;
     }
 
+    public function setTitle($value, $lang="fr") {
+        $oldTitle = $this->getTitle();
+        if($oldTitle && $oldTitle->getValue() != $value && $oldTitle->getLang() != $lang) {
+            $literalTitle = new Literal($value, $lang, null);
+            $this->setSimpleProperty($this->getProvidedCHO(), 'http://purl.org/dc/elements/1.1/title', $oldTitle, $literalTitle);
+            //clear cache
+            $this->title = false;
+        }
+    }
+
     public function getTitleValue() {
         $title = $this->getTitle();
         return is_null($title)?null:$title->getValue();
@@ -118,6 +156,17 @@
         return is_null($modified)?null:$modified->getValue();
     }
 
+    public function setModified($value) {
+        $modified = $this->getModified();
+        if($value && (!$modified || $modified->getValue() != $value) ) {
+
+            $newModified = new Literal($value, "http://purl.org/dc/terms/W3CDTF");
+            $this->setSimpleProperty($this->getProvidedCHO(), 'http://purl.org/dc/terms/modified', $modified, $newModified);
+
+            $this->modified = null;
+        }
+    }
+
     public function getMediaArray() {
 
         if(is_null($this->mediaArray)) {
@@ -163,25 +212,66 @@
     }
 
     public function getContributors() {
-        return array_reduce(
-            CocoonUtils::OLAC_ROLES,
-            function($res, $olacRole) {
-                return array_merge(
-                    $res,
-                    array_map(
-                        function($olacValue) use ($olacRole) {
-                            return [
-                                'name' => ($olacValue instanceof Literal)?$olacValue->getValue():null,
-                                'url' => ($olacValue instanceof Resource)?$olacValue->getUri():null,
-                                'role' => $olacRole
-                            ];
-                        },
-                        $this->getProvidedCHO()->all("<$olacRole>")
-                    )
-                );
-            },
-            []
-        );
+        if(is_null($this->contributors)) {
+            $this->contributors = array_reduce(
+                CocoonUtils::OLAC_ROLES,
+                function($res, $olacRole) {
+                    return array_merge(
+                        $res,
+                        array_map(
+                            function($olacValue) use ($olacRole) {
+                                return [
+                                    'name' => ($olacValue instanceof Literal)?$olacValue->getValue():null,
+                                    'nameLiteral' => ($olacValue instanceof Literal)?$olacValue:null,
+                                    'url' => ($olacValue instanceof Resource)?$olacValue->getUri():null,
+                                    'role' => $olacRole
+                                ];
+                            },
+                            $this->getProvidedCHO()->all("<$olacRole>")
+                        )
+                    );
+                },
+                []
+            );
+        }
+        return $this->contributors;
+    }
+
+    /**
+     * change contributors list
+     */
+    public function setContributors($contributors) {
+        $delta = $this->startDelta();
+        //remove old,
+        foreach ($this->getContributors() as $contribDef) {
+            $value = null;
+            if (is_null($contribDef['url'])) {
+                if(is_null($contribDef['nameLiteral'])) {
+                    $value = new Literal($contribDef['name']);
+                } else {
+                    $value = $contribDef['nameLiteral'];
+                }
+            } else {
+                $value = new Resource($contribDef['url']);
+            }
+            $this->getProvidedCHO()->delete($contribDef['role'], $value);
+            $delta->getDeletedGraph()->add($this->getProvidedCHO(), $contribDef['role'], $value);
+        }
+
+        //put new
+        foreach ($contributors as $newContribDef) {
+            $value = null;
+            if (is_null($newContribDef['url'])) {
+                $value = new Literal($newContribDef['name'], "fr", null);
+            } else {
+                $value = new Resource($newContribDef['url']);
+            }
+            $this->getProvidedCHO()->add($newContribDef['role'], $value);
+            $delta->getAddedGraph()->add($this->getProvidedCHO(), $newContribDef['role'], $value);
+        }
+
+        $this->contributors = null;
+
     }
 
     /**
@@ -240,13 +330,19 @@
                 $this->getPublishers()
             );
 
+            $contributors = array_map(
+                function($c) { unset($c['nameLiteral']); return $c; },
+                $this->getContributors()
+            );
+
             return [
                 'id' => $this->getId(),
                 'uri' => $this->getUri(),
                 'title' => $this->getTitleValue(),
+                'language' => $this->getLanguageValue(),
                 'modified' => $this->getModifiedValue(),
                 'publishers' => $publishers,
-                'contributors' => $this->getContributors(),
+                'contributors' => $contributors,
                 'mediaArray'=> $mediaArray
             ];
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Providers/LexvoServiceProvider.php	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,23 @@
+<?php
+
+namespace CorpusParole\Providers;
+
+use Config;
+
+use Illuminate\Support\ServiceProvider;
+
+class LexvoServiceProvider extends ServiceProvider
+{
+    /**
+     * Register the application services.
+     *
+     * @return void
+     */
+    public function register()
+    {
+        $this->app->bind('CorpusParole\Services\LexvoResolverInterface', function($app) {
+            $sparqlClient = $app->make('EasyRdf\Sparql\Client', [config('corpusparole.lexvo_sesame_query_url'), null]);
+            return $app->make('CorpusParole\Services\LexvoResolver', [$sparqlClient,]);
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Providers/VersionServiceProvider.php	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,24 @@
+<?php
+namespace CorpusParole\Providers;
+
+use CorpusParole\Services\Version;
+use Illuminate\Support\ServiceProvider;
+
+/**
+ * guzzle Service Provider, inspired by https://github.com/urakozz/laravel-guzzle
+ */
+class VersionServiceProvider extends ServiceProvider
+{
+    /**
+     * Register the version provider
+     *
+     * @return Version
+     */
+    public function register()
+    {
+        $this->app->singleton('version', function($app)
+        {
+            return new Version();
+        });
+    }
+}
--- a/server/src/app/Repositories/RdfDocumentRepository.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/app/Repositories/RdfDocumentRepository.php	Fri Jan 15 15:35:00 2016 +0100
@@ -40,6 +40,9 @@
             $newGraph->add($doc->uri, "http://www.europeana.eu/schemas/edm/aggregatedCHO", $doc->doc);
             $newGraph->add($doc->doc, "rdf:type", $newGraph->resource("http://www.europeana.eu/schemas/edm/ProvidedCHO"));
             $newGraph->add($doc->doc, "http://purl.org/dc/elements/1.1/title", $doc->title);
+            if(isset($doc->lang)) {
+                $newGraph->add($doc->doc, "http://purl.org/dc/elements/1.1/language", $doc->lang);
+            }
             if(isset($doc->issued)) {
                 $newGraph->add($doc->doc, "http://purl.org/dc/terms/issued", $doc->issued);
             }
@@ -55,10 +58,11 @@
     public function all() {
 
         return $this->queryDocs(
-        "SELECT DISTINCT ?uri ?doc ?title ?issued ?modified".
+        "SELECT DISTINCT ?uri ?doc ?title ?issued ?modified ?lang".
         "    WHERE {".
         "        GRAPH ?uri { ?doc a <http://www.europeana.eu/schemas/edm/ProvidedCHO>.".
         "        ?doc <http://purl.org/dc/elements/1.1/title> ?title.".
+        "        OPTIONAL {?doc <http://purl.org/dc/elements/1.1/language> ?lang.} ".
         "        OPTIONAL {?doc <http://purl.org/dc/terms/issued> ?issued.} ".
         "        OPTIONAL {?doc <http://purl.org/dc/terms/modified> ?modified.} }".
         "    } ORDER BY ?uri"
@@ -79,7 +83,8 @@
             return null;
         }
 
-        return new Document($docUri, $doc);
+        // clone the graph to force the URI
+        return new Document($docUri, new Graph($docUri, $doc->toRdfPhp()));
 
     }
 
@@ -143,10 +148,11 @@
         $offset = max(0,($page - 1) * $perPage);
 
         $query =
-            "SELECT DISTINCT ?uri ?doc ?title ?issued ?modified".
+            "SELECT DISTINCT ?uri ?doc ?title ?issued ?modified ?lang".
             "    WHERE {".
             "        GRAPH ?uri { ?doc a <http://www.europeana.eu/schemas/edm/ProvidedCHO>.".
             "        ?doc <http://purl.org/dc/elements/1.1/title> ?title.".
+            "        OPTIONAL {?doc <http://purl.org/dc/elements/1.1/language> ?lang.} ".
             "        OPTIONAL {?doc <http://purl.org/dc/terms/issued> ?issued.} ".
             "        OPTIONAL {?doc <http://purl.org/dc/terms/modified> ?modified.} }".
             "    } ORDER BY ?uri OFFSET $offset LIMIT $perPage";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Services/LexvoResolver.php	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,101 @@
+<?php
+namespace CorpusParole\Services;
+
+use Cache;
+use CorpusParole\Services\LexvoResolverInterface;
+
+class LexvoResolver implements LexvoResolverInterface {
+
+    public function __construct($sparqlClient) {
+        $this->sparqlClient = $sparqlClient;
+    }
+
+    private function checkLexvoId($id) {
+        $lexvoid = $id;
+        if(strpos($id, config('corpusparole.lexvo_base_url')) !== 0) {
+            $lexvoid = config('corpusparole.lexvo_base_url').$id;
+        }
+        $lexvoid = rtrim($lexvoid, '/');
+        if(preg_match("/^".preg_quote(config('corpusparole.lexvo_base_url'),"/")."[[:alpha:]]{3}$/", $lexvoid) !== 1) {
+            throw new LexvoResolverException("the provided id \"$id\" is not a Lexvo id");
+        }
+        return $lexvoid;
+    }
+    /**
+     * Get name from Viaf id
+     * @param string $id The id to resolve. Can be an url starting with http://viaf.org/viaf/
+     * @return a string with the name
+     */
+    public function getName($id) {
+        $res = $this->getNames([$id,]);
+        assert(array_key_exists($id,$res), "the result must contains $id");
+        return $res[$id];
+    }
+
+    /**
+     * Get a list of names from an array of viaf ids.
+     * @param array $ids The array of ids to resolve.
+     *                   Each id can be an url starting with http://viaf.org/viaf/
+     * @return array key is id, value is the name
+     */
+    public function getNames(array $ids) {
+
+        $lexvoids = array_map([$this, 'checkLexvoId'], $ids);
+        $lexvoidsMap = array_combine($lexvoids, $ids);
+
+        $results = [];
+        $missingLexvoids = [];
+
+        foreach ($lexvoidsMap as $lexvoid => $lexvoidSource) {
+            $cachedValue = Cache::get("lexvo:$lexvoid");
+            if(is_null($cachedValue)) {
+                array_push($missingLexvoids, $lexvoid);
+            } else {
+                $results[$lexvoidSource] = $cachedValue;
+            }
+        }
+
+        if(count($missingLexvoids) == 0) {
+            return $results;
+        }
+
+        $query = "SELECT ?s ?o WHERE {";
+        foreach ($missingLexvoids as $index => $lid) {
+            if($index > 0) {
+                $query .= " UNION ";
+            }
+            $query .= "{<$lid> rdfs:label ?o. ?s rdfs:label ?o FILTER(?s = <$lid> && (lang(?o) = \"fr\" || lang(?o) = \"en\"))}";
+        }
+        $query .= "}";
+
+
+        $docs = $this->sparqlClient->query($query);
+
+        $resultsRaw = [];
+
+        foreach ($docs as $doc) {
+            $lexvoid = $doc->s->getUri();
+            $lexvoname = $doc->o;
+
+            $lang = $lexvoname->getLang();
+            $value = $lexvoname->getValue();
+
+            if(!array_key_exists($lexvoid, $resultsRaw) ||
+            ($lang == "fr" && ($resultsRaw[$lexvoid]->getLang() == "en" || mb_strlen($resultsRaw[$lexvoid]->getValue()) > mb_strlen($value))) ||
+            ($lang == "en" && $resultsRaw[$lexvoid]->getLang() == "en" && mb_strlen($resultsRaw[$lexvoid]->getValue()) > mb_strlen($value)) ) {
+                $resultsRaw[$lexvoid] = $lexvoname;
+            }
+        }
+
+        foreach ($missingLexvoids as $lexvoid) {
+            $lexvoidSource = $lexvoidsMap[$lexvoid];
+            $missingValue = array_key_exists($lexvoid,$resultsRaw) && $resultsRaw[$lexvoid]?mb_strtolower($resultsRaw[$lexvoid]->getValue()):"";
+            Cache::put("lexvo:$lexvoid", $missingValue, config('corpusparole.lexvo_cache_expiration'));
+            $results[$lexvoidSource] = mb_strlen($missingValue)>0?$missingValue:null;
+        }
+
+        return $results;
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Services/LexvoResolverException.php	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,6 @@
+<?php
+namespace CorpusParole\Services;
+
+class LexvoResolverException extends \Exception {
+    // just extend...
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Services/LexvoResolverInterface.php	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,20 @@
+<?php
+namespace CorpusParole\Services;
+
+interface LexvoResolverInterface {
+
+    /**
+     * Get name from Viaf id
+     * @param string $id The id to resolve. Can be an url starting with http://viaf.org/viaf/
+     * @return a string with the name
+     */
+    public function getName($id);
+
+    /**
+     * Get a list of names from an array of viaf ids.
+     * @param array $ids The array of ids to resolve.
+     *                   Each id can be an url starting with http://viaf.org/viaf/
+     */
+    public function getNames(array $ids);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/app/Services/Version.php	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,8 @@
+<?php
+namespace CorpusParole\Services;
+
+class Version {
+    public function version() {
+        return config('version.version');
+    }
+}
--- a/server/src/config/app.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/config/app.php	Fri Jan 15 15:35:00 2016 +0100
@@ -146,13 +146,13 @@
          * Application Service Providers...
          */
         'CorpusParole\Providers\AppServiceProvider',
-#        'CorpusParole\Providers\BusServiceProvider',
-#        'CorpusParole\Providers\ConfigServiceProvider',
         'CorpusParole\Providers\EventServiceProvider',
         'CorpusParole\Providers\RouteServiceProvider',
         'CorpusParole\Providers\RepositoryServiceProvider',
         'CorpusParole\Providers\GuzzleServiceProvider',
         'CorpusParole\Providers\ViafServiceProvider',
+        'CorpusParole\Providers\LexvoServiceProvider',
+        'CorpusParole\Providers\VersionServiceProvider',
 
     ],
 
--- a/server/src/config/corpusparole.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/config/corpusparole.php	Fri Jan 15 15:35:00 2016 +0100
@@ -1,6 +1,8 @@
 <?php
 
 $sesameBaseUrl = rtrim(env('CORPUSPAROLE_SESAME_BASE_URL'),'/').'/';
+$baseUrl = parse_url(env('APP_URL','http://localhost'), PHP_URL_PATH);
+$baseUrl = ($baseUrl && strlen($baseUrl)>0)?$baseUrl:"/";
 
 return [
     'sesame_base_url' => $sesameBaseUrl,
@@ -81,5 +83,43 @@
     ],
 
     'viaf_base_url' => 'http://viaf.org/viaf/',
-    'viaf_cache_expiration' => 60*24*30
+    'viaf_cache_expiration' => 60*24*30,
+
+    'lexvo_base_url' => 'http://lexvo.org/id/iso639-3/',
+    'lexvo_cache_expiration' => 60*24*30,
+    'lexvo_sesame_query_url' => $sesameBaseUrl.'repositories/'.env('CORPUSPAROLE_SESAME_LEXVO_REPOSITORY'),
+
+    'bo_client_environment' => [
+        "modulePrefix" => "bo-client",
+        "podModulePrefix" => "bo-client/pods",
+        "environment" => "production",
+        "baseURL" => $baseUrl,
+        "locationType" => "hash",
+        "i18n" => ["defaultLocale" => "fr"],
+        "EmberENV" => ["FEATURES"=>(object)[]], # to force json serialisation as object
+        "APP" => [
+            "bo-doc-viaf-autocomplete" => [
+                "viafQueryUrl" => "http://viaf.org/viaf/AutoSuggest?query=",
+                "viafBaseUrl" => "http://viaf.org/viaf/"
+            ],
+            "LOG_RESOLVER" => true,
+            "LOG_ACTIVE_GENERATION" => true,
+            "LOG_TRANSITIONS" => true,
+            "LOG_TRANSITIONS_INTERNAL" => true,
+            "LOG_VIEW_LOOKUPS" => true,
+            "name" => "bo-client",
+            "version" => "0.0.0 "
+        ],
+        "contentSecurityPolicy" => [
+            "default-src" => "'none'",
+            "script-src" => "'self'",
+            "font-src" => "'self'",
+            "connect-src" => "'self' *",
+            "img-src" => "'self'",
+            "style-src" => "'self' *",
+            "media-src" => "'self'"
+        ],
+        "contentSecurityPolicyHeader" => "Content-Security-Policy-Report-Only",
+        "exportApplicationGlobal" => true
+    ]
 ];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/config/version.php	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,12 @@
+<?php
+    return [
+        /*
+        |--------------------------------------------------------------------------
+        | Application version
+        |--------------------------------------------------------------------------
+        |
+        | Must be incremented as needed.
+        |
+        */
+        'version' => '0.0.1'
+    ];
--- a/server/src/gulpfile.js	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/gulpfile.js	Fri Jan 15 15:35:00 2016 +0100
@@ -1,5 +1,6 @@
 var gulp = require('gulp'),
-    elixir = require('laravel-elixir');
+    elixir = require('laravel-elixir')
+    del = require('del');
 
 
 var exec = require('child_process').execSync;
@@ -31,7 +32,19 @@
     gulp.src('../bo_client/dist/assets/*.js')
         .pipe(gulp.dest('public/js/vendor/'));
     gulp.src('../bo_client/dist/assets/*.css')
-        .pipe(gulp.dest('public/css/vendor/'));
+        .pipe(gulp.dest('public/css/'));
+    gulp.src('../bo_client/dist/fonts/**/*')
+        .pipe(gulp.dest('public/fonts/'));
+});
+
+gulp.task('copy-to-build', function() {
+    del(['../../build/root'], {force: true}, function(err, files) {
+        if(err) {
+            return;
+        }
+        gulp.src(['**/*','!vendor', '!vendor/**', '!node_modules', '!node_modules/**', '!.env', '!.git*'])
+            .pipe(gulp.dest('../../build/root/var/www/corpusdelaparole/corpus/'))
+    });
 });
 
 elixir(function(mix) {
--- a/server/src/public/css/app.css	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/public/css/app.css	Fri Jan 15 15:35:00 2016 +0100
@@ -1,6 +1,6 @@
 @charset "UTF-8";
 /*!
- * Bootstrap v3.3.5 (http://getbootstrap.com)
+ * Bootstrap v3.3.6 (http://getbootstrap.com)
  * Copyright 2011-2015 Twitter, Inc.
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  */
@@ -253,10 +253,10 @@
   -moz-osx-font-smoothing: grayscale; }
 
 .glyphicon-asterisk:before {
-  content: "\2a"; }
+  content: "\002a"; }
 
 .glyphicon-plus:before {
-  content: "\2b"; }
+  content: "\002b"; }
 
 .glyphicon-euro:before,
 .glyphicon-eur:before {
@@ -1051,7 +1051,7 @@
   -webkit-tap-highlight-color: transparent; }
 
 body {
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-family: "Roboto", Helvetica, Arial, sans-serif;
   font-size: 14px;
   line-height: 1.42857;
   color: #333333;
@@ -2320,6 +2320,9 @@
     color: #999; }
   .form-control::-webkit-input-placeholder {
     color: #999; }
+  .form-control::-ms-expand {
+    border: 0;
+    background-color: transparent; }
   .form-control[disabled], .form-control[readonly],
   fieldset[disabled] .form-control {
     background-color: #eeeeee;
@@ -2757,7 +2760,7 @@
 
 @media (min-width: 768px) {
   .form-horizontal .form-group-lg .control-label {
-    padding-top: 14.33333px;
+    padding-top: 11px;
     font-size: 18px; } }
 
 @media (min-width: 768px) {
@@ -2768,7 +2771,7 @@
 .btn {
   display: inline-block;
   margin-bottom: 0;
-  font-weight: normal;
+  font-weight: 300;
   text-align: center;
   vertical-align: middle;
   -ms-touch-action: manipulation;
@@ -2834,13 +2837,10 @@
   .btn-default:active, .btn-default.active,
   .open > .btn-default.dropdown-toggle {
     background-image: none; }
-  .btn-default.disabled, .btn-default.disabled:hover, .btn-default.disabled:focus, .btn-default.disabled.focus, .btn-default.disabled:active, .btn-default.disabled.active, .btn-default[disabled], .btn-default[disabled]:hover, .btn-default[disabled]:focus, .btn-default[disabled].focus, .btn-default[disabled]:active, .btn-default[disabled].active,
-  fieldset[disabled] .btn-default,
+  .btn-default.disabled:hover, .btn-default.disabled:focus, .btn-default.disabled.focus, .btn-default[disabled]:hover, .btn-default[disabled]:focus, .btn-default[disabled].focus,
   fieldset[disabled] .btn-default:hover,
   fieldset[disabled] .btn-default:focus,
-  fieldset[disabled] .btn-default.focus,
-  fieldset[disabled] .btn-default:active,
-  fieldset[disabled] .btn-default.active {
+  fieldset[disabled] .btn-default.focus {
     background-color: #fff;
     border-color: #ccc; }
   .btn-default .badge {
@@ -2874,13 +2874,10 @@
   .btn-primary:active, .btn-primary.active,
   .open > .btn-primary.dropdown-toggle {
     background-image: none; }
-  .btn-primary.disabled, .btn-primary.disabled:hover, .btn-primary.disabled:focus, .btn-primary.disabled.focus, .btn-primary.disabled:active, .btn-primary.disabled.active, .btn-primary[disabled], .btn-primary[disabled]:hover, .btn-primary[disabled]:focus, .btn-primary[disabled].focus, .btn-primary[disabled]:active, .btn-primary[disabled].active,
-  fieldset[disabled] .btn-primary,
+  .btn-primary.disabled:hover, .btn-primary.disabled:focus, .btn-primary.disabled.focus, .btn-primary[disabled]:hover, .btn-primary[disabled]:focus, .btn-primary[disabled].focus,
   fieldset[disabled] .btn-primary:hover,
   fieldset[disabled] .btn-primary:focus,
-  fieldset[disabled] .btn-primary.focus,
-  fieldset[disabled] .btn-primary:active,
-  fieldset[disabled] .btn-primary.active {
+  fieldset[disabled] .btn-primary.focus {
     background-color: #337ab7;
     border-color: #2e6da4; }
   .btn-primary .badge {
@@ -2914,13 +2911,10 @@
   .btn-success:active, .btn-success.active,
   .open > .btn-success.dropdown-toggle {
     background-image: none; }
-  .btn-success.disabled, .btn-success.disabled:hover, .btn-success.disabled:focus, .btn-success.disabled.focus, .btn-success.disabled:active, .btn-success.disabled.active, .btn-success[disabled], .btn-success[disabled]:hover, .btn-success[disabled]:focus, .btn-success[disabled].focus, .btn-success[disabled]:active, .btn-success[disabled].active,
-  fieldset[disabled] .btn-success,
+  .btn-success.disabled:hover, .btn-success.disabled:focus, .btn-success.disabled.focus, .btn-success[disabled]:hover, .btn-success[disabled]:focus, .btn-success[disabled].focus,
   fieldset[disabled] .btn-success:hover,
   fieldset[disabled] .btn-success:focus,
-  fieldset[disabled] .btn-success.focus,
-  fieldset[disabled] .btn-success:active,
-  fieldset[disabled] .btn-success.active {
+  fieldset[disabled] .btn-success.focus {
     background-color: #5cb85c;
     border-color: #4cae4c; }
   .btn-success .badge {
@@ -2954,13 +2948,10 @@
   .btn-info:active, .btn-info.active,
   .open > .btn-info.dropdown-toggle {
     background-image: none; }
-  .btn-info.disabled, .btn-info.disabled:hover, .btn-info.disabled:focus, .btn-info.disabled.focus, .btn-info.disabled:active, .btn-info.disabled.active, .btn-info[disabled], .btn-info[disabled]:hover, .btn-info[disabled]:focus, .btn-info[disabled].focus, .btn-info[disabled]:active, .btn-info[disabled].active,
-  fieldset[disabled] .btn-info,
+  .btn-info.disabled:hover, .btn-info.disabled:focus, .btn-info.disabled.focus, .btn-info[disabled]:hover, .btn-info[disabled]:focus, .btn-info[disabled].focus,
   fieldset[disabled] .btn-info:hover,
   fieldset[disabled] .btn-info:focus,
-  fieldset[disabled] .btn-info.focus,
-  fieldset[disabled] .btn-info:active,
-  fieldset[disabled] .btn-info.active {
+  fieldset[disabled] .btn-info.focus {
     background-color: #5bc0de;
     border-color: #46b8da; }
   .btn-info .badge {
@@ -2994,13 +2985,10 @@
   .btn-warning:active, .btn-warning.active,
   .open > .btn-warning.dropdown-toggle {
     background-image: none; }
-  .btn-warning.disabled, .btn-warning.disabled:hover, .btn-warning.disabled:focus, .btn-warning.disabled.focus, .btn-warning.disabled:active, .btn-warning.disabled.active, .btn-warning[disabled], .btn-warning[disabled]:hover, .btn-warning[disabled]:focus, .btn-warning[disabled].focus, .btn-warning[disabled]:active, .btn-warning[disabled].active,
-  fieldset[disabled] .btn-warning,
+  .btn-warning.disabled:hover, .btn-warning.disabled:focus, .btn-warning.disabled.focus, .btn-warning[disabled]:hover, .btn-warning[disabled]:focus, .btn-warning[disabled].focus,
   fieldset[disabled] .btn-warning:hover,
   fieldset[disabled] .btn-warning:focus,
-  fieldset[disabled] .btn-warning.focus,
-  fieldset[disabled] .btn-warning:active,
-  fieldset[disabled] .btn-warning.active {
+  fieldset[disabled] .btn-warning.focus {
     background-color: #f0ad4e;
     border-color: #eea236; }
   .btn-warning .badge {
@@ -3034,13 +3022,10 @@
   .btn-danger:active, .btn-danger.active,
   .open > .btn-danger.dropdown-toggle {
     background-image: none; }
-  .btn-danger.disabled, .btn-danger.disabled:hover, .btn-danger.disabled:focus, .btn-danger.disabled.focus, .btn-danger.disabled:active, .btn-danger.disabled.active, .btn-danger[disabled], .btn-danger[disabled]:hover, .btn-danger[disabled]:focus, .btn-danger[disabled].focus, .btn-danger[disabled]:active, .btn-danger[disabled].active,
-  fieldset[disabled] .btn-danger,
+  .btn-danger.disabled:hover, .btn-danger.disabled:focus, .btn-danger.disabled.focus, .btn-danger[disabled]:hover, .btn-danger[disabled]:focus, .btn-danger[disabled].focus,
   fieldset[disabled] .btn-danger:hover,
   fieldset[disabled] .btn-danger:focus,
-  fieldset[disabled] .btn-danger.focus,
-  fieldset[disabled] .btn-danger:active,
-  fieldset[disabled] .btn-danger.active {
+  fieldset[disabled] .btn-danger.focus {
     background-color: #d9534f;
     border-color: #d43f3a; }
   .btn-danger .badge {
@@ -3376,13 +3361,15 @@
 
 .btn-group-vertical > .btn:first-child:not(:last-child) {
   border-top-right-radius: 4px;
+  border-top-left-radius: 4px;
   border-bottom-right-radius: 0;
   border-bottom-left-radius: 0; }
 
 .btn-group-vertical > .btn:last-child:not(:first-child) {
-  border-bottom-left-radius: 4px;
   border-top-right-radius: 0;
-  border-top-left-radius: 0; }
+  border-top-left-radius: 0;
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius: 4px; }
 
 .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
   border-radius: 0; }
@@ -3433,6 +3420,8 @@
     float: left;
     width: 100%;
     margin-bottom: 0; }
+    .input-group .form-control:focus {
+      z-index: 3; }
 
 .input-group-addon,
 .input-group-btn,
@@ -4081,7 +4070,7 @@
   .pagination > li > a:hover, .pagination > li > a:focus,
   .pagination > li > span:hover,
   .pagination > li > span:focus {
-    z-index: 3;
+    z-index: 2;
     color: #23527c;
     background-color: #eeeeee;
     border-color: #ddd; }
@@ -4089,7 +4078,7 @@
   .pagination > .active > span,
   .pagination > .active > span:hover,
   .pagination > .active > span:focus {
-    z-index: 2;
+    z-index: 3;
     color: #fff;
     background-color: #337ab7;
     border-color: #337ab7;
@@ -4281,7 +4270,9 @@
     border-top-color: #d5d5d5; }
   .container .jumbotron,
   .container-fluid .jumbotron {
-    border-radius: 6px; }
+    border-radius: 6px;
+    padding-left: 15px;
+    padding-right: 15px; }
   .jumbotron .container {
     max-width: 100%; }
   @media screen and (min-width: 768px) {
@@ -5080,8 +5071,12 @@
 
 .modal-header {
   padding: 15px;
-  border-bottom: 1px solid #e5e5e5;
-  min-height: 16.42857px; }
+  border-bottom: 1px solid #e5e5e5; }
+  .modal-header:before, .modal-header:after {
+    content: " ";
+    display: table; }
+  .modal-header:after {
+    clear: both; }
 
 .modal-header .close {
   margin-top: -2px; }
@@ -5135,7 +5130,7 @@
   position: absolute;
   z-index: 1070;
   display: block;
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-family: "Roboto", Helvetica, Arial, sans-serif;
   font-style: normal;
   font-weight: normal;
   letter-spacing: normal;
@@ -5248,7 +5243,7 @@
   display: none;
   max-width: 276px;
   padding: 1px;
-  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-family: "Roboto", Helvetica, Arial, sans-serif;
   font-style: normal;
   font-weight: normal;
   letter-spacing: normal;
@@ -5432,7 +5427,8 @@
   font-size: 20px;
   color: #fff;
   text-align: center;
-  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); }
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+  background-color: transparent; }
   .carousel-control.left {
     background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
     background-repeat: repeat-x;
@@ -5525,14 +5521,14 @@
   .carousel-control .icon-next {
     width: 30px;
     height: 30px;
-    margin-top: -15px;
+    margin-top: -10px;
     font-size: 30px; }
   .carousel-control .glyphicon-chevron-left,
   .carousel-control .icon-prev {
-    margin-left: -15px; }
+    margin-left: -10px; }
   .carousel-control .glyphicon-chevron-right,
   .carousel-control .icon-next {
-    margin-right: -15px; }
+    margin-right: -10px; }
   .carousel-caption {
     left: 20%;
     right: 20%;
--- a/server/src/resources/assets/sass/_app-core.scss	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/resources/assets/sass/_app-core.scss	Fri Jan 15 15:35:00 2016 +0100
@@ -1,7 +1,7 @@
+$font-family-sans-serif: "Roboto", Helvetica, Arial, sans-serif !default;
+$btn-font-weight: 300;
 @import "bootstrap";
 
-$btn-font-weight: 300;
-$font-family-sans-serif: "Roboto", Helvetica, Arial, sans-serif;
 
 body, label, .checkbox label {
 	font-weight: 300;
--- a/server/src/resources/views/app.blade.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/resources/views/app.blade.php	Fri Jan 15 15:35:00 2016 +0100
@@ -1,66 +1,77 @@
+@inject('version', 'version')
 <!DOCTYPE html>
 <html lang="en">
 <head>
-	<meta charset="utf-8">
-	<meta http-equiv="X-UA-Compatible" content="IE=edge">
-	<meta name="viewport" content="width=device-width, initial-scale=1">
-	<title>@yield('title','Laravel')</title>
+    @section('meta')
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    @show
+    <title>@yield('title','Laravel')</title>
 
-	@section('css-assets')
-	<link href="{{ asset('/css/app.css') }}" rel="stylesheet">
+    @section('css-assets')
+    <link href="{{ asset('/css/app.css') }}" rel="stylesheet">
 
-	<!-- Fonts -->
-	<link href='//fonts.googleapis.com/css?family=Roboto:400,300' rel='stylesheet' type='text/css'>
-	@show
+    <!-- Fonts -->
+    <link href="{{ asset('/css/fonts.css')}}" rel='stylesheet' type='text/css'>
+    @show
 
-	<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
-	<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
-	<!--[if lt IE 9]>
-		<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
-		<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
-	<![endif]-->
+    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
+    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+    <!--[if lt IE 9]>
+        <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+        <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+    <![endif]-->
 </head>
 <body>
-	<nav class="navbar navbar-default">
-		<div class="container-fluid">
-			<div class="navbar-header">
-				<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
-					<span class="sr-only">Toggle Navigation</span>
-					<span class="icon-bar"></span>
-					<span class="icon-bar"></span>
-					<span class="icon-bar"></span>
-				</button>
-				<a class="navbar-brand" href="#">Laravel</a>
-			</div>
+    <nav class="navbar navbar-default">
+        <div class="container-fluid">
+            <div class="navbar-header">
+                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
+                    <span class="sr-only">Toggle Navigation</span>
+                    <span class="icon-bar"></span>
+                    <span class="icon-bar"></span>
+                    <span class="icon-bar"></span>
+                </button>
+                <a class="navbar-brand" href="/">Corpus de la Parole</a>
+            </div>
 
-			<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
-				<ul class="nav navbar-nav">
-					<li><a href="{{ url('/') }}">Home</a></li>
-				</ul>
+            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+                <ul class="nav navbar-nav">
+                    @section('nav-bar')
+                    <li><a href="{{ url('/bo/docs/') }}">Accueil B.O.</a></li>
+                    @show
+                </ul>
 
-				<ul class="nav navbar-nav navbar-right">
-					@if (Auth::guest())
-						<li><a href="{{ url('/auth/login') }}">Login</a></li>
-						<li><a href="{{ url('/auth/register') }}">Register</a></li>
-					@else
-						<li class="dropdown">
-							<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ Auth::user()->name }} <span class="caret"></span></a>
-							<ul class="dropdown-menu" role="menu">
-								<li><a href="{{ url('/auth/logout') }}">Logout</a></li>
-							</ul>
-						</li>
-					@endif
-				</ul>
-			</div>
-		</div>
-	</nav>
+                <ul class="nav navbar-nav navbar-right">
+                    @if (Auth::guest())
+                        <li><a href="{{ url('/auth/login') }}">Connexion</a></li>
+                    @else
+                        <li class="dropdown">
+                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">{{ Auth::user()->name }} <span class="caret"></span></a>
+                            <ul class="dropdown-menu" role="menu">
+                                <li><a href="{{ url('/auth/logout') }}">Déconnexion</a></li>
+                            </ul>
+                        </li>
+                    @endif
+                </ul>
+            </div>
+        </div>
+    </nav>
 
-	@yield('content')
+    @yield('content')
 
-	@section('js-assets')
-	<!-- Scripts -->
-	<script src="{{ asset('/js/vendor/jquery.js') }}"></script>
-	<script src="{{ asset('/js/vendor/bootstrap.js') }}"></script>
-	@show
+    <footer class="footer">
+      <div class="container-fluid">
+        @yield('footer')
+        <p class="text-muted small text-right">Réalisé par <a href="http://www.iri.centrepompidou.fr" target="_blank">IRI</a> - version {{ $version->version() }}</p>
+      </div>
+    </footer>
+
+    @section('js-assets')
+    <!-- Scripts -->
+    <script src="{{ asset('/js/vendor/jquery.js') }}"></script>
+    <script src="{{ asset('/js/vendor/bootstrap.js') }}"></script>
+    @show
 </body>
 </html>
--- a/server/src/resources/views/bo/docDetailClient.blade.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/resources/views/bo/docDetailClient.blade.php	Fri Jan 15 15:35:00 2016 +0100
@@ -2,19 +2,30 @@
 
 @section('title', 'Document detail')
 
-@section('css-assets')
+@section('meta')
+@parent
+<meta name="bo-client/config/environment" content="{!! rawurlencode($boClientEnv) !!}">
+<meta name="bo-client.backurl" content="{{ URL::previous() }}">
+<meta name="bo-client.docid" content="{{ $docid }}">
+@endsection
 
-	<link href="{{ asset('/css/vendor/bo-client-vendor.css') }}" rel="stylesheet">
-	<link href="{{ asset('/css/vendor/bo-client.css') }}" rel="stylesheet">
+@section('css-assets')
+	<link href="{{ asset('/css/bo-client-vendor.css') }}" rel="stylesheet">
+	<link href="{{ asset('/css/bo-client.css') }}" rel="stylesheet">
 @endsection
 
 @section('js-assets')
 	@parent
-
 	<script src="{{ asset('/js/vendor/bo-client-vendor.js') }}"></script>
 	<script src="{{ asset('/js/vendor/bo-client.js') }}"></script>
 @endsection
 
+@section('nav-bar')
+@parent
+<li><a href="{{ URL::previous() }}">Liste</a></li>
+@endsection
+
+
 @section('content')
 <div class="container" id="ember-container">
 </div>
--- a/server/src/resources/views/bo/docList.blade.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/resources/views/bo/docList.blade.php	Fri Jan 15 15:35:00 2016 +0100
@@ -10,16 +10,16 @@
                 <div class="panel-body">
                     <table class="table table-striped">
                         <thead>
-                            <tr><th>ID</th><th>TITLE</th><th>DATE</th></tr>
+                            <tr><th>ID</th><th>TITRE</th><th>LANG.</th><th>DATE</th></tr>
                         </thead>
                         <tbody>
                         @foreach ($docs as $doc)
                             <tr>
                                 <td>
-                                    <a href="{{ route('bo.docs.show',[ 'id' => $doc->getId()]) }}">{{ $doc->getId() }}</a><br>
                                     <a href="{{ route('bo.docs.client',[ 'id' => $doc->getId()]) }}#/doc/{{ $doc->getId() }}">{{ $doc->getId() }}</a>
                                 </td>
                                 <td>{{ $doc->getTitle() }}</td>
+                                <td><a href="{{ $doc->getLanguageValue() }}" target="_blank" title="{{ $languageNames[$doc->getLanguageValue()]}}">{{substr($doc->getLanguageValue(), 29)}}</td>
                                 <td>{{ $doc->getModified() }}</td>
                             </tr>
                         @endforeach
--- a/server/src/tests/Models/DocumentTest.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/tests/Models/DocumentTest.php	Fri Jan 15 15:35:00 2016 +0100
@@ -302,6 +302,31 @@
 
     }
 
+    public function testUpdateTitle() {
+        $doc = new Document("http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-CFPP2000_35_SOUND", $this->graph);
+
+        $oldTitle = $doc->getTitle();
+
+        $doc->setTitle("new title", "en");
+
+        $this->assertEquals("new title", $doc->getTitleValue());
+        $this->assertEquals("new title", $doc->getTitle()->getValue());
+        $this->assertEquals("en", $doc->getTitle()->getLang());
+
+        $this->assertTrue($doc->isDirty());
+        $this->assertEquals(1, $doc->deltaCount(), "There is one delta");
+
+        $delta = $doc->getDeltaList()[0];
+
+        $addedTitles = $delta->getAddedGraph()->allLiterals($doc->getProvidedCHO(), '<http://purl.org/dc/elements/1.1/title>');
+        $this->assertCount(1, $addedTitles);
+
+        $removedTitles = $delta->getDeletedGraph()->allLiterals($doc->getProvidedCHO(), '<http://purl.org/dc/elements/1.1/title>');
+        $this->assertCount(1, $removedTitles);
+
+
+    }
+
     public function testUpdateDiscourseTypesIsomorphic() {
 
         $newDiscourseTypes = ['oratory','dialogue','narrative'];
@@ -330,4 +355,81 @@
         }
     }
 
+    public function testSetContributors() {
+        $doc = new Document("http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-CFPP2000_35_SOUND", $this->graph);
+
+        $contributors = $doc->getContributors();
+
+        $contribList = [[
+            "name"=> "Guylaine Brun-Trigaud",
+            "url"=> "http://viaf.org/viaf/56666014",
+            "role"=> "http://www.language-archives.org/OLAC/1.1/data_inputter"
+        ], [
+            "name"=> "LDOR",
+            "url"=> null,
+            "role"=> "http://www.language-archives.org/OLAC/1.1/depositor"
+        ], [
+            "name"=> "Thésaurus Occitan",
+            "url"=> null,
+            "role"=> "http://www.language-archives.org/OLAC/1.1/depositor"
+        ], [
+            "name"=> "Équipe de Recherche en Syntaxe et Sémantique",
+            "url"=> null,
+            "role"=> "http://www.language-archives.org/OLAC/1.1/editor"
+        ], [
+            "name"=> "Bases, corpus, langage",
+            "url"=> null,
+            "role"=> "http://www.language-archives.org/OLAC/1.1/editor"
+        ], [
+            "name"=> "Patrick Sauzet",
+            "url"=> "http://viaf.org/viaf/51700729",
+            "role"=> "http://www.language-archives.org/OLAC/1.1/researcher"
+        ], [
+            "name"=> "Alazet, Pierre",
+            "url"=> null,
+            "role"=> "http://www.language-archives.org/OLAC/1.1/speaker"
+        ], [
+            "name"=> "Del Duca, Jeanne",
+            "url"=> null,
+            "role"=> "http://www.language-archives.org/OLAC/1.1/transcriber"
+        ], [
+            "name"=> "Jane Austen, 1775-1817",
+            "url"=> "http://viaf.org/viaf/102333412",
+            "role"=> "http://www.language-archives.org/OLAC/1.1/compiler"
+        ]];
+
+        $doc->setContributors($contribList);
+
+        $newContribs = $doc->getContributors();
+
+        $this->assertCount(9, $newContribs);
+
+        $this->assertTrue($doc->isDirty());
+        $this->assertEquals(1, $doc->deltaCount(), "There is one delta");
+
+        $delta = $doc->getDeltaList()[0];
+
+        $addedGraph = $delta->getAddedGraph();
+        $this->assertEquals(9, $addedGraph->countTriples());
+
+        $removedGraph = $delta->getDeletedGraph();
+        $this->assertEquals(count($contributors), $removedGraph->countTriples());
+
+        $foundJaneAusten = false;
+        foreach ($newContribs as $contribDef) {
+            if(!is_null($contribDef['nameLiteral'])) {
+                $lit = $contribDef['nameLiteral'];
+                $this->assertNull($lit->getDatatype(), "Data type must be null $lit");
+                $this->assertNotNull($lit->getLang(), "lang must not be null $lit");
+            }
+            if($contribDef['url'] == 'http://viaf.org/viaf/102333412') {
+                $this->assertNull($contribDef['name'], 'Name must be null');
+                $this->assertNull($contribDef['nameLiteral'], 'Name literal must be null');
+                $foundJaneAusten = true;
+            }
+        }
+        $this->assertTrue($foundJaneAusten, "Jane austenn not foud");
+
+    }
+
 }
--- a/server/src/tests/Repositories/DocumentRepositoryIntegrationTest.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/tests/Repositories/DocumentRepositoryIntegrationTest.php	Fri Jan 15 15:35:00 2016 +0100
@@ -152,6 +152,7 @@
         $this->assertInstanceOf(Document::class, $res, "Result must be of type Document");
         $this->assertEquals('crdo-ALA_738', $res->getId(), 'id should be crdo-ALA_738' );
         $this->assertNotNull($res->getGraph(), "Graph shoul not be null");
+        $this->assertEquals("http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-ALA_738",$res->getGraph()->getUri(), "uri of graph must be http://purl.org/poi/corpusdelaparole.huma-num.fr/crdo-ALA_738");
         $this->assertTrue(EasyRdf\Isomorphic::isomorphic($res->getGraph(),$returnedGraph));
     }
 
--- a/server/src/tests/Repositories/DocumentRepositoryTest.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/tests/Repositories/DocumentRepositoryTest.php	Fri Jan 15 15:35:00 2016 +0100
@@ -84,6 +84,7 @@
 
     public function tearDown() {
         parent::tearDown();
+        m::close();
     }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/tests/Services/LexvoResolverTest.php	Fri Jan 15 15:35:00 2016 +0100
@@ -0,0 +1,543 @@
+<?php
+
+use Mockery as m;
+
+use EasyRdf\Http;
+
+class LexvoResolverTest extends TestCase
+{
+    const LEXVO_EMPTY_RDF_RESP = <<<EOT
+{
+  "head" : {
+    "vars" : [
+      "s",
+      "o"
+    ]
+  },
+  "results" : {
+    "bindings" : [ ]
+  }
+}
+EOT;
+    const LEXVO_FRA_RDF_RESP = <<<EOT
+{
+  "head" : {
+    "vars" : [
+      "s",
+      "o"
+    ]
+  },
+  "results" : {
+    "bindings" : [
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/fra"
+        },
+        "o" : {
+          "xml:lang" : "en",
+          "type" : "literal",
+          "value" : "French"
+        }
+      },
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/fra"
+        },
+        "o" : {
+          "xml:lang" : "en",
+          "type" : "literal",
+          "value" : "French language"
+        }
+      },
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/fra"
+        },
+        "o" : {
+          "xml:lang" : "fr",
+          "type" : "literal",
+          "value" : "Français"
+        }
+      },
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/fra"
+        },
+        "o" : {
+          "xml:lang" : "fr",
+          "type" : "literal",
+          "value" : "français"
+        }
+      }
+    ]
+  }
+}
+EOT;
+
+const LEXVO_FRA2_RDF_RESP = <<<EOT
+{
+    "head" : {
+        "vars" : [
+            "s",
+            "o"
+        ]
+    },
+    "results" : {
+        "bindings" : [
+            {
+                "s" : {
+                    "type" : "uri",
+                    "value" : "http://lexvo.org/id/iso639-3/fra"
+                },
+                "o" : {
+                    "xml:lang" : "en",
+                    "type" : "literal",
+                    "value" : "French"
+                }
+            },
+            {
+                "s" : {
+                    "type" : "uri",
+                    "value" : "http://lexvo.org/id/iso639-3/fra"
+                },
+                "o" : {
+                    "xml:lang" : "en",
+                    "type" : "literal",
+                    "value" : "French language"
+                }
+            },
+            {
+                "s" : {
+                    "type" : "uri",
+                    "value" : "http://lexvo.org/id/iso639-3/fra"
+                },
+                "o" : {
+                    "xml:lang" : "fr",
+                    "type" : "literal",
+                    "value" : "français"
+                }
+            },
+            {
+                "s" : {
+                    "type" : "uri",
+                    "value" : "http://lexvo.org/id/iso639-3/fra"
+                },
+                "o" : {
+                    "xml:lang" : "fr",
+                    "type" : "literal",
+                    "value" : "Français"
+                }
+            }
+        ]
+    }
+}
+EOT;
+
+    const LEXVO_FRA_AFR_RDF_RESP = <<<EOT
+{
+  "head" : {
+    "vars" : [
+      "s",
+      "o"
+    ]
+  },
+  "results" : {
+    "bindings" : [
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/fra"
+        },
+        "o" : {
+          "xml:lang" : "en",
+          "type" : "literal",
+          "value" : "French"
+        }
+      },
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/fra"
+        },
+        "o" : {
+          "xml:lang" : "en",
+          "type" : "literal",
+          "value" : "French language"
+        }
+      },
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/fra"
+        },
+        "o" : {
+          "xml:lang" : "fr",
+          "type" : "literal",
+          "value" : "Français"
+        }
+      },
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/fra"
+        },
+        "o" : {
+          "xml:lang" : "fr",
+          "type" : "literal",
+          "value" : "français"
+        }
+      },
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/afr"
+        },
+        "o" : {
+          "xml:lang" : "en",
+          "type" : "literal",
+          "value" : "Afrikaans"
+        }
+      },
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/afr"
+        },
+        "o" : {
+          "xml:lang" : "fr",
+          "type" : "literal",
+          "value" : "Afrikaans"
+        }
+      },
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/afr"
+        },
+        "o" : {
+          "xml:lang" : "fr",
+          "type" : "literal",
+          "value" : "afrikaans"
+        }
+      }
+    ]
+  }
+}
+EOT;
+    const LEXVO_XAG_RDF_RESP = <<<EOT
+{
+  "head" : {
+    "vars" : [
+      "s",
+      "o"
+    ]
+  },
+  "results" : {
+    "bindings" : [
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/xag"
+        },
+        "o" : {
+          "xml:lang" : "en",
+          "type" : "literal",
+          "value" : "Aghwan"
+        }
+      },
+      {
+        "s" : {
+          "type" : "uri",
+          "value" : "http://lexvo.org/id/iso639-3/xag"
+        },
+        "o" : {
+          "xml:lang" : "en",
+          "type" : "literal",
+          "value" : "Caucasian Albanian language"
+        }
+      }
+    ]
+  }
+}
+EOT;
+
+const LEXVO_XAG2_RDF_RESP = <<<EOT
+{
+"head" : {
+"vars" : [
+  "s",
+  "o"
+]
+},
+"results" : {
+"bindings" : [
+    {
+      "s" : {
+        "type" : "uri",
+        "value" : "http://lexvo.org/id/iso639-3/xag"
+      },
+      "o" : {
+        "xml:lang" : "en",
+        "type" : "literal",
+        "value" : "Caucasian Albanian language"
+      }
+  },
+  {
+    "s" : {
+      "type" : "uri",
+      "value" : "http://lexvo.org/id/iso639-3/xag"
+    },
+    "o" : {
+      "xml:lang" : "en",
+      "type" : "literal",
+      "value" : "Aghwan"
+    }
+  }
+]
+}
+}
+EOT;
+
+    private function setUpSparqlClient($queryResult) {
+        $response = m::mock('EasyRdf\Http\Response')
+            ->shouldReceive('isSuccessful')->andReturn(true)
+            ->shouldReceive('getBody')->andReturn($queryResult)
+            ->shouldReceive('getStatus')->andReturn(200)
+            ->shouldReceive('getHeader')->andReturn('application/sparql-results+json;charset=UTF-8')
+            ->mock();
+        $this->httpClient = m::mock('EasyRdf\Http\Client')
+            ->shouldReceive('setConfig')
+            ->shouldReceive('resetParameters')
+            ->shouldReceive('setHeaders')//->with(m::on(function($headers) { print("HEADER => $headers\n"); return true;}),m::on(function($value) { print("VALUE => $value\n"); return true;}))
+            ->shouldReceive('setMethod')
+            ->shouldReceive('setUri')//->with(m::on(function($uri) { print($uri."\n"); return true;}))
+            ->shouldReceive('request')->andReturn($response)
+            ->mock();
+        Http::setDefaultHttpClient($this->httpClient);
+        $this->lexvoResolver = $this->app->make('CorpusParole\Services\LexvoResolverInterface');
+    }
+
+    public function setUp() {
+        parent::setUp();
+    }
+
+    public function tearDown() {
+        parent::tearDown();
+        m::close();
+    }
+
+    /**
+     * Just test the setup
+     *
+     * @return void
+     */
+    public function testSetUp() {
+        $this->assertTrue(true);
+    }
+
+    /**
+     * resolve french
+     * @return void
+     */
+    public function testResolveSingleId() {
+
+        $this->setUpSparqlClient(self::LEXVO_FRA_RDF_RESP);
+
+        $resName = $this->lexvoResolver->getName('fra');
+
+        $this->assertEquals('français', $resName, "Result must be français");
+    }
+
+    /**
+     * resolve french
+     * @return void
+     */
+    public function testResolveSingleIdFullURL() {
+
+        $this->setUpSparqlClient(self::LEXVO_FRA_RDF_RESP);
+
+        $resName = $this->lexvoResolver->getName('http://lexvo.org/id/iso639-3/fra');
+
+        $this->assertEquals('français', $resName, "Result must be français");
+    }
+
+    /**
+     * resolve foo
+     * @return void
+     */
+    public function testResolveBadId() {
+
+        $this->setUpSparqlClient(self::LEXVO_EMPTY_RDF_RESP);
+
+        $resName = $this->lexvoResolver->getName('foo');
+
+        $this->assertNull($resName, "Result must be null");
+    }
+
+    /**
+     * resolve foo
+     * @return void
+     * @expectedException        CorpusParole\Services\LexvoResolverException
+     * @expectedExceptionMessage the provided id "21dsasd;;" is not a Lexvo id
+     * @expectedExceptionCode 0
+     */
+    public function testResolveBadFormat() {
+
+        $this->setUpSparqlClient(self::LEXVO_EMPTY_RDF_RESP);
+
+        $resName = $this->lexvoResolver->getName('21dsasd;;');
+    }
+
+    /**
+     * resolve foo
+     * @return void
+     * @expectedException        CorpusParole\Services\LexvoResolverException
+     * @expectedExceptionMessage the provided id "http://sdsasd.org/foo" is not a Lexvo id
+     * @expectedExceptionCode 0
+     */
+    public function testResolveBadFormatFullId() {
+
+        $this->setUpSparqlClient(self::LEXVO_EMPTY_RDF_RESP);
+
+        $resName = $this->lexvoResolver->getName('http://sdsasd.org/foo');
+    }
+
+
+    /**
+     * resolve french
+     * @return void
+     */
+    public function testResolveMultipleId() {
+
+        $this->setUpSparqlClient(self::LEXVO_FRA_AFR_RDF_RESP);
+
+        $resnames = $this->lexvoResolver->getNames(['fra', 'afr']);
+
+        $this->assertCount(2, $resnames, "Must have 2 results");
+        $this->assertArrayHasKey('fra', $resnames);
+        $this->assertArrayHasKey('afr', $resnames);
+
+        $this->assertEquals('français', $resnames['fra'], "Result for fra must be français");
+        $this->assertEquals('afrikaans', $resnames['afr'], "Result for afr must be afrikaans");
+    }
+
+    /**
+     * resolve french
+     * @return void
+     */
+    public function testResolveMultipleFullId() {
+
+        $this->setUpSparqlClient(self::LEXVO_FRA_AFR_RDF_RESP);
+
+        $resnames = $this->lexvoResolver->getNames(['http://lexvo.org/id/iso639-3/fra', 'http://lexvo.org/id/iso639-3/afr']);
+
+        $this->assertCount(2, $resnames, "Must have 2 results");
+        $this->assertArrayHasKey('http://lexvo.org/id/iso639-3/fra', $resnames);
+        $this->assertArrayHasKey('http://lexvo.org/id/iso639-3/afr', $resnames);
+
+        $this->assertEquals('français', $resnames['http://lexvo.org/id/iso639-3/fra'], "Result for fra must be français");
+        $this->assertEquals('afrikaans', $resnames['http://lexvo.org/id/iso639-3/afr'], "Result for afr must be afrikaans");
+    }
+
+    /**
+     * check query
+     * @return void
+     */
+    public function testQuery() {
+
+        $expectedUri = config('corpusparole.lexvo_sesame_query_url')."?query=PREFIX+rdfs%3A+%3Chttp%3A%2F%2Fwww.w3.org%2F2000%2F01%2Frdf-schema%23%3E%0ASELECT+%3Fs+%3Fo+WHERE+%7B%7B%3Chttp%3A%2F%2Flexvo.org%2Fid%2Fiso639-3%2Ffra%3E+rdfs%3Alabel+%3Fo.+%3Fs+rdfs%3Alabel+%3Fo+FILTER%28%3Fs+%3D+%3Chttp%3A%2F%2Flexvo.org%2Fid%2Fiso639-3%2Ffra%3E+%26%26+%28lang%28%3Fo%29+%3D+%22fr%22+%7C%7C+lang%28%3Fo%29+%3D+%22en%22%29%29%7D+UNION+%7B%3Chttp%3A%2F%2Flexvo.org%2Fid%2Fiso639-3%2Fafr%3E+rdfs%3Alabel+%3Fo.+%3Fs+rdfs%3Alabel+%3Fo+FILTER%28%3Fs+%3D+%3Chttp%3A%2F%2Flexvo.org%2Fid%2Fiso639-3%2Fafr%3E+%26%26+%28lang%28%3Fo%29+%3D+%22fr%22+%7C%7C+lang%28%3Fo%29+%3D+%22en%22%29%29%7D%7D";
+        $response = m::mock('EasyRdf\Http\Response')
+            ->shouldReceive('isSuccessful')->andReturn(true)
+            ->shouldReceive('getBody')->andReturn(self::LEXVO_EMPTY_RDF_RESP) //result not important
+            ->shouldReceive('getStatus')->andReturn(200)
+            ->shouldReceive('getHeader')->andReturn('application/sparql-results+json;charset=UTF-8')
+            ->mock();
+        $this->httpClient = m::mock('EasyRdf\Http\Client')
+            ->shouldReceive('setConfig')
+            ->shouldReceive('resetParameters')
+            ->shouldReceive('setHeaders')//->with(m::on(function($headers) { print("HEADER => $headers\n"); return true;}),m::on(function($value) { print("VALUE => $value\n"); return true;}))
+            ->shouldReceive('setMethod')
+            ->shouldReceive('setUri')
+            ->with($expectedUri)//->with(m::on(function($uri) { print($uri."\n"); return true;}))
+            ->shouldReceive('request')->andReturn($response)
+            ->mock();
+        Http::setDefaultHttpClient($this->httpClient);
+        $this->lexvoResolver = $this->app->make('CorpusParole\Services\LexvoResolverInterface');
+
+        $resName = $this->lexvoResolver->getNames(['fra','afr']);
+
+    }
+
+    /**
+     * check query
+     * @return void
+     */
+    public function testQueryFullId() {
+
+        $expectedUri = config('corpusparole.lexvo_sesame_query_url')."?query=PREFIX+rdfs%3A+%3Chttp%3A%2F%2Fwww.w3.org%2F2000%2F01%2Frdf-schema%23%3E%0ASELECT+%3Fs+%3Fo+WHERE+%7B%7B%3Chttp%3A%2F%2Flexvo.org%2Fid%2Fiso639-3%2Ffra%3E+rdfs%3Alabel+%3Fo.+%3Fs+rdfs%3Alabel+%3Fo+FILTER%28%3Fs+%3D+%3Chttp%3A%2F%2Flexvo.org%2Fid%2Fiso639-3%2Ffra%3E+%26%26+%28lang%28%3Fo%29+%3D+%22fr%22+%7C%7C+lang%28%3Fo%29+%3D+%22en%22%29%29%7D+UNION+%7B%3Chttp%3A%2F%2Flexvo.org%2Fid%2Fiso639-3%2Fafr%3E+rdfs%3Alabel+%3Fo.+%3Fs+rdfs%3Alabel+%3Fo+FILTER%28%3Fs+%3D+%3Chttp%3A%2F%2Flexvo.org%2Fid%2Fiso639-3%2Fafr%3E+%26%26+%28lang%28%3Fo%29+%3D+%22fr%22+%7C%7C+lang%28%3Fo%29+%3D+%22en%22%29%29%7D%7D";
+        $response = m::mock('EasyRdf\Http\Response')
+            ->shouldReceive('isSuccessful')->andReturn(true)
+            ->shouldReceive('getBody')->andReturn(self::LEXVO_EMPTY_RDF_RESP) //result not important
+            ->shouldReceive('getStatus')->andReturn(200)
+            ->shouldReceive('getHeader')->andReturn('application/sparql-results+json;charset=UTF-8')
+            ->mock();
+        $this->httpClient = m::mock('EasyRdf\Http\Client')
+            ->shouldReceive('setConfig')
+            ->shouldReceive('resetParameters')
+            ->shouldReceive('setHeaders')//->with(m::on(function($headers) { print("HEADER => $headers\n"); return true;}),m::on(function($value) { print("VALUE => $value\n"); return true;}))
+            ->shouldReceive('setMethod')
+            ->shouldReceive('setUri')
+            ->with($expectedUri)//->with(m::on(function($uri) { print($uri."\n"); return true;}))
+            ->shouldReceive('request')->andReturn($response)
+            ->mock();
+        Http::setDefaultHttpClient($this->httpClient);
+        $this->lexvoResolver = $this->app->make('CorpusParole\Services\LexvoResolverInterface');
+
+        $resName = $this->lexvoResolver->getNames(['http://lexvo.org/id/iso639-3/fra','http://lexvo.org/id/iso639-3/afr']);
+
+    }
+
+    /**
+     * resolve french
+     * @return void
+     */
+    public function testResolveSingleIdNofr() {
+
+        $this->setUpSparqlClient(self::LEXVO_XAG_RDF_RESP);
+
+        $resName = $this->lexvoResolver->getName('xag');
+
+        $this->assertEquals('aghwan', $resName, "Result must be aghwan");
+    }
+
+    /**
+     * resolve french
+     * @return void
+     */
+    public function testResolveSingleIdOrderNotFr() {
+
+        $this->setUpSparqlClient(self::LEXVO_XAG2_RDF_RESP);
+
+        $resName = $this->lexvoResolver->getName('xag');
+
+        $this->assertEquals('aghwan', $resName, "Result must be aghwan");
+    }
+
+    /**
+     * resolve french
+     * @return void
+     */
+    public function testResolveSingleIdOrder() {
+
+        $this->setUpSparqlClient(self::LEXVO_FRA2_RDF_RESP);
+
+        $resName = $this->lexvoResolver->getName('fra');
+
+        $this->assertEquals('français', $resName, "Result must be français");
+    }
+
+}
--- a/server/src/tests/Services/ViafResolverTest.php	Fri Jan 15 15:27:56 2016 +0100
+++ b/server/src/tests/Services/ViafResolverTest.php	Fri Jan 15 15:35:00 2016 +0100
@@ -1,9 +1,5 @@
 <?php
 
-use Illuminate\Foundation\Testing\WithoutMiddleware;
-use Illuminate\Foundation\Testing\DatabaseMigrations;
-use Illuminate\Foundation\Testing\DatabaseTransactions;
-
 use GuzzleHttp\Client;
 use GuzzleHttp\Handler\MockHandler;
 use GuzzleHttp\HandlerStack;