From 50aa90a07262918374586f711f1ae9bb61899a18 Mon Sep 17 00:00:00 2001 From: Gina Trapani Date: Sun, 24 Jan 2016 14:44:38 -0500 Subject: [PATCH] Update Vagrant vm (requires Vagrant 1.8) --- Vagrantfile | 11 +- puphpet/config.yaml | 107 +- puphpet/files/EXEC-README.txt | 4 +- puphpet/files/dot/.git-completion.bash | 2712 +++++++++++ puphpet/files/dot/.git-prompt.sh | 412 ++ puphpet/files/exec-preprovision/empty | 0 puphpet/puppet/Puppetfile | 73 +- puphpet/puppet/Puppetfile.lock | 226 +- puphpet/puppet/hiera.yaml | 1 + puphpet/puppet/{nodes => manifests}/Apache.pp | 74 +- .../puppet/{nodes => manifests}/Beanstalkd.pp | 0 .../puppet/{nodes => manifests}/Blackfire.pp | 0 puphpet/puppet/{nodes => manifests}/Cron.pp | 0 puphpet/puppet/{nodes => manifests}/Drush.pp | 0 .../{nodes => manifests}/ElasticSearch.pp | 16 + .../puppet/{nodes => manifests}/Firewall.pp | 12 +- puphpet/puppet/{nodes => manifests}/Hhvm.pp | 4 +- puphpet/puppet/{nodes => manifests}/Locale.pp | 17 +- puphpet/puppet/manifests/MailHog.pp | 60 + .../puppet/{nodes => manifests}/MariaDb.pp | 34 +- puphpet/puppet/manifests/MongoDb.pp | 102 + puphpet/puppet/{nodes => manifests}/Mysql.pp | 22 +- puphpet/puppet/{nodes => manifests}/Nginx.pp | 111 +- puphpet/puppet/manifests/NodeJs.pp | 101 + puphpet/puppet/{nodes => manifests}/Php.pp | 59 +- .../puppet/{nodes => manifests}/Postgresql.pp | 5 +- puphpet/puppet/{nodes => manifests}/Python.pp | 1 + .../puppet/{nodes => manifests}/RabbitMQ.pp | 26 +- puphpet/puppet/{nodes => manifests}/Redis.pp | 12 +- puphpet/puppet/manifests/Ruby.pp | 38 + puphpet/puppet/{nodes => manifests}/Server.pp | 41 +- puphpet/puppet/{nodes => manifests}/Solr.pp | 5 +- puphpet/puppet/{nodes => manifests}/Sqlite.pp | 9 +- .../{nodes => manifests}/UsersGroups.pp | 0 puphpet/puppet/{nodes => manifests}/WPCli.pp | 0 puphpet/puppet/{nodes => manifests}/Xdebug.pp | 3 +- puphpet/puppet/{nodes => manifests}/Xhprof.pp | 2 +- puphpet/puppet/{ => manifests}/site.pp | 24 +- puphpet/puppet/modules/apache/.fixtures.yml | 4 +- puphpet/puppet/modules/apache/.gitignore | 9 + puphpet/puppet/modules/apache/.sync.yml | 5 - puphpet/puppet/modules/apache/.travis.yml | 15 +- puphpet/puppet/modules/apache/CHANGELOG.md | 157 +- puphpet/puppet/modules/apache/Gemfile | 25 +- puphpet/puppet/modules/apache/README.md | 3992 ++++++++++------- .../puppet/modules/apache/README.passenger.md | 63 +- .../apache/{tests => examples}/apache.pp | 0 .../modules/apache/{tests => examples}/dev.pp | 0 .../apache/{tests => examples}/init.pp | 0 .../{tests => examples}/mod_load_params.pp | 0 .../apache/{tests => examples}/mods.pp | 0 .../apache/{tests => examples}/mods_custom.pp | 0 .../modules/apache/{tests => examples}/php.pp | 0 .../apache/{tests => examples}/vhost.pp | 8 + .../{tests => examples}/vhost_directories.pp | 0 .../modules/apache/examples/vhost_filter.pp | 17 + .../{tests => examples}/vhost_ip_based.pp | 0 .../{tests => examples}/vhost_proxypass.pp | 0 .../apache/{tests => examples}/vhost_ssl.pp | 0 .../vhosts_without_listen.pp | 0 .../functions/validate_apache_log_level.rb | 27 + .../modules/apache/manifests/custom_config.pp | 3 +- .../modules/apache/manifests/default_mods.pp | 27 +- .../puppet/modules/apache/manifests/dev.pp | 13 +- .../puppet/modules/apache/manifests/init.pp | 41 +- .../puppet/modules/apache/manifests/mod.pp | 39 +- .../modules/apache/manifests/mod/alias.pp | 30 +- .../apache/manifests/mod/auth_mellon.pp | 24 + .../apache/manifests/mod/authn_core.pp | 7 + .../apache/manifests/mod/authz_default.pp | 10 +- .../modules/apache/manifests/mod/cgid.pp | 6 +- .../modules/apache/manifests/mod/deflate.pp | 3 +- .../apache/manifests/mod/disk_cache.pp | 41 +- .../modules/apache/manifests/mod/expires.pp | 19 +- .../apache/manifests/mod/ext_filter.pp | 24 + .../modules/apache/manifests/mod/fcgid.pp | 13 +- .../modules/apache/manifests/mod/geoip.pp | 31 + .../modules/apache/manifests/mod/passenger.pp | 7 + .../modules/apache/manifests/mod/prefork.pp | 2 +- .../apache/manifests/mod/proxy_connect.pp | 2 +- .../modules/apache/manifests/mod/remoteip.pp | 27 + .../modules/apache/manifests/mod/security.pp | 1 + .../modules/apache/manifests/mod/ssl.pp | 21 +- .../modules/apache/manifests/mod/userdir.pp | 1 + .../modules/apache/manifests/mod/worker.pp | 58 +- .../modules/apache/manifests/mod/wsgi.pp | 2 +- .../puppet/modules/apache/manifests/mpm.pp | 34 +- .../modules/apache/manifests/package.pp | 14 +- .../puppet/modules/apache/manifests/params.pp | 98 +- .../modules/apache/manifests/service.pp | 8 +- .../modules/apache/manifests/version.pp | 9 +- .../puppet/modules/apache/manifests/vhost.pp | 127 +- puphpet/puppet/modules/apache/metadata.json | 22 +- .../spec/acceptance/apache_parameters_spec.rb | 2 +- .../apache/spec/acceptance/basic_spec.rb | 12 - .../apache/spec/acceptance/class_spec.rb | 2 +- .../spec/acceptance/custom_config_spec.rb | 21 + .../spec/acceptance/mod_passenger_spec.rb | 110 - .../spec/acceptance/mod_security_spec.rb | 35 +- .../spec/acceptance/nodesets/default.yml | 5 +- .../apache/spec/acceptance/vhost_spec.rb | 186 +- .../apache/spec/classes/apache_spec.rb | 89 +- .../modules/apache/spec/classes/dev_spec.rb | 29 +- .../spec/classes/mod/auth_mellon_spec.rb | 87 + .../apache/spec/classes/mod/dev_spec.rb | 20 +- .../apache/spec/classes/mod/disk_cache.rb | 111 + .../apache/spec/classes/mod/expires_spec.rb | 84 + .../spec/classes/mod/ext_filter_spec.rb | 66 + .../apache/spec/classes/mod/fcgid_spec.rb | 27 +- .../apache/spec/classes/mod/passenger_spec.rb | 12 + .../apache/spec/classes/mod/peruser_spec.rb | 2 +- .../spec/classes/mod/proxy_connect_spec.rb | 18 +- .../apache/spec/classes/mod/remoteip_spec.rb | 53 + .../apache/spec/classes/mod/ssl_spec.rb | 27 +- .../apache/spec/classes/mod/worker_spec.rb | 5 +- .../apache/spec/classes/mod/wsgi_spec.rb | 4 +- .../apache/spec/classes/params_spec.rb | 5 +- .../apache/spec/classes/service_spec.rb | 16 +- .../apache/spec/defines/custom_config_spec.rb | 14 +- .../modules/apache/spec/defines/vhost_spec.rb | 248 +- .../apache/spec/spec_helper_acceptance.rb | 37 +- .../functions/validate_apache_log_level.rb | 39 + .../modules/apache/templates/httpd.conf.erb | 16 +- .../apache/templates/mod/auth_mellon.conf.erb | 21 + .../apache/templates/mod/disk_cache.conf.erb | 12 +- .../apache/templates/mod/expires.conf.erb | 11 + .../apache/templates/mod/ext_filter.conf.erb | 6 + .../apache/templates/mod/geoip.conf.erb | 25 + .../apache/templates/mod/passenger.conf.erb | 3 + .../apache/templates/mod/remoteip.conf.erb | 23 + .../apache/templates/mod/security.conf.erb | 5 +- .../modules/apache/templates/mod/ssl.conf.erb | 3 + .../{fcgid.conf.erb => unixd_fcgid.conf.erb} | 0 .../apache/templates/mod/userdir.conf.erb | 8 +- .../apache/templates/mod/worker.conf.erb | 1 + .../templates/vhost/_additional_includes.erb | 5 +- .../apache/templates/vhost/_auth_kerb.erb | 23 + .../apache/templates/vhost/_directories.erb | 51 +- .../apache/templates/vhost/_docroot.erb | 2 +- .../apache/templates/vhost/_file_header.erb | 2 +- .../apache/templates/vhost/_filters.erb | 10 + .../apache/templates/vhost/_limits.erb | 5 + .../templates/vhost/_passenger_base_uris.erb | 7 + .../modules/apache/templates/vhost/_proxy.erb | 13 +- .../modules/apache/templates/vhost/_ssl.erb | 8 +- puphpet/puppet/modules/apt/.fixtures.yml | 2 +- puphpet/puppet/modules/apt/.gitignore | 9 + puphpet/puppet/modules/apt/.sync.yml | 23 +- puphpet/puppet/modules/apt/.travis.yml | 9 +- puphpet/puppet/modules/apt/CHANGELOG.md | 136 + puphpet/puppet/modules/apt/Gemfile | 26 +- puphpet/puppet/modules/apt/README.md | 756 ++-- .../puppet/modules/apt/examples/backports.pp | 11 + .../puppet/modules/apt/examples/builddep.pp | 3 + .../modules/apt/examples/debian_testing.pp | 18 + .../modules/apt/examples/debian_unstable.pp | 18 + .../modules/apt/examples/disable_keys.pp | 5 + .../modules/apt/examples/fancy_progress.pp | 4 + puphpet/puppet/modules/apt/examples/force.pp | 28 + puphpet/puppet/modules/apt/examples/hold.pp | 5 + puphpet/puppet/modules/apt/examples/key.pp | 6 + .../modules/apt/{tests => examples}/pin.pp | 0 .../modules/apt/{tests => examples}/ppa.pp | 0 .../puppet/modules/apt/examples/release.pp | 4 + puphpet/puppet/modules/apt/examples/source.pp | 35 + .../apt/examples/unattended_upgrades.pp | 1 + .../apt/lib/facter/apt_reboot_required.rb | 7 + .../lib/puppet/provider/apt_key/apt_key.rb | 13 +- .../modules/apt/lib/puppet/type/apt_key.rb | 4 +- .../puppet/modules/apt/manifests/backports.pp | 127 +- .../puppet/modules/apt/manifests/builddep.pp | 16 - puphpet/puppet/modules/apt/manifests/conf.pp | 26 +- .../modules/apt/manifests/debian/testing.pp | 21 - .../modules/apt/manifests/debian/unstable.pp | 21 - puphpet/puppet/modules/apt/manifests/force.pp | 60 - puphpet/puppet/modules/apt/manifests/hold.pp | 54 - puphpet/puppet/modules/apt/manifests/init.pp | 293 +- puphpet/puppet/modules/apt/manifests/key.pp | 151 +- .../puppet/modules/apt/manifests/params.pp | 185 +- puphpet/puppet/modules/apt/manifests/pin.pp | 37 +- puphpet/puppet/modules/apt/manifests/ppa.pp | 57 +- .../puppet/modules/apt/manifests/release.pp | 17 - .../puppet/modules/apt/manifests/setting.pp | 64 + .../puppet/modules/apt/manifests/source.pp | 181 +- .../apt/manifests/unattended_upgrades.pp | 81 - .../puppet/modules/apt/manifests/update.pp | 77 +- puphpet/puppet/modules/apt/metadata.json | 12 +- .../spec/acceptance/apt_key_provider_spec.rb | 195 +- .../modules/apt/spec/acceptance/apt_spec.rb | 43 +- .../apt/spec/classes/apt_backports_spec.rb | 268 ++ .../modules/apt/spec/classes/apt_spec.rb | 363 +- .../apt/spec/classes/apt_update_spec.rb | 136 +- .../apt/spec/classes/backports_spec.rb | 177 - .../apt/spec/classes/debian_testing_spec.rb | 15 - .../apt/spec/classes/debian_unstable_spec.rb | 15 - .../modules/apt/spec/classes/params_spec.rb | 26 +- .../modules/apt/spec/classes/release_spec.rb | 23 - .../spec/classes/unattended_upgrades_spec.rb | 211 - .../modules/apt/spec/defines/builddep_spec.rb | 19 - .../modules/apt/spec/defines/conf_spec.rb | 44 +- .../modules/apt/spec/defines/force_spec.rb | 102 - .../modules/apt/spec/defines/hold_spec.rb | 97 - .../apt/spec/defines/key_compat_spec.rb | 316 ++ .../modules/apt/spec/defines/key_spec.rb | 185 +- .../modules/apt/spec/defines/pin_spec.rb | 62 +- .../modules/apt/spec/defines/ppa_spec.rb | 176 +- .../modules/apt/spec/defines/setting_spec.rb | 115 + .../apt/spec/defines/source_compat_spec.rb | 158 + .../modules/apt/spec/defines/source_spec.rb | 382 +- .../apt/spec/spec_helper_acceptance.rb | 16 +- .../spec/unit/facter/apt_has_updates_spec.rb | 10 +- .../unit/facter/apt_package_updates_spec.rb | 6 +- .../unit/facter/apt_reboot_required_spec.rb | 25 + .../unit/facter/apt_security_updates_spec.rb | 4 +- .../facter/apt_update_last_success_spec.rb | 4 +- .../apt/spec/unit/facter/apt_updates_spec.rb | 4 +- .../apt/spec/unit/puppet/type/apt_key_spec.rb | 26 +- .../modules/apt/templates/10periodic.erb | 15 - .../apt/templates/50unattended-upgrades.erb | 62 - .../modules/apt/templates/_conf_header.erb | 1 + .../puppet/modules/apt/templates/pin.pref.erb | 2 +- .../modules/apt/templates/progressbar.erb | 1 - .../puppet/modules/apt/templates/proxy.erb | 5 +- .../puppet/modules/apt/templates/release.erb | 1 - .../modules/apt/templates/source.list.erb | 16 +- .../puppet/modules/apt/templates/unauth.erb | 1 - puphpet/puppet/modules/apt/tests/builddep.pp | 2 - .../modules/apt/tests/debian/testing.pp | 2 - .../modules/apt/tests/debian/unstable.pp | 2 - puphpet/puppet/modules/apt/tests/force.pp | 17 - puphpet/puppet/modules/apt/tests/init.pp | 1 - puphpet/puppet/modules/apt/tests/key.pp | 6 - puphpet/puppet/modules/apt/tests/params.pp | 1 - puphpet/puppet/modules/apt/tests/release.pp | 4 - puphpet/puppet/modules/apt/tests/source.pp | 29 - .../modules/apt/tests/unattended_upgrades.pp | 1 - .../modules/beanstalkd/manifests/init.pp | 4 +- .../modules/beanstalkd/manifests/init.pp | 4 +- .../puppet/modules/blackfire/.fixtures.yml | 2 +- puphpet/puppet/modules/blackfire/.gitignore | 5 + puphpet/puppet/modules/blackfire/.travis.yml | 19 +- puphpet/puppet/modules/blackfire/CHANGELOG.md | 24 + puphpet/puppet/modules/blackfire/Gemfile | 2 +- puphpet/puppet/modules/blackfire/LICENSE | 13 + puphpet/puppet/modules/blackfire/README.md | 8 +- .../modules/blackfire/manifests/agent.pp | 6 +- .../modules/blackfire/manifests/init.pp | 2 +- .../puppet/modules/blackfire/manifests/php.pp | 3 +- .../modules/blackfire/manifests/php/config.pp | 2 +- .../modules/blackfire/manifests/repo.pp | 31 +- .../puppet/modules/blackfire/metadata.json | 10 +- .../blackfire/spec/acceptance/agent_spec.rb | 10 +- .../acceptance/nodesets/debian-80-x64.yml | 11 + .../blackfire/spec/classes/init_spec.rb | 52 +- puphpet/puppet/modules/composer/.gitignore | 12 + .../modules/composer/templates/install.erb | 1 + puphpet/puppet/modules/concat/.gitignore | 7 + puphpet/puppet/modules/datacat/Changes | 61 + puphpet/puppet/modules/datacat/Gemfile | 22 + puphpet/puppet/modules/datacat/NOTES.md | 4 + puphpet/puppet/modules/datacat/README.md | 125 + puphpet/puppet/modules/datacat/Rakefile | 12 + puphpet/puppet/modules/datacat/TODO.md | 11 + puphpet/puppet/modules/datacat/checksums.json | 32 + .../puppet/parser/functions/template_body.rb | 8 + .../datacat_collector/datacat_collector.rb | 74 + .../datacat_fragment/datacat_fragment.rb | 3 + .../lib/puppet/type/datacat_collector.rb | 62 + .../lib/puppet/type/datacat_fragment.rb | 20 + .../datacat/lib/puppet_x/richardc/datacat.rb | 45 + .../puppet/modules/datacat/manifests/init.pp | 95 + puphpet/puppet/modules/datacat/metadata.json | 14 + .../datacat/spec/classes/demo1_spec.rb | 8 + .../datacat/spec/defines/datacat_spec.rb | 27 + .../fixtures/modules/demo1/manifests/init.pp | 18 + .../modules/demo1/templates/sheeps.erb | 3 + .../fixtures/modules/demo2/manifests/init.pp | 18 + .../modules/demo2/templates/merging.erb | 2 + .../fixtures/modules/demo3/manifests/init.pp | 22 + .../demo3/templates/hostgroups.cfg.erb | 7 + .../fixtures/modules/issue1/manifests/init.pp | 6 + .../issue1/templates/refers_to_scope.erb | 7 + .../modules/template_body/templates/test1.erb | 1 + .../spec/functions/template_body_spec.rb | 6 + .../modules/datacat/spec/spec_helper.rb | 1 + .../datacat/spec/spec_helper_system.rb | 23 + .../modules/datacat/spec/system/basic_spec.rb | 58 + .../spec/unit/type/datacat_collector_spec.rb | 163 + .../modules/elasticsearch/.fixtures.yml | 10 +- .../puppet/modules/elasticsearch/.gitignore | 12 + .../puppet/modules/elasticsearch/.pmtignore | 6 + .../puppet/modules/elasticsearch/.travis.yml | 33 - .../puppet/modules/elasticsearch/CHANGELOG | 91 - .../puppet/modules/elasticsearch/CHANGELOG.md | 446 ++ .../modules/elasticsearch/CONTRIBUTING.md | 38 +- puphpet/puppet/modules/elasticsearch/Gemfile | 31 +- puphpet/puppet/modules/elasticsearch/LICENSE | 2 +- .../puppet/modules/elasticsearch/Modulefile | 9 - .../puppet/modules/elasticsearch/README.md | 603 ++- puphpet/puppet/modules/elasticsearch/Rakefile | 31 +- .../elasticsearch/lib/facter/es_facts.rb | 99 + .../puppet/parser/functions/array_suffix.rb | 45 + .../lib/puppet/parser/functions/plugin_dir.rb | 43 + .../provider/elasticsearch_plugin/plugin.rb | 131 + .../es_instance_conn_validator/tcp_port.rb | 51 + .../lib/puppet/type/elasticsearch_plugin.rb | 31 + .../puppet/type/es_instance_conn_validator.rb | 38 + .../lib/puppet/util/es_instance_validator.rb | 36 + .../modules/elasticsearch/manifests/config.pp | 99 +- .../modules/elasticsearch/manifests/init.pp | 307 +- .../elasticsearch/manifests/instance.pp | 317 ++ .../modules/elasticsearch/manifests/java.pp | 50 - .../elasticsearch/manifests/package.pp | 122 +- .../modules/elasticsearch/manifests/params.pp | 144 +- .../modules/elasticsearch/manifests/plugin.pp | 109 +- .../modules/elasticsearch/manifests/python.pp | 9 +- .../modules/elasticsearch/manifests/repo.pp | 106 + .../modules/elasticsearch/manifests/ruby.pp | 10 +- .../modules/elasticsearch/manifests/script.pp | 55 + .../elasticsearch/manifests/service.pp | 76 +- .../elasticsearch/manifests/service/init.pp | 151 +- .../manifests/service/systemd.pp | 216 + .../elasticsearch/manifests/template.pp | 83 +- .../modules/elasticsearch/metadata.json | 96 + .../spec/acceptance/001_basic_spec.rb | 8 + .../spec/acceptance/002_class_spec.rb | 149 + .../spec/acceptance/003_template_spec.rb | 70 + .../spec/acceptance/004_plugin_spec.rb | 299 ++ .../spec/acceptance/009_datapath_spec.rb | 361 ++ .../spec/acceptance/010_pkg_url_spec.rb | 167 + .../spec/acceptance/011_service_spec.rb | 77 + .../spec/acceptance/012_instances_spec.rb | 197 + .../spec/acceptance/013_config_spec.rb | 83 + .../spec/acceptance/014_hiera_spec.rb | 181 + .../spec/acceptance/015_staged_removal.rb | 69 + .../spec/acceptance/016_package_pin_spec.rb | 107 + .../acceptance/017_restart_on_change_spec.rb | 144 + .../spec/acceptance/020_usergroup_spec.rb | 91 + .../spec/acceptance/021_es2x_spec.rb | 351 ++ .../spec/acceptance/integration001.rb | 153 + .../spec/acceptance/nodesets/centos-6-x64.yml | 16 + .../spec/acceptance/nodesets/centos-7-x64.yml | 15 + .../spec/acceptance/nodesets/debian-6-x64.yml | 16 + .../spec/acceptance/nodesets/debian-7-x64.yml | 16 + .../spec/acceptance/nodesets/debian-8-x64.yml | 16 + .../acceptance/nodesets/opensuse-121-x64.yml | 12 + .../acceptance/nodesets/opensuse-131-x64.yml | 12 + .../acceptance/nodesets/sles-11sp3-x64.yml | 12 + .../nodesets/ubuntu-server-1204-x64.yml | 15 + .../nodesets/ubuntu-server-1210-x64.yml | 15 + .../nodesets/ubuntu-server-1304-x64.yml | 15 + .../nodesets/ubuntu-server-1310-x64.yml | 15 + .../nodesets/ubuntu-server-1404-x64.yml | 15 + .../spec/acceptance/xplugins001.rb | 91 + .../classes/000_elasticsearch_init_spec.rb | 306 ++ .../001_elasticsearch_init_debian_spec.rb | 219 - .../spec/classes/001_hiera_spec.rb | 192 + .../002_elasticsearch_init_redhat_spec.rb | 219 - .../004_elasticsearch_init_config_spec.rb | 112 - .../classes/005_elasticsearch_java_spec.rb | 120 - .../classes/005_elasticsearch_repo_spec.rb | 143 + ... => 010_elasticsearch_init_unkown_spec.rb} | 0 .../spec/classes/099_coverage_spec.rb | 1 + .../defines/001_elasticsearch_python_spec.rb | 9 +- .../defines/002_elasticsearch_ruby_spec.rb | 11 +- .../003_elasticsearch_template_spec.rb | 35 +- .../defines/004_elasticsearch_plugin_spec.rb | 74 +- .../005_elasticsearch_instance_spec.rb | 329 ++ .../defines/006_elasticsearch_script_spec.rb | 39 + .../010_elasticsearch_service_init_spec.rb | 128 + .../011_elasticsearch_service_system_spec.rb | 130 + .../spec/fixtures/facts/facts_url1.json | 13 + .../spec/fixtures/facts/facts_url2.json | 1 + .../spec/fixtures/hiera/hiera.yaml | 8 + .../hiera/hieradata/envs/defaultinstance.yaml | 5 + .../hiera/hieradata/multipleinstances.yaml | 8 + .../hiera/hieradata/singleinstance.yaml | 5 + .../hiera/hieradata/singleplugin.yaml | 11 + .../spec/functions/es_facts_spec.rb | 74 + .../spec/functions/plugin_dir_spec.rb | 47 + .../spec/lib/parser_validate_task.rb | 40 - .../spec/lib/template_check_task.rb | 31 - .../spec/spec_acceptance_common.rb | 191 + .../spec/spec_acceptance_integration.rb | 32 + .../modules/elasticsearch/spec/spec_helper.rb | 15 +- .../spec/spec_helper_acceptance.rb | 154 + .../spec/unit/provider/plugin_spec.rb | 112 + .../spec/unit/type/plugin_spec.rb | 57 + .../etc/elasticsearch/elasticsearch.yml.erb | 14 +- .../etc/elasticsearch/logging.yml.erb | 52 + .../etc/init.d/elasticsearch.Debian.erb | 46 +- .../etc/init.d/elasticsearch.RedHat.erb | 22 +- .../etc/init.d/elasticsearch.systemd.erb | 24 + .../templates/etc/sysconfig/defaults.erb | 6 +- .../usr/lib/tmpfiles.d/elasticsearch.conf.erb | 1 + puphpet/puppet/modules/epel/Gemfile | 45 +- puphpet/puppet/modules/epel/Gemfile.lock | 436 ++ puphpet/puppet/modules/epel/README.md | 40 +- puphpet/puppet/modules/epel/Rakefile | 47 +- puphpet/puppet/modules/epel/checksums.json | 33 +- puphpet/puppet/modules/epel/manifests/init.pp | 50 +- .../puppet/modules/epel/manifests/params.pp | 16 +- .../modules/epel/manifests/rpm_gpg_key.pp | 2 +- puphpet/puppet/modules/epel/metadata.json | 6 +- .../modules/epel/spec/classes/epel_spec.rb | 36 +- .../modules/epel/spec/classes/shared_base.rb | 6 +- .../epel/spec/classes/shared_debuginfo.rb | 6 +- .../epel/spec/classes/shared_source.rb | 6 +- .../epel/spec/classes/shared_testing.rb | 6 +- .../spec/classes/shared_testing_debuginfo.rb | 6 +- .../spec/classes/shared_testing_source.rb | 6 +- .../epel/spec/defines/rpm_gpg_key_spec.rb | 6 +- puphpet/puppet/modules/epel/tests/init.pp | 2 +- puphpet/puppet/modules/erlang/.gitignore | 5 + puphpet/puppet/modules/erlang/.travis.yml | 29 +- puphpet/puppet/modules/erlang/Gemfile | 5 +- puphpet/puppet/modules/erlang/Gemfile.lock | 182 +- puphpet/puppet/modules/erlang/Modulefile | 10 - .../puppet/modules/erlang/manifests/params.pp | 14 +- puphpet/puppet/modules/erlang/metadata.json | 55 + .../erlang/spec/classes/erlang_spec.rb | 4 +- puphpet/puppet/modules/firewall/.gitignore | 9 + puphpet/puppet/modules/gnupg/.fixtures.yml | 4 + puphpet/puppet/modules/gnupg/.gitignore | 9 + puphpet/puppet/modules/gnupg/.nodeset.yml | 27 + puphpet/puppet/modules/gnupg/.travis.yml | 17 + puphpet/puppet/modules/gnupg/CHANGELOG | 43 + puphpet/puppet/modules/gnupg/CONTRIBUTING.md | 216 + puphpet/puppet/modules/gnupg/Gemfile | 33 + puphpet/puppet/modules/gnupg/LICENSE | 201 + puphpet/puppet/modules/gnupg/README.md | 225 + puphpet/puppet/modules/gnupg/Rakefile | 15 + .../modules/gnupg/files/broken.public.key | 30 + puphpet/puppet/modules/gnupg/files/random.key | 28 + .../modules/gnupg/files/random.private.key | 58 + .../modules/gnupg/files/random.public.key | 30 + .../modules/gnupg/lib/facter/gnupg_command.rb | 18 + .../gnupg/lib/facter/gnupg_installed.rb | 18 + .../lib/puppet/provider/gnupg_key/gnupg.rb | 166 + .../gnupg/lib/puppet/type/gnupg_key.rb | 153 + .../puppet/modules/gnupg/manifests/init.pp | 29 + .../puppet/modules/gnupg/manifests/install.pp | 9 + .../puppet/modules/gnupg/manifests/params.pp | 30 + puphpet/puppet/modules/gnupg/metadata.json | 67 + .../gnupg/spec/acceptance/class_spec.rb | 28 + .../spec/acceptance/gnupg_key_install_spec.rb | 388 ++ .../acceptance/nodesets/centos-59-x64.yml | 0 .../acceptance/nodesets/centos-64-x64-pe.yml | 0 .../acceptance/nodesets/centos-64-x64.yml | 0 .../acceptance/nodesets/centos-65-x64.yml | 0 .../acceptance/nodesets/debian-607-x64.yml | 11 + .../acceptance/nodesets/debian-70rc1-x64.yml | 11 + .../acceptance/nodesets/debian-73-i386.yml | 11 + .../acceptance/nodesets/debian-73-x64.yml | 11 + .../spec/acceptance/nodesets/default.yml | 11 + .../nodesets/ubuntu-server-10044-x64.yml | 10 + .../nodesets/ubuntu-server-12042-x64.yml | 10 + .../nodesets/ubuntu-server-1310-x64.yml | 11 + .../nodesets/ubuntu-server-1404-x64.yml | 11 + .../gnupg/spec/classes/gnupg_init_spec.rb | 39 + puphpet/puppet/modules/gnupg/spec/spec.opts | 6 + .../puppet/modules/gnupg/spec/spec_helper.rb | 3 + .../gnupg/spec/spec_helper_acceptance.rb | 48 + .../modules/gnupg/spec/spec_helper_system.rb | 66 + .../spec/system/gnupg_key_install_spec.rb | 152 + .../modules/gnupg/spec/system/install_spec.rb | 16 + .../spec/unit/puppet/type/gnupg_key_spec.rb | 127 + .../puppet/modules/gnupg/tests/gnupg_key.pp | 40 + puphpet/puppet/modules/gnupg/tests/init.pp | 1 + puphpet/puppet/modules/inifile/.gitignore | 7 + puphpet/puppet/modules/java/.gitignore | 9 + puphpet/puppet/modules/locales/.gitignore | 3 + .../puppet/modules/mailcatcher/.fixtures.yml | 5 - .../puppet/modules/mailcatcher/.travis.yml | 31 - puphpet/puppet/modules/mailcatcher/Gemfile | 12 - puphpet/puppet/modules/mailcatcher/Modulefile | 13 - puphpet/puppet/modules/mailcatcher/README.md | 34 - puphpet/puppet/modules/mailcatcher/Rakefile | 6 - .../modules/mailcatcher/manifests/config.pp | 18 - .../modules/mailcatcher/manifests/init.pp | 64 - .../modules/mailcatcher/manifests/package.pp | 17 - .../modules/mailcatcher/manifests/params.pp | 22 - .../spec/classes/mailcatcher_spec.rb | 41 - .../modules/mailcatcher/spec/spec_helper.rb | 1 - .../templates/etc/init/mailcatcher.conf.erb | 16 - .../puppet/modules/mailcatcher/tests/init.pp | 12 - puphpet/puppet/modules/mongodb/.fixtures.yml | 4 +- puphpet/puppet/modules/mongodb/.gitignore | 11 + puphpet/puppet/modules/mongodb/.sync.yml | 9 + puphpet/puppet/modules/mongodb/.travis.yml | 49 +- puphpet/puppet/modules/mongodb/CHANGELOG | 74 - puphpet/puppet/modules/mongodb/CHANGELOG.md | 129 + .../puppet/modules/mongodb/CONTRIBUTING.md | 220 + puphpet/puppet/modules/mongodb/Gemfile | 48 +- puphpet/puppet/modules/mongodb/Modulefile | 12 - puphpet/puppet/modules/mongodb/README.md | 247 +- puphpet/puppet/modules/mongodb/Rakefile | 9 + .../mongodb/lib/puppet/provider/mongodb.rb | 168 + .../mongodb_conn_validator/tcp_port.rb | 53 + .../provider/mongodb_database/mongodb.rb | 46 +- .../puppet/provider/mongodb_replset/mongo.rb | 122 +- .../puppet/provider/mongodb_shard/mongo.rb | 236 + .../puppet/provider/mongodb_user/mongodb.rb | 156 +- .../lib/puppet/type/mongodb_conn_validator.rb | 45 + .../lib/puppet/type/mongodb_database.rb | 2 +- .../lib/puppet/type/mongodb_replset.rb | 11 +- .../mongodb/lib/puppet/type/mongodb_shard.rb | 39 + .../mongodb/lib/puppet/type/mongodb_user.rb | 13 +- .../lib/puppet/util/mongodb_validator.rb | 49 + .../modules/mongodb/manifests/client.pp | 16 +- .../mongodb/manifests/client/install.pp | 10 +- .../puppet/modules/mongodb/manifests/db.pp | 8 +- .../modules/mongodb/manifests/globals.pp | 43 +- .../puppet/modules/mongodb/manifests/init.pp | 15 +- .../modules/mongodb/manifests/mongos.pp | 48 + .../mongodb/manifests/mongos/config.pp | 27 + .../mongodb/manifests/mongos/install.pp | 32 + .../mongodb/manifests/mongos/service.pp | 72 + .../modules/mongodb/manifests/params.pp | 213 +- .../modules/mongodb/manifests/replset.pp | 5 + .../puppet/modules/mongodb/manifests/repo.pp | 51 +- .../modules/mongodb/manifests/repo/apt.pp | 10 +- .../modules/mongodb/manifests/repo/yum.pp | 11 +- .../modules/mongodb/manifests/server.pp | 118 +- .../mongodb/manifests/server/config.pp | 145 +- .../mongodb/manifests/server/install.pp | 6 +- .../mongodb/manifests/server/service.pp | 60 +- .../modules/mongodb/manifests/shardsvr.pp | 11 + puphpet/puppet/modules/mongodb/metadata.json | 46 + .../mongodb/spec/acceptance/database_spec.rb | 99 + .../mongodb/spec/acceptance/mongos_spec.rb | 110 + .../acceptance/nodesets/centos-59-x64.yml | 10 + .../acceptance/nodesets/centos-65-x64.yml | 10 + .../acceptance/nodesets/centos-7-vcloud.yml | 15 + .../spec/acceptance/nodesets/centos-7-x64.yml | 9 + .../acceptance/nodesets/debian-607-x64.yml | 10 + .../acceptance/nodesets/debian-70rc1-x64.yml | 10 + .../nodesets/multi-centos-64-x64.yml | 9 +- .../nodesets/multi-centos-7-vcloud.yml | 21 + .../nodesets/multi-centos-7-x64.yml | 15 + .../nodesets/ubuntu-server-1404-x64.yml | 11 + .../mongodb/spec/acceptance/replset_spec.rb | 137 +- .../mongodb/spec/acceptance/server_spec.rb | 173 +- .../mongodb/spec/acceptance/sharding_spec.rb | 55 + .../mongodb/spec/acceptance/user_spec.rb | 99 + .../spec/classes/client_install_spec.rb | 2 +- .../spec/classes/mongos_config_spec.rb | 23 + .../spec/classes/mongos_install_spec.rb | 29 + .../spec/classes/mongos_service_spec.rb | 100 + .../mongodb/spec/classes/mongos_spec.rb | 30 + .../modules/mongodb/spec/classes/repo_spec.rb | 30 +- .../spec/classes/server_config_spec.rb | 101 +- .../spec/classes/server_install_spec.rb | 2 +- .../mongodb/spec/classes/server_spec.rb | 146 +- .../modules/mongodb/spec/defines/db_spec.rb | 21 +- puphpet/puppet/modules/mongodb/spec/spec.opts | 6 + .../modules/mongodb/spec/spec_helper.rb | 6 + .../mongodb/spec/spec_helper_acceptance.rb | 9 +- .../spec/unit/mongodb_password_spec.rb | 8 +- .../provider/mongodb_database/mongodb_spec.rb | 45 +- .../provider/mongodb_replset/mongodb_spec.rb | 87 +- .../provider/mongodb_shard/mongodb_spec.rb | 79 + .../provider/mongodb_user/mongodb_spec.rb | 100 +- .../unit/puppet/type/mongodb_database_spec.rb | 4 +- .../unit/puppet/type/mongodb_replset_spec.rb | 4 +- .../unit/puppet/type/mongodb_shard_spec.rb | 29 + .../unit/puppet/type/mongodb_user_spec.rb | 14 +- .../mongodb/templates/mongodb-shard.conf.erb | 21 + .../mongodb/templates/mongodb.conf.2.6.erb | 137 + .../mongodb/templates/mongodb.conf.erb | 28 +- .../modules/mongodb/templates/mongorc.js.erb | 27 + .../templates/mongos/Debian/mongos.erb | 266 ++ .../templates/mongos/RedHat/mongos.erb | 106 + .../puppet/modules/mongodb/tests/client.pp | 2 + .../puppet/modules/mongodb/tests/globals.pp | 2 +- .../modules/mongodb/tests/replicaset.pp | 6 +- .../puppet/modules/mongodb/tests/server.pp | 4 +- .../puppet/modules/mongodb/tests/sharding.pp | 59 + puphpet/puppet/modules/mysql/.gitignore | 9 + puphpet/puppet/modules/nginx/.gitignore | 9 + .../nginx/manifests/resource/location.pp | 11 +- .../modules/nginx/manifests/resource/vhost.pp | 3 + .../nginx/templates/vhost/location_header.erb | 11 + .../nginx/templates/vhost/locations/set.erb | 3 + .../nginx/templates/vhost/vhost_header.erb | 12 +- .../templates/vhost/vhost_ssl_header.erb | 12 + puphpet/puppet/modules/ntp/.gitignore | 9 + puphpet/puppet/modules/ntp/.sync.yml | 9 + puphpet/puppet/modules/ntp/.travis.yml | 45 +- puphpet/puppet/modules/ntp/CHANGELOG.md | 115 + puphpet/puppet/modules/ntp/CONTRIBUTING.md | 225 +- puphpet/puppet/modules/ntp/Gemfile | 43 +- puphpet/puppet/modules/ntp/Modulefile | 11 - puphpet/puppet/modules/ntp/README.markdown | 205 +- puphpet/puppet/modules/ntp/Rakefile | 9 + .../puppet/parser/functions/ntp_dirname.rb | 15 + .../puppet/modules/ntp/manifests/config.pp | 27 +- puphpet/puppet/modules/ntp/manifests/init.pp | 33 +- .../puppet/modules/ntp/manifests/install.pp | 9 +- .../puppet/modules/ntp/manifests/params.pp | 268 +- .../puppet/modules/ntp/manifests/service.pp | 10 +- puphpet/puppet/modules/ntp/metadata.json | 64 +- .../modules/ntp/spec/acceptance/class_spec.rb | 9 +- .../acceptance/disable_monitoring_spec.rb | 36 + .../acceptance/nodesets/centos-59-x64.yml | 10 + .../acceptance/nodesets/fedora-21-x64.yml | 9 + .../spec/acceptance/nodesets/sles-12-64.yml | 20 + .../nodesets/ubuntu-server-1404-x64.yml | 11 + .../nodesets/ubuntu-server-14042-x64.yml | 16 + .../ntp/spec/acceptance/ntp_config_spec.rb | 25 +- .../ntp/spec/acceptance/ntp_install_spec.rb | 19 +- .../spec/acceptance/ntp_parameters_spec.rb | 83 +- .../ntp/spec/acceptance/ntp_service_spec.rb | 72 +- .../spec/acceptance/preferred_servers_spec.rb | 18 +- .../ntp/spec/acceptance/restrict_spec.rb | 15 +- .../modules/ntp/spec/classes/ntp_spec.rb | 681 ++- .../puppet/modules/ntp/spec/spec_helper.rb | 27 + .../ntp/spec/spec_helper_acceptance.rb | 45 +- .../puppet/modules/ntp/templates/ntp.conf.erb | 69 +- puphpet/puppet/modules/php/.fixtures.yml | 3 +- puphpet/puppet/modules/php/.gemfile | 3 +- puphpet/puppet/modules/php/.gitignore | 12 + puphpet/puppet/modules/php/.travis.yml | 8 +- puphpet/puppet/modules/php/Modulefile | 9 - puphpet/puppet/modules/php/README.md | 30 +- .../php/lib/facter/php_fact_extension_dir.rb | 2 +- .../php/lib/facter/php_fact_version.rb | 2 +- .../puppet/modules/php/manifests/augeas.pp | 2 + puphpet/puppet/modules/php/manifests/devel.pp | 3 +- puphpet/puppet/modules/php/manifests/ini.pp | 69 +- puphpet/puppet/modules/php/manifests/init.pp | 39 +- puphpet/puppet/modules/php/manifests/mod.pp | 69 + .../puppet/modules/php/manifests/module.pp | 24 +- .../puppet/modules/php/manifests/params.pp | 1 + puphpet/puppet/modules/php/manifests/pear.pp | 14 +- .../modules/php/manifests/pear/module.pp | 20 +- .../modules/php/manifests/pecl/module.pp | 50 +- puphpet/puppet/modules/php/metadata.json | 21 + .../modules/php/spec/classes/php_spec.rb | 38 +- .../php/spec/defines/php_pear_module_spec.rb | 2 +- .../puppet/modules/postgresql/.fixtures.yml | 4 +- puphpet/puppet/modules/postgresql/.gitignore | 9 + puphpet/puppet/modules/postgresql/.sync.yml | 8 +- puphpet/puppet/modules/postgresql/.travis.yml | 19 +- .../puppet/modules/postgresql/CHANGELOG.md | 92 + puphpet/puppet/modules/postgresql/Gemfile | 25 +- puphpet/puppet/modules/postgresql/README.md | 235 +- puphpet/puppet/modules/postgresql/Rakefile | 2 +- .../puppet/provider/postgresql_psql/ruby.rb | 37 +- .../postgresql_replication_slot/ruby.rb | 68 + .../lib/puppet/type/postgresql_conf.rb | 44 +- .../lib/puppet/type/postgresql_psql.rb | 42 +- .../type/postgresql_replication_slot.rb | 16 + .../modules/postgresql/manifests/client.pp | 4 +- .../modules/postgresql/manifests/globals.pp | 99 +- .../modules/postgresql/manifests/lib/docs.pp | 16 + .../modules/postgresql/manifests/params.pp | 124 +- .../modules/postgresql/manifests/repo.pp | 3 +- .../manifests/repo/apt_postgresql_org.pp | 2 +- .../manifests/repo/yum_postgresql_org.pp | 1 + .../modules/postgresql/manifests/server.pp | 4 + .../postgresql/manifests/server/config.pp | 48 +- .../postgresql/manifests/server/extension.pp | 17 +- .../postgresql/manifests/server/grant.pp | 125 +- .../postgresql/manifests/server/initdb.pp | 38 +- .../postgresql/manifests/server/passwd.pp | 19 +- .../manifests/server/pg_hba_rule.pp | 28 +- .../postgresql/manifests/server/plpython.pp | 19 + .../postgresql/manifests/server/recovery.pp | 38 + .../postgresql/manifests/server/role.pp | 23 +- .../postgresql/manifests/server/schema.pp | 2 +- .../manifests/server/table_grant.pp | 24 +- .../manifests/validate_db_connection.pp | 7 +- .../puppet/modules/postgresql/metadata.json | 12 +- .../postgresql/spec/acceptance/db_spec.rb | 9 +- .../spec/acceptance/postgresql_psql_spec.rb | 67 + .../spec/acceptance/server/recovery_spec.rb | 61 + .../acceptance/z_alternative_pgdata_spec.rb | 4 +- .../postgresql/spec/spec_helper_acceptance.rb | 37 +- .../spec/unit/classes/client_spec.rb | 13 +- .../spec/unit/classes/globals_spec.rb | 71 +- .../spec/unit/classes/lib/pgdocs_spec.rb | 29 + .../spec/unit/classes/server/config_spec.rb | 55 + .../spec/unit/classes/server/plpython_spec.rb | 47 + .../spec/unit/classes/server_spec.rb | 19 +- .../unit/defines/server/extension_spec.rb | 6 +- .../spec/unit/defines/server/grant_spec.rb | 63 +- .../unit/defines/server/pg_hba_rule_spec.rb | 8 +- .../unit/defines/server/pg_ident_rule_spec.rb | 2 +- .../spec/unit/defines/server/recovery_spec.rb | 113 + .../spec/unit/defines/server/role_spec.rb | 16 +- .../defines/validate_db_connection_spec.rb | 31 + .../provider/postgresql_psql/ruby_spec.rb | 18 +- .../postgresql_replication_slot/ruby_spec.rb | 92 + .../type/postgresql_replication_slot_spec.rb | 11 + .../postgresql/templates/recovery.conf | 47 + .../postgresql/templates/systemd-override.erb | 4 + .../lib/puppet/parser/functions/deep_merge.rb | 4 +- .../lib/puppet/parser/functions/merge_yaml.rb | 23 +- .../lib/puppet/parser/functions/to_bool.rb | 12 + .../modules/puphpet/manifests/adminer.pp | 6 +- .../puphpet/manifests/apache/proxy_fcgi.pp | 4 +- .../modules/puphpet/manifests/apache/repo.pp | 14 +- .../puphpet/manifests/apache/repo/centos.pp | 36 +- .../puphpet/manifests/apache/repo/debian.pp | 8 +- .../puphpet/manifests/apache/repo/ubuntu.pp | 22 + .../puppet/modules/puphpet/manifests/hhvm.pp | 20 +- .../modules/puphpet/manifests/mariadb.pp | 8 +- .../modules/puphpet/manifests/mysql/repo.pp | 36 +- .../puppet/modules/puphpet/manifests/nginx.pp | 2 +- .../puphpet/manifests/nginx/upstream.pp | 2 +- .../modules/puphpet/manifests/nodejs.pp | 2 +- .../modules/puphpet/manifests/params.pp | 5 - .../modules/puphpet/manifests/php/composer.pp | 5 +- .../modules/puphpet/manifests/php/drush.pp | 1 + .../modules/puphpet/manifests/php/fpm/ini.pp | 33 +- .../puphpet/manifests/php/fpm/pool_ini.pp | 33 +- .../modules/puphpet/manifests/php/ini.pp | 96 +- .../modules/puphpet/manifests/php/module.pp | 18 +- .../modules/puphpet/manifests/php/pear.pp | 2 +- .../modules/puphpet/manifests/php/pecl.pp | 70 +- .../modules/puphpet/manifests/php/repos.pp | 78 +- .../modules/puphpet/manifests/php/settings.pp | 88 +- .../puphpet/manifests/php/wordpress/wpcli.pp | 1 + .../modules/puphpet/manifests/php/xdebug.pp | 41 +- .../modules/puphpet/manifests/php/xhprof.pp | 2 +- .../modules/puphpet/manifests/phpmyadmin.pp | 8 +- .../puphpet/manifests/server/centos_ius.pp | 23 + .../modules/puphpet/manifests/sqlite/db.pp | 13 +- .../modules/puphpet/manifests/supervisord.pp | 16 +- .../puphpet/templates/apache/files_match.erb | 36 +- .../puphpet/templates/nodejs/install.erb | 2 +- puphpet/puppet/modules/puppi/.gemfile | 7 - puphpet/puppet/modules/puppi/.gitignore | 12 + puphpet/puppet/modules/puppi/.travis.yml | 33 +- puphpet/puppet/modules/puppi/Gemfile | 21 + puphpet/puppet/modules/puppi/Modulefile | 4 +- puphpet/puppet/modules/puppi/README.md | 110 +- puphpet/puppet/modules/puppi/README_deploy.md | 31 +- puphpet/puppet/modules/puppi/Rakefile | 7 +- .../puppet/modules/puppi/files/scripts/git.sh | 2 +- .../puppet/modules/puppi/files/scripts/hg.sh | 159 + .../puppi/files/scripts/report_mongo.sh | 2 +- .../puppet/modules/puppi/files/scripts/svn.sh | 2 +- .../modules/puppi/lib/facter/last_run.rb | 2 +- .../lib/puppet/functions/params_lookup.rb | 80 + .../puppet/parser/functions/params_lookup.rb | 16 +- .../puppet/modules/puppi/manifests/init.pp | 4 +- .../puppi/manifests/mcollective/client.pp | 20 +- .../modules/puppi/manifests/netinstall.pp | 26 +- .../puppet/modules/puppi/manifests/params.pp | 2 + .../puppet/modules/puppi/manifests/project.pp | 2 +- .../puppi/manifests/project/archive.pp | 10 +- .../modules/puppi/manifests/project/hg.pp | 412 ++ .../puppet/modules/puppi/manifests/skel.pp | 22 +- .../modules/puppi/spec/classes/puppi_spec.rb | 2 +- .../puppi/spec/defines/puppi_check_spec.rb | 2 +- .../puppi/spec/defines/puppi_deploy_spec.rb | 2 +- .../puppi/spec/defines/puppi_helper_spec.rb | 2 +- .../puppi/spec/defines/puppi_info_spec.rb | 2 +- .../spec/defines/puppi_initialize_spec.rb | 2 +- .../puppi/spec/defines/puppi_log_spec.rb | 2 +- .../puppi/spec/defines/puppi_project_spec.rb | 2 +- .../puppi/spec/defines/puppi_report_spec.rb | 2 +- .../puppi/spec/defines/puppi_rollback_spec.rb | 2 +- .../puppi/spec/defines/puppi_run_spec.rb | 2 +- .../puppi/spec/defines/puppi_todo_spec.rb | 2 +- .../puppi/spec/defines/puppi_ze_spec.rb | 2 +- .../puppi/spec/functions/any2bool_spec.rb | 2 +- .../puppi/spec/functions/bool2ensure_spec.rb | 2 +- .../puppi/spec/functions/url_parse_spec.rb | 2 +- .../modules/puppi/templates/puppi_clean.erb | 6 +- .../puppet/modules/puppi/templates/todo.erb | 6 +- puphpet/puppet/modules/pyenv/.gitignore | 3 + puphpet/puppet/modules/rabbitmq/.fixtures.yml | 4 +- puphpet/puppet/modules/rabbitmq/.gitignore | 9 + puphpet/puppet/modules/rabbitmq/.travis.yml | 10 +- puphpet/puppet/modules/rabbitmq/CHANGELOG.md | 43 + puphpet/puppet/modules/rabbitmq/Gemfile | 21 +- puphpet/puppet/modules/rabbitmq/README.md | 52 +- .../provider/rabbitmq_erlang_cookie/ruby.rb | 2 +- .../rabbitmq_exchange/rabbitmqadmin.rb | 7 +- .../rabbitmq_parameter/rabbitmqctl.rb | 84 + .../lib/puppet/type/rabbitmq_exchange.rb | 3 + .../lib/puppet/type/rabbitmq_parameter.rb | 73 + .../lib/puppet/type/rabbitmq_policy.rb | 18 + .../modules/rabbitmq/manifests/config.pp | 53 +- .../puppet/modules/rabbitmq/manifests/init.pp | 11 +- .../manifests/install/rabbitmqadmin.pp | 5 +- .../modules/rabbitmq/manifests/params.pp | 4 +- puphpet/puppet/modules/rabbitmq/metadata.json | 4 +- .../spec/acceptance/rabbitmqadmin_spec.rb | 14 +- .../rabbitmq/spec/acceptance/zz281_spec.rb | 366 +- .../rabbitmq/spec/classes/rabbitmq_spec.rb | 279 +- .../rabbitmq/spec/spec_helper_acceptance.rb | 2 +- .../rabbitmq_parameter/rabbitmqctl_spec.rb | 87 + .../puppet/type/rabbitmq_parameter_spec.rb | 81 + .../unit/puppet/type/rabbitmq_policy_spec.rb | 28 + .../rabbitmq/templates/rabbitmq.config.erb | 27 +- .../rabbitmq/templates/rabbitmqadmin.conf.erb | 2 +- puphpet/puppet/modules/redis/.fixtures.yml | 9 + puphpet/puppet/modules/redis/.gitignore | 9 + puphpet/puppet/modules/redis/.puppet-lint.rc | 2 + puphpet/puppet/modules/redis/.travis.yml | 51 +- puphpet/puppet/modules/redis/CHANGELOG | 63 - puphpet/puppet/modules/redis/Gemfile | 31 +- puphpet/puppet/modules/redis/LICENSE | 21 +- puphpet/puppet/modules/redis/Modulefile | 13 - puphpet/puppet/modules/redis/README.md | 104 +- puphpet/puppet/modules/redis/Rakefile | 18 +- puphpet/puppet/modules/redis/Vagrantfile | 18 - .../puppet/modules/redis/manifests/config.pp | 106 + .../puppet/modules/redis/manifests/init.pp | 649 ++- .../puppet/modules/redis/manifests/install.pp | 12 + .../puppet/modules/redis/manifests/params.pp | 219 +- .../modules/redis/manifests/preinstall.pp | 82 + .../modules/redis/manifests/sentinel.pp | 230 + .../puppet/modules/redis/manifests/service.pp | 16 + puphpet/puppet/modules/redis/metadata.json | 80 + .../spec/acceptance/nodesets/default.yml | 11 + .../redis/spec/acceptance/redis_spec.rb | 23 + .../redis/spec/classes/redis_sentinel_spec.rb | 84 + .../modules/redis/spec/classes/redis_spec.rb | 862 ++++ puphpet/puppet/modules/redis/spec/spec.opts | 1 + .../puppet/modules/redis/spec/spec_helper.rb | 25 +- .../redis/spec/spec_helper_acceptance.rb | 31 + .../redis/templates/redis-sentinel.conf.erb | 17 + .../redis/templates/redis-sentinel.init.erb | 89 + .../{redis.rhel.conf.erb => redis.conf.erb} | 442 +- .../redis/templates/redis.debian.conf.erb | 221 - .../redis/templates/redis.logrotate.erb | 9 - puphpet/puppet/modules/redis/tests/init.pp | 15 - puphpet/puppet/modules/rvm/Gemfile | 4 +- puphpet/puppet/modules/rvm/Gemfile.lock | 194 +- puphpet/puppet/modules/rvm/Puppetfile.lock | 2 + puphpet/puppet/modules/rvm/README.markdown | 19 +- puphpet/puppet/modules/rvm/Rakefile | 1 - puphpet/puppet/modules/rvm/checksums.json | 36 +- .../puppet/modules/rvm/manifests/gnupg_key.pp | 15 + puphpet/puppet/modules/rvm/manifests/gpg.pp | 4 +- puphpet/puppet/modules/rvm/manifests/init.pp | 12 +- .../puppet/modules/rvm/manifests/params.pp | 10 +- puphpet/puppet/modules/rvm/manifests/rvmrc.pp | 2 +- .../puppet/modules/rvm/manifests/system.pp | 27 +- puphpet/puppet/modules/rvm/metadata.json | 9 +- .../rvm/spec/acceptance/nodesets/default.yml | 6 - .../rvm/spec/classes/gnupg_key_spec.rb | 9 + .../modules/rvm/spec/classes/gpg_spec.rb | 19 +- .../modules/rvm/spec/classes/init_spec.rb | 7 + .../modules/rvm/spec/classes/system_spec.rb | 10 + .../puppet/modules/rvm/spec/spec_helper.rb | 1 - .../puppet/modules/rvm/templates/rvmrc.erb | 6 +- puphpet/puppet/modules/solr/.gitignore | 9 + puphpet/puppet/modules/solr/Modulefile | 2 +- puphpet/puppet/modules/solr/README.markdown | 8 + puphpet/puppet/modules/solr/README.md | 6 +- puphpet/puppet/modules/solr/manifests/init.pp | 2 +- puphpet/puppet/modules/stdlib/.gitignore | 12 + puphpet/puppet/modules/stdlib/.travis.yml | 11 +- puphpet/puppet/modules/stdlib/CHANGELOG.md | 152 +- puphpet/puppet/modules/stdlib/Gemfile | 25 +- puphpet/puppet/modules/stdlib/README.markdown | 1151 +++-- puphpet/puppet/modules/stdlib/Rakefile | 13 +- .../stdlib/{tests => examples}/file_line.pp | 4 +- .../{tests => examples}/has_interface_with.pp | 3 +- .../{tests => examples}/has_ip_address.pp | 2 +- .../{tests => examples}/has_ip_network.pp | 3 +- .../puppet/modules/stdlib/examples/init.pp | 1 + .../modules/stdlib/lib/facter/facter_dot_d.rb | 2 +- .../stdlib/lib/facter/package_provider.rb | 21 + .../modules/stdlib/lib/facter/pe_version.rb | 9 +- .../modules/stdlib/lib/facter/root_home.rb | 13 + .../stdlib/lib/facter/service_provider.rb | 17 + .../stdlib/lib/puppet/functions/is_a.rb | 32 + .../lib/puppet/parser/functions/bool2str.rb | 26 +- .../puppet/parser/functions/convert_base.rb | 35 + .../lib/puppet/parser/functions/dos2unix.rb | 15 + .../lib/puppet/parser/functions/empty.rb | 12 +- .../parser/functions/fqdn_rand_string.rb | 34 + .../puppet/parser/functions/fqdn_rotate.rb | 28 +- .../lib/puppet/parser/functions/getvar.rb | 4 +- .../parser/functions/has_interface_with.rb | 7 +- .../puppet/parser/functions/intersection.rb | 6 +- .../parser/functions/is_absolute_path.rb | 50 + .../puppet/parser/functions/is_mac_address.rb | 2 +- .../parser/functions/load_module_metadata.rb | 24 + .../lib/puppet/parser/functions/loadyaml.rb | 7 +- .../lib/puppet/parser/functions/member.rb | 2 +- .../lib/puppet/parser/functions/parsejson.rb | 25 +- .../lib/puppet/parser/functions/parseyaml.rb | 22 +- .../lib/puppet/parser/functions/pw_hash.rb | 56 + .../lib/puppet/parser/functions/range.rb | 23 +- .../puppet/parser/functions/seeded_rand.rb | 22 + .../lib/puppet/parser/functions/size.rb | 8 +- .../lib/puppet/parser/functions/str2bool.rb | 8 +- .../lib/puppet/parser/functions/time.rb | 5 +- .../puppet/parser/functions/try_get_value.rb | 77 + .../lib/puppet/parser/functions/union.rb | 17 +- .../lib/puppet/parser/functions/unix2dos.rb | 15 + .../lib/puppet/parser/functions/upcase.rb | 2 +- .../functions/validate_absolute_path.rb | 24 +- .../parser/functions/validate_augeas.rb | 2 +- .../parser/functions/validate_integer.rb | 3 +- .../parser/functions/validate_ip_address.rb | 50 + .../parser/functions/validate_ipv4_address.rb | 2 +- .../parser/functions/validate_numeric.rb | 1 + .../puppet/parser/functions/validate_re.rb | 11 +- .../parser/functions/validate_slength.rb | 6 +- .../lib/puppet/provider/file_line/ruby.rb | 95 +- .../stdlib/lib/puppet/type/file_line.rb | 59 +- .../puppet/modules/stdlib/manifests/init.pp | 4 +- .../puppet/modules/stdlib/manifests/stages.pp | 2 +- puphpet/puppet/modules/stdlib/metadata.json | 12 +- .../stdlib/spec/acceptance/anchor_spec.rb | 26 + .../stdlib/spec/acceptance/empty_spec.rb | 14 + .../spec/acceptance/ensure_packages_spec.rb | 22 - .../spec/acceptance/ensure_resource_spec.rb | 20 +- .../spec/acceptance/fqdn_rand_string_spec.rb | 66 + .../spec/acceptance/fqdn_rotate_spec.rb | 79 +- .../stdlib/spec/acceptance/is_a_spec.rb | 30 + .../stdlib/spec/acceptance/parsejson_spec.rb | 23 +- .../stdlib/spec/acceptance/parseyaml_spec.rb | 25 +- .../stdlib/spec/acceptance/pw_hash_spec.rb | 34 + .../spec/acceptance/try_get_value_spec.rb | 47 + .../stdlib/spec/acceptance/union_spec.rb | 5 +- .../stdlib/spec/classes/anchor_spec.rb | 30 - .../modules/stdlib/spec/fixtures/lsuser/root | 2 + .../modules/stdlib/lib/facter/facter_dot_d.rb | 202 + .../stdlib/lib/facter/package_provider.rb | 21 + .../modules/stdlib/lib/facter/pe_version.rb | 58 + .../stdlib/lib/facter/puppet_vardir.rb | 26 + .../modules/stdlib/lib/facter/root_home.rb | 45 + .../stdlib/lib/facter/service_provider.rb | 17 + .../stdlib/lib/facter/util/puppet_settings.rb | 21 + .../stdlib/lib/puppet/functions/is_a.rb | 32 + .../stdlib/lib/puppet/functions/type_of.rb | 17 + .../stdlib/lib/puppet/parser/functions/abs.rb | 36 + .../lib/puppet/parser/functions/any2array.rb | 33 + .../puppet/parser/functions/assert_private.rb | 29 + .../lib/puppet/parser/functions/base64.rb | 37 + .../lib/puppet/parser/functions/basename.rb | 34 + .../lib/puppet/parser/functions/bool2num.rb | 26 + .../lib/puppet/parser/functions/bool2str.rb | 45 + .../lib/puppet/parser/functions/camelcase.rb | 33 + .../lib/puppet/parser/functions/capitalize.rb | 33 + .../lib/puppet/parser/functions/ceiling.rb | 25 + .../lib/puppet/parser/functions/chomp.rb | 34 + .../lib/puppet/parser/functions/chop.rb | 36 + .../lib/puppet/parser/functions/concat.rb | 41 + .../puppet/parser/functions/convert_base.rb | 35 + .../lib/puppet/parser/functions/count.rb | 22 + .../lib/puppet/parser/functions/deep_merge.rb | 44 + .../parser/functions/defined_with_params.rb | 35 + .../lib/puppet/parser/functions/delete.rb | 49 + .../lib/puppet/parser/functions/delete_at.rb | 49 + .../parser/functions/delete_undef_values.rb | 34 + .../puppet/parser/functions/delete_values.rb | 26 + .../lib/puppet/parser/functions/difference.rb | 36 + .../lib/puppet/parser/functions/dirname.rb | 21 + .../lib/puppet/parser/functions/dos2unix.rb | 15 + .../lib/puppet/parser/functions/downcase.rb | 32 + .../lib/puppet/parser/functions/empty.rb | 31 + .../parser/functions/ensure_packages.rb | 35 + .../parser/functions/ensure_resource.rb | 46 + .../lib/puppet/parser/functions/flatten.rb | 33 + .../lib/puppet/parser/functions/floor.rb | 25 + .../parser/functions/fqdn_rand_string.rb | 34 + .../puppet/parser/functions/fqdn_rotate.rb | 63 + .../parser/functions/get_module_path.rb | 17 + .../lib/puppet/parser/functions/getparam.rb | 35 + .../lib/puppet/parser/functions/getvar.rb | 31 + .../lib/puppet/parser/functions/grep.rb | 33 + .../parser/functions/has_interface_with.rb | 71 + .../puppet/parser/functions/has_ip_address.rb | 25 + .../puppet/parser/functions/has_ip_network.rb | 25 + .../lib/puppet/parser/functions/has_key.rb | 28 + .../lib/puppet/parser/functions/hash.rb | 41 + .../puppet/parser/functions/intersection.rb | 34 + .../parser/functions/is_absolute_path.rb | 50 + .../lib/puppet/parser/functions/is_array.rb | 22 + .../lib/puppet/parser/functions/is_bool.rb | 22 + .../puppet/parser/functions/is_domain_name.rb | 54 + .../lib/puppet/parser/functions/is_float.rb | 30 + .../parser/functions/is_function_available.rb | 26 + .../lib/puppet/parser/functions/is_hash.rb | 22 + .../lib/puppet/parser/functions/is_integer.rb | 45 + .../puppet/parser/functions/is_ip_address.rb | 32 + .../puppet/parser/functions/is_mac_address.rb | 27 + .../lib/puppet/parser/functions/is_numeric.rb | 75 + .../lib/puppet/parser/functions/is_string.rb | 26 + .../lib/puppet/parser/functions/join.rb | 41 + .../parser/functions/join_keys_to_values.rb | 47 + .../lib/puppet/parser/functions/keys.rb | 26 + .../parser/functions/load_module_metadata.rb | 24 + .../lib/puppet/parser/functions/loadyaml.rb | 25 + .../lib/puppet/parser/functions/lstrip.rb | 32 + .../stdlib/lib/puppet/parser/functions/max.rb | 21 + .../lib/puppet/parser/functions/member.rb | 62 + .../lib/puppet/parser/functions/merge.rb | 34 + .../stdlib/lib/puppet/parser/functions/min.rb | 21 + .../lib/puppet/parser/functions/num2bool.rb | 43 + .../lib/puppet/parser/functions/parsejson.rb | 29 + .../lib/puppet/parser/functions/parseyaml.rb | 30 + .../lib/puppet/parser/functions/pick.rb | 29 + .../puppet/parser/functions/pick_default.rb | 35 + .../lib/puppet/parser/functions/prefix.rb | 52 + .../lib/puppet/parser/functions/private.rb | 17 + .../lib/puppet/parser/functions/pw_hash.rb | 56 + .../lib/puppet/parser/functions/range.rb | 87 + .../lib/puppet/parser/functions/reject.rb | 31 + .../lib/puppet/parser/functions/reverse.rb | 27 + .../lib/puppet/parser/functions/rstrip.rb | 31 + .../puppet/parser/functions/seeded_rand.rb | 22 + .../lib/puppet/parser/functions/shuffle.rb | 45 + .../lib/puppet/parser/functions/size.rb | 46 + .../lib/puppet/parser/functions/sort.rb | 27 + .../lib/puppet/parser/functions/squeeze.rb | 36 + .../lib/puppet/parser/functions/str2bool.rb | 46 + .../parser/functions/str2saltedsha512.rb | 32 + .../lib/puppet/parser/functions/strftime.rb | 107 + .../lib/puppet/parser/functions/strip.rb | 38 + .../lib/puppet/parser/functions/suffix.rb | 45 + .../lib/puppet/parser/functions/swapcase.rb | 38 + .../lib/puppet/parser/functions/time.rb | 50 + .../lib/puppet/parser/functions/to_bytes.rb | 31 + .../puppet/parser/functions/try_get_value.rb | 77 + .../lib/puppet/parser/functions/type.rb | 19 + .../lib/puppet/parser/functions/type3x.rb | 51 + .../lib/puppet/parser/functions/union.rb | 29 + .../lib/puppet/parser/functions/unique.rb | 50 + .../lib/puppet/parser/functions/unix2dos.rb | 15 + .../lib/puppet/parser/functions/upcase.rb | 45 + .../lib/puppet/parser/functions/uriescape.rb | 34 + .../functions/validate_absolute_path.rb | 51 + .../puppet/parser/functions/validate_array.rb | 33 + .../parser/functions/validate_augeas.rb | 83 + .../puppet/parser/functions/validate_bool.rb | 34 + .../puppet/parser/functions/validate_cmd.rb | 63 + .../puppet/parser/functions/validate_hash.rb | 33 + .../parser/functions/validate_integer.rb | 132 + .../parser/functions/validate_ip_address.rb | 50 + .../parser/functions/validate_ipv4_address.rb | 48 + .../parser/functions/validate_ipv6_address.rb | 49 + .../parser/functions/validate_numeric.rb | 94 + .../puppet/parser/functions/validate_re.rb | 47 + .../parser/functions/validate_slength.rb | 69 + .../parser/functions/validate_string.rb | 38 + .../lib/puppet/parser/functions/values.rb | 39 + .../lib/puppet/parser/functions/values_at.rb | 99 + .../stdlib/lib/puppet/parser/functions/zip.rb | 39 + .../lib/puppet/provider/file_line/ruby.rb | 128 + .../modules/stdlib/lib/puppet/type/anchor.rb | 46 + .../stdlib/lib/puppet/type/file_line.rb | 118 + .../fixtures/modules/stdlib/manifests/init.pp | 18 + .../modules/stdlib/manifests/stages.pp | 43 + .../modules/stdlib/spec/functions/abs_spec.rb | 39 +- .../stdlib/spec/functions/any2array_spec.rb | 64 +- .../spec/functions/assert_private_spec.rb | 12 +- .../stdlib/spec/functions/base64_spec.rb | 42 +- .../stdlib/spec/functions/basename_spec.rb | 13 + .../stdlib/spec/functions/bool2num_spec.rb | 38 +- .../stdlib/spec/functions/bool2str_spec.rb | 17 + .../stdlib/spec/functions/camelcase_spec.rb | 17 + .../stdlib/spec/functions/capitalize_spec.rb | 37 +- .../stdlib/spec/functions/ceiling_spec.rb | 44 +- .../stdlib/spec/functions/chomp_spec.rb | 40 +- .../stdlib/spec/functions/chop_spec.rb | 40 +- .../stdlib/spec/functions/concat_spec.rb | 62 +- .../spec/functions/convert_base_spec.rb | 24 + .../stdlib/spec/functions/count_spec.rb | 43 +- .../stdlib/spec/functions/deep_merge_spec.rb | 144 +- .../functions/defined_with_params_spec.rb | 29 +- .../stdlib/spec/functions/delete_at_spec.rb | 37 +- .../stdlib/spec/functions/delete_spec.rb | 102 +- .../functions/delete_undef_values_spec.rb | 85 +- .../spec/functions/delete_values_spec.rb | 57 +- .../stdlib/spec/functions/difference_spec.rb | 34 +- .../stdlib/spec/functions/dirname_spec.rb | 45 +- .../stdlib/spec/functions/dos2unix_spec.rb | 40 + .../stdlib/spec/functions/downcase_spec.rb | 42 +- .../stdlib/spec/functions/empty_spec.rb | 42 +- .../spec/functions/ensure_packages_spec.rb | 105 +- .../spec/functions/ensure_resource_spec.rb | 128 +- .../stdlib/spec/functions/flatten_spec.rb | 35 +- .../stdlib/spec/functions/floor_spec.rb | 45 +- .../spec/functions/fqdn_rand_string_spec.rb | 65 + .../stdlib/spec/functions/fqdn_rotate_spec.rb | 81 +- .../spec/functions/get_module_path_spec.rb | 60 +- .../stdlib/spec/functions/getparam_spec.rb | 90 +- .../stdlib/spec/functions/getvar_spec.rb | 46 +- .../stdlib/spec/functions/grep_spec.rb | 32 +- .../spec/functions/has_interface_with_spec.rb | 80 +- .../spec/functions/has_ip_address_spec.rb | 45 +- .../spec/functions/has_ip_network_spec.rb | 42 +- .../stdlib/spec/functions/has_key_spec.rb | 51 +- .../stdlib/spec/functions/hash_spec.rb | 27 +- .../spec/functions/intersection_spec.rb | 34 +- .../stdlib/spec/functions/is_a_spec.rb | 25 + .../stdlib/spec/functions/is_array_spec.rb | 42 +- .../stdlib/spec/functions/is_bool_spec.rb | 53 +- .../spec/functions/is_domain_name_spec.rb | 108 +- .../stdlib/spec/functions/is_float_spec.rb | 41 +- .../spec/functions/is_function_available.rb | 34 +- .../stdlib/spec/functions/is_hash_spec.rb | 34 +- .../stdlib/spec/functions/is_integer_spec.rb | 88 +- .../spec/functions/is_ip_address_spec.rb | 56 +- .../spec/functions/is_mac_address_spec.rb | 47 +- .../stdlib/spec/functions/is_numeric_spec.rb | 141 +- .../stdlib/spec/functions/is_string_spec.rb | 50 +- .../functions/join_keys_to_values_spec.rb | 51 +- .../stdlib/spec/functions/join_spec.rb | 30 +- .../stdlib/spec/functions/keys_spec.rb | 32 +- .../functions/load_module_metadata_spec.rb | 29 + .../stdlib/spec/functions/loadyaml_spec.rb | 39 +- .../stdlib/spec/functions/lstrip_spec.rb | 56 +- .../modules/stdlib/spec/functions/max_spec.rb | 38 +- .../stdlib/spec/functions/member_spec.rb | 49 +- .../stdlib/spec/functions/merge_spec.rb | 69 +- .../modules/stdlib/spec/functions/min_spec.rb | 38 +- .../stdlib/spec/functions/num2bool_spec.rb | 83 +- .../stdlib/spec/functions/parsejson_spec.rb | 68 +- .../stdlib/spec/functions/parseyaml_spec.rb | 87 +- .../spec/functions/pick_default_spec.rb | 74 +- .../stdlib/spec/functions/pick_spec.rb | 40 +- .../stdlib/spec/functions/prefix_spec.rb | 55 +- .../stdlib/spec/functions/private_spec.rb | 16 +- .../stdlib/spec/functions/pw_hash_spec.rb | 69 + .../stdlib/spec/functions/range_spec.rb | 164 +- .../stdlib/spec/functions/reject_spec.rb | 31 +- .../stdlib/spec/functions/reverse_spec.rb | 45 +- .../stdlib/spec/functions/rstrip_spec.rb | 61 +- .../stdlib/spec/functions/seeded_rand_spec.rb | 53 + .../stdlib/spec/functions/shuffle_spec.rb | 48 +- .../stdlib/spec/functions/size_spec.rb | 45 +- .../stdlib/spec/functions/sort_spec.rb | 32 +- .../stdlib/spec/functions/squeeze_spec.rb | 50 +- .../stdlib/spec/functions/str2bool_spec.rb | 40 +- .../spec/functions/str2saltedsha512_spec.rb | 50 +- .../stdlib/spec/functions/strftime_spec.rb | 5 +- .../stdlib/spec/functions/strip_spec.rb | 55 +- .../stdlib/spec/functions/suffix_spec.rb | 65 +- .../stdlib/spec/functions/swapcase_spec.rb | 54 +- .../stdlib/spec/functions/time_spec.rb | 40 +- .../stdlib/spec/functions/to_bytes_spec.rb | 147 +- .../spec/functions/try_get_value_spec.rb | 100 + .../stdlib/spec/functions/type3x_spec.rb | 4 +- .../stdlib/spec/functions/type_of_spec.rb | 25 + .../stdlib/spec/functions/type_spec.rb | 4 +- .../stdlib/spec/functions/union_spec.rb | 33 +- .../stdlib/spec/functions/unique_spec.rb | 44 +- .../stdlib/spec/functions/unix2dos_spec.rb | 40 + .../stdlib/spec/functions/upcase_spec.rb | 64 +- .../stdlib/spec/functions/uriescape_spec.rb | 56 +- .../functions/validate_absolute_path_spec.rb | 120 +- .../spec/functions/validate_array_spec.rb | 49 +- .../spec/functions/validate_augeas_spec.rb | 70 +- .../spec/functions/validate_bool_spec.rb | 64 +- .../spec/functions/validate_cmd_spec.rb | 104 +- .../spec/functions/validate_hash_spec.rb | 53 +- .../spec/functions/validate_integer_spec.rb | 263 +- .../functions/validate_ip_address_spec.rb | 46 + .../functions/validate_ipv4_address_spec.rb | 92 +- .../functions/validate_ipv6_address_spec.rb | 87 +- .../spec/functions/validate_numeric_spec.rb | 260 +- .../stdlib/spec/functions/validate_re_spec.rb | 120 +- .../spec/functions/validate_slength_spec.rb | 94 +- .../spec/functions/validate_string_spec.rb | 65 +- .../stdlib/spec/functions/values_at_spec.rb | 71 +- .../stdlib/spec/functions/values_spec.rb | 42 +- .../modules/stdlib/spec/functions/zip_spec.rb | 40 +- .../stdlib/spec/lib/puppet_spec/compiler.rb | 47 - .../stdlib/spec/lib/puppet_spec/database.rb | 30 - .../stdlib/spec/lib/puppet_spec/files.rb | 61 - .../stdlib/spec/lib/puppet_spec/fixtures.rb | 29 - .../stdlib/spec/lib/puppet_spec/matchers.rb | 121 - .../stdlib/spec/lib/puppet_spec/modules.rb | 27 - .../stdlib/spec/lib/puppet_spec/pops.rb | 17 - .../stdlib/spec/lib/puppet_spec/scope.rb | 15 - .../stdlib/spec/lib/puppet_spec/settings.rb | 16 - .../stdlib/spec/lib/puppet_spec/verbose.rb | 10 - .../spec/puppetlabs_spec_helper_clone.rb | 34 + .../puppet/modules/stdlib/spec/spec_helper.rb | 33 +- .../stdlib/spec/spec_helper_acceptance.rb | 64 +- .../spec/unit/facter/package_provider_spec.rb | 44 + .../spec/unit/facter/pe_version_spec.rb | 12 + .../stdlib/spec/unit/facter/root_home_spec.rb | 13 + .../spec/unit/facter/service_provider_spec.rb | 37 + .../unit/facter/util/puppet_settings_spec.rb | 1 + .../unit/puppet/functions/type_of_spec.rb | 33 - .../puppet/parser/functions/basename_spec.rb | 46 - .../puppet/parser/functions/bool2str_spec.rb | 46 - .../puppet/parser/functions/camelcase_spec.rb | 24 - .../parser/functions/is_absolute_path_spec.rb | 86 + .../puppet/provider/file_line/ruby_spec.rb | 253 +- .../spec/unit/puppet/type/file_line_spec.rb | 3 + puphpet/puppet/modules/stdlib/tests/init.pp | 1 - puphpet/puppet/modules/supervisord/.gitignore | 7 + puphpet/puppet/modules/swap_file/.gitignore | 4 + puphpet/puppet/modules/timezone/.fixtures.yml | 7 + puphpet/puppet/modules/timezone/.gitignore | 6 + puphpet/puppet/modules/timezone/.rspec | 3 + puphpet/puppet/modules/timezone/.travis.yml | 37 + puphpet/puppet/modules/timezone/Gemfile | 16 + puphpet/puppet/modules/timezone/LICENSE | 202 + puphpet/puppet/modules/timezone/README.md | 23 + puphpet/puppet/modules/timezone/Rakefile | 24 + .../puppet/modules/timezone/manifests/init.pp | 109 + .../modules/timezone/manifests/params.pp | 68 + puphpet/puppet/modules/timezone/metadata.json | 52 + .../timezone/spec/classes/timezone_spec.rb | 9 + .../modules/timezone/spec/spec_helper.rb | 8 + .../modules/timezone/spec/support/debian.rb | 49 + .../modules/timezone/spec/support/freebsd.rb | 34 + .../modules/timezone/spec/support/gentoo.rb | 48 + .../modules/timezone/spec/support/redhat.rb | 55 + .../timezone/spec/support/validate_params.rb | 10 + .../modules/timezone/templates/clock.erb | 5 + .../modules/timezone/templates/timezone.erb | 4 + puphpet/puppet/modules/timezone/tests/init.pp | 1 + puphpet/puppet/modules/vcsrepo/.gitignore | 4 + puphpet/puppet/modules/yum/.fixtures.yml | 10 +- puphpet/puppet/modules/yum/.gemfile | 2 +- puphpet/puppet/modules/yum/.gitignore | 12 + puphpet/puppet/modules/yum/.travis.yml | 27 +- puphpet/puppet/modules/yum/Modulefile | 9 - .../CentOS.7/rpm-gpg/RPM-GPG-KEY-CentOS-7 | 30 + .../files/CentOS.7/rpm-gpg/RPM-GPG-KEY-EPEL | 29 + .../files/CentOS.7/rpm-gpg/RPM-GPG-KEY-PGDG | 31 + .../files/CentOS.7/rpm-gpg/RPM-GPG-KEY-RBEL | 36 + .../files/CentOS.7/rpm-gpg/RPM-GPG-KEY-beta | 28 + .../CentOS.7/rpm-gpg/RPM-GPG-KEY-kbsingh | 25 + .../files/CentOS.7/rpm-gpg/RPM-GPG-KEY-remi | 24 + .../CentOS.7/rpm-gpg/RPM-GPG-KEY-rpmforge-dag | 32 + .../rpm-gpg/RPM-GPG-KEY-webtatic-andy | 30 + .../files/CentOS.7/rpm-gpg/RPM-GPG-KEY.art | 24 + .../files/CentOS.7/rpm-gpg/RPM-GPG-KEY.atrpms | 20 + .../files/CentOS.7/rpm-gpg/RubyWorks.GPG.key | 30 + .../yum/files/rpm-gpg/RPM-GPG-KEY-CentOS-7 | 30 + .../yum/files/rpm-gpg/RPM-GPG-KEY-cloudera | 30 + .../files/rpm-gpg/RPM-GPG-KEY-elasticsearch | 31 + .../rpm-gpg/RPM-GPG-KEY-erlang_solutions | 52 + .../yum/files/rpm-gpg/RPM-GPG-KEY-icinga | 30 + .../files/rpm-gpg/RPM-GPG-KEY-webtatic-el7 | 29 + puphpet/puppet/modules/yum/manifests/cron.pp | 10 +- .../puppet/modules/yum/manifests/defaults.pp | 8 + puphpet/puppet/modules/yum/manifests/init.pp | 128 +- .../modules/yum/manifests/managed_yumrepo.pp | 36 +- .../puppet/modules/yum/manifests/params.pp | 13 +- .../puppet/modules/yum/manifests/plugin.pp | 18 +- .../modules/yum/manifests/plugin/security.pp | 10 + .../yum/manifests/plugin/versionlock.pp | 20 + .../manifests/repo/{10gen.pp => a10gen.pp} | 8 +- .../modules/yum/manifests/repo/atomic.pp | 16 +- .../modules/yum/manifests/repo/atrpms.pp | 16 +- .../puppet/modules/yum/manifests/repo/cdh5.pp | 29 + .../modules/yum/manifests/repo/centos4.pp | 12 +- .../modules/yum/manifests/repo/centos5.pp | 10 +- .../modules/yum/manifests/repo/centos6.pp | 10 +- .../modules/yum/manifests/repo/centos7.pp | 93 + .../puppet/modules/yum/manifests/repo/ceph.pp | 4 +- .../puppet/modules/yum/manifests/repo/cuda.pp | 15 + .../modules/yum/manifests/repo/dell_omsa.pp | 24 + .../modules/yum/manifests/repo/devtools.pp | 10 +- .../modules/yum/manifests/repo/devtools2.pp | 17 + .../yum/manifests/repo/elasticsearch10.pp | 11 +- .../yum/manifests/repo/elasticsearch17.pp | 18 + .../yum/manifests/repo/elasticsearch90.pp | 11 +- .../modules/yum/manifests/repo/elastix.pp | 60 +- .../modules/yum/manifests/repo/elrepo.pp | 2 +- .../puppet/modules/yum/manifests/repo/epel.pp | 12 +- .../puppet/modules/yum/manifests/repo/esl.pp | 13 +- .../modules/yum/manifests/repo/foreman.pp | 8 +- .../modules/yum/manifests/repo/icinga.pp | 20 + .../yum/manifests/repo/integ_ganeti.pp | 22 +- .../modules/yum/manifests/repo/karan.pp | 14 +- .../modules/yum/manifests/repo/kibana41.pp | 18 + .../modules/yum/manifests/repo/logstash13.pp | 11 +- .../modules/yum/manifests/repo/logstash14.pp | 13 +- .../yum/manifests/repo/logstashforwarder.pp | 18 + .../yum/manifests/repo/mod_pagespeed.pp | 8 +- .../modules/yum/manifests/repo/mongodb.pp | 8 +- .../yum/manifests/repo/mysql_community.pp | 73 +- .../modules/yum/manifests/repo/openshift3.pp | 14 + .../yum/manifests/repo/openshift_server.pp | 32 + .../modules/yum/manifests/repo/percona.pp | 15 + .../modules/yum/manifests/repo/pgdg91.pp | 14 +- .../modules/yum/manifests/repo/pgdg92.pp | 14 +- .../modules/yum/manifests/repo/pgdg93.pp | 14 +- .../modules/yum/manifests/repo/pgdg94.pp | 15 + .../modules/yum/manifests/repo/pgdg95.pp | 15 + .../puppet/modules/yum/manifests/repo/pulp.pp | 20 + .../modules/yum/manifests/repo/puppetlabs.pp | 9 +- .../manifests/repo/puppetlabs_collections.pp | 33 + .../puppet/modules/yum/manifests/repo/remi.pp | 28 +- .../modules/yum/manifests/repo/remi_php55.pp | 14 +- .../modules/yum/manifests/repo/remi_php56.pp | 14 +- .../modules/yum/manifests/repo/remi_php70.pp | 24 + .../modules/yum/manifests/repo/repoforge.pp | 18 +- .../yum/manifests/repo/repoforgeextras.pp | 4 +- .../modules/yum/manifests/repo/rpmforge.pp | 24 +- .../modules/yum/manifests/repo/rsyslog_v7.pp | 13 +- .../modules/yum/manifests/repo/rundeck1.pp | 1 + .../modules/yum/manifests/repo/rundeck2.pp | 1 + .../modules/yum/manifests/repo/sclruby200.pp | 29 + .../modules/yum/manifests/repo/shibboleth.pp | 14 + .../puppet/modules/yum/manifests/repo/sl5.pp | 2 +- .../puppet/modules/yum/manifests/repo/sl6.pp | 5 +- .../modules/yum/manifests/repo/tengen.pp | 14 + .../yum/manifests/repo/vmware_tools.pp | 1 + .../modules/yum/manifests/repo/webtatic.pp | 31 +- .../modules/yum/manifests/repo/xenserver.pp | 125 + .../modules/yum/manifests/repo/zabbix24.pp | 15 + .../modules/yum/manifests/versionlock.pp | 24 + puphpet/puppet/modules/yum/metadata.json | 21 + .../modules/yum/spec/classes/yum_spec.rb | 2 +- .../puppet/modules/yum/templates/yum-cron.erb | 3 +- puphpet/puppet/nodes/MailCatcher.pp | 60 - puphpet/puppet/nodes/MongoDb.pp | 54 - puphpet/puppet/nodes/NodeJs.pp | 24 - puphpet/puppet/nodes/Ruby.pp | 15 - puphpet/ruby/puppet.rb | 277 ++ puphpet/shell/check-puppet-modules.sh | 2 +- puphpet/shell/initial-setup.sh | 68 +- puphpet/shell/install-puppet.sh | 77 +- puphpet/shell/install-ruby.sh | 43 - puphpet/vagrant/Vagrantfile-aws | 10 +- puphpet/vagrant/Vagrantfile-digitalocean | 10 +- puphpet/vagrant/Vagrantfile-gce | 10 +- puphpet/vagrant/Vagrantfile-ikoulacloud | 10 +- puphpet/vagrant/Vagrantfile-linode | 10 +- puphpet/vagrant/Vagrantfile-local | 78 +- puphpet/vagrant/Vagrantfile-rackspace | 10 +- puphpet/vagrant/Vagrantfile-softlayer | 10 +- 1333 files changed, 52257 insertions(+), 15835 deletions(-) create mode 100644 puphpet/files/dot/.git-completion.bash create mode 100644 puphpet/files/dot/.git-prompt.sh create mode 100644 puphpet/files/exec-preprovision/empty rename puphpet/puppet/{nodes => manifests}/Apache.pp (80%) rename puphpet/puppet/{nodes => manifests}/Beanstalkd.pp (100%) rename puphpet/puppet/{nodes => manifests}/Blackfire.pp (100%) rename puphpet/puppet/{nodes => manifests}/Cron.pp (100%) rename puphpet/puppet/{nodes => manifests}/Drush.pp (100%) rename puphpet/puppet/{nodes => manifests}/ElasticSearch.pp (66%) rename puphpet/puppet/{nodes => manifests}/Firewall.pp (78%) rename puphpet/puppet/{nodes => manifests}/Hhvm.pp (95%) rename puphpet/puppet/{nodes => manifests}/Locale.pp (57%) create mode 100644 puphpet/puppet/manifests/MailHog.pp rename puphpet/puppet/{nodes => manifests}/MariaDb.pp (88%) create mode 100644 puphpet/puppet/manifests/MongoDb.pp rename puphpet/puppet/{nodes => manifests}/Mysql.pp (90%) rename puphpet/puppet/{nodes => manifests}/Nginx.pp (77%) create mode 100644 puphpet/puppet/manifests/NodeJs.pp rename puphpet/puppet/{nodes => manifests}/Php.pp (81%) rename puphpet/puppet/{nodes => manifests}/Postgresql.pp (96%) rename puphpet/puppet/{nodes => manifests}/Python.pp (95%) rename puphpet/puppet/{nodes => manifests}/RabbitMQ.pp (75%) rename puphpet/puppet/{nodes => manifests}/Redis.pp (59%) create mode 100644 puphpet/puppet/manifests/Ruby.pp rename puphpet/puppet/{nodes => manifests}/Server.pp (79%) rename puphpet/puppet/{nodes => manifests}/Solr.pp (88%) rename puphpet/puppet/{nodes => manifests}/Sqlite.pp (89%) rename puphpet/puppet/{nodes => manifests}/UsersGroups.pp (100%) rename puphpet/puppet/{nodes => manifests}/WPCli.pp (100%) rename puphpet/puppet/{nodes => manifests}/Xdebug.pp (90%) rename puphpet/puppet/{nodes => manifests}/Xhprof.pp (95%) rename puphpet/puppet/{ => manifests}/site.pp (90%) create mode 100644 puphpet/puppet/modules/apache/.gitignore rename puphpet/puppet/modules/apache/{tests => examples}/apache.pp (100%) rename puphpet/puppet/modules/apache/{tests => examples}/dev.pp (100%) rename puphpet/puppet/modules/apache/{tests => examples}/init.pp (100%) rename puphpet/puppet/modules/apache/{tests => examples}/mod_load_params.pp (100%) rename puphpet/puppet/modules/apache/{tests => examples}/mods.pp (100%) rename puphpet/puppet/modules/apache/{tests => examples}/mods_custom.pp (100%) rename puphpet/puppet/modules/apache/{tests => examples}/php.pp (100%) rename puphpet/puppet/modules/apache/{tests => examples}/vhost.pp (96%) rename puphpet/puppet/modules/apache/{tests => examples}/vhost_directories.pp (100%) create mode 100644 puphpet/puppet/modules/apache/examples/vhost_filter.pp rename puphpet/puppet/modules/apache/{tests => examples}/vhost_ip_based.pp (100%) rename puphpet/puppet/modules/apache/{tests => examples}/vhost_proxypass.pp (100%) rename puphpet/puppet/modules/apache/{tests => examples}/vhost_ssl.pp (100%) rename puphpet/puppet/modules/apache/{tests => examples}/vhosts_without_listen.pp (100%) create mode 100644 puphpet/puppet/modules/apache/lib/puppet/parser/functions/validate_apache_log_level.rb create mode 100644 puphpet/puppet/modules/apache/manifests/mod/auth_mellon.pp create mode 100644 puphpet/puppet/modules/apache/manifests/mod/authn_core.pp create mode 100644 puphpet/puppet/modules/apache/manifests/mod/ext_filter.pp create mode 100644 puphpet/puppet/modules/apache/manifests/mod/geoip.pp create mode 100644 puphpet/puppet/modules/apache/manifests/mod/remoteip.pp delete mode 100644 puphpet/puppet/modules/apache/spec/acceptance/basic_spec.rb create mode 100644 puphpet/puppet/modules/apache/spec/classes/mod/auth_mellon_spec.rb create mode 100644 puphpet/puppet/modules/apache/spec/classes/mod/disk_cache.rb create mode 100644 puphpet/puppet/modules/apache/spec/classes/mod/expires_spec.rb create mode 100644 puphpet/puppet/modules/apache/spec/classes/mod/ext_filter_spec.rb create mode 100644 puphpet/puppet/modules/apache/spec/classes/mod/remoteip_spec.rb create mode 100644 puphpet/puppet/modules/apache/spec/unit/puppet/parser/functions/validate_apache_log_level.rb create mode 100644 puphpet/puppet/modules/apache/templates/mod/auth_mellon.conf.erb create mode 100644 puphpet/puppet/modules/apache/templates/mod/expires.conf.erb create mode 100644 puphpet/puppet/modules/apache/templates/mod/ext_filter.conf.erb create mode 100644 puphpet/puppet/modules/apache/templates/mod/geoip.conf.erb create mode 100644 puphpet/puppet/modules/apache/templates/mod/remoteip.conf.erb rename puphpet/puppet/modules/apache/templates/mod/{fcgid.conf.erb => unixd_fcgid.conf.erb} (100%) create mode 100644 puphpet/puppet/modules/apache/templates/vhost/_auth_kerb.erb create mode 100644 puphpet/puppet/modules/apache/templates/vhost/_filters.erb create mode 100644 puphpet/puppet/modules/apache/templates/vhost/_limits.erb create mode 100644 puphpet/puppet/modules/apache/templates/vhost/_passenger_base_uris.erb create mode 100644 puphpet/puppet/modules/apt/.gitignore create mode 100644 puphpet/puppet/modules/apt/examples/backports.pp create mode 100644 puphpet/puppet/modules/apt/examples/builddep.pp create mode 100644 puphpet/puppet/modules/apt/examples/debian_testing.pp create mode 100644 puphpet/puppet/modules/apt/examples/debian_unstable.pp create mode 100644 puphpet/puppet/modules/apt/examples/disable_keys.pp create mode 100644 puphpet/puppet/modules/apt/examples/fancy_progress.pp create mode 100644 puphpet/puppet/modules/apt/examples/force.pp create mode 100644 puphpet/puppet/modules/apt/examples/hold.pp create mode 100644 puphpet/puppet/modules/apt/examples/key.pp rename puphpet/puppet/modules/apt/{tests => examples}/pin.pp (100%) rename puphpet/puppet/modules/apt/{tests => examples}/ppa.pp (100%) create mode 100644 puphpet/puppet/modules/apt/examples/release.pp create mode 100644 puphpet/puppet/modules/apt/examples/source.pp create mode 100644 puphpet/puppet/modules/apt/examples/unattended_upgrades.pp create mode 100644 puphpet/puppet/modules/apt/lib/facter/apt_reboot_required.rb delete mode 100644 puphpet/puppet/modules/apt/manifests/builddep.pp delete mode 100644 puphpet/puppet/modules/apt/manifests/debian/testing.pp delete mode 100644 puphpet/puppet/modules/apt/manifests/debian/unstable.pp delete mode 100644 puphpet/puppet/modules/apt/manifests/force.pp delete mode 100644 puphpet/puppet/modules/apt/manifests/hold.pp delete mode 100644 puphpet/puppet/modules/apt/manifests/release.pp create mode 100644 puphpet/puppet/modules/apt/manifests/setting.pp delete mode 100644 puphpet/puppet/modules/apt/manifests/unattended_upgrades.pp create mode 100644 puphpet/puppet/modules/apt/spec/classes/apt_backports_spec.rb delete mode 100644 puphpet/puppet/modules/apt/spec/classes/backports_spec.rb delete mode 100644 puphpet/puppet/modules/apt/spec/classes/debian_testing_spec.rb delete mode 100644 puphpet/puppet/modules/apt/spec/classes/debian_unstable_spec.rb delete mode 100644 puphpet/puppet/modules/apt/spec/classes/release_spec.rb delete mode 100644 puphpet/puppet/modules/apt/spec/classes/unattended_upgrades_spec.rb delete mode 100644 puphpet/puppet/modules/apt/spec/defines/builddep_spec.rb delete mode 100644 puphpet/puppet/modules/apt/spec/defines/force_spec.rb delete mode 100644 puphpet/puppet/modules/apt/spec/defines/hold_spec.rb create mode 100644 puphpet/puppet/modules/apt/spec/defines/key_compat_spec.rb create mode 100644 puphpet/puppet/modules/apt/spec/defines/setting_spec.rb create mode 100644 puphpet/puppet/modules/apt/spec/defines/source_compat_spec.rb create mode 100644 puphpet/puppet/modules/apt/spec/unit/facter/apt_reboot_required_spec.rb delete mode 100644 puphpet/puppet/modules/apt/templates/10periodic.erb delete mode 100644 puphpet/puppet/modules/apt/templates/50unattended-upgrades.erb create mode 100644 puphpet/puppet/modules/apt/templates/_conf_header.erb delete mode 100644 puphpet/puppet/modules/apt/templates/progressbar.erb delete mode 100644 puphpet/puppet/modules/apt/templates/release.erb delete mode 100644 puphpet/puppet/modules/apt/templates/unauth.erb delete mode 100644 puphpet/puppet/modules/apt/tests/builddep.pp delete mode 100644 puphpet/puppet/modules/apt/tests/debian/testing.pp delete mode 100644 puphpet/puppet/modules/apt/tests/debian/unstable.pp delete mode 100644 puphpet/puppet/modules/apt/tests/force.pp delete mode 100644 puphpet/puppet/modules/apt/tests/init.pp delete mode 100644 puphpet/puppet/modules/apt/tests/key.pp delete mode 100644 puphpet/puppet/modules/apt/tests/params.pp delete mode 100644 puphpet/puppet/modules/apt/tests/release.pp delete mode 100644 puphpet/puppet/modules/apt/tests/source.pp delete mode 100644 puphpet/puppet/modules/apt/tests/unattended_upgrades.pp create mode 100644 puphpet/puppet/modules/blackfire/.gitignore create mode 100644 puphpet/puppet/modules/blackfire/CHANGELOG.md create mode 100644 puphpet/puppet/modules/blackfire/LICENSE create mode 100644 puphpet/puppet/modules/blackfire/spec/acceptance/nodesets/debian-80-x64.yml create mode 100644 puphpet/puppet/modules/composer/.gitignore create mode 100644 puphpet/puppet/modules/concat/.gitignore create mode 100644 puphpet/puppet/modules/datacat/Changes create mode 100644 puphpet/puppet/modules/datacat/Gemfile create mode 100644 puphpet/puppet/modules/datacat/NOTES.md create mode 100644 puphpet/puppet/modules/datacat/README.md create mode 100644 puphpet/puppet/modules/datacat/Rakefile create mode 100644 puphpet/puppet/modules/datacat/TODO.md create mode 100644 puphpet/puppet/modules/datacat/checksums.json create mode 100644 puphpet/puppet/modules/datacat/lib/puppet/parser/functions/template_body.rb create mode 100644 puphpet/puppet/modules/datacat/lib/puppet/provider/datacat_collector/datacat_collector.rb create mode 100644 puphpet/puppet/modules/datacat/lib/puppet/provider/datacat_fragment/datacat_fragment.rb create mode 100644 puphpet/puppet/modules/datacat/lib/puppet/type/datacat_collector.rb create mode 100644 puphpet/puppet/modules/datacat/lib/puppet/type/datacat_fragment.rb create mode 100644 puphpet/puppet/modules/datacat/lib/puppet_x/richardc/datacat.rb create mode 100644 puphpet/puppet/modules/datacat/manifests/init.pp create mode 100644 puphpet/puppet/modules/datacat/metadata.json create mode 100644 puphpet/puppet/modules/datacat/spec/classes/demo1_spec.rb create mode 100644 puphpet/puppet/modules/datacat/spec/defines/datacat_spec.rb create mode 100644 puphpet/puppet/modules/datacat/spec/fixtures/modules/demo1/manifests/init.pp create mode 100644 puphpet/puppet/modules/datacat/spec/fixtures/modules/demo1/templates/sheeps.erb create mode 100644 puphpet/puppet/modules/datacat/spec/fixtures/modules/demo2/manifests/init.pp create mode 100644 puphpet/puppet/modules/datacat/spec/fixtures/modules/demo2/templates/merging.erb create mode 100644 puphpet/puppet/modules/datacat/spec/fixtures/modules/demo3/manifests/init.pp create mode 100644 puphpet/puppet/modules/datacat/spec/fixtures/modules/demo3/templates/hostgroups.cfg.erb create mode 100644 puphpet/puppet/modules/datacat/spec/fixtures/modules/issue1/manifests/init.pp create mode 100644 puphpet/puppet/modules/datacat/spec/fixtures/modules/issue1/templates/refers_to_scope.erb create mode 100644 puphpet/puppet/modules/datacat/spec/fixtures/modules/template_body/templates/test1.erb create mode 100644 puphpet/puppet/modules/datacat/spec/functions/template_body_spec.rb create mode 100644 puphpet/puppet/modules/datacat/spec/spec_helper.rb create mode 100644 puphpet/puppet/modules/datacat/spec/spec_helper_system.rb create mode 100644 puphpet/puppet/modules/datacat/spec/system/basic_spec.rb create mode 100644 puphpet/puppet/modules/datacat/spec/unit/type/datacat_collector_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/.gitignore create mode 100644 puphpet/puppet/modules/elasticsearch/.pmtignore delete mode 100644 puphpet/puppet/modules/elasticsearch/.travis.yml delete mode 100644 puphpet/puppet/modules/elasticsearch/CHANGELOG create mode 100644 puphpet/puppet/modules/elasticsearch/CHANGELOG.md delete mode 100644 puphpet/puppet/modules/elasticsearch/Modulefile create mode 100644 puphpet/puppet/modules/elasticsearch/lib/facter/es_facts.rb create mode 100644 puphpet/puppet/modules/elasticsearch/lib/puppet/parser/functions/array_suffix.rb create mode 100644 puphpet/puppet/modules/elasticsearch/lib/puppet/parser/functions/plugin_dir.rb create mode 100644 puphpet/puppet/modules/elasticsearch/lib/puppet/provider/elasticsearch_plugin/plugin.rb create mode 100644 puphpet/puppet/modules/elasticsearch/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb create mode 100644 puphpet/puppet/modules/elasticsearch/lib/puppet/type/elasticsearch_plugin.rb create mode 100644 puphpet/puppet/modules/elasticsearch/lib/puppet/type/es_instance_conn_validator.rb create mode 100644 puphpet/puppet/modules/elasticsearch/lib/puppet/util/es_instance_validator.rb create mode 100644 puphpet/puppet/modules/elasticsearch/manifests/instance.pp delete mode 100644 puphpet/puppet/modules/elasticsearch/manifests/java.pp create mode 100644 puphpet/puppet/modules/elasticsearch/manifests/repo.pp create mode 100644 puphpet/puppet/modules/elasticsearch/manifests/script.pp create mode 100644 puphpet/puppet/modules/elasticsearch/manifests/service/systemd.pp create mode 100644 puphpet/puppet/modules/elasticsearch/metadata.json create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/001_basic_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/002_class_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/003_template_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/004_plugin_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/009_datapath_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/010_pkg_url_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/011_service_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/012_instances_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/013_config_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/014_hiera_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/015_staged_removal.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/016_package_pin_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/017_restart_on_change_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/020_usergroup_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/021_es2x_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/integration001.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/centos-6-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/centos-7-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-6-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-7-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-8-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/opensuse-121-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/opensuse-131-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/sles-11sp3-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1204-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1210-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1304-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/acceptance/xplugins001.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/classes/000_elasticsearch_init_spec.rb delete mode 100644 puphpet/puppet/modules/elasticsearch/spec/classes/001_elasticsearch_init_debian_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/classes/001_hiera_spec.rb delete mode 100644 puphpet/puppet/modules/elasticsearch/spec/classes/002_elasticsearch_init_redhat_spec.rb delete mode 100644 puphpet/puppet/modules/elasticsearch/spec/classes/004_elasticsearch_init_config_spec.rb delete mode 100644 puphpet/puppet/modules/elasticsearch/spec/classes/005_elasticsearch_java_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/classes/005_elasticsearch_repo_spec.rb rename puphpet/puppet/modules/elasticsearch/spec/classes/{003_elasticsearch_init_unknown_spec.rb => 010_elasticsearch_init_unkown_spec.rb} (100%) create mode 100644 puphpet/puppet/modules/elasticsearch/spec/classes/099_coverage_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/defines/005_elasticsearch_instance_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/defines/006_elasticsearch_script_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/defines/010_elasticsearch_service_init_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/defines/011_elasticsearch_service_system_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/fixtures/facts/facts_url1.json create mode 100644 puphpet/puppet/modules/elasticsearch/spec/fixtures/facts/facts_url2.json create mode 100644 puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hiera.yaml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/envs/defaultinstance.yaml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/multipleinstances.yaml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleinstance.yaml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleplugin.yaml create mode 100644 puphpet/puppet/modules/elasticsearch/spec/functions/es_facts_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/functions/plugin_dir_spec.rb delete mode 100644 puphpet/puppet/modules/elasticsearch/spec/lib/parser_validate_task.rb delete mode 100644 puphpet/puppet/modules/elasticsearch/spec/lib/template_check_task.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/spec_acceptance_common.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/spec_acceptance_integration.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/spec_helper_acceptance.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/unit/provider/plugin_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/spec/unit/type/plugin_spec.rb create mode 100644 puphpet/puppet/modules/elasticsearch/templates/etc/elasticsearch/logging.yml.erb create mode 100644 puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.systemd.erb create mode 100644 puphpet/puppet/modules/elasticsearch/templates/usr/lib/tmpfiles.d/elasticsearch.conf.erb create mode 100644 puphpet/puppet/modules/epel/Gemfile.lock create mode 100644 puphpet/puppet/modules/erlang/.gitignore delete mode 100644 puphpet/puppet/modules/erlang/Modulefile create mode 100644 puphpet/puppet/modules/erlang/metadata.json create mode 100644 puphpet/puppet/modules/firewall/.gitignore create mode 100644 puphpet/puppet/modules/gnupg/.fixtures.yml create mode 100644 puphpet/puppet/modules/gnupg/.gitignore create mode 100644 puphpet/puppet/modules/gnupg/.nodeset.yml create mode 100644 puphpet/puppet/modules/gnupg/.travis.yml create mode 100644 puphpet/puppet/modules/gnupg/CHANGELOG create mode 100644 puphpet/puppet/modules/gnupg/CONTRIBUTING.md create mode 100644 puphpet/puppet/modules/gnupg/Gemfile create mode 100644 puphpet/puppet/modules/gnupg/LICENSE create mode 100644 puphpet/puppet/modules/gnupg/README.md create mode 100644 puphpet/puppet/modules/gnupg/Rakefile create mode 100644 puphpet/puppet/modules/gnupg/files/broken.public.key create mode 100644 puphpet/puppet/modules/gnupg/files/random.key create mode 100644 puphpet/puppet/modules/gnupg/files/random.private.key create mode 100644 puphpet/puppet/modules/gnupg/files/random.public.key create mode 100644 puphpet/puppet/modules/gnupg/lib/facter/gnupg_command.rb create mode 100644 puphpet/puppet/modules/gnupg/lib/facter/gnupg_installed.rb create mode 100644 puphpet/puppet/modules/gnupg/lib/puppet/provider/gnupg_key/gnupg.rb create mode 100644 puphpet/puppet/modules/gnupg/lib/puppet/type/gnupg_key.rb create mode 100644 puphpet/puppet/modules/gnupg/manifests/init.pp create mode 100644 puphpet/puppet/modules/gnupg/manifests/install.pp create mode 100644 puphpet/puppet/modules/gnupg/manifests/params.pp create mode 100644 puphpet/puppet/modules/gnupg/metadata.json create mode 100644 puphpet/puppet/modules/gnupg/spec/acceptance/class_spec.rb create mode 100644 puphpet/puppet/modules/gnupg/spec/acceptance/gnupg_key_install_spec.rb rename puphpet/puppet/modules/{apache => gnupg}/spec/acceptance/nodesets/centos-59-x64.yml (100%) rename puphpet/puppet/modules/{apache => gnupg}/spec/acceptance/nodesets/centos-64-x64-pe.yml (100%) rename puphpet/puppet/modules/{apache => gnupg}/spec/acceptance/nodesets/centos-64-x64.yml (100%) rename puphpet/puppet/modules/{apache => gnupg}/spec/acceptance/nodesets/centos-65-x64.yml (100%) create mode 100644 puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-607-x64.yml create mode 100644 puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-70rc1-x64.yml create mode 100644 puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-73-i386.yml create mode 100644 puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-73-x64.yml create mode 100644 puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/default.yml create mode 100644 puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml create mode 100644 puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml create mode 100644 puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml create mode 100644 puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml create mode 100644 puphpet/puppet/modules/gnupg/spec/classes/gnupg_init_spec.rb create mode 100644 puphpet/puppet/modules/gnupg/spec/spec.opts create mode 100644 puphpet/puppet/modules/gnupg/spec/spec_helper.rb create mode 100644 puphpet/puppet/modules/gnupg/spec/spec_helper_acceptance.rb create mode 100644 puphpet/puppet/modules/gnupg/spec/spec_helper_system.rb create mode 100644 puphpet/puppet/modules/gnupg/spec/system/gnupg_key_install_spec.rb create mode 100644 puphpet/puppet/modules/gnupg/spec/system/install_spec.rb create mode 100644 puphpet/puppet/modules/gnupg/spec/unit/puppet/type/gnupg_key_spec.rb create mode 100644 puphpet/puppet/modules/gnupg/tests/gnupg_key.pp create mode 100644 puphpet/puppet/modules/gnupg/tests/init.pp create mode 100644 puphpet/puppet/modules/inifile/.gitignore create mode 100644 puphpet/puppet/modules/java/.gitignore create mode 100644 puphpet/puppet/modules/locales/.gitignore delete mode 100644 puphpet/puppet/modules/mailcatcher/.fixtures.yml delete mode 100644 puphpet/puppet/modules/mailcatcher/.travis.yml delete mode 100644 puphpet/puppet/modules/mailcatcher/Gemfile delete mode 100644 puphpet/puppet/modules/mailcatcher/Modulefile delete mode 100644 puphpet/puppet/modules/mailcatcher/README.md delete mode 100644 puphpet/puppet/modules/mailcatcher/Rakefile delete mode 100644 puphpet/puppet/modules/mailcatcher/manifests/config.pp delete mode 100644 puphpet/puppet/modules/mailcatcher/manifests/init.pp delete mode 100644 puphpet/puppet/modules/mailcatcher/manifests/package.pp delete mode 100644 puphpet/puppet/modules/mailcatcher/manifests/params.pp delete mode 100644 puphpet/puppet/modules/mailcatcher/spec/classes/mailcatcher_spec.rb delete mode 100644 puphpet/puppet/modules/mailcatcher/spec/spec_helper.rb delete mode 100644 puphpet/puppet/modules/mailcatcher/templates/etc/init/mailcatcher.conf.erb delete mode 100644 puphpet/puppet/modules/mailcatcher/tests/init.pp create mode 100644 puphpet/puppet/modules/mongodb/.gitignore create mode 100644 puphpet/puppet/modules/mongodb/.sync.yml delete mode 100644 puphpet/puppet/modules/mongodb/CHANGELOG create mode 100644 puphpet/puppet/modules/mongodb/CHANGELOG.md create mode 100644 puphpet/puppet/modules/mongodb/CONTRIBUTING.md delete mode 100644 puphpet/puppet/modules/mongodb/Modulefile create mode 100644 puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb.rb create mode 100644 puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_conn_validator/tcp_port.rb create mode 100644 puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_shard/mongo.rb create mode 100644 puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_conn_validator.rb create mode 100644 puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_shard.rb create mode 100644 puphpet/puppet/modules/mongodb/lib/puppet/util/mongodb_validator.rb create mode 100644 puphpet/puppet/modules/mongodb/manifests/mongos.pp create mode 100644 puphpet/puppet/modules/mongodb/manifests/mongos/config.pp create mode 100644 puphpet/puppet/modules/mongodb/manifests/mongos/install.pp create mode 100644 puphpet/puppet/modules/mongodb/manifests/mongos/service.pp create mode 100644 puphpet/puppet/modules/mongodb/manifests/shardsvr.pp create mode 100644 puphpet/puppet/modules/mongodb/metadata.json create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/database_spec.rb create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/mongos_spec.rb create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-59-x64.yml create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-65-x64.yml create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-7-vcloud.yml create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-7-x64.yml create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/debian-607-x64.yml create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/debian-70rc1-x64.yml create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-7-vcloud.yml create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-7-x64.yml create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/sharding_spec.rb create mode 100644 puphpet/puppet/modules/mongodb/spec/acceptance/user_spec.rb create mode 100644 puphpet/puppet/modules/mongodb/spec/classes/mongos_config_spec.rb create mode 100644 puphpet/puppet/modules/mongodb/spec/classes/mongos_install_spec.rb create mode 100644 puphpet/puppet/modules/mongodb/spec/classes/mongos_service_spec.rb create mode 100644 puphpet/puppet/modules/mongodb/spec/classes/mongos_spec.rb create mode 100644 puphpet/puppet/modules/mongodb/spec/spec.opts create mode 100644 puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_shard/mongodb_spec.rb create mode 100644 puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_shard_spec.rb create mode 100644 puphpet/puppet/modules/mongodb/templates/mongodb-shard.conf.erb create mode 100644 puphpet/puppet/modules/mongodb/templates/mongodb.conf.2.6.erb create mode 100644 puphpet/puppet/modules/mongodb/templates/mongorc.js.erb create mode 100644 puphpet/puppet/modules/mongodb/templates/mongos/Debian/mongos.erb create mode 100644 puphpet/puppet/modules/mongodb/templates/mongos/RedHat/mongos.erb create mode 100644 puphpet/puppet/modules/mongodb/tests/client.pp create mode 100644 puphpet/puppet/modules/mongodb/tests/sharding.pp create mode 100644 puphpet/puppet/modules/mysql/.gitignore create mode 100644 puphpet/puppet/modules/nginx/.gitignore create mode 100644 puphpet/puppet/modules/nginx/templates/vhost/locations/set.erb create mode 100644 puphpet/puppet/modules/ntp/.gitignore create mode 100644 puphpet/puppet/modules/ntp/.sync.yml delete mode 100644 puphpet/puppet/modules/ntp/Modulefile create mode 100644 puphpet/puppet/modules/ntp/lib/puppet/parser/functions/ntp_dirname.rb create mode 100644 puphpet/puppet/modules/ntp/spec/acceptance/disable_monitoring_spec.rb create mode 100644 puphpet/puppet/modules/ntp/spec/acceptance/nodesets/centos-59-x64.yml create mode 100644 puphpet/puppet/modules/ntp/spec/acceptance/nodesets/fedora-21-x64.yml create mode 100644 puphpet/puppet/modules/ntp/spec/acceptance/nodesets/sles-12-64.yml create mode 100644 puphpet/puppet/modules/ntp/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml create mode 100644 puphpet/puppet/modules/ntp/spec/acceptance/nodesets/ubuntu-server-14042-x64.yml create mode 100644 puphpet/puppet/modules/php/.gitignore delete mode 100644 puphpet/puppet/modules/php/Modulefile create mode 100644 puphpet/puppet/modules/php/manifests/mod.pp create mode 100644 puphpet/puppet/modules/php/metadata.json create mode 100644 puphpet/puppet/modules/postgresql/.gitignore create mode 100644 puphpet/puppet/modules/postgresql/lib/puppet/provider/postgresql_replication_slot/ruby.rb create mode 100644 puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_replication_slot.rb create mode 100644 puphpet/puppet/modules/postgresql/manifests/lib/docs.pp create mode 100644 puphpet/puppet/modules/postgresql/manifests/server/plpython.pp create mode 100644 puphpet/puppet/modules/postgresql/manifests/server/recovery.pp create mode 100644 puphpet/puppet/modules/postgresql/spec/acceptance/server/recovery_spec.rb create mode 100644 puphpet/puppet/modules/postgresql/spec/unit/classes/lib/pgdocs_spec.rb create mode 100644 puphpet/puppet/modules/postgresql/spec/unit/classes/server/config_spec.rb create mode 100644 puphpet/puppet/modules/postgresql/spec/unit/classes/server/plpython_spec.rb create mode 100644 puphpet/puppet/modules/postgresql/spec/unit/defines/server/recovery_spec.rb create mode 100644 puphpet/puppet/modules/postgresql/spec/unit/puppet/provider/postgresql_replication_slot/ruby_spec.rb create mode 100644 puphpet/puppet/modules/postgresql/spec/unit/puppet/type/postgresql_replication_slot_spec.rb create mode 100644 puphpet/puppet/modules/postgresql/templates/recovery.conf create mode 100644 puphpet/puppet/modules/puphpet/manifests/apache/repo/ubuntu.pp create mode 100644 puphpet/puppet/modules/puphpet/manifests/server/centos_ius.pp delete mode 100644 puphpet/puppet/modules/puppi/.gemfile create mode 100644 puphpet/puppet/modules/puppi/.gitignore create mode 100644 puphpet/puppet/modules/puppi/Gemfile create mode 100644 puphpet/puppet/modules/puppi/files/scripts/hg.sh create mode 100644 puphpet/puppet/modules/puppi/lib/puppet/functions/params_lookup.rb create mode 100644 puphpet/puppet/modules/puppi/manifests/project/hg.pp create mode 100644 puphpet/puppet/modules/pyenv/.gitignore create mode 100644 puphpet/puppet/modules/rabbitmq/.gitignore create mode 100644 puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_parameter/rabbitmqctl.rb create mode 100644 puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_parameter.rb create mode 100644 puphpet/puppet/modules/rabbitmq/spec/unit/puppet/provider/rabbitmq_parameter/rabbitmqctl_spec.rb create mode 100644 puphpet/puppet/modules/rabbitmq/spec/unit/puppet/type/rabbitmq_parameter_spec.rb create mode 100644 puphpet/puppet/modules/redis/.fixtures.yml create mode 100644 puphpet/puppet/modules/redis/.gitignore create mode 100644 puphpet/puppet/modules/redis/.puppet-lint.rc delete mode 100644 puphpet/puppet/modules/redis/CHANGELOG delete mode 100644 puphpet/puppet/modules/redis/Modulefile delete mode 100644 puphpet/puppet/modules/redis/Vagrantfile create mode 100644 puphpet/puppet/modules/redis/manifests/config.pp create mode 100644 puphpet/puppet/modules/redis/manifests/install.pp create mode 100644 puphpet/puppet/modules/redis/manifests/preinstall.pp create mode 100644 puphpet/puppet/modules/redis/manifests/sentinel.pp create mode 100644 puphpet/puppet/modules/redis/manifests/service.pp create mode 100644 puphpet/puppet/modules/redis/metadata.json create mode 100644 puphpet/puppet/modules/redis/spec/acceptance/nodesets/default.yml create mode 100644 puphpet/puppet/modules/redis/spec/acceptance/redis_spec.rb create mode 100644 puphpet/puppet/modules/redis/spec/classes/redis_sentinel_spec.rb create mode 100644 puphpet/puppet/modules/redis/spec/classes/redis_spec.rb create mode 100644 puphpet/puppet/modules/redis/spec/spec.opts create mode 100644 puphpet/puppet/modules/redis/spec/spec_helper_acceptance.rb create mode 100644 puphpet/puppet/modules/redis/templates/redis-sentinel.conf.erb create mode 100644 puphpet/puppet/modules/redis/templates/redis-sentinel.init.erb rename puphpet/puppet/modules/redis/templates/{redis.rhel.conf.erb => redis.conf.erb} (56%) delete mode 100644 puphpet/puppet/modules/redis/templates/redis.debian.conf.erb delete mode 100644 puphpet/puppet/modules/redis/templates/redis.logrotate.erb delete mode 100644 puphpet/puppet/modules/redis/tests/init.pp create mode 100644 puphpet/puppet/modules/rvm/manifests/gnupg_key.pp create mode 100644 puphpet/puppet/modules/rvm/spec/classes/gnupg_key_spec.rb create mode 100644 puphpet/puppet/modules/solr/.gitignore create mode 100644 puphpet/puppet/modules/stdlib/.gitignore rename puphpet/puppet/modules/stdlib/{tests => examples}/file_line.pp (87%) rename puphpet/puppet/modules/stdlib/{tests => examples}/has_interface_with.pp (97%) rename puphpet/puppet/modules/stdlib/{tests => examples}/has_ip_address.pp (89%) rename puphpet/puppet/modules/stdlib/{tests => examples}/has_ip_network.pp (88%) create mode 100644 puphpet/puppet/modules/stdlib/examples/init.pp create mode 100644 puphpet/puppet/modules/stdlib/lib/facter/package_provider.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/facter/service_provider.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/puppet/functions/is_a.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/convert_base.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/dos2unix.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/is_absolute_path.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/load_module_metadata.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/pw_hash.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/seeded_rand.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/try_get_value.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/unix2dos.rb create mode 100644 puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_ip_address.rb create mode 100755 puphpet/puppet/modules/stdlib/spec/acceptance/anchor_spec.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/acceptance/ensure_packages_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/acceptance/fqdn_rand_string_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/acceptance/is_a_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/acceptance/pw_hash_spec.rb create mode 100755 puphpet/puppet/modules/stdlib/spec/acceptance/try_get_value_spec.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/classes/anchor_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/lsuser/root create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/facter_dot_d.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/package_provider.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/pe_version.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/puppet_vardir.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/root_home.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/service_provider.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/util/puppet_settings.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/functions/is_a.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/functions/type_of.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/abs.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/any2array.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/assert_private.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/base64.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/basename.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/bool2num.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/bool2str.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/camelcase.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/capitalize.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ceiling.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/chomp.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/chop.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/concat.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/convert_base.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/count.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/deep_merge.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/defined_with_params.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_at.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_undef_values.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_values.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/difference.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/dirname.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/dos2unix.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/downcase.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/empty.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ensure_packages.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ensure_resource.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/flatten.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/floor.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/fqdn_rotate.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/get_module_path.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/getparam.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/getvar.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/grep.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_interface_with.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_ip_address.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_ip_network.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_key.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/hash.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/intersection.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_absolute_path.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_array.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_bool.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_domain_name.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_float.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_function_available.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_hash.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_integer.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_ip_address.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_mac_address.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_numeric.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_string.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/join.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/join_keys_to_values.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/keys.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/load_module_metadata.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/loadyaml.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/lstrip.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/max.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/member.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/merge.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/min.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/num2bool.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/parsejson.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/parseyaml.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pick.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pick_default.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/prefix.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/private.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pw_hash.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/range.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/reject.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/reverse.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/rstrip.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/seeded_rand.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/shuffle.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/size.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/sort.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/squeeze.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/str2bool.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/str2saltedsha512.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/strftime.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/strip.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/suffix.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/swapcase.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/time.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/to_bytes.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/try_get_value.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/type.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/type3x.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/union.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/unique.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/unix2dos.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/upcase.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/uriescape.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_absolute_path.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_array.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_augeas.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_bool.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_cmd.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_hash.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_integer.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ip_address.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ipv4_address.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ipv6_address.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_numeric.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_re.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_slength.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_string.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/values.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/values_at.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/zip.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/provider/file_line/ruby.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/type/anchor.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/type/file_line.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/manifests/init.pp create mode 100644 puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/manifests/stages.pp create mode 100755 puphpet/puppet/modules/stdlib/spec/functions/basename_spec.rb create mode 100755 puphpet/puppet/modules/stdlib/spec/functions/bool2str_spec.rb create mode 100755 puphpet/puppet/modules/stdlib/spec/functions/camelcase_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/functions/convert_base_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/functions/dos2unix_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/functions/fqdn_rand_string_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/functions/is_a_spec.rb create mode 100755 puphpet/puppet/modules/stdlib/spec/functions/load_module_metadata_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/functions/pw_hash_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/functions/seeded_rand_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/functions/try_get_value_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/functions/type_of_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/functions/unix2dos_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/functions/validate_ip_address_spec.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/compiler.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/database.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/files.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/fixtures.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/matchers.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/modules.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/pops.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/scope.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/settings.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/verbose.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/puppetlabs_spec_helper_clone.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/unit/facter/package_provider_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/unit/facter/service_provider_spec.rb delete mode 100644 puphpet/puppet/modules/stdlib/spec/unit/puppet/functions/type_of_spec.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/basename_spec.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/bool2str_spec.rb delete mode 100755 puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/camelcase_spec.rb create mode 100644 puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/is_absolute_path_spec.rb delete mode 100644 puphpet/puppet/modules/stdlib/tests/init.pp create mode 100644 puphpet/puppet/modules/supervisord/.gitignore create mode 100644 puphpet/puppet/modules/swap_file/.gitignore create mode 100644 puphpet/puppet/modules/timezone/.fixtures.yml create mode 100644 puphpet/puppet/modules/timezone/.gitignore create mode 100644 puphpet/puppet/modules/timezone/.rspec create mode 100644 puphpet/puppet/modules/timezone/.travis.yml create mode 100644 puphpet/puppet/modules/timezone/Gemfile create mode 100644 puphpet/puppet/modules/timezone/LICENSE create mode 100644 puphpet/puppet/modules/timezone/README.md create mode 100644 puphpet/puppet/modules/timezone/Rakefile create mode 100644 puphpet/puppet/modules/timezone/manifests/init.pp create mode 100644 puphpet/puppet/modules/timezone/manifests/params.pp create mode 100644 puphpet/puppet/modules/timezone/metadata.json create mode 100644 puphpet/puppet/modules/timezone/spec/classes/timezone_spec.rb create mode 100644 puphpet/puppet/modules/timezone/spec/spec_helper.rb create mode 100644 puphpet/puppet/modules/timezone/spec/support/debian.rb create mode 100644 puphpet/puppet/modules/timezone/spec/support/freebsd.rb create mode 100644 puphpet/puppet/modules/timezone/spec/support/gentoo.rb create mode 100644 puphpet/puppet/modules/timezone/spec/support/redhat.rb create mode 100644 puphpet/puppet/modules/timezone/spec/support/validate_params.rb create mode 100644 puphpet/puppet/modules/timezone/templates/clock.erb create mode 100644 puphpet/puppet/modules/timezone/templates/timezone.erb create mode 100644 puphpet/puppet/modules/timezone/tests/init.pp create mode 100644 puphpet/puppet/modules/vcsrepo/.gitignore create mode 100644 puphpet/puppet/modules/yum/.gitignore delete mode 100644 puphpet/puppet/modules/yum/Modulefile create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-CentOS-7 create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-EPEL create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-PGDG create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-RBEL create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-beta create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-kbsingh create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-remi create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-rpmforge-dag create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-webtatic-andy create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY.art create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY.atrpms create mode 100644 puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RubyWorks.GPG.key create mode 100644 puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-CentOS-7 create mode 100644 puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-cloudera create mode 100644 puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-elasticsearch create mode 100644 puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-erlang_solutions create mode 100644 puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-icinga create mode 100644 puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-webtatic-el7 mode change 100755 => 100644 puphpet/puppet/modules/yum/manifests/defaults.pp create mode 100644 puphpet/puppet/modules/yum/manifests/plugin/security.pp create mode 100644 puphpet/puppet/modules/yum/manifests/plugin/versionlock.pp rename puphpet/puppet/modules/yum/manifests/repo/{10gen.pp => a10gen.pp} (50%) create mode 100644 puphpet/puppet/modules/yum/manifests/repo/cdh5.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/centos7.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/cuda.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/dell_omsa.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/devtools2.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/elasticsearch17.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/icinga.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/kibana41.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/logstashforwarder.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/openshift3.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/openshift_server.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/percona.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/pgdg94.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/pgdg95.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/pulp.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/puppetlabs_collections.pp mode change 100755 => 100644 puphpet/puppet/modules/yum/manifests/repo/remi_php55.pp mode change 100755 => 100644 puphpet/puppet/modules/yum/manifests/repo/remi_php56.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/remi_php70.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/sclruby200.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/shibboleth.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/tengen.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/xenserver.pp create mode 100644 puphpet/puppet/modules/yum/manifests/repo/zabbix24.pp create mode 100644 puphpet/puppet/modules/yum/manifests/versionlock.pp create mode 100644 puphpet/puppet/modules/yum/metadata.json delete mode 100644 puphpet/puppet/nodes/MailCatcher.pp delete mode 100644 puphpet/puppet/nodes/MongoDb.pp delete mode 100644 puphpet/puppet/nodes/NodeJs.pp delete mode 100644 puphpet/puppet/nodes/Ruby.pp create mode 100644 puphpet/ruby/puppet.rb delete mode 100644 puphpet/shell/install-ruby.sh diff --git a/Vagrantfile b/Vagrantfile index e42c709..c2ab2ed 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,10 +1,19 @@ +# -*- mode: ruby -*- + dir = File.dirname(File.expand_path(__FILE__)) require 'yaml' require "#{dir}/puphpet/ruby/deep_merge.rb" +require "#{dir}/puphpet/ruby/puppet.rb" configValues = YAML.load_file("#{dir}/puphpet/config.yaml") +provider = ENV['VAGRANT_DEFAULT_PROVIDER'] +if File.file?("#{dir}/puphpet/config-#{provider}.yaml") + custom = YAML.load_file("#{dir}/puphpet/config-#{provider}.yaml") + configValues.deep_merge!(custom) +end + if File.file?("#{dir}/puphpet/config-custom.yaml") custom = YAML.load_file("#{dir}/puphpet/config-custom.yaml") configValues.deep_merge!(custom) @@ -12,6 +21,6 @@ end data = configValues['vagrantfile'] -Vagrant.require_version '>= 1.6.0' +Vagrant.require_version '>= 1.8.1' eval File.read("#{dir}/puphpet/vagrant/Vagrantfile-#{data['target']}") diff --git a/puphpet/config.yaml b/puphpet/config.yaml index a026cc4..c450a89 100644 --- a/puphpet/config.yaml +++ b/puphpet/config.yaml @@ -7,33 +7,34 @@ vagrantfile: memory: '512' cpus: '1' chosen_provider: virtualbox + box_version: '' network: private_network: 192.168.56.101 forwarded_port: - vflnp_ru5y6y5ybb1b: + vflnp_v87rr0v8zkx8: host: '8916' guest: '22' post_up_message: '' provider: virtualbox: modifyvm: - natdnshostresolver1: 'on' + natdnshostresolver1: false showgui: '0' vmware: numvcpus: 1 parallels: - cpus: 1 + use_linked_clone: '0' + check_guest_tools: '0' + update_guest_tools: '0' provision: puppet: - manifests_path: puphpet/puppet - manifest_file: site.pp + manifests_path: puphpet/puppet/manifests module_path: puphpet/puppet/modules options: - '--verbose' - '--hiera_config /vagrant/puphpet/puppet/hiera.yaml' - - '--parser future' synced_folder: - vflsf_cfz58or0zys4: + vflsf_1j14k0inbioj: source: ./ target: /var/www sync_type: default @@ -41,6 +42,9 @@ vagrantfile: smb_host: '' smb_username: '' smb_password: '' + mount_options: + dir_mode: '0775' + file_mode: '0664' rsync: args: - '--verbose' @@ -65,8 +69,15 @@ vagrantfile: forward_agent: false forward_x11: false shell: 'bash -l' + insert_key: false vagrant: host: detect + proxy: + http: '' + https: '' + ftp: '' + no_proxy: '' + enabled: '' server: install: '1' packages: @@ -80,9 +91,8 @@ locale: install: '1' settings: default_locale: '' - locales: - - 'en_GB.UTF-8 UTF-8' - - 'en_US.UTF-8 UTF-8' + locales: { } + timezone: UTC firewall: install: '1' rules: { } @@ -95,9 +105,13 @@ nginx: default_vhost: 1 proxy_buffer_size: 128k proxy_buffers: '4 256k' + proxy_connect_timeout: 600s + proxy_send_timeout: 600s + proxy_read_timeout: 600s + names_hash_bucket_size: 128 upstreams: { } vhosts: - nxv_zp9kemga9v6g: + nxv_xmsfwtmmwa19: server_name: isosceles.dev server_aliases: - www.isosceles.dev @@ -118,6 +132,7 @@ nginx: apache: install: '1' settings: + version: 2.4 user: www-data group: www-data default_vhost: true @@ -128,7 +143,7 @@ apache: - proxy_fcgi - rewrite vhosts: - av_fmhqqm6ldxql: + av_zvezefqbe7wb: servername: isosceles.dev serveraliases: - www.isosceles.dev @@ -145,7 +160,7 @@ apache: ssl_protocol: '' ssl_cipher: '' directories: - avd_wm828ubc4nz3: + avd_2turl7zj6m0h: path: /var/www/www-example options: - Indexes @@ -157,7 +172,7 @@ apache: - 'all granted' custom_fragment: '' files_match: - avdfm_thtmgs6xj67s: + avdfm_sphbe5n0p88n: path: \.php$ sethandler: 'proxy:fcgi://127.0.0.1:9000' custom_fragment: '' @@ -169,16 +184,10 @@ php: version: '56' modules: php: - - cli - curl - - gd - - imagick - intl - - mcrypt pear: { } - pecl: - - PDO_MYSQL - - pecl_http + pecl: { } ini: display_errors: 'On' error_reporting: E_ALL @@ -186,7 +195,7 @@ php: fpm_ini: error_log: /var/log/php-fpm.log fpm_pools: - phpfp_1whbnvacpqsy: + phpfp_lv7wcd5j423l: ini: listen: '127.0.0.1:9000' security.limit_extensions: .php @@ -229,16 +238,18 @@ drush: ruby: install: '1' versions: - rv_jrwr0txy05m1: + rv_2qm0ukipcao0: version: '' python: install: '1' packages: { } versions: - pyenv_1wvvihp6fl7l: - version: 2.6.9 + pyenv_fwkjcy7y5c5c: + version: '' nodejs: install: '0' + settings: + version: null npm_packages: { } hhvm: install: '0' @@ -248,6 +259,16 @@ hhvm: settings: { } server_ini: { } php_ini: { } +mariadb: + install: '0' + settings: + version: '10.0' + root_password: '123' + override_options: { } + adminer: 0 + users: { } + databases: { } + grants: { } mysql: install: '1' settings: @@ -256,40 +277,30 @@ mysql: override_options: { } adminer: '1' users: - mysqlnu_b4losixhd0wu: + mysqlnu_6efdjlpoo19l: name: isosceles_web password: nice2bnice - mysqlnu_h233vl149ap6: + mysqlnu_ndukhgw8g567: name: isosceles_tests password: nice2bnice databases: - mysqlnd_56grg90r4m0c: + mysqlnd_z23s2dylfugz: name: isosceles_web sql: '' - mysqlnd_78nhi4w9lnvn: + mysqlnd_l8ylhahshuy3: name: isosceles_tests sql: '' grants: - mysqlng_uqwk544edprp: + mysqlng_jkn4o2dsy8ty: user: isosceles_web table: '*.*' privileges: - ALL - mysqlng_r9txh5hao51i: + mysqlng_0yik2cvw39ka: user: isosceles_tests table: '*.*' privileges: - ALL -mariadb: - install: '0' - settings: - version: '10.0' - root_password: '123' - override_options: { } - adminer: 0 - users: { } - databases: { } - grants: { } postgresql: install: '0' settings: @@ -308,24 +319,25 @@ mongodb: auth: 1 bind_ip: 127.0.0.1 port: '27017' + globals: + version: 2.6.0 databases: { } redis: install: '0' settings: - conf_port: '6379' + port: '6379' sqlite: install: '0' adminer: 0 databases: { } -mailcatcher: - install: '1' +mailhog: + install: '0' settings: smtp_ip: 0.0.0.0 smtp_port: 1025 http_ip: 0.0.0.0 - http_port: '1080' - mailcatcher_path: /usr/local/rvm/wrappers/default - from_email_method: inline + http_port: '8025' + path: /usr/local/bin/mailhog beanstalkd: install: '0' settings: @@ -349,6 +361,7 @@ elastic_search: settings: version: 1.4.1 java_install: true + instances: { } solr: install: '0' settings: diff --git a/puphpet/files/EXEC-README.txt b/puphpet/files/EXEC-README.txt index 11fca00..c9eb3f1 100644 --- a/puphpet/files/EXEC-README.txt +++ b/puphpet/files/EXEC-README.txt @@ -1,5 +1,7 @@ Files are executed in alphabetical order, and filenames must end in .sh. +Files within exec-preprovision are run one time before Puppet is called. + Files within exec-once-* are run before files within exec-always-*. Files within startup-once-* are run before files within startup-always-*. @@ -18,4 +20,4 @@ Files within exec-once-* will run only the first time you run Vagrant, unless yo Files within startup-always-* will run on each $ vagrant up. Files within startup-once-* will only run on the next time you run Vagrant, unless you SSH into the VM and remove - the /.puphpet-stuff/startup-once-ran and/or /.puphpet-stuff/startup-once-unprivileged-ran files and re-run Vagrant. \ No newline at end of file + the /.puphpet-stuff/startup-once-ran and/or /.puphpet-stuff/startup-once-unprivileged-ran files and re-run Vagrant. diff --git a/puphpet/files/dot/.git-completion.bash b/puphpet/files/dot/.git-completion.bash new file mode 100644 index 0000000..7a6e1d7 --- /dev/null +++ b/puphpet/files/dot/.git-completion.bash @@ -0,0 +1,2712 @@ +# bash/zsh completion support for core Git. +# +# Copyright (C) 2006,2007 Shawn O. Pearce +# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/). +# Distributed under the GNU General Public License, version 2.0. +# +# The contained completion routines provide support for completing: +# +# *) local and remote branch names +# *) local and remote tag names +# *) .git/remotes file names +# *) git 'subcommands' +# *) tree paths within 'ref:path/to/file' expressions +# *) file paths within current working directory and index +# *) common --long-options +# +# To use these routines: +# +# 1) Copy this file to somewhere (e.g. ~/.git-completion.sh). +# 2) Add the following line to your .bashrc/.zshrc: +# source ~/.git-completion.sh +# 3) Consider changing your PS1 to also show the current branch, +# see git-prompt.sh for details. +# +# If you use complex aliases of form '!f() { ... }; f', you can use the null +# command ':' as the first command in the function body to declare the desired +# completion style. For example '!f() { : git commit ; ... }; f' will +# tell the completion to use commit completion. This also works with aliases +# of form "!sh -c '...'". For example, "!sh -c ': git commit ; ... '". + +case "$COMP_WORDBREAKS" in +*:*) : great ;; +*) COMP_WORDBREAKS="$COMP_WORDBREAKS:" +esac + +# __gitdir accepts 0 or 1 arguments (i.e., location) +# returns location of .git repo +__gitdir () +{ + if [ -z "${1-}" ]; then + if [ -n "${__git_dir-}" ]; then + echo "$__git_dir" + elif [ -n "${GIT_DIR-}" ]; then + test -d "${GIT_DIR-}" || return 1 + echo "$GIT_DIR" + elif [ -d .git ]; then + echo .git + else + git rev-parse --git-dir 2>/dev/null + fi + elif [ -d "$1/.git" ]; then + echo "$1/.git" + else + echo "$1" + fi +} + +# The following function is based on code from: +# +# bash_completion - programmable completion functions for bash 3.2+ +# +# Copyright © 2006-2008, Ian Macdonald +# © 2009-2010, Bash Completion Maintainers +# +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The latest version of this software can be obtained here: +# +# http://bash-completion.alioth.debian.org/ +# +# RELEASE: 2.x + +# This function can be used to access a tokenized list of words +# on the command line: +# +# __git_reassemble_comp_words_by_ref '=:' +# if test "${words_[cword_-1]}" = -w +# then +# ... +# fi +# +# The argument should be a collection of characters from the list of +# word completion separators (COMP_WORDBREAKS) to treat as ordinary +# characters. +# +# This is roughly equivalent to going back in time and setting +# COMP_WORDBREAKS to exclude those characters. The intent is to +# make option types like --date= and : easy to +# recognize by treating each shell word as a single token. +# +# It is best not to set COMP_WORDBREAKS directly because the value is +# shared with other completion scripts. By the time the completion +# function gets called, COMP_WORDS has already been populated so local +# changes to COMP_WORDBREAKS have no effect. +# +# Output: words_, cword_, cur_. + +__git_reassemble_comp_words_by_ref() +{ + local exclude i j first + # Which word separators to exclude? + exclude="${1//[^$COMP_WORDBREAKS]}" + cword_=$COMP_CWORD + if [ -z "$exclude" ]; then + words_=("${COMP_WORDS[@]}") + return + fi + # List of word completion separators has shrunk; + # re-assemble words to complete. + for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do + # Append each nonempty word consisting of just + # word separator characters to the current word. + first=t + while + [ $i -gt 0 ] && + [ -n "${COMP_WORDS[$i]}" ] && + # word consists of excluded word separators + [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ] + do + # Attach to the previous token, + # unless the previous token is the command name. + if [ $j -ge 2 ] && [ -n "$first" ]; then + ((j--)) + fi + first= + words_[$j]=${words_[j]}${COMP_WORDS[i]} + if [ $i = $COMP_CWORD ]; then + cword_=$j + fi + if (($i < ${#COMP_WORDS[@]} - 1)); then + ((i++)) + else + # Done. + return + fi + done + words_[$j]=${words_[j]}${COMP_WORDS[i]} + if [ $i = $COMP_CWORD ]; then + cword_=$j + fi + done +} + +if ! type _get_comp_words_by_ref >/dev/null 2>&1; then +_get_comp_words_by_ref () +{ + local exclude cur_ words_ cword_ + if [ "$1" = "-n" ]; then + exclude=$2 + shift 2 + fi + __git_reassemble_comp_words_by_ref "$exclude" + cur_=${words_[cword_]} + while [ $# -gt 0 ]; do + case "$1" in + cur) + cur=$cur_ + ;; + prev) + prev=${words_[$cword_-1]} + ;; + words) + words=("${words_[@]}") + ;; + cword) + cword=$cword_ + ;; + esac + shift + done +} +fi + +__gitcompappend () +{ + local i=${#COMPREPLY[@]} + for x in $1; do + if [[ "$x" == "$3"* ]]; then + COMPREPLY[i++]="$2$x$4" + fi + done +} + +__gitcompadd () +{ + COMPREPLY=() + __gitcompappend "$@" +} + +# Generates completion reply, appending a space to possible completion words, +# if necessary. +# It accepts 1 to 4 arguments: +# 1: List of possible completion words. +# 2: A prefix to be added to each possible completion word (optional). +# 3: Generate possible completion matches for this word (optional). +# 4: A suffix to be appended to each possible completion word (optional). +__gitcomp () +{ + local cur_="${3-$cur}" + + case "$cur_" in + --*=) + ;; + *) + local c i=0 IFS=$' \t\n' + for c in $1; do + c="$c${4-}" + if [[ $c == "$cur_"* ]]; then + case $c in + --*=*|*.) ;; + *) c="$c " ;; + esac + COMPREPLY[i++]="${2-}$c" + fi + done + ;; + esac +} + +# Variation of __gitcomp_nl () that appends to the existing list of +# completion candidates, COMPREPLY. +__gitcomp_nl_append () +{ + local IFS=$'\n' + __gitcompappend "$1" "${2-}" "${3-$cur}" "${4- }" +} + +# Generates completion reply from newline-separated possible completion words +# by appending a space to all of them. +# It accepts 1 to 4 arguments: +# 1: List of possible completion words, separated by a single newline. +# 2: A prefix to be added to each possible completion word (optional). +# 3: Generate possible completion matches for this word (optional). +# 4: A suffix to be appended to each possible completion word instead of +# the default space (optional). If specified but empty, nothing is +# appended. +__gitcomp_nl () +{ + COMPREPLY=() + __gitcomp_nl_append "$@" +} + +# Generates completion reply with compgen from newline-separated possible +# completion filenames. +# It accepts 1 to 3 arguments: +# 1: List of possible completion filenames, separated by a single newline. +# 2: A directory prefix to be added to each possible completion filename +# (optional). +# 3: Generate possible completion matches for this word (optional). +__gitcomp_file () +{ + local IFS=$'\n' + + # XXX does not work when the directory prefix contains a tilde, + # since tilde expansion is not applied. + # This means that COMPREPLY will be empty and Bash default + # completion will be used. + __gitcompadd "$1" "${2-}" "${3-$cur}" "" + + # use a hack to enable file mode in bash < 4 + compopt -o filenames +o nospace 2>/dev/null || + compgen -f /non-existing-dir/ > /dev/null +} + +# Execute 'git ls-files', unless the --committable option is specified, in +# which case it runs 'git diff-index' to find out the files that can be +# committed. It return paths relative to the directory specified in the first +# argument, and using the options specified in the second argument. +__git_ls_files_helper () +{ + ( + test -n "${CDPATH+set}" && unset CDPATH + cd "$1" + if [ "$2" == "--committable" ]; then + git diff-index --name-only --relative HEAD + else + # NOTE: $2 is not quoted in order to support multiple options + git ls-files --exclude-standard $2 + fi + ) 2>/dev/null +} + + +# __git_index_files accepts 1 or 2 arguments: +# 1: Options to pass to ls-files (required). +# 2: A directory path (optional). +# If provided, only files within the specified directory are listed. +# Sub directories are never recursed. Path must have a trailing +# slash. +__git_index_files () +{ + local dir="$(__gitdir)" root="${2-.}" file + + if [ -d "$dir" ]; then + __git_ls_files_helper "$root" "$1" | + while read -r file; do + case "$file" in + ?*/*) echo "${file%%/*}" ;; + *) echo "$file" ;; + esac + done | sort | uniq + fi +} + +__git_heads () +{ + local dir="$(__gitdir)" + if [ -d "$dir" ]; then + git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + refs/heads + return + fi +} + +__git_tags () +{ + local dir="$(__gitdir)" + if [ -d "$dir" ]; then + git --git-dir="$dir" for-each-ref --format='%(refname:short)' \ + refs/tags + return + fi +} + +# __git_refs accepts 0, 1 (to pass to __gitdir), or 2 arguments +# presence of 2nd argument means use the guess heuristic employed +# by checkout for tracking branches +__git_refs () +{ + local i hash dir="$(__gitdir "${1-}")" track="${2-}" + local format refs + if [ -d "$dir" ]; then + case "$cur" in + refs|refs/*) + format="refname" + refs="${cur%/*}" + track="" + ;; + *) + for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do + if [ -e "$dir/$i" ]; then echo $i; fi + done + format="refname:short" + refs="refs/tags refs/heads refs/remotes" + ;; + esac + git --git-dir="$dir" for-each-ref --format="%($format)" \ + $refs + if [ -n "$track" ]; then + # employ the heuristic used by git checkout + # Try to find a remote branch that matches the completion word + # but only output if the branch name is unique + local ref entry + git --git-dir="$dir" for-each-ref --shell --format="ref=%(refname:short)" \ + "refs/remotes/" | \ + while read -r entry; do + eval "$entry" + ref="${ref#*/}" + if [[ "$ref" == "$cur"* ]]; then + echo "$ref" + fi + done | sort | uniq -u + fi + return + fi + case "$cur" in + refs|refs/*) + git ls-remote "$dir" "$cur*" 2>/dev/null | \ + while read -r hash i; do + case "$i" in + *^{}) ;; + *) echo "$i" ;; + esac + done + ;; + *) + echo "HEAD" + git for-each-ref --format="%(refname:short)" -- "refs/remotes/$dir/" | sed -e "s#^$dir/##" + ;; + esac +} + +# __git_refs2 requires 1 argument (to pass to __git_refs) +__git_refs2 () +{ + local i + for i in $(__git_refs "$1"); do + echo "$i:$i" + done +} + +# __git_refs_remotes requires 1 argument (to pass to ls-remote) +__git_refs_remotes () +{ + local i hash + git ls-remote "$1" 'refs/heads/*' 2>/dev/null | \ + while read -r hash i; do + echo "$i:refs/remotes/$1/${i#refs/heads/}" + done +} + +__git_remotes () +{ + local i IFS=$'\n' d="$(__gitdir)" + test -d "$d/remotes" && ls -1 "$d/remotes" + for i in $(git --git-dir="$d" config --get-regexp 'remote\..*\.url' 2>/dev/null); do + i="${i#remote.}" + echo "${i/.url*/}" + done +} + +__git_list_merge_strategies () +{ + git merge -s help 2>&1 | + sed -n -e '/[Aa]vailable strategies are: /,/^$/{ + s/\.$// + s/.*:// + s/^[ ]*// + s/[ ]*$// + p + }' +} + +__git_merge_strategies= +# 'git merge -s help' (and thus detection of the merge strategy +# list) fails, unfortunately, if run outside of any git working +# tree. __git_merge_strategies is set to the empty string in +# that case, and the detection will be repeated the next time it +# is needed. +__git_compute_merge_strategies () +{ + test -n "$__git_merge_strategies" || + __git_merge_strategies=$(__git_list_merge_strategies) +} + +__git_complete_revlist_file () +{ + local pfx ls ref cur_="$cur" + case "$cur_" in + *..?*:*) + return + ;; + ?*:*) + ref="${cur_%%:*}" + cur_="${cur_#*:}" + case "$cur_" in + ?*/*) + pfx="${cur_%/*}" + cur_="${cur_##*/}" + ls="$ref:$pfx" + pfx="$pfx/" + ;; + *) + ls="$ref" + ;; + esac + + case "$COMP_WORDBREAKS" in + *:*) : great ;; + *) pfx="$ref:$pfx" ;; + esac + + __gitcomp_nl "$(git --git-dir="$(__gitdir)" ls-tree "$ls" 2>/dev/null \ + | sed '/^100... blob /{ + s,^.* ,, + s,$, , + } + /^120000 blob /{ + s,^.* ,, + s,$, , + } + /^040000 tree /{ + s,^.* ,, + s,$,/, + } + s/^.* //')" \ + "$pfx" "$cur_" "" + ;; + *...*) + pfx="${cur_%...*}..." + cur_="${cur_#*...}" + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + ;; + *..*) + pfx="${cur_%..*}.." + cur_="${cur_#*..}" + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac +} + + +# __git_complete_index_file requires 1 argument: +# 1: the options to pass to ls-file +# +# The exception is --committable, which finds the files appropriate commit. +__git_complete_index_file () +{ + local pfx="" cur_="$cur" + + case "$cur_" in + ?*/*) + pfx="${cur_%/*}" + cur_="${cur_##*/}" + pfx="${pfx}/" + ;; + esac + + __gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_" +} + +__git_complete_file () +{ + __git_complete_revlist_file +} + +__git_complete_revlist () +{ + __git_complete_revlist_file +} + +__git_complete_remote_or_refspec () +{ + local cur_="$cur" cmd="${words[1]}" + local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0 + if [ "$cmd" = "remote" ]; then + ((c++)) + fi + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + --mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;; + --all) + case "$cmd" in + push) no_complete_refspec=1 ;; + fetch) + return + ;; + *) ;; + esac + ;; + -*) ;; + *) remote="$i"; break ;; + esac + ((c++)) + done + if [ -z "$remote" ]; then + __gitcomp_nl "$(__git_remotes)" + return + fi + if [ $no_complete_refspec = 1 ]; then + return + fi + [ "$remote" = "." ] && remote= + case "$cur_" in + *:*) + case "$COMP_WORDBREAKS" in + *:*) : great ;; + *) pfx="${cur_%%:*}:" ;; + esac + cur_="${cur_#*:}" + lhs=0 + ;; + +*) + pfx="+" + cur_="${cur_#+}" + ;; + esac + case "$cmd" in + fetch) + if [ $lhs = 1 ]; then + __gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_" + else + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + fi + ;; + pull|remote) + if [ $lhs = 1 ]; then + __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" + else + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + fi + ;; + push) + if [ $lhs = 1 ]; then + __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_" + else + __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_" + fi + ;; + esac +} + +__git_complete_strategy () +{ + __git_compute_merge_strategies + case "$prev" in + -s|--strategy) + __gitcomp "$__git_merge_strategies" + return 0 + esac + case "$cur" in + --strategy=*) + __gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}" + return 0 + ;; + esac + return 1 +} + +__git_commands () { + if test -n "${GIT_TESTING_COMMAND_COMPLETION:-}" + then + printf "%s" "${GIT_TESTING_COMMAND_COMPLETION}" + else + git help -a|egrep '^ [a-zA-Z0-9]' + fi +} + +__git_list_all_commands () +{ + local i IFS=" "$'\n' + for i in $(__git_commands) + do + case $i in + *--*) : helper pattern;; + *) echo $i;; + esac + done +} + +__git_all_commands= +__git_compute_all_commands () +{ + test -n "$__git_all_commands" || + __git_all_commands=$(__git_list_all_commands) +} + +__git_list_porcelain_commands () +{ + local i IFS=" "$'\n' + __git_compute_all_commands + for i in $__git_all_commands + do + case $i in + *--*) : helper pattern;; + applymbox) : ask gittus;; + applypatch) : ask gittus;; + archimport) : import;; + cat-file) : plumbing;; + check-attr) : plumbing;; + check-ignore) : plumbing;; + check-mailmap) : plumbing;; + check-ref-format) : plumbing;; + checkout-index) : plumbing;; + commit-tree) : plumbing;; + count-objects) : infrequent;; + credential-cache) : credentials helper;; + credential-store) : credentials helper;; + cvsexportcommit) : export;; + cvsimport) : import;; + cvsserver) : daemon;; + daemon) : daemon;; + diff-files) : plumbing;; + diff-index) : plumbing;; + diff-tree) : plumbing;; + fast-import) : import;; + fast-export) : export;; + fsck-objects) : plumbing;; + fetch-pack) : plumbing;; + fmt-merge-msg) : plumbing;; + for-each-ref) : plumbing;; + hash-object) : plumbing;; + http-*) : transport;; + index-pack) : plumbing;; + init-db) : deprecated;; + local-fetch) : plumbing;; + ls-files) : plumbing;; + ls-remote) : plumbing;; + ls-tree) : plumbing;; + mailinfo) : plumbing;; + mailsplit) : plumbing;; + merge-*) : plumbing;; + mktree) : plumbing;; + mktag) : plumbing;; + pack-objects) : plumbing;; + pack-redundant) : plumbing;; + pack-refs) : plumbing;; + parse-remote) : plumbing;; + patch-id) : plumbing;; + prune) : plumbing;; + prune-packed) : plumbing;; + quiltimport) : import;; + read-tree) : plumbing;; + receive-pack) : plumbing;; + remote-*) : transport;; + rerere) : plumbing;; + rev-list) : plumbing;; + rev-parse) : plumbing;; + runstatus) : plumbing;; + sh-setup) : internal;; + shell) : daemon;; + show-ref) : plumbing;; + send-pack) : plumbing;; + show-index) : plumbing;; + ssh-*) : transport;; + stripspace) : plumbing;; + symbolic-ref) : plumbing;; + unpack-file) : plumbing;; + unpack-objects) : plumbing;; + update-index) : plumbing;; + update-ref) : plumbing;; + update-server-info) : daemon;; + upload-archive) : plumbing;; + upload-pack) : plumbing;; + write-tree) : plumbing;; + var) : infrequent;; + verify-pack) : infrequent;; + verify-tag) : plumbing;; + *) echo $i;; + esac + done +} + +__git_porcelain_commands= +__git_compute_porcelain_commands () +{ + __git_compute_all_commands + test -n "$__git_porcelain_commands" || + __git_porcelain_commands=$(__git_list_porcelain_commands) +} + +__git_pretty_aliases () +{ + local i IFS=$'\n' + for i in $(git --git-dir="$(__gitdir)" config --get-regexp "pretty\..*" 2>/dev/null); do + case "$i" in + pretty.*) + i="${i#pretty.}" + echo "${i/ */}" + ;; + esac + done +} + +__git_aliases () +{ + local i IFS=$'\n' + for i in $(git --git-dir="$(__gitdir)" config --get-regexp "alias\..*" 2>/dev/null); do + case "$i" in + alias.*) + i="${i#alias.}" + echo "${i/ */}" + ;; + esac + done +} + +# __git_aliased_command requires 1 argument +__git_aliased_command () +{ + local word cmdline=$(git --git-dir="$(__gitdir)" \ + config --get "alias.$1") + for word in $cmdline; do + case "$word" in + \!gitk|gitk) + echo "gitk" + return + ;; + \!*) : shell command alias ;; + -*) : option ;; + *=*) : setting env ;; + git) : git itself ;; + \(\)) : skip parens of shell function definition ;; + {) : skip start of shell helper function ;; + :) : skip null command ;; + \'*) : skip opening quote after sh -c ;; + *) + echo "$word" + return + esac + done +} + +# __git_find_on_cmdline requires 1 argument +__git_find_on_cmdline () +{ + local word subcommand c=1 + while [ $c -lt $cword ]; do + word="${words[c]}" + for subcommand in $1; do + if [ "$subcommand" = "$word" ]; then + echo "$subcommand" + return + fi + done + ((c++)) + done +} + +__git_has_doubledash () +{ + local c=1 + while [ $c -lt $cword ]; do + if [ "--" = "${words[c]}" ]; then + return 0 + fi + ((c++)) + done + return 1 +} + +# Try to count non option arguments passed on the command line for the +# specified git command. +# When options are used, it is necessary to use the special -- option to +# tell the implementation were non option arguments begin. +# XXX this can not be improved, since options can appear everywhere, as +# an example: +# git mv x -n y +# +# __git_count_arguments requires 1 argument: the git command executed. +__git_count_arguments () +{ + local word i c=0 + + # Skip "git" (first argument) + for ((i=1; i < ${#words[@]}; i++)); do + word="${words[i]}" + + case "$word" in + --) + # Good; we can assume that the following are only non + # option arguments. + ((c = 0)) + ;; + "$1") + # Skip the specified git command and discard git + # main options + ((c = 0)) + ;; + ?*) + ((c++)) + ;; + esac + done + + printf "%d" $c +} + +__git_whitespacelist="nowarn warn error error-all fix" + +_git_am () +{ + local dir="$(__gitdir)" + if [ -d "$dir"/rebase-apply ]; then + __gitcomp "--skip --continue --resolved --abort" + return + fi + case "$cur" in + --whitespace=*) + __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" + return + ;; + --*) + __gitcomp " + --3way --committer-date-is-author-date --ignore-date + --ignore-whitespace --ignore-space-change + --interactive --keep --no-utf8 --signoff --utf8 + --whitespace= --scissors + " + return + esac +} + +_git_apply () +{ + case "$cur" in + --whitespace=*) + __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" + return + ;; + --*) + __gitcomp " + --stat --numstat --summary --check --index + --cached --index-info --reverse --reject --unidiff-zero + --apply --no-add --exclude= + --ignore-whitespace --ignore-space-change + --whitespace= --inaccurate-eof --verbose + " + return + esac +} + +_git_add () +{ + case "$cur" in + --*) + __gitcomp " + --interactive --refresh --patch --update --dry-run + --ignore-errors --intent-to-add + " + return + esac + + # XXX should we check for --update and --all options ? + __git_complete_index_file "--others --modified --directory --no-empty-directory" +} + +_git_archive () +{ + case "$cur" in + --format=*) + __gitcomp "$(git archive --list)" "" "${cur##--format=}" + return + ;; + --remote=*) + __gitcomp_nl "$(__git_remotes)" "" "${cur##--remote=}" + return + ;; + --*) + __gitcomp " + --format= --list --verbose + --prefix= --remote= --exec= + " + return + ;; + esac + __git_complete_file +} + +_git_bisect () +{ + __git_has_doubledash && return + + local subcommands="start bad good skip reset visualize replay log run" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + if [ -f "$(__gitdir)"/BISECT_START ]; then + __gitcomp "$subcommands" + else + __gitcomp "replay start" + fi + return + fi + + case "$subcommand" in + bad|good|reset|skip|start) + __gitcomp_nl "$(__git_refs)" + ;; + *) + ;; + esac +} + +_git_branch () +{ + local i c=1 only_local_ref="n" has_r="n" + + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -d|-m) only_local_ref="y" ;; + -r) has_r="y" ;; + esac + ((c++)) + done + + case "$cur" in + --set-upstream-to=*) + __gitcomp "$(__git_refs)" "" "${cur##--set-upstream-to=}" + ;; + --*) + __gitcomp " + --color --no-color --verbose --abbrev= --no-abbrev + --track --no-track --contains --merged --no-merged + --set-upstream-to= --edit-description --list + --unset-upstream + " + ;; + *) + if [ $only_local_ref = "y" -a $has_r = "n" ]; then + __gitcomp_nl "$(__git_heads)" + else + __gitcomp_nl "$(__git_refs)" + fi + ;; + esac +} + +_git_bundle () +{ + local cmd="${words[2]}" + case "$cword" in + 2) + __gitcomp "create list-heads verify unbundle" + ;; + 3) + # looking for a file + ;; + *) + case "$cmd" in + create) + __git_complete_revlist + ;; + esac + ;; + esac +} + +_git_checkout () +{ + __git_has_doubledash && return + + case "$cur" in + --conflict=*) + __gitcomp "diff3 merge" "" "${cur##--conflict=}" + ;; + --*) + __gitcomp " + --quiet --ours --theirs --track --no-track --merge + --conflict= --orphan --patch + " + ;; + *) + # check if --track, --no-track, or --no-guess was specified + # if so, disable DWIM mode + local flags="--track --no-track --no-guess" track=1 + if [ -n "$(__git_find_on_cmdline "$flags")" ]; then + track='' + fi + __gitcomp_nl "$(__git_refs '' $track)" + ;; + esac +} + +_git_cherry () +{ + __gitcomp "$(__git_refs)" +} + +_git_cherry_pick () +{ + local dir="$(__gitdir)" + if [ -f "$dir"/CHERRY_PICK_HEAD ]; then + __gitcomp "--continue --quit --abort" + return + fi + case "$cur" in + --*) + __gitcomp "--edit --no-commit --signoff --strategy= --mainline" + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac +} + +_git_clean () +{ + case "$cur" in + --*) + __gitcomp "--dry-run --quiet" + return + ;; + esac + + # XXX should we check for -x option ? + __git_complete_index_file "--others --directory" +} + +_git_clone () +{ + case "$cur" in + --*) + __gitcomp " + --local + --no-hardlinks + --shared + --reference + --quiet + --no-checkout + --bare + --mirror + --origin + --upload-pack + --template= + --depth + --single-branch + --branch + " + return + ;; + esac +} + +_git_commit () +{ + case "$prev" in + -c|-C) + __gitcomp_nl "$(__git_refs)" "" "${cur}" + return + ;; + esac + + case "$cur" in + --cleanup=*) + __gitcomp "default strip verbatim whitespace + " "" "${cur##--cleanup=}" + return + ;; + --reuse-message=*|--reedit-message=*|\ + --fixup=*|--squash=*) + __gitcomp_nl "$(__git_refs)" "" "${cur#*=}" + return + ;; + --untracked-files=*) + __gitcomp "all no normal" "" "${cur##--untracked-files=}" + return + ;; + --*) + __gitcomp " + --all --author= --signoff --verify --no-verify + --edit --no-edit + --amend --include --only --interactive + --dry-run --reuse-message= --reedit-message= + --reset-author --file= --message= --template= + --cleanup= --untracked-files --untracked-files= + --verbose --quiet --fixup= --squash= + " + return + esac + + if git rev-parse --verify --quiet HEAD >/dev/null; then + __git_complete_index_file "--committable" + else + # This is the first commit + __git_complete_index_file "--cached" + fi +} + +_git_describe () +{ + case "$cur" in + --*) + __gitcomp " + --all --tags --contains --abbrev= --candidates= + --exact-match --debug --long --match --always + " + return + esac + __gitcomp_nl "$(__git_refs)" +} + +__git_diff_algorithms="myers minimal patience histogram" + +__git_diff_common_options="--stat --numstat --shortstat --summary + --patch-with-stat --name-only --name-status --color + --no-color --color-words --no-renames --check + --full-index --binary --abbrev --diff-filter= + --find-copies-harder + --text --ignore-space-at-eol --ignore-space-change + --ignore-all-space --exit-code --quiet --ext-diff + --no-ext-diff + --no-prefix --src-prefix= --dst-prefix= + --inter-hunk-context= + --patience --histogram --minimal + --raw --word-diff + --dirstat --dirstat= --dirstat-by-file + --dirstat-by-file= --cumulative + --diff-algorithm= +" + +_git_diff () +{ + __git_has_doubledash && return + + case "$cur" in + --diff-algorithm=*) + __gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}" + return + ;; + --*) + __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex + --base --ours --theirs --no-index + $__git_diff_common_options + " + return + ;; + esac + __git_complete_revlist_file +} + +__git_mergetools_common="diffuse diffmerge ecmerge emerge kdiff3 meld opendiff + tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc3 codecompare +" + +_git_difftool () +{ + __git_has_doubledash && return + + case "$cur" in + --tool=*) + __gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}" + return + ;; + --*) + __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex + --base --ours --theirs + --no-renames --diff-filter= --find-copies-harder + --relative --ignore-submodules + --tool=" + return + ;; + esac + __git_complete_revlist_file +} + +__git_fetch_recurse_submodules="yes on-demand no" + +__git_fetch_options=" + --quiet --verbose --append --upload-pack --force --keep --depth= + --tags --no-tags --all --prune --dry-run --recurse-submodules= +" + +_git_fetch () +{ + case "$cur" in + --recurse-submodules=*) + __gitcomp "$__git_fetch_recurse_submodules" "" "${cur##--recurse-submodules=}" + return + ;; + --*) + __gitcomp "$__git_fetch_options" + return + ;; + esac + __git_complete_remote_or_refspec +} + +__git_format_patch_options=" + --stdout --attach --no-attach --thread --thread= --no-thread + --numbered --start-number --numbered-files --keep-subject --signoff + --signature --no-signature --in-reply-to= --cc= --full-index --binary + --not --all --cover-letter --no-prefix --src-prefix= --dst-prefix= + --inline --suffix= --ignore-if-in-upstream --subject-prefix= + --output-directory --reroll-count --to= --quiet --notes +" + +_git_format_patch () +{ + case "$cur" in + --thread=*) + __gitcomp " + deep shallow + " "" "${cur##--thread=}" + return + ;; + --*) + __gitcomp "$__git_format_patch_options" + return + ;; + esac + __git_complete_revlist +} + +_git_fsck () +{ + case "$cur" in + --*) + __gitcomp " + --tags --root --unreachable --cache --no-reflogs --full + --strict --verbose --lost-found + " + return + ;; + esac +} + +_git_gc () +{ + case "$cur" in + --*) + __gitcomp "--prune --aggressive" + return + ;; + esac +} + +_git_gitk () +{ + _gitk +} + +__git_match_ctag() { + awk "/^${1////\\/}/ { print \$1 }" "$2" +} + +_git_grep () +{ + __git_has_doubledash && return + + case "$cur" in + --*) + __gitcomp " + --cached + --text --ignore-case --word-regexp --invert-match + --full-name --line-number + --extended-regexp --basic-regexp --fixed-strings + --perl-regexp + --files-with-matches --name-only + --files-without-match + --max-depth + --count + --and --or --not --all-match + " + return + ;; + esac + + case "$cword,$prev" in + 2,*|*,-*) + if test -r tags; then + __gitcomp_nl "$(__git_match_ctag "$cur" tags)" + return + fi + ;; + esac + + __gitcomp_nl "$(__git_refs)" +} + +_git_help () +{ + case "$cur" in + --*) + __gitcomp "--all --info --man --web" + return + ;; + esac + __git_compute_all_commands + __gitcomp "$__git_all_commands $(__git_aliases) + attributes cli core-tutorial cvs-migration + diffcore gitk glossary hooks ignore modules + namespaces repository-layout tutorial tutorial-2 + workflows + " +} + +_git_init () +{ + case "$cur" in + --shared=*) + __gitcomp " + false true umask group all world everybody + " "" "${cur##--shared=}" + return + ;; + --*) + __gitcomp "--quiet --bare --template= --shared --shared=" + return + ;; + esac +} + +_git_ls_files () +{ + case "$cur" in + --*) + __gitcomp "--cached --deleted --modified --others --ignored + --stage --directory --no-empty-directory --unmerged + --killed --exclude= --exclude-from= + --exclude-per-directory= --exclude-standard + --error-unmatch --with-tree= --full-name + --abbrev --ignored --exclude-per-directory + " + return + ;; + esac + + # XXX ignore options like --modified and always suggest all cached + # files. + __git_complete_index_file "--cached" +} + +_git_ls_remote () +{ + __gitcomp_nl "$(__git_remotes)" +} + +_git_ls_tree () +{ + __git_complete_file +} + +# Options that go well for log, shortlog and gitk +__git_log_common_options=" + --not --all + --branches --tags --remotes + --first-parent --merges --no-merges + --max-count= + --max-age= --since= --after= + --min-age= --until= --before= + --min-parents= --max-parents= + --no-min-parents --no-max-parents +" +# Options that go well for log and gitk (not shortlog) +__git_log_gitk_options=" + --dense --sparse --full-history + --simplify-merges --simplify-by-decoration + --left-right --notes --no-notes +" +# Options that go well for log and shortlog (not gitk) +__git_log_shortlog_options=" + --author= --committer= --grep= + --all-match +" + +__git_log_pretty_formats="oneline short medium full fuller email raw format:" +__git_log_date_formats="relative iso8601 rfc2822 short local default raw" + +_git_log () +{ + __git_has_doubledash && return + + local g="$(git rev-parse --git-dir 2>/dev/null)" + local merge="" + if [ -f "$g/MERGE_HEAD" ]; then + merge="--merge" + fi + case "$cur" in + --pretty=*|--format=*) + __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases) + " "" "${cur#*=}" + return + ;; + --date=*) + __gitcomp "$__git_log_date_formats" "" "${cur##--date=}" + return + ;; + --decorate=*) + __gitcomp "long short" "" "${cur##--decorate=}" + return + ;; + --*) + __gitcomp " + $__git_log_common_options + $__git_log_shortlog_options + $__git_log_gitk_options + --root --topo-order --date-order --reverse + --follow --full-diff + --abbrev-commit --abbrev= + --relative-date --date= + --pretty= --format= --oneline + --cherry-pick + --graph + --decorate --decorate= + --walk-reflogs + --parents --children + $merge + $__git_diff_common_options + --pickaxe-all --pickaxe-regex + " + return + ;; + esac + __git_complete_revlist +} + +# Common merge options shared by git-merge(1) and git-pull(1). +__git_merge_options=" + --no-commit --no-stat --log --no-log --squash --strategy + --commit --stat --no-squash --ff --no-ff --ff-only --edit --no-edit + --verify-signatures --no-verify-signatures --gpg-sign + --quiet --verbose --progress --no-progress +" + +_git_merge () +{ + __git_complete_strategy && return + + case "$cur" in + --*) + __gitcomp "$__git_merge_options + --rerere-autoupdate --no-rerere-autoupdate --abort" + return + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_mergetool () +{ + case "$cur" in + --tool=*) + __gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}" + return + ;; + --*) + __gitcomp "--tool=" + return + ;; + esac +} + +_git_merge_base () +{ + case "$cur" in + --*) + __gitcomp "--octopus --independent --is-ancestor --fork-point" + return + ;; + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_mv () +{ + case "$cur" in + --*) + __gitcomp "--dry-run" + return + ;; + esac + + if [ $(__git_count_arguments "mv") -gt 0 ]; then + # We need to show both cached and untracked files (including + # empty directories) since this may not be the last argument. + __git_complete_index_file "--cached --others --directory" + else + __git_complete_index_file "--cached" + fi +} + +_git_name_rev () +{ + __gitcomp "--tags --all --stdin" +} + +_git_notes () +{ + local subcommands='add append copy edit list prune remove show' + local subcommand="$(__git_find_on_cmdline "$subcommands")" + + case "$subcommand,$cur" in + ,--*) + __gitcomp '--ref' + ;; + ,*) + case "$prev" in + --ref) + __gitcomp_nl "$(__git_refs)" + ;; + *) + __gitcomp "$subcommands --ref" + ;; + esac + ;; + add,--reuse-message=*|append,--reuse-message=*|\ + add,--reedit-message=*|append,--reedit-message=*) + __gitcomp_nl "$(__git_refs)" "" "${cur#*=}" + ;; + add,--*|append,--*) + __gitcomp '--file= --message= --reedit-message= + --reuse-message=' + ;; + copy,--*) + __gitcomp '--stdin' + ;; + prune,--*) + __gitcomp '--dry-run --verbose' + ;; + prune,*) + ;; + *) + case "$prev" in + -m|-F) + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac + ;; + esac +} + +_git_pull () +{ + __git_complete_strategy && return + + case "$cur" in + --recurse-submodules=*) + __gitcomp "$__git_fetch_recurse_submodules" "" "${cur##--recurse-submodules=}" + return + ;; + --*) + __gitcomp " + --rebase --no-rebase + $__git_merge_options + $__git_fetch_options + " + return + ;; + esac + __git_complete_remote_or_refspec +} + +__git_push_recurse_submodules="check on-demand" + +_git_push () +{ + case "$prev" in + --repo) + __gitcomp_nl "$(__git_remotes)" + return + esac + case "$cur" in + --repo=*) + __gitcomp_nl "$(__git_remotes)" "" "${cur##--repo=}" + return + ;; + --recurse-submodules=*) + __gitcomp "$__git_push_recurse_submodules" "" "${cur##--recurse-submodules=}" + return + ;; + --*) + __gitcomp " + --all --mirror --tags --dry-run --force --verbose + --receive-pack= --repo= --set-upstream + --recurse-submodules= + " + return + ;; + esac + __git_complete_remote_or_refspec +} + +_git_rebase () +{ + local dir="$(__gitdir)" + if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then + __gitcomp "--continue --skip --abort" + return + fi + __git_complete_strategy && return + case "$cur" in + --whitespace=*) + __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}" + return + ;; + --*) + __gitcomp " + --onto --merge --strategy --interactive + --preserve-merges --stat --no-stat + --committer-date-is-author-date --ignore-date + --ignore-whitespace --whitespace= + --autosquash --fork-point --no-fork-point + " + + return + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_reflog () +{ + local subcommands="show delete expire" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + else + __gitcomp_nl "$(__git_refs)" + fi +} + +__git_send_email_confirm_options="always never auto cc compose" +__git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all" + +_git_send_email () +{ + case "$cur" in + --confirm=*) + __gitcomp " + $__git_send_email_confirm_options + " "" "${cur##--confirm=}" + return + ;; + --suppress-cc=*) + __gitcomp " + $__git_send_email_suppresscc_options + " "" "${cur##--suppress-cc=}" + + return + ;; + --smtp-encryption=*) + __gitcomp "ssl tls" "" "${cur##--smtp-encryption=}" + return + ;; + --thread=*) + __gitcomp " + deep shallow + " "" "${cur##--thread=}" + return + ;; + --*) + __gitcomp "--annotate --bcc --cc --cc-cmd --chain-reply-to + --compose --confirm= --dry-run --envelope-sender + --from --identity + --in-reply-to --no-chain-reply-to --no-signed-off-by-cc + --no-suppress-from --no-thread --quiet + --signed-off-by-cc --smtp-pass --smtp-server + --smtp-server-port --smtp-encryption= --smtp-user + --subject --suppress-cc= --suppress-from --thread --to + --validate --no-validate + $__git_format_patch_options" + return + ;; + esac + __git_complete_revlist +} + +_git_stage () +{ + _git_add +} + +__git_config_get_set_variables () +{ + local prevword word config_file= c=$cword + while [ $c -gt 1 ]; do + word="${words[c]}" + case "$word" in + --system|--global|--local|--file=*) + config_file="$word" + break + ;; + -f|--file) + config_file="$word $prevword" + break + ;; + esac + prevword=$word + c=$((--c)) + done + + git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null | + while read -r line + do + case "$line" in + *.*=*) + echo "${line/=*/}" + ;; + esac + done +} + +_git_config () +{ + case "$prev" in + branch.*.remote|branch.*.pushremote) + __gitcomp_nl "$(__git_remotes)" + return + ;; + branch.*.merge) + __gitcomp_nl "$(__git_refs)" + return + ;; + branch.*.rebase) + __gitcomp "false true" + return + ;; + remote.pushdefault) + __gitcomp_nl "$(__git_remotes)" + return + ;; + remote.*.fetch) + local remote="${prev#remote.}" + remote="${remote%.fetch}" + if [ -z "$cur" ]; then + __gitcomp_nl "refs/heads/" "" "" "" + return + fi + __gitcomp_nl "$(__git_refs_remotes "$remote")" + return + ;; + remote.*.push) + local remote="${prev#remote.}" + remote="${remote%.push}" + __gitcomp_nl "$(git --git-dir="$(__gitdir)" \ + for-each-ref --format='%(refname):%(refname)' \ + refs/heads)" + return + ;; + pull.twohead|pull.octopus) + __git_compute_merge_strategies + __gitcomp "$__git_merge_strategies" + return + ;; + color.branch|color.diff|color.interactive|\ + color.showbranch|color.status|color.ui) + __gitcomp "always never auto" + return + ;; + color.pager) + __gitcomp "false true" + return + ;; + color.*.*) + __gitcomp " + normal black red green yellow blue magenta cyan white + bold dim ul blink reverse + " + return + ;; + diff.submodule) + __gitcomp "log short" + return + ;; + help.format) + __gitcomp "man info web html" + return + ;; + log.date) + __gitcomp "$__git_log_date_formats" + return + ;; + sendemail.aliasesfiletype) + __gitcomp "mutt mailrc pine elm gnus" + return + ;; + sendemail.confirm) + __gitcomp "$__git_send_email_confirm_options" + return + ;; + sendemail.suppresscc) + __gitcomp "$__git_send_email_suppresscc_options" + return + ;; + --get|--get-all|--unset|--unset-all) + __gitcomp_nl "$(__git_config_get_set_variables)" + return + ;; + *.*) + return + ;; + esac + case "$cur" in + --*) + __gitcomp " + --system --global --local --file= + --list --replace-all + --get --get-all --get-regexp + --add --unset --unset-all + --remove-section --rename-section + " + return + ;; + branch.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "remote pushremote merge mergeoptions rebase" "$pfx" "$cur_" + return + ;; + branch.*) + local pfx="${cur%.*}." cur_="${cur#*.}" + __gitcomp_nl "$(__git_heads)" "$pfx" "$cur_" "." + __gitcomp_nl_append $'autosetupmerge\nautosetuprebase\n' "$pfx" "$cur_" + return + ;; + guitool.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp " + argprompt cmd confirm needsfile noconsole norescan + prompt revprompt revunmerged title + " "$pfx" "$cur_" + return + ;; + difftool.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "cmd path" "$pfx" "$cur_" + return + ;; + man.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "cmd path" "$pfx" "$cur_" + return + ;; + mergetool.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "cmd path trustExitCode" "$pfx" "$cur_" + return + ;; + pager.*) + local pfx="${cur%.*}." cur_="${cur#*.}" + __git_compute_all_commands + __gitcomp_nl "$__git_all_commands" "$pfx" "$cur_" + return + ;; + remote.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp " + url proxy fetch push mirror skipDefaultUpdate + receivepack uploadpack tagopt pushurl + " "$pfx" "$cur_" + return + ;; + remote.*) + local pfx="${cur%.*}." cur_="${cur#*.}" + __gitcomp_nl "$(__git_remotes)" "$pfx" "$cur_" "." + __gitcomp_nl_append "pushdefault" "$pfx" "$cur_" + return + ;; + url.*.*) + local pfx="${cur%.*}." cur_="${cur##*.}" + __gitcomp "insteadOf pushInsteadOf" "$pfx" "$cur_" + return + ;; + esac + __gitcomp " + add.ignoreErrors + advice.commitBeforeMerge + advice.detachedHead + advice.implicitIdentity + advice.pushNonFastForward + advice.resolveConflict + advice.statusHints + alias. + am.keepcr + apply.ignorewhitespace + apply.whitespace + branch.autosetupmerge + branch.autosetuprebase + browser. + clean.requireForce + color.branch + color.branch.current + color.branch.local + color.branch.plain + color.branch.remote + color.decorate.HEAD + color.decorate.branch + color.decorate.remoteBranch + color.decorate.stash + color.decorate.tag + color.diff + color.diff.commit + color.diff.frag + color.diff.func + color.diff.meta + color.diff.new + color.diff.old + color.diff.plain + color.diff.whitespace + color.grep + color.grep.context + color.grep.filename + color.grep.function + color.grep.linenumber + color.grep.match + color.grep.selected + color.grep.separator + color.interactive + color.interactive.error + color.interactive.header + color.interactive.help + color.interactive.prompt + color.pager + color.showbranch + color.status + color.status.added + color.status.changed + color.status.header + color.status.nobranch + color.status.untracked + color.status.updated + color.ui + commit.status + commit.template + core.abbrev + core.askpass + core.attributesfile + core.autocrlf + core.bare + core.bigFileThreshold + core.compression + core.createObject + core.deltaBaseCacheLimit + core.editor + core.eol + core.excludesfile + core.fileMode + core.fsyncobjectfiles + core.gitProxy + core.ignoreStat + core.ignorecase + core.logAllRefUpdates + core.loosecompression + core.notesRef + core.packedGitLimit + core.packedGitWindowSize + core.pager + core.preferSymlinkRefs + core.preloadindex + core.quotepath + core.repositoryFormatVersion + core.safecrlf + core.sharedRepository + core.sparseCheckout + core.symlinks + core.trustctime + core.warnAmbiguousRefs + core.whitespace + core.worktree + diff.autorefreshindex + diff.external + diff.ignoreSubmodules + diff.mnemonicprefix + diff.noprefix + diff.renameLimit + diff.renames + diff.statGraphWidth + diff.submodule + diff.suppressBlankEmpty + diff.tool + diff.wordRegex + diff.algorithm + difftool. + difftool.prompt + fetch.recurseSubmodules + fetch.unpackLimit + format.attach + format.cc + format.coverLetter + format.headers + format.numbered + format.pretty + format.signature + format.signoff + format.subjectprefix + format.suffix + format.thread + format.to + gc. + gc.aggressiveWindow + gc.auto + gc.autopacklimit + gc.packrefs + gc.pruneexpire + gc.reflogexpire + gc.reflogexpireunreachable + gc.rerereresolved + gc.rerereunresolved + gitcvs.allbinary + gitcvs.commitmsgannotation + gitcvs.dbTableNamePrefix + gitcvs.dbdriver + gitcvs.dbname + gitcvs.dbpass + gitcvs.dbuser + gitcvs.enabled + gitcvs.logfile + gitcvs.usecrlfattr + guitool. + gui.blamehistoryctx + gui.commitmsgwidth + gui.copyblamethreshold + gui.diffcontext + gui.encoding + gui.fastcopyblame + gui.matchtrackingbranch + gui.newbranchtemplate + gui.pruneduringfetch + gui.spellingdictionary + gui.trustmtime + help.autocorrect + help.browser + help.format + http.lowSpeedLimit + http.lowSpeedTime + http.maxRequests + http.minSessions + http.noEPSV + http.postBuffer + http.proxy + http.sslCAInfo + http.sslCAPath + http.sslCert + http.sslCertPasswordProtected + http.sslKey + http.sslVerify + http.useragent + i18n.commitEncoding + i18n.logOutputEncoding + imap.authMethod + imap.folder + imap.host + imap.pass + imap.port + imap.preformattedHTML + imap.sslverify + imap.tunnel + imap.user + init.templatedir + instaweb.browser + instaweb.httpd + instaweb.local + instaweb.modulepath + instaweb.port + interactive.singlekey + log.date + log.decorate + log.showroot + mailmap.file + man. + man.viewer + merge. + merge.conflictstyle + merge.log + merge.renameLimit + merge.renormalize + merge.stat + merge.tool + merge.verbosity + mergetool. + mergetool.keepBackup + mergetool.keepTemporaries + mergetool.prompt + notes.displayRef + notes.rewrite. + notes.rewrite.amend + notes.rewrite.rebase + notes.rewriteMode + notes.rewriteRef + pack.compression + pack.deltaCacheLimit + pack.deltaCacheSize + pack.depth + pack.indexVersion + pack.packSizeLimit + pack.threads + pack.window + pack.windowMemory + pager. + pretty. + pull.octopus + pull.twohead + push.default + rebase.autosquash + rebase.stat + receive.autogc + receive.denyCurrentBranch + receive.denyDeleteCurrent + receive.denyDeletes + receive.denyNonFastForwards + receive.fsckObjects + receive.unpackLimit + receive.updateserverinfo + remote.pushdefault + remotes. + repack.usedeltabaseoffset + rerere.autoupdate + rerere.enabled + sendemail. + sendemail.aliasesfile + sendemail.aliasfiletype + sendemail.bcc + sendemail.cc + sendemail.cccmd + sendemail.chainreplyto + sendemail.confirm + sendemail.envelopesender + sendemail.from + sendemail.identity + sendemail.multiedit + sendemail.signedoffbycc + sendemail.smtpdomain + sendemail.smtpencryption + sendemail.smtppass + sendemail.smtpserver + sendemail.smtpserveroption + sendemail.smtpserverport + sendemail.smtpuser + sendemail.suppresscc + sendemail.suppressfrom + sendemail.thread + sendemail.to + sendemail.validate + showbranch.default + status.relativePaths + status.showUntrackedFiles + status.submodulesummary + submodule. + tar.umask + transfer.unpackLimit + url. + user.email + user.name + user.signingkey + web.browser + branch. remote. + " +} + +_git_remote () +{ + local subcommands="add rename remove set-head set-branches set-url show prune update" + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + return + fi + + case "$subcommand" in + rename|remove|set-url|show|prune) + __gitcomp_nl "$(__git_remotes)" + ;; + set-head|set-branches) + __git_complete_remote_or_refspec + ;; + update) + local i c='' IFS=$'\n' + for i in $(git --git-dir="$(__gitdir)" config --get-regexp "remotes\..*" 2>/dev/null); do + i="${i#remotes.}" + c="$c ${i/ */}" + done + __gitcomp "$c" + ;; + *) + ;; + esac +} + +_git_replace () +{ + __gitcomp_nl "$(__git_refs)" +} + +_git_reset () +{ + __git_has_doubledash && return + + case "$cur" in + --*) + __gitcomp "--merge --mixed --hard --soft --patch" + return + ;; + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_revert () +{ + case "$cur" in + --*) + __gitcomp "--edit --mainline --no-edit --no-commit --signoff" + return + ;; + esac + __gitcomp_nl "$(__git_refs)" +} + +_git_rm () +{ + case "$cur" in + --*) + __gitcomp "--cached --dry-run --ignore-unmatch --quiet" + return + ;; + esac + + __git_complete_index_file "--cached" +} + +_git_shortlog () +{ + __git_has_doubledash && return + + case "$cur" in + --*) + __gitcomp " + $__git_log_common_options + $__git_log_shortlog_options + --numbered --summary + " + return + ;; + esac + __git_complete_revlist +} + +_git_show () +{ + __git_has_doubledash && return + + case "$cur" in + --pretty=*|--format=*) + __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases) + " "" "${cur#*=}" + return + ;; + --diff-algorithm=*) + __gitcomp "$__git_diff_algorithms" "" "${cur##--diff-algorithm=}" + return + ;; + --*) + __gitcomp "--pretty= --format= --abbrev-commit --oneline + $__git_diff_common_options + " + return + ;; + esac + __git_complete_revlist_file +} + +_git_show_branch () +{ + case "$cur" in + --*) + __gitcomp " + --all --remotes --topo-order --current --more= + --list --independent --merge-base --no-name + --color --no-color + --sha1-name --sparse --topics --reflog + " + return + ;; + esac + __git_complete_revlist +} + +_git_stash () +{ + local save_opts='--keep-index --no-keep-index --quiet --patch' + local subcommands='save list show apply clear drop pop create branch' + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + case "$cur" in + --*) + __gitcomp "$save_opts" + ;; + *) + if [ -z "$(__git_find_on_cmdline "$save_opts")" ]; then + __gitcomp "$subcommands" + fi + ;; + esac + else + case "$subcommand,$cur" in + save,--*) + __gitcomp "$save_opts" + ;; + apply,--*|pop,--*) + __gitcomp "--index --quiet" + ;; + show,--*|drop,--*|branch,--*) + ;; + show,*|apply,*|drop,*|pop,*|branch,*) + __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \ + | sed -n -e 's/:.*//p')" + ;; + *) + ;; + esac + fi +} + +_git_submodule () +{ + __git_has_doubledash && return + + local subcommands="add status init deinit update summary foreach sync" + if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then + case "$cur" in + --*) + __gitcomp "--quiet --cached" + ;; + *) + __gitcomp "$subcommands" + ;; + esac + return + fi +} + +_git_svn () +{ + local subcommands=" + init fetch clone rebase dcommit log find-rev + set-tree commit-diff info create-ignore propget + proplist show-ignore show-externals branch tag blame + migrate mkdirs reset gc + " + local subcommand="$(__git_find_on_cmdline "$subcommands")" + if [ -z "$subcommand" ]; then + __gitcomp "$subcommands" + else + local remote_opts="--username= --config-dir= --no-auth-cache" + local fc_opts=" + --follow-parent --authors-file= --repack= + --no-metadata --use-svm-props --use-svnsync-props + --log-window-size= --no-checkout --quiet + --repack-flags --use-log-author --localtime + --ignore-paths= --include-paths= $remote_opts + " + local init_opts=" + --template= --shared= --trunk= --tags= + --branches= --stdlayout --minimize-url + --no-metadata --use-svm-props --use-svnsync-props + --rewrite-root= --prefix= --use-log-author + --add-author-from $remote_opts + " + local cmt_opts=" + --edit --rmdir --find-copies-harder --copy-similarity= + " + + case "$subcommand,$cur" in + fetch,--*) + __gitcomp "--revision= --fetch-all $fc_opts" + ;; + clone,--*) + __gitcomp "--revision= $fc_opts $init_opts" + ;; + init,--*) + __gitcomp "$init_opts" + ;; + dcommit,--*) + __gitcomp " + --merge --strategy= --verbose --dry-run + --fetch-all --no-rebase --commit-url + --revision --interactive $cmt_opts $fc_opts + " + ;; + set-tree,--*) + __gitcomp "--stdin $cmt_opts $fc_opts" + ;; + create-ignore,--*|propget,--*|proplist,--*|show-ignore,--*|\ + show-externals,--*|mkdirs,--*) + __gitcomp "--revision=" + ;; + log,--*) + __gitcomp " + --limit= --revision= --verbose --incremental + --oneline --show-commit --non-recursive + --authors-file= --color + " + ;; + rebase,--*) + __gitcomp " + --merge --verbose --strategy= --local + --fetch-all --dry-run $fc_opts + " + ;; + commit-diff,--*) + __gitcomp "--message= --file= --revision= $cmt_opts" + ;; + info,--*) + __gitcomp "--url" + ;; + branch,--*) + __gitcomp "--dry-run --message --tag" + ;; + tag,--*) + __gitcomp "--dry-run --message" + ;; + blame,--*) + __gitcomp "--git-format" + ;; + migrate,--*) + __gitcomp " + --config-dir= --ignore-paths= --minimize + --no-auth-cache --username= + " + ;; + reset,--*) + __gitcomp "--revision= --parent" + ;; + *) + ;; + esac + fi +} + +_git_tag () +{ + local i c=1 f=0 + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + -d|-v) + __gitcomp_nl "$(__git_tags)" + return + ;; + -f) + f=1 + ;; + esac + ((c++)) + done + + case "$prev" in + -m|-F) + ;; + -*|tag) + if [ $f = 1 ]; then + __gitcomp_nl "$(__git_tags)" + fi + ;; + *) + __gitcomp_nl "$(__git_refs)" + ;; + esac +} + +_git_whatchanged () +{ + _git_log +} + +__git_main () +{ + local i c=1 command __git_dir + + while [ $c -lt $cword ]; do + i="${words[c]}" + case "$i" in + --git-dir=*) __git_dir="${i#--git-dir=}" ;; + --git-dir) ((c++)) ; __git_dir="${words[c]}" ;; + --bare) __git_dir="." ;; + --help) command="help"; break ;; + -c|--work-tree|--namespace) ((c++)) ;; + -*) ;; + *) command="$i"; break ;; + esac + ((c++)) + done + + if [ -z "$command" ]; then + case "$cur" in + --*) __gitcomp " + --paginate + --no-pager + --git-dir= + --bare + --version + --exec-path + --exec-path= + --html-path + --man-path + --info-path + --work-tree= + --namespace= + --no-replace-objects + --help + " + ;; + *) __git_compute_porcelain_commands + __gitcomp "$__git_porcelain_commands $(__git_aliases)" ;; + esac + return + fi + + local completion_func="_git_${command//-/_}" + declare -f $completion_func >/dev/null && $completion_func && return + + local expansion=$(__git_aliased_command "$command") + if [ -n "$expansion" ]; then + words[1]=$expansion + completion_func="_git_${expansion//-/_}" + declare -f $completion_func >/dev/null && $completion_func + fi +} + +__gitk_main () +{ + __git_has_doubledash && return + + local g="$(__gitdir)" + local merge="" + if [ -f "$g/MERGE_HEAD" ]; then + merge="--merge" + fi + case "$cur" in + --*) + __gitcomp " + $__git_log_common_options + $__git_log_gitk_options + $merge + " + return + ;; + esac + __git_complete_revlist +} + +if [[ -n ${ZSH_VERSION-} ]]; then + echo "WARNING: this script is deprecated, please see git-completion.zsh" 1>&2 + + autoload -U +X compinit && compinit + + __gitcomp () + { + emulate -L zsh + + local cur_="${3-$cur}" + + case "$cur_" in + --*=) + ;; + *) + local c IFS=$' \t\n' + local -a array + for c in ${=1}; do + c="$c${4-}" + case $c in + --*=*|*.) ;; + *) c="$c " ;; + esac + array[${#array[@]}+1]="$c" + done + compset -P '*[=:]' + compadd -Q -S '' -p "${2-}" -a -- array && _ret=0 + ;; + esac + } + + __gitcomp_nl () + { + emulate -L zsh + + local IFS=$'\n' + compset -P '*[=:]' + compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0 + } + + __gitcomp_file () + { + emulate -L zsh + + local IFS=$'\n' + compset -P '*[=:]' + compadd -Q -p "${2-}" -f -- ${=1} && _ret=0 + } + + _git () + { + local _ret=1 cur cword prev + cur=${words[CURRENT]} + prev=${words[CURRENT-1]} + let cword=CURRENT-1 + emulate ksh -c __${service}_main + let _ret && _default && _ret=0 + return _ret + } + + compdef _git git gitk + return +fi + +__git_func_wrap () +{ + local cur words cword prev + _get_comp_words_by_ref -n =: cur words cword prev + $1 +} + +# Setup completion for certain functions defined above by setting common +# variables and workarounds. +# This is NOT a public function; use at your own risk. +__git_complete () +{ + local wrapper="__git_wrap${2}" + eval "$wrapper () { __git_func_wrap $2 ; }" + complete -o bashdefault -o default -o nospace -F $wrapper $1 2>/dev/null \ + || complete -o default -o nospace -F $wrapper $1 +} + +# wrapper for backwards compatibility +_git () +{ + __git_wrap__git_main +} + +# wrapper for backwards compatibility +_gitk () +{ + __git_wrap__gitk_main +} + +__git_complete git __git_main +__git_complete gitk __gitk_main + +# The following are necessary only for Cygwin, and only are needed +# when the user has tab-completed the executable name and consequently +# included the '.exe' suffix. +# +if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then +__git_complete git.exe __git_main +fi diff --git a/puphpet/files/dot/.git-prompt.sh b/puphpet/files/dot/.git-prompt.sh new file mode 100644 index 0000000..eaf5c36 --- /dev/null +++ b/puphpet/files/dot/.git-prompt.sh @@ -0,0 +1,412 @@ +# bash/zsh git prompt support +# +# Copyright (C) 2006,2007 Shawn O. Pearce +# Distributed under the GNU General Public License, version 2.0. +# +# This script allows you to see the current branch in your prompt. +# +# To enable: +# +# 1) Copy this file to somewhere (e.g. ~/.git-prompt.sh). +# 2) Add the following line to your .bashrc/.zshrc: +# source ~/.git-prompt.sh +# 3a) Change your PS1 to call __git_ps1 as +# command-substitution: +# Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' +# ZSH: PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ ' +# the optional argument will be used as format string. +# 3b) Alternatively, if you are using bash, __git_ps1 can be +# used for PROMPT_COMMAND with two parameters,
 and
+#        , which are strings you would put in $PS1 before
+#        and after the status string generated by the git-prompt
+#        machinery.  e.g.
+#           PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
+#        will show username, at-sign, host, colon, cwd, then
+#        various status string, followed by dollar and SP, as
+#        your prompt.
+#        Optionally, you can supply a third argument with a printf
+#        format string to finetune the output of the branch status
+#
+# The argument to __git_ps1 will be displayed only if you are currently
+# in a git repository.  The %s token will be the name of the current
+# branch.
+#
+# In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty value,
+# unstaged (*) and staged (+) changes will be shown next to the branch
+# name.  You can configure this per-repository with the
+# bash.showDirtyState variable, which defaults to true once
+# GIT_PS1_SHOWDIRTYSTATE is enabled.
+#
+# You can also see if currently something is stashed, by setting
+# GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
+# then a '$' will be shown next to the branch name.
+#
+# If you would like to see if there're untracked files, then you can set
+# GIT_PS1_SHOWUNTRACKEDFILES to a nonempty value. If there're untracked
+# files, then a '%' will be shown next to the branch name.  You can
+# configure this per-repository with the bash.showUntrackedFiles
+# variable, which defaults to true once GIT_PS1_SHOWUNTRACKEDFILES is
+# enabled.
+#
+# If you would like to see the difference between HEAD and its upstream,
+# set GIT_PS1_SHOWUPSTREAM="auto".  A "<" indicates you are behind, ">"
+# indicates you are ahead, "<>" indicates you have diverged and "="
+# indicates that there is no difference. You can further control
+# behaviour by setting GIT_PS1_SHOWUPSTREAM to a space-separated list
+# of values:
+#
+#     verbose       show number of commits ahead/behind (+/-) upstream
+#     legacy        don't use the '--count' option available in recent
+#                   versions of git-rev-list
+#     git           always compare HEAD to @{upstream}
+#     svn           always compare HEAD to your SVN upstream
+#
+# By default, __git_ps1 will compare HEAD to your SVN upstream if it can
+# find one, or @{upstream} otherwise.  Once you have set
+# GIT_PS1_SHOWUPSTREAM, you can override it on a per-repository basis by
+# setting the bash.showUpstream config variable.
+#
+# If you would like to see more information about the identity of
+# commits checked out as a detached HEAD, set GIT_PS1_DESCRIBE_STYLE
+# to one of these values:
+#
+#     contains      relative to newer annotated tag (v1.6.3.2~35)
+#     branch        relative to newer tag or branch (master~4)
+#     describe      relative to older annotated tag (v1.6.3.1-13-gdd42c2f)
+#     default       exactly matching tag
+#
+# If you would like a colored hint about the current dirty state, set
+# GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
+# the colored output of "git status -sb".
+
+# __gitdir accepts 0 or 1 arguments (i.e., location)
+# returns location of .git repo
+__gitdir ()
+{
+	# Note: this function is duplicated in git-completion.bash
+	# When updating it, make sure you update the other one to match.
+	if [ -z "${1-}" ]; then
+		if [ -n "${__git_dir-}" ]; then
+			echo "$__git_dir"
+		elif [ -n "${GIT_DIR-}" ]; then
+			test -d "${GIT_DIR-}" || return 1
+			echo "$GIT_DIR"
+		elif [ -d .git ]; then
+			echo .git
+		else
+			git rev-parse --git-dir 2>/dev/null
+		fi
+	elif [ -d "$1/.git" ]; then
+		echo "$1/.git"
+	else
+		echo "$1"
+	fi
+}
+
+# stores the divergence from upstream in $p
+# used by GIT_PS1_SHOWUPSTREAM
+__git_ps1_show_upstream ()
+{
+	local key value
+	local svn_remote svn_url_pattern count n
+	local upstream=git legacy="" verbose=""
+
+	svn_remote=()
+	# get some config options from git-config
+	local output="$(git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showupstream)$' 2>/dev/null | tr '\0\n' '\n ')"
+	while read -r key value; do
+		case "$key" in
+		bash.showupstream)
+			GIT_PS1_SHOWUPSTREAM="$value"
+			if [[ -z "${GIT_PS1_SHOWUPSTREAM}" ]]; then
+				p=""
+				return
+			fi
+			;;
+		svn-remote.*.url)
+			svn_remote[ $((${#svn_remote[@]} + 1)) ]="$value"
+			svn_url_pattern+="\\|$value"
+			upstream=svn+git # default upstream is SVN if available, else git
+			;;
+		esac
+	done <<< "$output"
+
+	# parse configuration values
+	for option in ${GIT_PS1_SHOWUPSTREAM}; do
+		case "$option" in
+		git|svn) upstream="$option" ;;
+		verbose) verbose=1 ;;
+		legacy)  legacy=1  ;;
+		esac
+	done
+
+	# Find our upstream
+	case "$upstream" in
+	git)    upstream="@{upstream}" ;;
+	svn*)
+		# get the upstream from the "git-svn-id: ..." in a commit message
+		# (git-svn uses essentially the same procedure internally)
+		local svn_upstream=($(git log --first-parent -1 \
+					--grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null))
+		if [[ 0 -ne ${#svn_upstream[@]} ]]; then
+			svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]}
+			svn_upstream=${svn_upstream%@*}
+			local n_stop="${#svn_remote[@]}"
+			for ((n=1; n <= n_stop; n++)); do
+				svn_upstream=${svn_upstream#${svn_remote[$n]}}
+			done
+
+			if [[ -z "$svn_upstream" ]]; then
+				# default branch name for checkouts with no layout:
+				upstream=${GIT_SVN_ID:-git-svn}
+			else
+				upstream=${svn_upstream#/}
+			fi
+		elif [[ "svn+git" = "$upstream" ]]; then
+			upstream="@{upstream}"
+		fi
+		;;
+	esac
+
+	# Find how many commits we are ahead/behind our upstream
+	if [[ -z "$legacy" ]]; then
+		count="$(git rev-list --count --left-right \
+				"$upstream"...HEAD 2>/dev/null)"
+	else
+		# produce equivalent output to --count for older versions of git
+		local commits
+		if commits="$(git rev-list --left-right "$upstream"...HEAD 2>/dev/null)"
+		then
+			local commit behind=0 ahead=0
+			for commit in $commits
+			do
+				case "$commit" in
+				"<"*) ((behind++)) ;;
+				*)    ((ahead++))  ;;
+				esac
+			done
+			count="$behind	$ahead"
+		else
+			count=""
+		fi
+	fi
+
+	# calculate the result
+	if [[ -z "$verbose" ]]; then
+		case "$count" in
+		"") # no upstream
+			p="" ;;
+		"0	0") # equal to upstream
+			p="=" ;;
+		"0	"*) # ahead of upstream
+			p=">" ;;
+		*"	0") # behind upstream
+			p="<" ;;
+		*)	    # diverged from upstream
+			p="<>" ;;
+		esac
+	else
+		case "$count" in
+		"") # no upstream
+			p="" ;;
+		"0	0") # equal to upstream
+			p=" u=" ;;
+		"0	"*) # ahead of upstream
+			p=" u+${count#0	}" ;;
+		*"	0") # behind upstream
+			p=" u-${count%	0}" ;;
+		*)	    # diverged from upstream
+			p=" u+${count#*	}-${count%	*}" ;;
+		esac
+	fi
+
+}
+
+
+# __git_ps1 accepts 0 or 1 arguments (i.e., format string)
+# when called from PS1 using command substitution
+# in this mode it prints text to add to bash PS1 prompt (includes branch name)
+#
+# __git_ps1 requires 2 or 3 arguments when called from PROMPT_COMMAND (pc)
+# in that case it _sets_ PS1. The arguments are parts of a PS1 string.
+# when two arguments are given, the first is prepended and the second appended
+# to the state string when assigned to PS1.
+# The optional third parameter will be used as printf format string to further
+# customize the output of the git-status string.
+# In this mode you can request colored hints using GIT_PS1_SHOWCOLORHINTS=true
+__git_ps1 ()
+{
+	local pcmode=no
+	local detached=no
+	local ps1pc_start='\u@\h:\w '
+	local ps1pc_end='\$ '
+	local printf_format=' (%s)'
+
+	case "$#" in
+		2|3)	pcmode=yes
+			ps1pc_start="$1"
+			ps1pc_end="$2"
+			printf_format="${3:-$printf_format}"
+		;;
+		0|1)	printf_format="${1:-$printf_format}"
+		;;
+		*)	return
+		;;
+	esac
+
+	local g="$(__gitdir)"
+	if [ -z "$g" ]; then
+		if [ $pcmode = yes ]; then
+			#In PC mode PS1 always needs to be set
+			PS1="$ps1pc_start$ps1pc_end"
+		fi
+	else
+		local r=""
+		local b=""
+		local step=""
+		local total=""
+		if [ -d "$g/rebase-merge" ]; then
+			b="$(cat "$g/rebase-merge/head-name")"
+			step=$(cat "$g/rebase-merge/msgnum")
+			total=$(cat "$g/rebase-merge/end")
+			if [ -f "$g/rebase-merge/interactive" ]; then
+				r="|REBASE-i"
+			else
+				r="|REBASE-m"
+			fi
+		else
+			if [ -d "$g/rebase-apply" ]; then
+				step=$(cat "$g/rebase-apply/next")
+				total=$(cat "$g/rebase-apply/last")
+				if [ -f "$g/rebase-apply/rebasing" ]; then
+					r="|REBASE"
+				elif [ -f "$g/rebase-apply/applying" ]; then
+					r="|AM"
+				else
+					r="|AM/REBASE"
+				fi
+			elif [ -f "$g/MERGE_HEAD" ]; then
+				r="|MERGING"
+			elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
+				r="|CHERRY-PICKING"
+			elif [ -f "$g/REVERT_HEAD" ]; then
+				r="|REVERTING"
+			elif [ -f "$g/BISECT_LOG" ]; then
+				r="|BISECTING"
+			fi
+
+			b="$(git symbolic-ref HEAD 2>/dev/null)" || {
+				detached=yes
+				b="$(
+				case "${GIT_PS1_DESCRIBE_STYLE-}" in
+				(contains)
+					git describe --contains HEAD ;;
+				(branch)
+					git describe --contains --all HEAD ;;
+				(describe)
+					git describe HEAD ;;
+				(* | default)
+					git describe --tags --exact-match HEAD ;;
+				esac 2>/dev/null)" ||
+
+				b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." ||
+				b="unknown"
+				b="($b)"
+			}
+		fi
+
+		if [ -n "$step" ] && [ -n "$total" ]; then
+			r="$r $step/$total"
+		fi
+
+		local w=""
+		local i=""
+		local s=""
+		local u=""
+		local c=""
+		local p=""
+
+		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
+			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
+				c="BARE:"
+			else
+				b="GIT_DIR!"
+			fi
+		elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
+			if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
+			   [ "$(git config --bool bash.showDirtyState)" != "false" ]
+			then
+				git diff --no-ext-diff --quiet --exit-code || w="*"
+				if git rev-parse --quiet --verify HEAD >/dev/null; then
+					git diff-index --cached --quiet HEAD -- || i="+"
+				else
+					i="#"
+				fi
+			fi
+			if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
+				git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
+			fi
+
+			if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
+			   [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
+			   [ -n "$(git ls-files --others --exclude-standard)" ]
+			then
+				u="%${ZSH_VERSION+%}"
+			fi
+
+			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+				__git_ps1_show_upstream
+			fi
+		fi
+
+		local f="$w$i$s$u"
+		if [ $pcmode = yes ]; then
+			local gitstring=
+			if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
+				local c_red='\e[31m'
+				local c_green='\e[32m'
+				local c_lblue='\e[1;34m'
+				local c_clear='\e[0m'
+				local bad_color=$c_red
+				local ok_color=$c_green
+				local branch_color="$c_clear"
+				local flags_color="$c_lblue"
+				local branchstring="$c${b##refs/heads/}"
+
+				if [ $detached = no ]; then
+					branch_color="$ok_color"
+				else
+					branch_color="$bad_color"
+				fi
+
+				# Setting gitstring directly with \[ and \] around colors
+				# is necessary to prevent wrapping issues!
+				gitstring="\[$branch_color\]$branchstring\[$c_clear\]"
+
+				if [ -n "$w$i$s$u$r$p" ]; then
+					gitstring="$gitstring "
+				fi
+				if [ "$w" = "*" ]; then
+					gitstring="$gitstring\[$bad_color\]$w"
+				fi
+				if [ -n "$i" ]; then
+					gitstring="$gitstring\[$ok_color\]$i"
+				fi
+				if [ -n "$s" ]; then
+					gitstring="$gitstring\[$flags_color\]$s"
+				fi
+				if [ -n "$u" ]; then
+					gitstring="$gitstring\[$bad_color\]$u"
+				fi
+				gitstring="$gitstring\[$c_clear\]$r$p"
+			else
+				gitstring="$c${b##refs/heads/}${f:+ $f}$r$p"
+			fi
+			gitstring=$(printf -- "$printf_format" "$gitstring")
+			PS1="$ps1pc_start$gitstring$ps1pc_end"
+		else
+			# NO color option unless in PROMPT_COMMAND mode
+			printf -- "$printf_format" "$c${b##refs/heads/}${f:+ $f}$r$p"
+		fi
+	fi
+}
diff --git a/puphpet/files/exec-preprovision/empty b/puphpet/files/exec-preprovision/empty
new file mode 100644
index 0000000..e69de29
diff --git a/puphpet/puppet/Puppetfile b/puphpet/puppet/Puppetfile
index 5ec528d..b15df2c 100644
--- a/puphpet/puppet/Puppetfile
+++ b/puphpet/puppet/Puppetfile
@@ -1,32 +1,41 @@
 forge "https://forgeapi.puppetlabs.com"
 
+mod 'puphpet/puphpet',
+    :git => 'https://github.com/puphpet/puppet-puphpet.git',
+    :ref => 'f1ba7141a4540ce3aff48d0a9da84da4d26bad30'
+mod 'puppetlabs/stdlib',
+    :git => 'https://github.com/puppetlabs/puppetlabs-stdlib.git',
+    :ref => '4.11.0'
 mod 'puppetlabs/apache',
     :git => 'https://github.com/puppetlabs/puppetlabs-apache.git',
-    :ref => '7dde9fc31e'
+    :ref => '1.7.1'
 mod 'puppetlabs/apt',
     :git => 'https://github.com/puppetlabs/puppetlabs-apt.git',
-    :ref => '1.8.0'
+    :ref => '2.2.1'
 mod 'keen99/beanstalkd',
     :git => 'https://github.com/keen99/puppet-beanstalkd.git',
-    :ref => '1.0.0'
+    :ref => '1.0.1'
 mod 's12v/blackfire',
-    :git => 'https://github.com/puphpet/puppet-blackfire.git',
-    :ref => 'cb938a5'
+    :git => 'https://github.com/s12v/puppet-blackfire.git',
+    :ref => '1.4.0'
 mod 'tPl0ch/composer',
     :git => 'https://github.com/puphpet/puppet-composer.git',
-    :ref => 'c4f9478'
+    :ref => '2cad1a23ca4fd3e03171a60a09c711e6e5097894'
 mod 'puppetlabs/concat',
     :git => 'https://github.com/puppetlabs/puppetlabs-concat.git',
     :ref => '1.1.1'
 mod 'elasticsearch/elasticsearch',
-    :git => 'https://github.com/puphpet/puppet-elasticsearch.git',
-    :ref => '0.2.2'
+    :git => 'https://github.com/elastic/puppet-elasticsearch.git',
+    :ref => '0.10.1'
 mod 'garethr/erlang',
     :git => 'https://github.com/garethr/garethr-erlang.git',
-    :ref => '91d8ec73c3'
+    :ref => 'a8f29a48e8127e75d3ab747bca1c4ed4746369f7'
 mod 'puppetlabs/firewall',
     :git => 'https://github.com/puppetlabs/puppetlabs-firewall.git',
     :ref => '1.1.1'
+mod 'golja-gnupg',
+    :git => 'https://github.com/n1tr0g/golja-gnupg.git',
+    :ref => '1.2.1'
 mod 'puppetlabs/inifile',
     :git => 'https://github.com/puppetlabs/puppetlabs-inifile.git',
     :ref => '1.2.0'
@@ -36,58 +45,54 @@ mod 'puppetlabs/java',
 mod 'attachmentgenie/locales',
     :git => 'https://github.com/saz/puppet-locales.git',
     :ref => 'v2.2.2'
-mod 'actionjack/mailcatcher',
-    :git => 'https://github.com/puphpet/puppet-mailcatcher.git',
-    :ref => 'dcc8c3d357'
 mod 'puppetlabs/mongodb',
     :git => 'https://github.com/puppetlabs/puppetlabs-mongodb.git',
-    :ref => '0.8.0'
+    :ref => '38ceb81e36bbbb844039e12fb8aebb43cb2cef0d'
 mod 'puppetlabs/mysql',
     :git => 'https://github.com/puppetlabs/puppetlabs-mysql.git',
     :ref => '3.3.0'
 mod 'jfryman/nginx',
     :git => 'https://github.com/puphpet/puppet-nginx.git',
-    :ref => 'd3ea0ee'
+    :ref => '3ab5c5ab549b56f641ae4d842415de8b99e3a522'
 mod 'puppetlabs/ntp',
     :git => 'https://github.com/puppetlabs/puppetlabs-ntp.git',
-    :ref => '3.0.4'
+    :ref => '4.1.1'
 mod 'puphpet/php',
     :git => 'https://github.com/puphpet/puppet-php.git',
-    :ref => 'eb14528'
+    :ref => 'c5aa4bf4ca3d2e8f2227959dd1d12981aeec840d'
 mod 'puppetlabs/postgresql',
     :git => 'https://github.com/puppetlabs/puppetlabs-postgresql.git',
-    :ref => '4.2.0'
-mod 'puphpet/puphpet',
-    :git => 'https://github.com/puphpet/puppet-puphpet.git',
-    :ref => '7c257c7'
+    :ref => '4.6.0'
 mod 'example42/puppi',
     :git => 'https://github.com/example42/puppi.git',
-    :ref => 'v2.1.9'
+    :ref => 'fe711883625bf4848d5f62b4fd64af7dddf6c424'
 mod 'daenney/pyenv',
     :git => 'https://github.com/puphpet/puppet-pyenv.git',
-    :ref => '062ae72'
+    :ref => '062ae728ae0ddcb76d6d60c3c268fc13b022106e'
 mod 'puppetlabs/rabbitmq',
     :git => 'https://github.com/puppetlabs/puppetlabs-rabbitmq.git',
-    :ref => '5.2.0'
-mod 'puphpet/redis',
-    :git => 'https://github.com/puphpet/puppet-redis.git',
-    :ref => 'd9b3b23b0c'
+    :ref => '5.3.1'
+mod 'arioch/redis',
+    :git => 'https://github.com/arioch/puppet-redis.git',
+    :ref => '1.2.1'
 mod 'maestrodev/rvm'
 mod 'example42/solr',
     :git => 'https://github.com/example42/puppet-solr.git',
-    :ref => 'v2.0.7'
+    :ref => '74b7c4d3bf8e6566aaf1cc4d28d97546f02179f8'
 mod 'petems/swap_file',
     :git => 'https://github.com/petems/puppet-swap_file.git',
-    :ref => '39582afda5'
+    :ref => '39582afda5fc98982977cf595883d90d63886d80'
 mod 'ajcrowe/supervisord',
     :git => 'https://github.com/puphpet/puppet-supervisord.git',
-    :ref => '17643f1'
-mod 'puppetlabs/stdlib',
-    :git => 'https://github.com/puppetlabs/puppetlabs-stdlib.git',
-    :ref => '4dab70b305'
+    :ref => '17643f10c2322bfab349108e02b7f5a9992dbdde'
+mod 'saz/timezone',
+    :git => 'https://github.com/saz/puppet-timezone.git',
+    :ref => 'v3.3.0'
 mod 'puppetlabs/vcsrepo',
     :git => 'https://github.com/puppetlabs/puppetlabs-vcsrepo.git',
     :ref => '0.2.0'
 mod 'example42/yum',
-    :git => 'https://github.com/example42/puppet-yum.git',
-    :ref => 'v2.1.17'
+    :git => 'https://github.com/puphpet/puppet-yum.git',
+    :ref => '8233e01382f9989e9a7b15fc529e34069f99fb37'
+exclusion 'ceritsc-yum'
+exclusion 'n1tr0g/gnupg'
diff --git a/puphpet/puppet/Puppetfile.lock b/puphpet/puppet/Puppetfile.lock
index 251fbdb..68258cb 100644
--- a/puphpet/puppet/Puppetfile.lock
+++ b/puphpet/puppet/Puppetfile.lock
@@ -3,111 +3,98 @@ FORGE
   specs:
     example42-monitor (2.0.3)
       example42-puppi (>= 2.0.0)
-    maestrodev-rvm (1.11.0)
+    maestrodev-rvm (1.12.1)
+      golja-gnupg (>= 1.2.0)
       puppetlabs-stdlib (>= 4.2.0)
     nanliu-staging (1.0.3)
-    puppetlabs-git (0.3.0)
-      puppetlabs-vcsrepo (>= 0.1.0)
-    stahnma-epel (1.0.2)
-    thias-sysctl (0.3.0)
+    puppetlabs-git (0.4.0)
+      puppetlabs-stdlib (>= 3.2.0)
+    richardc-datacat (0.6.2)
+    stahnma-epel (1.2.2)
+      puppetlabs-stdlib (>= 3.0.0)
 
 GIT
-  remote: https://github.com/attachmentgenie/attachmentgenie-locales.git
-  ref: 1.1.1
-  sha: a6d0ef7a58d0c3b58875b796c5f0b7301fece143
+  remote: https://github.com/arioch/puppet-redis.git
+  ref: 1.2.1
+  sha: 7aff3d9df5133adce16f2f512725f4c1f6154e7a
   specs:
-    attachmentgenie-locales (1.1.1)
-      puppetlabs-stdlib (< 5.0.0, >= 2.2.1)
+    arioch-redis (1.2.1)
+      puppetlabs-apt (< 3.0.0, >= 2.0.1)
+      puppetlabs-stdlib (< 5.0.0, >= 1.0.2)
+      stahnma-epel (< 2.0.0, >= 1.0.2)
+
+GIT
+  remote: https://github.com/elastic/puppet-elasticsearch.git
+  ref: 0.10.1
+  sha: 785afdc9783a2d4e79584514b1b6fb6c223a32ba
+  specs:
+    elasticsearch-elasticsearch (0.10.1)
+      puppetlabs-apt (< 3.0.0, >= 1.4.0)
+      puppetlabs-stdlib (< 5.0.0, >= 3.2.0)
+      richardc-datacat (< 1.0.0, >= 0.6.2)
 
 GIT
   remote: https://github.com/example42/puppet-solr.git
-  ref: v2.0.7
-  sha: dd1a31391d6565c39c360124201e4ff8beeee62a
+  ref: 74b7c4d3bf8e6566aaf1cc4d28d97546f02179f8
+  sha: 74b7c4d3bf8e6566aaf1cc4d28d97546f02179f8
   specs:
-    example42-solr (2.0.6)
+    example42-solr (2.0.7)
       example42-monitor (>= 2.0.0)
       example42-puppi (>= 2.0.0)
       puppetlabs-stdlib (>= 2.0.0)
 
-GIT
-  remote: https://github.com/example42/puppet-yum.git
-  ref: v2.1.17
-  sha: bc5af38cf09105733e5e57794cc82244c02e3114
-  specs:
-    example42-yum (2.1.16)
-      example42-puppi (> 2.0.0)
-
 GIT
   remote: https://github.com/example42/puppi.git
-  ref: v2.1.9
-  sha: 620883d691931a54c1f2bf75b0679ea56fd7820c
+  ref: fe711883625bf4848d5f62b4fd64af7dddf6c424
+  sha: fe711883625bf4848d5f62b4fd64af7dddf6c424
   specs:
-    example42-puppi (2.1.8)
+    example42-puppi (2.1.12)
 
 GIT
   remote: https://github.com/garethr/garethr-erlang.git
-  ref: 91d8ec73c3
-  sha: 91d8ec73c321f818da1fcfda8364a39aed444ac5
+  ref: a8f29a48e8127e75d3ab747bca1c4ed4746369f7
+  sha: a8f29a48e8127e75d3ab747bca1c4ed4746369f7
   specs:
     garethr-erlang (0.3.0)
-      puppetlabs-apt (>= 0)
-      puppetlabs-stdlib (>= 0)
-      stahnma-epel (>= 0)
+      puppetlabs-apt (>= 2.1.0)
+      puppetlabs-stdlib (< 5.0.0, >= 2.0.0)
+      stahnma-epel (< 2.0.0, >= 1.0.0)
 
 GIT
   remote: https://github.com/keen99/puppet-beanstalkd.git
-  ref: 1.0.0
-  sha: 4f4dce03856fc175338e2942c216547c8542fb25
+  ref: 1.0.1
+  sha: 3299b600c0ff2292a784ab6403f6d1b182a09fde
   specs:
     keen99-beanstalkd (0.0.1)
 
+GIT
+  remote: https://github.com/n1tr0g/golja-gnupg.git
+  ref: 1.2.1
+  sha: 6b9b760082b465e170ef18d3fbf2582183b2e67d
+  specs:
+    golja-gnupg (1.2.1)
+
 GIT
   remote: https://github.com/petems/puppet-swap_file.git
-  ref: 39582afda5
+  ref: 39582afda5fc98982977cf595883d90d63886d80
   sha: 39582afda5fc98982977cf595883d90d63886d80
   specs:
     petems-swap_file (0.1.3)
       puppetlabs-stdlib (>= 3.2.0)
 
-GIT
-  remote: https://github.com/puphpet/puppet-blackfire.git
-  ref: cb938a5
-  sha: cb938a59e400590ee077dfb511b5bf8f96602589
-  specs:
-    s12v-blackfire (1.2.2)
-      puppetlabs-apt (>= 1.0.0)
-      puppetlabs-inifile (>= 1.0.0)
-      puppetlabs-stdlib (>= 4.0.0)
-
 GIT
   remote: https://github.com/puphpet/puppet-composer.git
-  ref: c4f9478
-  sha: c4f9478869296df9344c8d3940ee16666dab6b18
+  ref: 2cad1a23ca4fd3e03171a60a09c711e6e5097894
+  sha: 2cad1a23ca4fd3e03171a60a09c711e6e5097894
   specs:
     tPl0ch-composer (1.3.6)
       puppetlabs-git (>= 0.0.2)
       puppetlabs-stdlib (>= 3.0.0)
 
-GIT
-  remote: https://github.com/puphpet/puppet-elasticsearch.git
-  ref: 0.2.2
-  sha: b8a47db04e2edb4916448f09032042e8b53ec6e4
-  specs:
-    elasticsearch-elasticsearch (0.2.2)
-      puppetlabs-stdlib (>= 3.0.0)
-
-GIT
-  remote: https://github.com/puphpet/puppet-mailcatcher.git
-  ref: dcc8c3d357
-  sha: dcc8c3d357353e07b4a4ef5fb984ff9019992d38
-  specs:
-    actionjack-mailcatcher (0.1.5)
-      puppetlabs-stdlib (>= 2.2.1)
-
 GIT
   remote: https://github.com/puphpet/puppet-nginx.git
-  ref: d3ea0ee
-  sha: d3ea0ee3189d440347741b41e1c135a99b0847f8
+  ref: 3ab5c5ab549b56f641ae4d842415de8b99e3a522
+  sha: 3ab5c5ab549b56f641ae4d842415de8b99e3a522
   specs:
     jfryman-nginx (0.0.10)
       puppetlabs-apt (>= 1.0.0)
@@ -116,60 +103,60 @@ GIT
 
 GIT
   remote: https://github.com/puphpet/puppet-php.git
-  ref: eb14528
-  sha: eb14528a5c8178b919c7b6a13dd6043bd5c8e217
+  ref: c5aa4bf4ca3d2e8f2227959dd1d12981aeec840d
+  sha: c5aa4bf4ca3d2e8f2227959dd1d12981aeec840d
   specs:
-    puphpet-php (2.0.17)
+    puphpet-php (2.0.25)
       example42-puppi (>= 2.0.0)
 
 GIT
   remote: https://github.com/puphpet/puppet-puphpet.git
-  ref: 7c257c7
-  sha: 7c257c735dca3b3eff9aa47eefbec481c50b215d
+  ref: f1ba7141a4540ce3aff48d0a9da84da4d26bad30
+  sha: f1ba7141a4540ce3aff48d0a9da84da4d26bad30
   specs:
     puphpet-puphpet (1.0)
 
 GIT
   remote: https://github.com/puphpet/puppet-pyenv.git
-  ref: 062ae72
+  ref: 062ae728ae0ddcb76d6d60c3c268fc13b022106e
   sha: 062ae728ae0ddcb76d6d60c3c268fc13b022106e
   specs:
     daenney-pyenv (3.0.3)
       puppetlabs-stdlib (>= 0.1.6)
 
-GIT
-  remote: https://github.com/puphpet/puppet-redis.git
-  ref: d9b3b23b0c
-  sha: d9b3b23b0c74d51fb8a4e06067c8766d4868bad8
-  specs:
-    puphpet-redis (0.0.11)
-      thias-sysctl (= 0.3.0)
-
 GIT
   remote: https://github.com/puphpet/puppet-supervisord.git
-  ref: 17643f1
+  ref: 17643f10c2322bfab349108e02b7f5a9992dbdde
   sha: 17643f10c2322bfab349108e02b7f5a9992dbdde
   specs:
     ajcrowe-supervisord (0.4.1)
       puppetlabs-concat (< 2.0.0, >= 1.0.0)
       puppetlabs-stdlib (>= 4.1.0)
 
+GIT
+  remote: https://github.com/puphpet/puppet-yum.git
+  ref: 8233e01382f9989e9a7b15fc529e34069f99fb37
+  sha: 8233e01382f9989e9a7b15fc529e34069f99fb37
+  specs:
+    example42-yum (2.1.25)
+      example42-puppi (>= 2.0.0)
+
 GIT
   remote: https://github.com/puppetlabs/puppetlabs-apache.git
-  ref: 7dde9fc31e
-  sha: 7dde9fc31e68a8acb2bd313fbcbc92ae33e0c440
+  ref: 1.7.1
+  sha: f7946501ddb68e0057b5dc3272657bea891639e5
   specs:
-    puppetlabs-apache (1.4.0)
+    puppetlabs-apache (1.7.1)
       puppetlabs-concat (< 2.0.0, >= 1.1.1)
       puppetlabs-stdlib (< 5.0.0, >= 2.4.0)
 
 GIT
   remote: https://github.com/puppetlabs/puppetlabs-apt.git
-  ref: 1.8.0
-  sha: 47c6f338eda98ed849531d92b63c5e33103f76e4
+  ref: 2.2.1
+  sha: 61804c0324d2bb30054dd60d93d9f13109c6f21d
   specs:
-    puppetlabs-apt (1.8.0)
-      puppetlabs-stdlib (>= 2.2.1)
+    puppetlabs-apt (2.2.1)
+      puppetlabs-stdlib (< 5.0.0, >= 4.5.0)
 
 GIT
   remote: https://github.com/puppetlabs/puppetlabs-concat.git
@@ -203,12 +190,12 @@ GIT
 
 GIT
   remote: https://github.com/puppetlabs/puppetlabs-mongodb.git
-  ref: 0.8.0
-  sha: de93beb8c2cee6b981e7f181ce10b51c60577e98
+  ref: 38ceb81e36bbbb844039e12fb8aebb43cb2cef0d
+  sha: 38ceb81e36bbbb844039e12fb8aebb43cb2cef0d
   specs:
-    puppetlabs-mongodb (0.8.0)
-      puppetlabs-apt (>= 1.0.0)
-      puppetlabs-stdlib (>= 2.2.0)
+    puppetlabs-mongodb (0.11.0)
+      puppetlabs-apt (< 3.0.0, >= 1.0.0)
+      puppetlabs-stdlib (< 5.0.0, >= 2.2.0)
 
 GIT
   remote: https://github.com/puppetlabs/puppetlabs-mysql.git
@@ -221,38 +208,38 @@ GIT
 
 GIT
   remote: https://github.com/puppetlabs/puppetlabs-ntp.git
-  ref: 3.0.4
-  sha: 7cfa3fda5028b693553a27f0e55ce2b9a2a919ae
+  ref: 4.1.1
+  sha: f6f74eb281f067e13ac66607aba361de44f8a11c
   specs:
-    puppetlabs-ntp (3.0.4)
-      puppetlabs-stdlib (>= 0.1.6)
+    puppetlabs-ntp (4.1.1)
+      puppetlabs-stdlib (< 5.0.0, >= 4.6.0)
 
 GIT
   remote: https://github.com/puppetlabs/puppetlabs-postgresql.git
-  ref: 4.2.0
-  sha: 6c61f6cfac4f26b60e253b57899264002e68f43f
+  ref: 4.6.0
+  sha: 43fd0e89254264329d53f7cc4da2f8f68888da48
   specs:
-    puppetlabs-postgresql (4.2.0)
-      puppetlabs-apt (< 2.0.0, >= 1.1.0)
+    puppetlabs-postgresql (4.6.0)
+      puppetlabs-apt (< 3.0.0, >= 1.8.0)
       puppetlabs-concat (< 2.0.0, >= 1.1.0)
       puppetlabs-stdlib (~> 4.0)
 
 GIT
   remote: https://github.com/puppetlabs/puppetlabs-rabbitmq.git
-  ref: 5.2.0
-  sha: fae371537b2ab7f4769b479aa2366115ecd88056
+  ref: 5.3.1
+  sha: b7e381715c599c527183257aa58df9d77bbe81ba
   specs:
-    puppetlabs-rabbitmq (5.2.0)
+    puppetlabs-rabbitmq (5.3.1)
       nanliu-staging (< 2.0.0, >= 0.3.1)
-      puppetlabs-apt (< 2.0.0, >= 1.8.0)
+      puppetlabs-apt (< 3.0.0, >= 1.8.0)
       puppetlabs-stdlib (< 5.0.0, >= 3.0.0)
 
 GIT
   remote: https://github.com/puppetlabs/puppetlabs-stdlib.git
-  ref: 4dab70b305
-  sha: 4dab70b305c4ab1c8c36356efa4bd205678c7c49
+  ref: 4.11.0
+  sha: fdf3f22e24a8d62712047bf66848c25461834abd
   specs:
-    puppetlabs-stdlib (4.5.1)
+    puppetlabs-stdlib (4.11.0)
 
 GIT
   remote: https://github.com/puppetlabs/puppetlabs-vcsrepo.git
@@ -261,9 +248,34 @@ GIT
   specs:
     puppetlabs-vcsrepo (0.2.0)
 
+GIT
+  remote: https://github.com/s12v/puppet-blackfire.git
+  ref: 1.4.0
+  sha: 6c90d5d865c0f001ec3971a1c31bfb125d98bc90
+  specs:
+    s12v-blackfire (1.4.0)
+      puppetlabs-apt (>= 1.0.0)
+      puppetlabs-inifile (< 2.0.0, >= 1.0.0)
+      puppetlabs-stdlib (< 5.0.0, >= 4.0.0)
+
+GIT
+  remote: https://github.com/saz/puppet-locales.git
+  ref: v2.2.2
+  sha: 3c077ea1300fc46a8b209d44bcd09a27e3b1b4c4
+  specs:
+    attachmentgenie-locales (2.2.2)
+
+GIT
+  remote: https://github.com/saz/puppet-timezone.git
+  ref: v3.3.0
+  sha: 734918982a512f51a3f1855396d2d7da3f37f53c
+  specs:
+    saz-timezone (3.3.0)
+      puppetlabs-stdlib (>= 2.3.0)
+
 DEPENDENCIES
-  actionjack-mailcatcher (>= 0)
   ajcrowe-supervisord (>= 0)
+  arioch-redis (>= 0)
   attachmentgenie-locales (>= 0)
   daenney-pyenv (>= 0)
   elasticsearch-elasticsearch (>= 0)
@@ -271,13 +283,13 @@ DEPENDENCIES
   example42-solr (>= 0)
   example42-yum (>= 0)
   garethr-erlang (>= 0)
+  golja-gnupg (>= 0)
   jfryman-nginx (>= 0)
   keen99-beanstalkd (>= 0)
   maestrodev-rvm (>= 0)
   petems-swap_file (>= 0)
   puphpet-php (>= 0)
   puphpet-puphpet (>= 0)
-  puphpet-redis (>= 0)
   puppetlabs-apache (>= 0)
   puppetlabs-apt (>= 0)
   puppetlabs-concat (>= 0)
@@ -292,5 +304,5 @@ DEPENDENCIES
   puppetlabs-stdlib (>= 0)
   puppetlabs-vcsrepo (>= 0)
   s12v-blackfire (>= 0)
+  saz-timezone (>= 0)
   tPl0ch-composer (>= 0)
-
diff --git a/puphpet/puppet/hiera.yaml b/puphpet/puppet/hiera.yaml
index 6718f9d..843f65f 100644
--- a/puphpet/puppet/hiera.yaml
+++ b/puphpet/puppet/hiera.yaml
@@ -3,6 +3,7 @@
 :yaml:
     :datadir: '/vagrant/puphpet'
 :hierarchy:
+    - config-%{::provisioner_type}
     - config-custom
     - config
 :merge_behavior: deeper
diff --git a/puphpet/puppet/nodes/Apache.pp b/puphpet/puppet/manifests/Apache.pp
similarity index 80%
rename from puphpet/puppet/nodes/Apache.pp
rename to puphpet/puppet/manifests/Apache.pp
index 19333e4..020d349 100644
--- a/puphpet/puppet/nodes/Apache.pp
+++ b/puphpet/puppet/manifests/Apache.pp
@@ -7,13 +7,42 @@
   include ::puphpet::apache::params
   include ::apache::params
 
-  class { 'puphpet::apache::repo': }
-
   # this variable is required by apache module templates
-  $apache_version = '2.4'
+  if array_true($apache['settings'], 'version')
+    and $apache['settings']['version'] in ['2.2', '22', 2.2, 22]
+  {
+    $apache_version = '2.2'
+  } else {
+    $apache_version = '2.4'
+  }
+
+  if $apache_version == '2.4' {
+    $apache_name = $::osfamily ? {
+      'Debian' => $::apache::params::apache_name,
+      'Redhat' => 'httpd24u'
+    }
+
+    $apache_mod = $::osfamily ? {
+      'Debian' => 'mod',
+      'Redhat' => 'mod24u'
+    }
+
+    class { 'puphpet::apache::repo': }
+  } else {
+    $apache_name = $::osfamily ? {
+      'Debian' => $::apache::params::apache_name,
+      'Redhat' => 'httpd'
+    }
+
+    $apache_mod = $::osfamily ? {
+      'Debian' => 'mod',
+      'Redhat' => 'mod'
+    }
+  }
+
   $modules = delete($apache['modules'], ['pagespeed', 'ssl'])
 
-  if array_true($php, 'install') {
+  if array_true($php, 'install') and ! ($php['settings']['version'] in ['5.3', '53']) {
     $php_engine    = true
     $php_fcgi_port = '9000'
   } elsif array_true($hhvm, 'install') {
@@ -54,16 +83,25 @@
     default => 'Off'
   }
 
-  $settings = merge($apache['settings'], {
+  $settings = delete(merge($apache['settings'], {
+    'apache_name'    => $apache_name,
     'default_vhost'  => false,
     'mpm_module'     => 'worker',
     'conf_template'  => $::apache::params::conf_template,
     'sendfile'       => $sendfile,
     'apache_version' => $apache_version
-  })
+  }), 'version')
 
   create_resources('class', { 'apache' => $settings })
 
+  if ! defined(Puphpet::Firewall::Port['80']) {
+    puphpet::firewall::port { '80': }
+  }
+
+  if ! defined(Puphpet::Firewall::Port['443']) {
+    puphpet::firewall::port { '443': }
+  }
+
   if $php_engine {
     $default_vhost_directories = {'default' => {
       'provider'        => 'directory',
@@ -192,8 +230,8 @@
 
     create_resources(::apache::vhost, { "${key}" => $vhost_merged })
 
-    if ! defined(Puphpet::Firewall::Port[$vhost['port']]) {
-      puphpet::firewall::port { $vhost['port']: }
+    if ! defined(Puphpet::Firewall::Port["${vhost['port']}"]) {
+      puphpet::firewall::port { "${vhost['port']}": }
     }
   }
 
@@ -216,6 +254,26 @@
     class { 'puphpet::apache::modpagespeed': }
   }
 
+  # CentOS will be using IUS which has different prefix for packages
+  if $::osfamily == 'redhat' and $apache_version == '2.4' {
+    # Install all available modules by default
+    each( ["${apache_name}-filesystem", "${apache_name}-tools", "${apache_mod}_ldap",
+           "${apache_mod}_proxy_html", "${apache_mod}_session"] ) |$package|
+    {
+      if ! defined(Package[$package]) {
+        package { $package:
+          ensure  => present,
+          require => Class['apache'],
+          notify  => Service['httpd'],
+        }
+      }
+    }
+
+    class { 'apache::mod::ssl':
+      package_name => "${apache_mod}_ssl",
+    }
+  }
+
   each( $modules ) |$module| {
     if ! defined(Apache::Mod[$module]) {
       apache::mod { $module: }
diff --git a/puphpet/puppet/nodes/Beanstalkd.pp b/puphpet/puppet/manifests/Beanstalkd.pp
similarity index 100%
rename from puphpet/puppet/nodes/Beanstalkd.pp
rename to puphpet/puppet/manifests/Beanstalkd.pp
diff --git a/puphpet/puppet/nodes/Blackfire.pp b/puphpet/puppet/manifests/Blackfire.pp
similarity index 100%
rename from puphpet/puppet/nodes/Blackfire.pp
rename to puphpet/puppet/manifests/Blackfire.pp
diff --git a/puphpet/puppet/nodes/Cron.pp b/puphpet/puppet/manifests/Cron.pp
similarity index 100%
rename from puphpet/puppet/nodes/Cron.pp
rename to puphpet/puppet/manifests/Cron.pp
diff --git a/puphpet/puppet/nodes/Drush.pp b/puphpet/puppet/manifests/Drush.pp
similarity index 100%
rename from puphpet/puppet/nodes/Drush.pp
rename to puphpet/puppet/manifests/Drush.pp
diff --git a/puphpet/puppet/nodes/ElasticSearch.pp b/puphpet/puppet/manifests/ElasticSearch.pp
similarity index 66%
rename from puphpet/puppet/nodes/ElasticSearch.pp
rename to puphpet/puppet/manifests/ElasticSearch.pp
index ba9b4ff..3438916 100644
--- a/puphpet/puppet/nodes/ElasticSearch.pp
+++ b/puphpet/puppet/manifests/ElasticSearch.pp
@@ -2,6 +2,10 @@
   $elasticsearch
 ) {
 
+  if ! defined(Puphpet::Firewall::Port["9200"]) {
+    puphpet::firewall::port { "9200": }
+  }
+
   $settings = $elasticsearch['settings']
   $version  = $elasticsearch['settings']['version']
 
@@ -33,4 +37,16 @@
 
   create_resources('class', { 'elasticsearch' => $merged })
 
+  # config file could contain no instance keys
+  $instances = array_true($elasticsearch, 'instances') ? {
+    true    => $elasticsearch['instances'],
+    default => { }
+  }
+
+  each( $instances ) |$key, $instance| {
+    $name = $instance['name']
+
+    create_resources( elasticsearch::instance, { "${name}" => $instance })
+  }
+
 }
diff --git a/puphpet/puppet/nodes/Firewall.pp b/puphpet/puppet/manifests/Firewall.pp
similarity index 78%
rename from puphpet/puppet/nodes/Firewall.pp
rename to puphpet/puppet/manifests/Firewall.pp
index f089203..34f455f 100644
--- a/puphpet/puppet/nodes/Firewall.pp
+++ b/puphpet/puppet/manifests/Firewall.pp
@@ -18,14 +18,14 @@
     }
 
     each( $ports ) |$port| {
-      if ! defined(Puphpet::Firewall::Port[$port]) {
+      if ! defined(Puphpet::Firewall::Port["${port}"]) {
         if has_key($rule, 'priority') {
           $priority = $rule['priority']
         } else {
           $priority = 100
         }
 
-        puphpet::firewall::port { $port:
+        puphpet::firewall::port { "${port}":
           protocol => $rule['proto'],
           priority => $priority,
           action   => $rule['action'],
@@ -43,8 +43,8 @@
       default => $vm['ssh']['port']
     }
 
-    if ! defined(Puphpet::Firewall::Port[$vm_ssh_port]) {
-      puphpet::firewall::port { $vm_ssh_port: }
+    if ! defined(Puphpet::Firewall::Port["${vm_ssh_port}"]) {
+      puphpet::firewall::port { "${vm_ssh_port}": }
     }
   }
 
@@ -54,8 +54,8 @@
     and has_key($vm['vm']['network'], 'forwarded_port')
   {
     each( $vm['vm']['network']['forwarded_port'] ) |$key, $ports| {
-      if ! defined(Puphpet::Firewall::Port[$ports['guest']]) {
-        puphpet::firewall::port { $ports['guest']: }
+      if ! defined(Puphpet::Firewall::Port["${ports['guest']}"]) {
+        puphpet::firewall::port {"${ports['guest']}": }
       }
     }
   }
diff --git a/puphpet/puppet/nodes/Hhvm.pp b/puphpet/puppet/manifests/Hhvm.pp
similarity index 95%
rename from puphpet/puppet/nodes/Hhvm.pp
rename to puphpet/puppet/manifests/Hhvm.pp
index def0c3d..df5e84b 100644
--- a/puphpet/puppet/nodes/Hhvm.pp
+++ b/puphpet/puppet/manifests/Hhvm.pp
@@ -55,7 +55,7 @@
   each( $server_inis ) |$key, $value| {
     $changes = [ "set '${key}' '${value}'" ]
 
-    augeas { "${key}: ${value}":
+    augeas { "hhvm server_ini, ${key}: ${value}":
       lens    => 'PHP.lns',
       incl    => $server_ini,
       context => "/files${server_ini}/.anon",
@@ -76,7 +76,7 @@
   each( $php_inis ) |$key, $value| {
     $changes = [ "set '${key}' '${value}'" ]
 
-    augeas { "${key}: ${value}":
+    augeas { "hhvm php_ini, ${key}: ${value}":
       lens    => 'PHP.lns',
       incl    => $php_ini,
       context => "/files${php_ini}/.anon",
diff --git a/puphpet/puppet/nodes/Locale.pp b/puphpet/puppet/manifests/Locale.pp
similarity index 57%
rename from puphpet/puppet/nodes/Locale.pp
rename to puphpet/puppet/manifests/Locale.pp
index 9423811..a4cabd5 100644
--- a/puphpet/puppet/nodes/Locale.pp
+++ b/puphpet/puppet/manifests/Locale.pp
@@ -12,15 +12,24 @@
 
     $user_locale = array_true($settings, 'locales') ? {
       true    => $settings['locales'],
-      default => ['en_US.UTF-8 UTF-8', 'en_GB.UTF-8 UTF-8']
+      default => ['en_US.UTF-8', 'en_GB.UTF-8']
     }
 
-    $merged = merge($settings, {
+    $merged = delete(merge($settings, {
       'default_locale' => $default_locale,
-      'locales'        => $user_locale,
-    })
+      'locales'        => suffix($user_locale, ' UTF-8'),
+    }), 'timezone')
 
     create_resources('class', { 'locales' => $merged })
   }
 
+  $timezone = array_true($settings, 'timezone') ? {
+    true    => $settings['timezone'],
+    default => 'UTC'
+  }
+
+  class { 'timezone':
+    timezone => $timezone,
+  }
+
 }
diff --git a/puphpet/puppet/manifests/MailHog.pp b/puphpet/puppet/manifests/MailHog.pp
new file mode 100644
index 0000000..cebff7f
--- /dev/null
+++ b/puphpet/puppet/manifests/MailHog.pp
@@ -0,0 +1,60 @@
+class puphpet_mailhog (
+  $mailhog
+) {
+
+  include puphpet::supervisord
+
+  $settings = $mailhog['settings']
+
+  $filename = $::architecture ? {
+    'i386'   => 'MailHog_linux_386',
+    'amd64'  => 'MailHog_linux_amd64',
+    'x86_64' => 'MailHog_linux_amd64'
+  }
+
+  $url  = "https://github.com/mailhog/MailHog/releases/download/v0.1.8/${filename}"
+  $path = $settings['path']
+  $cmd  = "wget --quiet --tries=5 --connect-timeout=10 -O '${path}' ${url}"
+
+  exec { "download ${url}":
+    creates => $path,
+    command => $cmd,
+    timeout => 3600,
+    path    => '/usr/bin',
+  } ->
+  file { $path:
+    ensure => present,
+    mode   => '+x',
+  } ->
+  user { 'mailhog':
+    ensure     => present,
+    shell      => '/bin/bash',
+    managehome => false,
+  }
+
+  if ! defined(Puphpet::Firewall::Port["${settings['smtp_port']}"]) {
+    puphpet::firewall::port { "${settings['smtp_port']}": }
+  }
+
+  if ! defined(Puphpet::Firewall::Port["${settings['http_port']}"]) {
+    puphpet::firewall::port { "${settings['http_port']}": }
+  }
+
+  $options = sort(join_keys_to_values({
+    ' -smtp-bind-addr' => "${settings['smtp_ip']}:${settings['smtp_port']}",
+    ' -ui-bind-addr'   => "${settings['http_ip']}:${settings['http_port']}"
+  }, ' '))
+
+  supervisord::program { 'mailhog':
+    command     => "${path} ${options}",
+    priority    => '100',
+    user        => 'mailhog',
+    autostart   => true,
+    autorestart => 'true',
+    environment => {
+      'PATH' => "/bin:/sbin:/usr/bin:/usr/sbin:${path}"
+    },
+    require     => File[$path],
+  }
+
+}
diff --git a/puphpet/puppet/nodes/MariaDb.pp b/puphpet/puppet/manifests/MariaDb.pp
similarity index 88%
rename from puphpet/puppet/nodes/MariaDb.pp
rename to puphpet/puppet/manifests/MariaDb.pp
index a04a3e5..34b690e 100644
--- a/puphpet/puppet/nodes/MariaDb.pp
+++ b/puphpet/puppet/manifests/MariaDb.pp
@@ -33,8 +33,9 @@
     $php_package = false
   }
 
-  if empty($mariadb['settings']['root_password']) {
-    fail( 'MariaDB requires choosing a root password. Please check your config.yaml file.' )
+  $root_password = array_true($mysql['settings'], 'root_password') ? {
+    true    => $mysql['settings']['root_password'],
+    default => $mysql::params::root_password
   }
 
   $override_options = deep_merge($mysql::params::default_options, {
@@ -48,10 +49,14 @@
     'restart'          => true,
     'override_options' => $override_options,
     'service_name'     => 'mysql',
-  }, $mariadb['settings']), 'version')
+  }, $mariadb['settings']), ['version', 'root_password'])
+
+  $settingsPw = deep_merge($settings, {
+    'root_password' => $root_password
+  })
 
   create_resources('class', {
-    'mysql::server' => $settings
+    'mysql::server' => $settingsPw
   })
 
   class { 'mysql::client':
@@ -74,18 +79,6 @@
     }
   }
 
-  # prevent problems with being unable to create dir in /tmp
-  if ! defined(File[$override_options['mysqld']['tmpdir']]) {
-    file { $override_options['mysqld']['tmpdir']:
-      ensure  => directory,
-      owner   => $mariadb_user,
-      group   => $mysql::params::root_group,
-      mode    => '0775',
-      require => Class['mysql::client'],
-      notify  => Service[$settings['service_name']]
-    }
-  }
-
   # Ensure the data directory exists
   if ! defined(File[$mysql::params::datadir]) {
     file { $mysql::params::datadir:
@@ -163,7 +156,7 @@
 
     create_resources( mysql_database, { "${name}" => $merged })
 
-    if $sql {
+    if $sql != '' {
       # Run import only on initial database creation
       $touch_file = "/.puphpet-stuff/db-import-${name}"
 
@@ -216,6 +209,8 @@
       $php_module = 'mysql'
     } elsif $::lsbdistcodename == 'lucid' or $::lsbdistcodename == 'squeeze' {
       $php_module = 'mysql'
+    } elsif $::osfamily == 'debian' and $php['settings']['version'] in ['7.0', '70'] {
+      $php_module = 'mysql'
     } else {
       $php_module = 'mysqlnd'
     }
@@ -247,9 +242,8 @@
     }
 
     class { 'puphpet::adminer':
-      location    => "${$adminer_webroot}/adminer",
-      owner       => 'www-data',
-      php_package => $php_package
+      location => "${$adminer_webroot}/adminer",
+      owner    => 'www-data'
     }
   }
 
diff --git a/puphpet/puppet/manifests/MongoDb.pp b/puphpet/puppet/manifests/MongoDb.pp
new file mode 100644
index 0000000..6c034af
--- /dev/null
+++ b/puphpet/puppet/manifests/MongoDb.pp
@@ -0,0 +1,102 @@
+class puphpet_mongodb (
+  $mongodb,
+  $apache,
+  $nginx,
+  $php
+) {
+
+  if array_true($apache, 'install') or array_true($nginx, 'install') {
+    $webserver_restart = true
+  } else {
+    $webserver_restart = false
+  }
+
+  file { ['/data', '/data/db']:
+    ensure => directory,
+    mode   => '0775',
+    before => Class['mongodb::globals'],
+  }
+
+  Class['mongodb::globals']
+  -> Class['mongodb::server']
+
+  # The GUI does not choose a version by default
+  $global_settings = array_true($mongodb, 'global') ? {
+    true    => $mongodb['global'],
+    default => { }
+  }
+
+  $merged_globals = merge({
+    'manage_package_repo' => true,
+    'version'             => $::osfamily ? {
+      'debian' => '2.6.11',
+      'redhat' => '2.6.11-1',
+    },
+  }, $global_settings)
+
+  create_resources('class', {
+    'mongodb::globals' => $merged_globals
+  })
+
+  create_resources('class', {
+    'mongodb::server' => $mongodb['settings']
+  })
+
+  if $::osfamily == 'redhat' {
+    class { 'mongodb::client':
+      require => Class['mongodb::server']
+    }
+  }
+
+  # MongoDB module does not handle creating log and pidfile directories
+  if ! defined(User[$::mongodb::params::user]) {
+    user { $::mongodb::params::user:
+      ensure     => present,
+      managehome => false,
+    }
+  }
+
+  file { '/var/log/mongodb':
+    ensure  => directory,
+    owner   => $::mongodb::params::user,
+    mode    => '0775',
+    notify  => Service[$::mongodb::globals::service_name],
+    require => User[$::mongodb::params::user]
+  }
+  -> file { '/var/run/mongodb':
+    ensure  => directory,
+    owner   => $::mongodb::params::user,
+    mode    => '0775',
+    notify  => Service[$::mongodb::globals::service_name],
+  }
+  -> file { $::mongodb::params::pidfilepath:
+    ensure  => file,
+    owner   => $::mongodb::params::user,
+    mode    => '0775',
+    notify  => Service[$::mongodb::globals::service_name],
+  }
+  -> file { $::mongodb::params::logpath:
+    ensure  => file,
+    owner   => $::mongodb::params::user,
+    mode    => '0775',
+    notify  => Service[$::mongodb::globals::service_name],
+  }
+
+  each( $mongodb['databases'] ) |$key, $database| {
+    $merged = delete(merge($database, {
+      'dbname' => $database['name'],
+    }), 'name')
+
+    create_resources( puphpet::mongodb::db, {
+      "${database['user']}@${database['name']}" => $merged
+    })
+  }
+
+  if array_true($php, 'install') and ! defined(Puphpet::Php::Pecl['mongo']) {
+    puphpet::php::pecl { 'mongo':
+      service_autorestart => $webserver_restart,
+      require             => Class['mongodb::server']
+    }
+  }
+
+}
diff --git a/puphpet/puppet/nodes/Mysql.pp b/puphpet/puppet/manifests/Mysql.pp
similarity index 90%
rename from puphpet/puppet/nodes/Mysql.pp
rename to puphpet/puppet/manifests/Mysql.pp
index 8886c12..37deb34 100644
--- a/puphpet/puppet/nodes/Mysql.pp
+++ b/puphpet/puppet/manifests/Mysql.pp
@@ -38,8 +38,9 @@
     $php_package = false
   }
 
-  if empty($mysql['settings']['root_password']) {
-    fail( 'MySQL requires choosing a root password. Please check your config.yaml file.' )
+  $root_password = array_true($mysql['settings'], 'root_password') ? {
+    true    => $mysql['settings']['root_password'],
+    default => $mysql::params::root_password
   }
 
   $override_options = deep_merge($mysql::params::default_options, {
@@ -53,10 +54,14 @@
     'restart'          => true,
     'override_options' => $override_options,
     require            => Class['puphpet::mysql::repo'],
-  }, $mysql['settings']), 'version')
+  }, $mysql['settings']), ['version', 'root_password'])
+
+  $settingsPw = deep_merge($settings, {
+    'root_password' => $root_password
+  })
 
   create_resources('class', {
-    'mysql::server' => $settings
+    'mysql::server' => $settingsPw
   })
 
   class { 'mysql::client':
@@ -114,7 +119,7 @@
 
     create_resources( mysql_database, { "${name}" => $merged })
 
-    if $sql {
+    if $sql != '' {
       # Run import only on initial database creation
       $touch_file = "/.puphpet-stuff/db-import-${name}"
 
@@ -167,6 +172,8 @@
       $php_module = 'mysql'
     } elsif $::lsbdistcodename == 'lucid' or $::lsbdistcodename == 'squeeze' {
       $php_module = 'mysql'
+    } elsif $::osfamily == 'debian' and $php['settings']['version'] in ['7.0', '70'] {
+      $php_module = 'mysql'
     } else {
       $php_module = 'mysqlnd'
     }
@@ -198,9 +205,8 @@
     }
 
     class { 'puphpet::adminer':
-      location    => "${$adminer_webroot}/adminer",
-      owner       => 'www-data',
-      php_package => $php_package
+      location => "${$adminer_webroot}/adminer",
+      owner    => 'www-data'
     }
   }
 
diff --git a/puphpet/puppet/nodes/Nginx.pp b/puphpet/puppet/manifests/Nginx.pp
similarity index 77%
rename from puphpet/puppet/nodes/Nginx.pp
rename to puphpet/puppet/manifests/Nginx.pp
index 6747c8c..ed48a5e 100644
--- a/puphpet/puppet/nodes/Nginx.pp
+++ b/puphpet/puppet/manifests/Nginx.pp
@@ -52,13 +52,19 @@
       "${name}" => $merged
     })
 
-    each( $upstream['members'] ) |$key, $member| {
+    # upstream hash could contain no members key
+    $members = array_true($upstream, 'members') ? {
+      true    => $upstream['members'],
+      default => { }
+    }
+
+    each( $members ) |$key, $member| {
       $member_array = $package_array = split($member, ':')
 
       if count($member_array) == 2
-        and ! defined(Puphpet::Firewall::Port[$member_array[1]])
+        and ! defined(Puphpet::Firewall::Port["${member_array[1]}"])
       {
-        puphpet::firewall::port { $member_array[1]: }
+        puphpet::firewall::port { "${member_array[1]}": }
       }
     }
   }
@@ -134,6 +140,7 @@
           {
             'location'              => '/',
             'autoindex'             => 'off',
+            'internal'              => false,
             'try_files'             => ['$uri', '$uri/', 'index.php',],
             'fastcgi'               => '',
             'fastcgi_index'         => '',
@@ -144,6 +151,7 @@
           {
             'location'              => '~ \.php$',
             'autoindex'             => 'off',
+            'internal'              => false,
             'try_files'             => [
               '$uri', '$uri/', 'index.php', '/index.php$is_args$args'
             ],
@@ -173,19 +181,22 @@
   }
 
   each( $vhosts ) |$key, $vhost| {
-    exec { "exec mkdir -p ${vhost['www_root']} @ key ${key}":
-      command => "mkdir -p ${vhost['www_root']}",
-      user    => $webroot_user,
-      group   => $webroot_group,
-      creates => $vhost['www_root'],
-      require => File[$www_location],
-    }
+    # Could be proxy vhost
+    if $vhost['www_root'] != '' {
+      exec { "exec mkdir -p ${vhost['www_root']} @ key ${key}":
+        command => "mkdir -p ${vhost['www_root']}",
+        user    => $webroot_user,
+        group   => $webroot_group,
+        creates => $vhost['www_root'],
+        require => File[$www_location],
+      }
 
-    if ! defined(File[$vhost['www_root']]) {
-      file { $vhost['www_root']:
-        ensure  => directory,
-        mode    => '0775',
-        require => Exec["exec mkdir -p ${vhost['www_root']} @ key ${key}"],
+      if ! defined(File[$vhost['www_root']]) {
+        file { $vhost['www_root']:
+          ensure  => directory,
+          mode    => '0775',
+          require => Exec["exec mkdir -p ${vhost['www_root']} @ key ${key}"],
+        }
       }
     }
 
@@ -240,8 +251,17 @@
       $vhost
     )
 
+    # rewrites
+    $rewrites = array_true($vhost, 'rewrites') ? {
+      true    =>  $vhost['rewrites'],
+      default =>  {}
+    }
+    $vhost_rewrites_append = deep_merge($vhost_cfg_append, {
+      'rewrites'  => $rewrites
+    })
+
     # puppet-nginx is stupidly strict about ssl value datatypes
-    $merged = delete(merge($vhost_cfg_append, {
+    $merged = delete(merge($vhost_rewrites_append, {
       'server_name'          => $server_names,
       'use_default_location' => false,
       'ssl'                  => $ssl,
@@ -268,6 +288,12 @@
         $autoindex = 'off'
       }
 
+      if array_true($location, 'internal') and $location['internal'] != 'off' {
+        $internal = true
+      } else {
+        $internal = false
+      }
+
       # remove empty values
       $location_trimmed = merge({
         'fast_cgi_params_extra' => [],
@@ -276,6 +302,7 @@
       # transforms user-data to expected
       $location_custom_data = merge($location_trimmed, {
         'autoindex' => $autoindex,
+        'internal'  => $internal,
       })
 
       # Takes gui ENV vars: fastcgi_param {ENV_NAME} {VALUE}
@@ -296,21 +323,27 @@
 
       # If www_root was removed with all the trimmings,
       # add it back it
-      if ! defined($location_no_root['fastcgi'])
-        or empty($location_no_root['fastcgi'])
-      {
-        $location_merged = merge({
+      if ! array_true($location_no_root, 'fastcgi') {
+        $location_root_merged = merge({
           'www_root' => $vhost['www_root'],
         }, $location_no_root)
       } else {
-        $location_merged = $location_no_root
+        $location_root_merged = $location_no_root
       }
 
+      # location rewrites
+      $location_merged = deep_merge($location_root_merged, {
+        'rewrites'  => array_true($location_root_merged, 'rewrites') ? {
+          true    => $location_root_merged['rewrites'],
+          default => { }
+        }
+      })
+
       create_resources(nginx::resource::location, { "${lkey}" => $location_merged })
     }
 
-    if ! defined(Puphpet::Firewall::Port[$vhost['listen_port']]) {
-      puphpet::firewall::port { $vhost['listen_port']: }
+    if ! defined(Puphpet::Firewall::Port["${vhost['listen_port']}"]) {
+      puphpet::firewall::port { "${vhost['listen_port']}": }
     }
   }
 
@@ -318,21 +351,23 @@
     puphpet::firewall::port { '443': }
   }
 
-  $default_vhost_index_file =
-    "${puphpet::params::nginx_webroot_location}/index.html"
-
-  $default_vhost_source_file =
-    '/vagrant/puphpet/puppet/modules/puphpet/files/webserver_landing.html'
-
-  exec { "Set ${default_vhost_index_file} contents":
-    command => "cat ${default_vhost_source_file} > ${default_vhost_index_file} && \
-                chmod 644 ${default_vhost_index_file} && \
-                chown root ${default_vhost_index_file} && \
-                chgrp ${webroot_group} ${default_vhost_index_file} && \
-                touch /.puphpet-stuff/default_vhost_index_file_set",
-    returns => [0, 1],
-    creates => '/.puphpet-stuff/default_vhost_index_file_set',
-    require => File[$puphpet::params::nginx_webroot_location],
+  if array_true($nginx['settings'], 'default_vhost') {
+    $default_vhost_index_file =
+      "${puphpet::params::nginx_webroot_location}/index.html"
+
+    $default_vhost_source_file =
+      '/vagrant/puphpet/puppet/modules/puphpet/files/webserver_landing.html'
+
+    exec { "Set ${default_vhost_index_file} contents":
+      command => "cat ${default_vhost_source_file} > ${default_vhost_index_file} && \
+                  chmod 644 ${default_vhost_index_file} && \
+                  chown root ${default_vhost_index_file} && \
+                  chgrp ${webroot_group} ${default_vhost_index_file} && \
+                  touch /.puphpet-stuff/default_vhost_index_file_set",
+      returns => [0, 1],
+      creates => '/.puphpet-stuff/default_vhost_index_file_set',
+      require => File[$puphpet::params::nginx_webroot_location],
+    }
   }
 
 }
diff --git a/puphpet/puppet/manifests/NodeJs.pp b/puphpet/puppet/manifests/NodeJs.pp
new file mode 100644
index 0000000..cca2c44
--- /dev/null
+++ b/puphpet/puppet/manifests/NodeJs.pp
@@ -0,0 +1,101 @@
+class puphpet_nodejs (
+  $nodejs
+) {
+
+  if array_true($nodejs, 'settings')
+    and array_true($nodejs['settings'], ['version'])
+  {
+    $version_num = $nodejs['settings']['version']
+  } else {
+    $version_num = '0.12'
+  }
+
+  if $::osfamily == 'debian' {
+    if ! defined('apt-transport-https') {
+      package { 'apt-transport-https':
+        ensure => present
+      }
+    }
+
+    $version = $version_num ? {
+      '5'     => '5.x',
+      '4'     => '4.x',
+      '0.12'  => '0.12',
+      '0.10'  => '0.10',
+      default => "${version_num}.x"
+    }
+
+    $url = "https://deb.nodesource.com/setup_${version}"
+
+    $save_to = '/.puphpet-stuff/nodesource'
+
+    exec { 'add nodejs repo':
+      command => "wget --quiet --tries=5 --connect-timeout=10 -O '${save_to}' ${url} \
+                  && bash ${save_to}",
+      creates => $save_to,
+      path    => '/usr/bin:/bin',
+      require => Package['apt-transport-https'],
+    }
+    -> package { 'nodejs':
+      ensure => present,
+    }
+  } else {
+    $pkg_url = $version_num ? {
+      '0.12'  => 'https://rpm.nodesource.com/pub_0.12/el/6/x86_64/nodejs-0.12.9-1nodesource.el6.x86_64.rpm',
+      '0.10'  => 'https://rpm.nodesource.com/pub_0.10/el/6/x86_64/nodejs-0.10.41-1nodesource.el6.x86_64.rpm',
+      default => false
+    }
+
+    if ! $pkg_url {
+      fail('You have chosen an unsupported NodeJS version.')
+    }
+
+    $dev_url = $version_num ? {
+      '0.12' => 'https://rpm.nodesource.com/pub_0.12/el/6/x86_64/nodejs-devel-0.12.9-1nodesource.el6.x86_64.rpm',
+      '0.10' => 'https://rpm.nodesource.com/pub_0.10/el/6/x86_64/nodejs-devel-0.10.41-1nodesource.el6.x86_64.rpm',
+    }
+
+    $pkg_save_to = '/.puphpet-stuff/nodesource_pkg'
+    $dev_save_to = '/.puphpet-stuff/nodesource_dev'
+
+    exec { 'add nodejs rpm':
+      command => "wget --quiet --tries=5 --connect-timeout=10 -O '${pkg_save_to}' ${pkg_url}",
+      creates => $pkg_save_to,
+      path    => '/usr/bin:/bin',
+    }
+    -> exec { 'add nodejs dev rpm':
+      command => "wget --quiet --tries=5 --connect-timeout=10 -O '${dev_save_to}' ${dev_url}",
+      creates => $dev_save_to,
+      path    => '/usr/bin:/bin',
+    }
+    -> package { 'nodejs':
+      ensure   => 'present',
+      provider => 'rpm',
+      source   => $pkg_save_to,
+    }
+    -> package { 'nodejs-devel':
+      ensure   => 'present',
+      provider => 'rpm',
+      source   => $dev_save_to,
+    }
+  }
+
+  each( $nodejs['npm_packages'] ) |$package| {
+      $npm_array = split($package, '@')
+
+      if count($npm_array) == 2 {
+        $npm_ensure = $npm_array[1]
+      } else {
+        $npm_ensure = present
+      }
+
+    if ! defined(Package[$npm_array[0]]) {
+      package { $npm_array[0]:
+        ensure   => $npm_ensure,
+        provider => npm,
+        require  => Package['nodejs']
+      }
+    }
+  }
+
+}
diff --git a/puphpet/puppet/nodes/Php.pp b/puphpet/puppet/manifests/Php.pp
similarity index 81%
rename from puphpet/puppet/nodes/Php.pp
rename to puphpet/puppet/manifests/Php.pp
index 41b9f2d..be9f0e6 100644
--- a/puphpet/puppet/nodes/Php.pp
+++ b/puphpet/puppet/manifests/Php.pp
@@ -1,6 +1,6 @@
 class puphpet_php (
   $php,
-  $mailcatcher
+  $mailhog
 ) {
 
   include ::php::params
@@ -9,33 +9,31 @@
     version_string => $php['settings']['version'],
   }
 
-  $version  = $puphpet::php::settings::version
-  $base_ini = $puphpet::php::settings::base_ini
-  $package  = $puphpet::php::settings::fpm_package
-  $service  = $puphpet::php::settings::service
+  $version       = $puphpet::php::settings::version
+  $base_ini      = $puphpet::php::settings::base_ini
+  $package       = $puphpet::php::settings::fpm_package
+  $package_devel = $puphpet::php::settings::package_devel
+  $service       = $puphpet::php::settings::service
 
   Class['Puphpet::Php::Settings']
   -> Package[$package]
 
-  if $version == '7.0' {
-    class { 'puphpet::php::beta': }
-  } else {
-    class { 'puphpet::php::repos':
-      php_version => $version,
-    }
+  class { 'puphpet::php::repos':
+    php_version => $version,
+  }
 
-    if ! defined(Service[$service]) {
-      service { $service:
-        ensure     => 'running',
-        enable     => true,
-        hasrestart => true,
-        hasstatus  => true,
-        require    => Package[$package]
-      }
+  if ! defined(Service[$service]) {
+    service { $service:
+      ensure     => 'running',
+      enable     => true,
+      hasrestart => true,
+      hasstatus  => true,
+      require    => Package[$package]
     }
 
     class { 'php':
       package             => $package,
+      package_devel       => $package_devel,
       service             => $service,
       version             => 'present',
       service_autorestart => false,
@@ -195,27 +193,28 @@
     }
   }
 
-  # Usually this would go within the library that needs in (Mailcatcher)
+  # Usually this would go within the library that needs it  (MailHog)
   # but the values required are sufficiently complex that it's easier to
   # add here
-  if array_true($mailcatcher, 'install')
+  if array_true($mailhog, 'install')
     and ! defined(Puphpet::Php::Ini['sendmail_path'])
   {
-    $mc_from_method = $mailcatcher['settings']['from_email_method']
-    $mc_path = $mailcatcher['settings']['mailcatcher_path']
-
-    $mailcatcher_f_flag = $mc_from_method ? {
-      'headers' => '',
-      default   => ' -f',
-    }
-
     puphpet::php::ini { 'sendmail_path':
       entry       => 'CUSTOM/sendmail_path',
-      value       => "${mc_path}/catchmail${mailcatcher_f_flag}",
+      value       => "${mailhog['settings']['path']} sendmail foo@example.com",
       php_version => $version,
       webserver   => $service,
       notify      => Service[$service],
     }
   }
 
+  if $version == '70' and $::osfamily == 'redhat' {
+    exec { 'Fix pid_file path':
+      command => "perl -p -i -e 's#/var/run/php-fpm/php-fpm.pid#/var/run/php-fpm.pid#gi' /etc/init.d/php-fpm",
+      unless  => "grep -x '/var/run/php-fpm.pid' /etc/init.d/php-fpm",
+      path    => [ '/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/' ],
+      notify  => Service[$service],
+    }
+  }
+
 }
diff --git a/puphpet/puppet/nodes/Postgresql.pp b/puphpet/puppet/manifests/Postgresql.pp
similarity index 96%
rename from puphpet/puppet/nodes/Postgresql.pp
rename to puphpet/puppet/manifests/Postgresql.pp
index 0a98f4e..1ef3cf8 100644
--- a/puphpet/puppet/nodes/Postgresql.pp
+++ b/puphpet/puppet/manifests/Postgresql.pp
@@ -140,9 +140,8 @@
     }
 
     class { 'puphpet::adminer':
-      location    => "${$adminer_webroot}/adminer",
-      owner       => 'www-data',
-      php_package => $php_package
+      location => "${$adminer_webroot}/adminer",
+      owner    => 'www-data',
     }
   }
 
diff --git a/puphpet/puppet/nodes/Python.pp b/puphpet/puppet/manifests/Python.pp
similarity index 95%
rename from puphpet/puppet/nodes/Python.pp
rename to puphpet/puppet/manifests/Python.pp
index e074b33..9f67bda 100644
--- a/puphpet/puppet/nodes/Python.pp
+++ b/puphpet/puppet/manifests/Python.pp
@@ -3,6 +3,7 @@
 ) {
 
   include pyenv::params
+  include puphpet::supervisord
 
   puphpet::python::preinstall { 'foo':
     before => Class['pyenv'],
diff --git a/puphpet/puppet/nodes/RabbitMQ.pp b/puphpet/puppet/manifests/RabbitMQ.pp
similarity index 75%
rename from puphpet/puppet/nodes/RabbitMQ.pp
rename to puphpet/puppet/manifests/RabbitMQ.pp
index 0aea7d0..d2e49b8 100644
--- a/puphpet/puppet/nodes/RabbitMQ.pp
+++ b/puphpet/puppet/manifests/RabbitMQ.pp
@@ -76,14 +76,34 @@
   }
 
   if array_true($php, 'install') and ! defined(Puphpet::Php::Pecl['amqp']) {
-    puphpet::php::pecl { 'amqp':
+    if $puphpet::php::settings::version == '70' {
+      $rabbitmq_dev_pkg = $::osfamily ? {
+        'debian' => 'librabbitmq-dev',
+        'redhat' => 'librabbitmq-devel',
+      }
+
+      if ! defined(Package[$rabbitmq_dev_pkg]) {
+        package { $rabbitmq_dev_pkg:
+          ensure => present,
+        }
+      }
+
+      $pecl_pkg = $::osfamily ? {
+        'debian' => 'amqp-1.7.0alpha1',
+        'redhat' => 'amqp',
+      }
+    } else {
+      $pecl_pkg = 'amqp'
+    }
+
+    puphpet::php::pecl { $pecl_pkg:
       service_autorestart => $webserver_restart,
       require             => Package['rabbitmq-server']
     }
   }
 
-  if ! defined(Puphpet::Firewall::Port[$settings['port']]) {
-    puphpet::firewall::port { $settings['port']: }
+  if ! defined(Puphpet::Firewall::Port["${settings['port']}"]) {
+    puphpet::firewall::port { "${settings['port']}": }
   }
 
 }
diff --git a/puphpet/puppet/nodes/Redis.pp b/puphpet/puppet/manifests/Redis.pp
similarity index 59%
rename from puphpet/puppet/nodes/Redis.pp
rename to puphpet/puppet/manifests/Redis.pp
index 27d0ac5..ea3a09c 100644
--- a/puphpet/puppet/nodes/Redis.pp
+++ b/puphpet/puppet/manifests/Redis.pp
@@ -11,7 +11,17 @@
     $webserver_restart = false
   }
 
-  create_resources('class', { 'redis' => $redis['settings'] })
+  if array_true($redis['settings'], 'conf_port') {
+    $port = $redis['settings']['conf_port']
+  } else {
+    $port = $redis['settings']['port']
+  }
+
+  $settings = delete(deep_merge({
+    'port' => $port,
+  }, $redis['settings']), 'conf_port')
+
+  create_resources('class', { 'redis' => $settings })
 
   if array_true($php, 'install') and ! defined(Puphpet::Php::Pecl['redis']) {
     puphpet::php::pecl { 'redis':
diff --git a/puphpet/puppet/manifests/Ruby.pp b/puphpet/puppet/manifests/Ruby.pp
new file mode 100644
index 0000000..dc3c509
--- /dev/null
+++ b/puphpet/puppet/manifests/Ruby.pp
@@ -0,0 +1,38 @@
+class puphpet_ruby (
+  $ruby
+) {
+
+  include '::gnupg'
+
+  Class['::rvm']
+  -> Puphpet::Ruby::Dotfile <| |>
+  -> Puphpet::Ruby::Install <| |>
+
+  class { '::rvm':
+    key_server => 'hkp://pgp.mit.edu/',
+  }
+
+  if ! defined(Group['rvm']) {
+    group { 'rvm':
+      ensure => present
+    }
+  }
+
+  exec { 'rvm rvmrc warning ignore all.rvmrcs':
+    command => 'rvm rvmrc warning ignore all.rvmrcs && touch /.puphpet-stuff/rvmrc',
+    creates => '/.puphpet-stuff/rvmrc',
+    path    => '/bin:/usr/bin:/usr/local/bin:/usr/local/rvm/bin',
+    require => Exec['system-rvm'],
+  }
+
+  User <| title == $::ssh_username |> {
+    groups +> 'rvm'
+  }
+
+  if array_true($ruby, 'versions') and count($ruby['versions']) > 0 {
+    puphpet::ruby::dotfile { 'do': }
+
+    create_resources(puphpet::ruby::install, $ruby['versions'])
+  }
+
+}
diff --git a/puphpet/puppet/nodes/Server.pp b/puphpet/puppet/manifests/Server.pp
similarity index 79%
rename from puphpet/puppet/nodes/Server.pp
rename to puphpet/puppet/manifests/Server.pp
index d1edef0..5068caa 100644
--- a/puphpet/puppet/nodes/Server.pp
+++ b/puphpet/puppet/manifests/Server.pp
@@ -33,7 +33,7 @@
     require    => [Group['www-data'], Group['www-user']],
   }
 
-  User[$::ssh_username]
+  realize(User[$::ssh_username])
 
   each( ['apache', 'nginx', 'httpd', 'www-data', 'www-user'] ) |$key| {
     if ! defined(User[$key]) {
@@ -80,13 +80,6 @@
 
       Class['::yum'] -> Yum::Managed_yumrepo <| |> -> Package <| |>
 
-      if ! defined(Package['git']) {
-        package { 'git':
-          ensure  => latest,
-          require => Class['yum::repo::repoforgeextras']
-        }
-      }
-
       if ! defined(Package['augeas']) {
         package { 'augeas':
           ensure => present,
@@ -108,39 +101,43 @@
           release           => $::lsbdistcodename,
           repos             => 'all',
           required_packages => 'debian-keyring debian-archive-keyring',
-          key               => '89DF5277',
-          key_server        => 'hkp://keyserver.ubuntu.com:80',
-          include_src       => true
+          key               => {
+            'id'      => '89DF5277',
+            'server'  => 'hkp://keyserver.ubuntu.com:80',
+          },
+          include           => { 'src' => true }
         }
       }
 
       $lsbdistcodename = downcase($::lsbdistcodename)
 
-      apt::force { 'git':
-        release => "${lsbdistcodename}-backports",
-        timeout => 60
+      if ! defined(Package['git']) {
+        package { 'git':
+          ensure          => present,
+          install_options => "-t ${lsbdistcodename}-backports"
+        }
       }
     }
     'ubuntu': {
-      if ! defined(Apt::Key['4F4EA0AAE5267A6C']){
-        apt::key { '4F4EA0AAE5267A6C':
-          key_server => 'hkp://keyserver.ubuntu.com:80'
+      if ! defined(Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C']){
+        apt::key { '14AA40EC0831756756D7F66C4F4EA0AAE5267A6C':
+          server => 'hkp://keyserver.ubuntu.com:80'
         }
       }
-      if ! defined(Apt::Key['4CBEDD5A']){
-        apt::key { '4CBEDD5A':
-          key_server => 'hkp://keyserver.ubuntu.com:80'
+      if ! defined(Apt::Key['945A6177078449082DDCC0E5551CE2FB4CBEDD5A']){
+        apt::key { '945A6177078449082DDCC0E5551CE2FB4CBEDD5A':
+          server => 'hkp://keyserver.ubuntu.com:80'
         }
       }
 
       if $::lsbdistcodename in ['lucid', 'precise'] {
         apt::ppa { 'ppa:pdoes/ppa':
-          require => Apt::Key['4CBEDD5A'],
+          require => Apt::Key['945A6177078449082DDCC0E5551CE2FB4CBEDD5A'],
           options => ''
         }
       } else {
         apt::ppa { 'ppa:pdoes/ppa':
-          require => Apt::Key['4CBEDD5A']
+          require => Apt::Key['945A6177078449082DDCC0E5551CE2FB4CBEDD5A']
         }
       }
     }
diff --git a/puphpet/puppet/nodes/Solr.pp b/puphpet/puppet/manifests/Solr.pp
similarity index 88%
rename from puphpet/puppet/nodes/Solr.pp
rename to puphpet/puppet/manifests/Solr.pp
index 51864ff..542a032 100644
--- a/puphpet/puppet/nodes/Solr.pp
+++ b/puphpet/puppet/manifests/Solr.pp
@@ -3,6 +3,7 @@
 ) {
 
   include solr::params
+  include puphpet::supervisord
 
   $settings = $solr['settings']
 
@@ -31,8 +32,8 @@
     ],
   }
 
-  if ! defined(Puphpet::Firewall::Port[$settings['port']]) {
-    puphpet::firewall::port { $settings['port']: }
+  if ! defined(Puphpet::Firewall::Port["${settings['port']}"]) {
+    puphpet::firewall::port { "${settings['port']}": }
   }
 
   $destination = $solr::params::install_destination
diff --git a/puphpet/puppet/nodes/Sqlite.pp b/puphpet/puppet/manifests/Sqlite.pp
similarity index 89%
rename from puphpet/puppet/nodes/Sqlite.pp
rename to puphpet/puppet/manifests/Sqlite.pp
index 7a96e50..7ceef45 100644
--- a/puphpet/puppet/nodes/Sqlite.pp
+++ b/puphpet/puppet/manifests/Sqlite.pp
@@ -37,7 +37,9 @@
       'group' => $group,
     }), 'mode')
 
-    create_resources( puphpet::sqlite::db, { "${key}" => $merged })
+    create_resources( puphpet::sqlite::db, {
+      "${name}" => $merged
+    })
   }
 
   if $php_package == 'php' and ! defined(Puphpet::Php::Pecl['sqlite']) {
@@ -66,9 +68,8 @@
     }
 
     class { 'puphpet::adminer':
-      location    => "${$adminer_webroot}/adminer",
-      owner       => 'www-data',
-      php_package => $php_package
+      location => "${$adminer_webroot}/adminer",
+      owner    => 'www-data',
     }
   }
 
diff --git a/puphpet/puppet/nodes/UsersGroups.pp b/puphpet/puppet/manifests/UsersGroups.pp
similarity index 100%
rename from puphpet/puppet/nodes/UsersGroups.pp
rename to puphpet/puppet/manifests/UsersGroups.pp
diff --git a/puphpet/puppet/nodes/WPCli.pp b/puphpet/puppet/manifests/WPCli.pp
similarity index 100%
rename from puphpet/puppet/nodes/WPCli.pp
rename to puphpet/puppet/manifests/WPCli.pp
diff --git a/puphpet/puppet/nodes/Xdebug.pp b/puphpet/puppet/manifests/Xdebug.pp
similarity index 90%
rename from puphpet/puppet/nodes/Xdebug.pp
rename to puphpet/puppet/manifests/Xdebug.pp
index 87baff8..aae8b18 100644
--- a/puphpet/puppet/nodes/Xdebug.pp
+++ b/puphpet/puppet/manifests/Xdebug.pp
@@ -6,12 +6,13 @@
   Class['Puphpet::Php::Settings']
   -> Class['Puphpet::Php::Xdebug']
 
-  $version = $php['settings']['version']
+  $version = $puphpet::php::settings::version
   $service = $puphpet::php::settings::service
 
   $compile = $version ? {
     '5.6'   => true,
     '56'    => true,
+    '70'    => true,
     default => false,
   }
 
diff --git a/puphpet/puppet/nodes/Xhprof.pp b/puphpet/puppet/manifests/Xhprof.pp
similarity index 95%
rename from puphpet/puppet/nodes/Xhprof.pp
rename to puphpet/puppet/manifests/Xhprof.pp
index b1fa4bc..b90b03f 100644
--- a/puphpet/puppet/nodes/Xhprof.pp
+++ b/puphpet/puppet/manifests/Xhprof.pp
@@ -14,7 +14,7 @@
     ]
   {
     apt::key { '8D0DC64F':
-      key_server => 'hkp://keyserver.ubuntu.com:80'
+      server => 'hkp://keyserver.ubuntu.com:80'
     }
     apt::ppa { 'ppa:brianmercer/php5-xhprof':
       require => Apt::Key['8D0DC64F']
diff --git a/puphpet/puppet/site.pp b/puphpet/puppet/manifests/site.pp
similarity index 90%
rename from puphpet/puppet/site.pp
rename to puphpet/puppet/manifests/site.pp
index c04bdd1..1919152 100644
--- a/puphpet/puppet/site.pp
+++ b/puphpet/puppet/manifests/site.pp
@@ -1,5 +1,6 @@
 $yaml = merge_yaml(
   '/vagrant/puphpet/config.yaml',
+  "/vagrant/puphpet/config-${::provisioner_type}.yaml",
   '/vagrant/puphpet/config-custom.yaml'
 )
 
@@ -11,8 +12,8 @@
 $elasticsearch  = hiera_hash('elastic_search', {})
 $firewall       = hiera_hash('firewall', {})
 $hhvm           = hiera_hash('hhvm', {})
-$locales        = hiera_hash('locales', {})
-$mailcatcher    = hiera_hash('mailcatcher', {})
+$locales        = hiera_hash('locale', {})
+$mailhog        = hiera_hash('mailhog', {})
 $mariadb        = hiera_hash('mariadb', {})
 $mongodb        = hiera_hash('mongodb', {})
 $mysql          = hiera_hash('mysql', {})
@@ -23,7 +24,7 @@
 $python         = hiera_hash('python', {})
 $rabbitmq       = hiera_hash('rabbitmq', {})
 $redis          = hiera_hash('redis', {})
-$ruby           = hiera_hash('ruby', {})
+$rubyhash       = hiera_hash('ruby', {})
 $server         = hiera_hash('server', {})
 $solr           = hiera_hash('solr', {})
 $sqlite         = hiera_hash('sqlite', {})
@@ -37,8 +38,6 @@
 
 include ::puphpet::params
 
-import 'nodes/*'
-
 if array_true($apache, 'install') {
   class { '::puphpet_apache':
     apache => $apache,
@@ -86,9 +85,9 @@
   }
 }
 
-if array_true($mailcatcher, 'install') {
-  class { '::puphpet_mailcatcher':
-    mailcatcher => $mailcatcher
+if array_true($mailhog, 'install') {
+  class { '::puphpet_mailhog':
+    mailhog => $mailhog
   }
 }
 
@@ -135,8 +134,8 @@
 
 if array_true($php, 'install') {
   class { '::puphpet_php':
-    php         => $php,
-    mailcatcher => $mailcatcher
+    php     => $php,
+    mailhog => $mailhog
   }
 
   if array_true($blackfire, 'install') {
@@ -197,7 +196,7 @@
 }
 
 class { '::puphpet_ruby':
-  ruby => $ruby
+  ruby => $rubyhash
 }
 
 class { '::puphpet_server':
@@ -214,8 +213,7 @@
   }
 }
 
-# puppet manifests for mailcatcher and sqlite are not compatible
-if array_true($sqlite, 'install') and ! array_true($mailcatcher, 'install') {
+if array_true($sqlite, 'install') {
   class { '::puphpet_sqlite':
     sqlite => $sqlite,
     apache => $apache,
diff --git a/puphpet/puppet/modules/apache/.fixtures.yml b/puphpet/puppet/modules/apache/.fixtures.yml
index 6eddf26..4645a75 100644
--- a/puphpet/puppet/modules/apache/.fixtures.yml
+++ b/puphpet/puppet/modules/apache/.fixtures.yml
@@ -1,7 +1,9 @@
 fixtures:
   repositories:
     stdlib: "git://github.com/puppetlabs/puppetlabs-stdlib.git"
-    concat: "git://github.com/puppetlabs/puppetlabs-concat.git"
+    concat:
+      repo: "git://github.com/puppetlabs/puppetlabs-concat.git"
+      branch: "1.2.x"
     portage: "git://github.com/gentoo/puppet-portage.git"
   symlinks:
     apache: "#{source_dir}"
diff --git a/puphpet/puppet/modules/apache/.gitignore b/puphpet/puppet/modules/apache/.gitignore
new file mode 100644
index 0000000..b5db85e
--- /dev/null
+++ b/puphpet/puppet/modules/apache/.gitignore
@@ -0,0 +1,9 @@
+pkg/
+Gemfile.lock
+vendor/
+spec/fixtures/
+.vagrant/
+.bundle/
+coverage/
+.idea/
+*.iml
diff --git a/puphpet/puppet/modules/apache/.sync.yml b/puphpet/puppet/modules/apache/.sync.yml
index 96d3c2b..e5f5f79 100644
--- a/puphpet/puppet/modules/apache/.sync.yml
+++ b/puphpet/puppet/modules/apache/.sync.yml
@@ -1,10 +1,5 @@
 ---
 .travis.yml:
-  extras:
-  - rvm: 1.9.3
-    env: PUPPET_GEM_VERSION="~> 3.5.0" STRICT_VARIABLES="yes"
-  - rvm: 2.0.0
-    env: PUPPET_GEM_VERSION="~> 3.5.0" STRICT_VARIABLES="yes"
 Rakefile:
   extra_disabled_lint_checks:
   - 'disable_only_variable_string'
diff --git a/puphpet/puppet/modules/apache/.travis.yml b/puphpet/puppet/modules/apache/.travis.yml
index bd66c7d..c418ab5 100644
--- a/puphpet/puppet/modules/apache/.travis.yml
+++ b/puphpet/puppet/modules/apache/.travis.yml
@@ -1,21 +1,18 @@
 ---
+sudo: false
 language: ruby
 bundler_args: --without system_tests
 script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake spec SPEC_OPTS='--format documentation'"
 matrix:
   fast_finish: true
   include:
-  - rvm: 1.8.7
-    env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0"
-  - rvm: 1.8.7
-    env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0"
   - rvm: 1.9.3
     env: PUPPET_GEM_VERSION="~> 3.0"
-  - rvm: 2.0.0
+  - rvm: 2.1.5
     env: PUPPET_GEM_VERSION="~> 3.0"
-  - rvm: 1.9.3
-    env: PUPPET_GEM_VERSION="~> 3.5.0" STRICT_VARIABLES="yes"
-  - rvm: 2.0.0
-    env: PUPPET_GEM_VERSION="~> 3.5.0" STRICT_VARIABLES="yes"
+  - rvm: 2.1.5
+    env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes"
+  - rvm: 2.1.6
+    env: PUPPET_GEM_VERSION="~> 4.0" STRICT_VARIABLES="yes"
 notifications:
   email: false
diff --git a/puphpet/puppet/modules/apache/CHANGELOG.md b/puphpet/puppet/modules/apache/CHANGELOG.md
index b6dd08a..737aa45 100644
--- a/puphpet/puppet/modules/apache/CHANGELOG.md
+++ b/puphpet/puppet/modules/apache/CHANGELOG.md
@@ -1,9 +1,112 @@
-##2015-03-17 - Supported Release 1.4.0
+## 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
+#### Features
 - New parameters to `apache`
   - `default_charset`
   - `default_type`
@@ -31,7 +134,7 @@ This release fixes the issue where the docroot was still managed even if the def
 - Added proper array support for `require` in the `directories` parameter in `apache::vhost`
 - Added support for `setenv` inside proxy locations
 
-###Bugfixes
+### 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.
@@ -41,12 +144,12 @@ This release fixes the issue where the docroot was still managed even if the def
 - 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
+## 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
+#### Features
 - New parameters - `apache`
   - `service_manage`
   - `use_optional_includes`
@@ -81,7 +184,7 @@ This release has many new features and bugfixes, including the ability to option
 - Add passenger support for Debian Jessie
 - Add support for not having puppet restart the apache service (MODULES-1559)
 
-####Bugfixes
+#### 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
@@ -100,12 +203,12 @@ This release has many new features and bugfixes, including the ability to option
 - 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
+## 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
+#### Features
 - Convert apache::vhost to use concat for easier extensions
 - Test improvements
 - Synchronize files with modulesync
@@ -168,7 +271,7 @@ This release features many improvements and bugfixes, including several new defi
   - Add apache_version parameter to apache::mod::userdir
   - Add apache::mod::version class
 
-####Bugfixes
+#### Bugfixes
 - Set osfamily defaults for wsgi_socket_prefix
 - Support multiple balancermembers with the same url
 - Validate apache::vhost::custom_fragment
@@ -199,25 +302,25 @@ This release features many improvements and bugfixes, including several new defi
 - Fix RedirectMatch rules
 - Fix misleading error message in apache::version
 
-####Known Bugs
+#### 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
+## 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
+### 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
+#### Features
 
 - Add support for RHEL7 and Ubuntu 14.04
 - More complete apache24 support
@@ -232,7 +335,7 @@ through adding RHEL7 and Ubuntu 14.04 support.  It also includes Passenger
 - Add support for custom extensions for mod_php
 - Improve proxy_html support for Debian
 
-####Bugfixes
+#### Bugfixes
 
 - Remove NameVirtualHost directive for apache >= 2.4
 - Order proxy_set option so it doesn't change between runs
@@ -240,42 +343,42 @@ through adding RHEL7 and Ubuntu 14.04 support.  It also includes Passenger
 - Fix missing ensure on concat::fragment resources
 - Fix bad dependencies in apache::mod and apache::mod::mime
 
-####Known Bugs
+#### 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
+### 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
+#### 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
+### Summary
 
 This is a supported release. This release introduces Apache 2.4 support for
 Debian and RHEL based osfamilies.
 
-####Features
+#### Features
 
 - Add apache24 support
 - Add rewrite_base functionality to rewrites
 - Updated README documentation
 - Add WSGIApplicationGroup and WSGIImportScript directives
 
-####Bugfixes
+#### Bugfixes
 
 - Replace mutating hashes with merge() for Puppet 3.5
 - Fix WSGI import_script and mod_ssl issues on Lucid
 
-####Known Bugs
+#### Known Bugs
 * By default, the version of Apache that ships with Ubuntu 10.04 does not work with `wsgi_import_script`.
 * SLES is unsupported.
 
@@ -457,7 +560,7 @@ worker/prefork
 - Fix formatting in vhost template
 - Fix spec tests such that they pass
 
-##2012-05-08 Puppet Labs  - 0.0.4
+## 2012-05-08 Puppet Labs  - 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
diff --git a/puphpet/puppet/modules/apache/Gemfile b/puphpet/puppet/modules/apache/Gemfile
index 62c5693..bfe64b1 100644
--- a/puphpet/puppet/modules/apache/Gemfile
+++ b/puphpet/puppet/modules/apache/Gemfile
@@ -1,21 +1,38 @@
 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',                    :require => false
   gem 'rspec-core', '3.1.7',     :require => false
-  gem 'rspec-puppet', '~> 1.0',  :require => false
   gem 'puppetlabs_spec_helper',  :require => false
-  gem 'puppet-lint',             :require => false
   gem 'simplecov',               :require => false
   gem 'puppet_facts',            :require => false
   gem 'json',                    :require => false
 end
 
 group :system_tests do
-  gem 'beaker-rspec',  :require => false
+  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
diff --git a/puphpet/puppet/modules/apache/README.md b/puphpet/puppet/modules/apache/README.md
index ee88972..15565ed 100644
--- a/puphpet/puppet/modules/apache/README.md
+++ b/puphpet/puppet/modules/apache/README.md
@@ -1,535 +1,1232 @@
-#apache
-
-####Table of Contents
-
-1. [Overview - What is the apache module?](#overview)
-2. [Module Description - What does the module do?](#module-description)
-3. [Setup - The basics of getting started with apache](#setup)
-    * [Beginning with apache - Installation](#beginning-with-apache)
-    * [Configure a virtual host - Basic options for getting started](#configure-a-virtual-host)
-4. [Usage - The classes and defined types available for configuration](#usage)
-    * [Classes and Defined Types](#classes-and-defined-types)
-        * [Class: apache](#class-apache)
-        * [Defined Type: apache::custom_config](#defined-type-apachecustom_config)
-        * [Class: apache::default_mods](#class-apachedefault_mods)
-        * [Defined Type: apache::mod](#defined-type-apachemod)
-        * [Classes: apache::mod::*](#classes-apachemodname)
-        * [Class: apache::mod::alias](#class-apachemodalias)
-        * [Class: apache::mod::event](#class-apachemodevent)
-        * [Class: apache::mod::info](#class-apachemodinfo)
-        * [Class: apache::mod::pagespeed](#class-apachemodpagespeed)
-        * [Class: apache::mod::php](#class-apachemodphp)
-        * [Class: apache::mod::ssl](#class-apachemodssl)
-        * [Class: apache::mod::status](#class-apachemodstatus)
-        * [Class: apache::mod::wsgi](#class-apachemodwsgi)
-        * [Class: apache::mod::fcgid](#class-apachemodfcgid)
-        * [Class: apache::mod::negotiation](#class-apachemodnegotiation)
-        * [Class: apache::mod::deflate](#class-apachemoddeflate)
-        * [Class: apache::mod::reqtimeout](#class-apachemodreqtimeout)
-        * [Class: apache::mod::security](#class-modsecurity)
-        * [Class: apache::mod::version](#class-apachemodversion)
-        * [Defined Type: apache::vhost](#defined-type-apachevhost)
-        * [Parameter: `directories` for apache::vhost](#parameter-directories-for-apachevhost)
-        * [SSL parameters for apache::vhost](#ssl-parameters-for-apachevhost)
-        * [Defined Type: apache::fastcgi::server](#defined-type-fastcgi-server)
-    * [Virtual Host Examples - Demonstrations of some configuration options](#virtual-host-examples)
-    * [Load Balancing](#load-balancing)
-        * [Defined Type: apache::balancer](#defined-type-apachebalancer)
-        * [Defined Type: apache::balancermember](#defined-type-apachebalancermember)
-        * [Examples - Load balancing with exported and non-exported resources](#examples)
-5. [Reference - An under-the-hood peek at what the module is doing and how](#reference)
-    * [Classes](#classes)
-        * [Public Classes](#public-classes)
-        * [Private Classes](#private-classes)
-    * [Defined Types](#defined-types)
-        * [Public Defined Types](#public-defined-types)
-        * [Private Defined Types](#private-defined-types)
-    * [Templates](#templates)
-6. [Limitations - OS compatibility, etc.](#limitations)
-7. [Development - Guide for contributing to the module](#development)
-    * [Contributing to the apache module](#contributing)
-    * [Running tests - A quick guide](#running-tests)
-
-##Overview
-
-The apache module allows you to set up virtual hosts and manage web services with minimal effort.
-
-##Module Description
-
-Apache is a widely-used web server, and this module provides a simplified way of creating configurations to manage your infrastructure. This includes the ability to configure and manage a range of different virtual host setups, as well as a streamlined way to install and configure Apache modules.
-
-##Setup
-
-**What apache affects:**
-
-* configuration files and directories (created and written to)
-    * **WARNING**: Configurations that are *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
-* depends on module 'gentoo/puppet-portage' for Gentoo
-
-###Beginning with Apache
-
-To install Apache with the default parameters
-
-```puppet
-    class { 'apache':  }
-```
-
-The defaults are determined by your operating system (e.g. Debian systems have one set of defaults, and RedHat systems have another, as do FreeBSD and Gentoo systems). These defaults work well in a testing environment, but are not suggested for production. To establish customized parameters
-
-```puppet
-    class { 'apache':
-      default_mods        => false,
-      default_confd_files => false,
-    }
-```
+# 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::`]: #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,
+}
+~~~
 
-###Configure a virtual host
+## Usage
 
-Declaring the `apache` class creates a default virtual host by setting up a vhost on port 80, listening on all interfaces and serving `$apache::docroot`.
+### Configuring a virtual host
 
-```puppet
-    class { 'apache': }
-```
+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`.
 
-To configure a very basic, name-based virtual host
+**Note**: See the [`apache::vhost`][] define's reference for a list of all virtual host parameters.
 
-```puppet
-    apache::vhost { 'first.example.com':
-      port    => '80',
-      docroot => '/var/www/first',
-    }
-```
+To configure basic [name-based virtual hosts][], specify the [`port`][] and [`docroot`][] parameters in the [`apache::vhost`][] define:
 
-*Note:* The default priority is 15. If nothing matches this priority, the alphabetically first name-based vhost is used. This is also true if you pass a higher priority and no names match anything else.
+~~~ puppet
+apache::vhost { 'vhost.example.com':
+  port    => '80',
+  docroot => '/var/www/vhost',
+}
+~~~
 
-A slightly more complicated example, changes the docroot owner/group from the default 'root'
+**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.
 
-```puppet
-    apache::vhost { 'second.example.com':
-      port          => '80',
-      docroot       => '/var/www/second',
-      docroot_owner => 'third',
-      docroot_group => 'third',
-    }
-```
+To configure user and group ownership for `docroot`, use the [`docroot_owner`][] and [`docroot_group`][] parameters:
 
-To set up a virtual host with SSL and default SSL certificates
+~~~ puppet
+apache::vhost { 'user.example.com':
+  port          => '80',
+  docroot       => '/var/www/user',
+  docroot_owner => 'www-data',
+  docroot_group => 'www-data',
+}
+~~~
 
-```puppet
-    apache::vhost { 'ssl.example.com':
-      port    => '443',
-      docroot => '/var/www/ssl',
-      ssl     => true,
-    }
-```
+#### Configuring virtual hosts with SSL
 
-To set up a virtual host with SSL and specific SSL certificates
+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 { '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',
-    }
-```
+~~~ puppet
+apache::vhost { 'ssl.example.com':
+  port    => '443',
+  docroot => '/var/www/ssl',
+  ssl     => true,
+}
+~~~
 
-Virtual hosts listen on '*' by default. To listen on a specific IP address
+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 { 'subdomain.example.com':
-      ip      => '127.0.0.1',
-      port    => '80',
-      docroot => '/var/www/subdomain',
-    }
-```
+~~~ 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 set up a virtual host with a wildcard alias for the subdomain mapped to a same-named directory, for example: `http://example.com.loc` to `/var/www/example.com`
+To configure a mix of SSL and unencrypted virtual hosts at the same domain, declare them with separate [`apache::vhost`] defines:
 
-```puppet
-    apache::vhost { 'subdomain.loc':
-      vhost_name       => '*',
-      port             => '80',
-      virtual_docroot  => '/var/www/%-2+',
-      docroot          => '/var/www',
-      serveraliases    => ['*.loc',],
-    }
-```
+~~~ puppet
+# The non-ssl virtual host
+apache::vhost { 'mix.example.com non-ssl':
+  servername => 'mix.example.com',
+  port       => '80',
+  docroot    => '/var/www/mix',
+}
 
-To set up a virtual host with suPHP
+# 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,
+}
+~~~
 
-```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' },
-      }
-    }
-```
+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:
 
-To set up a virtual host with WSGI
+~~~ 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/'
+}
 
-```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' },
-    }
-```
+apache::vhost { 'redirect.example.com ssl':
+  servername => 'redirect.example.com',
+  port       => '443',
+  docroot    => '/var/www/redirect',
+  ssl        => true,
+}
+~~~
 
-Starting in Apache 2.2.16, HTTPD supports [FallbackResource](https://httpd.apache.org/docs/current/mod/mod_dir.html#fallbackresource), a simple replacement for common RewriteRules.
+#### Configuring virtual host port and address bindings
 
-```puppet
-    apache::vhost { 'wordpress.example.com':
-      port                => '80',
-      docroot             => '/var/www/wordpress',
-      fallbackresource    => '/index.php',
-    }
-```
+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',
+}
 
-Please note that the 'disabled' argument to FallbackResource is only supported since Apache 2.2.24.
+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::`][] 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::`][] 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::`][].
+
+#### 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:
 
-See a list of all [virtual host parameters](#defined-type-apachevhost). See an extensive list of [virtual host examples](#virtual-host-examples).
+~~~ 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:
 
-##Usage
+~~~ puppet
+apache::balancer { 'puppet00': }
+~~~
 
-###Classes and Defined Types
+To enable load balancing without exporting resources, declare the following on the proxy server:
 
-This module modifies Apache configuration files and directories and purges any configuration not managed by Puppet. Configuration of Apache should be managed by Puppet, as non-Puppet configuration files can cause unexpected failures.
+~~~ puppet
+apache::balancer { 'puppet00': }
 
-It is possible to temporarily disable full Puppet management by setting the [`purge_configs`](#purge_configs) parameter within the base `apache` class to 'false'. This option should only be used as a temporary means of saving and relocating customized configurations. See the [`purge_configs` parameter](#purge_configs) for more information.
+apache::balancermember { "${::fqdn}-puppet00":
+    balancer_cluster => 'puppet00',
+    url              => "ajp://${::fqdn}:8009",
+    options          => ['ping=5', 'disablereuse=on', 'retry=5', 'ttl=120'],
+  }
+~~~
 
-####Class: `apache`
+Then declare the `apache::balancer` and `apache::balancermember` defines on the proxy server.
 
-The apache module's primary class, `apache`, guides the basic setup of Apache on your system.
+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`:
 
-You can establish a default vhost in this class, the `vhost` class, or both. You can add additional vhost configurations for specific virtual hosts using a declaration of the `vhost` type.
+~~~ 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`
+##### `allow_encoded_slashes`
 
-This sets the server default for the [`AllowEncodedSlashes` declaration](http://httpd.apache.org/docs/current/mod/core.html#allowencodedslashes) which modifies the responses to URLs with `\` and `/` characters. The default is undefined, which omits the declaration from the server configuration and select the Apache default setting of `Off`. Allowed values are: `on`, `off` or `nodecode`.
+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`
+##### `apache_version`
 
-Configures the behavior of the module templates, package names, and default mods by setting the Apache version. Default is determined by the class `apache::version` using the OS family and release. It should not be configured manually without special reason.
+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`
+##### `conf_dir`
 
-Changes the location of the configuration directory the main configuration file is placed in. Defaults to '/etc/httpd/conf' on RedHat, '/etc/apache2' on Debian, '/usr/local/etc/apache22' on FreeBSD, and '/etc/apache2' on Gentoo.
+Sets the directory where the Apache server's main configuration file is located. Default: Depends on your operating system.
 
-#####`confd_dir`
+- **Debian**: `/etc/apache2`
+- **FreeBSD**: `/usr/local/etc/apache22`
+- **Gentoo**: `/etc/apache2`
+- **Red Hat**: `/etc/httpd/conf`
 
-Changes the location of the configuration directory your custom configuration files are placed in. Defaults to '/etc/httpd/conf' on RedHat, '/etc/apache2/conf.d' on Debian, '/usr/local/etc/apache22' on FreeBSD, and '/etc/apache2/conf.d' on Gentoo.
+##### `conf_template`
 
-#####`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.
 
-Overrides the template used for the main apache configuration file. Defaults to 'apache/httpd.conf.erb'.
+##### `confd_dir`
 
-*Note:* Using this parameter is potentially risky, as the module has been built for a minimal configuration file with the configuration primarily coming from conf.d/ entries.
+Sets the location of the Apache server's custom configuration directory. Default: Depends on your operating system.
 
-#####`default_charset`
+- **Debian**: `/etc/apache2/conf.d`
+- **FreeBSD**: `/usr/local/etc/apache22`
+- **Gentoo**: `/etc/apache2/conf.d`
+- **Red Hat**: `/etc/httpd/conf.d`
 
-If defined, the value will be set as `AddDefaultCharset` in the main configuration file. It is undefined by default.
+##### `default_charset`
 
-#####`default_confd_files`
+Used as the [`AddDefaultCharset`][] directive in the main configuration file. Default: 'undef'.
 
-Generates default set of include-able Apache configuration files under  `${apache::confd_dir}` directory. These configuration files correspond to what is usually installed with the Apache package on a given platform.
+##### `default_confd_files`
 
-#####`default_mods`
+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'.
 
-Sets up Apache with default settings based on your OS. Valid values are 'true', 'false', or an array of mod names.
+##### `default_mods`
 
-Defaults to 'true', which includes the default [HTTPD mods](https://github.com/puppetlabs/puppetlabs-apache/blob/master/manifests/default_mods.pp).
+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 false, it only includes the mods required to make HTTPD work, and any other mods can be declared on their own.
+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::`][] class or [`apache::mod`][] define.
 
-If an array, the apache module includes the array of mods listed.
+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.
 
-#####`default_ssl_ca`
+If this parameter contains an array, Puppet instead enables all passed Apache modules.
 
-The default certificate authority, which is automatically set to 'undef'. This default works out of the box but must be updated with your specific certificate information before being used in production.
+##### `default_ssl_ca`
 
-#####`default_ssl_cert`
+Sets the default certificate authority for the Apache server. Default: 'undef'.
 
-The default SSL certification, which is automatically set based on your operating system  ('/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' for Gentoo). This default works out of the box but must be updated with your specific certificate information before being used in production.
+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_chain`
+##### `default_ssl_cert`
 
-The default SSL chain, which is automatically set to 'undef'. This default works out of the box but must be updated with your specific certificate information before being used in production.
+Sets the [SSL encryption][] certificate location. Default: Determined by your operating system.
 
-#####`default_ssl_crl`
+- **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`
 
-The default certificate revocation list to use, which is automatically set to 'undef'. This default works out of the box but must be updated with your specific certificate information before being used in production.
+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_crl_path`
+##### `default_ssl_chain`
 
-The default certificate revocation list path, which is automatically set to 'undef'. This default works out of the box but must be updated with your specific certificate information before being used in production.
+Sets the default [SSL chain][] location. Default: 'undef'.
 
-#####`default_ssl_crl_check`
+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.
 
-Sets the default certificate revocation check level via the [SSLCARevocationCheck directive](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcarevocationcheck), which is automatically set 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.
+##### `default_ssl_crl`
 
-#####`default_ssl_key`
+Sets the path of the default [certificate revocation list][] (CRL) file to use. Default: 'undef'.
 
-The default SSL key, which is automatically set 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' for Gentoo). This default works out of the box but must be updated with your specific certificate information before being used in production.
+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_vhost`
+##### `default_ssl_crl_path`
 
-Sets up a default SSL virtual host. Defaults to 'false'. If set to 'true', sets up the following vhost:
+Sets the server's [certificate revocation list path][], which contains your CRLs. Default: 'undef'.
 
-```puppet
-    apache::vhost { 'default-ssl':
-      port            => 443,
-      ssl             => true,
-      docroot         => $docroot,
-      scriptalias     => $scriptalias,
-      serveradmin     => $serveradmin,
-      access_log_file => "ssl_${access_log_file}",
-      }
-```
+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.
 
-SSL vhosts only respond to HTTPS queries.
+##### `default_ssl_crl_check`
 
-#####`default_type`
+Sets the default certificate revocation check level via the [`SSLCARevocationCheck`][] directive. Default: 'undef'.
 
-(Apache httpd 2.2 only) MIME content-type that will be sent if the server cannot determine a type in any other way. This directive has been deprecated in Apache httpd 2.4, and only exists there for backwards compatibility of configuration files.
+While this default value results in a functioning Apache server, you **must** specify this parameter when using certificate revocation lists in a production environment.
 
-#####`default_vhost`
+This parameter only applies to Apache 2.4 or higher and is ignored on older versions.
 
-Sets up a default virtual host. Defaults to 'true', set to 'false' to set up [customized virtual hosts](#configure-a-virtual-host).
+##### `default_ssl_key`
 
-#####`docroot`
+Sets the [SSL certificate key file][] location. Default: Determined by your operating system.
 
-Changes the location of the default [Documentroot](https://httpd.apache.org/docs/current/mod/core.html#documentroot). Defaults to '/var/www/html' on RedHat, '/var/www' on Debian, '/usr/local/www/apache22/data' on FreeBSD, and '/var/www/localhost/htdocs' on Gentoo.
+- **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`
 
-#####`error_documents`
+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.
 
-Enables custom error documents. Defaults to 'false'.
+##### `default_ssl_vhost`
 
-#####`httpd_dir`
+Configures a default [SSL][SSL encryption] virtual host. Valid options: Boolean. Default: 'false'.
 
-Changes the base location of the configuration directories used for the apache service. This is useful for specially repackaged HTTPD builds, but might have unintended consequences when used in combination with the default distribution packages. Defaults to '/etc/httpd' on RedHat, '/etc/apache2' on Debian, '/usr/local/etc/apache22' on FreeBSD, and '/etc/apache2' on Gentoo.
+If 'true', Puppet automatically configures the following virtual host using the [`apache::vhost`][] define:
 
-#####`keepalive`
+~~~ puppet
+apache::vhost { 'default-ssl':
+  port            => 443,
+  ssl             => true,
+  docroot         => $docroot,
+  scriptalias     => $scriptalias,
+  serveradmin     => $serveradmin,
+  access_log_file => "ssl_${access_log_file}",
+  }
+~~~
 
-Enables persistent connections.
+**Note**: SSL virtual hosts only respond to HTTPS queries.
 
-#####`keepalive_timeout`
+##### `default_type`
 
-Sets the amount of time the server waits for subsequent requests on a persistent connection. Defaults to '15'.
+_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'.
 
-#####`max_keepalive_requests`
+##### `default_vhost`
 
-Sets the limit of the number of requests allowed per connection when KeepAlive is on. Defaults to '100'.
+Configures a default virtual host when the class is declared. Valid options: Boolean. Default: 'true'.
 
-#####`loadfile_name`
+To configure [customized virtual hosts][Configuring virtual hosts], set this parameter's value to 'false'.
 
-Sets the file name for the module loadfile. Should be in the format *.load.  This can be used to set the module load order.
+##### `dev_packages`
 
-#####`log_level`
+Configures a specific dev package to use. Valid options: String.  Default: 'OS default httpd dev package'.
 
-Changes the verbosity level of the error log. Defaults to 'warn'. Valid values are 'emerg', 'alert', 'crit', 'error', 'warn', 'notice', 'info', or 'debug'.
+Example for using httpd 2.4 from the IUS yum repo:
 
-#####`log_formats`
+~~~ puppet
+include ::apache::dev
+class { 'apache':
+  apache_name  => 'httpd24u',
+  dev_packages => 'httpd24u-devel',
+}
+~~~
 
-Define additional [LogFormats](https://httpd.apache.org/docs/current/mod/mod_log_config.html#logformat). This is done in a Hash:
+##### `docroot`
 
-```puppet
-  $log_formats = { vhost_common => '%v %h %l %u %t \"%r\" %>s %b' }
-```
+Sets the default [`DocumentRoot`][] location. Default: Determined by your operating system.
 
-#####`logroot`
+- **Debian**: `/var/www/html`
+- **FreeBSD**: `/usr/local/www/apache22/data`
+- **Gentoo**: `/var/www/localhost/htdocs`
+- **Red Hat**: `/var/www/html`
 
-Changes the directory where Apache log files for the virtual host are placed. Defaults to '/var/log/httpd' on RedHat, '/var/log/apache2' on Debian, '/var/log/apache22' on FreeBSD, and '/var/log/apache2' on Gentoo.
+##### `error_documents`
 
-#####`logroot_mode`
+Determines whether to enable [custom error documents][] on the Apache server. Valid options: Boolean. Default: 'false'.
 
-Overrides the mode the default logroot directory is set to ($::apache::logroot). 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.
+##### `group`
 
-#####`manage_group`
+Sets the group ID that owns any Apache processes spawned to answer requests.
 
-Setting this to 'false' stops the group resource from being created. This is for when you have a group, created from another Puppet module, you want to use to run Apache. Without this parameter, attempting to use a previously established group would result in a duplicate resource error.
+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'.
 
-#####`manage_user`
+**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.
 
-Setting this to 'false' stops the user resource from being created. 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.
+##### `httpd_dir`
 
-#####`mod_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.
 
-Changes the location of the configuration directory your Apache modules configuration files are placed in. Defaults to '/etc/httpd/conf.d' for RedHat, '/etc/apache2/mods-available' for Debian, '/usr/local/etc/apache22/Modules' for FreeBSD, and '/etc/apache2/modules.d' on Gentoo.
+- **Debian**: `/etc/apache2`
+- **FreeBSD**: `/usr/local/etc/apache22`
+- **Gentoo**: `/etc/apache2`
+- **Red Hat**: `/etc/httpd`
 
-#####`mpm_module`
+##### `keepalive`
 
-Determines which MPM is loaded and configured for the HTTPD process. Valid values are 'event', 'itk', 'peruser', 'prefork', 'worker', or 'false'. Defaults to 'prefork' on RedHat, FreeBSD and Gentoo, and 'worker' on Debian. Must be set to 'false' to explicitly declare the following classes with custom parameters:
+Determines whether to enable persistent HTTP connections with the [`KeepAlive`][] directive. Valid options: 'Off', 'On'. Default: 'Off'.
 
-* `apache::mod::event`
-* `apache::mod::itk`
-* `apache::mod::peruser`
-* `apache::mod::prefork`
-* `apache::mod::worker`
+If 'On', use the [`keepalive_timeout`][] and [`max_keepalive_requests`][] parameters to set relevant options.
 
-*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 currently-installed Apache.
+##### `keepalive_timeout`
 
-#####`package_ensure`
+Sets the [`KeepAliveTimeout`] directive, which determines the amount of time the Apache server waits for subsequent requests on a persistent HTTP connection. Default: '15'.
 
-Allows control over the package ensure attribute. Can be 'present','absent', or a version string.
+This parameter is only relevant if the [`keepalive` parameter][] is enabled.
 
-#####`ports_file`
+##### `max_keepalive_requests`
 
-Changes the name of the file containing Apache ports configuration. Default is `${conf_dir}/ports.conf`.
+Limits the number of requests allowed per connection when the [`keepalive` parameter][] is enabled. Default: '100'.
 
-#####`purge_configs`
+##### `lib_path`
 
-Removes all other Apache configs and vhosts, defaults to 'true'. Setting this to 'false' is a stopgap measure to allow the apache module to coexist with existing or otherwise-managed configuration. It is recommended that you move your configuration entirely to resources within this module.
+Specifies the location where [Apache module][Apache modules] files are stored. Default: Depends on the operating system.
 
-#####`purge_vhost_configs`
+- **Debian** and **Gentoo**: `/usr/lib/apache2/modules`
+- **FreeBSD**: `/usr/local/libexec/apache24`
+- **Red Hat**: `modules`
 
-If `vhost_dir` != `confd_dir`, this controls the removal of any configurations that are not managed by Puppet within `vhost_dir`. It defaults to the value of `purge_configs`. Setting this to false is a stopgap measure to allow the apache module to coexist with existing or otherwise unmanaged configurations within `vhost_dir`
+**Note**: Do not configure this parameter manually without special reason.
 
-#####`sendfile`
+##### `loadfile_name`
 
-Makes Apache use the Linux kernel sendfile to serve static files. Defaults to 'On'.
+Sets the [`LoadFile`] directive's filename. Valid options: Filenames in the format `\*.load`.
 
-#####`serveradmin`
+This can be used to set the module load order.
 
-Sets the server administrator. Defaults to 'root@localhost'.
+##### `log_level`
 
-#####`servername`
+Changes the error log's verbosity. Valid options: 'alert', 'crit', 'debug', 'emerg', 'error', 'info', 'notice', 'warn'. Default: 'warn'.
 
-Sets the server name. Defaults to `fqdn` provided by Facter.
+##### `log_formats`
 
-#####`server_root`
+Define additional [`LogFormat`][] directives. Valid options: A [Hash][], such as:
 
-Sets the root directory in which the server resides. Defaults to '/etc/httpd' on RedHat, '/etc/apache2' on Debian, '/usr/local' on FreeBSD, and '/var/www' on Gentoo.
+~~~ puppet
+$log_formats = { vhost_common => '%v %h %l %u %t \"%r\" %>s %b' }
+~~~
 
-#####`server_signature`
+There are a number of predefined `LogFormats` in the `httpd.conf` that Puppet creates:
 
-Configures a trailing footer line under server-generated documents. More information about [ServerSignature](http://httpd.apache.org/docs/current/mod/core.html#serversignature). Defaults to 'On'.
+~~~ 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
+~~~
 
-#####`server_tokens`
+If your `log_formats` parameter contains one of those, it will be overwritten with **your** definition.
 
-Controls how much information Apache sends to the browser about itself and the operating system. More information about [ServerTokens](http://httpd.apache.org/docs/current/mod/core.html#servertokens). Defaults to 'OS'.
+##### `logroot`
 
-#####`service_enable`
+Changes the directory of Apache log files for the virtual host. Default: Determined by your operating system.
 
-Determines whether the HTTPD service is enabled when the machine is booted. Defaults to 'true'.
+- **Debian**: `/var/log/apache2`
+- **FreeBSD**: `/var/log/apache22`
+- **Gentoo**: `/var/log/apache2`
+- **Red Hat**: `/var/log/httpd`
 
-#####`service_ensure`
+##### `logroot_mode`
 
-Determines whether the service should be running. Valid values are 'true', 'false', 'running', or 'stopped' when Puppet should manage the service. Any other value sets ensure to 'false' for the Apache service, which is useful when you want to let the service be managed by some other application like Pacemaker. Defaults to 'running'.
+Overrides the default [`logroot`][] directory's mode. Default: 'undef'.
 
-#####`service_name`
+**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.
 
-Name of the Apache service to run. Defaults to: 'httpd' on RedHat, 'apache2' on Debian and Gentoo, and 'apache22' on FreeBSD.
+##### `manage_group`
 
-#####`service_manage`
+When 'false', stops Puppet from creating the group resource. Valid options: Boolean. Default: 'true'.
 
-Determines whether the HTTPD service state is managed by Puppet . Defaults to '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.
 
-#####`trace_enable`
+##### `manage_user`
 
-Controls how TRACE requests per RFC 2616 are handled. More information about [TraceEnable](http://httpd.apache.org/docs/current/mod/core.html#traceenable). Defaults to 'On'.
+When 'false', stops Puppet from creating the user resource. Valid options: Boolean. Default: 'true'.
 
-#####`vhost_dir`
+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.
 
-Changes the location of the configuration directory your virtual host configuration files are placed in. Defaults to 'etc/httpd/conf.d' on RedHat, '/etc/apache2/sites-available' on Debian, '/usr/local/etc/apache22/Vhosts' on FreeBSD, and '/etc/apache2/vhosts.d' on Gentoo.
+##### `mod_dir`
 
-#####`apache_name`
+Sets where Puppet places configuration files for your [Apache modules][]. Default: Determined by your operating system.
 
-The name of the Apache package to install. This is automatically detected in `::apache::params`. You might need to override this if you are using a non-standard Apache package, such as those from Red Hat's software collections.
+- **Debian**: `/etc/apache2/mods-available`
+- **FreeBSD**: `/usr/local/etc/apache22/Modules`
+- **Gentoo**: `/etc/apache2/modules.d`
+- **Red Hat**: `/etc/httpd/conf.d`
 
-####Defined Type: `apache::custom_config`
+##### `mpm_module`
 
-Allows you to create custom configs for Apache. The configuration files are only added to the Apache confd dir if the file is valid. An error is raised during the Puppet run if the file is invalid and `$verify_config` is `true`.
+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.
 
-```puppet
-    apache::custom_config { 'test':
-        content => '# Test',
-    }
-```
+- **Debian**: `worker`
+- **FreeBSD, Gentoo, and Red Hat**: `prefork`
 
-**Parameters within `apache::custom_config`:**
+You must set this to 'false' to explicitly declare the following classes with custom parameters:
 
-#####`ensure`
+- [`apache::mod::event`][]
+- [`apache::mod::itk`][]
+- [`apache::mod::peruser`][]
+- [`apache::mod::prefork`][]
+- [`apache::mod::worker`][]
 
-Specify whether the configuration file is present or absent. Defaults to 'present'. Valid values are 'present' and 'absent'.
+**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.
 
-#####`confdir`
+##### `package_ensure`
 
-The directory to place the configuration file in. Defaults to `$::apache::confd_dir`.
+Controls the `package` resource's [`ensure`][] attribute. Valid options: 'absent', 'installed' (or the equivalent 'present'), or a version string. Default: 'installed'.
 
-#####`content`
+##### `pidfile`
 
-The content of the configuration file. Only one of `$content` and `$source` can be specified.
+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.
 
-#####`priority`
+##### `ports_file`
 
-The priority of the configuration file, used for ordering. Defaults to '25'.
+Sets the path to the file containing Apache ports configuration. Default: `{$conf_dir}/ports.conf`.
 
-Pass priority `false` to omit the priority prefix in file names.
+##### `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`
 
-#####`source`
+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'.
 
-The source of the configuration file. Only one of `$content` and `$source` can be specified.
+This parameter only applies to Apache version 2.2 or lower and is ignored on newer versions.
 
-#####`verify_command`
+##### `sendfile`
 
-The command to use to verify the configuration file. It should use a fully qualified command. Defaults to '/usr/sbin/apachectl -t'. The `$verify_command` is only used if `$verify_config` is `true`. If the `$verify_command` fails, the configuration file is deleted, the Apache service is not notified, and an error is raised during the Puppet run.
+Forces Apache to use the Linux kernel's `sendfile` support to serve static files, via the [`EnableSendfile`][] directive. Valid options: 'On', 'Off'. Default: 'On'.
 
-#####`verify_config`
+##### `serveradmin`
 
-Boolean to specify whether the configuration file should be validated before the Apache service is notified. Defaults to `true`.
+Sets the Apache server administrator's contact information via Apache's [`ServerAdmin`][] directive. Default: 'root@localhost'.
 
-####Class: `apache::default_mods`
+##### `servername`
 
-Installs default Apache modules based on what OS you are running.
+Sets the Apache server name via Apache's [`ServerName`][] directive. Default: the 'fqdn' fact reported by [Facter][].
 
-```puppet
-    class { 'apache::default_mods': }
-```
+##### `server_root`
 
-####Defined Type: `apache::mod`
+Sets the Apache server's root directory via Apache's [`ServerRoot`][] directive. Default: determined by your operating system.
 
-Used to enable arbitrary Apache HTTPD modules for which there is no specific `apache::mod::[name]` class. The `apache::mod` defined type also installs the required packages to enable the module, if any.
+- **Debian**: `/etc/apache2`
+- **FreeBSD**: `/usr/local`
+- **Gentoo**: `/var/www`
+- **Red Hat**: `/etc/httpd`
 
-```puppet
-    apache::mod { 'rewrite': }
-    apache::mod { 'ldap': }
-```
+##### `server_signature`
 
-####Classes: `apache::mod::[name]`
+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'.
 
-There are many `apache::mod::[name]` classes within this module that can be declared using `include`:
+##### `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::`
+
+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`](#class-apachemodalias) below)
+* `alias` (see [`apache::mod::alias`][])
 * `auth_basic`
-* `auth_cas`* (see [`apache::mod::auth_cas`](#class-apachemodauthcas) below)
+* `auth_cas`* (see [`apache::mod::auth_cas`][])
+* `auth_mellon`* (see [`apache::mod::auth_mellon`][])
 * `auth_kerb`
+* `authn_core`
 * `authn_file`
 * `authnz_ldap`*
 * `authz_default`
@@ -544,12 +1241,14 @@ There are many `apache::mod::[name]` classes within this module that can be decl
 * `deflate`
 * `dev`
 * `dir`*
-* `disk_cache`
-* `event`(see [`apache::mod::event`](#class-apachemodevent) below)
+* `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`*
@@ -559,11 +1258,11 @@ There are many `apache::mod::[name]` classes within this module that can be decl
 * `mime_magic`*
 * `negotiation`
 * `nss`*
-* `pagespeed` (see [`apache::mod::pagespeed`](#class-apachemodpagespeed) below)
+* `pagespeed` (see [`apache::mod::pagespeed`][])
 * `passenger`*
 * `perl`
 * `peruser`
-* `php` (requires [`mpm_module`](#mpm_module) set to `prefork`)
+* `php` (requires [`mpm_module`][] set to `prefork`)
 * `prefork`*
 * `proxy`*
 * `proxy_ajp`
@@ -572,745 +1271,922 @@ There are many `apache::mod::[name]` classes within this module that can be decl
 * `proxy_http`
 * `python`
 * `reqtimeout`
+* `remoteip`*
 * `rewrite`
 * `rpaf`*
 * `setenvif`
 * `security`
-* `shib`* (see [`apache::mod::shib`](#class-apachemodshib) below)
+* `shib`* (see [`apache::mod::shib`])
 * `speling`
-* `ssl`* (see [`apache::mod::ssl`](#class-apachemodssl) below)
-* `status`* (see [`apache::mod::status`](#class-apachemodstatus) below)
+* `ssl`* (see [`apache::mod::ssl`][])
+* `status`* (see [`apache::mod::status`][])
 * `suphp`
 * `userdir`*
+* `version`
 * `vhost_alias`
 * `worker`*
-* `wsgi` (see [`apache::mod::wsgi`](#class-apachemodwsgi) below)
+* `wsgi` (see [`apache::mod::wsgi`][])
 * `xsendfile`
 
-Modules noted with a * indicate that the module has settings and, thus, a template that includes parameters. These parameters control the module's configuration. Most of the time, these parameters do not require any configuration or attention.
+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.
 
-The modules mentioned above, and other Apache modules that have templates, cause template files to be dropped along with the mod install. The module will not work without the template. Any module without a template installs the package but drops no files.
+##### Class: `apache::mod::alias`
 
-###Class: `apache::mod::alias`
+Installs and manages [`mod_alias`][].
 
-Installs and manages the alias module.
+**Parameters within `apache::mod::alias`**:
 
-Full Documentation for alias is available from [Apache](https://httpd.apache.org/docs/current/mod/mod_alias.html).
+* `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.
 
-To disable directory listing for the icons directory:
-```puppet
-  class { 'apache::mod::alias':
-    icons_options => 'None',
-  }
-```
+- **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::event`
+#### Class: `apache::mod::disk_cache`
 
-Installs and manages mpm_event module.
+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: 
 
-Full Documentation for mpm_event is available from [Apache](https://httpd.apache.org/docs/current/mod/event.html).
+- **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`
 
-To configure the event thread limit:
+You can specify the cache root by passing a path as a string to the `cache_root` parameter.
 
-```puppet
-  class {'apache::mod::event':
-    $threadlimit      => '128',
-  }
-```
+~~~ puppet
+class {'::apache::mod::disk_cache':
+  cache_root => '/path/to/cache',
+}
+~~~
 
-####Class: `apache::mod::auth_cas`
+##### Class: `apache::mod::event`
 
-Installs and manages mod_auth_cas. The parameters `cas_login_url` and `cas_validate_url` are required.
+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.
 
-Full documentation on mod_auth_cas is available from [JASIG](https://github.com/Jasig/mod_auth_cas).
+**Parameters within `apache::mod::event`**:
 
-####Class: `apache::mod::info`
+- `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'.
 
-Installs and manages mod_info which provides a comprehensive overview of the server configuration.
+##### Class: `apache::mod::auth_cas`
 
-Full documentation for mod_info is available from [Apache](https://httpd.apache.org/docs/current/mod/mod_info.html).
+Installs and manages [`mod_auth_cas`][]. Its parameters share names with the Apache module's directives.
 
-These are the default settings:
+The `cas_login_url` and `cas_validate_url` parameters are required; several other parameters have 'undef' default values.
 
-```puppet
-  $allow_from      = ['127.0.0.1','::1'],
-  $apache_version  = $::apache::apache_version,
-  $restrict_access = true,
-```
+**Parameters within `apache::mod::auth_cas`**:
 
-To set the addresses that are allowed to access /server-info add the following:
+- `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'.
 
-```puppet
-  class {'apache::mod::info':
-    allow_from      => [
-      '10.10.36',
-      '10.10.38',
-      '127.0.0.1',
-    ],
-  }
-```
+##### Class: `apache::mod::auth_mellon`
 
-To disable the access restrictions add the following:
+Installs and manages [`mod_auth_mellon`][]. Its parameters share names with the Apache module's directives.
 
-```puppet
-  class {'apache::mod::info':
-    restrict_access => false,
-  }
-```
-
-It is not recommended to leave this set to false though it can be very useful for testing. For this reason, you can insert this setting in your normal code to temporarily disable the restrictions like so:
-
-```puppet
-  class {'apache::mod::info':
-    restrict_access => false, # false disables the block below
-    allow_from      => [
-      '10.10.36',
-      '10.10.38',
-      '127.0.0.1',
-    ],
-  }
-```
-
-####Class: `apache::mod::pagespeed`
-
-Installs and manages mod_pagespeed, which is a Google module that rewrites web pages to reduce latency and bandwidth.
-
-This module does *not* manage the software repositories needed to automatically install the
-mod-pagespeed-stable package. The module does however require that the package be installed,
-or be installable using the system's default package provider.  You should ensure that this
-pre-requisite is met or declaring `apache::mod::pagespeed` causes the Puppet run to fail.
-
-These are the defaults:
-
-```puppet
-    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      => { }
-    }
-```
+~~~ puppet
+class{ 'apache::mod::auth_mellon':
+  mellon_cache_size => 101,
+}
+~~~
 
-Full documentation for mod_pagespeed is available from [Google](http://modpagespeed.com).
+**Parameters within `apache::mod::auth_mellon`**:
 
-####Class: `apache::mod::php`
+- `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'.
 
-Installs and configures mod_php. The defaults are OS-dependant.
+##### Class: `apache::mod::deflate`
 
-Overriding the package name:
-```puppet
-  class {'::apache::mod::php':
-    package_name => "php54-php",
-    path         => "${::apache::params::lib_path}/libphp54-php5.so",
-  }
-```
+Installs and configures [`mod_deflate`][].
 
-Overriding the default configuartion:
-```puppet
-  class {'::apache::mod::php':
-    source => 'puppet:///modules/apache/my_php.conf',
-  }
-```
+**Parameters within `apache::mod::deflate`**:
 
-or
-```puppet
-  class {'::apache::mod::php':
-    template => 'apache/php.conf.erb',
-  }
-```
+- `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' }
 
-or
+##### Class: `apache::mod::expires`
 
-```puppet
-  class {'::apache::mod::php':
-    content => '
-AddHandler php5-script .php
-AddType text/html .php',
-  }
-```
-####Class: `apache::mod::shib`
+Installs [`mod_expires`][] and uses the `expires.conf.erb` template to generate its configuration.
 
-Installs the [Shibboleth](http://shibboleth.net/) module for Apache which allows the use of SAML2 Single-Sign-On (SSO) authentication by Shibboleth Identity Providers and Shibboleth Federations. This class only installs and configures the Apache components of a Shibboleth Service Provider (a web application that consumes Shibboleth SSO identities). The Shibboleth configuration can be managed manually, with Puppet, or using a [Shibboleth Puppet Module](https://github.com/aethylred/puppet-shibboleth).
+**Parameters within `apache::mod::expires`**:
 
-Defining this class enables the Shibboleth specific parameters in `apache::vhost` instances.
+- `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::ssl`
+##### Class: `apache::mod::ext_filter`
 
-Installs Apache SSL capabilities and uses the ssl.conf.erb template. These are the defaults:
+Installs and configures [`mod_ext_filter`][].
 
-```puppet
-    class { 'apache::mod::ssl':
-      ssl_compression         => false,
-      ssl_cryptodevice        => 'builtin',
-      ssl_options             => [ 'StdEnvVars' ],
-      ssl_cipher              => 'HIGH:MEDIUM:!aNULL:!MD5',
-      ssl_honorcipherorder    => 'On',
-      ssl_protocol            => [ 'all', '-SSLv2', '-SSLv3' ],
-      ssl_pass_phrase_dialog  => 'builtin',
-      ssl_random_seed_bytes   => '512',
-      ssl_sessioncachetimeout => '300',
-    }
-```
+~~~ 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"',
+  },
+}
+~~~
 
-To *use* SSL with a virtual host, you must either set the`default_ssl_vhost` parameter in `::apache` to 'true' or set the `ssl` parameter in `apache::vhost` to 'true'.
+**Parameters within `apache::mod::ext_filter`**:
 
-####Class: `apache::mod::status`
+- `ext_filter_define`: A hash of filter names and their parameters. Default: undef.
 
-Installs Apache mod_status and uses the status.conf.erb template. These are the defaults:
+##### Class: `apache::mod::fcgid`
 
-```puppet
-    class { 'apache::mod::status':
-      allow_from      = ['127.0.0.1','::1'],
-      extended_status = 'On',
-      status_path     = '/server-status',
-){
+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',
+  },
+}
+~~~
 
-####Class: `apache::mod::wsgi`
+For a full list of options, see the [official `mod_fcgid` documentation][`mod_fcgid`].
 
-Enables Python support in the WSGI module. To use, simply `include 'apache::mod::wsgi'`.
+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`.
 
-For customized parameters, which tell Apache how Python is currently configured on the operating system,
+~~~ puppet
+include apache::mod::fcgid
 
-```puppet
-    class { 'apache::mod::wsgi':
-      wsgi_socket_prefix => "\${APACHE_RUN_DIR}WSGI",
-      wsgi_python_home   => '/path/to/venv',
-      wsgi_python_path   => '/path/to/venv/site-packages',
+apache::vhost { 'example.org':
+  docroot     => '/var/www/html',
+  directories => {
+    path        => '/var/www/html',
+    fcgiwrapper => {
+      command => '/usr/local/bin/fcgiwrapper',
     }
-```
-
-To specify an alternate mod\_wsgi package name to install and the name of the module .so it provides,
-(e.g. a "python27-mod\_wsgi" package that provides "python27-mod_wsgi.so" in the default module directory):
-
-```puppet
-    class { 'apache::mod::wsgi':
-      wsgi_socket_prefix => "\${APACHE_RUN_DIR}WSGI",
-      wsgi_python_home   => '/path/to/venv',
-      wsgi_python_path   => '/path/to/venv/site-packages',
-	  package_name       => 'python27-mod_wsgi',
-	  mod_path           => 'python27-mod_wsgi.so',
-    }
-```
+  },
+}
+~~~
 
-If ``mod_path`` does not contain "/", it will be prefixed by the default module path
-for your OS; otherwise, it will be used literally.
+##### Class: `apache::mod::geoip`
 
-More information about [WSGI](http://modwsgi.readthedocs.org/en/latest/).
+Installs and manages [`mod_geoip`][].
 
-####Class: `apache::mod::fcgid`
+**Parameters within `apache::mod::geoip`**:
 
-Installs and configures mod_fcgid.
+- `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'.
 
-The class makes no effort to list all available options, but rather uses an options hash to allow for ultimate flexibility:
+##### Class: `apache::mod::info`
 
-```puppet
-    class { 'apache::mod::fcgid':
-      options => {
-        'FcgidIPCDir'  => '/var/run/fcgidsock',
-        'SharememPath' => '/var/run/fcgid_shm',
-        'AddHandler'   => 'fcgid-script .fcgi',
-      },
-    }
-```
+Installs and manages [`mod_info`][], which provides a comprehensive overview of the server configuration.
 
-For a full list op options, see the [official mod_fcgid documentation](https://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html).
+**Parameters within `apache::mod::info`**:
 
-It is also possible to set the FcgidWrapper per directory per vhost. You must ensure the fcgid module is loaded because there is no auto loading.
+- `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'.
 
-```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::negotiation`
 
-See [FcgidWrapper documentation](https://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html#fcgidwrapper) for more information.
+Installs and configures [`mod_negotiation`][].
 
-####Class: `apache::mod::negotiation`
+**Parameters within `apache::mod::negotiation`:**
 
-Installs and configures mod_negotiation. If there are not provided any
-parameter, default apache mod_negotiation configuration is done.
+- `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' ]
 
-```puppet
-  class { '::apache::mod::negotiation':
-    force_language_priority => 'Prefer',
-    language_priority       => [ 'es', 'en', 'ca', 'cs', 'da', 'de', 'el', 'eo' ],
-  }
-```
+##### Class: `apache::mod::pagespeed`
 
-**Parameters within `apache::mod::negotiation`:**
+Installs and manages [`mod_pagespeed`], a Google module that rewrites web pages to reduce latency and bandwidth.
 
-#####`force_language_priority`
+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.
 
-A string that sets the `ForceLanguagePriority` option. Defaults to `Prefer Fallback`.
+**Parameters within `apache::mod::info`**:
 
-#####`language_priority`
+- `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: { }.
 
-An array of languages to set the `LanguagePriority` option of the module.
+The class's parameters correspond to the module's directives. See the [module's documentation][`mod_pagespeed`] for details.
 
-####Class: `apache::mod::deflate`
+##### Class: `apache::mod::php`
 
-Installs and configures mod_deflate. If no parameters are provided, a default configuration is applied.
+Installs and configures [`mod_php`][].
 
-```puppet
-  class { '::apache::mod::deflate':
-    types => [ 'text/html', 'text/css' ],
-    notes => {
-      'Input' => 'instream',
-      'Ratio' => 'ratio',
-    },
-  }
-```
+**Parameters within `apache::mod::php`**:
 
-#####`types`
+Default values depend on your operating system.
 
-An array of mime types to be deflated.
+> **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.
 
-#####`notes`
+- `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`.
 
-A hash where the key represents the type and the value represents the note name.
+##### Class: `apache::mod::reqtimeout`
 
+Installs and configures [`mod_reqtimeout`][].
 
-####Class: `apache::mod::reqtimeout`
+**Parameters within `apache::mod::reqtimeout`**:
 
-Installs and configures mod_reqtimeout. Defaults to recommended apache
-mod_reqtimeout configuration.
+- `timeouts`: A string or [array][] that sets the [`RequestReadTimeout`][] option. Default: ['header=20-40,MinRate=500', 'body=20,MinRate=500'].
 
-```puppet
-  class { '::apache::mod::reqtimeout':
-    timeouts => ['header=20-40,MinRate=500', 'body=20,MinRate=500'],
-  }
-```
+##### Class: `apache::mod::shib`
 
-####Class: `apache::mod::version`
+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).
 
-This wrapper around mod_version warns on Debian and Ubuntu systems with Apache httpd 2.4
-about loading mod_version, as on these platforms it's already built-in.
+Defining this class enables Shibboleth-specific parameters in `apache::vhost` instances.
 
-```puppet
-  include '::apache::mod::version'
-```
+##### Class: `apache::mod::ssl`
 
-#####`timeouts`
+Installs [Apache SSL features][`mod_ssl`] and uses the `ssl.conf.erb` template to generate its configuration.
 
-A string or an array that sets the `RequestReadTimeout` option. Defaults to
-`['header=20-40,MinRate=500', 'body=20,MinRate=500']`.
+**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'.
 
-####Class: `apache::mod::security`
+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'.
 
-Installs and configures mod_security.  Defaults to enabled and running on all
-vhosts.
+##### Class: `apache::mod::status`
 
-```puppet
-  include '::apache::mod::security'
-```
+Installs [`mod_status`][] and uses the `status.conf.erb` template to generate its configuration.
 
-#####`crs_package`
+**Parameters within `apache::mod::status`**:
 
-Name of package to install containing crs rules
+- `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'.
 
-#####`modsec_dir`
+##### Class: `apache::mod::version`
 
-Directory to install the modsec configuration and activated rules links into
+Installs [`mod_version`][] on many operating systems and Apache configurations.
 
-#####`activated_rules`
+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.
 
-Array of rules from the modsec_crs_path to activate by symlinking to
-${modsec_dir}/activated_rules.
+##### Class: `apache::mod::security`
 
-#####`allowed_methods`
+Installs and configures Trustwave's [`mod_security`][]. It is enabled and runs by default on all virtual hosts.
 
-HTTP methods allowed by mod_security
+**Parameters within `apache::mod::security`**:
 
-#####`content_types`
+- `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/'.
 
-Content-types allowed by mod_security
+##### Class: `apache::mod::wsgi`
 
-#####`restricted_extensions`
+Enables Python support via [`mod_wsgi`][].
 
-Extensions prohibited by mod_security
+**Parameters within `apache::mod::wsgi`**:
 
-#####`restricted_headers`
+- `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`][].
 
-Headers restricted by mod_security
+The class's parameters correspond to the module's directives. See the [module's documentation][`mod_wsgi`] for details.
 
+### Private Classes
 
-####Defined Type: `apache::vhost`
+#### Class: `apache::confd::no_accf`
 
-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 it to be evaluated multiple times with different parameters.
+Creates the `no-accf.conf` configuration file in `conf.d`, required by FreeBSD's Apache 2.4.
 
-The `vhost` defined type allows you to have specialized configurations for virtual hosts that have requirements outside the defaults. You can set up a default vhost within the base `::apache` class, as well as set a customized vhost as default. Your customized vhost (priority 10) will be privileged over the base class vhost (15).
+#### Class: `apache::default_confd_files`
 
-The `vhost` defined type uses `concat::fragment` to build the configuration file, so if you want to inject custom fragments for pieces of the configuration not supported by default by the defined type, you can add a custom fragment.  For the `order` parameter for the custom fragment, the `vhost` defined type uses multiples of 10, so any order that isn't a multiple of 10 should work.
+Includes `conf.d` files for FreeBSD.
 
-```puppet
-    apache::vhost { "example.com":
-      docroot  => '/var/www/html',
-      priority => '25',
-    }
-    concat::fragment { "example.com-my_custom_fragment":
-      target  => '25-example.com.conf',
-      order   => 11,
-      content => '# my custom comment',
-    }
-```
+#### Class: `apache::default_mods`
 
-If you have a series of specific configurations and do not want a base `::apache` class default vhost, make sure to set the base class `default_vhost` to 'false'.
+Installs the Apache modules required to run the default configuration. See the `apache` class's [`default_mods`][] parameter for details.
 
-```puppet
-    class { 'apache':
-      default_vhost => false,
-    }
-```
+#### Class: `apache::package`
 
-**Parameters within `apache::vhost`:**
+Installs and configures basic Apache packages.
 
-#####`access_log`
+#### Class: `apache::params`
 
-Specifies whether `*_access.log` directives (`*_file`,`*_pipe`, or `*_syslog`) should be configured. Setting the value to 'false' chooses none. Defaults to 'true'.
+Manages Apache parameters for different operating systems.
 
-#####`access_log_file`
+#### Class: `apache::service`
 
-Sets the `*_access.log` filename that is placed in `$logroot`. Given a vhost, example.com, it defaults to 'example.com_ssl.log' for SSL vhosts and 'example.com_access.log' for non-SSL vhosts.
+Manages the Apache daemon.
 
-#####`access_log_pipe`
+#### Class: `apache::version`
 
-Specifies a pipe to send access log messages to. Defaults to 'undef'.
+Attempts to automatically detect the Apache version based on the operating system.
 
-#####`access_log_syslog`
+### Public Defines
 
-Sends all access log messages to syslog. Defaults to 'undef'.
+#### Define: `apache::balancer`
 
-#####`access_log_format`
+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.
 
-Specifies the use of either a LogFormat nickname or a custom format string for the access log. Defaults to 'combined'. See [these examples](http://httpd.apache.org/docs/current/mod/mod_log_config.html).
+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][].
 
-#####`access_log_env_var`
+**Parameters within `apache::balancer`**:
 
-Specifies that only requests with particular environment variables be logged. Defaults to 'undef'.
+##### `name`
 
-#####`add_default_charset`
+Sets the title of the balancer cluster and name of the `conf.d` file containing its configuration.
 
-Sets [AddDefaultCharset](http://httpd.apache.org/docs/current/mod/core.html#adddefaultcharset), a default value for the media charset, which is added to text/plain and text/html responses.
+##### `proxy_set`
 
-#####`add_listen`
+Configures key-value pairs as [`ProxySet`][] lines. Valid options: [Hash][]. Default: '{}'.
 
-Determines whether the vhost creates a Listen statement. The default value is 'true'.
+##### `collect_exported`
 
-Setting `add_listen` to 'false' stops the vhost from creating a Listen statement, and this is important when you combine vhosts that are not passed an `ip` parameter with vhosts that *are* passed the `ip` parameter.
+Determines whether to use [exported resources][]. Valid options: Boolean. Default: 'true'.
 
-#####`use_optional_includes`
+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.
 
-Specifies if for apache > 2.4 it should use IncludeOptional instead of Include for `additional_includes`. Defaults to 'false'.
+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.
 
-#####`additional_includes`
+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.
 
-Specifies paths to additional static, vhost-specific Apache configuration files. Useful for implementing a unique, custom configuration not supported by this module. Can be an array. Defaults to '[]'.
+#### Define: `apache::balancermember`
 
-#####`aliases`
+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`.
 
-Passes a list of hashes to the vhost to create Alias, AliasMatch, ScriptAlias or ScriptAliasMatch directives as per the [mod_alias documentation](http://httpd.apache.org/docs/current/mod/mod_alias.html). These hashes are formatted as follows:
+**Parameters within `apache::balancermember`**:
 
-```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',
-  },
-],
-```
+##### `balancer_cluster`
 
-For `alias`, `aliasmatch`, `scriptalias` and `scriptaliasmatch` to work, each needs a corresponding context, such as `` or ``. The directives are created in the order specified in the `aliases` parameter. As described in the [`mod_alias` documentation](http://httpd.apache.org/docs/current/mod/mod_alias.html), more specific `alias`, `aliasmatch`, `scriptalias` or `scriptaliasmatch` parameters should come before the more general ones to avoid shadowing.
+**Required**. Sets the Apache service's instance name, and must match the name of a declared [`apache::balancer`][] resource.
 
-*Note*: Using the `aliases` parameter is preferred over the `scriptaliases` parameter since here the order of the various alias directives among each other can be controlled precisely. 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 is often problematic, for example in case of Nagios.
+##### `url`
 
-*Note:* If `apache::mod::passenger` is loaded and `PassengerHighPerformance => true` is set, then Alias might have issues honoring the `PassengerEnabled => off` statement. See [this article](http://www.conandalton.net/2010/06/passengerenabled-off-not-working.html) for details.
+Specifies the URL used to contact the balancer member server. Default:  'http://${::fqdn}/'.
 
-#####`allow_encoded_slashes`
+##### `options`
 
-This sets the [`AllowEncodedSlashes` declaration](http://httpd.apache.org/docs/current/mod/core.html#allowencodedslashes) for the vhost, overriding the server default. This modifies the vhost responses to URLs with `\` and `/` characters. The default is undefined, which omits the declaration from the server configuration and select the Apache default setting of `Off`. Allowed values are: `on`, `off` or `nodecode`.
+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.
 
-#####`block`
+#### Define: `apache::custom_config`
 
-Specifies the list of things Apache blocks access to. The default is an empty set, '[]'. Currently, the only option is 'scm', which blocks web access to .svn, .git and .bzr directories.
+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.
 
-#####`custom_fragment`
+**Parameters within `apache::custom_config`**:
 
-Passes a string of custom configuration directives to be placed at the end of the vhost configuration. Defaults to 'undef'.
+##### `ensure`
 
-#####`default_vhost`
+Specifies whether the configuration file should be present. Valid options: 'absent', 'present'. Default: 'present'.
 
-Sets a given `apache::vhost` as the default to serve requests that do not match any other `apache::vhost` definitions. The default value is 'false'.
+##### `confdir`
 
-#####`directories`
+Sets the directory in which Puppet places configuration files. Default: '$::apache::confd_dir'.
 
-See the [`directories` section](#parameter-directories-for-apachevhost).
+##### `content`
 
-#####`directoryindex`
+Sets the configuration file's content. The `content` and [`source`][] parameters are exclusive of each other.
 
-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. [DirectoryIndex](http://httpd.apache.org/docs/current/mod/mod_dir.html#directoryindex) has more information. Defaults to 'undef'.
+##### `priority`
 
-#####`docroot`
+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`.
 
-Provides the
-[DocumentRoot](http://httpd.apache.org/docs/current/mod/core.html#documentroot)
-directive, which identifies the directory Apache serves files from. Required.
+To omit the priority prefix in the configuration file's name, set this parameter to `false`.
 
-#####`docroot_group`
+##### `source`
 
-Sets group access to the docroot directory. Defaults to 'root'.
+Points to the configuration file's source. The [`content`][] and `source` parameters are exclusive of each other.
 
-#####`docroot_owner`
+##### `verify_command`
 
-Sets individual user access to the docroot directory. Defaults to 'root'.
+Specifies the command Puppet uses to verify the configuration file. Use a fully qualified command. Default: `/usr/sbin/apachectl -t`.
 
-#####`docroot_mode`
+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.
 
-Sets access permissions of the docroot directory. Defaults to 'undef'.
+##### `verify_config`
 
-#####`manage_docroot`
+Specifies whether to validate the configuration file before notifying the Apache service. Valid options: Boolean. Default: `true`.
 
-Whether to manage to docroot directory at all. Defaults to 'true'.
+#### Define: `apache::fastcgi::server`
 
-#####`error_log`
+Defines one or more external FastCGI servers to handle specific file types. Use this define with [`mod_fastcgi`][FastCGI].
 
-Specifies whether `*_error.log` directives should be configured. Defaults to 'true'.
+**Parameters within `apache::fastcgi::server`:**
 
-#####`error_log_file`
+##### `host`
 
-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.
+Determines the FastCGI's hostname or IP address and TCP port number (1-65535).
 
-#####`error_log_pipe`
+##### `timeout`
 
-Specifies a pipe to send error log messages to. Defaults to 'undef'.
+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.
 
-#####`error_log_syslog`
+##### `flush`
 
-Sends all error log messages to syslog. Defaults to 'undef'.
+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.
 
-#####`error_documents`
+##### `faux_path`
 
-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:
+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.
 
-```puppet
-    apache::vhost { 'sample.example.net':
-      error_documents => [
-        { 'error_code' => '503', 'document' => '/service-unavail' },
-        { 'error_code' => '407', 'document' => 'https://example.com/proxy/login' },
-      ],
-    }
-```
+##### `alias`
 
-#####`ensure`
+Internally links actions with the FastCGI server. This alias must be unique.
 
-Specifies if the vhost file is present or absent. Defaults to 'present'.
+##### `file_type`
 
-#####`fallbackresource`
+Sets the [MIME `content-type`][] of the file to be processed by the FastCGI server.
 
-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'.
+#### Define: `apache::listen`
 
-#####`headers`
+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 '', ':', or ':'.
 
-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'.
+#### Define: `apache::mod`
 
-#####`ip`
+Installs packages for an Apache module that doesn't have a corresponding [`apache::mod::`][] 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.
 
-Sets the IP address the vhost listens on. Defaults to listen on all IPs.
+**Parameters within `apache::mod`**:
 
-#####`ip_based`
+##### `package`
 
-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'.
+**Required**. Names the package Puppet uses to install the Apache module.
 
-#####`itk`
+##### `package_ensure`
 
-Configures [ITK](http://mpm-itk.sesse.net/) in a hash. Keys can be:
+Determines whether Puppet ensures the Apache module should be installed. Valid options: 'absent', 'present'. Default: 'present'.
 
-* user + group
-* `assignuseridexpr`
-* `assigngroupidexpr`
-* `maxclientvhost`
-* `nice`
-* `limituidrange` (Linux 3.5.0 or newer)
-* `limitgidrange` (Linux 3.5.0 or newer)
+##### `lib`
 
-Usage typically looks like:
+Defines the module's shared object name. Its default value is `mod_$name.so`, and it should not be configured manually without special reason.
 
-```puppet
+##### `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 '\*', '*:', '\_default_:, '', or ':'.
+
+#### 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 `` or ``. 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 `` 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':
-      docroot => '/path/to/directory',
-      itk     => {
-        user  => 'someuser',
-        group => 'somegroup',
-      },
+      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.
 
-#####`logroot`
+##### `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//'.
 
-#####`$logroot_ensure`
+##### `$logroot_ensure`
 
 Determines whether or not to remove the logroot directory for a virtual host. Valid values are 'directory', or 'absent'.
 
-#####`logroot_mode`
+##### `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`
+##### `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`
+###### `modsec_body_limit`
 
 Configures the maximum request body size (in bytes) ModSecurity will accept for buffering
 
-######`modsec_disable_vhost`
+###### `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`
+###### `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
+~~~ puppet
     apache::vhost { 'sample.example.net':
       modsec_disable_ids => [ 90015, 90016 ],
     }
-```
+~~~
 
-```puppet
+~~~ puppet
     apache::vhost { 'sample.example.net':
       modsec_disable_ids => { '/location1' => [ 90015, 90016 ] },
     }
-```
+~~~
 
-######`modsec_disable_ips`
+###### `modsec_disable_ips`
 
 Array of IPs to exclude from mod_security rule matching
 
-#####`no_proxy_uris`
+##### `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`
+##### `no_proxy_uris_match`
 
 This directive is equivalent to `no_proxy_uris`, but takes regular expressions.
 
-#####`proxy_preserve_host`
+##### `proxy_preserve_host`
 
-Sets the [ProxyPreserveHost Directive](http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypreservehost).  true Enables the Host: line from an incoming request to be proxied to the host instead of hostname .  false sets this option to off (default).
+Sets the [ProxyPreserveHost Directive](http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypreservehost). Valid options: Boolean. Default: 'false'.
 
-#####`proxy_error_override`
+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'.
 
-Sets the [ProxyErrorOverride Directive](http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxyerroroverride). This directive controls whether apache should override error pages for proxied content. This option is off by default.
+##### `proxy_error_override`
 
-#####`options`
+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.
 
-Sets the [Options](http://httpd.apache.org/docs/current/mod/core.html#options) for the specified virtual host. Defaults to '['Indexes','FollowSymLinks','MultiViews']', as demonstrated below:
+##### `options`
 
-```puppet
+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 [`directories`](#parameter-directories-for-apachevhost), 'Options', 'Override', and 'DirectoryIndex' are ignored because they are parameters within `directories`.
+**Note**: If you use the [`directories`][] parameter of [`apache::vhost`][], 'Options', 'Override', and 'DirectoryIndex' are ignored because they are parameters within `directories`.
 
-#####`override`
+##### `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`
+##### `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`
+##### `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`
+##### `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`
+##### `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`
+##### `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`
+##### `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`
+##### `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 '[]'.
+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`
+##### `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 '[]'.
+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`
+##### `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`
+##### `priority`
 
 Sets the relative load-order for Apache HTTPD VirtualHost configuration files. Defaults to '25'.
 
@@ -1320,15 +2196,15 @@ If nothing matches the priority, the first name-based vhost is used. Likewise, p
 
 Pass priority `false` to omit the priority prefix in file names.
 
-#####`proxy_dest`
+##### `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`
+##### `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
+~~~ puppet
 apache::vhost { 'site.name.fdqn':
   …
   proxy_pass => [
@@ -1343,220 +2219,226 @@ apache::vhost { 'site.name.fdqn':
       '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`
+##### `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`
+##### `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`
+##### `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`
+##### `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'.
 
-#####`redirect_dest`
+#####`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`
+##### `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/'],
-    }
-```
+~~~ puppet
+apache::vhost { 'site.name.fdqn':
+  …
+  redirect_source => ['/images','/downloads'],
+  redirect_dest   => ['http://img.example.com/','http://downloads.example.com/'],
+}
+~~~
 
-#####`redirect_status`
+##### `redirect_status`
 
 Specifies the status to append to the redirect. Defaults to 'undef'.
 
-```puppet
-    apache::vhost { 'site.name.fdqn':
-      …
-      redirect_status => ['temp','permanent'],
-    }
-```
+~~~ puppet
+apache::vhost { 'site.name.fdqn':
+  …
+  redirect_status => ['temp','permanent'],
+}
+~~~
 
-#####`redirectmatch_regexp` & `redirectmatch_status` & `redirectmatch_dest`
+##### `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'],
-    }
-```
+~~~ 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`
+##### `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`
+~~~ 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'] } ]
-    }
-```
+~~~ 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'],
-        },
-      ],
-    }
-```
+~~~ 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'],
-        },
-      ],
-    }
-```
+~~~ 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]'],
-        },
-     ],
-    }
-```
+~~~ 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`
+##### `scriptalias`
 
 Defines a directory of CGI scripts to be aliased to the path '/cgi-bin', for example: '/usr/scripts'. Defaults to 'undef'.
 
-#####`scriptaliases`
+##### `scriptaliases`
 
-*Note*: This parameter is deprecated in favour of the `aliases` parameter.
+**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 as per the [`mod_alias` documentation](http://httpd.apache.org/docs/current/mod/mod_alias.html). These hashes are formatted as follows:
+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',
-      },
-    ]
-```
+~~~ 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, more specific aliases should come before more general ones to avoid shadowing.
+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`
+##### `serveradmin`
 
 Specifies the email address Apache displays when it renders one of its error pages. Defaults to 'undef'.
 
-#####`serveraliases`
+##### `serveraliases`
 
 Sets the [ServerAliases](http://httpd.apache.org/docs/current/mod/core.html#serveralias) of the site. Defaults to '[]'.
 
-#####`servername`
+##### `servername`
 
 Sets the servername corresponding to the hostname you connect to the virtual host at. Defaults to the title of the resource.
 
-#####`setenv`
+##### `setenv`
 
 Used by HTTPD to set environment variables for vhosts. Defaults to '[]'.
 
 Example:
 
-```puppet
-    apache::vhost { 'setenv.example.com':
-      setenv => ['SPECIAL_PATH /foo/bin'],
-    }
-```
+~~~ puppet
+apache::vhost { 'setenv.example.com':
+  setenv => ['SPECIAL_PATH /foo/bin'],
+}
+~~~
 
-#####`setenvif`
+##### `setenvif`
 
 Used by HTTPD to conditionally set environment variables for vhosts. Defaults to '[]'.
 
-#####`suphp_addhandler`, `suphp_configpath`, & `suphp_engine`
+##### `suphp_addhandler`, `suphp_configpath`, & `suphp_engine`
 
 Set up a virtual host with [suPHP](http://suphp.org/DocumentationView.html?file=apache/CONFIG).
 
@@ -1568,38 +2450,38 @@ Set up a virtual host with [suPHP](http://suphp.org/DocumentationView.html?file=
 
 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' },
-      }
-    }
-```
+~~~ 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`
+##### `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`
+##### `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',],
-    }
-```
+~~~ 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`
+##### `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/).
 
@@ -1617,23 +2499,23 @@ Set up a virtual host with [WSGI](https://code.google.com/p/modwsgi/).
 
 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',
-    }
-```
+~~~ 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`
+#### 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>'.
 
@@ -1643,137 +2525,137 @@ The `provider` key is optional. If missing, this key defaults to 'directory'. Va
 
 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'
-         },
-      ],
-    }
-```
+~~~ 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
+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 } ],
+~~~ 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`
+###### `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']}],
-        },
-      ],
-    }
-```
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path        => '/path/to/directory',
+      addhandlers => [{ handler => 'cgi-script', extensions => ['.cgi']}],
+    },
+  ],
+}
+~~~
 
-######`allow`
+###### `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',
-        },
-      ],
-    }
-```
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path  => '/path/to/directory',
+      allow => 'from example.org',
+    },
+  ],
+}
+~~~
 
-######`allow_override`
+###### `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'],
-        },
-      ],
-    }
-```
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot      => '/path/to/directory',
+  directories  => [
+    { path           => '/path/to/directory',
+      allow_override => ['AuthConfig', 'Indexes'],
+    },
+  ],
+}
+~~~
 
-######`auth_basic_authoritative`
+###### `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`
+###### `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`
+###### `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`
+###### `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`
+###### `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`
+###### `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`
+###### `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`
+###### `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`
+###### `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`
+###### `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`
+###### `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`
+###### `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`
+###### `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`
+###### `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`
+###### `custom_fragment`
 
 Pass a string of custom configuration directives to be placed at the end of the directory configuration.
 
-```puppet
+~~~ puppet
   apache::vhost { 'monitor':
     …
     directories => [
@@ -1794,13 +2676,13 @@ Pass a string of custom configuration directives to be placed at the end of the
       },
     ]
   }
-```
+~~~
 
-######`deny`
+###### `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
+~~~ puppet
     apache::vhost { 'sample.example.net':
       docroot     => '/path/to/directory',
       directories => [
@@ -1809,348 +2691,468 @@ Sets a [Deny](http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#deny) dir
         },
       ],
     }
-```
+~~~
 
-######`error_documents`
+###### `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',
-            },
-          ],
+~~~ 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',
+    },
+  ],
+}
+~~~
 
-######`headers`
+###### `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"',
-      },
-    }
-```
+~~~ 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`
+###### `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',
-          options       => ['Indexes','FollowSymLinks','MultiViews'],
-          index_options => ['IgnoreCase', 'FancyIndexing', 'FoldersFirst', 'NameWidth=*', 'DescriptionWidth=*', 'SuppressHTMLPreamble'],
-        },
-      ],
-    }
-```
+~~~ 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`
+###### `index_order_default`
 
-Sets the [default ordering](http://httpd.apache.org/docs/current/mod/mod_autoindex.html#indexorderdefault) of the directory index.
+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'],
-        },
-      ],
-    }
-```
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path                => '/path/to/directory',
+      order               => 'Allow,Deny',
+      index_order_default => ['Descending', 'Date'],
+    },
+  ],
+}
+~~~
 
-######`options`
+###### `index_style_sheet`
 
-Lists the [Options](http://httpd.apache.org/docs/current/mod/core.html#options) for the given Directory block.
+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'],
-        },
-      ],
-    }
-```
+~~~ 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`
+###### `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',
-        },
-      ],
-    }
-```
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path  => '/path/to/directory',
+      order => 'Allow,Deny',
+    },
+  ],
+}
+~~~
 
-######`passenger_enabled`
+###### `passenger_enabled`
 
-Sets the value for the [PassengerEnabled](http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerEnabled) directory to 'on' or 'off'. Requires `apache::mod::passenger` to be included.
+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',
-        },
-      ],
-    }
-```
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path              => '/path/to/directory',
+      passenger_enabled => 'on',
+    },
+  ],
+}
+~~~
 
-*Note:* Be aware that there is an [issue](http://www.conandalton.net/2010/06/passengerenabled-off-not-working.html) using the PassengerEnabled directive with the PassengerHighPerformance directive.
+**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` 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` 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`
+###### `satisfy`
 
-Sets a `Satisfy` directive as per the [Apache Core documentation](http://httpd.apache.org/docs/2.2/mod/core.html#satisfy). **Deprecated:** This parameter is being deprecated due to a change in Apache. It only works with Apache 2.2 and lower.
+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',
-        }
-      ],
+~~~ puppet
+apache::vhost { 'sample.example.net':
+  docroot     => '/path/to/directory',
+  directories => [
+    { path    => '/path/to/directory',
+      satisfy => 'Any',
     }
-```
+  ],
+}
+~~~
 
-######`sethandler`
+###### `sethandler`
 
-Sets a `SetHandler` directive as per the [Apache Core documentation](http://httpd.apache.org/docs/2.2/mod/core.html#sethandler). An example:
+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',
-        }
-      ],
+~~~ 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`
+###### `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]' ],
-                        }
-                      ],
-        },
-      ],
-    }
-```
+~~~ 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 make sure you are also including `apache::mod::rewrite`. You may also want to consider setting the rewrites using the `rewrites` parameter in `apache::vhost` rather than setting the rewrites in the vhost directories.
+***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`
+###### `shib_request_setting`
 
-Allows an 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.
+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_require_setting  => 'requiresession 1',
-          shib_use_headers      => 'On',
-        },
-      ],
-    }
-```
+~~~ 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`
+###### `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.
+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`
+###### `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'],
-        },
-      ],
-    }
-```
+~~~ 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`
+###### `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',
-            },
-        },
-      ],
-    }
-```
+~~~ 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`
+#### 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`
+##### `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`
+##### `ssl_ca`
 
 Specifies the SSL certificate authority. Defaults to 'undef'.
 
-#####`ssl_cert`
+##### `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`
+##### `ssl_protocol`
 
-Specifies [SSLProtocol](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslprotocol). Expects an array of accepted protocols. Defaults to 'all', '-SSLv2', '-SSLv3'.
+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`
+##### `ssl_cipher`
 
 Specifies [SSLCipherSuite](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslciphersuite). Defaults to 'HIGH:MEDIUM:!aNULL:!MD5'.
 
-#####`ssl_honorcipherorder`
+##### `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`
+##### `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`
+##### `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`
+##### `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`
+##### `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`
+##### `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`
+##### `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`
+##### `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
+~~~ puppet
     apache::vhost { 'sample.example.net':
       …
       ssl_verify_client => 'optional',
     }
-```
+~~~
 
-#####`ssl_verify_depth`
+##### `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
+~~~ 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`
+##### `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
+~~~ puppet
     apache::vhost { 'sample.example.net':
       …
       ssl_options => '+ExportCertData',
     }
-```
+~~~
 
 An array:
 
-```puppet
+~~~ puppet
     apache::vhost { 'sample.example.net':
       …
       ssl_options => [ '+StrictRequire', '+ExportCertData' ],
     }
-```
+~~~
+
+##### `ssl_openssl_conf_cmd`
 
-#####`ssl_proxyengine`
+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'.
 
-####Defined Type: FastCGI Server
+####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
+~~~ puppet
 apache::fastcgi::server { 'php':
   host       => '127.0.0.1:9000',
   timeout    => 15,
@@ -2159,426 +3161,172 @@ apache::fastcgi::server { 'php':
   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
+~~~ puppet
 apache::vhost { 'www':
   ...
   custom_fragment => 'AddType application/x-httpd-php .php'
   ...
 }
-```
+~~~
 
-#####`host`
+##### `host`
 
 The hostname or IP address and TCP port number (1-65535) of the FastCGI server.
 
-#####`timeout`
+##### `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`
+##### `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`
 
 `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`
+##### `alias`
 
 A unique alias. This is used internally to link the action with the FastCGI server.
 
-#####`file_type`
+##### `file_type`
 
 The MIME-type of the file to be processed by the FastCGI server.
 
-###Virtual Host Examples
-
-The apache module allows you to set up pretty much any configuration of virtual host you might need. This section addresses some common configurations, but look at the [Tests section](https://github.com/puppetlabs/puppetlabs-apache/tree/master/tests) for even more examples.
-
-Configure a vhost with a server administrator
-
-```puppet
-    apache::vhost { 'third.example.com':
-      port        => '80',
-      docroot     => '/var/www/third',
-      serveradmin => 'admin@example.com',
-    }
-```
-
-- - -
+### Private Defines
 
-Set up a vhost with aliased servers
+#### Define: `apache::peruser::multiplexer`
 
-```puppet
-    apache::vhost { 'sixth.example.com':
-      serveraliases => [
-        'sixth.example.org',
-        'sixth.example.net',
-      ],
-      port          => '80',
-      docroot       => '/var/www/fifth',
-    }
-```
+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`
 
-Configure a vhost with a cgi-bin
+Enables the [`Peruser`][] module for FreeBSD only.
 
-```puppet
-    apache::vhost { 'eleventh.example.com':
-      port        => '80',
-      docroot     => '/var/www/eleventh',
-      scriptalias => '/usr/lib/cgi-bin',
-    }
-```
+#### Define: `apache::peruser::processor`
 
-- - -
+Enables the [`Peruser`][] module for FreeBSD only.
 
-Set up a vhost with a rack configuration
+#### Define: `apache::security::file_link`
 
-```puppet
-    apache::vhost { 'fifteenth.example.com':
-      port           => '80',
-      docroot        => '/var/www/fifteenth',
-      rack_base_uris => ['/rackapp1', '/rackapp2'],
-    }
-```
+Links the `activated_rules` from [`apache::mod::security`][] to the respective CRS rules on disk.
 
-- - -
+### Templates
 
-Set up a mix of SSL and non-SSL vhosts at the same domain
+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.
 
-```puppet
-    #The non-ssl vhost
-    apache::vhost { 'first.example.com non-ssl':
-      servername => 'first.example.com',
-      port       => '80',
-      docroot    => '/var/www/first',
-    }
+## Limitations
 
-    #The SSL vhost at the same domain
-    apache::vhost { 'first.example.com ssl':
-      servername => 'first.example.com',
-      port       => '443',
-      docroot    => '/var/www/first',
-      ssl        => true,
-    }
-```
+### 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.
 
-Configure a vhost to redirect non-SSL connections to SSL
+### RHEL/CentOS 5
 
-```puppet
-    apache::vhost { 'sixteenth.example.com non-ssl':
-      servername      => 'sixteenth.example.com',
-      port            => '80',
-      docroot         => '/var/www/sixteenth',
-      redirect_status => 'permanent',
-      redirect_dest   => 'https://sixteenth.example.com/'
-    }
-    apache::vhost { 'sixteenth.example.com ssl':
-      servername => 'sixteenth.example.com',
-      port       => '443',
-      docroot    => '/var/www/sixteenth',
-      ssl        => true,
-    }
-```
+The [`apache::mod::passenger`][] and [`apache::mod::proxy_html`][] classes are untested since repositories are missing compatible packages.
 
-- - -
+### RHEL/CentOS 6
 
-Set up IP-based vhosts on any listen port and have them respond to requests on specific IP addresses. In this example, we set listening on ports 80 and 81. This is required because the example vhosts are not declared with a port parameter.
+The [`apache::mod::passenger`][] class is not installing as the the EL6 repository is missing compatible packages.
 
-```puppet
-    apache::listen { '80': }
-    apache::listen { '81': }
-```
+### RHEL/CentOS 7
 
-Then we set up the IP-based vhosts
+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.
 
-```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,
-    }
-```
+### General
 
-- - -
+This module is CI tested against both [open source Puppet][] and [Puppet Enterprise][] on:
 
-Configure a mix of name-based and IP-based vhosts. First, we add two IP-based vhosts on 10.0.0.10, one SSL and one non-SSL
+- CentOS 5 and 6
+- Ubuntu 12.04 and 14.04
+- Debian 7
+- RHEL 5, 6, and 7
 
-```puppet
-    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,
-    }
-```
+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.
 
-Then, we add two name-based vhosts listening on 10.0.0.20
+### SELinux and custom paths
 
-```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',
-    }
-```
+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.
 
-If you want to add two name-based vhosts so that they answer on either 10.0.0.10 or 10.0.0.20, you **MUST** declare `add_listen => 'false'` to disable the otherwise automatic 'Listen 80', as it conflicts with the preceding IP-based vhosts.
+You can do this with Puppet:
 
-```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,
-    }
-```
-
-###Load Balancing
-
-####Defined Type: `apache::balancer`
-
-`apache::balancer` creates an Apache balancer cluster. Each balancer cluster needs one or more balancer members, which are declared with [`apache::balancermember`](#defined-type-apachebalancermember).
-
-One `apache::balancer` defined resource should be defined for each Apache load balanced set of servers. The `apache::balancermember` resources for all balancer members can be exported and collected on a single Apache load balancer server using exported resources.
-
-**Parameters within `apache::balancer`:**
-
-#####`name`
-
-Sets the balancer cluster's title. This parameter also sets the title of the conf.d file.
-
-#####`proxy_set`
-
-Configures key-value pairs as [ProxySet](http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxyset) lines. Accepts a hash, and defaults to '{}'.
-
-#####`collect_exported`
-
-Determines whether or not to use exported resources. Valid values 'true' and 'false', defaults to 'true'.
-
-If you statically declare all of your backend servers, you should set this to 'false' to rely on existing declared balancer member resources. Also make sure to use `apache::balancermember` with array arguments.
-
-If you wish to dynamically declare your backend servers via [exported resources](http://docs.puppetlabs.com/guides/exported_resources.html) collected on a central node, you must set this parameter to 'true' in order to collect the exported balancer member resources that were exported by the balancer member nodes.
-
-If you choose not to use exported resources, all balancer members will be configured in a single Puppet run. If you are using exported resources, Puppet has to run on the balanced nodes, then run on the balancer.
-
-####Defined Type: `apache::balancermember`
-
-Defines members of [mod_proxy_balancer](http://httpd.apache.org/docs/current/mod/mod_proxy_balancer.html), which sets up a balancer member inside a listening service configuration block in etc/apache/apache.cfg on the load balancer.
-
-**Parameters within `apache::balancermember`:**
-
-#####`name`
-
-Sets the title of the resource. This name also sets the name of the concat fragment.
-
-#####`balancer_cluster`
-
-Sets the Apache service's instance name. This must match the name of a declared `apache::balancer` resource. Required.
-
-#####`url`
-
-Specifies the URL used to contact the balancer member server. Defaults to 'http://${::fqdn}/'.
-
-#####`options`
-
-An array of [options](http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#balancermember) to be specified after the URL. Accepts any key-value pairs available to [ProxyPass](http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass).
-
-####Examples
-
-To load balance with exported resources, export the `balancermember` from the balancer member
-
-```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 balancer cluster
-
-```puppet
-      apache::balancer { 'puppet00': }
-```
-
-To load balance without exported resources, declare the following on the proxy
-
-```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 `apache::balancer` and `apache::balancermember` on the proxy server.
-
-If you need to use ProxySet in the balancer config
-
-```puppet
-      apache::balancer { 'puppet01':
-        proxy_set => {'stickysession' => 'JSESSIONID'},
-      }
-```
-
-##Reference
-
-###Classes
-
-####Public Classes
-
-* [`apache`](#class-apache): Guides the basic setup of Apache.
-* `apache::dev`: Installs Apache development libraries. (*Note:* On FreeBSD, you must declare `apache::package` or `apache` before `apache::dev`.)
-* [`apache::mod::[name]`](#classes-apachemodname): Enables specific Apache HTTPD modules.
-
-####Private Classes
-
-* `apache::confd::no_accf`: Creates the no-accf.conf configuration file in conf.d, required by FreeBSD's Apache 2.4.
-* `apache::default_confd_files`: Includes conf.d files for FreeBSD.
-* `apache::default_mods`: Installs the Apache modules required to run the default configuration.
-* `apache::package`: Installs and configures basic Apache packages.
-* `apache::params`: Manages Apache parameters.
-* `apache::service`: Manages the Apache daemon.
-
-###Defined Types
-
-####Public Defined Types
-
-* `apache::balancer`: Creates an Apache balancer cluster.
-* `apache::balancermember`: Defines members of [mod_proxy_balancer](http://httpd.apache.org/docs/current/mod/mod_proxy_balancer.html).
-* `apache::listen`: Based on the title, controls which ports Apache binds to for listening. Adds [Listen](http://httpd.apache.org/docs/current/bind.html) directives to ports.conf in the Apache HTTPD configuration directory. Titles take the form '', ':', or ':'.
-* `apache::mod`: Used to enable arbitrary Apache HTTPD modules for which there is no specific `apache::mod::[name]` class.
-* `apache::namevirtualhost`: Enables name-based hosting of a virtual host. Adds all [NameVirtualHost](http://httpd.apache.org/docs/current/vhosts/name-based.html) directives to the `ports.conf` file in the Apache HTTPD configuration directory. Titles take the form '\*', '*:', '\_default_:, '', or ':'.
-* `apache::vhost`: Allows specialized configurations for virtual hosts that have requirements outside the defaults.
-
-####Private Defined Types
-
-* `apache::peruser::multiplexer`: Enables the [Peruser](http://www.freebsd.org/cgi/url.cgi?ports/www/apache22-peruser-mpm/pkg-descr) module for FreeBSD only.
-* `apache::peruser::processor`: Enables the [Peruser](http://www.freebsd.org/cgi/url.cgi?ports/www/apache22-peruser-mpm/pkg-descr) module for FreeBSD only.
-* `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 `vhost` and `apache::mod` defined types. These templates are built based on Facter facts around 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 VirtualHost which is unsupported on older versions of Apache, causing this 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 7
-
-The `apache::mod::passenger` class is untested as the repository does not have packages for EL7 yet.  The fact that passenger packages aren't available also makes us unable to test the `rack_base_uri` parameter in `apache::vhost`.
-
-###General
+~~~ 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'],
+}
 
-This module is CI tested on Centos 5 & 6, Ubuntu 12.04 & 14.04, Debian 7, and RHEL 5, 6 & 7 platforms against both the OSS and Enterprise version of Puppet.
+package { 'policycoreutils-python':
+  ensure => installed,
+}
 
-The module contains support for other distributions and operating systems, such as FreeBSD, Gentoo and Amazon Linux, but is not formally tested on those and regressions can occur.
+exec { 'restorecon_apache':
+  command => 'restorecon -Rv /apache_spec',
+  path    => '/bin:/usr/bin/:/sbin:/usr/sbin',
+  before  => Class['Apache::Service'],
+  require => Class['apache'],
+}
 
-###SELinux and Custom Paths
+class { 'apache': }
 
-If you are running with SELinux in enforcing mode and want to use custom paths for your `logroot`, `mod_dir`, `vhost_dir`, and `docroot`, you need to manage the context for the files yourself.
+host { 'test.server':
+  ip => '127.0.0.1',
+}
 
-Something along the lines of:
+file { '/custom/path':
+  ensure => directory,
+}
 
-```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',
-        }
-```
+file { '/custom/path/include':
+  ensure  => present,
+  content => '#additional_includes',
+}
 
-You need to set the contexts using `semanage fcontext` not `chcon` because `file {...}` resources reset the context to the values in the database if the resource isn't specifying the context.
+apache::vhost { 'test.server':
+  docroot             => '/custom/path',
+  additional_includes => '/custom/path/include',
+}
+~~~
 
-###FreeBSD
+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.
 
-In order to use this module on FreeBSD, you *must* use apache24-2.4.12 (www/apache24) or newer.
+### FreeBSD
 
-##Development
+In order to use this module on FreeBSD, you _must_ use apache24-2.4.12 (www/apache24) or newer.
 
-###Contributing
+## 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.
+### Contributing
 
-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.
+[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.
 
-Read the complete module [contribution guide](https://docs.puppetlabs.com/forge/contributing.html)
+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.
 
-###Running tests
+For more information, please read the complete [module contribution guide][].
 
-This project contains tests for both [rspec-puppet](http://rspec-puppet.com/) and [beaker-rspec](https://github.com/puppetlabs/beaker-rspec) to verify functionality. For in-depth information please see their respective documentation.
+### Running tests
 
-Quickstart:
+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.
 
-####Ruby > 1.8.7
+#### 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
-```
+~~~
+gem install bundler
+bundle install
+bundle exec rake spec
+bundle exec rspec spec/acceptance
+RS_DEBUG=yes bundle exec rspec spec/acceptance
+~~~
 
-####Ruby = 1.8.7
+#### Testing quickstart: Ruby = 1.8.7
 
-```
-    gem install bundler
-    bundle install --without system_tests
-    bundle exec rake spec
-```
+~~~
+gem install bundler
+bundle install --without system_tests
+bundle exec rake spec
+~~~
diff --git a/puphpet/puppet/modules/apache/README.passenger.md b/puphpet/puppet/modules/apache/README.passenger.md
index 5b33d29..c16c5a4 100644
--- a/puphpet/puppet/modules/apache/README.passenger.md
+++ b/puphpet/puppet/modules/apache/README.passenger.md
@@ -13,7 +13,7 @@ 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
+## 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
@@ -35,7 +35,7 @@ RHEL with EPEL6  | 3.0.21             | /usr/lib/ruby/gems/1.8/gems/passenger-3.
 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
+### Configuration files and locations on RHEL/CentOS
 
 Notice two important points:
 
@@ -55,7 +55,7 @@ directives as described in the remainder of this document are placed in
 
 This pertains *only* to RHEL/CentOS, *not* Debian and Ubuntu.
 
-## Third-party and custom Passenger packages and versions
+### 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
@@ -75,7 +75,7 @@ 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`
+## Parameters for `apache::mod::passenger`
 
 The following class parameters configure Passenger in a global, server-wide
 context.
@@ -95,12 +95,12 @@ class { 'apache::mod::passenger':
 The general form is using the all lower-case version of the configuration
 directive, with underscores instead of CamelCase.
 
-## Parameters used with passenger.conf
+### 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
+#### 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
@@ -112,7 +112,7 @@ information.
 
 http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerroot_lt_directory_gt
 
-### passenger_default_ruby
+#### 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
@@ -126,7 +126,7 @@ set to '/usr/bin/ruby'.
 
 http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerDefaultRuby
 
-### passenger_ruby
+#### 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.
@@ -141,28 +141,28 @@ Defaults to `/usr/bin/ruby` for all supported operating systems except Ubuntu
 
 http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerRuby
 
-### passenger_high_performance
+#### 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
+#### 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
+#### 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
+#### 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
@@ -170,14 +170,23 @@ shut down if the Pool Idle Time (see above) expires.
 
 http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerMaxRequests
 
-### passenger_stat_throttle_rate
+#### 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
+#### 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
@@ -186,7 +195,7 @@ Use this directive only on Passenger < 4.x.
 
 http://www.modrails.com/documentation/Users%20guide%20Apache.html#_rackautodetect_lt_on_off_gt
 
-### rails_autodetect
+#### 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
@@ -195,13 +204,13 @@ 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
+#### 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
+#### 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'.
@@ -209,43 +218,43 @@ 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
+### 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
+#### mod_package
 
 Allows overriding the default package name used for the passenger module
 package.
 
-### mod_package_ensure
+#### mod_package_ensure
 
 Allows overriding the package installation setting used by puppet when
 installing the passenger module. The default is 'present'.
 
-### mod_id
+#### mod_id
 
 Allows overriding the value used by apache to identify the passenger module.
 The default is 'passenger_module'.
 
-### mod_lib_path
+#### 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
+#### mod_lib
 
 Allows overriding the library file name used by apache when loading the
 passenger module. The default is 'mod_passenger.so'.
 
-### mod_path
+#### 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
+## Dependencies
 
 RedHat-based systems will need to configure additional package repositories in
 order to install Passenger, specifically:
@@ -256,7 +265,7 @@ order to install Passenger, specifically:
 Configuration of these repositories is beyond the scope of this module and is
 left to the user.
 
-# Attribution
+## 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
@@ -268,7 +277,7 @@ PuppetLabs Apache module on GitHub.
 * http://www.nesi.org.nz//
 * https://tuakiri.ac.nz/confluence/display/Tuakiri/Home
 
-# Copyright and License
+## Copyright and License
 
 Copyright (C) 2012 [Puppet Labs](https://www.puppetlabs.com/) Inc
 
diff --git a/puphpet/puppet/modules/apache/tests/apache.pp b/puphpet/puppet/modules/apache/examples/apache.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/apache.pp
rename to puphpet/puppet/modules/apache/examples/apache.pp
diff --git a/puphpet/puppet/modules/apache/tests/dev.pp b/puphpet/puppet/modules/apache/examples/dev.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/dev.pp
rename to puphpet/puppet/modules/apache/examples/dev.pp
diff --git a/puphpet/puppet/modules/apache/tests/init.pp b/puphpet/puppet/modules/apache/examples/init.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/init.pp
rename to puphpet/puppet/modules/apache/examples/init.pp
diff --git a/puphpet/puppet/modules/apache/tests/mod_load_params.pp b/puphpet/puppet/modules/apache/examples/mod_load_params.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/mod_load_params.pp
rename to puphpet/puppet/modules/apache/examples/mod_load_params.pp
diff --git a/puphpet/puppet/modules/apache/tests/mods.pp b/puphpet/puppet/modules/apache/examples/mods.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/mods.pp
rename to puphpet/puppet/modules/apache/examples/mods.pp
diff --git a/puphpet/puppet/modules/apache/tests/mods_custom.pp b/puphpet/puppet/modules/apache/examples/mods_custom.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/mods_custom.pp
rename to puphpet/puppet/modules/apache/examples/mods_custom.pp
diff --git a/puphpet/puppet/modules/apache/tests/php.pp b/puphpet/puppet/modules/apache/examples/php.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/php.pp
rename to puphpet/puppet/modules/apache/examples/php.pp
diff --git a/puphpet/puppet/modules/apache/tests/vhost.pp b/puphpet/puppet/modules/apache/examples/vhost.pp
similarity index 96%
rename from puphpet/puppet/modules/apache/tests/vhost.pp
rename to puphpet/puppet/modules/apache/examples/vhost.pp
index a46b677..0cf8da7 100644
--- a/puphpet/puppet/modules/apache/tests/vhost.pp
+++ b/puphpet/puppet/modules/apache/examples/vhost.pp
@@ -141,6 +141,7 @@
   rack_base_uris => ['/rackapp1', '/rackapp2'],
 }
 
+
 # Vhost to redirect non-ssl to ssl
 apache::vhost { 'sixteenth.example.com non-ssl':
   servername => 'sixteenth.example.com',
@@ -251,3 +252,10 @@
   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'],
+}
+
diff --git a/puphpet/puppet/modules/apache/tests/vhost_directories.pp b/puphpet/puppet/modules/apache/examples/vhost_directories.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/vhost_directories.pp
rename to puphpet/puppet/modules/apache/examples/vhost_directories.pp
diff --git a/puphpet/puppet/modules/apache/examples/vhost_filter.pp b/puphpet/puppet/modules/apache/examples/vhost_filter.pp
new file mode 100644
index 0000000..ca1a8bb
--- /dev/null
+++ b/puphpet/puppet/modules/apache/examples/vhost_filter.pp
@@ -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',
+  ],
+}
+
diff --git a/puphpet/puppet/modules/apache/tests/vhost_ip_based.pp b/puphpet/puppet/modules/apache/examples/vhost_ip_based.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/vhost_ip_based.pp
rename to puphpet/puppet/modules/apache/examples/vhost_ip_based.pp
diff --git a/puphpet/puppet/modules/apache/tests/vhost_proxypass.pp b/puphpet/puppet/modules/apache/examples/vhost_proxypass.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/vhost_proxypass.pp
rename to puphpet/puppet/modules/apache/examples/vhost_proxypass.pp
diff --git a/puphpet/puppet/modules/apache/tests/vhost_ssl.pp b/puphpet/puppet/modules/apache/examples/vhost_ssl.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/vhost_ssl.pp
rename to puphpet/puppet/modules/apache/examples/vhost_ssl.pp
diff --git a/puphpet/puppet/modules/apache/tests/vhosts_without_listen.pp b/puphpet/puppet/modules/apache/examples/vhosts_without_listen.pp
similarity index 100%
rename from puphpet/puppet/modules/apache/tests/vhosts_without_listen.pp
rename to puphpet/puppet/modules/apache/examples/vhosts_without_listen.pp
diff --git a/puphpet/puppet/modules/apache/lib/puppet/parser/functions/validate_apache_log_level.rb b/puphpet/puppet/modules/apache/lib/puppet/parser/functions/validate_apache_log_level.rb
new file mode 100644
index 0000000..8a1ade0
--- /dev/null
+++ b/puphpet/puppet/modules/apache/lib/puppet/parser/functions/validate_apache_log_level.rb
@@ -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
diff --git a/puphpet/puppet/modules/apache/manifests/custom_config.pp b/puphpet/puppet/modules/apache/manifests/custom_config.pp
index ceb1fd0..7ce755b 100644
--- a/puphpet/puppet/modules/apache/manifests/custom_config.pp
+++ b/puphpet/puppet/modules/apache/manifests/custom_config.pp
@@ -49,12 +49,13 @@
   }
 
   if $ensure == 'present' and $verify_config {
-    exec { "service notify for ${name}":
+    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":
diff --git a/puphpet/puppet/modules/apache/manifests/default_mods.pp b/puphpet/puppet/modules/apache/manifests/default_mods.pp
index 145c4fe..fd057d1 100644
--- a/puphpet/puppet/modules/apache/manifests/default_mods.pp
+++ b/puphpet/puppet/modules/apache/manifests/default_mods.pp
@@ -1,7 +1,8 @@
 class apache::default_mods (
   $all            = true,
   $mods           = undef,
-  $apache_version = $::apache::apache_version
+  $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
@@ -12,8 +13,10 @@
       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' and versioncmp($::operatingsystemrelease, '2014.09') <= 0  ) ) {
-          ::apache::mod { 'systemd': }
+        if ( !($::osfamily == 'redhat' and versioncmp($::operatingsystemrelease, '7.0') == -1) and !($::operatingsystem == 'Amazon') ) {
+          if ($use_systemd) {
+            ::apache::mod { 'systemd': }
+          }
         }
         ::apache::mod { 'unixd': }
       }
@@ -22,6 +25,9 @@
       ::apache::mod { 'log_config': }
       ::apache::mod { 'unixd': }
     }
+    'Suse': {
+      ::apache::mod { 'log_config': }
+    }
     default: {}
   }
   case $::osfamily {
@@ -34,14 +40,17 @@
   if $all {
     case $::osfamily {
       'debian': {
+        include ::apache::mod::authn_core
         include ::apache::mod::reqtimeout
-        if versioncmp($apache_version, '2.4') >= 0 {
-          ::apache::mod { 'authn_core': }
+        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
@@ -55,22 +64,19 @@
         ::apache::mod { 'authz_dbm': }
         ::apache::mod { 'authz_owner': }
         ::apache::mod { 'expires': }
-        ::apache::mod { 'ext_filter': }
         ::apache::mod { 'include': }
         ::apache::mod { 'logio': }
         ::apache::mod { 'substitute': }
         ::apache::mod { 'usertrack': }
 
-        if versioncmp($apache_version, '2.4') >= 0 {
-          ::apache::mod { 'authn_core': }
-        }
-        else {
+        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
@@ -88,7 +94,6 @@
         ::apache::mod { 'auth_digest': }
         ::apache::mod { 'auth_form': }
         ::apache::mod { 'authn_anon': }
-        ::apache::mod { 'authn_core': }
         ::apache::mod { 'authn_dbm': }
         ::apache::mod { 'authn_socache': }
         ::apache::mod { 'authz_dbd': }
diff --git a/puphpet/puppet/modules/apache/manifests/dev.pp b/puphpet/puppet/modules/apache/manifests/dev.pp
index 4eaeb55..fdebf59 100644
--- a/puphpet/puppet/modules/apache/manifests/dev.pp
+++ b/puphpet/puppet/modules/apache/manifests/dev.pp
@@ -1,11 +1,10 @@
 class apache::dev {
-  if $::osfamily == 'FreeBSD' and !defined(Class['apache::package']) {
-    fail('apache::dev requires apache::package; please include apache or apache::package class first')
-  }
   include ::apache::params
-  $packages = $::apache::params::dev_packages
-  package { $packages:
-    ensure  => present,
-    require => Package['httpd'],
+  $packages = $::apache::dev_packages
+  if $packages { # FreeBSD doesn't have dev packages to install
+    package { $packages:
+      ensure  => present,
+      require => Package['httpd'],
+    }
   }
 }
diff --git a/puphpet/puppet/modules/apache/manifests/init.pp b/puphpet/puppet/modules/apache/manifests/init.pp
index 0b8544f..6aaa57c 100644
--- a/puphpet/puppet/modules/apache/manifests/init.pp
+++ b/puphpet/puppet/modules/apache/manifests/init.pp
@@ -28,10 +28,12 @@
   $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,
@@ -45,11 +47,15 @@
   $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,
@@ -70,6 +76,7 @@
   $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)
@@ -124,16 +131,14 @@
     }
   }
 
-  $valid_log_level_re = '(emerg|alert|crit|error|warn|notice|info|debug)'
-
-  validate_re($log_level, $valid_log_level_re,
-  "Log level '${log_level}' is not one of the supported Apache HTTP Server log levels.")
+  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_name    => $service_name,
+    service_enable  => $service_enable,
+    service_manage  => $service_manage,
+    service_ensure  => $service_ensure,
+    service_restart => $service_restart,
   }
 
   # Deprecated backwards-compatibility
@@ -247,24 +252,20 @@
   if $::apache::conf_dir and $::apache::params::conf_file {
     case $::osfamily {
       'debian': {
-        $pidfile              = "\${APACHE_PID_FILE}"
         $error_log            = 'error.log'
         $scriptalias          = '/usr/lib/cgi-bin'
         $access_log_file      = 'access.log'
       }
       'redhat': {
-        $pidfile              = 'run/httpd.pid'
         $error_log            = 'error_log'
         $scriptalias          = '/var/www/cgi-bin'
         $access_log_file      = 'access_log'
       }
       'freebsd': {
-        $pidfile              = '/var/run/httpd.pid'
         $error_log            = 'httpd-error.log'
         $scriptalias          = '/usr/local/www/apache24/cgi-bin'
         $access_log_file      = 'httpd-access.log'
       } 'gentoo': {
-        $pidfile              = '/run/apache2.pid'
         $error_log            = 'error.log'
         $error_documents_path = '/usr/share/apache2/error'
         $scriptalias          = '/var/www/localhost/cgi-bin'
@@ -281,6 +282,11 @@
           require => Package['httpd'],
         }
       }
+      'Suse': {
+        $error_log            = 'error.log'
+        $scriptalias          = '/usr/lib/cgi-bin'
+        $access_log_file      = 'access.log'
+      }
       default: {
         fail("Unsupported osfamily ${::osfamily}")
       }
@@ -291,6 +297,10 @@
       default   => false
     }
 
+    if $rewrite_lock {
+      validate_absolute_path($rewrite_lock)
+    }
+
     # Template uses:
     # - $pidfile
     # - $user
@@ -312,11 +322,12 @@
     # - $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'],
+      require => [Package['httpd'], File[$ports_file]],
     }
 
     # preserve back-wards compatibility to the times when default_mods was
@@ -377,4 +388,8 @@
       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': }
 }
diff --git a/puphpet/puppet/modules/apache/manifests/mod.pp b/puphpet/puppet/modules/apache/manifests/mod.pp
index 0891bf0..abdbfcb 100644
--- a/puphpet/puppet/modules/apache/manifests/mod.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod.pp
@@ -2,7 +2,7 @@
   $package        = undef,
   $package_ensure = 'present',
   $lib            = undef,
-  $lib_path       = $::apache::params::lib_path,
+  $lib_path       = $::apache::lib_path,
   $id             = undef,
   $path           = undef,
   $loadfile_name  = undef,
@@ -126,5 +126,42 @@
         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']
 }
diff --git a/puphpet/puppet/modules/apache/manifests/mod/alias.pp b/puphpet/puppet/modules/apache/manifests/mod/alias.pp
index c1f60fd..5b59baa 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/alias.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/alias.pp
@@ -1,26 +1,20 @@
 class apache::mod::alias(
   $apache_version = $apache::apache_version,
   $icons_options  = 'Indexes MultiViews',
-) {
-  $ver24 = versioncmp($apache_version, '2.4') >= 0
+  # set icons_path to false to disable the alias
+  $icons_path     = $::apache::params::alias_icons_path,
 
-  $icons_path = $::osfamily ? {
-    'debian'  => '/usr/share/apache2/icons',
-    'redhat'  => $ver24 ? {
-      true    => '/usr/share/httpd/icons',
-      default => '/var/www/icons',
-    },
-    'freebsd' => '/usr/local/www/apache24/icons',
-    'gentoo'  => '/usr/share/apache2/icons',
-  }
+) {
   apache::mod { 'alias': }
   # Template uses $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'],
+  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'],
+    }
   }
 }
diff --git a/puphpet/puppet/modules/apache/manifests/mod/auth_mellon.pp b/puphpet/puppet/modules/apache/manifests/mod/auth_mellon.pp
new file mode 100644
index 0000000..79f6ffe
--- /dev/null
+++ b/puphpet/puppet/modules/apache/manifests/mod/auth_mellon.pp
@@ -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'],
+  }
+
+}
diff --git a/puphpet/puppet/modules/apache/manifests/mod/authn_core.pp b/puphpet/puppet/modules/apache/manifests/mod/authn_core.pp
new file mode 100644
index 0000000..c5ce5b1
--- /dev/null
+++ b/puphpet/puppet/modules/apache/manifests/mod/authn_core.pp
@@ -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': }
+  }
+}
diff --git a/puphpet/puppet/modules/apache/manifests/mod/authz_default.pp b/puphpet/puppet/modules/apache/manifests/mod/authz_default.pp
index 23edd9b..e457774 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/authz_default.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/authz_default.pp
@@ -1,3 +1,9 @@
-class apache::mod::authz_default {
-  ::apache::mod { 'authz_default': }
+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': }
+  }
 }
diff --git a/puphpet/puppet/modules/apache/manifests/mod/cgid.pp b/puphpet/puppet/modules/apache/manifests/mod/cgid.pp
index 8946f65..4094c32 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/cgid.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/cgid.pp
@@ -2,7 +2,11 @@
   case $::osfamily {
     'FreeBSD': {}
     default: {
-      Class['::apache::mod::worker'] -> Class['::apache::mod::cgid']
+      if defined(Class['::apache::mod::event']) {
+        Class['::apache::mod::event'] -> Class['::apache::mod::cgid']
+      } else {
+        Class['::apache::mod::worker'] -> Class['::apache::mod::cgid']
+      }
     }
   }
 
diff --git a/puphpet/puppet/modules/apache/manifests/mod/deflate.pp b/puphpet/puppet/modules/apache/manifests/mod/deflate.pp
index 9b8d436..0748a54 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/deflate.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/deflate.pp
@@ -3,7 +3,8 @@
     'text/html text/plain text/xml',
     'text/css',
     'application/x-javascript application/javascript application/ecmascript',
-    'application/rss+xml'
+    'application/rss+xml',
+    'application/json'
   ],
   $notes = {
     'Input'  => 'instream',
diff --git a/puphpet/puppet/modules/apache/manifests/mod/disk_cache.pp b/puphpet/puppet/modules/apache/manifests/mod/disk_cache.pp
index 2b9d8a9..2f0a476 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/disk_cache.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/disk_cache.pp
@@ -1,25 +1,34 @@
-class apache::mod::disk_cache {
-  $cache_root = $::osfamily ? {
-    'debian'  => '/var/cache/apache2/mod_disk_cache',
-    'redhat'  => '/var/cache/mod_proxy',
-    'freebsd' => '/var/cache/mod_disk_cache',
-    'gentoo'  => '/var/cache/apache2/mod_disk_cache',
+class apache::mod::disk_cache (
+  $cache_root = undef,
+) {
+  if $cache_root {
+    $_cache_root = $cache_root
   }
-
-  $mod_name = $::osfamily ? {
-    'FreeBSD' => 'cache_disk',
-    default   => 'disk_cache',
+  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 $::osfamily != 'FreeBSD' {
-    # FIXME: investigate why disk_cache was dependent on proxy
-    # NOTE: on FreeBSD disk_cache is compiled by default but proxy is not
-    Class['::apache::mod::proxy'] -> Class['::apache::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']
 
-  apache::mod { $mod_name: }
-  # Template uses $cache_proxy
+  # Template uses $_cache_root
   file { 'disk_cache.conf':
     ensure  => file,
     path    => "${::apache::mod_dir}/disk_cache.conf",
diff --git a/puphpet/puppet/modules/apache/manifests/mod/expires.pp b/puphpet/puppet/modules/apache/manifests/mod/expires.pp
index aae4c59..1054291 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/expires.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/expires.pp
@@ -1,3 +1,20 @@
-class apache::mod::expires {
+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'],
+  }
 }
diff --git a/puphpet/puppet/modules/apache/manifests/mod/ext_filter.pp b/puphpet/puppet/modules/apache/manifests/mod/ext_filter.pp
new file mode 100644
index 0000000..b78abb6
--- /dev/null
+++ b/puphpet/puppet/modules/apache/manifests/mod/ext_filter.pp
@@ -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'],
+    }
+  }
+}
diff --git a/puphpet/puppet/modules/apache/manifests/mod/fcgid.pp b/puphpet/puppet/modules/apache/manifests/mod/fcgid.pp
index a143c2b..9786670 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/fcgid.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/fcgid.pp
@@ -1,22 +1,17 @@
 class apache::mod::fcgid(
   $options = {},
 ) {
-  if $::osfamily == 'RedHat' and $::operatingsystemmajrelease == '7' {
-    $loadfile_name = 'unixd_fcgid.load'
-  } else {
-    $loadfile_name = undef
-  }
 
   ::apache::mod { 'fcgid':
-    loadfile_name => $loadfile_name
+    loadfile_name => 'unixd_fcgid.load',
   }
 
   # Template uses:
   # - $options
-  file { 'fcgid.conf':
+  file { 'unixd_fcgid.conf':
     ensure  => file,
-    path    => "${::apache::mod_dir}/fcgid.conf",
-    content => template('apache/mod/fcgid.conf.erb'),
+    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'],
diff --git a/puphpet/puppet/modules/apache/manifests/mod/geoip.pp b/puphpet/puppet/modules/apache/manifests/mod/geoip.pp
new file mode 100644
index 0000000..1f8fb08
--- /dev/null
+++ b/puphpet/puppet/modules/apache/manifests/mod/geoip.pp
@@ -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'],
+  }
+
+}
diff --git a/puphpet/puppet/modules/apache/manifests/mod/passenger.pp b/puphpet/puppet/modules/apache/manifests/mod/passenger.pp
index 03cce4d..efd3486 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/passenger.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/passenger.pp
@@ -4,6 +4,7 @@
   $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,
@@ -21,6 +22,11 @@
   $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':
@@ -61,6 +67,7 @@
   # - $passenger_min_instances
   # - $passenger_high_performance
   # - $passenger_max_requests
+  # - $passenger_spawn_method
   # - $passenger_stat_throttle_rate
   # - $passenger_use_global_queue
   # - $passenger_app_env
diff --git a/puphpet/puppet/modules/apache/manifests/mod/prefork.pp b/puphpet/puppet/modules/apache/manifests/mod/prefork.pp
index 035e881..91567de 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/prefork.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/prefork.pp
@@ -60,7 +60,7 @@
         }
       }
     }
-    'debian', 'freebsd' : {
+    'debian', 'freebsd', 'Suse' : {
       ::apache::mpm{ 'prefork':
         apache_version => $apache_version,
       }
diff --git a/puphpet/puppet/modules/apache/manifests/mod/proxy_connect.pp b/puphpet/puppet/modules/apache/manifests/mod/proxy_connect.pp
index 3bae848..7adef1f 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/proxy_connect.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/proxy_connect.pp
@@ -1,7 +1,7 @@
 class apache::mod::proxy_connect (
   $apache_version  = $::apache::apache_version,
 ) {
-  if versioncmp($apache_version, '2.4') >= 0 {
+  if versioncmp($apache_version, '2.2') >= 0 {
     Class['::apache::mod::proxy'] -> Class['::apache::mod::proxy_connect']
     ::apache::mod { 'proxy_connect': }
   }
diff --git a/puphpet/puppet/modules/apache/manifests/mod/remoteip.pp b/puphpet/puppet/modules/apache/manifests/mod/remoteip.pp
new file mode 100644
index 0000000..564390e
--- /dev/null
+++ b/puphpet/puppet/modules/apache/manifests/mod/remoteip.pp
@@ -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'],
+  }
+}
diff --git a/puphpet/puppet/modules/apache/manifests/mod/security.pp b/puphpet/puppet/modules/apache/manifests/mod/security.pp
index 84e55e2..050b1bd 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/security.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/security.pp
@@ -2,6 +2,7 @@
   $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/',
diff --git a/puphpet/puppet/modules/apache/manifests/mod/ssl.pp b/puphpet/puppet/modules/apache/manifests/mod/ssl.pp
index 4a6b823..a653bad 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/ssl.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/ssl.pp
@@ -2,7 +2,8 @@
   $ssl_compression         = false,
   $ssl_cryptodevice        = 'builtin',
   $ssl_options             = [ 'StdEnvVars' ],
-  $ssl_cipher              = 'HIGH:MEDIUM:!aNULL:!MD5',
+  $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',
@@ -11,12 +12,6 @@
   $apache_version          = $::apache::apache_version,
   $package_name            = undef,
 ) {
-  $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)',
-  }
 
   case $::osfamily {
     'debian': {
@@ -37,11 +32,22 @@
     '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,
   }
@@ -57,6 +63,7 @@
   # $ssl_cipher
   # $ssl_honorcipherorder
   # $ssl_options
+  # $ssl_openssl_conf_cmd
   # $session_cache
   # $ssl_mutex
   # $ssl_random_seed_bytes
diff --git a/puphpet/puppet/modules/apache/manifests/mod/userdir.pp b/puphpet/puppet/modules/apache/manifests/mod/userdir.pp
index 038e079..4b3d0b8 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/userdir.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/userdir.pp
@@ -3,6 +3,7 @@
   $dir = 'public_html',
   $disable_root = true,
   $apache_version = $::apache::apache_version,
+  $options = [ 'MultiViews', 'Indexes', 'SymLinksIfOwnerMatch', 'IncludesNoExec' ],
 ) {
   ::apache::mod { 'userdir': }
 
diff --git a/puphpet/puppet/modules/apache/manifests/mod/worker.pp b/puphpet/puppet/modules/apache/manifests/mod/worker.pp
index 02a1bea..2e6a642 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/worker.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/worker.pp
@@ -1,3 +1,57 @@
+# == 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',
@@ -7,6 +61,7 @@
   $maxrequestsperchild = '0',
   $serverlimit         = '25',
   $threadlimit         = '64',
+  $listenbacklog       = '511',
   $apache_version      = $::apache::apache_version,
 ) {
   if defined(Class['apache::mod::event']) {
@@ -36,6 +91,7 @@
   # - $maxrequestsperchild
   # - $serverlimit
   # - $threadLimit
+  # - $listenbacklog
   file { "${::apache::mod_dir}/worker.conf":
     ensure  => file,
     content => template('apache/mod/worker.conf.erb'),
@@ -62,7 +118,7 @@
         }
       }
     }
-    'debian', 'freebsd': {
+    'debian', 'freebsd', 'Suse': {
       ::apache::mpm{ 'worker':
         apache_version => $apache_version,
       }
diff --git a/puphpet/puppet/modules/apache/manifests/mod/wsgi.pp b/puphpet/puppet/modules/apache/manifests/mod/wsgi.pp
index 80f9738..bff5b46 100644
--- a/puphpet/puppet/modules/apache/manifests/mod/wsgi.pp
+++ b/puphpet/puppet/modules/apache/manifests/mod/wsgi.pp
@@ -14,7 +14,7 @@
     if $mod_path =~ /\// {
       $_mod_path = $mod_path
     } else {
-      $_mod_path = "${::apache::params::lib_path}/${mod_path}"
+      $_mod_path = "${::apache::lib_path}/${mod_path}"
     }
     ::apache::mod { 'wsgi':
       package => $package_name,
diff --git a/puphpet/puppet/modules/apache/manifests/mpm.pp b/puphpet/puppet/modules/apache/manifests/mpm.pp
index a5cca49..9e77349 100644
--- a/puphpet/puppet/modules/apache/manifests/mpm.pp
+++ b/puphpet/puppet/modules/apache/manifests/mpm.pp
@@ -1,5 +1,5 @@
 define apache::mpm (
-  $lib_path       = $::apache::params::lib_path,
+  $lib_path       = $::apache::lib_path,
   $apache_version = $::apache::apache_version,
 ) {
   if ! defined(Class['apache']) {
@@ -68,6 +68,38 @@
     '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}")
     }
diff --git a/puphpet/puppet/modules/apache/manifests/package.pp b/puphpet/puppet/modules/apache/manifests/package.pp
index 395c031..5c59f25 100644
--- a/puphpet/puppet/modules/apache/manifests/package.pp
+++ b/puphpet/puppet/modules/apache/manifests/package.pp
@@ -2,6 +2,12 @@
   $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 {
@@ -11,11 +17,11 @@
         }
         'worker': {
           $set = 'MPM_WORKER'
-          $unset = 'MPM_PERFORK MPM_EVENT'
+          $unset = 'MPM_PREFORK MPM_EVENT'
         }
         'event': {
           $set = 'MPM_EVENT'
-          $unset = 'MPM_PERFORK MPM_WORKER'
+          $unset = 'MPM_PREFORK MPM_WORKER'
         }
         'itk': {
           $set = undef
@@ -44,10 +50,10 @@
           before => Package['httpd'],
         }
       }
-      $apache_package = $::apache::params::apache_name
+      $apache_package = $::apache::apache_name
     }
     default: {
-      $apache_package = $::apache::params::apache_name
+      $apache_package = $::apache::apache_name
     }
   }
 
diff --git a/puphpet/puppet/modules/apache/manifests/params.pp b/puphpet/puppet/modules/apache/manifests/params.pp
index 54b74e6..36d2815 100644
--- a/puphpet/puppet/modules/apache/manifests/params.pp
+++ b/puphpet/puppet/modules/apache/manifests/params.pp
@@ -29,6 +29,11 @@
   $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 {
@@ -50,6 +55,7 @@
     $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'
@@ -71,12 +77,14 @@
     $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,
@@ -112,6 +120,10 @@
     $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'
@@ -122,9 +134,13 @@
       $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',
@@ -164,6 +180,7 @@
     $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'
@@ -177,9 +194,11 @@
     $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',
@@ -204,11 +223,19 @@
     $fastcgi_lib_path       = '/var/lib/apache2/fastcgi'
     $mime_support_package = 'mime-support'
     $mime_types_config    = '/etc/mime.types'
-    $docroot              = '/var/www'
+    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',
@@ -232,6 +259,7 @@
       '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']
@@ -307,6 +335,7 @@
     $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'
@@ -354,6 +383,7 @@
     $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'
@@ -415,7 +445,73 @@
     $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}")
   }
diff --git a/puphpet/puppet/modules/apache/manifests/service.pp b/puphpet/puppet/modules/apache/manifests/service.pp
index d934f3d..7080279 100644
--- a/puphpet/puppet/modules/apache/manifests/service.pp
+++ b/puphpet/puppet/modules/apache/manifests/service.pp
@@ -21,6 +21,7 @@
   $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']) {
@@ -39,9 +40,10 @@
   }
   if $service_manage {
     service { 'httpd':
-      ensure => $_service_ensure,
-      name   => $service_name,
-      enable => $service_enable,
+      ensure  => $_service_ensure,
+      name    => $service_name,
+      enable  => $service_enable,
+      restart => $service_restart
     }
   }
 }
diff --git a/puphpet/puppet/modules/apache/manifests/version.pp b/puphpet/puppet/modules/apache/manifests/version.pp
index ce3b907..527dc6d 100644
--- a/puphpet/puppet/modules/apache/manifests/version.pp
+++ b/puphpet/puppet/modules/apache/manifests/version.pp
@@ -3,7 +3,7 @@
 # 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, 3 on Amazon, etc.
+  # 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 {
@@ -12,7 +12,9 @@
 
   case $::osfamily {
     'RedHat': {
-      if ($::operatingsystem == 'Fedora' and versioncmp($distrelease, '18') >= 0) or ($::operatingsystem != 'Fedora' and versioncmp($distrelease, '7') >= 0) {
+      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'
@@ -33,6 +35,9 @@
     'Gentoo': {
       $default = '2.4'
     }
+    'Suse': {
+      $default = '2.2'
+    }
     default: {
       fail("Class['apache::version']: Unsupported osfamily: ${::osfamily}")
     }
diff --git a/puphpet/puppet/modules/apache/manifests/vhost.pp b/puphpet/puppet/modules/apache/manifests/vhost.pp
index 70d2a57..4556015 100644
--- a/puphpet/puppet/modules/apache/manifests/vhost.pp
+++ b/puphpet/puppet/modules/apache/manifests/vhost.pp
@@ -25,7 +25,9 @@
   $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,
@@ -79,8 +81,10 @@
   $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,
@@ -105,6 +109,7 @@
   $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,
@@ -119,13 +124,21 @@
   $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::params::apache_name
+  $apache_name = $::apache::apache_name
 
   validate_re($ensure, '^(present|absent)$',
   "${ensure} is not supported for ensure.
@@ -147,7 +160,7 @@
   # Input validation begins
 
   if $suexec_user_group {
-    validate_re($suexec_user_group, '^\w+ \w+$',
+    validate_re($suexec_user_group, '^[\w-]+ [\w-]+$',
     "${suexec_user_group} is not supported for suexec_user_group.  Must be 'user group'.")
   }
 
@@ -186,8 +199,7 @@
   Allowed values are 'directory' and 'absent'.")
 
   if $log_level {
-    validate_re($log_level, '^(emerg|alert|crit|error|warn|notice|info|debug)$',
-    "Log level '${log_level}' is not one of the supported Apache HTTP Server log levels.")
+    validate_apache_log_level($log_level)
   }
 
   if $access_log_file and $access_log_pipe {
@@ -210,6 +222,17 @@
     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' {
@@ -218,6 +241,10 @@
     include ::apache::mod::mime
   }
 
+  if $auth_kerb and $ensure == 'present' {
+    include ::apache::mod::auth_kerb
+  }
+
   if $virtual_docroot {
     include ::apache::mod::vhost_alias
   }
@@ -250,7 +277,7 @@
 
   # This ensures that the docroot exists
   # But enables it to be specified across multiple vhost resources
-  if ! defined(File[$docroot]) and $manage_docroot {
+  if $manage_docroot and $docroot and ! defined(File[$docroot]) {
     file { $docroot:
       ensure  => directory,
       owner   => $docroot_owner,
@@ -318,8 +345,8 @@
 
   if $ip {
     if $port {
-      $listen_addr_port = "${ip}:${port}"
-      $nvh_addr_port = "${ip}:${port}"
+      $listen_addr_port = suffix(any2array($ip),":${port}")
+      $nvh_addr_port = suffix(any2array($ip),":${port}")
     } else {
       $listen_addr_port = undef
       $nvh_addr_port = $ip
@@ -343,13 +370,13 @@
     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 ! defined(Apache::Listen["${listen_addr_port}"]) and $listen_addr_port and $ensure == 'present' {
-      ::apache::listen { "${listen_addr_port}": }
+    if $listen_addr_port and $ensure == 'present' {
+      ensure_resource('apache::listen', $listen_addr_port)
     }
   }
   if ! $ip_based {
-    if ! defined(Apache::Namevirtualhost[$nvh_addr_port]) and $ensure == 'present' and (versioncmp($apache_version, '2.4') < 0) {
-      ::apache::namevirtualhost { $nvh_addr_port: }
+    if $ensure == 'present' and (versioncmp($apache_version, '2.4') < 0) {
+      ensure_resource('apache::namevirtualhost', $nvh_addr_port)
     }
   }
 
@@ -361,8 +388,8 @@
   }
 
   # Load mod_alias if needed and not yet loaded
-  if ($scriptalias or $scriptaliases != []) or ($redirect_source and $redirect_dest) {
-    if ! defined(Class['apache::mod::alias']) {
+  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
     }
   }
@@ -384,6 +411,11 @@
     }
   }
 
+  # 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']) {
@@ -398,6 +430,13 @@
     }
   }
 
+  # 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
@@ -410,7 +449,7 @@
       fail("Apache::Vhost[${name}]: 'directories' must be either a Hash or an Array of Hashes")
     }
     $_directories = $directories
-  } else {
+  } elsif $docroot {
     $_directory = {
       provider       => 'directory',
       path           => $docroot,
@@ -485,10 +524,12 @@
   # Template uses:
   # - $virtual_docroot
   # - $docroot
-  concat::fragment { "${name}-docroot":
-    target  => "${priority_real}${filename}.conf",
-    order   => 10,
-    content => template('apache/vhost/_docroot.erb'),
+  if $docroot {
+    concat::fragment { "${name}-docroot":
+      target  => "${priority_real}${filename}.conf",
+      order   => 10,
+      content => template('apache/vhost/_docroot.erb'),
+    }
   }
 
   # Template uses:
@@ -625,9 +666,10 @@
   # Template uses:
   # - $proxy_dest
   # - $proxy_pass
+  # - $proxy_pass_match
   # - $proxy_preserve_host
   # - $no_proxy_uris
-  if $proxy_dest or $proxy_pass {
+  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,
@@ -645,6 +687,16 @@
     }
   }
 
+  # 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
@@ -728,7 +780,9 @@
   # - $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":
@@ -738,6 +792,22 @@
     }
   }
 
+  # 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
@@ -880,6 +950,25 @@
     }
   }
 
+  # 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",
diff --git a/puphpet/puppet/modules/apache/metadata.json b/puphpet/puppet/modules/apache/metadata.json
index feb7daa..85e6889 100644
--- a/puphpet/puppet/modules/apache/metadata.json
+++ b/puphpet/puppet/modules/apache/metadata.json
@@ -1,12 +1,16 @@
 {
   "name": "puppetlabs-apache",
-  "version": "1.4.0",
+  "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",
@@ -46,6 +50,12 @@
         "7"
       ]
     },
+    {
+      "operatingsystem": "SLES",
+      "operatingsystemrelease": [
+        "11 SP1"
+      ]
+    },
     {
       "operatingsystem": "Ubuntu",
       "operatingsystemrelease": [
@@ -58,16 +68,12 @@
   "requirements": [
     {
       "name": "pe",
-      "version_requirement": "3.x"
+      "version_requirement": ">= 3.7.0 < 2015.4.0"
     },
     {
       "name": "puppet",
-      "version_requirement": "3.x"
+      "version_requirement": ">= 3.0.0 < 5.0.0"
     }
   ],
-  "description": "Module for Apache configuration",
-  "dependencies": [
-    {"name":"puppetlabs/stdlib","version_requirement":">= 2.4.0 < 5.0.0"},
-    {"name":"puppetlabs/concat","version_requirement":">= 1.1.1 < 2.0.0"}
-  ]
+  "description": "Module for Apache configuration"
 }
diff --git a/puphpet/puppet/modules/apache/spec/acceptance/apache_parameters_spec.rb b/puphpet/puppet/modules/apache/spec/acceptance/apache_parameters_spec.rb
index 4c6fa7f..c46a220 100644
--- a/puphpet/puppet/modules/apache/spec/acceptance/apache_parameters_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/acceptance/apache_parameters_spec.rb
@@ -358,7 +358,7 @@ class { 'apache':
     describe 'setup' do
       it 'applies cleanly' do
         pp = <<-EOS
-          if $::osfamily == 'RedHat' and $::selinux {
+          if $::osfamily == 'RedHat' and "$::selinux" == "true" {
             $semanage_package = $::operatingsystemmajrelease ? {
               '5'     => 'policycoreutils',
               default => 'policycoreutils-python',
diff --git a/puphpet/puppet/modules/apache/spec/acceptance/basic_spec.rb b/puphpet/puppet/modules/apache/spec/acceptance/basic_spec.rb
deleted file mode 100644
index 6c2b3f4..0000000
--- a/puphpet/puppet/modules/apache/spec/acceptance/basic_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require 'spec_helper_acceptance'
-
-describe 'disable selinux:', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do
-  it "because otherwise apache won't work" do
-    apply_manifest(%{
-      exec { "setenforce 0":
-        path   => "/bin:/sbin:/usr/bin:/usr/sbin",
-        onlyif => "which setenforce && getenforce | grep Enforcing",
-      }
-    }, :catch_failures => true)
-  end
-end
diff --git a/puphpet/puppet/modules/apache/spec/acceptance/class_spec.rb b/puphpet/puppet/modules/apache/spec/acceptance/class_spec.rb
index 0a7d67b..0cf1c36 100644
--- a/puphpet/puppet/modules/apache/spec/acceptance/class_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/acceptance/class_spec.rb
@@ -45,7 +45,7 @@ class { 'apache': }
     # Using puppet_apply as a helper
     it 'should work with no errors' do
       pp = <<-EOS
-      if $::osfamily == 'RedHat' and $::selinux {
+      if $::osfamily == 'RedHat' and "$::selinux" == "true" {
         $semanage_package = $::operatingsystemmajrelease ? {
           '5'     => 'policycoreutils',
           default => 'policycoreutils-python',
diff --git a/puphpet/puppet/modules/apache/spec/acceptance/custom_config_spec.rb b/puphpet/puppet/modules/apache/spec/acceptance/custom_config_spec.rb
index 8b59f70..d4526e8 100644
--- a/puphpet/puppet/modules/apache/spec/acceptance/custom_config_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/acceptance/custom_config_spec.rb
@@ -52,4 +52,25 @@ class { 'apache': }
       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
diff --git a/puphpet/puppet/modules/apache/spec/acceptance/mod_passenger_spec.rb b/puphpet/puppet/modules/apache/spec/acceptance/mod_passenger_spec.rb
index 7b2d0da..5af9113 100644
--- a/puphpet/puppet/modules/apache/spec/acceptance/mod_passenger_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/acceptance/mod_passenger_spec.rb
@@ -194,115 +194,5 @@ class { 'apache::mod::passenger': }
       end
 
     end
-
-  when 'RedHat'
-    # no fedora 18 passenger package yet, and rhel5 packages only exist for ruby 1.8.5
-    unless (fact('operatingsystem') == 'Fedora' and fact('operatingsystemrelease').to_f >= 18) or (fact('osfamily') == 'RedHat' and fact('operatingsystemmajrelease') == '5' and fact('rubyversion') != '1.8.5')
-
-      if fact('osfamily') == 'RedHat' and fact('operatingsystemmajrelease') == '7'
-        pending('test passenger - RHEL7 packages don\'t exist')
-      else
-        context "default passenger config" do
-          it 'succeeds in puppeting passenger' do
-            pp = <<-EOS
-              /* EPEL and passenger repositories */
-              class { 'epel': }
-              exec { 'passenger.repo GPG key':
-                command => '/usr/bin/curl -o /etc/yum.repos.d/RPM-GPG-KEY-stealthymonkeys.asc http://passenger.stealthymonkeys.com/RPM-GPG-KEY-stealthymonkeys.asc',
-                creates => '/etc/yum.repos.d/RPM-GPG-KEY-stealthymonkeys.asc',
-              }
-              file { 'passenger.repo GPG key':
-                ensure  => file,
-                path    => '/etc/yum.repos.d/RPM-GPG-KEY-stealthymonkeys.asc',
-                require => Exec['passenger.repo GPG key'],
-              }
-              epel::rpm_gpg_key { 'passenger.stealthymonkeys.com':
-                path    => '/etc/yum.repos.d/RPM-GPG-KEY-stealthymonkeys.asc',
-                require => [
-                  Class['epel'],
-                  File['passenger.repo GPG key'],
-                ]
-              }
-              $releasever_string = $operatingsystem ? {
-                'Scientific' => '6',
-                default      => '$releasever',
-              }
-              yumrepo { 'passenger':
-                baseurl         => "http://passenger.stealthymonkeys.com/rhel/${releasever_string}/\\$basearch" ,
-                descr           => "Red Hat Enterprise ${releasever_string} - Phusion Passenger",
-                enabled         => 1,
-                gpgcheck        => 1,
-                gpgkey          => 'http://passenger.stealthymonkeys.com/RPM-GPG-KEY-stealthymonkeys.asc',
-                mirrorlist      => 'http://passenger.stealthymonkeys.com/rhel/mirrors',
-                require => [
-                  Epel::Rpm_gpg_key['passenger.stealthymonkeys.com'],
-                ],
-              }
-              /* apache and mod_passenger */
-              class { 'apache':
-                  require => [
-                    Class['epel'],
-                ],
-              }
-              class { 'apache::mod::passenger':
-                require => [
-                  Yumrepo['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}" }
-            it { is_expected.to contain "PassengerRuby #{passenger_ruby}" }
-            it { is_expected.to contain "PassengerTempDir #{passenger_tempdir}" }
-          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("/usr/bin/passenger-memory-stats", :pty => true) do |r|
-              expect(r.stdout).to match(/Apache processes/)
-              expect(r.stdout).to match(/Nginx processes/)
-              expect(r.stdout).to match(/Passenger processes/)
-              expect(r.stdout).to match(/### Processes: [0-9]+/)
-              expect(r.stdout).to match(/### Total private dirty RSS: [0-9\.]+ MB/)
-
-              expect(r.exit_code).to eq(0)
-            end
-          end
-
-          it 'should output status via passenger-status' do
-            shell("PASSENGER_TMPDIR=/var/run/rubygem-passenger /usr/bin/passenger-status") do |r|
-              # spacing may vary
-              r.stdout.should =~ /[\-]+ General information [\-]+/
-              r.stdout.should =~ /max[ ]+= [0-9]+/
-              r.stdout.should =~ /count[ ]+= [0-9]+/
-              r.stdout.should =~ /active[ ]+= [0-9]+/
-              r.stdout.should =~ /inactive[ ]+= [0-9]+/
-              r.stdout.should =~ /Waiting on global queue: [0-9]+/
-
-              r.exit_code.should == 0
-            end
-          end
-
-          it 'should answer to passenger.example.com' do
-            shell("/usr/bin/curl passenger.example.com:80") do |r|
-              r.stdout.should =~ /^hello world<\/b>$/
-              r.exit_code.should == 0
-            end
-          end
-        end
-      end
-    end
   end
 end
diff --git a/puphpet/puppet/modules/apache/spec/acceptance/mod_security_spec.rb b/puphpet/puppet/modules/apache/spec/acceptance/mod_security_spec.rb
index 6029578..67ad7d5 100644
--- a/puphpet/puppet/modules/apache/spec/acceptance/mod_security_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/acceptance/mod_security_spec.rb
@@ -1,6 +1,6 @@
 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'))) do
+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'
@@ -18,6 +18,18 @@
         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
@@ -35,6 +47,11 @@ class { 'apache::mod::security': }
         }
       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
@@ -50,15 +67,17 @@ class { 'apache::mod::security': }
       it { is_expected.to contain "mod_security2.c" }
     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)
+    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
-    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]
+      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
diff --git a/puphpet/puppet/modules/apache/spec/acceptance/nodesets/default.yml b/puphpet/puppet/modules/apache/spec/acceptance/nodesets/default.yml
index ce47212..00e141d 100644
--- a/puphpet/puppet/modules/apache/spec/acceptance/nodesets/default.yml
+++ b/puphpet/puppet/modules/apache/spec/acceptance/nodesets/default.yml
@@ -1,10 +1,9 @@
 HOSTS:
-  centos-64-x64:
+  centos-66-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
+    box : puppetlabs/centos-6.6-64-nocm
     hypervisor : vagrant
 CONFIG:
   log_level: debug
diff --git a/puphpet/puppet/modules/apache/spec/acceptance/vhost_spec.rb b/puphpet/puppet/modules/apache/spec/acceptance/vhost_spec.rb
index 6fe87c5..c4a34b1 100644
--- a/puphpet/puppet/modules/apache/spec/acceptance/vhost_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/acceptance/vhost_spec.rb
@@ -119,6 +119,33 @@ class { 'apache': }
     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 '' }
+      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 "" }
+    end
+  end
+
   context 'new vhost on port 80' do
     it 'should configure two apache vhosts' do
       pp = <<-EOS
@@ -163,6 +190,59 @@ class { 'apache': }
     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 '' }
+      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
@@ -498,6 +578,47 @@ class { 'apache': default_vhost => false, }
     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
@@ -937,40 +1058,6 @@ class { 'apache': }
     end
   end
 
-  # Passenger isn't even in EPEL on el-5
-  if default['platform'] !~ /^el-5/
-    if fact('osfamily') == 'RedHat' and fact('operatingsystemmajrelease') == '7'
-      pending('Since we don\'t have passenger on RHEL7 rack_base_uris tests will fail')
-    else
-      describe 'rack_base_uris' do
-        if fact('osfamily') == 'RedHat'
-          it 'adds epel' do
-            pp = "class { 'epel': }"
-            apply_manifest(pp, :catch_failures => true)
-          end
-        end
-
-        it 'applies cleanly' do
-          pp = <<-EOS
-            class { 'apache': }
-            host { 'test.server': ip => '127.0.0.1' }
-            apache::vhost { 'test.server':
-              docroot          => '/tmp',
-              rack_base_uris  => ['/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 'RackBaseURI /test' }
-        end
-      end
-    end
-  end
-
-
   describe 'request_headers' do
     it 'applies cleanly' do
       pp = <<-EOS
@@ -1219,7 +1306,7 @@ class { 'apache::mod::fastcgi': }
   describe 'additional_includes' do
     it 'applies cleanly' do
       pp = <<-EOS
-        if $::osfamily == 'RedHat' and $::selinux {
+        if $::osfamily == 'RedHat' and "$::selinux" == "true" {
           $semanage_package = $::operatingsystemmajrelease ? {
             '5'     => 'policycoreutils',
             default => 'policycoreutils-python',
@@ -1271,4 +1358,33 @@ class { 'apache': }
       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
diff --git a/puphpet/puppet/modules/apache/spec/classes/apache_spec.rb b/puphpet/puppet/modules/apache/spec/classes/apache_spec.rb
index 2be2ef3..a766764 100644
--- a/puphpet/puppet/modules/apache/spec/classes/apache_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/apache_spec.rb
@@ -156,23 +156,23 @@
             :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
           {
@@ -218,6 +218,35 @@
       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({
@@ -225,6 +254,18 @@
         })
       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({
@@ -371,6 +412,37 @@
         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' }
@@ -432,7 +504,7 @@
       it { is_expected.to contain_file("/opt/rh/root/etc/httpd/conf/httpd.conf").with(
         'ensure'  => 'file',
         'notify'  => 'Class[Apache::Service]',
-        'require' => 'Package[httpd]'
+        'require' => ['Package[httpd]', 'File[/etc/httpd/conf/ports.conf]'],
       ) }
     end
 
@@ -487,7 +559,7 @@
         let :params do
           { :mpm_module => 'breakme' }
         end
-        it { expect { subject }.to raise_error Puppet::Error, /does not match/ }
+        it { expect { catalogue }.to raise_error Puppet::Error, /does not match/ }
       end
     end
 
@@ -561,7 +633,7 @@
         end
         it "should fail" do
           expect do
-            subject
+            catalogue
           end.to raise_error(Puppet::Error, /"foo" does not match/)
         end
       end
@@ -660,6 +732,7 @@
     # Assert that load files are placed for these mods, but no conf file.
     [
       'auth_basic',
+      'authn_core',
       'authn_file',
       'authz_groupfile',
       'authz_host',
@@ -794,7 +867,7 @@
 
     it do
       expect {
-       should compile
+       catalogue
       }.to raise_error(Puppet::Error, /Unsupported osfamily/)
     end
   end
diff --git a/puphpet/puppet/modules/apache/spec/classes/dev_spec.rb b/puphpet/puppet/modules/apache/spec/classes/dev_spec.rb
index e2e0b47..eb3d765 100644
--- a/puphpet/puppet/modules/apache/spec/classes/dev_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/dev_spec.rb
@@ -1,6 +1,9 @@
 require 'spec_helper'
 
 describe 'apache::dev', :type => :class do
+  let(:pre_condition) {[
+    'include apache'
+  ]}
   context "on a Debian OS" do
     let :facts do
       {
@@ -9,6 +12,10 @@
         :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") }
@@ -25,6 +32,10 @@
         :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") }
@@ -36,29 +47,31 @@
         :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 :pre_condition do
-      'include apache::package'
-    end
     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 :pre_condition do
-      'include apache::package'
-    end
     let :facts do
       {
         :osfamily               => 'Gentoo',
@@ -66,6 +79,10 @@
         :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") }
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/auth_mellon_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/auth_mellon_spec.rb
new file mode 100644
index 0000000..f022e48
--- /dev/null
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/auth_mellon_spec.rb
@@ -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
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/dev_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/dev_spec.rb
index f653389..1686a02 100644
--- a/puphpet/puppet/modules/apache/spec/classes/mod/dev_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/dev_spec.rb
@@ -1,16 +1,14 @@
 require 'spec_helper'
 
 describe 'apache::mod::dev', :type => :class do
+  let(:pre_condition) {[
+    'include apache'
+  ]}
   [
-    ['RedHat',  '6', 'Santiago'],
-    ['Debian',  '6', 'squeeze'],
-    ['FreeBSD', '9', 'FreeBSD'],
-  ].each do |osfamily, operatingsystemrelease, lsbdistcodename|
-    if osfamily == 'FreeBSD'
-      let :pre_condition do
-        'include apache::package'
-      end
-    end
+    ['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
         {
@@ -19,6 +17,10 @@
           :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') }
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/disk_cache.rb b/puphpet/puppet/modules/apache/spec/classes/mod/disk_cache.rb
new file mode 100644
index 0000000..263b4ca
--- /dev/null
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/disk_cache.rb
@@ -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
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/expires_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/expires_spec.rb
new file mode 100644
index 0000000..e6eab7c
--- /dev/null
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/expires_spec.rb
@@ -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
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/ext_filter_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/ext_filter_spec.rb
new file mode 100644
index 0000000..afa71c1
--- /dev/null
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/ext_filter_spec.rb
@@ -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
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/fcgid_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/fcgid_spec.rb
index f772ff7..9895362 100644
--- a/puphpet/puppet/modules/apache/spec/classes/mod/fcgid_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/fcgid_spec.rb
@@ -21,7 +21,9 @@
       }
     end
     it { is_expected.to contain_class("apache::params") }
-    it { is_expected.to contain_apache__mod('fcgid') }
+    it { is_expected.to contain_apache__mod('fcgid').with({
+      'loadfile_name' => 'unixd_fcgid.load'
+    }) }
     it { is_expected.to contain_package("libapache2-mod-fcgid") }
   end
 
@@ -36,13 +38,15 @@
         :id                        => 'root',
         :kernel                    => 'Linux',
         :path                      => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
-        :is_pe                  => false,
+        :is_pe                     => false,
       }
     end
 
     describe 'without parameters' do
       it { is_expected.to contain_class("apache::params") }
-      it { is_expected.to contain_apache__mod('fcgid') }
+      it { is_expected.to contain_apache__mod('fcgid').with({
+        'loadfile_name' => 'unixd_fcgid.load'
+      }) }
       it { is_expected.to contain_package("mod_fcgid") }
     end
 
@@ -57,7 +61,7 @@
       } end
 
       it 'should contain the correct config' do
-        content = subject.resource('file', 'fcgid.conf').send(:parameters)[:content]
+        content = catalogue.resource('file', 'unixd_fcgid.conf').send(:parameters)[:content]
         expect(content.split("\n").reject { |c| c =~ /(^#|^$)/ }).to eq([
           '',
           '  AddHandler fcgid-script .fcgi',
@@ -89,8 +93,7 @@
       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
@@ -99,8 +102,8 @@
     let :facts do
       {
         :osfamily                  => 'FreeBSD',
-        :operatingsystemrelease    => '9',
-        :operatingsystemmajrelease => '9',
+        :operatingsystemrelease    => '10',
+        :operatingsystemmajrelease => '10',
         :concat_basedir            => '/dne',
         :operatingsystem           => 'FreeBSD',
         :id                        => 'root',
@@ -111,7 +114,9 @@
     end
 
     it { is_expected.to contain_class("apache::params") }
-    it { is_expected.to contain_apache__mod('fcgid') }
+    it { is_expected.to contain_apache__mod('fcgid').with({
+      'loadfile_name' => 'unixd_fcgid.load'
+    }) }
     it { is_expected.to contain_package("www/mod_fcgid") }
   end
 
@@ -130,7 +135,9 @@
     end
 
     it { is_expected.to contain_class("apache::params") }
-    it { is_expected.to contain_apache__mod('fcgid') }
+    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
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/passenger_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/passenger_spec.rb
index 07ce358..40ac749 100644
--- a/puphpet/puppet/modules/apache/spec/classes/mod/passenger_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/passenger_spec.rb
@@ -64,6 +64,18 @@
       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 }
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/peruser_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/peruser_spec.rb
index f39cbcf..097a36f 100644
--- a/puphpet/puppet/modules/apache/spec/classes/mod/peruser_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/peruser_spec.rb
@@ -19,7 +19,7 @@
     end
     it do
       expect {
-        should compile
+        catalogue
       }.to raise_error(Puppet::Error, /Unsupported osfamily FreeBSD/)
     end
   end
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/proxy_connect_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/proxy_connect_spec.rb
index f4b4cc2..dbb314c 100644
--- a/puphpet/puppet/modules/apache/spec/classes/mod/proxy_connect_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/proxy_connect_spec.rb
@@ -19,7 +19,7 @@
         :is_pe                  => false,
       }
     end
-    context 'with Apache version < 2.4' do
+    context 'with Apache version < 2.2' do
       let :facts do
         super().merge({
           :operatingsystemrelease => '7.0',
@@ -28,11 +28,25 @@
       end
       let :params do
         {
-          :apache_version => '2.2',
+          :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({
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/remoteip_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/remoteip_spec.rb
new file mode 100644
index 0000000..c9f5b4e
--- /dev/null
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/remoteip_spec.rb
@@ -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
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/ssl_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/ssl_spec.rb
index 7ef8fba..0fd813d 100644
--- a/puphpet/puppet/modules/apache/spec/classes/mod/ssl_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/ssl_spec.rb
@@ -17,7 +17,7 @@
         :is_pe                  => false,
       }
     end
-    it { expect { subject }.to raise_error(Puppet::Error, /Unsupported osfamily:/) }
+    it { expect { catalogue }.to raise_error(Puppet::Error, /Unsupported osfamily:/) }
   end
 
   context 'on a RedHat OS' do
@@ -100,6 +100,22 @@
     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
@@ -136,5 +152,14 @@
       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
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/worker_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/worker_spec.rb
index 38a79ae..9d0d8e5 100644
--- a/puphpet/puppet/modules/apache/spec/classes/mod/worker_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/worker_spec.rb
@@ -157,6 +157,7 @@
       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
@@ -169,7 +170,8 @@
           :maxsparethreads      => 14,
           :threadsperchild      => 15,
           :maxrequestsperchild  => 16,
-          :threadlimit          => 17
+          :threadlimit          => 17,
+          :listenbacklog        => 8,
         }
       end
       it { should contain_file('/etc/httpd/conf.d/worker.conf').with(:content => /^$/) }
@@ -181,6 +183,7 @@
       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
diff --git a/puphpet/puppet/modules/apache/spec/classes/mod/wsgi_spec.rb b/puphpet/puppet/modules/apache/spec/classes/mod/wsgi_spec.rb
index 3f03ec9..5fe313a 100644
--- a/puphpet/puppet/modules/apache/spec/classes/mod/wsgi_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/mod/wsgi_spec.rb
@@ -93,7 +93,7 @@
           :mod_path => '/foo/bar/baz',
         }
       end
-      it { expect { subject }.to raise_error Puppet::Error, /apache::mod::wsgi - both package_name and mod_path must be specified!/ }
+      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
@@ -101,7 +101,7 @@
           :package_name => '/foo/bar/baz',
         }
       end
-      it { expect { subject }.to raise_error Puppet::Error, /apache::mod::wsgi - both package_name and mod_path must be specified!/ }
+      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
diff --git a/puphpet/puppet/modules/apache/spec/classes/params_spec.rb b/puphpet/puppet/modules/apache/spec/classes/params_spec.rb
index 92b314f..d022094 100644
--- a/puphpet/puppet/modules/apache/spec/classes/params_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/params_spec.rb
@@ -17,11 +17,8 @@
     end
     it { is_expected.to contain_apache__params }
 
-    # There are 4 resources in this class currently
-    # there should not be any more resources because it is a params class
-    # The resources are class[apache::version], class[apache::params], class[main], class[settings], stage[main]
     it "Should not contain any resources" do
-      expect(subject.resources.size).to eq(5)
+      should have_resource_count(0)
     end
   end
 end
diff --git a/puphpet/puppet/modules/apache/spec/classes/service_spec.rb b/puphpet/puppet/modules/apache/spec/classes/service_spec.rb
index 09906b0..4c85138 100644
--- a/puphpet/puppet/modules/apache/spec/classes/service_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/classes/service_spec.rb
@@ -57,7 +57,7 @@
       let (:params) {{ :service_enable => 'not-a-boolean' }}
 
       it 'should fail' do
-        expect { subject }.to raise_error(Puppet::Error, /is not a boolean/)
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a boolean/)
       end
     end
 
@@ -65,7 +65,7 @@
       let (:params) {{ :service_manage => 'not-a-boolean' }}
 
       it 'should fail' do
-        expect { subject }.to raise_error(Puppet::Error, /is not a boolean/)
+        expect { catalogue }.to raise_error(Puppet::Error, /is not a boolean/)
       end
     end
 
@@ -91,6 +91,18 @@
       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
 
 
diff --git a/puphpet/puppet/modules/apache/spec/defines/custom_config_spec.rb b/puphpet/puppet/modules/apache/spec/defines/custom_config_spec.rb
index 4a38a1f..7d566b0 100644
--- a/puphpet/puppet/modules/apache/spec/defines/custom_config_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/defines/custom_config_spec.rb
@@ -26,7 +26,7 @@
         'content' => '# Test',
       }
     end
-    it { is_expected.to contain_exec("service notify for rspec").with({
+    it { is_expected.to contain_exec("syntax verification for rspec").with({
       'refreshonly' => 'true',
       'subscribe'   => 'File[apache_rspec]',
       'command'     => '/usr/sbin/apachectl -t',
@@ -56,7 +56,7 @@
         'verify_command' => '/bin/true',
       }
     end
-    it { is_expected.to contain_exec("service notify for rspec").with({
+    it { is_expected.to contain_exec("syntax verification for rspec").with({
       'command'     => '/bin/true',
     })
     }
@@ -80,7 +80,7 @@
         'verify_config' => false,
       }
     end
-    it { is_expected.to_not contain_exec('service notify for rspec') }
+    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]'
@@ -93,7 +93,7 @@
         'ensure' => 'absent'
       }
     end
-    it { is_expected.to_not contain_exec('service notify for rspec') }
+    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',
@@ -110,14 +110,14 @@
       end
       it do
         expect {
-          should compile
+          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 {
-          should compile
+          catalogue
         }.to raise_error(Puppet::Error, /One of \$content and \$source must be specified\./)
       end
     end
@@ -130,7 +130,7 @@
       end
       it do
         expect {
-          should compile
+          catalogue
         }.to raise_error(Puppet::Error, /is not supported for ensure/)
       end
     end
diff --git a/puphpet/puppet/modules/apache/spec/defines/vhost_spec.rb b/puphpet/puppet/modules/apache/spec/defines/vhost_spec.rb
index add8a2b..f092f41 100644
--- a/puphpet/puppet/modules/apache/spec/defines/vhost_spec.rb
+++ b/puphpet/puppet/modules/apache/spec/defines/vhost_spec.rb
@@ -153,6 +153,7 @@
           '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,
@@ -168,7 +169,6 @@
           'log_level'                   => 'crit',
           'access_log'                  => false,
           'access_log_file'             => 'httpd_access_log',
-          'access_log_pipe'             => '',
           'access_log_syslog'           => true,
           'access_log_format'           => '%h %l %u %t \"%r\" %>s %b',
           'access_log_env_var'          => '',
@@ -184,10 +184,18 @@
               '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_pipe'              => '',
           'error_log_syslog'            => true,
           'error_documents'             => 'true',
           'fallbackresource'            => '/index.php',
@@ -205,10 +213,14 @@
           'proxy_dest'                  => '/',
           'proxy_pass'                  => [
             {
-              'path'     => '/a',
-              'url'      => 'http://backend-a/',
-              'keywords' => ['noquery', 'interpolate'],
-              'params'   => {
+              'path'            => '/a',
+              'url'             => 'http://backend-a/',
+              'keywords'        => ['noquery', 'interpolate'],
+              'reverse_cookies' => [{
+                'path'          => '/a',
+                'url'           => 'http://backend-a/',
+              }],
+              'params'          => {
                       'retry'   => '0',
                       'timeout' => '5'
               },
@@ -243,6 +255,7 @@
           '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'                    => [
@@ -250,6 +263,15 @@
               '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',
@@ -285,6 +307,7 @@
           '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',
@@ -294,6 +317,14 @@
           '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
@@ -337,6 +368,7 @@
       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',
@@ -362,6 +394,16 @@
         :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') }
@@ -379,6 +421,8 @@
               /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') }
@@ -386,9 +430,13 @@
       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') }
@@ -398,6 +446,91 @@
       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]*[.\/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
@@ -450,7 +583,7 @@
       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 contain_class('apache::mod::alias') }
+      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') }
@@ -510,8 +643,19 @@
       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
@@ -795,94 +939,4 @@
       it { expect { is_expected.to compile }.to raise_error }
     end
   end
-  describe 'allow/deny/order/satisfy deprecation validation' 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
-    context 'bad allow parameter' do
-      let :params do
-        {
-          'docroot'        => '/var/www/files',
-          'apache_version' => '2.4',
-          'directories'    => {
-            'path'     => '/var/www/files',
-            'provider' => 'files',
-            'allow'    => 'from 127.0.0.1',
-          },
-        }
-      end
-      let :facts do default_facts end
-      it do
-        expect {
-          should contain_concat__fragment('rspec.example.com-directories')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-    context 'bad deny parameter' do
-      let :params do
-        {
-          'docroot'        => '/var/www/files',
-          'apache_version' => '2.4',
-          'directories'    => {
-            'path'     => '/var/www/files',
-            'provider' => 'files',
-            'deny'     => 'from 127.0.0.1',
-          },
-        }
-      end
-      let :facts do default_facts end
-      it do
-        expect {
-          should contain_concat__fragment('rspec.example.com-directories')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-    context 'bad satisfy parameter' do
-      let :params do
-        {
-          'docroot'        => '/var/www/files',
-          'apache_version' => '2.4',
-          'directories'    => {
-            'path'     => '/var/www/files',
-            'provider' => 'files',
-            'satisfy'  => 'any',
-          },
-        }
-      end
-      let :facts do default_facts end
-      it do
-        expect {
-          should contain_concat__fragment('rspec.example.com-directories')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-    context 'bad order parameter' do
-      let :params do
-        {
-          'docroot'        => '/var/www/files',
-          'apache_version' => '2.4',
-          'directories'    => {
-            'path'     => '/var/www/files',
-            'provider' => 'files',
-            'order'    => 'deny,allow',
-          },
-        }
-      end
-      let :facts do default_facts end
-      it do
-        expect {
-          should contain_concat__fragment('rspec.example.com-directories')
-        }.to raise_error(Puppet::Error)
-      end
-    end
-  end
 end
diff --git a/puphpet/puppet/modules/apache/spec/spec_helper_acceptance.rb b/puphpet/puppet/modules/apache/spec/spec_helper_acceptance.rb
index ce38832..d767b1e 100644
--- a/puphpet/puppet/modules/apache/spec/spec_helper_acceptance.rb
+++ b/puphpet/puppet/modules/apache/spec/spec_helper_acceptance.rb
@@ -1,22 +1,8 @@
 require 'beaker-rspec/spec_helper'
 require 'beaker-rspec/helpers/serverspec'
+require 'beaker/puppet_install_helper'
 
-
-unless ENV['RS_PROVISION'] == 'no'
-  # This will install the latest available package on el and deb based
-  # systems fail on windows and osx, and install via gem on other *nixes
-  foss_opts = { :default_action => 'gem_install' }
-
-  if default.is_pe?; then install_pe; else install_puppet( foss_opts ); end
-
-  hosts.each do |host|
-    if host['platform'] =~ /debian/
-      on host, 'echo \'export PATH=/var/lib/gems/1.8/bin/:${PATH}\' >> ~/.bashrc'
-    end
-
-    on host, "mkdir -p #{host['distmoduledir']}"
-  end
-end
+run_puppet_install_helper
 
 UNSUPPORTED_PLATFORMS = ['Suse','windows','AIX','Solaris']
 
@@ -29,19 +15,36 @@
 
   # 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'), { :acceptable_exit_codes => [0,1] }
+        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
diff --git a/puphpet/puppet/modules/apache/spec/unit/puppet/parser/functions/validate_apache_log_level.rb b/puphpet/puppet/modules/apache/spec/unit/puppet/parser/functions/validate_apache_log_level.rb
new file mode 100644
index 0000000..dfef66e
--- /dev/null
+++ b/puphpet/puppet/modules/apache/spec/unit/puppet/parser/functions/validate_apache_log_level.rb
@@ -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
diff --git a/puphpet/puppet/modules/apache/templates/httpd.conf.erb b/puphpet/puppet/modules/apache/templates/httpd.conf.erb
index 6c50e28..6fb9892 100644
--- a/puphpet/puppet/modules/apache/templates/httpd.conf.erb
+++ b/puphpet/puppet/modules/apache/templates/httpd.conf.erb
@@ -11,6 +11,10 @@ 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 %>
 
@@ -60,10 +64,18 @@ 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 %>
@@ -77,9 +89,9 @@ Include "<%= @confd_dir %>/*.conf"
 <%- end -%>
 <% if @vhost_load_dir != @confd_dir -%>
 <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
-IncludeOptional "<%= @vhost_load_dir %>/*"
+IncludeOptional "<%= @vhost_load_dir %>/<%= @vhost_include_pattern %>"
 <%- else -%>
-Include "<%= @vhost_load_dir %>/*"
+Include "<%= @vhost_load_dir %>/<%= @vhost_include_pattern %>"
 <%- end -%>
 <% end -%>
 
diff --git a/puphpet/puppet/modules/apache/templates/mod/auth_mellon.conf.erb b/puphpet/puppet/modules/apache/templates/mod/auth_mellon.conf.erb
new file mode 100644
index 0000000..e36a733
--- /dev/null
+++ b/puphpet/puppet/modules/apache/templates/mod/auth_mellon.conf.erb
@@ -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 -%>
diff --git a/puphpet/puppet/modules/apache/templates/mod/disk_cache.conf.erb b/puphpet/puppet/modules/apache/templates/mod/disk_cache.conf.erb
index 0c7e2c4..b1b460e 100644
--- a/puphpet/puppet/modules/apache/templates/mod/disk_cache.conf.erb
+++ b/puphpet/puppet/modules/apache/templates/mod/disk_cache.conf.erb
@@ -1,8 +1,4 @@
-
-  
-     CacheEnable disk /
-     CacheRoot "<%= @cache_root %>"
-     CacheDirLevels 2
-     CacheDirLength 1
-  
-
+CacheEnable disk /
+CacheRoot "<%= @_cache_root %>"
+CacheDirLevels 2
+CacheDirLength 1
diff --git a/puphpet/puppet/modules/apache/templates/mod/expires.conf.erb b/puphpet/puppet/modules/apache/templates/mod/expires.conf.erb
new file mode 100644
index 0000000..7660cfc
--- /dev/null
+++ b/puphpet/puppet/modules/apache/templates/mod/expires.conf.erb
@@ -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 -%>
diff --git a/puphpet/puppet/modules/apache/templates/mod/ext_filter.conf.erb b/puphpet/puppet/modules/apache/templates/mod/ext_filter.conf.erb
new file mode 100644
index 0000000..67f98fd
--- /dev/null
+++ b/puphpet/puppet/modules/apache/templates/mod/ext_filter.conf.erb
@@ -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 -%>
diff --git a/puphpet/puppet/modules/apache/templates/mod/geoip.conf.erb b/puphpet/puppet/modules/apache/templates/mod/geoip.conf.erb
new file mode 100644
index 0000000..00e61d9
--- /dev/null
+++ b/puphpet/puppet/modules/apache/templates/mod/geoip.conf.erb
@@ -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 -%>
+
diff --git a/puphpet/puppet/modules/apache/templates/mod/passenger.conf.erb b/puphpet/puppet/modules/apache/templates/mod/passenger.conf.erb
index e50a2d6..1af4eaa 100644
--- a/puphpet/puppet/modules/apache/templates/mod/passenger.conf.erb
+++ b/puphpet/puppet/modules/apache/templates/mod/passenger.conf.erb
@@ -25,6 +25,9 @@
   <%- 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 -%>
diff --git a/puphpet/puppet/modules/apache/templates/mod/remoteip.conf.erb b/puphpet/puppet/modules/apache/templates/mod/remoteip.conf.erb
new file mode 100644
index 0000000..b4518f9
--- /dev/null
+++ b/puphpet/puppet/modules/apache/templates/mod/remoteip.conf.erb
@@ -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 -%>
diff --git a/puphpet/puppet/modules/apache/templates/mod/security.conf.erb b/puphpet/puppet/modules/apache/templates/mod/security.conf.erb
index 7597c46..7b2da76 100644
--- a/puphpet/puppet/modules/apache/templates/mod/security.conf.erb
+++ b/puphpet/puppet/modules/apache/templates/mod/security.conf.erb
@@ -9,7 +9,7 @@
 <%- end -%>
 
     # Default recommended configuration
-    SecRuleEngine On
+    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"
@@ -59,10 +59,13 @@
     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
 
diff --git a/puphpet/puppet/modules/apache/templates/mod/ssl.conf.erb b/puphpet/puppet/modules/apache/templates/mod/ssl.conf.erb
index 933aa1f..96b80b0 100644
--- a/puphpet/puppet/modules/apache/templates/mod/ssl.conf.erb
+++ b/puphpet/puppet/modules/apache/templates/mod/ssl.conf.erb
@@ -25,4 +25,7 @@
 <% if @ssl_options -%>
   SSLOptions <%= @ssl_options.compact.join(' ') %>
 <% end -%>
+<%- if @ssl_openssl_conf_cmd -%>
+  SSLOpenSSLConfCmd <%= @ssl_openssl_conf_cmd %>
+<%- end -%>
 
diff --git a/puphpet/puppet/modules/apache/templates/mod/fcgid.conf.erb b/puphpet/puppet/modules/apache/templates/mod/unixd_fcgid.conf.erb
similarity index 100%
rename from puphpet/puppet/modules/apache/templates/mod/fcgid.conf.erb
rename to puphpet/puppet/modules/apache/templates/mod/unixd_fcgid.conf.erb
diff --git a/puphpet/puppet/modules/apache/templates/mod/userdir.conf.erb b/puphpet/puppet/modules/apache/templates/mod/userdir.conf.erb
index add525d..83263c3 100644
--- a/puphpet/puppet/modules/apache/templates/mod/userdir.conf.erb
+++ b/puphpet/puppet/modules/apache/templates/mod/userdir.conf.erb
@@ -2,14 +2,14 @@
 <% if @disable_root -%>
   UserDir disabled root
 <% end -%>
-  UserDir <%= @dir %>
+  UserDir <%= @home %>/*/<%= @dir %>
 
   /*/<%= @dir %>">
     AllowOverride FileInfo AuthConfig Limit Indexes
-    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
+    Options <%= @options.join(' ') %>
     
       <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
-      Require all denied
+      Require all granted
       <%- else -%>
       Order allow,deny
       Allow from all
@@ -17,7 +17,7 @@
     
     
       <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%>
-      Require all denied
+      Require all granted
       <%- else -%>
       Order allow,deny
       Allow from all
diff --git a/puphpet/puppet/modules/apache/templates/mod/worker.conf.erb b/puphpet/puppet/modules/apache/templates/mod/worker.conf.erb
index 597e05f..ad2bc44 100644
--- a/puphpet/puppet/modules/apache/templates/mod/worker.conf.erb
+++ b/puphpet/puppet/modules/apache/templates/mod/worker.conf.erb
@@ -7,4 +7,5 @@
   ThreadsPerChild     <%= @threadsperchild %>
   MaxRequestsPerChild <%= @maxrequestsperchild %>
   ThreadLimit         <%= @threadlimit %>
+  ListenBacklog       <%= @listenbacklog %>
 
diff --git a/puphpet/puppet/modules/apache/templates/vhost/_additional_includes.erb b/puphpet/puppet/modules/apache/templates/vhost/_additional_includes.erb
index aa9f0fe..a07bb81 100644
--- a/puphpet/puppet/modules/apache/templates/vhost/_additional_includes.erb
+++ b/puphpet/puppet/modules/apache/templates/vhost/_additional_includes.erb
@@ -2,9 +2,8 @@
 
   ## Load additional static includes
 <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 && @use_optional_includes -%>
-IncludeOptional "<%= include %>"
+  IncludeOptional "<%= include %>"
 <%- else -%>
-Include "<%= include %>"
+  Include "<%= include %>"
 <%- end -%>
-
 <% end -%>
diff --git a/puphpet/puppet/modules/apache/templates/vhost/_auth_kerb.erb b/puphpet/puppet/modules/apache/templates/vhost/_auth_kerb.erb
new file mode 100644
index 0000000..9179ee8
--- /dev/null
+++ b/puphpet/puppet/modules/apache/templates/vhost/_auth_kerb.erb
@@ -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 -%>
diff --git a/puphpet/puppet/modules/apache/templates/vhost/_directories.erb b/puphpet/puppet/modules/apache/templates/vhost/_directories.erb
index 4f40cac..df6b661 100644
--- a/puphpet/puppet/modules/apache/templates/vhost/_directories.erb
+++ b/puphpet/puppet/modules/apache/templates/vhost/_directories.erb
@@ -4,16 +4,16 @@
   <%- [@_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_fail(["Apache::Vhost: Using allow is not supported in your Apache version"]) -%>
+        <%- 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_fail(["Apache::Vhost: Using deny is not supported in your Apache version"]) -%>
+        <%- 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_fail(["Apache::Vhost: Using order is not supported in your Apache version"]) -%>
+        <%- 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_fail(["Apache::Vhost: Using satisfy is not supported in your Apache version"]) -%>
+        <%- scope.function_warning(["Apache::Vhost: Using satisfy is deprecated in your Apache version"]) -%>
       <%- end -%>
     <%- end -%>
     <%- if directory['path'] and directory['path'] != '' -%>
@@ -34,6 +34,9 @@
     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 -%>
@@ -43,6 +46,9 @@
       <%- 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(' ') %>
@@ -192,6 +198,9 @@
     ExpiresByType <%= rule %>
     <%- end -%>
     <%- end -%>
+    <%- if directory['ext_filter_options'] -%>
+    ExtFilterOptions <%= directory['ext_filter_options'] %>
+    <%- end -%>
     <%- if directory['force_type'] -%>
     ForceType <%= directory['force_type'] %>
     <%- end -%>
@@ -233,6 +242,9 @@
     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'] %>
@@ -246,6 +258,37 @@
     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 -%>
diff --git a/puphpet/puppet/modules/apache/templates/vhost/_docroot.erb b/puphpet/puppet/modules/apache/templates/vhost/_docroot.erb
index 6039fa6..b67998b 100644
--- a/puphpet/puppet/modules/apache/templates/vhost/_docroot.erb
+++ b/puphpet/puppet/modules/apache/templates/vhost/_docroot.erb
@@ -2,6 +2,6 @@
   ## Vhost docroot
 <% if @virtual_docroot -%>
   VirtualDocumentRoot "<%= @virtual_docroot %>"
-<% else -%>
+<% elsif @docroot -%>
   DocumentRoot "<%= @docroot %>"
 <% end -%>
diff --git a/puphpet/puppet/modules/apache/templates/vhost/_file_header.erb b/puphpet/puppet/modules/apache/templates/vhost/_file_header.erb
index e6f2f95..9350781 100644
--- a/puphpet/puppet/modules/apache/templates/vhost/_file_header.erb
+++ b/puphpet/puppet/modules/apache/templates/vhost/_file_header.erb
@@ -3,7 +3,7 @@
 # Managed by Puppet
 # ************************************
 
->
+>
   ServerName <%= @servername %>
 <% if @serveradmin -%>
   ServerAdmin <%= @serveradmin %>
diff --git a/puphpet/puppet/modules/apache/templates/vhost/_filters.erb b/puphpet/puppet/modules/apache/templates/vhost/_filters.erb
new file mode 100644
index 0000000..b862597
--- /dev/null
+++ b/puphpet/puppet/modules/apache/templates/vhost/_filters.erb
@@ -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 -%>
diff --git a/puphpet/puppet/modules/apache/templates/vhost/_limits.erb b/puphpet/puppet/modules/apache/templates/vhost/_limits.erb
new file mode 100644
index 0000000..0bd56db
--- /dev/null
+++ b/puphpet/puppet/modules/apache/templates/vhost/_limits.erb
@@ -0,0 +1,5 @@
+
+  ## Limit Request Values
+<% if @limit_request_field_size -%>
+  LimitRequestFieldSize <%= @limit_request_field_size %>
+<% end -%>
diff --git a/puphpet/puppet/modules/apache/templates/vhost/_passenger_base_uris.erb b/puphpet/puppet/modules/apache/templates/vhost/_passenger_base_uris.erb
new file mode 100644
index 0000000..f3ef5aa
--- /dev/null
+++ b/puphpet/puppet/modules/apache/templates/vhost/_passenger_base_uris.erb
@@ -0,0 +1,7 @@
+<% if @passenger_base_uris -%>
+
+  ## Enable passenger base uris
+<% Array(@passenger_base_uris).each do |uri| -%>
+  PassengerBaseURI <%= uri %>
+<% end -%>
+<% end -%>
diff --git a/puphpet/puppet/modules/apache/templates/vhost/_proxy.erb b/puphpet/puppet/modules/apache/templates/vhost/_proxy.erb
index 67c8eb2..3f94af9 100644
--- a/puphpet/puppet/modules/apache/templates/vhost/_proxy.erb
+++ b/puphpet/puppet/modules/apache/templates/vhost/_proxy.erb
@@ -1,4 +1,4 @@
-<% if @proxy_dest or @proxy_pass -%>
+<% if @proxy_dest or @proxy_pass or @proxy_pass_match or @proxy_dest_match -%>
 
   ## Proxy rules
   ProxyRequests Off
@@ -18,6 +18,11 @@
   <%- if proxy['keywords'] %> <%= proxy['keywords'].join(' ') -%>
   <%- end %>
   >
+  <%- 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 -%>
@@ -27,13 +32,13 @@
   <%- end -%>
   <%- if proxy['setenv'] -%>
     <%- Array(proxy['setenv']).each do |setenv_var| -%>
-    SetEnv <%= setenv_var -%>
+    SetEnv <%= setenv_var %>
     <%- end -%>
   <%- end -%>
   
 <% end -%>
 <% [@proxy_pass_match].flatten.compact.each do |proxy| %>
-  ProxyPassMatch <%= proxy['path'] %> <%= proxy['url'] %>
+  ProxyPassMatch <%= proxy['path'] %> <%= proxy['url'] -%>
   <%- if proxy['params'] -%>
     <%- proxy['params'].each_pair do |key, value| -%> <%= key %>=<%= value -%>
     <%- end -%>
@@ -50,7 +55,7 @@
   <%- end -%>
   <%- if proxy['setenv'] -%>
     <%- Array(proxy['setenv']).each do |setenv_var| -%>
-    SetEnv <%= setenv_var -%>
+    SetEnv <%= setenv_var %>
     <%- end -%>
   <%- end -%>
   
diff --git a/puphpet/puppet/modules/apache/templates/vhost/_ssl.erb b/puphpet/puppet/modules/apache/templates/vhost/_ssl.erb
index 5169925..a3d76fb 100644
--- a/puphpet/puppet/modules/apache/templates/vhost/_ssl.erb
+++ b/puphpet/puppet/modules/apache/templates/vhost/_ssl.erb
@@ -26,7 +26,7 @@
   SSLProxyEngine On
   <%- end -%>
   <%- if @ssl_protocol -%>
-  SSLProtocol             <%= @ssl_protocol %>
+  SSLProtocol             <%= [@ssl_protocol].flatten.compact.join(' ') %>
   <%- end -%>
   <%- if @ssl_cipher -%>
   SSLCipherSuite          <%= @ssl_cipher %>
@@ -40,7 +40,13 @@
   <%- 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 -%>
diff --git a/puphpet/puppet/modules/apt/.fixtures.yml b/puphpet/puppet/modules/apt/.fixtures.yml
index 2bb941d..578437c 100644
--- a/puphpet/puppet/modules/apt/.fixtures.yml
+++ b/puphpet/puppet/modules/apt/.fixtures.yml
@@ -2,6 +2,6 @@ fixtures:
   repositories:
     "stdlib":
       "repo": "git://github.com/puppetlabs/puppetlabs-stdlib.git"
-      "ref": "v2.2.1"
+      "ref": "4.5.0"
   symlinks:
     "apt": "#{source_dir}"
diff --git a/puphpet/puppet/modules/apt/.gitignore b/puphpet/puppet/modules/apt/.gitignore
new file mode 100644
index 0000000..b5db85e
--- /dev/null
+++ b/puphpet/puppet/modules/apt/.gitignore
@@ -0,0 +1,9 @@
+pkg/
+Gemfile.lock
+vendor/
+spec/fixtures/
+.vagrant/
+.bundle/
+coverage/
+.idea/
+*.iml
diff --git a/puphpet/puppet/modules/apt/.sync.yml b/puphpet/puppet/modules/apt/.sync.yml
index 08e91a7..625d045 100644
--- a/puphpet/puppet/modules/apt/.sync.yml
+++ b/puphpet/puppet/modules/apt/.sync.yml
@@ -2,8 +2,25 @@
 .travis.yml:
   includes:
   - rvm: 1.8.7
-    env: PUPPET_GEM_VERSION="~> 3.0"
+    env: PUPPET_GEM_VERSION="~> 3.0" STRICT_VARIABLES="yes" ORDERING="random"
   - rvm: 1.9.3
-    env: PUPPET_GEM_VERSION="~> 3.0"
+    env: PUPPET_GEM_VERSION="~> 3.0" STRICT_VARIABLES="yes" ORDERING="random"
   - rvm: 2.0.0
-    env: PUPPET_GEM_VERSION="~> 3.0"
+    env: PUPPET_GEM_VERSION="~> 3.0" STRICT_VARIABLES="yes" ORDERING="random"
+  - rvm: 2.1.6
+    env: PUPPET_GEM_VERSION="~> 4.0" STRICT_VARIABLES="yes" ORDERING="random"
+    allow_failures:
+Gemfile:
+  required:
+    ':development, :unit_tests':
+      - gem: rspec-puppet
+        version: '~> 2.1'
+      - gem: rspec-core
+        version: '3.1.7'
+      - gem: puppetlabs_spec_helper
+      - gem: simplecov
+      - gem: puppet_facts
+      - gem: json
+    ':system_tests':
+      - gem: beaker-rspec
+      - gem: serverspec
diff --git a/puphpet/puppet/modules/apt/.travis.yml b/puphpet/puppet/modules/apt/.travis.yml
index ec6f08d..8b6adc2 100644
--- a/puphpet/puppet/modules/apt/.travis.yml
+++ b/puphpet/puppet/modules/apt/.travis.yml
@@ -1,4 +1,5 @@
 ---
+sudo: false
 language: ruby
 bundler_args: --without system_tests
 script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake spec SPEC_OPTS='--format documentation'"
@@ -6,10 +7,12 @@ matrix:
   fast_finish: true
   include:
   - rvm: 1.8.7
-    env: PUPPET_GEM_VERSION="~> 3.0"
+    env: PUPPET_GEM_VERSION="~> 3.0" STRICT_VARIABLES="yes" ORDERING="random"
   - rvm: 1.9.3
-    env: PUPPET_GEM_VERSION="~> 3.0"
+    env: PUPPET_GEM_VERSION="~> 3.0" STRICT_VARIABLES="yes" ORDERING="random"
   - rvm: 2.0.0
-    env: PUPPET_GEM_VERSION="~> 3.0"
+    env: PUPPET_GEM_VERSION="~> 3.0" STRICT_VARIABLES="yes" ORDERING="random"
+  - rvm: 2.1.6
+    env: PUPPET_GEM_VERSION="~> 4.0" STRICT_VARIABLES="yes" ORDERING="random"
 notifications:
   email: false
diff --git a/puphpet/puppet/modules/apt/CHANGELOG.md b/puphpet/puppet/modules/apt/CHANGELOG.md
index 5b2a45a..c310fb6 100644
--- a/puphpet/puppet/modules/apt/CHANGELOG.md
+++ b/puphpet/puppet/modules/apt/CHANGELOG.md
@@ -1,3 +1,139 @@
+##Supported Release 2.2.1
+###Summary
+
+Small release for support of newer PE versions. This increments the version of PE in the metadata.json file.
+
+##2015-09-29 - Supported Release 2.2.0
+###Summary
+
+This release includes a few bugfixes.
+
+####Features
+- Adds an `ensure` parameter for user control of proxy presence.
+- Adds ability to set `notify_update` to `apt::conf` (MODULES-2269).
+- Apt pins no longer trigger an `apt-get update` run.
+- Adds support for creating pins from main class.
+
+####Bugfixes
+- Updates to use the official Debian mirrors.
+- Fixes path to `preferences` and `preferences.d`
+- Fixes pinning for backports (MODULES-2446).
+- Fixes the name/extension of the preferences files.
+
+##2015-07-28 - Supported Release 2.1.1
+###Summary
+
+This release includes a few bugfixes.
+
+####Bugfixes
+- Fix incorrect use of anchoring (MODULES-2190)
+- Use correct comment type for apt.conf files
+- Test fixes
+- Documentation fixes
+
+##2015-06-16 - Supported Release 2.1.0
+###Summary
+
+This release largely makes `apt::key` and `apt::source` API-compatible with the 1.8.x versions for ease in upgrading, and also addresses some compatibility issues with older versions of Puppet.
+
+####Features
+- Add API compatibility to `apt::key` and `apt::source`
+- Added `apt_reboot_required` fact
+
+####Bugfixes
+- Fix compatibility with Puppet versions 3.0-3.4
+- Work around future parser bug PUP-4133
+
+##2015-04-28 - Supported Release 2.0.1
+###Summary
+
+This bug fixes a few compatibility issues that came up with the 2.0.0 release, and includes test and documentation updates.
+
+####Bugfixes
+- Fix incompatibility with keyrings containing multiple keys
+- Fix bugs preventing the module from working with Puppet < 3.5.0
+
+##2015-04-07 - Supported Release 2.0.0
+###Summary
+
+This is a major rewrite of the apt module. Many classes and defines were removed, but all existing functionality should still work. Please carefully review documentation before upgrading.
+
+####Backwards-incompatible changes
+
+As this is a major rewrite of the module there are a great number of backwards incompatible changes. Please review this and the updated README carefully before upgrading.
+
+#####`apt_key`
+- `keyserver_options` parameter renamed to `options`
+
+#####`apt::backports`
+- This no longer works out of the box on Linux Mint. If using this on mint, you must specify the `location`, `release`, `repos`, and `key` parameters. [Example](examples/backports.pp)
+
+#####`apt::builddep`
+- This define was removed. Functionality can be matched passing 'build-dep' to `install_options` in the package resource. [Example](examples/builddep.pp)
+
+#####`apt::debian::testing`
+- This class was removed. Manually add an `apt::source` instead. [Example](examples/debian_testing.pp)
+
+#####`apt::debian::unstable`
+- This class was removed. Manually add an `apt::source` instead. [Example](examples/debian_unstable.pp)
+
+#####`apt::force`
+- This define was removed. Functionallity can be matched by setting `install_options` in the package resource. See [here](examples/force.pp) for how to set the options.
+
+#####`apt::hold`
+- This define was removed. Simply use an `apt::pin` with `priority => 1001` for the same functionality.
+
+#####`apt`
+- `always_apt_update` - This parameter was removed. Use `update => { 'frequency' => 'always' }` instead.
+- `apt_update_frequency` - This parameter was removed. Use `update => { 'frequency' =>  }` instead.
+- `disable_keys` - This parameter was removed. See this [example](examples/disable_keys.pp) if you need this functionality.
+- `proxy_host` - This parameter was removed. Use `proxy => { 'host' =>  }` instead.
+- `proxy_port` - This parameter was removed. Use `proxy => { 'port' =>  }` instead.
+- `purge_sources_list` - This parameter was removed. Use `purge => { 'sources.list' =>  }` instead.
+- `purge_sources_list_d` - This parameter was removed. Use `purge => { 'sources.list.d' =>  }` instead.
+- `purge_preferences` - This parameter was removed. Use `purge => { 'preferences' =>  }` instead.
+- `purge_preferences_d` - This parameter was removed. Use `purge => { 'preferences.d' =>  }` instead.
+- `update_timeout` - This parameter was removed. Use `update => { 'timeout' =>  }` instead.
+- `update_tries` - This parameter was removed. Use `update => { 'tries' =>  }` instead.
+
+#####`apt::key`
+- `key` - This parameter was renamed to `id`.
+- `key_content` - This parameter was renamed to `content`.
+- `key_source` - This parameter was renamed to `source`.
+- `key_server` - This parameter was renamed to `server`.
+- `key_options` - This parameter was renamed to `options`.
+
+#####`apt::release`
+- This class was removed. See this [example](examples/release.pp) for how to achieve this functionality.
+
+#####`apt::source`
+- `include_src` - This parameter was removed. Use `include => { 'src' =>  }` instead. ***NOTE*** This now defaults to false.
+- `include_deb` - This parameter was removed. Use `include => { 'deb' =>  }` instead.
+- `required_packages` - This parameter was removed. Use package resources for these packages if needed.
+- `key` - This can either be a key id or a hash including key options. If using a hash, `key => { 'id' =>  }` must be specified.
+- `key_server` - This parameter was removed. Use `key => { 'server' =>  }` instead.
+- `key_content` - This parameter was removed. Use `key => { 'content' =>  }` instead.
+- `key_source` - This parameter was removed. Use `key => { 'source' =>  }` instead.
+- `trusted_source` - This parameter was renamed to `allow_unsigned`.
+
+#####`apt::unattended_upgrades`
+- This class was removed and is being republished under the puppet-community namespace. The git repository is available [here](https://github.com/puppet-community/puppet-unattended_upgrades) and it will be published to the forge [here](https://forge.puppetlabs.com/puppet/unattended_upgrades).
+
+####Changes to default behavior
+- By default purge unmanaged files in 'sources.list', 'sources.list.d', 'preferences', and 'preferences.d'.
+- Changed default for `package_manage` in `apt::ppa` to `false`. Set to `true` in a single PPA if you need the package to be managed.
+- `apt::source` will no longer include the `src` entries by default. 
+- `pin` in `apt::source` now defaults to `undef` instead of `false`
+
+####Features
+- Added the ability to pass hashes of `apt::key`s, `apt::ppa`s, and `apt::setting`s to `apt`.
+- Added 'https' key to `proxy` hash to allow disabling `https_proxy` for the `apt::ppa` environment.
+- Added `apt::setting` define to abstract away configuration.
+- Added the ability to pass hashes to `pin` and `key` in `apt::backports` and `apt::source`.
+
+####Bugfixes
+- Fixes for strict variables.
+
 ##2015-03-17 - Supported Release 1.8.0
 ###Summary
 
diff --git a/puphpet/puppet/modules/apt/Gemfile b/puphpet/puppet/modules/apt/Gemfile
index 62c5693..643d3f5 100644
--- a/puphpet/puppet/modules/apt/Gemfile
+++ b/puphpet/puppet/modules/apt/Gemfile
@@ -1,21 +1,39 @@
 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',                    :require => false
+  gem 'rspec-puppet', '~> 2.1',  :require => false
   gem 'rspec-core', '3.1.7',     :require => false
-  gem 'rspec-puppet', '~> 1.0',  :require => false
   gem 'puppetlabs_spec_helper',  :require => false
-  gem 'puppet-lint',             :require => false
   gem 'simplecov',               :require => false
   gem 'puppet_facts',            :require => false
   gem 'json',                    :require => false
 end
 
 group :system_tests do
-  gem 'beaker-rspec',  :require => false
+  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
diff --git a/puphpet/puppet/modules/apt/README.md b/puphpet/puppet/modules/apt/README.md
index 186c2c2..1c9591d 100644
--- a/puphpet/puppet/modules/apt/README.md
+++ b/puphpet/puppet/modules/apt/README.md
@@ -1,424 +1,478 @@
 # apt
 
+#### 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 apt](#setup)
+    * [What apt affects](#what-apt-affects)
+    * [Beginning with apt](#beginning-with-apt)
+4. [Usage - Configuration options and additional functionality](#usage)
+5. [Reference - An under-the-hood peek at what the module is doing and how](#reference)
+    * [Classes](#classes)
+    * [Defines](#defines)
+    * [Types](#types)
+    * [Facts](#facts)
+6. [Limitations - OS compatibility, etc.](#limitations)
+7. [Development - Guide for contributing to the module](#development)
+
 ## Overview
 
-The apt module provides a simple interface for managing Apt source, key, and definitions with Puppet.
+The apt module lets you use Puppet to manage Apt sources, keys, and other configuration options.
 
 ## Module Description
 
-The apt module automates obtaining and installing software packages on \*nix systems.
+Apt (Advanced Package Tool) is a package manager available on Debian, Ubuntu, and several other operating systems. The apt module provides a series of classes, defines, types, and facts to help you automate Apt package management.
 
-**Note**: While this module allows the use of short keys, **warnings are thrown if a full fingerprint is not used**, as they pose a serious security issue by opening you up to collision attacks.
+**Note**: For this module to correctly autodetect which version of Debian/Ubuntu (or derivative) you're running, you need to make sure the 'lsb-release' package is installed. We highly recommend you either make this part of your provisioning layer, if you run many Debian or derivative systems, or ensure that you have Facter 2.2.0 or later installed, which will pull this dependency in for you.
 
 ## Setup
 
-### What apt affects:
+### What apt affects
 
-* Package/service/configuration files for Apt
+* Your system's `preferences` file and `preferences.d` directory
 * Your system's `sources.list` file and `sources.list.d` directory
 * System repositories
 * Authentication keys
 
-**Note**: Setting the apt module's `purge_sources_list` and `purge_sources_list_d` parameters to 'true' will **destroy** any existing content that was not declared with Puppet. The default for these parameters is 'false'.
+**Note:** This module offers `purge` parameters which, if set to 'true', **destroy** any configuration on the node's `sources.list(.d)` and `preferences(.d)` that you haven't declared through Puppet. The default for these parameters is 'false'.
 
 ### Beginning with apt
 
-To begin using the apt module with default parameters, declare the class with `include apt`.
+To use the apt module with default parameters, declare the `apt` class.
+
+~~~puppet
+include apt
+~~~
 
-Any Puppet code that uses anything from the apt module requires that the core apt class be declared.
+**Note:** The main `apt` class is required by all other classes, types, and defines in this module. You must declare it whenever you use the module.
 
 ## Usage
 
-Using the apt module consists predominantly of declaring classes and defined types that provide the desired functionality and features. This module provides common resources and options that are shared by the various defined types in the apt module, so you **must always** include this class in your manifests.
+### Add GPG keys
+
+**Warning:** Using short key IDs presents a serious security issue, potentially leaving you open to collision attacks. We recommend you always use full fingerprints to identify your GPG keys. This module allows short keys, but issues a security warning if you use them.
+
+Declare the `apt::key` class:
+
+~~~puppet
+apt::key { 'puppetlabs':
+  id      => '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30',
+  server  => 'pgp.mit.edu',
+  options => 'http-proxy="http://proxyuser:proxypass@example.org:3128"',
+}
+~~~
+
+### Prioritize backports
+
+~~~puppet
+class { 'apt::backports':
+  pin => 500,
+}
+~~~
+
+By default, the `apt::backports` class drops a pin file for backports, pinning it to a priority of 200. This is lower than the normal default of 500, so packages with `ensure => latest` don't get upgraded from backports without your explicit permission.
 
-```
+If you raise the priority through the `pin` parameter to 500, normal policy goes into effect and Apt installs or upgrades to the newest version. This means that if a package is available from backports, it and its dependencies are pulled in from backports unless you explicitly set the `ensure` attribute of the `package` resource to `installed`/`present` or a specific version.
+
+### Update the list of packages
+
+By default, Puppet runs `apt-get update` on the first Puppet run after you include the `apt` class, and anytime `notify  => Exec['apt_update']` occurs; i.e., whenever config files get updated or other relevant changes occur. If you set `update['frequency']` to 'always', the update runs on every Puppet run. You can also set `update['frequency']` to 'daily' or 'weekly':
+
+~~~puppet
 class { 'apt':
-  always_apt_update    => false,
-  apt_update_frequency => undef,
-  disable_keys         => undef,
-  proxy_host           => false,
-  proxy_port           => '8080',
-  purge_sources_list   => false,
-  purge_sources_list_d => false,
-  purge_preferences_d  => false,
-  update_timeout       => undef,
-  fancy_progress       => undef
+  update => {
+    frequency => 'daily',
+  },
+}
+~~~
+
+### Pin a specific release
+
+~~~puppet
+apt::pin { 'karmic': priority => 700 }
+apt::pin { 'karmic-updates': priority => 700 }
+apt::pin { 'karmic-security': priority => 700 }
+~~~
+
+You can also specify more complex pins using distribution properties:
+
+~~~puppet
+apt::pin { 'stable':
+  priority        => -10,
+  originator      => 'Debian',
+  release_version => '3.0',
+  component       => 'main',
+  label           => 'Debian'
+}
+~~~
+
+To pin multiple packages, pass them to the `packages` parameter as an array or a space-delimited string.
+
+### Add a PPA (Personal Package Archive) repository
+
+~~~puppet
+apt::ppa { 'ppa:drizzle-developers/ppa': }
+~~~
+
+### Add an Apt source to `/etc/apt/sources.list.d/`
+
+~~~puppet
+apt::source { 'debian_unstable':
+  comment  => 'This is the iWeb Debian unstable mirror',
+  location => 'http://debian.mirror.iweb.ca/debian/',
+  release  => 'unstable',
+  repos    => 'main contrib non-free',
+  pin      => '-10',
+  key      => {
+    'id'     => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553',
+    'server' => 'subkeys.pgp.net',
+  },
+  include  => {
+    'src' => true,
+    'deb' => true,
+  },
 }
-```
+~~~
+
+To use the Puppet Labs Apt repository as a source:
+
+~~~puppet
+apt::source { 'puppetlabs':
+  location => 'http://apt.puppetlabs.com',
+  repos    => 'main',
+  key      => {
+    'id'     => '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30',
+    'server' => 'pgp.mit.edu',
+  },
+},
+~~~
+
+### Configure Apt from Hiera
+
+~~~yaml
+apt::sources:
+  'debian_unstable':
+    location: 'http://debian.mirror.iweb.ca/debian/'
+    release: 'unstable'
+    repos: 'main contrib non-free'
+    key:
+      id: '9AA38DCD55BE302B'
+      server: 'subkeys.pgp.net'
+    pin: '-10'
+    include:
+      src: true
+      deb: true
+
+  'puppetlabs':
+    location: 'http://apt.puppetlabs.com'
+    repos: 'main'
+    key:
+      id: '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30'
+      server: 'pgp.mit.edu'
+~~~
 
 ## Reference
 
 ### Classes
 
-* `apt`: Main class, provides common resources and options. Allows Puppet to manage your system's sources.list file and sources.list.d directory, but it does its best to respect existing content.
+#### Public Classes
 
-  If you declare your apt class with `purge_sources_list`, `purge_sources_list_d`, `purge_preferences` and `purge_preferences_d` set to 'true', Puppet will unapologetically purge any existing content it finds that wasn't declared with Puppet.
-  
-* `apt::backports`: This class adds the necessary components to get backports for Ubuntu and Debian. The release name defaults to `$lsbdistcodename`. Setting this manually can cause undefined and potentially serious behavior.
+* [`apt`](#class-apt)
+* [`apt::backports`](#class-aptbackports)
 
-  By default, this class drops a pin-file for backports, pinning it to a priority of 200. This is lower than the normal Debian archive, which gets a priority of 500 to ensure that packages with `ensure => latest` don't get magically upgraded from backports without your explicit permission.
+#### Private Classes
 
-  If you raise the priority through the `pin_priority` parameter to 500---identical to the rest of the Debian mirrors---normal policy goes into effect, and Apt installs or upgrades to the newest version. This means that if a package is available from backports, it and its dependencies are pulled in from backports unless you explicitly set the `ensure` attribute of the `package` resource to `installed`/`present` or a specific version.
+* `apt::params`: Provides defaults for the apt module parameters.
+* `apt::update`: Updates the list of available packages using `apt-get update`.
 
-* `apt::params`: Sets defaults for the apt module parameters.
+### Defines
 
-* `apt::release`: Sets the default Apt release. This class is particularly useful when using repositories that are unstable in Ubuntu, such as Debian.
+* [`apt::conf`](#define-aptconf)
+* [`apt::key`](#define-aptkey)
+* [`apt::pin`](#define-aptpin)
+* [`apt::ppa`](#define-aptppa)
+* [`apt::setting`](#define-aptsetting)
+* [`apt::source`](#define-aptsource)
 
-  ```
-  class { 'apt::release':
-    release_id => 'precise',
-  }
-  ```  
+### Types
 
-* `apt::unattended_upgrades`: This class manages the unattended-upgrades package and related configuration files for Ubuntu and Debian systems. You can configure the class to automatically upgrade all new package releases or just security releases.
+* [`apt_key`](#type-apt_key)
 
-  ```
-  class { 'apt::unattended_upgrades':
-    blacklist     => [],
-    update        => '1',
-    download      => '1',
-    upgrade       => '1',
-    autoclean     => '7',
-  }
-  ```
-  
-* `apt::update`: Runs `apt-get update`, updating the list of available packages and their versions without installing or upgrading any packages. The update runs on the first Puppet run after you include the class, then whenever `notify  => Exec['apt_update']` occurs; i.e., whenever config files get updated or other relevant changes occur. If you set the `always_apt_update` parameter to 'true', the update runs on every Puppet run.
+### Facts
 
-### Types
+* `apt_updates`: The number of installed packages with available updates.
 
-* `apt_key`
+* `apt_security_updates`: The number of installed packages with available security updates.
 
-  A native Puppet type and provider for managing GPG keys for Apt is provided by this module.
+* `apt_package_updates`: The names of all installed packages with available updates. In Facter 2.0 and later this data is formatted as an array; in earlier versions it is a comma-delimited string.
 
-  ```
-  apt_key { 'puppetlabs':
-    ensure => 'present',
-    id     => '1054B7A24BD6EC30',
-  }
-  ```
+* `apt_update_last_success`: The date, in epochtime, of the most recent successful `apt-get update` run (based on the mtime of  /var/lib/apt/periodic/update-success-stamp).
 
-  You can additionally set the following attributes:
+* `apt_reboot_required`: Determines if a reboot is necessary after updates have been installed.
 
-   * `source`: HTTP, HTTPS or FTP location of a GPG key or path to a file on the target host.
-   * `content`: Instead of pointing to a file, pass the key in as a string.
-   * `server`: The GPG key server to use. It defaults to *keyserver.ubuntu.com*.
-   * `keyserver_options`: Additional options to pass to `--keyserver`.
+#### Class: `apt`
 
-  Because apt_key is a native type, you can use it and query for it with MCollective. 
-
-### Defined Types
+Main class, includes all other classes.
 
-* `apt::builddep`: Installs the build dependencies of a specified package.
+##### Parameters (all optional)
 
-  `apt::builddep { 'glusterfs-server': }`
-    
-* `apt::conf`: Specifies a custom configuration file. The priority defaults to 50, but you can set the priority parameter to load the file earlier or later. The content parameter passes specified content, if any, into the file resource.
-
-* `apt::hold`: Holds a specific version of a package. You can hold a package to a full version or a partial version.
-
-  To set a package's ensure attribute to 'latest' but get the version specified by `apt::hold`:
-
-  ```
-  apt::hold { 'vim':
-    version => '2:7.3.547-7',
-  }
-  ```
-
-  Alternatively, if you want to hold your package at a partial version, you can use a wildcard. For example, you can hold Vim at version 7.3.*:
-
-
-  ```
-  apt::hold { 'vim':
-    version => '2:7.3.*',
-  }
-  ```
-
-* `apt::force`: Forces a package to be installed from a specific release. This is particularly useful when using repositories that are unstable in Ubuntu, such as Debian.
-
-  ```
-  apt::force { 'glusterfs-server':
-    release     => 'unstable',
-    version     => '3.0.3',
-    cfg_files   => 'unchanged',
-    cfg_missing => true,
-    require => Apt::Source['debian_unstable'],
-  }
-  ```
-
-  Valid values for `cfg_files` are:
-    * 'new': Overwrites all existing configuration files with newer ones.
-    * 'old': Forces usage of all old files.
-    * 'unchanged: Updates only unchanged config files.
-    * 'none': Provides backward-compatibility with existing Puppet manifests.
-   
-  Valid values for `cfg_missing` are 'true', 'false'. Setting this to 'false' provides backward compatibility; setting it to 'true' checks for and installs missing configuration files for the selected package.
-
-* `apt::key`: Adds a key to the list of keys used by Apt to authenticate packages. This type uses the aforementioned `apt_key` native type. As such, it no longer requires the `wget` command on which the old implementation depended.
-
-  ```
-  apt::key { 'puppetlabs':
-    key        => '1054B7A24BD6EC30',
-    key_server => 'pgp.mit.edu',
-  }
-
-  apt::key { 'jenkins':
-    key        => '9B7D32F2D50582E6',
-    key_source => 'http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key',
-  }
-  ```
-
-* `apt::pin`: Defined type that adds an Apt pin for a certain release.
-
-  ```
-  apt::pin { 'karmic': priority => 700 }
-  apt::pin { 'karmic-updates': priority => 700 }
-  apt::pin { 'karmic-security': priority => 700 }
-  ```
-
-  Note that you can also specify more complex pins using distribution properties.
-
-  ```
-  apt::pin { 'stable':
-    priority        => -10,
-    originator      => 'Debian',
-    release_version => '3.0',
-    component       => 'main',
-    label           => 'Debian'
-  }
-  ```  
-
-  If you want to pin a number of packages, you can specify the packages as a space-delimited string using the `packages` attribute, or you can pass in an array of package names.
-
-* `apt::ppa`: Adds a PPA repository using `add-apt-repository`. For example, `apt::ppa { 'ppa:drizzle-developers/ppa': }`.
-
-* `apt::source`: Adds an Apt source to `/etc/apt/sources.list.d/`. For example:
-
-  ```
-  apt::source { 'debian_unstable':
-    comment           => 'This is the iWeb Debian unstable mirror',
-    location          => 'http://debian.mirror.iweb.ca/debian/',
-    release           => 'unstable',
-    repos             => 'main contrib non-free',
-    required_packages => 'debian-keyring debian-archive-keyring',
-    key               => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553',
-    key_server        => 'subkeys.pgp.net',
-    pin               => '-10',
-    include_src       => true,
-    include_deb       => true
-  }
-  ```  
-
-  For example, to configure your system so the source is the Puppet Labs Apt repository:
-
-  ```
-  apt::source { 'puppetlabs':
-    location   => 'http://apt.puppetlabs.com',
-    repos      => 'main',
-    key        => '1054B7A24BD6EC30',
-    key_server => 'pgp.mit.edu',
-    }
-  ```
+* `keys`: Creates new `apt::key` resources. Valid options: a hash to be passed to the [`create_resources` function](https://docs.puppetlabs.com/references/latest/function.html#createresources). Default: {}.
 
-### Facts
+* `ppas`: Creates new `apt::ppa` resources. Valid options: a hash to be passed to the [`create_resources` function](https://docs.puppetlabs.com/references/latest/function.html#createresources). Default: {}.
 
-The apt module includes a few facts to describe the state of the Apt system:
+* `proxy`: Configures Apt to connect to a proxy server. Valid options: a hash made up from the following keys:
 
-* `apt_updates`: The number of updates available on the system
-* `apt_security_updates`: The number of updates which are security updates
-* `apt_package_updates`: The package names that are available for update. In Facter 2.0 and later, this will be a list type; in earlier versions, it is a comma-delimited string.
-* `apt_update_last_success`: The date, in epochtime, of the most recent successful `apt-get update` run. This is determined by reading the mtime of  /var/lib/apt/periodic/update-success-stamp.
+  * 'host': Specifies a proxy host to be stored in `/etc/apt/apt.conf.d/01proxy`. Valid options: a string containing a hostname. Default: undef.
 
-**Note:** The facts depend on 'update-notifier' being installed on your system. Though this is a GNOME daemon only the support files are needed so the package 'update-notifier-common' is enough to enable this functionality.
+  * 'port': Specifies a proxy port to be stored in `/etc/apt/apt.conf.d/01proxy`. Valid options: a string containing a port number. Default: '8080'.
 
-#### Hiera example
+  * 'https': Specifies whether to enable https proxies. Valid options: 'true' and 'false'. Default: 'false'.
 
-```
-
-apt::sources:
-  'debian_unstable':
-    location: 'http://debian.mirror.iweb.ca/debian/'
-    release: 'unstable'
-    repos: 'main contrib non-free'
-    required_packages: 'debian-keyring debian-archive-keyring'
-    key: '9AA38DCD55BE302B'
-    key_server: 'subkeys.pgp.net'
-    pin: '-10'
-    include_src: true
-    include_deb: true
+  * 'ensure': Optional parameter. Valid options: 'file', 'present', and 'absent'. Default: 'undef'. Prefer 'file' over 'present'.
 
-  'puppetlabs':
-    location: 'http://apt.puppetlabs.com'
-    repos: 'main'
-    key: '1054B7A24BD6EC30'
-    key_server: 'pgp.mit.edu'
-
-``` - -### Parameters - -#### apt - -* `always_apt_update`: Set to 'true' to update Apt on every run. This setting is intended for development environments where package updates are frequent. Defaults to 'false'. -* `apt_update_frequency`: Sets the run frequency for `apt-get update`. Defaults to 'reluctantly'. Accepts the following values: - * 'always': Runs update at every Puppet run. - * 'daily': Runs update daily; that is, `apt-get update` runs if the value of `apt_update_last_success` is less than current epoch time - 86400. If the exec resource `apt_update` is notified, `apt-get update` runs regardless of this value. - * 'weekly': Runs update weekly; that is, `apt-get update` runs if the value of `apt_update_last_success` is less than current epoch time - 604800. If the exec resource `apt_update` is notified, `apt-get update` runs regardless of this value. - * 'reluctantly': Only runs `apt-get update` if the exec resource `apt_update` is notified. This is the default setting. -* `disable_keys`: Disables the requirement for all packages to be signed. -* `proxy_host`: Configures a proxy host and stores the configuration in /etc/apt/apt.conf.d/01proxy. -* `proxy_port`: Configures a proxy port and stores the configuration in /etc/apt/apt.conf.d/01proxy. -* `purge_sources_list`: If set to 'true', Puppet purges all unmanaged entries from sources.list. Accepts 'true' or 'false'. Defaults to 'false'. -* `purge_sources_list_d`: If set to 'true', Puppet purges all unmanaged entries from sources.list.d. Accepts 'true' or 'false'. Defaults to 'false'. -* `update_timeout`: Overrides the exec timeout in seconds for `apt-get update`. Defaults to exec default (300). -* `update_tries`: Sets how many times to attempt running `apt-get update`. Use this to work around transient DNS and HTTP errors. By default, the command runs only once. -* `sources`: Passes a hash to create_resource to make new `apt::source` resources. -* `fancy_progress`: Enables fancy progress bars for apt. Accepts 'true', 'false'. Defaults to 'false'. - -####apt::unattended_upgrades - -* `legacy_origin`: If set to true, use the old `Unattended-Upgrade::Allowed-Origins` variable. If false, use `Unattended-Upgrade::Origins-Pattern`. OS-dependent defaults are defined in `apt::params`. -* `origins`: The repositories from which to automatically upgrade included packages. -* `blacklist`: A list of packages to **not** automatically upgrade. -* `update`: How often, in days, to run `apt-get update`. -* `download`: How often, in days, to run `apt-get upgrade --download-only`. -* `upgrade`: How often, in days, to upgrade packages included in the origins list. -* `autoclean`: How often, in days, to run `apt-get autoclean`. -* `randomsleep`: How long, in seconds, to randomly wait before applying upgrades. - -####apt::source - -* `comment`: Add a comment to the apt source file. -* `ensure`: Allows you to remove the apt source file. Can be 'present' or 'absent'. -* `location`: The URL of the apt repository. -* `release`: The distribution of the apt repository. Defaults to fact 'lsbdistcodename'. -* `repos`: The component of the apt repository. This defaults to 'main'. -* `include_deb`: References a Debian distribution's binary package. -* `include_src`: Enable the deb-src type, references a Debian distribution's source code in the same form as the include_deb type. A deb-src line is required to fetch source indexes. -* `required_packages`: install required packages via an exec. defaults to 'false'. -* `key`: See apt::key -* `key_server`: See apt::key -* `key_content`: See apt::key -* `key_source`: See apt::key -* `pin`: See apt::pin -* `architecture`: can be used to specify for which architectures information should be downloaded. If this option is not set all architectures defined by the APT::Architectures option will be downloaded. Defaults to 'undef' which means all. Example values can be 'i386' or 'i386,alpha,powerpc'. -* `trusted_source` can be set to indicate that packages from this source are always authenticated even if the Release file is not signed or the signature can't be checked. Defaults to false. Can be 'true' or 'false'. - -####apt::key - -* `ensure`: The state we want this key in. Can be 'present' or 'absent'. -* `key`: Is a GPG key ID or full key fingerprint. This value is validated with a regex enforcing it to only contain valid hexadecimal characters, be precisely 8 or 16 hexadecimal characters long and optionally prefixed with 0x for key IDs, or 40 hexadecimal characters long for key fingerprints. -* `key_content`: This parameter can be used to pass in a GPG key as a string in case it cannot be fetched from a remote location and using a file resource is for other reasons inconvenient. -* `key_source`: This parameter can be used to pass in the location of a GPG key. This URI can take the form of a `URL` (ftp, http or https) and a `path` (absolute path to a file on the target system). -* `key_server`: The keyserver from where to fetch our GPG key. It can either be a domain name or URL. It defaults to undef which results in apt_key's default keyserver being used, currently `keyserver.ubuntu.com`. -* `key_options`: Additional options to pass on to `apt-key adv --keyserver-options`. - -####apt::pin - -* `ensure`: The state we want this pin in. Can be 'present' or 'absent'. -* `explanation`: Add a comment. Defaults to `${caller_module_name}: ${name}`. -* `order`: The order of the file name. Defaults to '', otherwise must be an integer. -* `packages`: The list of packages to pin. Defaults to '\*'. Can be an array or string. -* `priority`: Several versions of a package may be available for installation when the sources.list(5) file contains references to more than one distribution (for example, stable and testing). APT assigns a priority to each version that is available. Subject to dependency constraints, apt-get selects the version with the highest priority for installation. -* `release`: The Debian release. Defaults to ''. Typical values can be 'stable', 'testing' and 'unstable'. -* `origin`: Can be used to match a hostname. The following record will assign a high priority to all versions available from the server identified by the hostname. Defaults to ''. -* `version`: The specific form assigns a priority (a "Pin-Priority") to one or more specified packages with a specified version or version range. -* `codename`: The distribution (lsbdistcodename) of the apt repository. Defaults to ''. -* `release_version`: Names the release version. For example, the packages in the tree might belong to Debian release version 7. Defaults to ''. -* `component`: Names the licensing component associated with the packages in the directory tree of the Release file. defaults to ''. Typical values can be 'main', 'dependencies' and 'restricted' -* `originator`: Names the originator of the packages in the directory tree of the Release file. Defaults to ''. Most commonly, this is Debian. -* `label`: Names the label of the packages in the directory tree of the Release file. Defaults to ''. Most commonly, this is Debian. - -**Note**: Parameters release, origin, and version are mutually exclusive. - -It is recommended to read the manpage 'apt_preferences(5)' - -####apt::ppa - -* `ensure`: Whether we are adding or removing the PPA. Can be 'present' or 'absent'. Defaults to 'present'. -* `release`: The codename for the operating system you're running. Defaults to `$lsbdistcodename`. Required if lsb-release is not installed. -* `options`: Options to be passed to the `apt-add-repository` command. OS-dependent defaults are set in `apt::params`. -* `package_name`: The package that provides the `apt-add-repository` command. OS-dependent defaults are set in `apt::params`. -* `package_manage`: Whether or not to manage the package providing `apt-add-repository`. Defaults to true. - -### Testing - -The apt module is mostly a collection of defined resource types, which provide reusable logic for managing Apt. It provides smoke tests for testing functionality on a target system, as well as spec tests for checking a compiled catalog against an expected set of resources. - -#### Example Test - -This test sets up a Puppet Labs Apt repository. Start by creating a new smoke test, called puppetlabs-apt.pp, in the apt module's test folder. In this test, declare a single resource representing the Puppet Labs Apt source and GPG key: - -``` -apt::source { 'puppetlabs': - location => 'http://apt.puppetlabs.com', - repos => 'main', - key => '1054B7A24BD6EC30', - key_server => 'pgp.mit.edu', -} -``` +* `purge`: Specifies whether to purge any existing settings that aren't managed by Puppet. Valid options: a hash made up from the following keys: + + * 'sources.list': Specifies whether to purge any unmanaged entries from `sources.list`. Valid options: 'true' and 'false'. Default: 'false'. + + * 'sources.list.d': Specifies whether to purge any unmanaged entries from `sources.list.d`. Valid options: 'true' and 'false'. Default: 'false'. + + * 'preferences': Specifies whether to purge any unmanaged entries from `preferences`. Valid options: 'true' and 'false'. Default: 'false'. + + * 'preferences.d': Specifies whether to purge any unmanaged entries from `preferences.d`. Valid options: 'true' and 'false'. Default: 'false'. + +* `settings`: Creates new `apt::setting` resources. Valid options: a hash to be passed to the [`create_resources` function](https://docs.puppetlabs.com/references/latest/function.html#createresources). Default: {}. + +* `sources`: Creates new `apt::source` resources. Valid options: a hash to be passed to the [`create_resources` function](https://docs.puppetlabs.com/references/latest/function.html#createresources). Default: {}. + +* `pins`: Creates new `apt::pin` resources. Valid options: a hash to be passed to the [`create_resources` function](https://docs.puppetlabs.com/references/latest/function.html#createresources). Default: {}. + +* `update`: Configures various update settings. Valid options: a hash made up from the following keys: + + * 'frequency': Specifies how often to run `apt-get update`. If the exec resource `apt_update` is notified, `apt-get update` runs regardless of this value. Valid options: 'always' (at every Puppet run); 'daily' (if the value of `apt_update_last_success` is less than current epoch time minus 86400); 'weekly' (if the value of `apt_update_last_success` is less than current epoch time minus 604800); and 'reluctantly' (only if the exec resource `apt_update` is notified). Default: 'reluctantly'. + + * 'timeout': Specifies how long to wait for the update to complete before canceling it. Valid options: an integer, in seconds. Default: 300. + + * 'tries': Specifies how many times to retry the update after receiving a DNS or HTTP error. Valid options: an integer. Default: 1. + +#### Class: `apt::backports` + +Manages backports. + +##### Parameters (all optional on Debian and Ubuntu; all required on other operating systems, except where specified) + +* `key`: Specifies a key to authenticate the backports. Valid options: a string to be passed to the `id` parameter of the `apt::key` define, or a hash of `parameter => value` pairs to be passed to `apt::key`'s `id`, `server`, `content`, `source`, and/or `options` parameters. Defaults: + + * Debian: 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553' + * Ubuntu: '630239CC130E1A7FD81A27B140976EAF437D05B5' + +* `location`: Specifies an Apt repository containing the backports to manage. Valid options: a string containing a URL. Defaults: + + * Debian (squeeze): 'http://httpredir.debian.org/debian-backports' + * Debian (other): 'http://httpredir.debian.org/debian' + * Ubuntu: 'http://archive.ubuntu.com/ubuntu' + +* `pin`: *Optional.* Specifies a pin priority for the backports. Valid options: a number or string to be passed to the `id` parameter of the `apt::pin` define, or a hash of `parameter => value` pairs to be passed to `apt::pin`'s corresponding parameters. Default: '200'. + +* `release`: Specifies a distribution of the Apt repository containing the backports to manage. Valid options: a string containing the release, used in populating the `source.list` configuration file. Default: on Debian and Ubuntu, '${lsbdistcodename}-backports'. We recommend keeping this default, except on other operating systems. + +* `repos`: Specifies a component of the Apt repository containing the backports to manage. Valid options: A string containing the repos to include, used in populating the `source.list` configuration file. Defaults: + + * Debian: 'main contrib non-free' + * Ubuntu: 'main universe multiverse restricted' + +#### Define: `apt::conf` + +Specifies a custom Apt configuration file. + +##### Parameters + +* `content`: *Required, unless `ensure` is set to 'absent'.* Directly supplies content for the configuration file. Valid options: a string. Default: undef. + +* `ensure`: Specifies whether the configuration file should exist. Valid options: 'present' and 'absent'. Default: 'present'. + +* `priority`: *Optional.* Determines the order in which Apt processes the configuration file. Files with lower priority numbers are loaded first. Valid options: a string containing an integer. Default: '50'. + +* `notify_update`: *Optional.* Specifies whether to trigger an `apt-get update` run. Valid options: 'true' and 'false'. Default: 'true'. + +#### Define: `apt::key` + +Manages the GPG keys that Apt uses to authenticate packages. + +The `apt::key` define makes use of the `apt_key` type, but includes extra functionality to help prevent duplicate keys. + +##### Parameters (all optional) + +* `content`: Supplies the entire GPG key. Useful in case the key can't be fetched from a remote location and using a file resource is inconvenient. Valid options: a string. Default: undef. + +* `ensure`: Specifies whether the key should exist. Valid options: 'present' and 'absent'. Default: 'present'. + +* `id`: Specifies a GPG key to authenticate Apt package signatures. Valid options: a string containing a key ID (8 or 16 hexadecimal characters, optionally prefixed with "0x") or a full key fingerprint (40 hexadecimal characters). Default: $title. + +* `options`: Passes additional options to `apt-key adv --keyserver-options`. Valid options: a string. Default: undef. + +* `source`: Specifies the location of an existing GPG key file to copy. Valid options: a string containing a URL (ftp://, http://, or https://) or an absolute path. Default: undef. + +* `server`: Specifies a keyserver to provide the GPG key. Valid options: a string containing a domain name or a full URL (http://, https://, or hkp://). Default: 'keyserver.ubuntu.com'. + +* `key`: Specifies a GPG key to authenticate Apt package signatures. Valid options: a string containing a key ID (8 or 16 hexadecimal characters, optionally prefixed with "0x") or a full key fingerprint (40 hexadecimal characters). Default: undef. **Note** This parameter is deprecated and will be removed in a future release. + +* `key_content`: Supplies the entire GPG key. Useful in case the key can't be fetched from a remote location and using a file resource is inconvenient. Valid options: a string. Default: undef. **Note** This parameter is deprecated and will be removed in a future release. + +* `key_source`: Specifies the location of an existing GPG key file to copy. Valid options: a string containing a URL (ftp://, http://, or https://) or an absolute path. Default: undef. **Note** This parameter is deprecated and will be removed in a future release. + +* `key_server`: Specifies a keyserver to provide the GPG key. Valid options: a string containing a domain name or a full URL (http://, https://, or hkp://). Default: 'keyserver.ubuntu.com'. **Note** This parameter is deprecated and will be removed in a future release. + +* `key_options`: Passes additional options to `apt-key adv --keyserver-options`. Valid options: a string. Default: undef. **Note** This parameter is deprecated and will be removed in a future release. + +#### Define: `apt::pin` + +Manages Apt pins. Does not trigger an `apt-get update` run. + +**Note:** For context on these parameters, we recommend reading the man page ['apt_preferences(5)'](http://linux.die.net/man/5/apt_preferences) + +##### Parameters (all optional) + +* `codename`: Specifies the distribution (lsbdistcodename) of the Apt repository. Valid options: a string. Default: ''. + +* `component`: Names the licensing component associated with the packages in the directory tree of the Release file. Valid options: a string. Default: ''. + +* `ensure`: Specifies whether the pin should exist. Valid options: 'file', 'present', and 'absent'. Default: 'present'. + +* `explanation`: Supplies a comment to explain the pin. Valid options: a string. Default: "${caller_module_name}: ${name}". + +* `label`: Names the label of the packages in the directory tree of the Release file. Valid options: a string (most commonly, 'debian'). Default: ''. + +* `order`: Determines the order in which Apt processes the pin file. Files with lower order numbers are loaded first. Valid options: an integer. Default: 50. + +* `origin`: Tells Apt to prefer packages from the specified server. Valid options: a string containing a hostname. Default: ''. + +* `originator`: Names the originator of the packages in the directory tree of the Release file. Valid options: a string (most commonly, 'debian'). Default: ''. + +* `packages`: Specifies which package(s) to pin. Valid options: a string or an array. Default: '*'. + +* `priority`: Sets the priority of the package. If multiple versions of a given package are available, `apt-get` installs the one with the highest priority number (subject to dependency constraints). Valid options: an integer. Default: 0. + +* `release`: Tells Apt to prefer packages that support the specified release. Typical values include 'stable', 'testing', and 'unstable' Valid options: a string. Default: ''. + +* `release_version`: Tells Apt to prefer packages that support the specified operating system release version (e.g., Debian release version 7). Valid options: a string. Default: ''. + +* `version`: Tells Apt to prefer a specified package version or version range. Valid options: a string. Default: ''. + +#### Define: `apt::ppa` + +Manages PPA repositories using `add-apt-repository`. Not supported on Debian. + +##### Parameters (all optional, except where specified) + +* `ensure`: Specifies whether the PPA should exist. Valid options: 'present' and 'absent'. Default: 'present'. + +* `options`: Supplies options to be passed to the `add-apt-repository` command. Valid options: a string. Defaults: + + * Lucid: undef + * All others: '-y' + +* `package_manage`: Specifies whether Puppet should manage the package that provides `apt-add-repository`. Valid options: 'true' and 'false'. Default: 'false'. + +* `package_name`: Names the package that provides the `apt-add-repository` command. Valid options: a string. Defaults: + + * Lucid and Precise: 'python-software-properties' + * Trusty, Utopic, and Vivid: 'software-properties-common' + * All others: undef + +* `release`: *Optional if lsb-release is installed (unless you're using a different release than indicated by lsb-release, e.g., Linux Mint).* Specifies the operating system of your node. Valid options: a string containing a valid LSB distribution codename. Default: "$lsbdistcodename". + +#### Define: `apt:setting` + +Manages Apt configuration files. + +##### Parameters + +* `content`: *Required, unless `source` is set.* Directly supplies content for the configuration file. Cannot be used in combination with `source`. Valid options: see the `content` attribute of [Puppet's native `file` type](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-content). Default: undef. + +* `ensure`: Specifies whether the file should exist. Valid options: 'present', 'absent', and 'file'. Default: 'file'. + +* `notify_update`: *Optional.* Specifies whether to trigger an `apt-get update` run. Valid options: 'true' and 'false'. Default: 'true'. + +* `priority`: *Optional.* Determines the order in which Apt processes the configuration file. Files with higher priority numbers are loaded first. Valid options: an integer or zero-padded integer. Default: 50. + +* `source`: *Required, unless `content` is set.* Specifies a source file to supply the content of the configuration file. Cannot be used in combination with `content`. Valid options: see the `source` attribute of [Puppet's native `file` type](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-source). Default: undef. + +#### Define: `apt::source` + +Manages the Apt sources in `/etc/apt/sources.list.d/`. + +##### Parameters (all optional, except where specified) + +* `allow_unsigned`: Specifies whether to authenticate packages from this release, even if the Release file is not signed or the signature can't be checked. Valid options: 'true' and 'false'. Default: 'false'. + +* `architecture`: Tells Apt to only download information for specified architectures. Valid options: a string containing one or more architecture names, separated by commas (e.g., 'i386' or 'i386,alpha,powerpc'). Default: undef (if unspecified, Apt downloads information for all architectures defined in the Apt::Architectures option). + +* `comment`: Supplies a comment for adding to the Apt source file. Valid options: a string. Default: $name. + +* `ensure`: Specifies whether the Apt source file should exist. Valid options: 'present' and 'absent'. Default: 'present'. + +* `key`: Creates a declaration of the apt::key define Valid options: a string to be passed to the `id` parameter of the `apt::key` define, or a hash of `parameter => value` pairs to be passed to `apt::key`'s `id`, `server`, `content`, `source`, and/or `options` parameters. Default: undef. + +* `include`: Configures include options. Valid options: a hash of available keys. Default: {}. Available keys are: + + * 'deb' - Specifies whether to request the distribution's compiled binaries. Valid options: 'true' and 'false'. Default: 'true'. + + * 'src' - Specifies whether to request the distribution's uncompiled source code. Valid options: 'true' and 'false'. Default: 'false'. + +* `location`: *Required, unless `ensure` is set to 'absent'.* Specifies an Apt repository. Valid options: a string containing a repository URL. Default: undef. + +* `pin`: Creates a declaration of the apt::pin define Valid options: a number or string to be passed to the `id` parameter of the `apt::pin` define, or a hash of `parameter => value` pairs to be passed to `apt::pin`'s corresponding parameters. Default: undef. + +* `release`: Specifies a distribution of the Apt repository. Valid options: a string. Default: "$lsbdistcodename". + + * `repos`: Specifies a component of the Apt repository. Valid options: a string. Default: 'main'. + +* `include_deb`: Specify whether to request the distrubution's compiled binaries. Valid options: 'true' and 'false'. Default: undef. **Note**: This parameter is deprecated and will be removed in future versions of the module. + +* `include_src`: Specifies whether to request the distribution's uncompiled source code. Valid options: 'true' and 'false'. Default: undef. **Note**: This parameter is deprecated and will be removed in future versions of the module. + +* `required_packages`: Installs packages required for this Apt source via an exec. Default: 'false'. **Note**: This parameter is deprecated and will be removed in future versions of the module. + +* `key_content`: Specifies the content to be passed to `apt::key`. Default: undef. **Note**: This parameter is deprecated and will be removed in future versions of the module. + +* `key_server`: Specifies the server to be passed to `apt::key`. Default: undef. **Note**: This parameter is deprecated and will be removed in future versions of the module. -This resource creates an Apt source named puppetlabs and gives Puppet information about the repository's location and the key used to sign its packages. Puppet leverages Facter to determine the appropriate release, but you can set this directly by adding the release type. +* `key_source`: Specifies the source to be passed to `apt::key`. Default: undef. **Note**: This parameter is deprecated and will be removed in future versions of the module. -Check your smoke test for syntax errors: +* `trusted_source`: Specifies whether to authenticate packages from this release, even if the Release file is not signed or the signature can't be checked. Valid options: 'true' and 'false'. Default: undef. This parameter is **deprecated** and will be removed in a future version of the module. -`$ puppet parser validate tests/puppetlabs-apt.pp` +#### Type: `apt_key` -If you receive no output from that command, it means nothing is wrong. Then, apply the code: +Manages the GPG keys that Apt uses to authenticate packages. -``` -$ puppet apply --verbose tests/puppetlabs-apt.pp -notice: /Stage[main]//Apt::Source[puppetlabs]/File[puppetlabs.list]/ensure: defined content as '{md5}3be1da4923fb910f1102a233b77e982e' -info: /Stage[main]//Apt::Source[puppetlabs]/File[puppetlabs.list]: Scheduling refresh of Exec[puppetlabs apt update] -notice: /Stage[main]//Apt::Source[puppetlabs]/Exec[puppetlabs apt update]: Triggered 'refresh' from 1 events> -``` +**Note:** In most cases, we recommend using the `apt::key` define. It makes use of the `apt_key` type, but includes extra functionality to help prevent duplicate keys. -The above example uses a smoke test to lay out a resource declaration and apply it on your system. In production, you might want to declare your Apt sources inside the classes where they’re needed. +##### Parameters (all optional) -Limitations ------------ +* `content`: Supplies the entire GPG key. Useful in case the key can't be fetched from a remote location and using a file resource is inconvenient. Cannot be used in combination with `source`. Valid options: a string. Default: undef. -This module should work across all versions of Debian/Ubuntu and support all major Apt repository management features. +* `options`: Passes additional options to `apt-key adv --keyserver-options`. Valid options: a string. Default: undef. -Development ------------- +* `server`: Specifies a keyserver to provide Puppet's GPG key. Valid options: a string containing a domain name or a full URL. Default: 'keyserver.ubuntu.com'. -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. +* `source`: Specifies the location of an existing GPG key file to copy. Cannot be used in combination with `content`. Valid options: a string containing a URL (ftp://, http://, or https://) or an absolute path. Default: undef. -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. +## Limitations -You can read the complete module contribution guide [on the Puppet Labs wiki.](http://projects.puppetlabs.com/projects/module-site/wiki/Module_contributing) +This module is tested and officially supported on Debian 6 and 7 and Ubuntu 10.04, 12.04, and 14.04. Testing on other platforms has been light and cannot be guaranteed. -License -------- +### Adding new sources or PPAs -The original code for this module comes from Evolving Web and was licensed under the MIT license. Code added since the fork of this module is licensed under the Apache 2.0 License like the rest of the Puppet Labs products. +If you are adding a new source or PPA and trying to install packages from the new source or PPA on the same Puppet run, your `package` resource should depend on `Class['apt::update']`, in addition to depending on the `Apt::Source` or the `Apt::Ppa`. You can also add [collectors](https://docs.puppetlabs.com/puppet/latest/reference/lang_collectors.html) to ensure that all packages happen after `apt::update`, but this can lead to dependency cycles and has implications for [virtual resources](https://docs.puppetlabs.com/puppet/latest/reference/lang_collectors.html#behavior). -The LICENSE contains both licenses. +~~~puppet +Class['apt::update'] -> Package<| |> +~~~ -Contributors ------------- +## 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. -A lot of great people have contributed to this module. A somewhat current list follows: +For more information, see our [module contribution guide.](https://docs.puppetlabs.com/forge/contributing.html) -* Ben Godfrey -* Branan Purvine-Riley -* Christian G. Warden -* Dan Bode -* Daniel Tremblay -* Garrett Honeycutt -* Jeff Wallace -* Ken Barber -* Matthaus Litteken -* Matthias Pigulla -* Monty Taylor -* Peter Drake -* Reid Vandewiele -* Robert Navarro -* Ryan Coleman -* Scott McLeod -* Spencer Krum -* William Van Hevelingen -* Zach Leslie -* Daniele Sluijters -* Daniel Paulus -* Wolf Noble +To see who's already involved, see the [list of contributors.](https://github.com/puppetlabs/puppetlabs-apt/graphs/contributors) diff --git a/puphpet/puppet/modules/apt/examples/backports.pp b/puphpet/puppet/modules/apt/examples/backports.pp new file mode 100644 index 0000000..0dfe084 --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/backports.pp @@ -0,0 +1,11 @@ +# Set up a backport for linuxmint qiana +class { 'apt': } +apt::backports { 'qiana': + location => 'http://us.archive.ubuntu.com/ubuntu', + release => 'trusty-backports', + repos => 'main universe multiverse restricted', + key => { + id => '630239CC130E1A7FD81A27B140976EAF437D05B5', + server => 'pgp.mit.edu', + }, +} diff --git a/puphpet/puppet/modules/apt/examples/builddep.pp b/puphpet/puppet/modules/apt/examples/builddep.pp new file mode 100644 index 0000000..deaaef8 --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/builddep.pp @@ -0,0 +1,3 @@ +package{ 'glusterfs-server': + install_options => 'build-dep', +} diff --git a/puphpet/puppet/modules/apt/examples/debian_testing.pp b/puphpet/puppet/modules/apt/examples/debian_testing.pp new file mode 100644 index 0000000..3ed98f2 --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/debian_testing.pp @@ -0,0 +1,18 @@ +package { 'debian-keyring': + ensure => present +} + +package { 'debian-archive-keyring': + ensure => present +} + +apt::source { 'debian_testing': + location => 'http://debian.mirror.iweb.ca/debian/', + release => 'testing', + repos => 'main contrib non-free', + pin => '-10', + key => { + id => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + server => 'subkeys.pgp.net', + }, +} diff --git a/puphpet/puppet/modules/apt/examples/debian_unstable.pp b/puphpet/puppet/modules/apt/examples/debian_unstable.pp new file mode 100644 index 0000000..b1492cd --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/debian_unstable.pp @@ -0,0 +1,18 @@ +package { 'debian-keyring': + ensure => present +} + +package { 'debian-archive-keyring': + ensure => present +} + +apt::source { 'debian_unstable': + location => 'http://debian.mirror.iweb.ca/debian/', + release => 'unstable', + repos => 'main contrib non-free', + pin => '-10', + key => { + id => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + server => 'subkeys.pgp.net', + }, +} diff --git a/puphpet/puppet/modules/apt/examples/disable_keys.pp b/puphpet/puppet/modules/apt/examples/disable_keys.pp new file mode 100644 index 0000000..50d0ea8 --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/disable_keys.pp @@ -0,0 +1,5 @@ +#Note: This is generally a bad idea. You should not disable verifying repository signatures. +apt::conf { 'unauth': + priority => 99, + content => 'APT::Get::AllowUnauthenticated 1;' +} diff --git a/puphpet/puppet/modules/apt/examples/fancy_progress.pp b/puphpet/puppet/modules/apt/examples/fancy_progress.pp new file mode 100644 index 0000000..db78441 --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/fancy_progress.pp @@ -0,0 +1,4 @@ +apt::conf { 'progressbar': + priority => 99, + content => 'Dpkg::Progress-Fancy "1";', +} diff --git a/puphpet/puppet/modules/apt/examples/force.pp b/puphpet/puppet/modules/apt/examples/force.pp new file mode 100644 index 0000000..4cfaa96 --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/force.pp @@ -0,0 +1,28 @@ +#if you need to specify a release +$rel_string = '-t ' +#else +$rel_string = '' + +#if you need to specify a version +$ensure = '' +#else +$ensure = installed + +#if overwrite existing cfg files +$config_files = '-o Dpkg::Options::="--force-confnew"' +#elsif force use of old files +$config_files = '-o Dpkg::Options::="--force-confold"' +#elsif update only unchanged files +$config_files = '-o Dpkg::Options::="--force-confdef"' +#else +$config_files = '' + +#if install missing configuration files for the package +$config_missing = '-o Dpkg::Options::="--force-confmiss"' +#else +$config_missing = '' + +package { '': + ensure => $ensure, + install_options => "${config_files} ${config_missing} ${rel_string}", +} diff --git a/puphpet/puppet/modules/apt/examples/hold.pp b/puphpet/puppet/modules/apt/examples/hold.pp new file mode 100644 index 0000000..00f760c --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/hold.pp @@ -0,0 +1,5 @@ +apt::pin { 'hold-vim': + packages => 'vim', + version => '2:7.4.488-5', + priority => 1001, +} diff --git a/puphpet/puppet/modules/apt/examples/key.pp b/puphpet/puppet/modules/apt/examples/key.pp new file mode 100644 index 0000000..cc8681f --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/key.pp @@ -0,0 +1,6 @@ +# Declare Apt key for apt.puppetlabs.com source +apt::key { 'puppetlabs': + id => '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30', + server => 'pgp.mit.edu', + options => 'http-proxy="http://proxyuser:proxypass@example.org:3128"', +} diff --git a/puphpet/puppet/modules/apt/tests/pin.pp b/puphpet/puppet/modules/apt/examples/pin.pp similarity index 100% rename from puphpet/puppet/modules/apt/tests/pin.pp rename to puphpet/puppet/modules/apt/examples/pin.pp diff --git a/puphpet/puppet/modules/apt/tests/ppa.pp b/puphpet/puppet/modules/apt/examples/ppa.pp similarity index 100% rename from puphpet/puppet/modules/apt/tests/ppa.pp rename to puphpet/puppet/modules/apt/examples/ppa.pp diff --git a/puphpet/puppet/modules/apt/examples/release.pp b/puphpet/puppet/modules/apt/examples/release.pp new file mode 100644 index 0000000..46d6893 --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/release.pp @@ -0,0 +1,4 @@ +apt::conf { 'release': + content => 'APT::Default-Release "karmic";', + priority => '01', +} diff --git a/puphpet/puppet/modules/apt/examples/source.pp b/puphpet/puppet/modules/apt/examples/source.pp new file mode 100644 index 0000000..33dc2a1 --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/source.pp @@ -0,0 +1,35 @@ +# Declare the apt class to manage /etc/apt/sources.list and /etc/sources.list.d +class { 'apt': } + +# Install the puppetlabs apt source +# Release is automatically obtained from lsbdistcodename fact if available. +apt::source { 'puppetlabs': + location => 'http://apt.puppetlabs.com', + repos => 'main', + key => { + id => '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30', + server => 'pgp.mit.edu', + }, +} + +# test two sources with the same key +apt::source { 'debian_testing': + location => 'http://debian.mirror.iweb.ca/debian/', + release => 'testing', + repos => 'main contrib non-free', + key => { + id => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + server => 'subkeys.pgp.net', + }, + pin => '-10', +} +apt::source { 'debian_unstable': + location => 'http://debian.mirror.iweb.ca/debian/', + release => 'unstable', + repos => 'main contrib non-free', + key => { + id => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + server => 'subkeys.pgp.net', + }, + pin => '-10', +} diff --git a/puphpet/puppet/modules/apt/examples/unattended_upgrades.pp b/puphpet/puppet/modules/apt/examples/unattended_upgrades.pp new file mode 100644 index 0000000..4640904 --- /dev/null +++ b/puphpet/puppet/modules/apt/examples/unattended_upgrades.pp @@ -0,0 +1 @@ +# TODO diff --git a/puphpet/puppet/modules/apt/lib/facter/apt_reboot_required.rb b/puphpet/puppet/modules/apt/lib/facter/apt_reboot_required.rb new file mode 100644 index 0000000..8de904a --- /dev/null +++ b/puphpet/puppet/modules/apt/lib/facter/apt_reboot_required.rb @@ -0,0 +1,7 @@ +# apt_reboot_required.rb +Facter.add(:apt_reboot_required) do + confine :osfamily => 'Debian' + setcode do + File.file?('/var/run/reboot-required') + end +end diff --git a/puphpet/puppet/modules/apt/lib/puppet/provider/apt_key/apt_key.rb b/puphpet/puppet/modules/apt/lib/puppet/provider/apt_key/apt_key.rb index cd68d37..f8c7d19 100644 --- a/puphpet/puppet/modules/apt/lib/puppet/provider/apt_key/apt_key.rb +++ b/puphpet/puppet/modules/apt/lib/puppet/provider/apt_key/apt_key.rb @@ -141,7 +141,14 @@ def tempfile(content) if File.executable? command(:gpg) extracted_key = execute(["#{command(:gpg)} --with-fingerprint --with-colons #{file.path} | awk -F: '/^fpr:/ { print $10 }'"], :failonfail => false) extracted_key = extracted_key.chomp - if extracted_key != name + + found_match = false + extracted_key.each_line do |line| + if line.chomp == name + found_match = true + end + end + if not found_match fail("The id in your manifest #{resource[:name]} and the fingerprint from content/source do not match. Please check there is not an error in the id or check the content/source is legitimate.") end else @@ -161,8 +168,8 @@ def create # Breaking up the command like this is needed because it blows up # if --recv-keys isn't the last argument. command.push('adv', '--keyserver', resource[:server]) - unless resource[:keyserver_options].nil? - command.push('--keyserver-options', resource[:keyserver_options]) + unless resource[:options].nil? + command.push('--keyserver-options', resource[:options]) end command.push('--recv-keys', resource[:id]) elsif resource[:content] diff --git a/puphpet/puppet/modules/apt/lib/puppet/type/apt_key.rb b/puphpet/puppet/modules/apt/lib/puppet/type/apt_key.rb index 7130496..81b66a2 100644 --- a/puphpet/puppet/modules/apt/lib/puppet/type/apt_key.rb +++ b/puphpet/puppet/modules/apt/lib/puppet/type/apt_key.rb @@ -61,11 +61,11 @@ newparam(:server) do desc 'The key server to fetch the key from based on the ID. It can either be a domain name or url.' defaultto :'keyserver.ubuntu.com' - + newvalues(/\A((hkp|http|https):\/\/)?([a-z\d])([a-z\d-]{0,61}\.)+[a-z\d]+(:\d{2,5})?$/) end - newparam(:keyserver_options) do + newparam(:options) do desc 'Additional options to pass to apt-key\'s --keyserver-options.' end diff --git a/puphpet/puppet/modules/apt/manifests/backports.pp b/puphpet/puppet/modules/apt/manifests/backports.pp index ff8cb44..f7e85f5 100644 --- a/puphpet/puppet/modules/apt/manifests/backports.pp +++ b/puphpet/puppet/modules/apt/manifests/backports.pp @@ -1,82 +1,65 @@ -# This adds the necessary components to get backports for ubuntu and debian -# -# == Parameters -# -# [*release*] -# The ubuntu/debian release name. Defaults to $lsbdistcodename. Setting this -# manually can cause undefined behavior. (Read: universe exploding) -# -# [*pin_priority*] -# _default_: 200 -# -# The priority that should be awarded by default to all packages coming from -# the Debian Backports project. -# -# == Examples -# -# include apt::backports -# -# class { 'apt::backports': -# release => 'natty', -# } -# -# == Authors -# -# Ben Hughes, I think. At least blame him if this goes wrong. -# I just added puppet doc. -# -# == Copyright -# -# Copyright 2011 Puppet Labs Inc, unless otherwise noted. -class apt::backports( - $release = $::lsbdistcodename, - $location = $::apt::params::backports_location, - $pin_priority = 200, -) inherits apt::params { - - if ! is_integer($pin_priority) { - fail('$pin_priority must be an integer') +class apt::backports ( + $location = undef, + $release = undef, + $repos = undef, + $key = undef, + $pin = 200, +){ + if $location { + validate_string($location) + $_location = $location } - - if $::lsbdistid == 'LinuxMint' { - if $::lsbdistcodename == 'debian' { - $distid = 'debian' - $release_real = 'wheezy' - } else { - $distid = 'ubuntu' - $release_real = $::lsbdistcodename ? { - 'qiana' => 'trusty', - 'petra' => 'saucy', - 'olivia' => 'raring', - 'nadia' => 'quantal', - 'maya' => 'precise', - } - } - } else { - $distid = $::lsbdistid - $release_real = downcase($release) + if $release { + validate_string($release) + $_release = $release } - - $key = $distid ? { - 'debian' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', - 'ubuntu' => '630239CC130E1A7FD81A27B140976EAF437D05B5', + if $repos { + validate_string($repos) + $_repos = $repos } - $repos = $distid ? { - 'debian' => 'main contrib non-free', - 'ubuntu' => 'main universe multiverse restricted', + if $key { + unless is_hash($key) { + validate_string($key) + } + $_key = $key + } + if ($::apt::xfacts['lsbdistid'] == 'debian' or $::apt::xfacts['lsbdistid'] == 'ubuntu') { + unless $location { + $_location = $::apt::backports['location'] + } + unless $release { + $_release = "${::apt::xfacts['lsbdistcodename']}-backports" + } + unless $repos { + $_repos = $::apt::backports['repos'] + } + unless $key { + $_key = $::apt::backports['key'] + } + } else { + unless $location and $release and $repos and $key { + fail('If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key') + } } - apt::pin { 'backports': - before => Apt::Source['backports'], - release => "${release_real}-backports", - priority => $pin_priority, + if is_hash($pin) { + $_pin = $pin + } elsif is_numeric($pin) or is_string($pin) { + # apt::source defaults to pinning to origin, but we should pin to release + # for backports + $_pin = { + 'priority' => $pin, + 'release' => $_release, + } + } else { + fail('pin must be either a string, number or hash') } apt::source { 'backports': - location => $location, - release => "${release_real}-backports", - repos => $repos, - key => $key, - key_server => 'pgp.mit.edu', + location => $_location, + release => $_release, + repos => $_repos, + key => $_key, + pin => $_pin, } } diff --git a/puphpet/puppet/modules/apt/manifests/builddep.pp b/puphpet/puppet/modules/apt/manifests/builddep.pp deleted file mode 100644 index 3a059c2..0000000 --- a/puphpet/puppet/modules/apt/manifests/builddep.pp +++ /dev/null @@ -1,16 +0,0 @@ -# builddep.pp - -define apt::builddep() { - include apt::update - - exec { "apt-builddep-${name}": - command => "/usr/bin/apt-get -y --force-yes build-dep ${name}", - logoutput => 'on_failure', - require => Exec['apt_update'], - } - - # Need anchor to provide containment for dependencies. - anchor { "apt::builddep::${name}": - require => Class['apt::update'], - } -} diff --git a/puphpet/puppet/modules/apt/manifests/conf.pp b/puphpet/puppet/modules/apt/manifests/conf.pp index 318422e..97b70a1 100644 --- a/puphpet/puppet/modules/apt/manifests/conf.pp +++ b/puphpet/puppet/modules/apt/manifests/conf.pp @@ -1,18 +1,20 @@ define apt::conf ( - $content, - $ensure = present, - $priority = '50' + $content = undef, + $ensure = present, + $priority = '50', + $notify_update = undef, ) { - include apt::params - - $apt_conf_d = $apt::params::apt_conf_d + unless $ensure == 'absent' { + unless $content { + fail('Need to pass in content parameter') + } + } - file { "${apt_conf_d}/${priority}${name}": - ensure => $ensure, - content => template('apt/_header.erb', 'apt/conf.erb'), - owner => root, - group => root, - mode => '0644', + apt::setting { "conf-${name}": + ensure => $ensure, + priority => $priority, + content => template('apt/_conf_header.erb', 'apt/conf.erb'), + notify_update => $notify_update, } } diff --git a/puphpet/puppet/modules/apt/manifests/debian/testing.pp b/puphpet/puppet/modules/apt/manifests/debian/testing.pp deleted file mode 100644 index 7af48d2..0000000 --- a/puphpet/puppet/modules/apt/manifests/debian/testing.pp +++ /dev/null @@ -1,21 +0,0 @@ -# testing.pp - -class apt::debian::testing { - include apt - - # deb http://debian.mirror.iweb.ca/debian/ testing main contrib non-free - # deb-src http://debian.mirror.iweb.ca/debian/ testing main contrib non-free - # Key: 46925553 Server: subkeys.pgp.net - # debian-keyring - # debian-archive-keyring - - apt::source { 'debian_testing': - location => 'http://debian.mirror.iweb.ca/debian/', - release => 'testing', - repos => 'main contrib non-free', - required_packages => 'debian-keyring debian-archive-keyring', - key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', - key_server => 'subkeys.pgp.net', - pin => '-10', - } -} diff --git a/puphpet/puppet/modules/apt/manifests/debian/unstable.pp b/puphpet/puppet/modules/apt/manifests/debian/unstable.pp deleted file mode 100644 index 23ce9b4..0000000 --- a/puphpet/puppet/modules/apt/manifests/debian/unstable.pp +++ /dev/null @@ -1,21 +0,0 @@ -# unstable.pp - -class apt::debian::unstable { - include apt - - # deb http://debian.mirror.iweb.ca/debian/ unstable main contrib non-free - # deb-src http://debian.mirror.iweb.ca/debian/ unstable main contrib non-free - # Key: 46925553 Server: subkeys.pgp.net - # debian-keyring - # debian-archive-keyring - - apt::source { 'debian_unstable': - location => 'http://debian.mirror.iweb.ca/debian/', - release => 'unstable', - repos => 'main contrib non-free', - required_packages => 'debian-keyring debian-archive-keyring', - key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', - key_server => 'subkeys.pgp.net', - pin => '-10', - } -} diff --git a/puphpet/puppet/modules/apt/manifests/force.pp b/puphpet/puppet/modules/apt/manifests/force.pp deleted file mode 100644 index 8ceeb17..0000000 --- a/puphpet/puppet/modules/apt/manifests/force.pp +++ /dev/null @@ -1,60 +0,0 @@ -# force.pp -# force a package from a specific release - -define apt::force( - $release = false, - $version = false, - $timeout = 300, - $cfg_files = 'none', - $cfg_missing = false, -) { - - validate_re($cfg_files, ['^new', '^old', '^unchanged', '^none']) - validate_bool($cfg_missing) - - $provider = $apt::params::provider - - $version_string = $version ? { - false => undef, - default => "=${version}", - } - - $release_string = $release ? { - false => undef, - default => "-t ${release}", - } - - case $cfg_files { - 'new': { $config_files = '-o Dpkg::Options::="--force-confnew"' } - 'old': { $config_files = '-o Dpkg::Options::="--force-confold"' } - 'unchanged': { $config_files = '-o Dpkg::Options::="--force-confdef"' } - 'none', default: { $config_files = '' } - } - - case $cfg_missing { - true: { $config_missing = '-o Dpkg::Options::="--force-confmiss"' } - false, default: { $config_missing = '' } - } - - if $version == false { - if $release == false { - $install_check = "/usr/bin/dpkg -s ${name} | grep -q 'Status: install'" - } else { - # If installed version and candidate version differ, this check returns 1 (false). - $install_check = "/usr/bin/test \$(/usr/bin/apt-cache policy -t ${release} ${name} | /bin/grep -E 'Installed|Candidate' | /usr/bin/uniq -s 14 | /usr/bin/wc -l) -eq 1" - } - } else { - if $release == false { - $install_check = "/usr/bin/dpkg -s ${name} | grep -q 'Version: ${version}'" - } else { - $install_check = "/usr/bin/apt-cache policy -t ${release} ${name} | /bin/grep -q 'Installed: ${version}'" - } - } - - exec { "${provider} -y ${config_files} ${config_missing} ${release_string} install ${name}${version_string}": - unless => $install_check, - environment => ['LC_ALL=C', 'LANG=C'], - logoutput => 'on_failure', - timeout => $timeout, - } -} diff --git a/puphpet/puppet/modules/apt/manifests/hold.pp b/puphpet/puppet/modules/apt/manifests/hold.pp deleted file mode 100644 index 61e8afc..0000000 --- a/puphpet/puppet/modules/apt/manifests/hold.pp +++ /dev/null @@ -1,54 +0,0 @@ -# == Define apt::hold -# -# This defined type allows you to hold a package based on the version you -# require. It's implemented by dropping an apt preferences file pinning the -# package to the version you require. -# -# === Parameters -# -# [*version*] -# The version at which you wish to pin a package. -# -# This can either be the full version, such as 4:2.11.8.1-5, or -# a partial version, such as 4:2.11.* -# -# [*package*] -# _default_: +$title+, the title/name of the resource. -# -# Name of the package that apt is to hold. -# -# [*priority*] -# _default_: +1001+ -# -# The default priority of 1001 causes this preference to always win. By -# setting the priority to a number greater than 1000 apt will always install -# this version even if it means downgrading the currently installed version. -define apt::hold( - $version, - $ensure = 'present', - $package = $title, - $priority = 1001, -){ - - validate_string($title) - validate_re($ensure, ['^present|absent',]) - validate_string($package) - validate_string($version) - - if ! is_integer($priority) { - fail('$priority must be an integer') - } - - if $ensure == 'present' { - ::apt::pin { "hold_${package}": - packages => $package, - version => $version, - priority => $priority, - } - } else { - ::apt::pin { "hold_${package}": - ensure => 'absent', - } - } - -} diff --git a/puphpet/puppet/modules/apt/manifests/init.pp b/puphpet/puppet/modules/apt/manifests/init.pp index 5f33fdb..2e82502 100644 --- a/puphpet/puppet/modules/apt/manifests/init.pp +++ b/puphpet/puppet/modules/apt/manifests/init.pp @@ -1,216 +1,163 @@ -# == Class: apt -# -# This module manages the initial configuration of apt. -# -# The parameters listed here are not required in general and were -# added for use cases related to development environments. -# -# === Parameters -# -# [*disable_keys*] -# Disables the requirement for all packages to be signed -# -# [*always_apt_update*] -# Rather apt should be updated on every run (intended -# for development environments where package updates are frequent) -# -# [*apt_update_frequency*] -# String: Supported values: -# **always**: Will fire `apt-get update` at every puppet run. Intended to -# deprecate the `always_apt_update` parameter. -# *daily**: Trigger `apt-get update` if the value of the fact -# `apt_update_last_success` is less than current epoch time - 86400. -# *notifying the apt_update exec will trigger apt-get update regardless* -# *weekly**: Trigger `apt-get update` if the value of the fact -# `apt_update_last_success` is less than current epoch time - 604800. -# *notifying the apt_update exec will trigger apt-get update regardless* -# *reluctantly**: *Default* only run apt-get update if the exec resource `apt_update` is notified. -# -# [*purge_sources_list*] -# Accepts true or false. Defaults to false If set to -# true, Puppet will purge all unmanaged entries from sources.list -# -# [*purge_sources_list_d*] -# Accepts true or false. Defaults to false. If set -# to true, Puppet will purge all unmanaged entries from sources.list.d -# -# [*update_timeout*] -# Overrides the exec timeout in seconds for apt-get update. -# If not set defaults to Exec's default (300) -# -# [*update_tries*] -# Number of times that `apt-get update` will be tried. Use this -# to work around transient DNS and HTTP errors. By default, the command -# will only be run once. -# -# === Examples -# -# class { 'apt': } -# -# === Requires -# -# puppetlabs/stdlib >= 2.2.1 # class apt( - $always_apt_update = false, - $apt_update_frequency = 'reluctantly', - $disable_keys = undef, - $proxy_host = undef, - $proxy_port = '8080', - $purge_sources_list = false, - $purge_sources_list_d = false, - $purge_preferences = false, - $purge_preferences_d = false, - $update_timeout = undef, - $update_tries = undef, - $sources = undef, - $fancy_progress = undef -) { - - if $::osfamily != 'Debian' { - fail('This module only works on Debian or derivatives like Ubuntu') - } + $update = {}, + $purge = {}, + $proxy = {}, + $sources = {}, + $keys = {}, + $ppas = {}, + $pins = {}, + $settings = {}, +) inherits ::apt::params { $frequency_options = ['always','daily','weekly','reluctantly'] - validate_re($apt_update_frequency, $frequency_options) - include apt::params - include apt::update + validate_hash($update) + if $update['frequency'] { + validate_re($update['frequency'], $frequency_options) + } + if $update['timeout'] { + unless is_integer($update['timeout']) { + fail('timeout value for update must be an integer') + } + } + if $update['tries'] { + unless is_integer($update['tries']) { + fail('tries value for update must be an integer') + } + } - validate_bool($purge_sources_list, $purge_sources_list_d, - $purge_preferences, $purge_preferences_d) + $_update = merge($::apt::update_defaults, $update) + include ::apt::update - $sources_list_content = $purge_sources_list ? { - false => undef, - true => "# Repos managed by puppet.\n", + validate_hash($purge) + if $purge['sources.list'] { + validate_bool($purge['sources.list']) + } + if $purge['sources.list.d'] { + validate_bool($purge['sources.list.d']) + } + if $purge['preferences'] { + validate_bool($purge['preferences']) + } + if $purge['preferences.d'] { + validate_bool($purge['preferences.d']) + } + + $_purge = merge($::apt::purge_defaults, $purge) + + validate_hash($proxy) + if $proxy['ensure'] { + validate_re($proxy['ensure'], ['file', 'present', 'absent']) + } + if $proxy['host'] { + validate_string($proxy['host']) + } + if $proxy['port'] { + unless is_integer($proxy['port']) { + fail('$proxy port must be an integer') + } + } + if $proxy['https'] { + validate_bool($proxy['https']) } - if $always_apt_update == true { + $_proxy = merge($apt::proxy_defaults, $proxy) + + validate_hash($sources) + validate_hash($keys) + validate_hash($settings) + validate_hash($ppas) + validate_hash($pins) + + if $_proxy['ensure'] == 'absent' or $_proxy['host'] { + apt::setting { 'conf-proxy': + ensure => $_proxy['ensure'], + priority => '01', + content => template('apt/_conf_header.erb', 'apt/proxy.erb'), + } + } + + $sources_list_content = $_purge['sources.list'] ? { + true => "# Repos managed by puppet.\n", + default => undef, + } + + $preferences_ensure = $_purge['preferences'] ? { + true => absent, + default => file, + } + + if $_update['frequency'] == 'always' { Exec <| title=='apt_update' |> { refreshonly => false, } } - file { '/etc/apt/apt.conf.d/15update-stamp': - ensure => 'file', - content => template('apt/_header.erb', 'apt/15update-stamp.erb'), - group => 'root', - mode => '0644', - owner => 'root', + apt::setting { 'conf-update-stamp': + priority => 15, + content => template('apt/_conf_header.erb', 'apt/15update-stamp.erb'), } - $root = $apt::params::root - $apt_conf_d = $apt::params::apt_conf_d - $sources_list_d = $apt::params::sources_list_d - $preferences_d = $apt::params::preferences_d - $provider = $apt::params::provider - file { 'sources.list': - ensure => present, - path => "${root}/sources.list", + ensure => file, + path => $::apt::sources_list, owner => root, group => root, mode => '0644', content => $sources_list_content, - notify => Exec['apt_update'], + notify => Class['apt::update'], } file { 'sources.list.d': ensure => directory, - path => $sources_list_d, + path => $::apt::sources_list_d, owner => root, group => root, - purge => $purge_sources_list_d, - recurse => $purge_sources_list_d, - notify => Exec['apt_update'], + mode => '0644', + purge => $_purge['sources.list.d'], + recurse => $_purge['sources.list.d'], + notify => Class['apt::update'], } - if $purge_preferences { - file { 'apt-preferences': - ensure => absent, - path => "${root}/preferences", - } + file { 'preferences': + ensure => $preferences_ensure, + path => $::apt::preferences, + owner => root, + group => root, + mode => '0644', + notify => Class['apt::update'], } file { 'preferences.d': ensure => directory, - path => $preferences_d, + path => $::apt::preferences_d, owner => root, group => root, - purge => $purge_preferences_d, - recurse => $purge_preferences_d, - } - - case $fancy_progress { - true: { - file { '99progressbar': - ensure => present, - content => template('apt/_header.erb', 'apt/progressbar.erb'), - path => "${apt_conf_d}/99progressbar", - } - } - false: { - file { '99progressbar': - ensure => absent, - path => "${apt_conf_d}/99progressbar", - } - } - undef: {} # do nothing - default: { fail('Valid values for fancy_progress are true or false') } + mode => '0644', + purge => $_purge['preferences.d'], + recurse => $_purge['preferences.d'], + notify => Class['apt::update'], } - case $disable_keys { - true: { - file { '99unauth': - ensure => present, - content => template('apt/_header.erb', 'apt/unauth.erb'), - path => "${apt_conf_d}/99unauth", - } - } - false: { - file { '99unauth': - ensure => absent, - path => "${apt_conf_d}/99unauth", - } - } - undef: { } # do nothing - default: { fail('Valid values for disable_keys are true or false') } + # manage sources if present + if $sources { + create_resources('apt::source', $sources) } - - case $proxy_host { - false, '', undef: { - file { '01proxy': - ensure => absent, - path => "${apt_conf_d}/01proxy", - notify => Exec['apt_update'], - } - } - default: { - file { '01proxy': - ensure => present, - path => "${apt_conf_d}/01proxy", - content => template('apt/_header.erb', 'apt/proxy.erb'), - notify => Exec['apt_update'], - mode => '0644', - owner => root, - group => root, - } - } + # manage keys if present + if $keys { + create_resources('apt::key', $keys) } - - file { 'old-proxy-file': - ensure => absent, - path => "${apt_conf_d}/proxy", - notify => Exec['apt_update'], + # manage ppas if present + if $ppas { + create_resources('apt::ppa', $ppas) } - - # Need anchor to provide containment for dependencies. - anchor { 'apt::update': - require => Class['apt::update'], + # manage settings if present + if $settings { + create_resources('apt::setting', $settings) } - # manage sources if present - if $sources != undef { - validate_hash($sources) - create_resources('apt::source', $sources) + # manage pins if present + if $pins { + create_resources('apt::pin', $pins) } } diff --git a/puphpet/puppet/modules/apt/manifests/key.pp b/puphpet/puppet/modules/apt/manifests/key.pp index ce5fc25..8fbb47a 100644 --- a/puphpet/puppet/modules/apt/manifests/key.pp +++ b/puphpet/puppet/modules/apt/manifests/key.pp @@ -1,117 +1,106 @@ # == Define: apt::key -# -# The apt::key defined type allows for keys to be added to apt's keyring -# which is used for package validation. This defined type uses the apt_key -# native type to manage keys. This is a simple wrapper around apt_key with -# a few safeguards in place. -# -# === Parameters -# -# [*key*] -# _default_: +$title+, the title/name of the resource -# -# Is a GPG key ID or full key fingerprint. This value is validated with -# a regex enforcing it to only contain valid hexadecimal characters, be -# precisely 8 or 16 hexadecimal characters long and optionally prefixed -# with 0x for key IDs, or 40 hexadecimal characters long for key -# fingerprints. -# -# [*ensure*] -# _default_: +present+ -# -# The state we want this key in, may be either one of: -# * +present+ -# * +absent+ -# -# [*key_content*] -# _default_: +undef+ -# -# This parameter can be used to pass in a GPG key as a -# string in case it cannot be fetched from a remote location -# and using a file resource is for other reasons inconvenient. -# -# [*key_source*] -# _default_: +undef+ -# -# This parameter can be used to pass in the location of a GPG -# key. This URI can take the form of a: -# * +URL+: ftp, http or https -# * +path+: absolute path to a file on the target system. -# -# [*key_server*] -# _default_: +undef+ -# -# The keyserver from where to fetch our GPG key. It can either be a domain -# name or url. It defaults to -# undef which results in apt_key's default keyserver being used, -# currently +keyserver.ubuntu.com+. -# -# [*key_options*] -# _default_: +undef+ -# -# Additional options to pass on to `apt-key adv --keyserver-options`. define apt::key ( - $key = $title, + $id = $title, $ensure = present, + $content = undef, + $source = undef, + $server = $::apt::keyserver, + $options = undef, + $key = undef, $key_content = undef, $key_source = undef, $key_server = undef, $key_options = undef, ) { - validate_re($key, ['\A(0x)?[0-9a-fA-F]{8}\Z', '\A(0x)?[0-9a-fA-F]{16}\Z', '\A(0x)?[0-9a-fA-F]{40}\Z']) + if $key != undef { + warning('$key is deprecated and will be removed in the next major release. Please use $id instead.') + $_id = $key + } else { + $_id = $id + } + + if $key_content != undef { + warning('$key_content is deprecated and will be removed in the next major release. Please use $content instead.') + $_content = $key_content + } else { + $_content = $content + } + + if $key_source != undef { + warning('$key_source is deprecated and will be removed in the next major release. Please use $source instead.') + $_source = $key_source + } else { + $_source = $source + } + + if $key_server != undef { + warning('$key_server is deprecated and will be removed in the next major release. Please use $server instead.') + $_server = $key_server + } else { + $_server = $server + } + + if $key_options != undef { + warning('$key_options is deprecated and will be removed in the next major release. Please use $options instead.') + $_options = $key_options + } else { + $_options = $options + } + + validate_re($_id, ['\A(0x)?[0-9a-fA-F]{8}\Z', '\A(0x)?[0-9a-fA-F]{16}\Z', '\A(0x)?[0-9a-fA-F]{40}\Z']) validate_re($ensure, ['\Aabsent|present\Z',]) - if $key_content { - validate_string($key_content) + if $_content { + validate_string($_content) } - if $key_source { - validate_re($key_source, ['\Ahttps?:\/\/', '\Aftp:\/\/', '\A\/\w+']) + if $_source { + validate_re($_source, ['\Ahttps?:\/\/', '\Aftp:\/\/', '\A\/\w+']) } - if $key_server { - validate_re($key_server,['\A((hkp|http|https):\/\/)?([a-z\d])([a-z\d-]{0,61}\.)+[a-z\d]+(:\d{2,5})?$']) + if $_server { + validate_re($_server,['\A((hkp|http|https):\/\/)?([a-z\d])([a-z\d-]{0,61}\.)+[a-z\d]+(:\d{2,5})?$']) } - if $key_options { - validate_string($key_options) + if $_options { + validate_string($_options) } case $ensure { present: { - if defined(Anchor["apt_key ${key} absent"]){ - fail("key with id ${key} already ensured as absent") + if defined(Anchor["apt_key ${_id} absent"]){ + fail("key with id ${_id} already ensured as absent") } - if !defined(Anchor["apt_key ${key} present"]) { + if !defined(Anchor["apt_key ${_id} present"]) { apt_key { $title: - ensure => $ensure, - id => $key, - source => $key_source, - content => $key_content, - server => $key_server, - keyserver_options => $key_options, + ensure => $ensure, + id => $_id, + source => $_source, + content => $_content, + server => $_server, + options => $_options, } -> - anchor { "apt_key ${key} present": } + anchor { "apt_key ${_id} present": } } } absent: { - if defined(Anchor["apt_key ${key} present"]){ - fail("key with id ${key} already ensured as present") + if defined(Anchor["apt_key ${_id} present"]){ + fail("key with id ${_id} already ensured as present") } - if !defined(Anchor["apt_key ${key} absent"]){ + if !defined(Anchor["apt_key ${_id} absent"]){ apt_key { $title: - ensure => $ensure, - id => $key, - source => $key_source, - content => $key_content, - server => $key_server, - keyserver_options => $key_options, + ensure => $ensure, + id => $_id, + source => $_source, + content => $_content, + server => $_server, + options => $_options, } -> - anchor { "apt_key ${key} absent": } + anchor { "apt_key ${_id} absent": } } } diff --git a/puphpet/puppet/modules/apt/manifests/params.pp b/puphpet/puppet/modules/apt/manifests/params.pp index 4efe872..861a6af 100644 --- a/puphpet/puppet/modules/apt/manifests/params.pp +++ b/puphpet/puppet/modules/apt/manifests/params.pp @@ -1,95 +1,162 @@ class apt::params { + + if $::osfamily != 'Debian' { + fail('This module only works on Debian or derivatives like Ubuntu') + } + + # prior to puppet 3.5.0, defined couldn't test if a variable was defined + # strict variables wasn't added until 3.5.0, so this should be fine. + if ! $::settings::strict_variables { + $xfacts = { + 'lsbdistcodename' => $::lsbdistcodename, + 'lsbdistrelease' => $::lsbdistrelease, + 'lsbmajdistrelease' => $::lsbmajdistrelease, + 'lsbdistdescription' => $::lsbdistdescription, + 'lsbminordistrelease' => $::lsbminordistrelease, + 'lsbdistid' => $::lsbdistid, + } + } else { + # Strict variables facts lookup compatibility + $xfacts = { + 'lsbdistcodename' => defined('$lsbdistcodename') ? { + true => $::lsbdistcodename, + default => undef, + }, + 'lsbdistrelease' => defined('$lsbdistrelease') ? { + true => $::lsbdistrelease, + default => undef, + }, + 'lsbmajdistrelease' => defined('$lsbmajdistrelease') ? { + true => $::lsbmajdistrelease, + default => undef, + }, + 'lsbdistdescription' => defined('$lsbdistdescription') ? { + true => $::lsbdistdescription, + default => undef, + }, + 'lsbminordistrelease' => defined('$lsbminordistrelease') ? { + true => $::lsbminordistrelease, + default => undef, + }, + 'lsbdistid' => defined('$lsbdistid') ? { + true => $::lsbdistid, + default => undef, + }, + } + } + $root = '/etc/apt' $provider = '/usr/bin/apt-get' + $sources_list = "${root}/sources.list" $sources_list_d = "${root}/sources.list.d" - $apt_conf_d = "${root}/apt.conf.d" + $conf_d = "${root}/apt.conf.d" + $preferences = "${root}/preferences" $preferences_d = "${root}/preferences.d" + $keyserver = 'keyserver.ubuntu.com' - case $::lsbdistid { - 'ubuntu', 'debian': { - $distid = $::lsbdistid - $distcodename = $::lsbdistcodename - } - 'linuxmint': { - if $::lsbdistcodename == 'debian' { - $distid = 'debian' - $distcodename = 'wheezy' - } else { - $distid = 'ubuntu' - $distcodename = $::lsbdistcodename ? { - 'qiana' => 'trusty', - 'petra' => 'saucy', - 'olivia' => 'raring', - 'nadia' => 'quantal', - 'maya' => 'precise', - } - } - } - 'Cumulus Networks': { - $distid = 'debian' - $distcodename = $::lsbdistcodename - } - '': { - fail('Unable to determine lsbdistid, is lsb-release installed?') - } - default: { - fail("Unsupported lsbdistid (${::lsbdistid})") + $config_files = { + 'conf' => { + 'path' => $conf_d, + 'ext' => '', + }, + 'pref' => { + 'path' => $preferences_d, + 'ext' => '.pref', + }, + 'list' => { + 'path' => $sources_list_d, + 'ext' => '.list', } } - case $distid { + + $update_defaults = { + 'frequency' => 'reluctantly', + 'timeout' => undef, + 'tries' => undef, + } + + $proxy_defaults = { + 'ensure' => undef, + 'host' => undef, + 'port' => 8080, + 'https' => false, + } + + $purge_defaults = { + 'sources.list' => false, + 'sources.list.d' => false, + 'preferences' => false, + 'preferences.d' => false, + } + + $source_key_defaults = { + 'server' => $keyserver, + 'options' => undef, + 'content' => undef, + 'source' => undef, + } + + $include_defaults = { + 'deb' => true, + 'src' => false, + } + + case $xfacts['lsbdistid'] { 'debian': { - case $distcodename { + case $xfacts['lsbdistcodename'] { 'squeeze': { - $backports_location = 'http://backports.debian.org/debian-backports' - $legacy_origin = true - $origins = ['${distro_id} oldstable', #lint:ignore:single_quote_string_with_variables - '${distro_id} ${distro_codename}-security', #lint:ignore:single_quote_string_with_variables - '${distro_id} ${distro_codename}-lts'] #lint:ignore:single_quote_string_with_variables - } - 'wheezy': { - $backports_location = 'http://ftp.debian.org/debian/' - $legacy_origin = false - $origins = ['origin=Debian,archive=stable,label=Debian-Security', - 'origin=Debian,archive=oldstable,label=Debian-Security'] + $backports = { + 'location' => 'http://httpredir.debian.org/debian-backports', + 'key' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + 'repos' => 'main contrib non-free', + } } default: { - $backports_location = 'http://http.debian.net/debian/' - $legacy_origin = false - $origins = ['origin=Debian,archive=stable,label=Debian-Security'] + $backports = { + 'location' => 'http://httpredir.debian.org/debian', + 'key' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + 'repos' => 'main contrib non-free', + } } } + + $ppa_options = undef + $ppa_package = undef + } 'ubuntu': { - case $distcodename { + $backports = { + 'location' => 'http://archive.ubuntu.com/ubuntu', + 'key' => '630239CC130E1A7FD81A27B140976EAF437D05B5', + 'repos' => 'main universe multiverse restricted', + } + + case $xfacts['lsbdistcodename'] { 'lucid': { - $backports_location = 'http://us.archive.ubuntu.com/ubuntu' $ppa_options = undef $ppa_package = 'python-software-properties' - $legacy_origin = true - $origins = ['${distro_id} ${distro_codename}-security'] #lint:ignore:single_quote_string_with_variables } 'precise': { - $backports_location = 'http://us.archive.ubuntu.com/ubuntu' $ppa_options = '-y' $ppa_package = 'python-software-properties' - $legacy_origin = true - $origins = ['${distro_id}:${distro_codename}-security'] #lint:ignore:single_quote_string_with_variables } 'trusty', 'utopic', 'vivid': { - $backports_location = 'http://us.archive.ubuntu.com/ubuntu' $ppa_options = '-y' $ppa_package = 'software-properties-common' - $legacy_origin = true - $origins = ['${distro_id}:${distro_codename}-security'] #lint:ignore:single_quote_string_with_variables } default: { - $backports_location = 'http://old-releases.ubuntu.com/ubuntu' $ppa_options = '-y' $ppa_package = 'python-software-properties' - $legacy_origin = true - $origins = ['${distro_id}:${distro_codename}-security'] #lint:ignore:single_quote_string_with_variables } } } + undef: { + fail('Unable to determine lsbdistid, please install lsb-release first') + } + default: { + $ppa_options = undef + $ppa_package = undef + $backports = undef + } } } diff --git a/puphpet/puppet/modules/apt/manifests/pin.pp b/puphpet/puppet/modules/apt/manifests/pin.pp index 935dc22..cc89689 100644 --- a/puphpet/puppet/modules/apt/manifests/pin.pp +++ b/puphpet/puppet/modules/apt/manifests/pin.pp @@ -3,8 +3,8 @@ define apt::pin( $ensure = present, - $explanation = "${caller_module_name}: ${name}", - $order = '', + $explanation = undef, + $order = undef, $packages = '*', $priority = 0, $release = '', # a= @@ -16,14 +16,20 @@ $originator = '', # o= $label = '' # l= ) { - include apt::params - - $preferences_d = $apt::params::preferences_d - - if $order != '' and !is_integer($order) { + if $order and !is_integer($order) { fail('Only integers are allowed in the apt::pin order param') } + if $explanation { + $_explanation = $explanation + } else { + if defined('$caller_module_name') { # strict vars check + $_explanation = "${caller_module_name}: ${name}" + } else { + $_explanation = ": ${name}" + } + } + $pin_release_array = [ $release, $codename, @@ -56,7 +62,6 @@ } } - # According to man 5 apt_preferences: # The files have either no or "pref" as filename extension # and only contain alphanumeric, hyphen (-), underscore (_) and period @@ -66,16 +71,10 @@ # be silently ignored. $file_name = regsubst($title, '[^0-9a-z\-_\.]', '_', 'IG') - $path = $order ? { - '' => "${preferences_d}/${file_name}.pref", - default => "${preferences_d}/${order}-${file_name}.pref", - } - file { "${file_name}.pref": - ensure => $ensure, - path => $path, - owner => root, - group => root, - mode => '0644', - content => template('apt/_header.erb', 'apt/pin.pref.erb'), + apt::setting { "pref-${file_name}": + ensure => $ensure, + priority => $order, + content => template('apt/_header.erb', 'apt/pin.pref.erb'), + notify_update => false, } } diff --git a/puphpet/puppet/modules/apt/manifests/ppa.pp b/puphpet/puppet/modules/apt/manifests/ppa.pp index e86a19f..6352352 100644 --- a/puphpet/puppet/modules/apt/manifests/ppa.pp +++ b/puphpet/puppet/modules/apt/manifests/ppa.pp @@ -1,23 +1,17 @@ # ppa.pp - define apt::ppa( $ensure = 'present', - $release = $::lsbdistcodename, - $options = $::apt::params::ppa_options, - $package_name = $::apt::params::ppa_package, - $package_manage = true, + $options = $::apt::ppa_options, + $release = $::apt::xfacts['lsbdistcodename'], + $package_name = $::apt::ppa_package, + $package_manage = false, ) { - include apt::params - include apt::update - - $sources_list_d = $apt::params::sources_list_d - - if ! $release { + unless $release { fail('lsbdistcodename fact not available: release parameter required') } - if $::operatingsystem != 'Ubuntu' { - fail('apt::ppa is currently supported on Ubuntu only.') + if $::apt::xfacts['lsbdistid'] == 'Debian' { + fail('apt::ppa is not currently supported on Debian.') } $filename_without_slashes = regsubst($name, '/', '-', 'G') @@ -27,52 +21,43 @@ if $ensure == 'present' { if $package_manage { - if ! defined(Package[$package_name]) { - package { $package_name: } - } + package { $package_name: } $_require = [File['sources.list.d'], Package[$package_name]] } else { $_require = File['sources.list.d'] } - if defined(Class['apt']) { - case $::apt::proxy_host { - false, '', undef: { - $proxy_env = [] - } - default: { - $proxy_env = ["http_proxy=http://${::apt::proxy_host}:${::apt::proxy_port}", "https_proxy=http://${::apt::proxy_host}:${::apt::proxy_port}"] - } + $_proxy = $::apt::_proxy + if $_proxy['host'] { + if $_proxy['https'] { + $_proxy_env = ["http_proxy=http://${$_proxy['host']}:${$_proxy['port']}", "https_proxy=https://${$_proxy['host']}:${$_proxy['port']}"] + } else { + $_proxy_env = ["http_proxy=http://${$_proxy['host']}:${$_proxy['port']}"] } } else { - $proxy_env = [] + $_proxy_env = [] } exec { "add-apt-repository-${name}": - environment => $proxy_env, + environment => $_proxy_env, command => "/usr/bin/add-apt-repository ${options} ${name}", - unless => "/usr/bin/test -s ${sources_list_d}/${sources_list_d_filename}", + unless => "/usr/bin/test -s ${::apt::sources_list_d}/${sources_list_d_filename}", user => 'root', logoutput => 'on_failure', - notify => Exec['apt_update'], + notify => Class['apt::update'], require => $_require, } - file { "${sources_list_d}/${sources_list_d_filename}": + file { "${::apt::sources_list_d}/${sources_list_d_filename}": ensure => file, require => Exec["add-apt-repository-${name}"], } } else { - file { "${sources_list_d}/${sources_list_d_filename}": + file { "${::apt::sources_list_d}/${sources_list_d_filename}": ensure => 'absent', - notify => Exec['apt_update'], + notify => Class['apt::update'], } } - - # Need anchor to provide containment for dependencies. - anchor { "apt::ppa::${name}": - require => Class['apt::update'], - } } diff --git a/puphpet/puppet/modules/apt/manifests/release.pp b/puphpet/puppet/modules/apt/manifests/release.pp deleted file mode 100644 index ae12dd4..0000000 --- a/puphpet/puppet/modules/apt/manifests/release.pp +++ /dev/null @@ -1,17 +0,0 @@ -# release.pp - -class apt::release ( - $release_id -) { - - include apt::params - - $root = $apt::params::root - - file { "${root}/apt.conf.d/01release": - owner => root, - group => root, - mode => '0644', - content => template('apt/_header.erb', 'apt/release.erb'), - } -} diff --git a/puphpet/puppet/modules/apt/manifests/setting.pp b/puphpet/puppet/modules/apt/manifests/setting.pp new file mode 100644 index 0000000..b0fb62b --- /dev/null +++ b/puphpet/puppet/modules/apt/manifests/setting.pp @@ -0,0 +1,64 @@ +define apt::setting ( + $priority = 50, + $ensure = file, + $source = undef, + $content = undef, + $notify_update = true, +) { + + include 'apt::params' + if $content and $source { + fail('apt::setting cannot have both content and source') + } + + if !$content and !$source { + fail('apt::setting needs either of content or source') + } + + validate_re($ensure, ['file', 'present', 'absent']) + validate_bool($notify_update) + + $title_array = split($title, '-') + $setting_type = $title_array[0] + $base_name = join(delete_at($title_array, 0), '-') + + validate_re($setting_type, ['\Aconf\z', '\Apref\z', '\Alist\z'], "apt::setting resource name/title must start with either 'conf-', 'pref-' or 'list-'") + + unless is_integer($priority) { + # need this to allow zero-padded priority. + validate_re($priority, '^\d+$', 'apt::setting priority must be an integer or a zero-padded integer') + } + + if $source { + validate_string($source) + } + + if $content { + validate_string($content) + } + + if ($setting_type == 'list') or ($setting_type == 'pref') { + $_priority = '' + } else { + $_priority = $priority + } + + $_path = $::apt::params::config_files[$setting_type]['path'] + $_ext = $::apt::params::config_files[$setting_type]['ext'] + + if $notify_update { + $_notify = Class['apt::update'] + } else { + $_notify = undef + } + + file { "${_path}/${_priority}${base_name}${_ext}": + ensure => $ensure, + owner => 'root', + group => 'root', + mode => '0644', + content => $content, + source => $source, + notify => $_notify, + } +} diff --git a/puphpet/puppet/modules/apt/manifests/source.pp b/puphpet/puppet/modules/apt/manifests/source.pp index f6647df..1307a3a 100644 --- a/puphpet/puppet/modules/apt/manifests/source.pp +++ b/puphpet/puppet/modules/apt/manifests/source.pp @@ -1,93 +1,156 @@ # source.pp # add an apt source - define apt::source( + $location = undef, $comment = $name, $ensure = present, - $location = '', - $release = 'UNDEF', + $release = undef, $repos = 'main', - $include_src = true, - $include_deb = true, - $required_packages = false, + $include = {}, $key = undef, - $key_server = 'keyserver.ubuntu.com', + $pin = undef, + $architecture = undef, + $allow_unsigned = false, + $include_src = undef, + $include_deb = undef, + $required_packages = undef, + $key_server = undef, $key_content = undef, $key_source = undef, - $pin = false, - $architecture = undef, - $trusted_source = false, + $trusted_source = undef, ) { + validate_string($architecture, $comment, $location, $repos) + validate_bool($allow_unsigned) + validate_hash($include) + + # This is needed for compat with 1.8.x + include ::apt + + $_before = Apt::Setting["list-${title}"] + + if $include_src != undef { + warning("\$include_src is deprecated and will be removed in the next major release, please use \$include => { 'src' => ${include_src} } instead") + } + + if $include_deb != undef { + warning("\$include_deb is deprecated and will be removed in the next major release, please use \$include => { 'deb' => ${include_deb} } instead") + } + + if $required_packages != undef { + warning('$required_packages is deprecated and will be removed in the next major release, please use package resources instead.') + exec { "Required packages: '${required_packages}' for ${name}": + command => "${::apt::params::provider} -y install ${required_packages}", + logoutput => 'on_failure', + refreshonly => true, + tries => 3, + try_sleep => 1, + before => $_before, + } + } - include apt::params - include apt::update + if $key_server != undef { + warning("\$key_server is deprecated and will be removed in the next major release, please use \$key => { 'server' => ${key_server} } instead.") + } - validate_string($architecture) - validate_bool($trusted_source) + if $key_content != undef { + warning("\$key_content is deprecated and will be removed in the next major release, please use \$key => { 'content' => ${key_content} } instead.") + } - $sources_list_d = $apt::params::sources_list_d - $provider = $apt::params::provider + if $key_source != undef { + warning("\$key_source is deprecated and will be removed in the next major release, please use \$key => { 'source' => ${key_source} } instead.") + } + + if $trusted_source != undef { + warning('$trusted_source is deprecated and will be removed in the next major release, please use $allow_unsigned instead.') + $_allow_unsigned = $trusted_source + } else { + $_allow_unsigned = $allow_unsigned + } - if $release == 'UNDEF' { - if $::lsbdistcodename == undef { + if ! $release { + $_release = $::apt::params::xfacts['lsbdistcodename'] + unless $_release { fail('lsbdistcodename fact not available: release parameter required') - } else { - $release_real = $::lsbdistcodename } } else { - $release_real = $release + $_release = $release } - file { "${name}.list": - ensure => $ensure, - path => "${sources_list_d}/${name}.list", - owner => root, - group => root, - mode => '0644', - content => template('apt/_header.erb', 'apt/source.list.erb'), - notify => Exec['apt_update'], + if $ensure == 'present' and ! $location { + fail('cannot create a source entry without specifying a location') } + if $include_src != undef and $include_deb != undef { + $_deprecated_include = { + 'src' => $include_src, + 'deb' => $include_deb, + } + } elsif $include_src != undef { + $_deprecated_include = { 'src' => $include_src } + } elsif $include_deb != undef { + $_deprecated_include = { 'deb' => $include_deb } + } else { + $_deprecated_include = {} + } + + $_include = merge($::apt::params::include_defaults, $_deprecated_include, $include) - if ($pin != false) { - # Get the host portion out of the url so we can pin to origin - $url_split = split($location, '/') - $host = $url_split[2] + $_deprecated_key = { + 'key_server' => $key_server, + 'key_content' => $key_content, + 'key_source' => $key_source, + } - apt::pin { $name: - ensure => $ensure, - priority => $pin, - before => File["${name}.list"], - origin => $host, + if $key { + if is_hash($key) { + unless $key['id'] { + fail('key hash must contain at least an id entry') + } + $_key = merge($::apt::params::source_key_defaults, $_deprecated_key, $key) + } else { + validate_string($key) + $_key = merge( { 'id' => $key }, $_deprecated_key) } } - if ($required_packages != false) and ($ensure == 'present') { - exec { "Required packages: '${required_packages}' for ${name}": - command => "${provider} -y install ${required_packages}", - logoutput => 'on_failure', - refreshonly => true, - tries => 3, - try_sleep => 1, - subscribe => File["${name}.list"], - before => Exec['apt_update'], + apt::setting { "list-${name}": + ensure => $ensure, + content => template('apt/_header.erb', 'apt/source.list.erb'), + } + + if $pin { + if is_hash($pin) { + $_pin = merge($pin, { 'ensure' => $ensure, 'before' => $_before }) + } elsif (is_numeric($pin) or is_string($pin)) { + $url_split = split($location, '/') + $host = $url_split[2] + $_pin = { + 'ensure' => $ensure, + 'priority' => $pin, + 'before' => $_before, + 'origin' => $host, + } + } else { + fail('Received invalid value for pin parameter') } + create_resources('apt::pin', { "${name}" => $_pin }) } # We do not want to remove keys when the source is absent. if $key and ($ensure == 'present') { - apt::key { "Add key: ${key} from Apt::Source ${title}": - ensure => present, - key => $key, - key_server => $key_server, - key_content => $key_content, - key_source => $key_source, - before => File["${name}.list"], + if is_hash($_key) { + apt::key { "Add key: ${$_key['id']} from Apt::Source ${title}": + ensure => present, + id => $_key['id'], + server => $_key['server'], + content => $_key['content'], + source => $_key['source'], + options => $_key['options'], + key_server => $_key['key_server'], + key_content => $_key['key_content'], + key_source => $_key['key_source'], + before => $_before, + } } } - - # Need anchor to provide containment for dependencies. - anchor { "apt::source::${name}": - require => Class['apt::update'], - } } diff --git a/puphpet/puppet/modules/apt/manifests/unattended_upgrades.pp b/puphpet/puppet/modules/apt/manifests/unattended_upgrades.pp deleted file mode 100644 index 028ffc6..0000000 --- a/puphpet/puppet/modules/apt/manifests/unattended_upgrades.pp +++ /dev/null @@ -1,81 +0,0 @@ -# Class: apt::unattended_upgrades -# -# This class manages the unattended-upgrades package and related configuration -# files for ubuntu -# -# origins are the repositories to automatically upgrade included packages -# blacklist is a list of packages to not automatically upgrade -# update is how often to run "apt-get update" in days -# download is how often to run "apt-get upgrade --download-only" in days -# upgrade is how often to upgrade packages included in the origins list in days -# autoclean is how often to run "apt-get autoclean" in days -# -# information on the other options can be found in the 50unattended-upgrades -# file and in /etc/cron.daily/apt -# -class apt::unattended_upgrades ( - $legacy_origin = $::apt::params::legacy_origin, - $origins = $::apt::params::origins, - $blacklist = [], - $update = '1', - $download = '1', - $upgrade = '1', - $autoclean = '7', - $auto_fix = true, - $minimal_steps = false, - $install_on_shutdown = false, - $mail_to = 'NONE', - $mail_only_on_error = false, - $remove_unused = true, - $auto_reboot = false, - $dl_limit = 'NONE', - $randomsleep = undef, - $enable = '1', - $backup_interval = '0', - $backup_level = '3', - $max_age = '0', - $min_age = '0', - $max_size = '0', - $download_delta = '0', - $verbose = '0', -) inherits ::apt::params { - - validate_bool( - $legacy_origin, - $auto_fix, - $minimal_steps, - $install_on_shutdown, - $mail_only_on_error, - $remove_unused, - $auto_reboot - ) - validate_array($origins) - - if $randomsleep { - unless is_numeric($randomsleep) { - fail('randomsleep must be numeric') - } - } - - package { 'unattended-upgrades': - ensure => present, - } - - file { '/etc/apt/apt.conf.d/50unattended-upgrades': - ensure => file, - owner => 'root', - group => 'root', - mode => '0644', - content => template('apt/_header.erb', 'apt/50unattended-upgrades.erb'), - require => Package['unattended-upgrades'], - } - - file { '/etc/apt/apt.conf.d/10periodic': - ensure => file, - owner => 'root', - group => 'root', - mode => '0644', - content => template('apt/_header.erb', 'apt/10periodic.erb'), - require => Package['unattended-upgrades'], - } -} diff --git a/puphpet/puppet/modules/apt/manifests/update.pp b/puphpet/puppet/modules/apt/manifests/update.pp index d9b338d..9b1f686 100644 --- a/puphpet/puppet/modules/apt/manifests/update.pp +++ b/puphpet/puppet/modules/apt/manifests/update.pp @@ -1,55 +1,48 @@ class apt::update { - include apt::params #TODO: to catch if $::apt_update_last_success has the value of -1 here. If we #opt to do this, a info/warn would likely be all you'd need likely to happen #on the first run, but if it's not run in awhile something is likely borked #with apt and we'd want to know about it. - if $::apt::always_apt_update == false { - #if always_apt_update is true there's no point in parsing this logic. - - case $apt::apt_update_frequency { - 'always': { - $_kick_apt = true - } - 'daily': { - #compare current date with the apt_update_last_success fact to determine - #if we should kick apt_update. - $daily_threshold = (strftime('%s') - 86400) - if $::apt_update_last_success { - if $::apt_update_last_success < $daily_threshold { - $_kick_apt = true - } else { - $_kick_apt = false - } - } else { - #if apt-get update has not successfully run, we should kick apt_update + case $::apt::_update['frequency'] { + 'always': { + $_kick_apt = true + } + 'daily': { + #compare current date with the apt_update_last_success fact to determine + #if we should kick apt_update. + $daily_threshold = (strftime('%s') - 86400) + if $::apt_update_last_success { + if $::apt_update_last_success < $daily_threshold { $_kick_apt = true + } else { + $_kick_apt = false } + } else { + #if apt-get update has not successfully run, we should kick apt_update + $_kick_apt = true } - 'weekly':{ - #compare current date with the apt_update_last_success fact to determine - #if we should kick apt_update. - $weekly_threshold = (strftime('%s') - 604800) - if $::apt_update_last_success { - if ( $::apt_update_last_success < $weekly_threshold ) { - $_kick_apt = true - } else { - $_kick_apt = false - } - } else { - #if apt-get update has not successfully run, we should kick apt_update + } + 'weekly':{ + #compare current date with the apt_update_last_success fact to determine + #if we should kick apt_update. + $weekly_threshold = (strftime('%s') - 604800) + if $::apt_update_last_success { + if ( $::apt_update_last_success < $weekly_threshold ) { $_kick_apt = true + } else { + $_kick_apt = false } - } - default: { - #catches 'recluctantly', and any other value (which should not occur). - #do nothing. - $_kick_apt = false + } else { + #if apt-get update has not successfully run, we should kick apt_update + $_kick_apt = true } } - } else { - $_kick_apt = false + default: { + #catches 'reluctantly', and any other value (which should not occur). + #do nothing. + $_kick_apt = false + } } if $_kick_apt { @@ -58,11 +51,11 @@ $_refresh = true } exec { 'apt_update': - command => "${apt::params::provider} update", + command => "${::apt::provider} update", logoutput => 'on_failure', refreshonly => $_refresh, - timeout => $apt::update_timeout, - tries => $apt::update_tries, + timeout => $::apt::_update['timeout'], + tries => $::apt::_update['tries'], try_sleep => 1 } } diff --git a/puphpet/puppet/modules/apt/metadata.json b/puphpet/puppet/modules/apt/metadata.json index 5b14ae4..77ba0fc 100644 --- a/puphpet/puppet/modules/apt/metadata.json +++ b/puphpet/puppet/modules/apt/metadata.json @@ -1,12 +1,15 @@ { "name": "puppetlabs-apt", - "version": "1.8.0", + "version": "2.2.1", "author": "Puppet Labs", "summary": "Provides an interface for managing Apt source, key, and definitions with Puppet", "license": "Apache-2.0", "source": "https://github.com/puppetlabs/puppetlabs-apt", "project_page": "https://github.com/puppetlabs/puppetlabs-apt", "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", + "dependencies": [ + {"name":"puppetlabs/stdlib","version_requirement":">= 4.5.0 < 5.0.0"} + ], "operatingsystem_support": [ { "operatingsystem": "Debian", @@ -27,14 +30,11 @@ "requirements": [ { "name": "pe", - "version_requirement": "3.x" + "version_requirement": ">= 3.3.0 < 2015.4.0" }, { "name": "puppet", - "version_requirement": "3.x" + "version_requirement": ">= 3.0.0 < 5.0.0" } - ], - "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":">= 2.2.1"} ] } diff --git a/puphpet/puppet/modules/apt/spec/acceptance/apt_key_provider_spec.rb b/puphpet/puppet/modules/apt/spec/acceptance/apt_key_provider_spec.rb index 1f703c9..f1f232e 100644 --- a/puphpet/puppet/modules/apt/spec/acceptance/apt_key_provider_spec.rb +++ b/puphpet/puppet/modules/apt/spec/acceptance/apt_key_provider_spec.rb @@ -202,6 +202,187 @@ end end + context 'multiple keys' do + it 'runs without errors' do + pp = <<-EOS + apt_key { 'puppetlabs': + id => '#{PUPPETLABS_GPG_KEY_FINGERPRINT}', + ensure => 'present', + content => "-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.12 (GNU/Linux) +Comment: GPGTools - http://gpgtools.org + +mQINBEw3u0ABEAC1+aJQpU59fwZ4mxFjqNCgfZgDhONDSYQFMRnYC1dzBpJHzI6b +fUBQeaZ8rh6N4kZ+wq1eL86YDXkCt4sCvNTP0eF2XaOLbmxtV9bdpTIBep9bQiKg +5iZaz+brUZlFk/MyJ0Yz//VQ68N1uvXccmD6uxQsVO+gx7rnarg/BGuCNaVtGwy+ +S98g8Begwxs9JmGa8pMCcSxtC7fAfAEZ02cYyrw5KfBvFI3cHDdBqrEJQKwKeLKY +GHK3+H1TM4ZMxPsLuR/XKCbvTyl+OCPxU2OxPjufAxLlr8BWUzgJv6ztPe9imqpH +Ppp3KuLFNorjPqWY5jSgKl94W/CO2x591e++a1PhwUn7iVUwVVe+mOEWnK5+Fd0v +VMQebYCXS+3dNf6gxSvhz8etpw20T9Ytg4EdhLvCJRV/pYlqhcq+E9le1jFOHOc0 +Nc5FQweUtHGaNVyn8S1hvnvWJBMxpXq+Bezfk3X8PhPT/l9O2lLFOOO08jo0OYiI +wrjhMQQOOSZOb3vBRvBZNnnxPrcdjUUm/9cVB8VcgI5KFhG7hmMCwH70tpUWcZCN +NlI1wj/PJ7Tlxjy44f1o4CQ5FxuozkiITJvh9CTg+k3wEmiaGz65w9jRl9ny2gEl +f4CR5+ba+w2dpuDeMwiHJIs5JsGyJjmA5/0xytB7QvgMs2q25vWhygsmUQARAQAB +tEdQdXBwZXQgTGFicyBSZWxlYXNlIEtleSAoUHVwcGV0IExhYnMgUmVsZWFzZSBL +ZXkpIDxpbmZvQHB1cHBldGxhYnMuY29tPokCPgQTAQIAKAUCTDe7QAIbAwUJA8Jn +AAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQEFS3okvW7DAZaw//aLmE/eob +pXpIUVyCUWQxEvPtM/h/SAJsG3KoHN9u216ews+UHsL/7F91ceVXQQdD2e8CtYWF +eLNM0RSM9i/KM60g4CvIQlmNqdqhi1HsgGqInZ72/XLAXun0gabfC36rLww2kel+ +aMpRf58SrSuskY321NnMEJl4OsHV2hfNtAIgw2e/zm9RhoMpGKxoHZCvFhnP7u2M +2wMq7iNDDWb6dVsLpzdlVf242zCbubPCxxQXOpA56rzkUPuJ85mdVw4i19oPIFIZ +VL5owit1SxCOxBg4b8oaMS36hEl3qtZG834rtLfcqAmqjhx6aJuJLOAYN84QjDEU +3NI5IfNRMvluIeTcD4Dt5FCYahN045tW1Rc6s5GAR8RW45GYwQDzG+kkkeeGxwEh +qCW7nOHuwZIoVJufNhd28UFn83KGJHCQt4NBBr3K5TcY6bDQEIrpSplWSDBbd3p1 +IaoZY1WSDdP9OTVOSbsz0JiglWmUWGWCdd/CMSW/D7/3VUOJOYRDwptvtSYcjJc8 +1UV+1zB+rt5La/OWe4UOORD+jU1ATijQEaFYxBbqBBkFboAEXq9btRQyegqk+eVp +HhzacP5NYFTMThvHuTapNytcCso5au/cMywqCgY1DfcMJyjocu4bCtrAd6w4kGKN +MUdwNDYQulHZDI+UjJInhramyngdzZLjdeGJARwEEAECAAYFAkw3wEYACgkQIVr+ +UOQUcDKvEwgAoBuOPnPioBwYp8oHVPTo/69cJn1225kfraUYGebCcrRwuoKd8Iyh +R165nXYJmD8yrAFBk8ScUVKsQ/pSnqNrBCrlzQD6NQvuIWVFegIdjdasrWX6Szj+ +N1OllbzIJbkE5eo0WjCMEKJVI/GTY2AnTWUAm36PLQC5HnSATykqwxeZDsJ/s8Rc +kd7+QN5sBVytG3qb45Q7jLJpLcJO6KYH4rz9ZgN7LzyyGbu9DypPrulADG9OrL7e +lUnsGDG4E1M8Pkgk9Xv9MRKao1KjYLD5zxOoVtdeoKEQdnM+lWMJin1XvoqJY7FT +DJk6o+cVqqHkdKL+sgsscFVQljgCEd0EgIkCHAQQAQgABgUCTPlA6QAKCRBcE9bb +kwUuAxdYD/40FxAeNCYByxkr/XRT0gFT+NCjPuqPWCM5tf2NIhSapXtb2+32WbAf +DzVfqWjC0G0RnQBve+vcjpY4/rJu4VKIDGIT8CtnKOIyEcXTNFOehi65xO4ypaei +BPSb3ip3P0of1iZZDQrNHMW5VcyL1c+PWT/6exXSGsePtO/89tc6mupqZtC05f5Z +XG4jswMF0U6Q5s3S0tG7Y+oQhKNFJS4sH4rHe1o5CxKwNRSzqccA0hptKy3MHUZ2 ++zeHzuRdRWGjb2rUiVxnIvPPBGxF2JHhB4ERhGgbTxRZ6wZbdW06BOE8r7pGrUpU +fCw/WRT3gGXJHpGPOzFAvr3Xl7VcDUKTVmIajnpd3SoyD1t2XsvJlSQBOWbViucH +dvE4SIKQ77vBLRlZIoXXVb6Wu7Vq+eQs1ybjwGOhnnKjz8llXcMnLzzN86STpjN4 +qGTXQy/E9+dyUP1sXn3RRwb+ZkdI77m1YY95QRNgG/hqh77IuWWg1MtTSgQnP+F2 +7mfo0/522hObhdAe73VO3ttEPiriWy7tw3bS9daP2TAVbYyFqkvptkBb1OXRUSzq +UuWjBmZ35UlXjKQsGeUHlOiEh84aondF90A7gx0X/ktNIPRrfCGkHJcDu+HVnR7x +Kk+F0qb9+/pGLiT3rqeQTr8fYsb4xLHT7uEg1gVFB1g0kd+RQHzV74kCPgQTAQIA +KAIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AFAk/x5PoFCQtIMjoACgkQEFS3 +okvW7DAIKQ/9HvZyf+LHVSkCk92Kb6gckniin3+5ooz67hSr8miGBfK4eocqQ0H7 +bdtWjAILzR/IBY0xj6OHKhYP2k8TLc7QhQjt0dRpNkX+Iton2AZryV7vUADreYz4 +4B0bPmhiE+LL46ET5IThLKu/KfihzkEEBa9/t178+dO9zCM2xsXaiDhMOxVE32gX +vSZKP3hmvnK/FdylUY3nWtPedr+lHpBLoHGaPH7cjI+MEEugU3oAJ0jpq3V8n4w0 +jIq2V77wfmbD9byIV7dXcxApzciK+ekwpQNQMSaceuxLlTZKcdSqo0/qmS2A863Y +ZQ0ZBe+Xyf5OI33+y+Mry+vl6Lre2VfPm3udgR10E4tWXJ9Q2CmG+zNPWt73U1FD +7xBI7PPvOlyzCX4QJhy2Fn/fvzaNjHp4/FSiCw0HvX01epcersyun3xxPkRIjwwR +M9m5MJ0o4hhPfa97zibXSh8XXBnosBQxeg6nEnb26eorVQbqGx0ruu/W2m5/JpUf +REsFmNOBUbi8xlKNS5CZypH3Zh88EZiTFolOMEh+hT6s0l6znBAGGZ4m/Unacm5y +DHmg7unCk4JyVopQ2KHMoqG886elu+rm0ASkhyqBAk9sWKptMl3NHiYTRE/m9VAk +ugVIB2pi+8u84f+an4Hml4xlyijgYu05pqNvnLRyJDLd61hviLC8GYWJAhwEEAEC +AAYFAlHk3M4ACgkQSjMLmtZI+uP5hA//UTZfD340ukip6jPlMzxwSD/QapwtO7D4 +gsGTsXezDkO97D21d1pNaNT0RrXAMagwk1ElDxmn/YHUDfMovZa2bKagjWmV38xk +Ws+Prh1P44vUDG30CAU6KZ+mTGLUbolfOvDffCTm9Mn1i2kxFaJxbVhWR6zR28KZ +R28s1IBsrqeTCksYfdKdkuw1/j850hW8MM3hPBJ/48VLx5QEFfnlXwt1fp+LygAv +rIyJw7vJtsa9QjCIkQk2tcv77rhkiZ6ADthgVIx5j3yDWSm4nLqFpwbQTKrNRrCb +5XbL/oIMeHJuFICb2HckDS1KuKXHmqvDuLoRr0/wFEZMps5XQevomUa7JkMeS5j9 +AubCG4g1zKEtPPaGDsfDKBljCHBKwUysQj5oGU5w8VvlOPnS62DBfsgU2y5ipmmI +TYkjSOL6LXwO6xG5/sxA8cyoJSmbN286imcY6AHloTiiu6/N7Us+CNrhw/V7HAun +56etWBn3bZWCRGGAPF3qJr4y2sUMY0E3Ha7OPEHIKfBb4MiJnpXntWT28nQfF3dl +TFTthAzwcnZchx2es4yrfDXn33Y4eisqxWCbTluErXUogUEKH1KohSatYMtxencv +7bUlzIr22zSUCYyVf9cyg50kBy+0J7seEpqG5K5R8z9s/63BT5Oghmi6bB2s5iK5 +fBt3Tu1IYpyZAg0EURGeeQEQALoU2rlo+usvGKqmBKaEl8Cbx0UZY4tQa1OQSDCj +6QeCBc36rq2NCAFpjYg0nrxMN86e0aHYVVetT75rSX701jRJD/TRCPzr03QVwEtk +GpGIpBXtdx0962I0We5rSZL2TWKuPtGRKrbs6CSVlNynLprIEnN+2sJYd/1yEsrR +9wBtUfVOkq6o4hBWOj4oEqhqQv1MPv1RPqGEgJl19s4LS9277cMIwrj553nGzsy1 +XwO6BQIP8IhJQZ+8Okw3UaJjLHkJExgo3UHMFdZhAOOYbrlxwq3lENmkdgjxCUBZ +iVNiEX9NLm8x1HWaW/nnBIHu6g7r+1Ff5qMSI2hBVan6om4gKHdI9wThG89V16Nq +3YztuK5L6Nh9a7BVQJos0r419NHGXPqXqN99jWRL+jAqwKozviUYijDx8k4xLnpQ +1dIbHfwE0MPuIkgHeQIoBMkxD1tiQC7ouqVRqU1gg9VKhOZf0opDnvqQ+cDMyfUC +hgrjjikSoCBIVCDvr1r7T/gUMDEXfnaMfAdEy1z9qnUzTRRzMbl4BN3Zn+4Htf+B +zpAln6H8h7sBb6CO1TX2Qh3JPTrV9zSSbbOW/kuySU+rkHBQPza5l+pnWD7eXaVj +7+WEx+TsYIP9Gpe/FOVp2ht93NgjNFAodPW+i5jm7MRk+vlzjidHJ69pEUoQQtuk +Td8LABEBAAG0V1B1cHBldCBMYWJzIE5pZ2h0bHkgQnVpbGQgS2V5IChQdXBwZXQg +TGFicyBOaWdodGx5IEJ1aWxkIEtleSkgPGRlbGl2ZXJ5QHB1cHBldGxhYnMuY29t +PokCPwQTAQIAKQUCURGzrQIbAwUJBaOagAcLCQgHAwIBBhUIAgkKCwQWAgMBAh4B +AheAAAoJELj5mcAHu2xX7UUQAKGDOQS20BRNEa3top+dQONWmC/j1ABDVTOkF7Zc +9JT5oEESzVof/yIWKAfCbYyH5l3yySZI3NOQt7CswIWDYe0JR/uBhyGoHkA1t52L +zP45UxI29K5XaeBm3qoQbV3W6GWScGkijfaJ2yz/dIHh0m3SkC8mUGBrIqqVwV38 +JcsW1/CzTetZiWGlk8/nPeUg+snGwd22zUlZkTaVh3FbHrqh2xsMFdrphDOtSU5s +Jzebu5h6mp7cMZELaRNNmg3O7VeQMA1hwaq05jQuPisS/ktOqSgJXh8pOaUpDoV0 +ta4JSwaqEkWsZHv3tmaXGy0Qzs9X9bOjRbIKgN2w9JY+z2OKJ5L4Yg5VMJPYMdKp +wGSQf70YaaT0d1N/84P8j7CRsDBnVME/TDuE2u1XM/9B7xmdcI28FxZrqQc06OGS +UvK9vSgTkTxXSsjobah8ssi4C4/zRgTZu94KOhSlH4YGrzLX7g25M708NxgXJiPZ +7K8Ceea28mHYf3f+JobEbpzPeewURAFCXHCm4cFU31FsiXQrNhGmUpRKVayiMMzN +JF8yjuHpwB2DjGdV3QR5C8Ms+RO86JnD/Yq9zeoF7T7jCAkQKuh76cQe60XllKhV +Dlh2rpKXAtLAbea9hcSraZkm3Lj+oKzXUSf3Ml9xp65yjUjm9O+a4AMQ1wFroGEP +QUEEiQEcBBABCgAGBQJT0XkMAAoJELrV8KOS6YVy7O8IAKJYT0Afd6Ufkx4cR0rj +soCoPpDDiyITmSdeLSzvl9rr1X39+PqR0dcncEhO1heCZo8sm/iMNsiV4UORv2Wh +lCriE2fDpu9ByX1rwuKl9nEu9xx2WTRWtdx4M4fB+ZXYiJbgb1vuM46mGp51NYRK +ByPIm1EAjOhsfXm14BZICOQO5WLy5Sv/oRVSEBiGXNXf1kweXSzrhRCNEWYfPhQJ +4pCsvNeiQuhqQIB+J9FbA48x47JikMM92w0aEa4aVVokNF2PBCp9/SdRAzlY7Ikx +aAdIzuyc0ANIZBPgYxIgdH/Fltwz6VW6iFNk3gS7jR6TFBjRQba73I53IBbiVIRq +dnWJAhwEEAECAAYFAlPRd2QACgkQRp6bNpsPDx1HiQ//TEOYPkp+iHT/wNcTUO4A +r00La6xl9bw3v5XlnW83YjrB0ieChbXcHpChNRk08vdRSgxyWCtbIwmMeOO8mDiv +aJbYrgngJY+FSMsAzhSyPauze0l4PV3dnLRMZmK5Nro4GNI4oiOGp0qXPcBjstlc +BnEa6XuLHDnRYFhkcVboZDu2o/tdz+OJD+CZjyeiIAtChMJ+ghlpfO3cOuK0wmTh +Jtn/eDAfjB34CZdkt1paKZap5bLZCF0QwP+DbJd189HZy/ot6w2jpNXFt1JFnoyn +7Nluo6MPNTZSG3pzh7fvzb924M1sm+CyLFzEV1rYi6ujyHOsW+KYc6fOUB5jk/BZ +QPaU6vG1JRDLHWPjbPf9Ax8uGQSrVXC3txiu2OLZcn4Ti54PoHed5m7Fxk9fnaiT +gNGL0ox/wmIPbIsdGrXuTHcdmPyuRM5btXFWCMbknTIbefEEOQdbPl+e5QgWR5cf +EVOvo6qTBstH7aHqiWMQpuvnU7l9xpfcJ40SawHxiY/UCKXhpf7SJXAvE8zkMIvi +PJaHKDy2FyCwtCHwG1wiQSqjnCJt5gmTGCXzO/yAGhcgUWbTpykIMij9IPboL7VL +er+I/3CikWeszcjBp5lJhg4k2OCBi5LOiI+8EUTlFcAqxbTFEyM+IQDOwnW8Gznf +nMb070gS9iBk0GTVC9iXHla0U1B1cHBldCBMYWJzIE5pZ2h0bHkgQnVpbGQgS2V5 +IChQdXBwZXQgTGFicyBOaWdodGx5IEJ1aWxkIEtleSkgPGluZm9AcHVwcGV0bGFi +cy5jb20+iQI+BBMBAgAoBQJREZ55AhsDBQkFo5qABgsJCAcDAgYVCAIJCgsEFgID +AQIeAQIXgAAKCRC4+ZnAB7tsVyjmEACSw9ZLq1ehcq8/QemiB+i8W/yVYZAxphmq +w547JXOxk19V5joR5Wp0fwqIEvE1Thw0mAiMUDAgM4TpdZc8zOaILj2OH1gWsuyi +fbFTHExTZAuZ1Lx1Nc1AlUv5Q+bmrzjAhx13Nk3LE7yfe4DLZnSyF3cZxAcSXYSq +wSo1sBrWxf2bOYnuyJwLlz94eeEkNdSi0mfANqt+ihiiAeTe9OXf65iPFn8SYRqV +W0hUayVlOedoCl0kviVXHvIgHxgkfazeIPqncFgPiRyYGNCVhKjaFjpUm+RzBFOk +HQzzcyNovlnjHmhxKkN+L2f1JqmHmUQguTTpJfpRdwmnEkA1BYY6m0WQ5Owga1eE +WEeHh9AjtVrukJOOibvpoS/M5FdAgaUgGXPIOziURDKBjQ0zuYMtlXgEDzKt0ugp +7YO74EAv1JiyeZ0Mu+m6WnxRX0Sb/op0ef74xZYD4eKYixOxahQ7kxtO9qTy+pOs +c3/KSNGv+oQh/CgChBbN3oq1UBfL6gVioRIp2GmP6Jmfipfod+VGIVI8xyfD3h/Z +nKF7dEHHMsyB03Ap2ypCcy8OEVwCeAZ4eY+lKXNyBSnddXcMGuFTqgJ1IMvTm0T8 +BfYn74A4fDqwNKKQGYjb67MZ+3N7YaWwCgWUvFpfd557fTQmZfV1arok2urvWIGa +x82lgKTA64kBHAQQAQoABgUCU9F5DwAKCRC61fCjkumFchUwB/wLfX/PA0LUbSen +es6ilcbHOZVZKyppMA5bIU6fG6SIS9FVauL0lgkEnJAhr5w3rXGd14LM33QkkPbs +/uNe2YQHzzrsffLhFyJkKJXH5rc6sSM7RYbAxtMNXKpkdMhPGmHgIgMzJo3ZuD8+ +ixsyR/8tGAMXbHwX5aAJDKYfg8X4kkPBxzysWJzN5/wFbYEK8FHiULkHNfJv480H +UBLNwczVeg9Etaje0tCQuGkD/CJHR50Kxuc/BiGYdYVjAnQVILXa2NcBizXtUU3f +N+6L+K2m9Fm3Dvhw0ZVEq7TxTMmHA23HGt8fMJ7zNCRO3krK7vtjUQxSXKOM7HF+ +D60QA/oGiQIcBBABAgAGBQJT0XdkAAoJEEaemzabDw8dtt0QAITarh4rsJWupVXD +BFHbxsUyT7AXspJ7kW3vxG3Y/gHSjleDX0VdblzUUBmD5y5JvR/DHrAgDd8XQN4E +4+hTOpZhzILZcoSWhiAW+VuL5b+R5NxSzIiHEt/qKgslvcx/sbQz8+Ro/zWHxhn9 +1uFf5JOFw+5W2wBmC4OdQby7B8AiV58OBAGcVUs0+57oJRYIU0zTRAJKRstMlD7s +F3R1d6EyNUbGjnJhPcltk6RRsYuJJx8vJzyY4pEy5eZPNSPEpFBjWlWyRnKDbQ6/ +TbtSB7bojbtjQFhh905kvdKxzcBkFgYTyzqJffUwHqJti8QQMraGAtC79/D/0vmf +lIJtzTB+gA/NOhyriaSXoGzi0oA/ZKReU3uJd5Yl202s/hvG+xpBkh7ouaVa5zFX +cqfi6gmmpQzVo6snI7d+Wonyvg1lhqZ7TXvtUIilsmbc5zEedidaCei77buX/ZuV +8jo+32HtsSKTYYHVsJzY6YzEy1SVfrUY+EdXXWG7Y97JaXKJc8oCNT1YA8BG4c+M +1cMXO1LTiP56gyYnrH6/oTIFrBXMl3dO/gKpcwUmf8lScFXIfVn5Wm3D0n6cUBKT +aRmmpfu7UhzBMEA7ZrIGxNBuD8WwfVi8ZSwBbV92fHkukkfixkhmeUmCB9vyq31+ +UfTwFXkHDTMZ4jfctKuBU+3p5sEwuQINBFERnnkBEAC0XpaBe0L9yvF1oc7rDLEt +XMrjDWHL6qPEW8ei94D619n1eo1QbZA4zZSZFjmN1SWtxg+2VRJazIlaFNMTpp+q +7lpmHPwzGdFdZZPVvjwd7cIe5KrGjEiTD1zf7i5Ws5Xh9jTh6VzY8nseakhIGTOC +lWzxl/+X2cJlMAR4/nLJjiTi3VwI2JBT8w2H8j8EgfRpjf6P1FyLv0WWMODc/hgc +/o5koLb4WRsK2w5usP/a3RNeh6L6iqHiiAL1Y9+0GZXOrjtNpkzPRarIL3MiX29o +VKSFcjUREpsEZHBHLwuA3WIR6WBX49LhrA6uLgofYhALeky6/H3ZFEH9ZS3plmnX +/vow8YWmz0Lyzzf848qsg5E5cHg36m2CXSEUeZfH748H78R62uIf/shusffl9Op2 +aZnQoPyeYIkA6N8m29CqIa/pzd68rLEQ+MNHHkp0KjQ0oKyrz9/YCXeQg3lIBXAv ++FIVK/04fMA3rr5tnynkeG9Ow6fGEtqzNjZhMZtx5BnkhdLTt6qu+wyaDw3q9X1/ +/j3lhplXteYzUkNUIinCHODGXaI55R/I4HNsbvtvy904g5sTHZX9QBn0x7QpVZaW +90jCgl6+NPH96g1cuHFuk+HED4H6XYFcdt1VRVb9YA7GgRXkSyfw6KdtGFT15e7o +7PcaD6NpqyBfbYfrNQmiOwARAQABiQIlBBgBAgAPBQJREZ55AhsMBQkFo5qAAAoJ +ELj5mcAHu2xXR8cP/Ai4PqUKBZdN6Jz628VQdiVX2EO7jhQ7KYdt9RWz87kfm0rC +LhdROCyeddgGsYbpdikC3Gzrk0JFIs/qAzpZOMIip0cXTxDEWWObuwShIac8hmZz +BE5SM7TcA9+/jmBwLajcreGgKs/MfDkkWkiBT/B+FyHkqS6O/rdBvYqFzLtvUigG +SRf1clP4QEGWcR6LLsJ1uiH+brK3G1GsILVpX5iQ0Y4wNv0xNRGZzAPVZ1/vgHCM +sAG7TZy26oOraigvnZeo1Q9r7pg+i6uSIu4ywfdNTOuoBK+VY+RKyAybBHIqH07w +p9TmYOY1x+wmIe0oSYcR47OcvZU57fdLsEB9djYvkGkkmbz0gwXQL0iEW3kX+05J +zrLzPsx6muR35SPNCvfR2T/0VCDwtNwwxACWuZI/tqsobU/+lA/MqRZ4kOD/Bx07 +CpZfYIAi2STc0MIDvpyDnZLiYVMMkqV4+gn2ANtkF+GKbra3Aeof9b4KEVabSaQ5 +5W70DJF0G5bmHBSdyqdYnKB/yRj1rH+dgRbiRMv7rBAx5Q8rbYiym8im+5XNUDy2 +ZTQcCD53HcBLvKX6RJ4ByYawKaQqMa27WK/YWVmFXqVDVk12iKrQW6zktDdGInnD ++f0rRH7c/7F/QuBR6Y4Zkso0CuVMNsmxv0E+7Zk0z4dWalzQuXpN7OXcZ8Gp +=Gl+v +-----END PGP PUBLIC KEY BLOCK-----", + } + EOS + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_failures => true) + shell(PUPPETLABS_KEY_CHECK_COMMAND) + end + end + context 'bogus key' do it 'fails' do pp = <<-EOS @@ -488,14 +669,14 @@ end end - describe 'keyserver_options =>' do + describe 'options =>' do context 'debug' do it 'works' do pp = <<-EOS apt_key { 'puppetlabs': - id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', - ensure => 'present', - keyserver_options => 'debug', + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + options => 'debug', } EOS @@ -507,9 +688,9 @@ it 'fails on invalid options' do pp = <<-EOS apt_key { 'puppetlabs': - id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', - ensure => 'present', - keyserver_options => 'this is totally bonkers', + id => '#{PUPPETLABS_GPG_KEY_LONG_ID}', + ensure => 'present', + options => 'this is totally bonkers', } EOS diff --git a/puphpet/puppet/modules/apt/spec/acceptance/apt_spec.rb b/puphpet/puppet/modules/apt/spec/acceptance/apt_spec.rb index 9ace221..d3bd761 100644 --- a/puphpet/puppet/modules/apt/spec/acceptance/apt_spec.rb +++ b/puphpet/puppet/modules/apt/spec/acceptance/apt_spec.rb @@ -11,25 +11,34 @@ context 'all the things' do it 'should work with no errors' do pp = <<-EOS - class { 'apt': - always_apt_update => true, - disable_keys => true, - purge_sources_list => true, - purge_sources_list_d => true, - purge_preferences => true, - purge_preferences_d => true, - update_timeout => '400', - update_tries => '3', - sources => { + if $::lsbdistcodename == 'lucid' { + $sources = undef + } else { + $sources = { 'puppetlabs' => { - 'ensure' => present, - 'location' => 'http://apt.puppetlabs.com', - 'repos' => 'main', - 'key' => '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30', - 'key_server' => 'pgp.mit.edu', - } + 'ensure' => present, + 'location' => 'http://apt.puppetlabs.com', + 'repos' => 'main', + 'key' => { + 'id' => '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30', + 'server' => 'pgp.mit.edu', + }, + }, + } + } + class { 'apt': + update => { + 'frequency' => 'always', + 'timeout' => '400', + 'tries' => '3', + }, + purge => { + 'sources.list' => true, + 'sources.list.d' => true, + 'preferences' => true, + 'preferences.d' => true, }, - fancy_progress => true, + sources => $sources, } EOS diff --git a/puphpet/puppet/modules/apt/spec/classes/apt_backports_spec.rb b/puphpet/puppet/modules/apt/spec/classes/apt_backports_spec.rb new file mode 100644 index 0000000..496fec0 --- /dev/null +++ b/puphpet/puppet/modules/apt/spec/classes/apt_backports_spec.rb @@ -0,0 +1,268 @@ +#!/usr/bin/env rspec +require 'spec_helper' + +describe 'apt::backports', :type => :class do + let (:pre_condition) { "class{ '::apt': }" } + describe 'debian/ubuntu tests' do + context 'defaults on deb' do + let(:facts) do + { + :lsbdistid => 'Debian', + :osfamily => 'Debian', + :lsbdistcodename => 'wheezy', + :puppetversion => Puppet.version, + } + end + it { is_expected.to contain_apt__source('backports').with({ + :location => 'http://httpredir.debian.org/debian', + :key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + :repos => 'main contrib non-free', + :release => 'wheezy-backports', + :pin => { 'priority' => 200, 'release' => 'wheezy-backports' }, + }) + } + end + context 'defaults on squeeze' do + let(:facts) do + { + :lsbdistid => 'Debian', + :osfamily => 'Debian', + :lsbdistcodename => 'squeeze', + :puppetversion => Puppet.version, + } + end + it { is_expected.to contain_apt__source('backports').with({ + :location => 'http://httpredir.debian.org/debian-backports', + :key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + :repos => 'main contrib non-free', + :release => 'squeeze-backports', + :pin => { 'priority' => 200, 'release' => 'squeeze-backports' }, + }) + } + end + context 'defaults on ubuntu' do + let(:facts) do + { + :lsbdistid => 'Ubuntu', + :osfamily => 'Debian', + :lsbdistcodename => 'trusty', + :puppetversion => Puppet.version, + } + end + it { is_expected.to contain_apt__source('backports').with({ + :location => 'http://archive.ubuntu.com/ubuntu', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + :repos => 'main universe multiverse restricted', + :release => 'trusty-backports', + :pin => { 'priority' => 200, 'release' => 'trusty-backports' }, + }) + } + end + context 'set everything' do + let(:facts) do + { + :lsbdistid => 'Ubuntu', + :osfamily => 'Debian', + :lsbdistcodename => 'trusty', + :puppetversion => Puppet.version, + } + end + let(:params) do + { + :location => 'http://archive.ubuntu.com/ubuntu-test', + :release => 'vivid', + :repos => 'main', + :key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + :pin => '90', + } + end + it { is_expected.to contain_apt__source('backports').with({ + :location => 'http://archive.ubuntu.com/ubuntu-test', + :key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + :repos => 'main', + :release => 'vivid', + :pin => { 'priority' => 90, 'release' => 'vivid' }, + }) + } + end + context 'set things with hashes' do + let(:facts) do + { + :lsbdistid => 'Ubuntu', + :osfamily => 'Debian', + :lsbdistcodename => 'trusty', + :puppetversion => Puppet.version, + } + end + let(:params) do + { + :key => { + 'id' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', + }, + :pin => { + 'priority' => '90', + }, + } + end + it { is_expected.to contain_apt__source('backports').with({ + :key => { 'id' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553' }, + :pin => { 'priority' => '90' }, + }) + } + end + end + describe 'mint tests' do + let(:facts) do + { + :lsbdistid => 'linuxmint', + :osfamily => 'Debian', + :lsbdistcodename => 'qiana', + :puppetversion => Puppet.version, + } + end + context 'sets all the needed things' do + let(:params) do + { + :location => 'http://archive.ubuntu.com/ubuntu', + :release => 'trusty-backports', + :repos => 'main universe multiverse restricted', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + } + end + it { is_expected.to contain_apt__source('backports').with({ + :location => 'http://archive.ubuntu.com/ubuntu', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + :repos => 'main universe multiverse restricted', + :release => 'trusty-backports', + :pin => { 'priority' => 200, 'release' => 'trusty-backports' }, + }) + } + end + context 'missing location' do + let(:params) do + { + :release => 'trusty-backports', + :repos => 'main universe multiverse restricted', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + } + end + it do + expect { + subject.call + }.to raise_error(Puppet::Error, /If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key/) + end + end + context 'missing release' do + let(:params) do + { + :location => 'http://archive.ubuntu.com/ubuntu', + :repos => 'main universe multiverse restricted', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + } + end + it do + expect { + subject.call + }.to raise_error(Puppet::Error, /If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key/) + end + end + context 'missing repos' do + let(:params) do + { + :location => 'http://archive.ubuntu.com/ubuntu', + :release => 'trusty-backports', + :key => '630239CC130E1A7FD81A27B140976EAF437D05B5', + } + end + it do + expect { + subject.call + }.to raise_error(Puppet::Error, /If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key/) + end + end + context 'missing key' do + let(:params) do + { + :location => 'http://archive.ubuntu.com/ubuntu', + :release => 'trusty-backports', + :repos => 'main universe multiverse restricted', + } + end + it do + expect { + subject.call + }.to raise_error(Puppet::Error, /If not on Debian or Ubuntu, you must explicitly pass location, release, repos, and key/) + end + end + end + describe 'validation' do + let(:facts) do + { + :lsbdistid => 'Ubuntu', + :osfamily => 'Debian', + :lsbdistcodename => 'trusty', + :puppetversion => Puppet.version, + } + end + context 'invalid location' do + let(:params) do + { + :location => true + } + end + it do + expect { + subject.call + }.to raise_error(Puppet::Error, /is not a string/) + end + end + context 'invalid release' do + let(:params) do + { + :release => true + } + end + it do + expect { + subject.call + }.to raise_error(Puppet::Error, /is not a string/) + end + end + context 'invalid repos' do + let(:params) do + { + :repos => true + } + end + it do + expect { + subject.call + }.to raise_error(Puppet::Error, /is not a string/) + end + end + context 'invalid key' do + let(:params) do + { + :key => true + } + end + it do + expect { + subject.call + }.to raise_error(Puppet::Error, /is not a string/) + end + end + context 'invalid pin' do + let(:params) do + { + :pin => true + } + end + it do + expect { + subject.call + }.to raise_error(Puppet::Error, /pin must be either a string, number or hash/) + end + end + end +end diff --git a/puphpet/puppet/modules/apt/spec/classes/apt_spec.rb b/puphpet/puppet/modules/apt/spec/classes/apt_spec.rb index d3ef34d..5aded56 100644 --- a/puphpet/puppet/modules/apt/spec/classes/apt_spec.rb +++ b/puphpet/puppet/modules/apt/spec/classes/apt_spec.rb @@ -1,143 +1,136 @@ require 'spec_helper' -describe 'apt', :type => :class do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian' } } +describe 'apt' do + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version} } context 'defaults' do - it { should contain_file('sources.list').that_notifies('Exec[apt_update]').only_with({ - 'ensure' => 'present', - 'path' => '/etc/apt/sources.list', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - 'notify' => 'Exec[apt_update]', + it { is_expected.to contain_file('sources.list').that_notifies('Class[Apt::Update]').only_with({ + :ensure => 'file', + :path => '/etc/apt/sources.list', + :owner => 'root', + :group => 'root', + :mode => '0644', + :notify => 'Class[Apt::Update]', })} - it { should contain_file('sources.list.d').that_notifies('Exec[apt_update]').only_with({ - 'ensure' => 'directory', - 'path' => '/etc/apt/sources.list.d', - 'owner' => 'root', - 'group' => 'root', - 'purge' => false, - 'recurse' => false, - 'notify' => 'Exec[apt_update]', + it { is_expected.to contain_file('sources.list.d').that_notifies('Class[Apt::Update]').only_with({ + :ensure => 'directory', + :path => '/etc/apt/sources.list.d', + :owner => 'root', + :group => 'root', + :mode => '0644', + :purge => false, + :recurse => false, + :notify => 'Class[Apt::Update]', })} - it { should contain_file('preferences.d').only_with({ - 'ensure' => 'directory', - 'path' => '/etc/apt/preferences.d', - 'owner' => 'root', - 'group' => 'root', - 'purge' => false, - 'recurse' => false, + it { is_expected.to contain_file('preferences').that_notifies('Class[Apt::Update]').only_with({ + :ensure => 'file', + :path => '/etc/apt/preferences', + :owner => 'root', + :group => 'root', + :mode => '0644', + :notify => 'Class[Apt::Update]', })} - it { should contain_file('01proxy').that_notifies('Exec[apt_update]').only_with({ - 'ensure' => 'absent', - 'path' => '/etc/apt/apt.conf.d/01proxy', - 'notify' => 'Exec[apt_update]', + it { is_expected.to contain_file('preferences.d').that_notifies('Class[Apt::Update]').only_with({ + :ensure => 'directory', + :path => '/etc/apt/preferences.d', + :owner => 'root', + :group => 'root', + :mode => '0644', + :purge => false, + :recurse => false, + :notify => 'Class[Apt::Update]', })} it 'should lay down /etc/apt/apt.conf.d/15update-stamp' do - should contain_file('/etc/apt/apt.conf.d/15update-stamp').with({ - 'group' => 'root', - 'mode' => '0644', - 'owner' => 'root', + is_expected.to contain_file('/etc/apt/apt.conf.d/15update-stamp').with({ + :group => 'root', + :mode => '0644', + :owner => 'root', }).with_content(/APT::Update::Post-Invoke-Success \{"touch \/var\/lib\/apt\/periodic\/update-success-stamp 2>\/dev\/null \|\| true";\};/) end - it { should contain_file('old-proxy-file').that_notifies('Exec[apt_update]').only_with({ - 'ensure' => 'absent', - 'path' => '/etc/apt/apt.conf.d/proxy', - 'notify' => 'Exec[apt_update]', + it { is_expected.to contain_exec('apt_update').with({ + :refreshonly => 'true', })} - it { should contain_exec('apt_update').with({ - 'refreshonly' => 'true', - })} + it { is_expected.not_to contain_apt__setting('conf-proxy') } end + describe 'proxy=' do + context 'host=localhost' do + let(:params) { { :proxy => { 'host' => 'localhost'} } } + it { is_expected.to contain_apt__setting('conf-proxy').with({ + :priority => '01', + }).with_content( + /Acquire::http::proxy "http:\/\/localhost:8080\/";/ + ).without_content( + /Acquire::https::proxy/ + )} + end + + context 'host=localhost and port=8180' do + let(:params) { { :proxy => { 'host' => 'localhost', 'port' => 8180} } } + it { is_expected.to contain_apt__setting('conf-proxy').with({ + :priority => '01', + }).with_content( + /Acquire::http::proxy "http:\/\/localhost:8180\/";/ + ).without_content( + /Acquire::https::proxy/ + )} + end + + context 'host=localhost and https=true' do + let(:params) { { :proxy => { 'host' => 'localhost', 'https' => true} } } + it { is_expected.to contain_apt__setting('conf-proxy').with({ + :priority => '01', + }).with_content( + /Acquire::http::proxy "http:\/\/localhost:8080\/";/ + ).with_content( + /Acquire::https::proxy "https:\/\/localhost:8080\/";/ + )} + end + + context 'ensure=absent' do + let(:params) { { :proxy => { 'ensure' => 'absent'} } } + it { is_expected.to contain_apt__setting('conf-proxy').with({ + :ensure => 'absent', + :priority => '01', + })} + end + end context 'lots of non-defaults' do let :params do { - :always_apt_update => true, - :disable_keys => true, - :proxy_host => 'foo', - :proxy_port => '9876', - :purge_sources_list => true, - :purge_sources_list_d => true, - :purge_preferences => true, - :purge_preferences_d => true, - :update_timeout => '1', - :update_tries => '3', - :fancy_progress => true, + :update => { 'frequency' => 'always', 'timeout' => 1, 'tries' => 3 }, + :purge => { 'sources.list' => false, 'sources.list.d' => false, + 'preferences' => false, 'preferences.d' => false, }, } end - it { should contain_file('sources.list').with({ - 'content' => "# Repos managed by puppet.\n" + it { is_expected.to contain_file('sources.list').with({ + :content => nil, })} - it { should contain_file('sources.list.d').with({ - 'purge' => 'true', - 'recurse' => 'true', + it { is_expected.to contain_file('sources.list.d').with({ + :purge => false, + :recurse => false, })} - it { should contain_file('apt-preferences').only_with({ - 'ensure' => 'absent', - 'path' => '/etc/apt/preferences', + it { is_expected.to contain_file('preferences').with({ + :ensure => 'file', })} - it { should contain_file('preferences.d').with({ - 'purge' => 'true', - 'recurse' => 'true', + it { is_expected.to contain_file('preferences.d').with({ + :purge => false, + :recurse => false, })} - it { should contain_file('99progressbar').only_with({ - 'ensure' => 'present', - 'content' => /Dpkg::Progress-Fancy "1";/, - 'path' => '/etc/apt/apt.conf.d/99progressbar', - })} - - it { should contain_file('99unauth').only_with({ - 'ensure' => 'present', - 'content' => /APT::Get::AllowUnauthenticated 1;/, - 'path' => '/etc/apt/apt.conf.d/99unauth', - })} - - it { should contain_file('01proxy').that_notifies('Exec[apt_update]').only_with({ - 'ensure' => 'present', - 'path' => '/etc/apt/apt.conf.d/01proxy', - 'content' => /Acquire::http::Proxy "http:\/\/foo:9876";/, - 'notify' => 'Exec[apt_update]', - 'mode' => '0644', - 'owner' => 'root', - 'group' => 'root' - })} - - it { should contain_exec('apt_update').with({ - 'refreshonly' => 'false', - 'timeout' => '1', - 'tries' => '3', - })} - - end - - context 'more non-default' do - let :params do - { - :fancy_progress => false, - :disable_keys => false, - } - end - - it { should contain_file('99progressbar').only_with({ - 'ensure' => 'absent', - 'path' => '/etc/apt/apt.conf.d/99progressbar', - })} - - it { should contain_file('99unauth').only_with({ - 'ensure' => 'absent', - 'path' => '/etc/apt/apt.conf.d/99unauth', + it { is_expected.to contain_exec('apt_update').with({ + :refreshonly => false, + :timeout => 1, + :tries => 3, })} end @@ -147,6 +140,7 @@ { :osfamily => 'Debian', :lsbdistcodename => 'precise', :lsbdistid => 'Debian', + :puppetversion => Puppet.version, } end let(:params) { { :sources => { @@ -154,110 +148,157 @@ 'location' => 'http://debian.mirror.iweb.ca/debian/', 'release' => 'unstable', 'repos' => 'main contrib non-free', - 'required_packages' => 'debian-keyring debian-archive-keyring', - 'key' => '150C8614919D8446E01E83AF9AA38DCD55BE302B', - 'key_server' => 'subkeys.pgp.net', + 'key' => { 'id' => '150C8614919D8446E01E83AF9AA38DCD55BE302B', 'server' => 'subkeys.pgp.net' }, 'pin' => '-10', - 'include_src' => true + 'include' => {'src' => true,}, }, 'puppetlabs' => { 'location' => 'http://apt.puppetlabs.com', 'repos' => 'main', - 'key' => '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30', - 'key_server' => 'pgp.mit.edu', + 'key' => { 'id' => '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30', 'server' => 'pgp.mit.edu' }, } } } } it { - should contain_file('debian_unstable.list').with({ - 'ensure' => 'present', - 'path' => '/etc/apt/sources.list.d/debian_unstable.list', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - 'notify' => 'Exec[apt_update]', + is_expected.to contain_apt__setting('list-debian_unstable').with({ + :ensure => 'present', }) } - it { should contain_file('debian_unstable.list').with_content(/^deb http:\/\/debian.mirror.iweb.ca\/debian\/ unstable main contrib non-free$/) } - it { should contain_file('debian_unstable.list').with_content(/^deb-src http:\/\/debian.mirror.iweb.ca\/debian\/ unstable main contrib non-free$/) } + it { is_expected.to contain_file('/etc/apt/sources.list.d/debian_unstable.list').with_content(/^deb http:\/\/debian.mirror.iweb.ca\/debian\/ unstable main contrib non-free$/) } + it { is_expected.to contain_file('/etc/apt/sources.list.d/debian_unstable.list').with_content(/^deb-src http:\/\/debian.mirror.iweb.ca\/debian\/ unstable main contrib non-free$/) } it { - should contain_file('puppetlabs.list').with({ - 'ensure' => 'present', - 'path' => '/etc/apt/sources.list.d/puppetlabs.list', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - 'notify' => 'Exec[apt_update]', + is_expected.to contain_apt__setting('list-puppetlabs').with({ + :ensure => 'present', }) } - it { should contain_file('puppetlabs.list').with_content(/^deb http:\/\/apt.puppetlabs.com precise main$/) } - it { should contain_file('puppetlabs.list').with_content(/^deb-src http:\/\/apt.puppetlabs.com precise main$/) } + it { is_expected.to contain_file('/etc/apt/sources.list.d/puppetlabs.list').with_content(/^deb http:\/\/apt.puppetlabs.com precise main$/) } + end + + context 'with keys defined on valid osfamily' do + let :facts do + { :osfamily => 'Debian', + :lsbdistcodename => 'precise', + :lsbdistid => 'Debian', + :puppetversion => Puppet.version, + } + end + let(:params) { { :keys => { + '55BE302B' => { + 'server' => 'subkeys.pgp.net', + }, + '4BD6EC30' => { + 'server' => 'pgp.mit.edu', + } + } } } + + it { is_expected.to contain_apt__key('55BE302B').with({ + :server => 'subkeys.pgp.net', + })} + + it { is_expected.to contain_apt__key('4BD6EC30').with({ + :server => 'pgp.mit.edu', + })} + end + + context 'with ppas defined on valid osfamily' do + let :facts do + { :osfamily => 'Debian', + :lsbdistcodename => 'precise', + :lsbdistid => 'ubuntu', + :puppetversion => Puppet.version, + } + end + let(:params) { { :ppas => { + 'ppa:drizzle-developers/ppa' => {}, + 'ppa:nginx/stable' => {}, + } } } + + it { is_expected.to contain_apt__ppa('ppa:drizzle-developers/ppa')} + it { is_expected.to contain_apt__ppa('ppa:nginx/stable')} + end + + context 'with settings defined on valid osfamily' do + let :facts do + { :osfamily => 'Debian', + :lsbdistcodename => 'precise', + :lsbdistid => 'Debian', + :puppetversion => Puppet.version, + } + end + let(:params) { { :settings => { + 'conf-banana' => { 'content' => 'banana' }, + 'pref-banana' => { 'content' => 'banana' }, + } } } + + it { is_expected.to contain_apt__setting('conf-banana')} + it { is_expected.to contain_apt__setting('pref-banana')} + end + + context 'with pins defined on valid osfamily' do + let :facts do + { :osfamily => 'Debian', + :lsbdistcodename => 'precise', + :lsbdistid => 'Debian', + :puppetversion => Puppet.version, + } + end + let(:params) { { :pins => { + 'stable' => { 'priority' => 600, 'order' => 50 }, + 'testing' => { 'priority' => 700, 'order' => 100 }, + } } } + + it { is_expected.to contain_apt__pin('stable') } + it { is_expected.to contain_apt__pin('testing') } end describe 'failing tests' do - context 'bad purge_sources_list' do - let :params do - { - 'purge_sources_list' => 'foo' - } - end + context "purge['sources.list']=>'banana'" do + let(:params) { { :purge => { 'sources.list' => 'banana' }, } } it do expect { - should compile + subject.call }.to raise_error(Puppet::Error) end end - context 'bad purge_sources_list_d' do - let :params do - { - 'purge_sources_list_d' => 'foo' - } - end + context "purge['sources.list.d']=>'banana'" do + let(:params) { { :purge => { 'sources.list.d' => 'banana' }, } } it do expect { - should compile + subject.call }.to raise_error(Puppet::Error) end end - context 'bad purge_preferences' do - let :params do - { - 'purge_preferences' => 'foo' - } - end + context "purge['preferences']=>'banana'" do + let(:params) { { :purge => { 'preferences' => 'banana' }, } } it do expect { - should compile + subject.call }.to raise_error(Puppet::Error) end end - context 'bad purge_preferences_d' do - let :params do - { - 'purge_preferences_d' => 'foo' - } - end + context "purge['preferences.d']=>'banana'" do + let(:params) { { :purge => { 'preferences.d' => 'banana' }, } } it do expect { - should compile + subject.call }.to raise_error(Puppet::Error) end end context 'with unsupported osfamily' do let :facts do - { :osfamily => 'Darwin', } + { :osfamily => 'Darwin', :puppetversion => Puppet.version,} end it do expect { - should compile + subject.call }.to raise_error(Puppet::Error, /This module only works on Debian or derivatives like Ubuntu/) end end diff --git a/puphpet/puppet/modules/apt/spec/classes/apt_update_spec.rb b/puphpet/puppet/modules/apt/spec/classes/apt_update_spec.rb index d70efd3..d031104 100644 --- a/puphpet/puppet/modules/apt/spec/classes/apt_update_spec.rb +++ b/puphpet/puppet/modules/apt/spec/classes/apt_update_spec.rb @@ -2,106 +2,72 @@ require 'spec_helper' describe 'apt::update', :type => :class do - context 'when apt::always_apt_update is true' do - #This should completely disable all of this logic. These tests are to guarantee that we don't somehow magically change the behavior. - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian' } } - let (:pre_condition) { "class{'::apt': always_apt_update => true}" } - it 'should trigger an apt-get update run' do - #set the apt_update exec's refreshonly attribute to false - should contain_exec('apt_update').with({'refreshonly' => false }) - end - ['always','daily','weekly','reluctantly'].each do |update_frequency| - context "when apt::apt_update_frequency has the value of #{update_frequency}" do - { 'a recent run' => Time.now.to_i, 'we are due for a run' => 1406660561,'the update-success-stamp file does not exist' => -1 }.each_pair do |desc, factval| - context "and $::apt_update_last_success indicates #{desc}" do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :apt_update_last_success => factval } } - let (:pre_condition) { "class{'::apt': always_apt_update => true, apt_update_frequency => '#{update_frequency}' }" } - it 'should trigger an apt-get update run' do - # set the apt_update exec's refreshonly attribute to false - should contain_exec('apt_update').with({'refreshonly' => false}) - end - end - context 'when $::apt_update_last_success is nil' do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian' } } - let (:pre_condition) { "class{'::apt': always_apt_update => true, apt_update_frequency => '#{update_frequency}' }" } - it 'should trigger an apt-get update run' do - #set the apt_update exec\'s refreshonly attribute to false - should contain_exec('apt_update').with({'refreshonly' => false}) - end - end + context "and apt::update['frequency']='always'" do + { 'a recent run' => Time.now.to_i, 'we are due for a run' => 1406660561,'the update-success-stamp file does not exist' => -1 }.each_pair do |desc, factval| + context "and $::apt_update_last_success indicates #{desc}" do + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :apt_update_last_success => factval, :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version, } } + let (:pre_condition) { "class{'::apt': update => {'frequency' => 'always' },}" } + it 'should trigger an apt-get update run' do + #set the apt_update exec's refreshonly attribute to false + is_expected.to contain_exec('apt_update').with({'refreshonly' => false}) end end end + context 'when $::apt_update_last_success is nil' do + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version, } } + let (:pre_condition) { "class{ '::apt': update => {'frequency' => 'always' },}" } + it 'should trigger an apt-get update run' do + #set the apt_update exec\'s refreshonly attribute to false + is_expected.to contain_exec('apt_update').with({'refreshonly' => false}) + end + end end - - context 'when apt::always_apt_update is false' do - context "and apt::apt_update_frequency has the value of always" do - { 'a recent run' => Time.now.to_i, 'we are due for a run' => 1406660561,'the update-success-stamp file does not exist' => -1 }.each_pair do |desc, factval| - context "and $::apt_update_last_success indicates #{desc}" do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :apt_update_last_success => factval } } - let (:pre_condition) { "class{'::apt': always_apt_update => false, apt_update_frequency => 'always' }" } - it 'should trigger an apt-get update run' do - #set the apt_update exec's refreshonly attribute to false - should contain_exec('apt_update').with({'refreshonly' => false}) - end + context "and apt::update['frequency']='reluctantly'" do + {'a recent run' => Time.now.to_i, 'we are due for a run' => 1406660561,'the update-success-stamp file does not exist' => -1 }.each_pair do |desc, factval| + context "and $::apt_update_last_success indicates #{desc}" do + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :apt_update_last_success => factval, :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version,} } + let (:pre_condition) { "class{ '::apt': update => {'frequency' => 'reluctantly' },}" } + it 'should not trigger an apt-get update run' do + #don't change the apt_update exec's refreshonly attribute. (it should be true) + is_expected.to contain_exec('apt_update').with({'refreshonly' => true}) end end - context 'when $::apt_update_last_success is nil' do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian' } } - let (:pre_condition) { "class{ '::apt': always_apt_update => false, apt_update_frequency => 'always' }" } - it 'should trigger an apt-get update run' do - #set the apt_update exec\'s refreshonly attribute to false - should contain_exec('apt_update').with({'refreshonly' => false}) - end + end + context 'when $::apt_update_last_success is nil' do + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version, } } + let (:pre_condition) { "class{ '::apt': update => {'frequency' => 'reluctantly' },}" } + it 'should not trigger an apt-get update run' do + #don't change the apt_update exec's refreshonly attribute. (it should be true) + is_expected.to contain_exec('apt_update').with({'refreshonly' => true}) end end - context "and apt::apt_update_frequency has the value of reluctantly" do - {'a recent run' => Time.now.to_i, 'we are due for a run' => 1406660561,'the update-success-stamp file does not exist' => -1 }.each_pair do |desc, factval| + end + ['daily','weekly'].each do |update_frequency| + context "and apt::update['frequency'] has the value of #{update_frequency}" do + { 'we are due for a run' => 1406660561,'the update-success-stamp file does not exist' => -1 }.each_pair do |desc, factval| context "and $::apt_update_last_success indicates #{desc}" do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :apt_update_last_success => factval} } - let (:pre_condition) { "class{ '::apt': always_apt_update => false, apt_update_frequency => 'reluctantly' }" } - it 'should not trigger an apt-get update run' do - #don't change the apt_update exec's refreshonly attribute. (it should be true) - should contain_exec('apt_update').with({'refreshonly' => true}) + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :apt_update_last_success => factval, :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version, } } + let (:pre_condition) { "class{ '::apt': update => {'frequency' => '#{update_frequency}',} }" } + it 'should trigger an apt-get update run' do + #set the apt_update exec\'s refreshonly attribute to false + is_expected.to contain_exec('apt_update').with({'refreshonly' => false}) end end end - context 'when $::apt_update_last_success is nil' do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian' } } - let (:pre_condition) { "class{ '::apt': always_apt_update => false, apt_update_frequency => 'reluctantly' }" } + context 'when the $::apt_update_last_success fact has a recent value' do + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :lsbdistcodename => 'wheezy', :apt_update_last_success => Time.now.to_i, :puppetversion => Puppet.version, } } + let (:pre_condition) { "class{ '::apt': update => {'frequency' => '#{update_frequency}',} }" } it 'should not trigger an apt-get update run' do - #don't change the apt_update exec's refreshonly attribute. (it should be true) - should contain_exec('apt_update').with({'refreshonly' => true}) + #don't change the apt_update exec\'s refreshonly attribute. (it should be true) + is_expected.to contain_exec('apt_update').with({'refreshonly' => true}) end end - end - ['daily','weekly'].each do |update_frequency| - context "and apt::apt_update_frequency has the value of #{update_frequency}" do - { 'we are due for a run' => 1406660561,'the update-success-stamp file does not exist' => -1 }.each_pair do |desc, factval| - context "and $::apt_update_last_success indicates #{desc}" do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :apt_update_last_success => factval } } - let (:pre_condition) { "class{ '::apt': always_apt_update => false, apt_update_frequency => '#{update_frequency}' }" } - it 'should trigger an apt-get update run' do - #set the apt_update exec\'s refreshonly attribute to false - should contain_exec('apt_update').with({'refreshonly' => false}) - end - end - end - context 'when the $::apt_update_last_success fact has a recent value' do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :apt_update_last_success => Time.now.to_i } } - let (:pre_condition) { "class{ '::apt': always_apt_update => false, apt_update_frequency => '#{update_frequency}' }" } - it 'should not trigger an apt-get update run' do - #don't change the apt_update exec\'s refreshonly attribute. (it should be true) - should contain_exec('apt_update').with({'refreshonly' => true}) - end - end - context 'when $::apt_update_last_success is nil' do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian' } } - let (:pre_condition) { "class{ '::apt': always_apt_update => false, apt_update_frequency => '#{update_frequency}' }" } - it 'should trigger an apt-get update run' do - #set the apt_update exec\'s refreshonly attribute to false - should contain_exec('apt_update').with({'refreshonly' => false}) - end + context 'when $::apt_update_last_success is nil' do + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :lsbdistcodename => 'wheezy', :apt_update_last_success => nil, :puppetversion => Puppet.version, } } + let (:pre_condition) { "class{ '::apt': update => {'frequency' => '#{update_frequency}',} }" } + it 'should trigger an apt-get update run' do + #set the apt_update exec\'s refreshonly attribute to false + is_expected.to contain_exec('apt_update').with({'refreshonly' => false}) end end end diff --git a/puphpet/puppet/modules/apt/spec/classes/backports_spec.rb b/puphpet/puppet/modules/apt/spec/classes/backports_spec.rb deleted file mode 100644 index 721a4a6..0000000 --- a/puphpet/puppet/modules/apt/spec/classes/backports_spec.rb +++ /dev/null @@ -1,177 +0,0 @@ -require 'spec_helper' -describe 'apt::backports', :type => :class do - - describe 'when asigning a custom priority to backports' do - let :facts do - { - 'lsbdistcodename' => 'Karmic', - 'lsbdistid' => 'Ubuntu', - 'osfamily' => 'Debian' - } - end - - context 'integer priority' do - let :params do { :pin_priority => 500 } end - - it { should contain_apt__source('backports').with({ - 'location' => 'http://old-releases.ubuntu.com/ubuntu', - 'release' => 'karmic-backports', - 'repos' => 'main universe multiverse restricted', - 'key' => '630239CC130E1A7FD81A27B140976EAF437D05B5', - 'key_server' => 'pgp.mit.edu', - }) - } - - it { should contain_apt__pin('backports').with({ - 'release' => 'karmic-backports', - 'priority' => 500, - }) - } - end - - context 'invalid priority' do - let :params do { :pin_priority => 'banana' } end - it 'should fail' do - expect { subject }.to raise_error(/must be an integer/) - end - end - end - - describe 'when turning on backports for ubuntu karmic' do - - let :facts do - { - 'lsbdistcodename' => 'Karmic', - 'lsbdistid' => 'Ubuntu', - 'osfamily' => 'Debian' - } - end - - it { should contain_apt__source('backports').with({ - 'location' => 'http://old-releases.ubuntu.com/ubuntu', - 'release' => 'karmic-backports', - 'repos' => 'main universe multiverse restricted', - 'key' => '630239CC130E1A7FD81A27B140976EAF437D05B5', - 'key_server' => 'pgp.mit.edu', - }) - } - - it { should contain_apt__pin('backports').with({ - 'release' => 'karmic-backports', - 'priority' => 200, - }) - } - end - - describe "when turning on backports for debian squeeze" do - - let :facts do - { - 'lsbdistcodename' => 'Squeeze', - 'lsbdistid' => 'Debian', - 'osfamily' => 'Debian' - } - end - - it { should contain_apt__source('backports').with({ - 'location' => 'http://backports.debian.org/debian-backports', - 'release' => 'squeeze-backports', - 'repos' => 'main contrib non-free', - 'key' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', - 'key_server' => 'pgp.mit.edu', - }) - } - - it { should contain_apt__pin('backports').with({ - 'release' => 'squeeze-backports', - 'priority' => 200, - }) - } - end - - describe "when turning on backports for linux mint debian edition" do - - let :facts do - { - 'lsbdistcodename' => 'debian', - 'lsbdistid' => 'LinuxMint', - 'osfamily' => 'Debian' - } - end - - it { should contain_apt__source('backports').with({ - 'location' => 'http://ftp.debian.org/debian/', - 'release' => 'wheezy-backports', - 'repos' => 'main contrib non-free', - 'key' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', - 'key_server' => 'pgp.mit.edu', - }) - } - - it { should contain_apt__pin('backports').with({ - 'release' => 'wheezy-backports', - 'priority' => 200, - }) - } - end - - describe "when turning on backports for linux mint 17 (ubuntu-based)" do - - let :facts do - { - 'lsbdistcodename' => 'qiana', - 'lsbdistid' => 'LinuxMint', - 'osfamily' => 'Debian' - } - end - - it { should contain_apt__source('backports').with({ - 'location' => 'http://us.archive.ubuntu.com/ubuntu', - 'release' => 'trusty-backports', - 'repos' => 'main universe multiverse restricted', - 'key' => '630239CC130E1A7FD81A27B140976EAF437D05B5', - 'key_server' => 'pgp.mit.edu', - }) - } - - it { should contain_apt__pin('backports').with({ - 'release' => 'trusty-backports', - 'priority' => 200, - }) - } - end - - describe "when turning on backports for debian squeeze but using your own mirror" do - - let :facts do - { - 'lsbdistcodename' => 'Squeeze', - 'lsbdistid' => 'Debian', - 'osfamily' => 'Debian' - } - end - - let :location do - 'http://mirrors.example.com/debian-backports' - end - - let :params do - { 'location' => location } - end - - it { should contain_apt__source('backports').with({ - 'location' => location, - 'release' => 'squeeze-backports', - 'repos' => 'main contrib non-free', - 'key' => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', - 'key_server' => 'pgp.mit.edu', - }) - } - - it { should contain_apt__pin('backports').with({ - 'release' => 'squeeze-backports', - 'priority' => 200, - }) - } - end -end diff --git a/puphpet/puppet/modules/apt/spec/classes/debian_testing_spec.rb b/puphpet/puppet/modules/apt/spec/classes/debian_testing_spec.rb deleted file mode 100644 index a2e35f5..0000000 --- a/puphpet/puppet/modules/apt/spec/classes/debian_testing_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' -describe 'apt::debian::testing', :type => :class do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian' } } - it { - should contain_apt__source("debian_testing").with({ - "location" => "http://debian.mirror.iweb.ca/debian/", - "release" => "testing", - "repos" => "main contrib non-free", - "required_packages" => "debian-keyring debian-archive-keyring", - "key" => "A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553", - "key_server" => "subkeys.pgp.net", - "pin" => "-10" - }) - } -end diff --git a/puphpet/puppet/modules/apt/spec/classes/debian_unstable_spec.rb b/puphpet/puppet/modules/apt/spec/classes/debian_unstable_spec.rb deleted file mode 100644 index 14d8650..0000000 --- a/puphpet/puppet/modules/apt/spec/classes/debian_unstable_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'spec_helper' -describe 'apt::debian::unstable', :type => :class do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian' } } - it { - should contain_apt__source("debian_unstable").with({ - "location" => "http://debian.mirror.iweb.ca/debian/", - "release" => "unstable", - "repos" => "main contrib non-free", - "required_packages" => "debian-keyring debian-archive-keyring", - "key" => "A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553", - "key_server" => "subkeys.pgp.net", - "pin" => "-10" - }) - } -end diff --git a/puphpet/puppet/modules/apt/spec/classes/params_spec.rb b/puphpet/puppet/modules/apt/spec/classes/params_spec.rb index d85e849..e9eb6fb 100644 --- a/puphpet/puppet/modules/apt/spec/classes/params_spec.rb +++ b/puphpet/puppet/modules/apt/spec/classes/params_spec.rb @@ -1,39 +1,25 @@ require 'spec_helper' describe 'apt::params', :type => :class do - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian' } } + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version, } } let (:title) { 'my_package' } - it { should contain_apt__params } + it { is_expected.to contain_apt__params } # There are 4 resources in this class currently # there should not be any more resources because it is a params class # The resources are class[apt::params], class[main], class[settings], stage[main] it "Should not contain any resources" do - subject.resources.size.should == 4 - end - - describe "With unknown lsbdistid" do - - let(:facts) { { :lsbdistid => 'CentOS' } } - let (:title) { 'my_package' } - - it do - expect { - should compile - }.to raise_error(Puppet::Error, /Unsupported lsbdistid/) - end - + expect(subject.call.resources.size).to eq(4) end describe "With lsb-release not installed" do - let(:facts) { { :lsbdistid => '' } } + let(:facts) { { :osfamily => 'Debian', :puppetversion => Puppet.version, } } let (:title) { 'my_package' } it do expect { - should compile - }.to raise_error(Puppet::Error, /Unable to determine lsbdistid, is lsb-release installed/) + subject.call + }.to raise_error(Puppet::Error, /Unable to determine lsbdistid, please install lsb-release first/) end end - end diff --git a/puphpet/puppet/modules/apt/spec/classes/release_spec.rb b/puphpet/puppet/modules/apt/spec/classes/release_spec.rb deleted file mode 100644 index f8c6512..0000000 --- a/puphpet/puppet/modules/apt/spec/classes/release_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'spec_helper' -describe 'apt::release', :type => :class do - let(:facts) { { :lsbdistid => 'Debian' } } - let (:title) { 'my_package' } - - let :param_set do - { :release_id => 'precise' } - end - - let (:params) { param_set } - - it { should contain_class("apt::params") } - - it { - should contain_file("/etc/apt/apt.conf.d/01release").with({ - "mode" => "0644", - "owner" => "root", - "group" => "root", - "content" => /APT::Default-Release "#{param_set[:release_id]}";/ - }) - } -end - diff --git a/puphpet/puppet/modules/apt/spec/classes/unattended_upgrades_spec.rb b/puphpet/puppet/modules/apt/spec/classes/unattended_upgrades_spec.rb deleted file mode 100644 index 0a02755..0000000 --- a/puphpet/puppet/modules/apt/spec/classes/unattended_upgrades_spec.rb +++ /dev/null @@ -1,211 +0,0 @@ -require 'spec_helper' -describe 'apt::unattended_upgrades', :type => :class do - let(:file_unattended) { '/etc/apt/apt.conf.d/50unattended-upgrades' } - let(:file_periodic) { '/etc/apt/apt.conf.d/10periodic' } - let(:facts) { { :lsbdistid => 'Debian' } } - - it { should contain_package("unattended-upgrades") } - - it { - should create_file("/etc/apt/apt.conf.d/50unattended-upgrades").with({ - "owner" => "root", - "group" => "root", - "mode" => "0644", - "require" => "Package[unattended-upgrades]", - }) - } - - it { - should create_file("/etc/apt/apt.conf.d/10periodic").with({ - "owner" => "root", - "group" => "root", - "mode" => "0644", - "require" => "Package[unattended-upgrades]", - }) - } - - describe 'failing' do - let :facts do - { - 'lsbdistid' => 'debian', - 'lsbdistcodename' => 'squeeze', - } - end - context 'bad auto_fix' do - let :params do - { - 'auto_fix' => 'foo', - } - end - it { expect { should raise_error(Puppet::Error) } } - end - - context 'bad minimal_steps' do - let :params do - { - 'minimal_steps' => 'foo', - } - end - it { expect { should raise_error(Puppet::Error) } } - end - - context 'bad install_on_shutdown' do - let :params do - { - 'install_on_shutdown' => 'foo', - } - end - it { expect { should raise_error(Puppet::Error) } } - end - - context 'bad mail_only_on_error' do - let :params do - { - 'mail_only_on_error' => 'foo', - } - end - it { expect { should raise_error(Puppet::Error) } } - end - - context 'bad remove_unused' do - let :params do - { - 'remove_unused' => 'foo', - } - end - it { expect { should raise_error(Puppet::Error) } } - end - - context 'bad auto_reboot' do - let :params do - { - 'auto_reboot' => 'foo', - } - end - it { expect { should raise_error(Puppet::Error) } } - end - - context 'bad origins' do - let :params do - { - 'origins' => 'foo' - } - end - it { expect { should raise_error(Puppet::Error) } } - end - - context 'bad randomsleep' do - let :params do - { - 'randomsleep' => '4ever' - } - end - it { expect { should raise_error(Puppet::Error) } } - end - end - - context 'defaults' do - let :facts do - { - 'lsbdistid' => 'debian', - 'lsbdistcodename' => 'squeeze', - } - end - - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::Allowed-Origins \{\n\t"\${distro_id} oldstable";\n\t"\${distro_id} \${distro_codename}-security";\n\t"\${distro_id} \${distro_codename}-lts";\n\};} } - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::AutoFixInterruptedDpkg "true";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::MinimalSteps "false";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::InstallOnShutdown "false";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::Remove-Unused-Dependencies "true";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::Automatic-Reboot "false";}} - - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Enable "1";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::BackUpArchiveInterval "0";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::BackUpLevel "3";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::MaxAge "0";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::MinAge "0";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::MaxSize "0";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Update-Package-Lists "1";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Download-Upgradeable-Packages "1";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Download-Upgradeable-Packages-Debdelta "0";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Unattended-Upgrade "1";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::AutocleanInterval "7";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Verbose "0";}} - it { is_expected.to_not contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::RandomSleep}} - end - - context 'wheezy' do - let :facts do - { - 'lsbdistid' => 'debian', - 'lsbdistcodename' => 'wheezy', - } - end - - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::Origins-Pattern \{\n\t"origin=Debian,archive=stable,label=Debian-Security";\n\t"origin=Debian,archive=oldstable,label=Debian-Security";\n\};} } - end - - context 'anything but defaults' do - let :facts do - { - 'lsbdistid' => 'debian', - 'lsbdistcodename' => 'wheezy', - } - end - - let :params do - { - 'legacy_origin' => true, - 'enable' => '0', - 'backup_interval' => '3', - 'backup_level' => '1', - 'max_age' => '7', - 'min_age' => '1', - 'max_size' => '100', - 'update' => '0', - 'download' => '0', - 'download_delta' => '1', - 'upgrade' => '0', - 'autoclean' => '0', - 'verbose' => '1', - 'origins' => ['bananas'], - 'blacklist' => ['foo', 'bar'], - 'auto_fix' => false, - 'minimal_steps' => true, - 'install_on_shutdown' => true, - 'mail_to' => 'root@localhost', - 'mail_only_on_error' => true, - 'remove_unused' => false, - 'auto_reboot' => true, - 'dl_limit' => '70', - 'randomsleep' => '1799', - } - end - - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::Allowed-Origins \{\n\t"bananas";\n\};} } - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::Package-Blacklist \{\n\t"foo";\n\t"bar";\n\};} } - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::AutoFixInterruptedDpkg "false";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::MinimalSteps "true";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::InstallOnShutdown "true";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::Mail "root@localhost";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::MailOnlyOnError "true";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::Remove-Unused-Dependencies "false";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Unattended-Upgrade::Automatic-Reboot "true";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/50unattended-upgrades").with_content %r{Acquire::http::Dl-Limit "70";}} - - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Enable "0";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::BackUpArchiveInterval "3";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::BackUpLevel "1";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::MaxAge "7";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::MinAge "1";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::MaxSize "100";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Update-Package-Lists "0";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Download-Upgradeable-Packages "0";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Download-Upgradeable-Packages-Debdelta "1";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Unattended-Upgrade "0";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::AutocleanInterval "0";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::Verbose "1";}} - it { is_expected.to contain_file("/etc/apt/apt.conf.d/10periodic").with_content %r{APT::Periodic::RandomSleep "1799";}} - - end -end diff --git a/puphpet/puppet/modules/apt/spec/defines/builddep_spec.rb b/puphpet/puppet/modules/apt/spec/defines/builddep_spec.rb deleted file mode 100644 index 41152d5..0000000 --- a/puphpet/puppet/modules/apt/spec/defines/builddep_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'spec_helper' -describe 'apt::builddep', :type => :define do - - let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian' } } - let(:title) { 'my_package' } - - describe "defaults" do - it { should contain_exec("apt-builddep-my_package").that_requires('Exec[apt_update]').with({ - 'command' => "/usr/bin/apt-get -y --force-yes build-dep my_package", - 'logoutput' => 'on_failure' - }) - } - it { should contain_anchor("apt::builddep::my_package").with({ - 'require' => 'Class[Apt::Update]', - }) - } - end - -end diff --git a/puphpet/puppet/modules/apt/spec/defines/conf_spec.rb b/puphpet/puppet/modules/apt/spec/defines/conf_spec.rb index 2c1752f..c74bf1a 100644 --- a/puphpet/puppet/modules/apt/spec/defines/conf_spec.rb +++ b/puphpet/puppet/modules/apt/spec/defines/conf_spec.rb @@ -1,23 +1,29 @@ require 'spec_helper' describe 'apt::conf', :type => :define do - let(:facts) { { :lsbdistid => 'Debian' } } + let :pre_condition do + 'class { "apt": }' + end + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version, } } let :title do 'norecommends' end describe "when creating an apt preference" do - let :params do + let :default_params do { :priority => '00', :content => "Apt::Install-Recommends 0;\nApt::AutoRemove::InstallRecommends 1;\n" } end + let :params do + default_params + end let :filename do "/etc/apt/apt.conf.d/00norecommends" end - it { should contain_file(filename).with({ + it { is_expected.to contain_file(filename).with({ 'ensure' => 'present', 'content' => /Apt::Install-Recommends 0;\nApt::AutoRemove::InstallRecommends 1;/, 'owner' => 'root', @@ -25,6 +31,34 @@ 'mode' => '0644', }) } + + context "with notify_update = true (default)" do + let :params do + default_params + end + it { is_expected.to contain_apt__setting("conf-#{title}").with_notify_update(true) } + end + + context "with notify_update = false" do + let :params do + default_params.merge({ + :notify_update => false + }) + end + it { is_expected.to contain_apt__setting("conf-#{title}").with_notify_update(false) } + end + end + + describe "when creating a preference without content" do + let :params do + { + :priority => '00', + } + end + + it 'fails' do + expect { subject.call } .to raise_error(/pass in content/) + end end describe "when removing an apt preference" do @@ -32,7 +66,6 @@ { :ensure => 'absent', :priority => '00', - :content => "Apt::Install-Recommends 0;\nApt::AutoRemove::InstallRecommends 1;\n" } end @@ -40,9 +73,8 @@ "/etc/apt/apt.conf.d/00norecommends" end - it { should contain_file(filename).with({ + it { is_expected.to contain_file(filename).with({ 'ensure' => 'absent', - 'content' => /Apt::Install-Recommends 0;\nApt::AutoRemove::InstallRecommends 1;/, 'owner' => 'root', 'group' => 'root', 'mode' => '0644', diff --git a/puphpet/puppet/modules/apt/spec/defines/force_spec.rb b/puphpet/puppet/modules/apt/spec/defines/force_spec.rb deleted file mode 100644 index c32c438..0000000 --- a/puphpet/puppet/modules/apt/spec/defines/force_spec.rb +++ /dev/null @@ -1,102 +0,0 @@ -require 'spec_helper' -describe 'apt::force', :type => :define do - let(:facts) { { :lsbdistid => 'Debian' } } - let :pre_condition do - 'include apt::params' - end - - let :title do - 'my_package' - end - - let :default_params do - { - :release => false, - :version => false, - :cfg_files => 'none', - :cfg_missing => false, - } - end - - describe "when using default parameters" do - it { should contain_exec("/usr/bin/apt-get -y install #{title}").with( - :unless => "/usr/bin/dpkg -s #{title} | grep -q 'Status: install'", - :logoutput => 'on_failure', - :timeout => '300' - ) } - end - - describe "when specifying release parameter" do - let :params do - default_params.merge(:release => 'testing') - end - it { should contain_exec("/usr/bin/apt-get -y -t #{params[:release]} install #{title}").with( - :unless => "/usr/bin/test \$(/usr/bin/apt-cache policy -t #{params[:release]} #{title} | /bin/grep -E 'Installed|Candidate' | /usr/bin/uniq -s 14 | /usr/bin/wc -l) -eq 1" - ) } - end - - describe "when specifying version parameter" do - let :params do - default_params.merge(:version => '1') - end - it { should contain_exec("/usr/bin/apt-get -y install #{title}=#{params[:version]}").with( - :unless => "/usr/bin/dpkg -s #{title} | grep -q 'Version: #{params[:version]}'" - ) } - end - - describe "when specifying cfg_files parameter" do - let :params do - default_params.merge(:cfg_files => 'unchanged') - end - it { should contain_exec('/usr/bin/apt-get -y -o Dpkg::Options::="--force-confdef" install my_package').with( - :unless => "/usr/bin/dpkg -s #{title} | grep -q 'Status: install'" - ) } - end - - describe "when specifying cfg_missing parameter" do - let :params do - default_params.merge(:cfg_missing => true) - end - it { should contain_exec('/usr/bin/apt-get -y -o Dpkg::Options::="--force-confmiss" install my_package').with( - :unless => "/usr/bin/dpkg -s #{title} | grep -q 'Status: install'" - ) } - end - - describe "when specifying cfg_files and cfg_missing parameter" do - let :params do - default_params.merge( - :cfg_files => 'unchanged', - :cfg_missing => true - ) - end - it { should contain_exec('/usr/bin/apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confmiss" install my_package').with( - :unless => "/usr/bin/dpkg -s #{title} | grep -q 'Status: install'" - ) } - end - - describe "when specifying release and version parameters" do - let :params do - default_params.merge( - :release => 'testing', - :version => '1' - ) - end - it { should contain_exec("/usr/bin/apt-get -y -t #{params[:release]} install #{title}=1").with( - :unless => "/usr/bin/apt-cache policy -t #{params[:release]} #{title} | /bin/grep -q 'Installed: #{params[:version]}'" - ) } - end - - describe "when specifying release, version, cfg_files and cfg_missing parameters" do - let :params do - default_params.merge( - :release => 'testing', - :version => '1', - :cfg_files => 'unchanged', - :cfg_missing => true - ) - end - it { should contain_exec('/usr/bin/apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confmiss" -t testing install my_package=1').with( - :unless => "/usr/bin/apt-cache policy -t #{params[:release]} #{title} | /bin/grep -q 'Installed: #{params[:version]}'" - ) } - end -end diff --git a/puphpet/puppet/modules/apt/spec/defines/hold_spec.rb b/puphpet/puppet/modules/apt/spec/defines/hold_spec.rb deleted file mode 100644 index 60b991f..0000000 --- a/puphpet/puppet/modules/apt/spec/defines/hold_spec.rb +++ /dev/null @@ -1,97 +0,0 @@ -require 'spec_helper' -describe 'apt::hold' do - let :facts do { - :osfamily => 'Debian', - :lsbdistid => 'Debian', - :lsbrelease => 'wheezy', - } end - - let :title do - 'vim' - end - - let :default_params do { - :version => '1.1.1', - } end - - describe 'default params' do - let :params do default_params end - - it 'creates an apt preferences file' do - should contain_apt__pin("hold_#{title}").with({ - :ensure => 'present', - :packages => title, - :version => params[:version], - :priority => 1001, - }) - end - end - - describe 'ensure => absent' do - let :params do default_params.merge({:ensure => 'absent',}) end - - it 'creates an apt preferences file' do - - should contain_apt__pin("hold_#{title}").with({ - :ensure => params[:ensure], - }) - end - end - - describe 'priority => 990' do - let :params do default_params.merge({:priority => 990,}) end - - it 'creates an apt preferences file' do - should contain_apt__pin("hold_#{title}").with({ - :ensure => 'present', - :packages => title, - :version => params[:version], - :priority => params[:priority], - }) - end - end - - describe 'package => foo' do - let :params do default_params.merge({:package => 'foo'}) end - - it 'creates an apt preferences file' do - should contain_apt__pin("hold_foo").with({ - :ensure => 'present', - :packages => 'foo', - :version => params[:version], - :priority => 1001, - }) - end - end - - - describe 'validation' do - context 'version => {}' do - let :params do { :version => {}, } end - it 'should fail' do - expect { subject }.to raise_error(/is not a string/) - end - end - - context 'ensure => bananana' do - let :params do default_params.merge({:ensure => 'bananana',}) end - it 'should fail' do - expect { subject }.to raise_error(/does not match/) - end - end - - context 'package => []' do - let :params do default_params.merge({:package => [],}) end - it 'should fail' do - expect { subject }.to raise_error(/is not a string/) - end - end - - context 'priority => bananana' do - let :params do default_params.merge({:priority => 'bananana',}) end - it 'should fail' do - expect { subject }.to raise_error(/must be an integer/) - end - end - end -end diff --git a/puphpet/puppet/modules/apt/spec/defines/key_compat_spec.rb b/puphpet/puppet/modules/apt/spec/defines/key_compat_spec.rb new file mode 100644 index 0000000..872bcad --- /dev/null +++ b/puphpet/puppet/modules/apt/spec/defines/key_compat_spec.rb @@ -0,0 +1,316 @@ +require 'spec_helper' + +describe 'apt::key', :type => :define do + let(:facts) { { :lsbdistid => 'Debian' } } + GPG_KEY_ID = '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30' + + let :title do + GPG_KEY_ID + end + + describe 'normal operation' do + describe 'default options' do + it 'contains the apt_key' do + should contain_apt_key(title).with({ + :id => title, + :ensure => 'present', + :source => nil, + :server => nil, + :content => nil, + :keyserver_options => nil, + }) + end + it 'contains the apt_key present anchor' do + should contain_anchor("apt_key #{title} present") + end + end + + describe 'title and key =>' do + let :title do + 'puppetlabs' + end + + let :params do { + :key => GPG_KEY_ID, + } end + + it 'contains the apt_key' do + should contain_apt_key(title).with({ + :id => GPG_KEY_ID, + :ensure => 'present', + :source => nil, + :server => nil, + :content => nil, + :keyserver_options => nil, + }) + end + it 'contains the apt_key present anchor' do + should contain_anchor("apt_key #{GPG_KEY_ID} present") + end + end + + describe 'ensure => absent' do + let :params do { + :ensure => 'absent', + } end + + it 'contains the apt_key' do + should contain_apt_key(title).with({ + :id => title, + :ensure => 'absent', + :source => nil, + :server => nil, + :content => nil, + :keyserver_options => nil, + }) + end + it 'contains the apt_key absent anchor' do + should contain_anchor("apt_key #{title} absent") + end + end + + describe 'set a bunch of things!' do + let :params do { + :key_content => 'GPG key content', + :key_source => 'http://apt.puppetlabs.com/pubkey.gpg', + :key_server => 'pgp.mit.edu', + :key_options => 'debug', + } end + + it 'contains the apt_key' do + should contain_apt_key(title).with({ + :id => title, + :ensure => 'present', + :source => 'http://apt.puppetlabs.com/pubkey.gpg', + :server => 'pgp.mit.edu', + :content => params[:key_content], + :options => 'debug', + }) + end + it 'contains the apt_key present anchor' do + should contain_anchor("apt_key #{title} present") + end + end + + context "domain with dash" do + let(:params) do{ + :key_server => 'p-gp.m-it.edu', + } end + it 'contains the apt_key' do + should contain_apt_key(title).with({ + :id => title, + :server => 'p-gp.m-it.edu', + }) + end + end + + context "url" do + let :params do + { + :key_server => 'hkp://pgp.mit.edu', + } + end + it 'contains the apt_key' do + should contain_apt_key(title).with({ + :id => title, + :server => 'hkp://pgp.mit.edu', + }) + end + end + context "url with port number" do + let :params do + { + :key_server => 'hkp://pgp.mit.edu:80', + } + end + it 'contains the apt_key' do + should contain_apt_key(title).with({ + :id => title, + :server => 'hkp://pgp.mit.edu:80', + }) + end + end + end + + describe 'validation' do + context "domain begin with dash" do + let(:params) do{ + :key_server => '-pgp.mit.edu', + } end + it 'fails' do + expect { subject.call } .to raise_error(/does not match/) + end + end + + context "domain begin with dot" do + let(:params) do{ + :key_server => '.pgp.mit.edu', + } end + it 'fails' do + expect { subject.call } .to raise_error(/does not match/) + end + end + + context "domain end with dot" do + let(:params) do{ + :key_server => "pgp.mit.edu.", + } end + it 'fails' do + expect { subject.call } .to raise_error(/does not match/) + end + end + context "exceed character url" do + let :params do + { + :key_server => 'hkp://pgpiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.mit.edu' + } + end + it 'fails' do + expect { subject.call }.to raise_error(/does not match/) + end + end + context "incorrect port number url" do + let :params do + { + :key_server => 'hkp://pgp.mit.edu:8008080' + } + end + it 'fails' do + expect { subject.call }.to raise_error(/does not match/) + end + end + context "incorrect protocol for url" do + let :params do + { + :key_server => 'abc://pgp.mit.edu:80' + } + end + it 'fails' do + expect { subject.call }.to raise_error(/does not match/) + end + end + context "missing port number url" do + let :params do + { + :key_server => 'hkp://pgp.mit.edu:' + } + end + it 'fails' do + expect { subject.call }.to raise_error(/does not match/) + end + end + context "url ending with a dot" do + let :params do + { + :key_server => 'hkp://pgp.mit.edu.' + } + end + it 'fails' do + expect { subject.call }.to raise_error(/does not match/) + end + end + context "url begin with a dash" do + let(:params) do{ + :key_server => "hkp://-pgp.mit.edu", + } end + it 'fails' do + expect { subject.call }.to raise_error(/does not match/) + end + end + context 'invalid key' do + let :title do + 'Out of rum. Why? Why are we out of rum?' + end + it 'fails' do + expect { subject.call }.to raise_error(/does not match/) + end + end + + context 'invalid source' do + let :params do { + :key_source => 'afp://puppetlabs.com/key.gpg', + } end + it 'fails' do + expect { subject.call }.to raise_error(/does not match/) + end + end + + context 'invalid content' do + let :params do { + :key_content => [], + } end + it 'fails' do + expect { subject.call }.to raise_error(/is not a string/) + end + end + + context 'invalid server' do + let :params do { + :key_server => 'two bottles of rum', + } end + it 'fails' do + expect { subject.call }.to raise_error(/does not match/) + end + end + + context 'invalid keyserver_options' do + let :params do { + :key_options => {}, + } end + it 'fails' do + expect { subject.call }.to raise_error(/is not a string/) + end + end + + context 'invalid ensure' do + let :params do + { + :ensure => 'foo', + } + end + it 'fails' do + expect { subject.call }.to raise_error(/does not match/) + end + end + + describe 'duplication' do + context 'two apt::key resources for same key, different titles' do + let :pre_condition do + "apt::key { 'duplicate': key => '#{title}', }" + end + + it 'contains two apt::key resources' do + should contain_apt__key('duplicate').with({ + :key => title, + :ensure => 'present', + }) + should contain_apt__key(title).with({ + :id => title, + :ensure => 'present', + }) + end + + it 'contains only a single apt_key' do + should contain_apt_key('duplicate').with({ + :id => title, + :ensure => 'present', + :source => nil, + :server => nil, + :content => nil, + :keyserver_options => nil, + }) + should_not contain_apt_key(title) + end + end + + context 'two apt::key resources, different ensure' do + let :pre_condition do + "apt::key { 'duplicate': key => '#{title}', ensure => 'absent', }" + end + it 'informs the user of the impossibility' do + expect { subject.call }.to raise_error(/already ensured as absent/) + end + end + end + end +end diff --git a/puphpet/puppet/modules/apt/spec/defines/key_spec.rb b/puphpet/puppet/modules/apt/spec/defines/key_spec.rb index 7ac1d28..d4a85a4 100644 --- a/puphpet/puppet/modules/apt/spec/defines/key_spec.rb +++ b/puphpet/puppet/modules/apt/spec/defines/key_spec.rb @@ -1,7 +1,12 @@ require 'spec_helper' -describe 'apt::key', :type => :define do - let(:facts) { { :lsbdistid => 'Debian' } } +describe 'apt::key' do + let :pre_condition do + 'class { "apt": }' + end + + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version, } } + GPG_KEY_ID = '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30' let :title do @@ -11,17 +16,17 @@ describe 'normal operation' do describe 'default options' do it 'contains the apt_key' do - should contain_apt_key(title).with({ - :id => title, - :ensure => 'present', - :source => nil, - :server => nil, - :content => nil, - :keyserver_options => nil, + is_expected.to contain_apt_key(title).with({ + :id => title, + :ensure => 'present', + :source => nil, + :server => 'keyserver.ubuntu.com', + :content => nil, + :options => nil, }) end it 'contains the apt_key present anchor' do - should contain_anchor("apt_key #{title} present") + is_expected.to contain_anchor("apt_key #{title} present") end end @@ -31,21 +36,21 @@ end let :params do { - :key => GPG_KEY_ID, + :id => GPG_KEY_ID, } end it 'contains the apt_key' do - should contain_apt_key(title).with({ - :id => GPG_KEY_ID, - :ensure => 'present', - :source => nil, - :server => nil, - :content => nil, - :keyserver_options => nil, + is_expected.to contain_apt_key(title).with({ + :id => GPG_KEY_ID, + :ensure => 'present', + :source => nil, + :server => 'keyserver.ubuntu.com', + :content => nil, + :options => nil, }) end it 'contains the apt_key present anchor' do - should contain_anchor("apt_key #{GPG_KEY_ID} present") + is_expected.to contain_anchor("apt_key #{GPG_KEY_ID} present") end end @@ -55,49 +60,49 @@ } end it 'contains the apt_key' do - should contain_apt_key(title).with({ - :id => title, - :ensure => 'absent', - :source => nil, - :server => nil, - :content => nil, - :keyserver_options => nil, + is_expected.to contain_apt_key(title).with({ + :id => title, + :ensure => 'absent', + :source => nil, + :server => 'keyserver.ubuntu.com', + :content => nil, + :keyserver => nil, }) end it 'contains the apt_key absent anchor' do - should contain_anchor("apt_key #{title} absent") + is_expected.to contain_anchor("apt_key #{title} absent") end end describe 'set a bunch of things!' do let :params do { - :key_content => 'GPG key content', - :key_source => 'http://apt.puppetlabs.com/pubkey.gpg', - :key_server => 'pgp.mit.edu', - :key_options => 'debug', + :content => 'GPG key content', + :source => 'http://apt.puppetlabs.com/pubkey.gpg', + :server => 'pgp.mit.edu', + :options => 'debug', } end it 'contains the apt_key' do - should contain_apt_key(title).with({ - :id => title, - :ensure => 'present', - :source => 'http://apt.puppetlabs.com/pubkey.gpg', - :server => 'pgp.mit.edu', - :content => params[:key_content], - :keyserver_options => 'debug', + is_expected.to contain_apt_key(title).with({ + :id => title, + :ensure => 'present', + :source => 'http://apt.puppetlabs.com/pubkey.gpg', + :server => 'pgp.mit.edu', + :content => params[:content], + :options => 'debug', }) end it 'contains the apt_key present anchor' do - should contain_anchor("apt_key #{title} present") + is_expected.to contain_anchor("apt_key #{title} present") end end context "domain with dash" do let(:params) do{ - :key_server => 'p-gp.m-it.edu', + :server => 'p-gp.m-it.edu', } end it 'contains the apt_key' do - should contain_apt_key(title).with({ + is_expected.to contain_apt_key(title).with({ :id => title, :server => 'p-gp.m-it.edu', }) @@ -107,11 +112,11 @@ context "url" do let :params do { - :key_server => 'hkp://pgp.mit.edu', + :server => 'hkp://pgp.mit.edu', } end it 'contains the apt_key' do - should contain_apt_key(title).with({ + is_expected.to contain_apt_key(title).with({ :id => title, :server => 'hkp://pgp.mit.edu', }) @@ -120,11 +125,11 @@ context "url with port number" do let :params do { - :key_server => 'hkp://pgp.mit.edu:80', + :server => 'hkp://pgp.mit.edu:80', } end it 'contains the apt_key' do - should contain_apt_key(title).with({ + is_expected.to contain_apt_key(title).with({ :id => title, :server => 'hkp://pgp.mit.edu:80', }) @@ -135,86 +140,86 @@ describe 'validation' do context "domain begin with dash" do let(:params) do{ - :key_server => '-pgp.mit.edu', + :server => '-pgp.mit.edu', } end it 'fails' do - expect { subject } .to raise_error(/does not match/) + expect { subject.call } .to raise_error(/does not match/) end end context "domain begin with dot" do let(:params) do{ - :key_server => '.pgp.mit.edu', + :server => '.pgp.mit.edu', } end it 'fails' do - expect { subject } .to raise_error(/does not match/) + expect { subject.call } .to raise_error(/does not match/) end end context "domain end with dot" do let(:params) do{ - :key_server => "pgp.mit.edu.", + :server => "pgp.mit.edu.", } end it 'fails' do - expect { subject } .to raise_error(/does not match/) + expect { subject.call } .to raise_error(/does not match/) end end context "exceed character url" do let :params do { - :key_server => 'hkp://pgpiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.mit.edu' + :server => 'hkp://pgpiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii.mit.edu' } end it 'fails' do - expect { subject }.to raise_error(/does not match/) + expect { subject.call }.to raise_error(/does not match/) end end context "incorrect port number url" do let :params do { - :key_server => 'hkp://pgp.mit.edu:8008080' + :server => 'hkp://pgp.mit.edu:8008080' } end it 'fails' do - expect { subject }.to raise_error(/does not match/) + expect { subject.call }.to raise_error(/does not match/) end end context "incorrect protocol for url" do let :params do { - :key_server => 'abc://pgp.mit.edu:80' + :server => 'abc://pgp.mit.edu:80' } end it 'fails' do - expect { subject }.to raise_error(/does not match/) + expect { subject.call }.to raise_error(/does not match/) end end context "missing port number url" do let :params do { - :key_server => 'hkp://pgp.mit.edu:' + :server => 'hkp://pgp.mit.edu:' } end it 'fails' do - expect { subject }.to raise_error(/does not match/) + expect { subject.call }.to raise_error(/does not match/) end end context "url ending with a dot" do let :params do { - :key_server => 'hkp://pgp.mit.edu.' + :server => 'hkp://pgp.mit.edu.' } end it 'fails' do - expect { subject }.to raise_error(/does not match/) + expect { subject.call }.to raise_error(/does not match/) end end context "url begin with a dash" do let(:params) do{ - :key_server => "hkp://-pgp.mit.edu", + :server => "hkp://-pgp.mit.edu", } end it 'fails' do - expect { subject }.to raise_error(/does not match/) + expect { subject.call }.to raise_error(/does not match/) end end context 'invalid key' do @@ -222,43 +227,43 @@ 'Out of rum. Why? Why are we out of rum?' end it 'fails' do - expect { subject }.to raise_error(/does not match/) + expect { subject.call }.to raise_error(/does not match/) end end context 'invalid source' do let :params do { - :key_source => 'afp://puppetlabs.com/key.gpg', + :source => 'afp://puppetlabs.com/key.gpg', } end it 'fails' do - expect { subject }.to raise_error(/does not match/) + expect { subject.call }.to raise_error(/does not match/) end end context 'invalid content' do let :params do { - :key_content => [], + :content => [], } end it 'fails' do - expect { subject }.to raise_error(/is not a string/) + expect { subject.call }.to raise_error(/is not a string/) end end context 'invalid server' do let :params do { - :key_server => 'two bottles of rum', + :server => 'two bottles of rum', } end it 'fails' do - expect { subject }.to raise_error(/does not match/) + expect { subject.call }.to raise_error(/does not match/) end end - context 'invalid keyserver_options' do + context 'invalid options' do let :params do { - :key_options => {}, + :options => {}, } end it 'fails' do - expect { subject }.to raise_error(/is not a string/) + expect { subject.call }.to raise_error(/is not a string/) end end @@ -269,46 +274,48 @@ } end it 'fails' do - expect { subject }.to raise_error(/does not match/) + expect { subject.call }.to raise_error(/does not match/) end end describe 'duplication' do context 'two apt::key resources for same key, different titles' do let :pre_condition do - "apt::key { 'duplicate': key => '#{title}', }" + "class { 'apt': } + apt::key { 'duplicate': id => '#{title}', }" end it 'contains two apt::key resources' do - should contain_apt__key('duplicate').with({ - :key => title, + is_expected.to contain_apt__key('duplicate').with({ + :id => title, :ensure => 'present', }) - should contain_apt__key(title).with({ - :key => title, + is_expected.to contain_apt__key(title).with({ + :id => title, :ensure => 'present', }) end it 'contains only a single apt_key' do - should contain_apt_key('duplicate').with({ - :id => title, - :ensure => 'present', - :source => nil, - :server => nil, - :content => nil, - :keyserver_options => nil, + is_expected.to contain_apt_key('duplicate').with({ + :id => title, + :ensure => 'present', + :source => nil, + :server => 'keyserver.ubuntu.com', + :content => nil, + :options => nil, }) - should_not contain_apt_key(title) + is_expected.not_to contain_apt_key(title) end end context 'two apt::key resources, different ensure' do let :pre_condition do - "apt::key { 'duplicate': key => '#{title}', ensure => 'absent', }" + "class { 'apt': } + apt::key { 'duplicate': id => '#{title}', ensure => 'absent', }" end it 'informs the user of the impossibility' do - expect { subject }.to raise_error(/already ensured as absent/) + expect { subject.call }.to raise_error(/already ensured as absent/) end end end diff --git a/puphpet/puppet/modules/apt/spec/defines/pin_spec.rb b/puphpet/puppet/modules/apt/spec/defines/pin_spec.rb index 23ebd59..9fb28c6 100644 --- a/puphpet/puppet/modules/apt/spec/defines/pin_spec.rb +++ b/puphpet/puppet/modules/apt/spec/defines/pin_spec.rb @@ -1,18 +1,14 @@ require 'spec_helper' describe 'apt::pin', :type => :define do - let(:facts) { { :lsbdistid => 'Debian' } } + let :pre_condition do + 'class { "apt": }' + end + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version, } } let(:title) { 'my_pin' } context 'defaults' do - it { is_expected.to contain_file("my_pin.pref").with_content(/Explanation: : my_pin\nPackage: \*\nPin: release a=my_pin\nPin-Priority: 0\n/)} - it { is_expected.to contain_file("my_pin.pref").with({ - 'ensure' => 'present', - 'path' => '/etc/apt/preferences.d/my_pin.pref', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - }) - } + it { is_expected.to contain_apt__setting("pref-my_pin").with_content(/Explanation: : my_pin\nPackage: \*\nPin: release a=my_pin\nPin-Priority: 0\n/)} + it { is_expected.to contain_apt__setting("pref-my_pin") } end context 'set version' do @@ -22,15 +18,8 @@ 'version' => '1', } end - it { is_expected.to contain_file("my_pin.pref").with_content(/Explanation: : my_pin\nPackage: vim\nPin: version 1\nPin-Priority: 0\n/)} - it { is_expected.to contain_file("my_pin.pref").with({ - 'ensure' => 'present', - 'path' => '/etc/apt/preferences.d/my_pin.pref', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - }) - } + it { is_expected.to contain_apt__setting("pref-my_pin").with_content(/Explanation: : my_pin\nPackage: vim\nPin: version 1\nPin-Priority: 0\n/)} + it { is_expected.to contain_apt__setting("pref-my_pin") } end context 'set origin' do @@ -40,15 +29,8 @@ 'origin' => 'test', } end - it { is_expected.to contain_file("my_pin.pref").with_content(/Explanation: : my_pin\nPackage: vim\nPin: origin test\nPin-Priority: 0\n/)} - it { is_expected.to contain_file("my_pin.pref").with({ - 'ensure' => 'present', - 'path' => '/etc/apt/preferences.d/my_pin.pref', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - }) - } + it { is_expected.to contain_apt__setting("pref-my_pin").with_content(/Explanation: : my_pin\nPackage: vim\nPin: origin test\nPin-Priority: 0\n/)} + it { is_expected.to contain_apt__setting("pref-my_pin") } end context 'not defaults' do @@ -65,13 +47,9 @@ 'priority' => 10, } end - it { is_expected.to contain_file("my_pin.pref").with_content(/Explanation: foo\nPackage: \*\nPin: release a=1, n=bar, v=2, c=baz, o=foobar, l=foobaz\nPin-Priority: 10\n/) } - it { is_expected.to contain_file("my_pin.pref").with({ - 'ensure' => 'present', - 'path' => '/etc/apt/preferences.d/99-my_pin.pref', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', + it { is_expected.to contain_apt__setting("pref-my_pin").with_content(/Explanation: foo\nPackage: \*\nPin: release a=1, n=bar, v=2, c=baz, o=foobar, l=foobaz\nPin-Priority: 10\n/) } + it { is_expected.to contain_apt__setting("pref-my_pin").with({ + 'priority' => 99, }) } end @@ -82,7 +60,7 @@ 'ensure' => 'absent' } end - it { is_expected.to contain_file("my_pin.pref").with({ + it { is_expected.to contain_apt__setting("pref-my_pin").with({ 'ensure' => 'absent', }) } @@ -90,7 +68,7 @@ context 'bad characters' do let(:title) { 'such bad && wow!' } - it { is_expected.to contain_file("such__bad____wow_.pref") } + it { is_expected.to contain_apt__setting("pref-such__bad____wow_") } end describe 'validation' do @@ -102,7 +80,7 @@ end it do expect { - should compile + subject.call }.to raise_error(Puppet::Error, /Only integers are allowed/) end end @@ -115,7 +93,7 @@ end it do expect { - should compile + subject.call }.to raise_error(Puppet::Error, /parameter version cannot be used in general form/) end end @@ -129,7 +107,7 @@ end it do expect { - should compile + subject.call }.to raise_error(Puppet::Error, /parameters release and origin are mutually exclusive/) end end @@ -144,7 +122,7 @@ end it do expect { - should compile + subject.call }.to raise_error(Puppet::Error, /parameters release, origin, and version are mutually exclusive/) end end @@ -159,7 +137,7 @@ end it do expect { - should compile + subject.call }.to raise_error(Puppet::Error, /parameters release, origin, and version are mutually exclusive/) end end diff --git a/puphpet/puppet/modules/apt/spec/defines/ppa_spec.rb b/puphpet/puppet/modules/apt/spec/defines/ppa_spec.rb index 866d323..b7a2f6c 100644 --- a/puphpet/puppet/modules/apt/spec/defines/ppa_spec.rb +++ b/puphpet/puppet/modules/apt/spec/defines/ppa_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' -describe 'apt::ppa', :type => :define do +describe 'apt::ppa' do + let :pre_condition do + 'class { "apt": }' + end describe 'defaults' do - let :pre_condition do - 'class { "apt": }' - end let :facts do { :lsbdistrelease => '11.04', @@ -12,24 +12,26 @@ :operatingsystem => 'Ubuntu', :osfamily => 'Debian', :lsbdistid => 'Ubuntu', + :puppetversion => Puppet.version, } end let(:title) { 'ppa:needs/such.substitution/wow' } - it { is_expected.to contain_package('python-software-properties') } - it { is_expected.to contain_exec('add-apt-repository-ppa:needs/such.substitution/wow').that_notifies('Exec[apt_update]').with({ - 'environment' => [], - 'command' => '/usr/bin/add-apt-repository -y ppa:needs/such.substitution/wow', - 'unless' => '/usr/bin/test -s /etc/apt/sources.list.d/needs-such_substitution-wow-natty.list', - 'user' => 'root', - 'logoutput' => 'on_failure', + it { is_expected.to_not contain_package('python-software-properties') } + it { is_expected.to contain_exec('add-apt-repository-ppa:needs/such.substitution/wow').that_notifies('Class[Apt::Update]').with({ + :environment => [], + :command => '/usr/bin/add-apt-repository -y ppa:needs/such.substitution/wow', + :unless => '/usr/bin/test -s /etc/apt/sources.list.d/needs-such_substitution-wow-natty.list', + :user => 'root', + :logoutput => 'on_failure', }) } + end - it { is_expected.to contain_file('/etc/apt/sources.list.d/needs-such_substitution-wow-natty.list').that_requires('Exec[add-apt-repository-ppa:needs/such.substitution/wow]').with({ - 'ensure' => 'file', - }) - } + describe 'ppa depending on ppa, MODULES-1156' do + let :pre_condition do + 'class { "apt": }' + end end describe 'package_name => software-properties-common' do @@ -38,7 +40,8 @@ end let :params do { - :package_name => 'software-properties-common' + :package_name => 'software-properties-common', + :package_manage => true, } end let :facts do @@ -48,12 +51,13 @@ :operatingsystem => 'Ubuntu', :osfamily => 'Debian', :lsbdistid => 'Ubuntu', + :puppetversion => Puppet.version, } end let(:title) { 'ppa:needs/such.substitution/wow' } it { is_expected.to contain_package('software-properties-common') } - it { is_expected.to contain_exec('add-apt-repository-ppa:needs/such.substitution/wow').that_notifies('Exec[apt_update]').with({ + it { is_expected.to contain_exec('add-apt-repository-ppa:needs/such.substitution/wow').that_notifies('Class[Apt::Update]').with({ 'environment' => [], 'command' => '/usr/bin/add-apt-repository -y ppa:needs/such.substitution/wow', 'unless' => '/usr/bin/test -s /etc/apt/sources.list.d/needs-such_substitution-wow-natty.list', @@ -79,6 +83,7 @@ :operatingsystem => 'Ubuntu', :osfamily => 'Debian', :lsbdistid => 'Ubuntu', + :puppetversion => Puppet.version, } end let :params do @@ -89,7 +94,7 @@ let(:title) { 'ppa:needs/such.substitution/wow' } it { is_expected.to_not contain_package('python-software-properties') } - it { is_expected.to contain_exec('add-apt-repository-ppa:needs/such.substitution/wow').that_notifies('Exec[apt_update]').with({ + it { is_expected.to contain_exec('add-apt-repository-ppa:needs/such.substitution/wow').that_notifies('Class[Apt::Update]').with({ 'environment' => [], 'command' => '/usr/bin/add-apt-repository -y ppa:needs/such.substitution/wow', 'unless' => '/usr/bin/test -s /etc/apt/sources.list.d/needs-such_substitution-wow-natty.list', @@ -106,7 +111,9 @@ describe 'apt included, no proxy' do let :pre_condition do - 'class { "apt": }' + 'class { "apt": } + apt::ppa { "ppa:foo2": } + ' end let :facts do { @@ -115,33 +122,68 @@ :operatingsystem => 'Ubuntu', :lsbdistid => 'Ubuntu', :osfamily => 'Debian', + :puppetversion => Puppet.version, } end let :params do { - 'options' => '', + :options => '', + :package_manage => true, + :require => 'Apt::Ppa[ppa:foo2]', } end let(:title) { 'ppa:foo' } + it { is_expected.to compile.with_all_deps } it { is_expected.to contain_package('software-properties-common') } - it { is_expected.to contain_exec('add-apt-repository-ppa:foo').that_notifies('Exec[apt_update]').with({ - 'environment' => [], - 'command' => '/usr/bin/add-apt-repository ppa:foo', - 'unless' => '/usr/bin/test -s /etc/apt/sources.list.d/foo-trusty.list', - 'user' => 'root', - 'logoutput' => 'on_failure', + it { is_expected.to contain_exec('add-apt-repository-ppa:foo').that_notifies('Class[Apt::Update]').with({ + :environment => [], + :command => '/usr/bin/add-apt-repository ppa:foo', + :unless => '/usr/bin/test -s /etc/apt/sources.list.d/foo-trusty.list', + :user => 'root', + :logoutput => 'on_failure', }) } + end - it { is_expected.to contain_file('/etc/apt/sources.list.d/foo-trusty.list').that_requires('Exec[add-apt-repository-ppa:foo]').with({ - 'ensure' => 'file', + describe 'apt included, proxy host' do + let :pre_condition do + 'class { "apt": + proxy => { "host" => "localhost" }, + }' + end + let :facts do + { + :lsbdistrelease => '14.04', + :lsbdistcodename => 'trusty', + :operatingsystem => 'Ubuntu', + :lsbdistid => 'Ubuntu', + :osfamily => 'Debian', + :puppetversion => Puppet.version, + } + end + let :params do + { + 'options' => '', + 'package_manage' => true, + } + end + let(:title) { 'ppa:foo' } + it { is_expected.to contain_package('software-properties-common') } + it { is_expected.to contain_exec('add-apt-repository-ppa:foo').that_notifies('Class[Apt::Update]').with({ + :environment => ['http_proxy=http://localhost:8080'], + :command => '/usr/bin/add-apt-repository ppa:foo', + :unless => '/usr/bin/test -s /etc/apt/sources.list.d/foo-trusty.list', + :user => 'root', + :logoutput => 'on_failure', }) } end - describe 'apt included, proxy' do + describe 'apt included, proxy host and port' do let :pre_condition do - 'class { "apt": proxy_host => "example.com" }' + 'class { "apt": + proxy => { "host" => "localhost", "port" => 8180 }, + }' end let :facts do { @@ -150,31 +192,65 @@ :operatingsystem => 'Ubuntu', :lsbdistid => 'Ubuntu', :osfamily => 'Debian', + :puppetversion => Puppet.version, } end let :params do { - 'release' => 'lucid', + :options => '', + :package_manage => true, } end let(:title) { 'ppa:foo' } it { is_expected.to contain_package('software-properties-common') } - it { is_expected.to contain_exec('add-apt-repository-ppa:foo').that_notifies('Exec[apt_update]').with({ - 'environment' => ['http_proxy=http://example.com:8080', 'https_proxy=http://example.com:8080'], - 'command' => '/usr/bin/add-apt-repository -y ppa:foo', - 'unless' => '/usr/bin/test -s /etc/apt/sources.list.d/foo-lucid.list', - 'user' => 'root', - 'logoutput' => 'on_failure', + it { is_expected.to contain_exec('add-apt-repository-ppa:foo').that_notifies('Class[Apt::Update]').with({ + :environment => ['http_proxy=http://localhost:8180'], + :command => '/usr/bin/add-apt-repository ppa:foo', + :unless => '/usr/bin/test -s /etc/apt/sources.list.d/foo-trusty.list', + :user => 'root', + :logoutput => 'on_failure', }) } + end - it { is_expected.to contain_file('/etc/apt/sources.list.d/foo-lucid.list').that_requires('Exec[add-apt-repository-ppa:foo]').with({ - 'ensure' => 'file', + describe 'apt included, proxy host and port and https' do + let :pre_condition do + 'class { "apt": + proxy => { "host" => "localhost", "port" => 8180, "https" => true }, + }' + end + let :facts do + { + :lsbdistrelease => '14.04', + :lsbdistcodename => 'trusty', + :operatingsystem => 'Ubuntu', + :lsbdistid => 'Ubuntu', + :osfamily => 'Debian', + :puppetversion => Puppet.version, + } + end + let :params do + { + :options => '', + :package_manage => true, + } + end + let(:title) { 'ppa:foo' } + it { is_expected.to contain_package('software-properties-common') } + it { is_expected.to contain_exec('add-apt-repository-ppa:foo').that_notifies('Class[Apt::Update]').with({ + :environment => ['http_proxy=http://localhost:8180', 'https_proxy=https://localhost:8180'], + :command => '/usr/bin/add-apt-repository ppa:foo', + :unless => '/usr/bin/test -s /etc/apt/sources.list.d/foo-trusty.list', + :user => 'root', + :logoutput => 'on_failure', }) } end describe 'ensure absent' do + let :pre_condition do + 'class { "apt": }' + end let :facts do { :lsbdistrelease => '14.04', @@ -182,16 +258,17 @@ :operatingsystem => 'Ubuntu', :lsbdistid => 'Ubuntu', :osfamily => 'Debian', + :puppetversion => Puppet.version, } end let(:title) { 'ppa:foo' } let :params do { - 'ensure' => 'absent' + :ensure => 'absent' } end - it { is_expected.to contain_file('/etc/apt/sources.list.d/foo-trusty.list').that_notifies('Exec[apt_update]').with({ - 'ensure' => 'absent', + it { is_expected.to contain_file('/etc/apt/sources.list.d/foo-trusty.list').that_notifies('Class[Apt::Update]').with({ + :ensure => 'absent', }) } end @@ -204,12 +281,14 @@ :operatingsystem => 'Ubuntu', :lsbdistid => 'Ubuntu', :osfamily => 'Debian', + :lsbdistcodeanme => nil, + :puppetversion => Puppet.version, } end let(:title) { 'ppa:foo' } it do expect { - should compile + subject.call }.to raise_error(Puppet::Error, /lsbdistcodename fact not available: release parameter required/) end end @@ -217,18 +296,19 @@ describe 'not ubuntu' do let :facts do { - :lsbdistrelease => '14.04', - :lsbdistcodename => 'trusty', + :lsbdistrelease => '6.0.7', + :lsbdistcodename => 'wheezy', :operatingsystem => 'Debian', - :lsbdistid => 'Ubuntu', + :lsbdistid => 'debian', :osfamily => 'Debian', + :puppetversion => Puppet.version, } end let(:title) { 'ppa:foo' } it do expect { - should compile - }.to raise_error(Puppet::Error, /apt::ppa is currently supported on Ubuntu only./) + subject.call + }.to raise_error(Puppet::Error, /not currently supported on Debian/) end end end diff --git a/puphpet/puppet/modules/apt/spec/defines/setting_spec.rb b/puphpet/puppet/modules/apt/spec/defines/setting_spec.rb new file mode 100644 index 0000000..a326bdb --- /dev/null +++ b/puphpet/puppet/modules/apt/spec/defines/setting_spec.rb @@ -0,0 +1,115 @@ +require 'spec_helper' + +describe 'apt::setting' do + let(:pre_condition) { 'class { "apt": }' } + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version, } } + let(:title) { 'conf-teddybear' } + + let(:default_params) { { :content => 'di' } } + + describe 'when using the defaults' do + context 'without source or content' do + it do + expect { subject.call }.to raise_error(Puppet::Error, /needs either of /) + end + end + + context 'with title=conf-teddybear ' do + let(:params) { default_params } + it { is_expected.to contain_file('/etc/apt/apt.conf.d/50teddybear').that_notifies('Class[Apt::Update]') } + end + + context 'with title=pref-teddybear' do + let(:title) { 'pref-teddybear' } + let(:params) { default_params } + it { is_expected.to contain_file('/etc/apt/preferences.d/teddybear.pref').that_notifies('Class[Apt::Update]') } + end + + context 'with title=list-teddybear' do + let(:title) { 'list-teddybear' } + let(:params) { default_params } + it { is_expected.to contain_file('/etc/apt/sources.list.d/teddybear.list').that_notifies('Class[Apt::Update]') } + end + + context 'with source' do + let(:params) { { :source => 'puppet:///la/die/dah' } } + it { + is_expected.to contain_file('/etc/apt/apt.conf.d/50teddybear').that_notifies('Class[Apt::Update]').with({ + :ensure => 'file', + :owner => 'root', + :group => 'root', + :mode => '0644', + :source => "#{params[:source]}", + })} + end + + context 'with content' do + let(:params) { default_params } + it { is_expected.to contain_file('/etc/apt/apt.conf.d/50teddybear').that_notifies('Class[Apt::Update]').with({ + :ensure => 'file', + :owner => 'root', + :group => 'root', + :mode => '0644', + :content => "#{params[:content]}", + })} + end + end + + describe 'settings requiring settings, MODULES-769' do + let(:pre_condition) do + 'class { "apt": } + apt::setting { "list-teddybear": content => "foo" } + ' + end + let(:facts) { { :lsbdistid => 'Debian', :osfamily => 'Debian', :lsbdistcodename => 'wheezy', :puppetversion => Puppet.version, } } + let(:title) { 'conf-teddybear' } + let(:default_params) { { :content => 'di' } } + + let(:params) { default_params.merge({ :require => 'Apt::Setting[list-teddybear]' }) } + + it { is_expected.to compile.with_all_deps } + end + + describe 'when trying to pull one over' do + context 'with source and content' do + let(:params) { default_params.merge({ :source => 'la' }) } + it do + expect { subject.call }.to raise_error(Puppet::Error, /cannot have both /) + end + end + + context 'with title=ext-teddybear' do + let(:title) { 'ext-teddybear' } + let(:params) { default_params } + it do + expect { subject.call }.to raise_error(Puppet::Error, /must start with /) + end + end + + context 'with ensure=banana' do + let(:params) { default_params.merge({ :ensure => 'banana' }) } + it do + expect { subject.call }.to raise_error(Puppet::Error, /"banana" does not /) + end + end + + context 'with priority=1.2' do + let(:params) { default_params.merge({ :priority => 1.2 }) } + it do + expect { subject.call }.to raise_error(Puppet::Error, /be an integer /) + end + end + end + + describe 'with priority=100' do + let(:params) { default_params.merge({ :priority => 100 }) } + it { is_expected.to contain_file('/etc/apt/apt.conf.d/100teddybear').that_notifies('Class[Apt::Update]') } + end + + describe 'with ensure=absent' do + let(:params) { default_params.merge({ :ensure => 'absent' }) } + it { is_expected.to contain_file('/etc/apt/apt.conf.d/50teddybear').that_notifies('Class[Apt::Update]').with({ + :ensure => 'absent', + })} + end +end diff --git a/puphpet/puppet/modules/apt/spec/defines/source_compat_spec.rb b/puphpet/puppet/modules/apt/spec/defines/source_compat_spec.rb new file mode 100644 index 0000000..2e813f3 --- /dev/null +++ b/puphpet/puppet/modules/apt/spec/defines/source_compat_spec.rb @@ -0,0 +1,158 @@ +require 'spec_helper' + +describe 'apt::source', :type => :define do + GPG_KEY_ID = '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30' + + let :title do + 'my_source' + end + + context 'mostly defaults' do + let :facts do + { + :lsbdistid => 'Debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'Debian', + } + end + + let :params do + { + 'include_deb' => false, + 'include_src' => true, + 'location' => 'http://debian.mirror.iweb.ca/debian/', + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with_content(/# my_source\ndeb-src http:\/\/debian\.mirror\.iweb\.ca\/debian\/ wheezy main\n/) + } + end + + context 'no defaults' do + let :facts do + { + :lsbdistid => 'Debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'Debian' + } + end + let :params do + { + 'comment' => 'foo', + 'location' => 'http://debian.mirror.iweb.ca/debian/', + 'release' => 'sid', + 'repos' => 'testing', + 'include_src' => false, + 'required_packages' => 'vim', + 'key' => GPG_KEY_ID, + 'key_server' => 'pgp.mit.edu', + 'key_content' => 'GPG key content', + 'key_source' => 'http://apt.puppetlabs.com/pubkey.gpg', + 'pin' => '10', + 'architecture' => 'x86_64', + 'trusted_source' => true, + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with_content(/# foo\ndeb \[arch=x86_64 trusted=yes\] http:\/\/debian\.mirror\.iweb\.ca\/debian\/ sid testing\n/).without_content(/deb-src/) + } + + it { is_expected.to contain_apt__pin('my_source').that_comes_before('Apt::Setting[list-my_source]').with({ + 'ensure' => 'present', + 'priority' => '10', + 'origin' => 'debian.mirror.iweb.ca', + }) + } + + it { is_expected.to contain_exec("Required packages: 'vim' for my_source").that_comes_before('Apt::Setting[list-my_source]').with({ + 'command' => '/usr/bin/apt-get -y install vim', + 'logoutput' => 'on_failure', + 'refreshonly' => true, + 'tries' => '3', + 'try_sleep' => '1', + }) + } + + it { is_expected.to contain_apt__key("Add key: #{GPG_KEY_ID} from Apt::Source my_source").that_comes_before('Apt::Setting[list-my_source]').with({ + 'ensure' => 'present', + 'id' => GPG_KEY_ID, + 'key_server' => 'pgp.mit.edu', + 'key_content' => 'GPG key content', + 'key_source' => 'http://apt.puppetlabs.com/pubkey.gpg', + }) + } + end + + context 'trusted_source true' do + let :facts do + { + :lsbdistid => 'Debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'Debian' + } + end + let :params do + { + 'include_src' => false, + 'location' => 'http://debian.mirror.iweb.ca/debian/', + 'trusted_source' => true, + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with_content(/# my_source\ndeb \[trusted=yes\] http:\/\/debian\.mirror\.iweb\.ca\/debian\/ wheezy main\n/) } + end + + context 'architecture equals x86_64' do + let :facts do + { + :lsbdistid => 'Debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'Debian' + } + end + let :params do + { + 'location' => 'http://debian.mirror.iweb.ca/debian/', + 'architecture' => 'x86_64', + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with_content(/# my_source\ndeb \[arch=x86_64 \] http:\/\/debian\.mirror\.iweb\.ca\/debian\/ wheezy main\n/) + } + end + + context 'ensure => absent' do + let :facts do + { + :lsbdistid => 'Debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'Debian' + } + end + let :params do + { + 'ensure' => 'absent', + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with({ + 'ensure' => 'absent' + }) + } + end + + describe 'validation' do + context 'no release' do + let :facts do + { + :lsbdistid => 'Debian', + :osfamily => 'Debian' + } + end + + it do + expect { subject.call }.to raise_error(Puppet::Error, /lsbdistcodename fact not available: release parameter required/) + end + end + end +end diff --git a/puphpet/puppet/modules/apt/spec/defines/source_spec.rb b/puphpet/puppet/modules/apt/spec/defines/source_spec.rb index 8ca7f8e..8a2cfcc 100644 --- a/puphpet/puppet/modules/apt/spec/defines/source_spec.rb +++ b/puphpet/puppet/modules/apt/spec/defines/source_spec.rb @@ -1,165 +1,347 @@ require 'spec_helper' -describe 'apt::source', :type => :define do +describe 'apt::source' do GPG_KEY_ID = '47B320EB4C7C375AA9DAE1A01054B7A24BD6EC30' + let :pre_condition do + 'class { "apt": }' + end let :title do 'my_source' end - context 'mostly defaults' do + context 'defaults' do + context 'without location' do + let :facts do + { + :lsbdistid => 'Debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'Debian', + :puppetversion => Puppet.version, + } + end + it do + expect { + subject.call + }.to raise_error(Puppet::Error, /source entry without specifying a location/) + end + end + context 'with location' do + let :facts do + { + :lsbdistid => 'Debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'Debian', + :puppetversion => Puppet.version, + } + end + let(:params) { { :location => 'hello.there', } } + + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).without_content(/# my_source\ndeb-src hello.there wheezy main\n/) + } + end + end + + describe 'no defaults' do let :facts do { :lsbdistid => 'Debian', :lsbdistcodename => 'wheezy', - :osfamily => 'Debian' + :osfamily => 'Debian', + :puppetversion => Puppet.version, + } + end + + context 'with complex pin' do + let :params do + { + :location => 'hello.there', + :pin => { 'release' => 'wishwash', + 'explanation' => 'wishwash', + 'priority' => 1001, }, + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).with_content(/hello.there wheezy main\n/) + } + + it { is_expected.to contain_file('/etc/apt/sources.list.d/my_source.list').that_notifies('Class[Apt::Update]')} + + it { is_expected.to contain_apt__pin('my_source').that_comes_before('Apt::Setting[list-my_source]').with({ + :ensure => 'present', + :priority => 1001, + :explanation => 'wishwash', + :release => 'wishwash', + }) } end + context 'with simple key' do + let :params do + { + :comment => 'foo', + :location => 'http://debian.mirror.iweb.ca/debian/', + :release => 'sid', + :repos => 'testing', + :key => GPG_KEY_ID, + :pin => '10', + :architecture => 'x86_64', + :allow_unsigned => true, + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).with_content(/# foo\ndeb \[arch=x86_64 trusted=yes\] http:\/\/debian\.mirror\.iweb\.ca\/debian\/ sid testing\n/).without_content(/deb-src/) + } + + it { is_expected.to contain_apt__pin('my_source').that_comes_before('Apt::Setting[list-my_source]').with({ + :ensure => 'present', + :priority => '10', + :origin => 'debian.mirror.iweb.ca', + }) + } + + it { is_expected.to contain_apt__key("Add key: #{GPG_KEY_ID} from Apt::Source my_source").that_comes_before('Apt::Setting[list-my_source]').with({ + :ensure => 'present', + :id => GPG_KEY_ID, + }) + } + end + + context 'with complex key' do + let :params do + { + :comment => 'foo', + :location => 'http://debian.mirror.iweb.ca/debian/', + :release => 'sid', + :repos => 'testing', + :key => { 'id' => GPG_KEY_ID, 'server' => 'pgp.mit.edu', + 'content' => 'GPG key content', + 'source' => 'http://apt.puppetlabs.com/pubkey.gpg',}, + :pin => '10', + :architecture => 'x86_64', + :allow_unsigned => true, + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).with_content(/# foo\ndeb \[arch=x86_64 trusted=yes\] http:\/\/debian\.mirror\.iweb\.ca\/debian\/ sid testing\n/).without_content(/deb-src/) + } + + it { is_expected.to contain_apt__pin('my_source').that_comes_before('Apt::Setting[list-my_source]').with({ + :ensure => 'present', + :priority => '10', + :origin => 'debian.mirror.iweb.ca', + }) + } + + it { is_expected.to contain_apt__key("Add key: #{GPG_KEY_ID} from Apt::Source my_source").that_comes_before('Apt::Setting[list-my_source]').with({ + :ensure => 'present', + :id => GPG_KEY_ID, + :server => 'pgp.mit.edu', + :content => 'GPG key content', + :source => 'http://apt.puppetlabs.com/pubkey.gpg', + }) + } + end + + context 'with simple key' do + let :params do + { + :comment => 'foo', + :location => 'http://debian.mirror.iweb.ca/debian/', + :release => 'sid', + :repos => 'testing', + :key => GPG_KEY_ID, + :pin => '10', + :architecture => 'x86_64', + :allow_unsigned => true, + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).with_content(/# foo\ndeb \[arch=x86_64 trusted=yes\] http:\/\/debian\.mirror\.iweb\.ca\/debian\/ sid testing\n/).without_content(/deb-src/) + } + + it { is_expected.to contain_apt__pin('my_source').that_comes_before('Apt::Setting[list-my_source]').with({ + :ensure => 'present', + :priority => '10', + :origin => 'debian.mirror.iweb.ca', + }) + } + + it { is_expected.to contain_apt__key("Add key: #{GPG_KEY_ID} from Apt::Source my_source").that_comes_before('Apt::Setting[list-my_source]').with({ + :ensure => 'present', + :id => GPG_KEY_ID, + }) + } + end + end + + context 'allow_unsigned true' do + let :facts do + { + :lsbdistid => 'Debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'Debian', + :puppetversion => Puppet.version, + } + end let :params do { - 'include_deb' => false, + :location => 'hello.there', + :allow_unsigned => true, } end - it { is_expected.to contain_file('my_source.list').that_notifies('Exec[apt_update]').with({ - 'ensure' => 'present', - 'path' => '/etc/apt/sources.list.d/my_source.list', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - }).with_content(/# my_source\ndeb-src wheezy main\n/) + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).with_content(/# my_source\ndeb \[trusted=yes\] hello.there wheezy main\n/) } end - context 'no defaults' do + context 'architecture equals x86_64' do let :facts do { :lsbdistid => 'Debian', :lsbdistcodename => 'wheezy', - :osfamily => 'Debian' + :osfamily => 'Debian', + :puppetversion => Puppet.version, } end let :params do { - 'comment' => 'foo', - 'location' => 'http://debian.mirror.iweb.ca/debian/', - 'release' => 'sid', - 'repos' => 'testing', - 'include_src' => false, - 'required_packages' => 'vim', - 'key' => GPG_KEY_ID, - 'key_server' => 'pgp.mit.edu', - 'key_content' => 'GPG key content', - 'key_source' => 'http://apt.puppetlabs.com/pubkey.gpg', - 'pin' => '10', - 'architecture' => 'x86_64', - 'trusted_source' => true, - } - end - - it { is_expected.to contain_file('my_source.list').that_notifies('Exec[apt_update]').with({ - 'ensure' => 'present', - 'path' => '/etc/apt/sources.list.d/my_source.list', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - }).with_content(/# foo\ndeb \[arch=x86_64 trusted=yes\] http:\/\/debian\.mirror\.iweb\.ca\/debian\/ sid testing\n/).without_content(/deb-src/) - } + :location => 'hello.there', + :include => {'deb' => false, 'src' => true,}, + :architecture => 'x86_64', + } + end - it { is_expected.to contain_apt__pin('my_source').that_comes_before('File[my_source.list]').with({ - 'ensure' => 'present', - 'priority' => '10', - 'origin' => 'debian.mirror.iweb.ca', - }) + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).with_content(/# my_source\ndeb-src \[arch=x86_64 \] hello.there wheezy main\n/) } + end - it { is_expected.to contain_exec("Required packages: 'vim' for my_source").that_comes_before('Exec[apt_update]').that_subscribes_to('File[my_source.list]').with({ - 'command' => '/usr/bin/apt-get -y install vim', - 'logoutput' => 'on_failure', - 'refreshonly' => true, - 'tries' => '3', - 'try_sleep' => '1', - }) + context 'include_src => true' do + let :facts do + { + :lsbdistid => 'Debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'Debian', + :puppetversion => Puppet.version, + } + end + let :params do + { + :location => 'hello.there', + :include_src => true, + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).with_content(/# my_source\ndeb hello.there wheezy main\ndeb-src hello.there wheezy main\n/) } + end - it { is_expected.to contain_apt__key("Add key: #{GPG_KEY_ID} from Apt::Source my_source").that_comes_before('File[my_source.list]').with({ - 'ensure' => 'present', - 'key' => GPG_KEY_ID, - 'key_server' => 'pgp.mit.edu', - 'key_content' => 'GPG key content', - 'key_source' => 'http://apt.puppetlabs.com/pubkey.gpg', - }) + context 'include_deb => false' do + let :facts do + { + :lsbdistid => 'debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'debian', + :puppetversion => Puppet.version, + } + end + let :params do + { + :location => 'hello.there', + :include_deb => false, + } + end + + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).without_content(/deb-src hello.there wheezy main\n/) } + it { is_expected.to contain_apt__setting('list-my_source').without_content(/deb hello.there wheezy main\n/) } end - context 'trusted_source true' do + context 'include_src => true and include_deb => false' do let :facts do { - :lsbdistid => 'Debian', + :lsbdistid => 'debian', :lsbdistcodename => 'wheezy', - :osfamily => 'Debian' + :osfamily => 'debian', + :puppetversion => Puppet.version, } end let :params do { - 'include_src' => false, - 'trusted_source' => true, + :location => 'hello.there', + :include_deb => false, + :include_src => true, } end - it { is_expected.to contain_file('my_source.list').that_notifies('Exec[apt_update]').with({ - 'ensure' => 'present', - 'path' => '/etc/apt/sources.list.d/my_source.list', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - }).with_content(/# my_source\ndeb \[trusted=yes\] wheezy main\n/) + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).with_content(/deb-src hello.there wheezy main\n/) } + it { is_expected.to contain_apt__setting('list-my_source').without_content(/deb hello.there wheezy main\n/) } end - context 'architecture equals x86_64' do + context 'include precedence' do let :facts do { - :lsbdistid => 'Debian', + :lsbdistid => 'debian', :lsbdistcodename => 'wheezy', - :osfamily => 'Debian' + :osfamily => 'debian', + :puppetversion => Puppet.version, } end let :params do { - 'include_deb' => false, - 'architecture' => 'x86_64', + :location => 'hello.there', + :include_deb => true, + :include_src => false, + :include => { 'deb' => false, 'src' => true }, } end - it { is_expected.to contain_file('my_source.list').that_notifies('Exec[apt_update]').with({ - 'ensure' => 'present', - 'path' => '/etc/apt/sources.list.d/my_source.list', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - }).with_content(/# my_source\ndeb-src \[arch=x86_64 \] wheezy main\n/) + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'present', + }).with_content(/deb-src hello.there wheezy main\n/) } + it { is_expected.to contain_apt__setting('list-my_source').without_content(/deb hello.there wheezy main\n/) } end - + context 'ensure => absent' do let :facts do { :lsbdistid => 'Debian', :lsbdistcodename => 'wheezy', - :osfamily => 'Debian' + :osfamily => 'Debian', + :puppetversion => Puppet.version, } end let :params do { - 'ensure' => 'absent', + :ensure => 'absent', } end - it { is_expected.to contain_file('my_source.list').that_notifies('Exec[apt_update]').with({ - 'ensure' => 'absent' + it { is_expected.to contain_apt__setting('list-my_source').with({ + :ensure => 'absent' }) } end @@ -169,15 +351,41 @@ let :facts do { :lsbdistid => 'Debian', - :osfamily => 'Debian' + :osfamily => 'Debian', + :puppetversion => Puppet.version, } end + let(:params) { { :location => 'hello.there', } } it do expect { - should compile + subject.call }.to raise_error(Puppet::Error, /lsbdistcodename fact not available: release parameter required/) end end + + context 'invalid pin' do + let :facts do + { + :lsbdistid => 'Debian', + :lsbdistcodename => 'wheezy', + :osfamily => 'Debian', + :puppetversion => Puppet.version, + } + end + let :params do + { + :location => 'hello.there', + :pin => true, + } + end + + it do + expect { + subject.call + }.to raise_error(Puppet::Error, /invalid value for pin/) + end + end + end end diff --git a/puphpet/puppet/modules/apt/spec/spec_helper_acceptance.rb b/puphpet/puppet/modules/apt/spec/spec_helper_acceptance.rb index 6b2aa5d..409ce68 100644 --- a/puphpet/puppet/modules/apt/spec/spec_helper_acceptance.rb +++ b/puphpet/puppet/modules/apt/spec/spec_helper_acceptance.rb @@ -1,17 +1,7 @@ require 'beaker-rspec' +require 'beaker/puppet_install_helper' -# Install Puppet -unless ENV['RS_PROVISION'] == 'no' - # This will install the latest available package on el and deb based - # systems fail on windows and osx, and install via gem on other *nixes - foss_opts = { :default_action => 'gem_install' } - - if default.is_pe?; then install_pe; else install_puppet( foss_opts ); end - - hosts.each do |host| - on host, "mkdir -p #{host['distmoduledir']}" - end -end +run_puppet_install_helper UNSUPPORTED_PLATFORMS = ['RedHat','Suse','windows','AIX','Solaris'] @@ -28,7 +18,7 @@ hosts.each do |host| copy_module_to(host, :source => proj_root, :module_name => 'apt') shell("/bin/touch #{default['puppetpath']}/hiera.yaml") - on host, puppet('module install puppetlabs-stdlib --version 2.2.1'), { :acceptable_exit_codes => [0,1] } + on host, puppet('module install puppetlabs-stdlib --version 4.5.0'), { :acceptable_exit_codes => [0,1] } end end end diff --git a/puphpet/puppet/modules/apt/spec/unit/facter/apt_has_updates_spec.rb b/puphpet/puppet/modules/apt/spec/unit/facter/apt_has_updates_spec.rb index f8a3f20..b6eee26 100644 --- a/puphpet/puppet/modules/apt/spec/unit/facter/apt_has_updates_spec.rb +++ b/puphpet/puppet/modules/apt/spec/unit/facter/apt_has_updates_spec.rb @@ -8,7 +8,7 @@ before { Facter.fact(:osfamily).expects(:value).at_least(1).returns 'RedHat' } - it { should be_nil } + it { is_expected.to be_nil } end describe 'on Debian based distro missing update-notifier-common' do @@ -17,7 +17,7 @@ File.stubs(:executable?) # Stub all other calls File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns false } - it { should be_nil } + it { is_expected.to be_nil } end describe 'on Debian based distro with broken packages' do @@ -28,7 +28,7 @@ File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns true Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>&1').returns "E: Error: BrokenCount > 0" } - it { should be_nil } + it { is_expected.to be_nil } end describe 'on Debian based distro with unknown error with semicolons' do @@ -39,7 +39,7 @@ File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns true Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>&1').returns "E: Unknown Error: 'This error contains something that could be parsed like 4;3' (10)" } - it { should be_nil } + it { is_expected.to be_nil } end describe 'on Debian based distro' do @@ -50,7 +50,7 @@ File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns true Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>&1').returns "4;3" } - it { should be true } + it { is_expected.to be true } end end diff --git a/puphpet/puppet/modules/apt/spec/unit/facter/apt_package_updates_spec.rb b/puphpet/puppet/modules/apt/spec/unit/facter/apt_package_updates_spec.rb index 5c7a624..08bfb42 100644 --- a/puphpet/puppet/modules/apt/spec/unit/facter/apt_package_updates_spec.rb +++ b/puphpet/puppet/modules/apt/spec/unit/facter/apt_package_updates_spec.rb @@ -8,7 +8,7 @@ before { Facter.fact(:apt_has_updates).stubs(:value).returns false } - it { should be nil } + it { is_expected.to be nil } end describe 'when apt has updates' do @@ -22,9 +22,9 @@ } it { if Facter.version < '2.0.0' - should == 'puppet-common,linux-generic,linux-image-generic' + is_expected.to eq('puppet-common,linux-generic,linux-image-generic') else - should == ['puppet-common', 'linux-generic', 'linux-image-generic'] + is_expected.to eq(['puppet-common', 'linux-generic', 'linux-image-generic']) end } end diff --git a/puphpet/puppet/modules/apt/spec/unit/facter/apt_reboot_required_spec.rb b/puphpet/puppet/modules/apt/spec/unit/facter/apt_reboot_required_spec.rb new file mode 100644 index 0000000..ed6efd0 --- /dev/null +++ b/puphpet/puppet/modules/apt/spec/unit/facter/apt_reboot_required_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe 'apt_reboot_required fact' do + subject { Facter.fact(:apt_reboot_required).value } + after(:each) { Facter.clear } + + describe 'if a reboot is required' do + before { + Facter.fact(:osfamily).expects(:value).at_least(1).returns 'Debian' + File.stubs(:file?).returns true + File.expects(:file?).at_least(1).with('/var/run/reboot-required').returns true + } + it { is_expected.to eq true } + end + + describe 'if a reboot is not required' do + before { + Facter.fact(:osfamily).expects(:value).at_least(1).returns 'Debian' + File.stubs(:file?).returns true + File.expects(:file?).at_least(1).with('/var/run/reboot-required').returns false + } + it { is_expected.to eq false } + end + +end diff --git a/puphpet/puppet/modules/apt/spec/unit/facter/apt_security_updates_spec.rb b/puphpet/puppet/modules/apt/spec/unit/facter/apt_security_updates_spec.rb index 4bc760f..83aa6ff 100644 --- a/puphpet/puppet/modules/apt/spec/unit/facter/apt_security_updates_spec.rb +++ b/puphpet/puppet/modules/apt/spec/unit/facter/apt_security_updates_spec.rb @@ -8,7 +8,7 @@ before { Facter.fact(:apt_has_updates).stubs(:value).returns false } - it { should be nil } + it { is_expected.to be nil } end describe 'when apt has security updates' do @@ -19,7 +19,7 @@ File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns true Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>&1').returns "14;7" } - it { should == 7 } + it { is_expected.to eq(7) } end end diff --git a/puphpet/puppet/modules/apt/spec/unit/facter/apt_update_last_success_spec.rb b/puphpet/puppet/modules/apt/spec/unit/facter/apt_update_last_success_spec.rb index 08774cd..cb32a5e 100644 --- a/puphpet/puppet/modules/apt/spec/unit/facter/apt_update_last_success_spec.rb +++ b/puphpet/puppet/modules/apt/spec/unit/facter/apt_update_last_success_spec.rb @@ -10,7 +10,7 @@ File.stubs(:exists?).returns false } it 'should have a value of -1' do - should == -1 + is_expected.to eq(-1) end end @@ -21,7 +21,7 @@ File.stubs(:mtime).returns 1407660561 } it 'should have the value of the mtime of the file' do - should == 1407660561 + is_expected.to eq(1407660561) end end diff --git a/puphpet/puppet/modules/apt/spec/unit/facter/apt_updates_spec.rb b/puphpet/puppet/modules/apt/spec/unit/facter/apt_updates_spec.rb index 7e9b77f..781ffd6 100644 --- a/puphpet/puppet/modules/apt/spec/unit/facter/apt_updates_spec.rb +++ b/puphpet/puppet/modules/apt/spec/unit/facter/apt_updates_spec.rb @@ -8,7 +8,7 @@ before { Facter.fact(:apt_has_updates).stubs(:value).returns false } - it { should be nil } + it { is_expected.to be nil } end describe 'when apt has updates' do @@ -19,7 +19,7 @@ File.expects(:executable?).with('/usr/lib/update-notifier/apt-check').returns true Facter::Util::Resolution.expects(:exec).with('/usr/lib/update-notifier/apt-check 2>&1').returns "14;7" } - it { should == 14 } + it { is_expected.to eq(14) } end end diff --git a/puphpet/puppet/modules/apt/spec/unit/puppet/type/apt_key_spec.rb b/puphpet/puppet/modules/apt/spec/unit/puppet/type/apt_key_spec.rb index e8a5462..e412b50 100644 --- a/puphpet/puppet/modules/apt/spec/unit/puppet/type/apt_key_spec.rb +++ b/puphpet/puppet/modules/apt/spec/unit/puppet/type/apt_key_spec.rb @@ -7,23 +7,23 @@ :id => '4BD6EC30' )} it 'id is set' do - resource[:id].should eq '4BD6EC30' + expect(resource[:id]).to eq '4BD6EC30' end it 'name is set to id' do - resource[:name].should eq '4BD6EC30' + expect(resource[:name]).to eq '4BD6EC30' end it 'keyserver is default' do - resource[:server].should eq :'keyserver.ubuntu.com' + expect(resource[:server]).to eq :'keyserver.ubuntu.com' end it 'source is not set' do - resource[:source].should eq nil + expect(resource[:source]).to eq nil end it 'content is not set' do - resource[:content].should eq nil + expect(resource[:content]).to eq nil end end @@ -32,7 +32,7 @@ :id => '4bd6ec30' )} it 'id is set' do - resource[:id].should eq '4BD6EC30' + expect(resource[:id]).to eq '4BD6EC30' end end @@ -41,7 +41,7 @@ :id => 'FFFFFFFF4BD6EC30' )} it 'id is set' do - resource[:id].should eq 'FFFFFFFF4BD6EC30' + expect(resource[:id]).to eq 'FFFFFFFF4BD6EC30' end end @@ -50,7 +50,7 @@ :id => '0x4BD6EC30' )} it 'id is set' do - resource[:id].should eq '4BD6EC30' + expect(resource[:id]).to eq '4BD6EC30' end end @@ -59,7 +59,7 @@ :id => '0x4bd6ec30' )} it 'id is set' do - resource[:id].should eq '4BD6EC30' + expect(resource[:id]).to eq '4BD6EC30' end end @@ -68,7 +68,7 @@ :id => '0xFFFFFFFF4BD6EC30' )} it 'id is set' do - resource[:id].should eq 'FFFFFFFF4BD6EC30' + expect(resource[:id]).to eq 'FFFFFFFF4BD6EC30' end end @@ -79,7 +79,7 @@ )} it 'source is set to the URL' do - resource[:source].should eq 'http://apt.puppetlabs.com/pubkey.gpg' + expect(resource[:source]).to eq 'http://apt.puppetlabs.com/pubkey.gpg' end end @@ -90,7 +90,7 @@ )} it 'content is set to the string' do - resource[:content].should eq 'http://apt.puppetlabs.com/pubkey.gpg' + expect(resource[:content]).to eq 'http://apt.puppetlabs.com/pubkey.gpg' end end @@ -101,7 +101,7 @@ )} it 'keyserver is set to Debian' do - resource[:server].should eq 'http://keyring.debian.org' + expect(resource[:server]).to eq 'http://keyring.debian.org' end end diff --git a/puphpet/puppet/modules/apt/templates/10periodic.erb b/puphpet/puppet/modules/apt/templates/10periodic.erb deleted file mode 100644 index 43caed9..0000000 --- a/puphpet/puppet/modules/apt/templates/10periodic.erb +++ /dev/null @@ -1,15 +0,0 @@ -APT::Periodic::Enable "<%= @enable %>"; -APT::Periodic::BackUpArchiveInterval "<%= @backup_interval %>"; -APT::Periodic::BackUpLevel "<%= @backup_level %>"; -APT::Periodic::MaxAge "<%= @max_age %>"; -APT::Periodic::MinAge "<%= @min_age %>"; -APT::Periodic::MaxSize "<%= @max_size %>"; -APT::Periodic::Update-Package-Lists "<%= @update %>"; -APT::Periodic::Download-Upgradeable-Packages "<%= @download %>"; -APT::Periodic::Download-Upgradeable-Packages-Debdelta "<%= @download_delta %>"; -APT::Periodic::Unattended-Upgrade "<%= @upgrade %>"; -APT::Periodic::AutocleanInterval "<%= @autoclean %>"; -APT::Periodic::Verbose "<%= @verbose %>"; -<%- unless @randomsleep.nil? -%> -APT::Periodic::RandomSleep "<%= @randomsleep %>"; -<%- end -%> diff --git a/puphpet/puppet/modules/apt/templates/50unattended-upgrades.erb b/puphpet/puppet/modules/apt/templates/50unattended-upgrades.erb deleted file mode 100644 index 47ecb34..0000000 --- a/puphpet/puppet/modules/apt/templates/50unattended-upgrades.erb +++ /dev/null @@ -1,62 +0,0 @@ -// Automatically upgrade packages from these (origin:archive) pairs -<%- if @legacy_origin -%> -Unattended-Upgrade::Allowed-Origins { -<%- else -%> -Unattended-Upgrade::Origins-Pattern { -<%- end -%> -<% @origins.each do |origin| -%> - "<%= origin %>"; -<% end -%> -}; - -// List of packages to not update -Unattended-Upgrade::Package-Blacklist { -<% @blacklist.each do |package| -%> - "<%= package %>"; -<% end -%> -}; - -// This option allows you to control if on a unclean dpkg exit -// unattended-upgrades will automatically run -// dpkg --force-confold --configure -a -// The default is true, to ensure updates keep getting installed -Unattended-Upgrade::AutoFixInterruptedDpkg "<%= @auto_fix %>"; - -// Split the upgrade into the smallest possible chunks so that -// they can be interrupted with SIGUSR1. This makes the upgrade -// a bit slower but it has the benefit that shutdown while a upgrade -// is running is possible (with a small delay) -Unattended-Upgrade::MinimalSteps "<%= @minimal_steps %>"; - -// Install all unattended-upgrades when the machine is shuting down -// instead of doing it in the background while the machine is running -// This will (obviously) make shutdown slower -Unattended-Upgrade::InstallOnShutdown "<%= @install_on_shutdown %>"; - -<% if @mail_to != "NONE" %> -// Send email to this address for problems or packages upgrades -// If empty or unset then no email is sent, make sure that you -// have a working mail setup on your system. A package that provides -// 'mailx' must be installed. -Unattended-Upgrade::Mail "<%= @mail_to %>"; -<% end %> - -<% if @mail_to != "NONE" %> -// Set this value to "true" to get emails only on errors. Default -// is to always send a mail if Unattended-Upgrade::Mail is set -Unattended-Upgrade::MailOnlyOnError "<%= @mail_only_on_error %>"; -<% end %> - -// Do automatic removal of new unused dependencies after the upgrade -// (equivalent to apt-get autoremove) -Unattended-Upgrade::Remove-Unused-Dependencies "<%= @remove_unused %>"; - -// Automatically reboot *WITHOUT CONFIRMATION* if a -// the file /var/run/reboot-required is found after the upgrade -Unattended-Upgrade::Automatic-Reboot "<%= @auto_reboot %>"; - -<% if @dl_limit != "NONE" %> -// Use apt bandwidth limit feature, this example limits the download -// speed to 70kb/sec -Acquire::http::Dl-Limit "<%= @dl_limit %>"; -<% end %> diff --git a/puphpet/puppet/modules/apt/templates/_conf_header.erb b/puphpet/puppet/modules/apt/templates/_conf_header.erb new file mode 100644 index 0000000..bfa365e --- /dev/null +++ b/puphpet/puppet/modules/apt/templates/_conf_header.erb @@ -0,0 +1 @@ +// This file is managed by Puppet. DO NOT EDIT. diff --git a/puphpet/puppet/modules/apt/templates/pin.pref.erb b/puphpet/puppet/modules/apt/templates/pin.pref.erb index 26b2516..76936d7 100644 --- a/puphpet/puppet/modules/apt/templates/pin.pref.erb +++ b/puphpet/puppet/modules/apt/templates/pin.pref.erb @@ -15,7 +15,7 @@ elsif @origin.length > 0 @pin = "origin #{@origin}" end -%> -Explanation: <%= @explanation %> +Explanation: <%= @_explanation %> Package: <%= @packages_string %> Pin: <%= @pin %> Pin-Priority: <%= @priority %> diff --git a/puphpet/puppet/modules/apt/templates/progressbar.erb b/puphpet/puppet/modules/apt/templates/progressbar.erb deleted file mode 100644 index d3d9278..0000000 --- a/puphpet/puppet/modules/apt/templates/progressbar.erb +++ /dev/null @@ -1 +0,0 @@ -Dpkg::Progress-Fancy "1"; diff --git a/puphpet/puppet/modules/apt/templates/proxy.erb b/puphpet/puppet/modules/apt/templates/proxy.erb index accb0cc..670e3a7 100644 --- a/puphpet/puppet/modules/apt/templates/proxy.erb +++ b/puphpet/puppet/modules/apt/templates/proxy.erb @@ -1 +1,4 @@ -Acquire::http::Proxy "http://<%= @proxy_host %>:<%= @proxy_port %>"; +Acquire::http::proxy "http://<%= @_proxy['host'] %>:<%= @_proxy['port'] %>/"; +<%- if @_proxy['https'] %> +Acquire::https::proxy "https://<%= @_proxy['host'] %>:<%= @_proxy['port'] %>/"; +<%- end -%> diff --git a/puphpet/puppet/modules/apt/templates/release.erb b/puphpet/puppet/modules/apt/templates/release.erb deleted file mode 100644 index 08760af..0000000 --- a/puphpet/puppet/modules/apt/templates/release.erb +++ /dev/null @@ -1 +0,0 @@ -APT::Default-Release "<%= @release_id %>"; diff --git a/puphpet/puppet/modules/apt/templates/source.list.erb b/puphpet/puppet/modules/apt/templates/source.list.erb index b50be8d..fe7f559 100644 --- a/puphpet/puppet/modules/apt/templates/source.list.erb +++ b/puphpet/puppet/modules/apt/templates/source.list.erb @@ -1,11 +1,11 @@ # <%= @comment %> -<%- if @include_deb then -%> -deb <%- if @architecture or @trusted_source -%> -[<%- if @architecture %>arch=<%= @architecture %> <% end %><% if @trusted_source %>trusted=yes<% end -%> -] <%- end %><%= @location %> <%= @release_real %> <%= @repos %> +<%- if @_include['deb'] then -%> +deb <%- if @architecture or @_allow_unsigned -%> +[<%- if @architecture %>arch=<%= @architecture %> <% end %><% if @_allow_unsigned %>trusted=yes<% end -%> +] <%- end %><%= @location %> <%= @_release %> <%= @repos %> <%- end -%> -<%- if @include_src then -%> -deb-src <%- if @architecture or @trusted_source -%> -[<%- if @architecture %>arch=<%= @architecture %> <% end %><% if @trusted_source %>trusted=yes<% end -%> -] <%- end %><%= @location %> <%= @release_real %> <%= @repos %> +<%- if @_include['src'] then -%> +deb-src <%- if @architecture or @_allow_unsigned -%> +[<%- if @architecture %>arch=<%= @architecture %> <% end %><% if @_allow_unsigned %>trusted=yes<% end -%> +] <%- end %><%= @location %> <%= @_release %> <%= @repos %> <%- end -%> diff --git a/puphpet/puppet/modules/apt/templates/unauth.erb b/puphpet/puppet/modules/apt/templates/unauth.erb deleted file mode 100644 index 77edd28..0000000 --- a/puphpet/puppet/modules/apt/templates/unauth.erb +++ /dev/null @@ -1 +0,0 @@ -APT::Get::AllowUnauthenticated 1; diff --git a/puphpet/puppet/modules/apt/tests/builddep.pp b/puphpet/puppet/modules/apt/tests/builddep.pp deleted file mode 100644 index 8b4f796..0000000 --- a/puphpet/puppet/modules/apt/tests/builddep.pp +++ /dev/null @@ -1,2 +0,0 @@ -class { 'apt': } -apt::builddep{ 'glusterfs-server': } diff --git a/puphpet/puppet/modules/apt/tests/debian/testing.pp b/puphpet/puppet/modules/apt/tests/debian/testing.pp deleted file mode 100644 index 8245b3a..0000000 --- a/puphpet/puppet/modules/apt/tests/debian/testing.pp +++ /dev/null @@ -1,2 +0,0 @@ -class { 'apt': } -class { 'apt::debian::testing': } diff --git a/puphpet/puppet/modules/apt/tests/debian/unstable.pp b/puphpet/puppet/modules/apt/tests/debian/unstable.pp deleted file mode 100644 index 8605179..0000000 --- a/puphpet/puppet/modules/apt/tests/debian/unstable.pp +++ /dev/null @@ -1,2 +0,0 @@ -class { 'apt': } -class { 'apt::debian::unstable': } diff --git a/puphpet/puppet/modules/apt/tests/force.pp b/puphpet/puppet/modules/apt/tests/force.pp deleted file mode 100644 index 59ad8f1..0000000 --- a/puphpet/puppet/modules/apt/tests/force.pp +++ /dev/null @@ -1,17 +0,0 @@ -# force.pp - -# force a package from a specific release -apt::force { 'package1': - release => 'backports', -} - -# force a package to be a specific version -apt::force { 'package2': - version => '1.0.0-1', -} - -# force a package from a specific release to be a specific version -apt::force { 'package3': - release => 'sid', - version => '2.0.0-1', -} diff --git a/puphpet/puppet/modules/apt/tests/init.pp b/puphpet/puppet/modules/apt/tests/init.pp deleted file mode 100644 index abc75af..0000000 --- a/puphpet/puppet/modules/apt/tests/init.pp +++ /dev/null @@ -1 +0,0 @@ -class { 'apt': } diff --git a/puphpet/puppet/modules/apt/tests/key.pp b/puphpet/puppet/modules/apt/tests/key.pp deleted file mode 100644 index 79e0e1b..0000000 --- a/puphpet/puppet/modules/apt/tests/key.pp +++ /dev/null @@ -1,6 +0,0 @@ -# Declare Apt key for apt.puppetlabs.com source -apt::key { 'puppetlabs': - key => '4BD6EC30', - key_server => 'pgp.mit.edu', - key_options => 'http-proxy="http://proxyuser:proxypass@example.org:3128"', -} diff --git a/puphpet/puppet/modules/apt/tests/params.pp b/puphpet/puppet/modules/apt/tests/params.pp deleted file mode 100644 index 5ddf3c6..0000000 --- a/puphpet/puppet/modules/apt/tests/params.pp +++ /dev/null @@ -1 +0,0 @@ -include apt::params diff --git a/puphpet/puppet/modules/apt/tests/release.pp b/puphpet/puppet/modules/apt/tests/release.pp deleted file mode 100644 index 823f586..0000000 --- a/puphpet/puppet/modules/apt/tests/release.pp +++ /dev/null @@ -1,4 +0,0 @@ -class { 'apt': } -class { 'apt::release': - release_id => 'karmic' -} diff --git a/puphpet/puppet/modules/apt/tests/source.pp b/puphpet/puppet/modules/apt/tests/source.pp deleted file mode 100644 index 823b37b..0000000 --- a/puphpet/puppet/modules/apt/tests/source.pp +++ /dev/null @@ -1,29 +0,0 @@ -# Declare the apt class to manage /etc/apt/sources.list and /etc/sources.list.d -class { 'apt': } - -# Install the puppetlabs apt source -# Release is automatically obtained from lsbdistcodename fact if available. -apt::source { 'puppetlabs': - location => 'http://apt.puppetlabs.com', - repos => 'main', - key => '4BD6EC30', - key_server => 'pgp.mit.edu', -} - -# test two sources with the same key -apt::source { 'debian_testing': - location => 'http://debian.mirror.iweb.ca/debian/', - release => 'testing', - repos => 'main contrib non-free', - key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', - key_server => 'subkeys.pgp.net', - pin => '-10', -} -apt::source { 'debian_unstable': - location => 'http://debian.mirror.iweb.ca/debian/', - release => 'unstable', - repos => 'main contrib non-free', - key => 'A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553', - key_server => 'subkeys.pgp.net', - pin => '-10', -} diff --git a/puphpet/puppet/modules/apt/tests/unattended_upgrades.pp b/puphpet/puppet/modules/apt/tests/unattended_upgrades.pp deleted file mode 100644 index 3b9b49e..0000000 --- a/puphpet/puppet/modules/apt/tests/unattended_upgrades.pp +++ /dev/null @@ -1 +0,0 @@ -include apt::unattended_upgrades diff --git a/puphpet/puppet/modules/beanstalkd/manifests/init.pp b/puphpet/puppet/modules/beanstalkd/manifests/init.pp index 5437ee8..1c8a773 100644 --- a/puphpet/puppet/modules/beanstalkd/manifests/init.pp +++ b/puphpet/puppet/modules/beanstalkd/manifests/init.pp @@ -40,7 +40,7 @@ $configtemplate = "${module_name}/debian/beanstalkd.erb" $hasstatus = 'true' $restart = '/etc/init.d/beanstalkd restart' - $mode = 0755 + $mode = '0755' } centos, redhat: { $defaultpackagename = 'beanstalkd' @@ -50,7 +50,7 @@ $configtemplate = "${module_name}/redhat/beanstalkd_sysconfig.erb" $hasstatus = 'true' $restart = '/etc/init.d/beanstalkd restart' - $mode = 0644 + $mode = '0644' } # TODO: add more OS support! default: { diff --git a/puphpet/puppet/modules/beanstalkd/spec/fixtures/modules/beanstalkd/manifests/init.pp b/puphpet/puppet/modules/beanstalkd/spec/fixtures/modules/beanstalkd/manifests/init.pp index 5437ee8..1c8a773 100644 --- a/puphpet/puppet/modules/beanstalkd/spec/fixtures/modules/beanstalkd/manifests/init.pp +++ b/puphpet/puppet/modules/beanstalkd/spec/fixtures/modules/beanstalkd/manifests/init.pp @@ -40,7 +40,7 @@ $configtemplate = "${module_name}/debian/beanstalkd.erb" $hasstatus = 'true' $restart = '/etc/init.d/beanstalkd restart' - $mode = 0755 + $mode = '0755' } centos, redhat: { $defaultpackagename = 'beanstalkd' @@ -50,7 +50,7 @@ $configtemplate = "${module_name}/redhat/beanstalkd_sysconfig.erb" $hasstatus = 'true' $restart = '/etc/init.d/beanstalkd restart' - $mode = 0644 + $mode = '0644' } # TODO: add more OS support! default: { diff --git a/puphpet/puppet/modules/blackfire/.fixtures.yml b/puphpet/puppet/modules/blackfire/.fixtures.yml index 5812f37..59001f6 100644 --- a/puphpet/puppet/modules/blackfire/.fixtures.yml +++ b/puphpet/puppet/modules/blackfire/.fixtures.yml @@ -1,7 +1,7 @@ fixtures: forge: "https//forge.puppetlabs.com" repositories: - apt: "git://github.com/puppetlabs/puppetlabs-apt.git" + apt: 'https://github.com/puppetlabs/puppetlabs-apt.git' inifile: "git://github.com/puppetlabs/puppetlabs-inifile.git" stdlib: "git://github.com/puppetlabs/puppetlabs-stdlib.git" symlinks: diff --git a/puphpet/puppet/modules/blackfire/.gitignore b/puphpet/puppet/modules/blackfire/.gitignore new file mode 100644 index 0000000..794e490 --- /dev/null +++ b/puphpet/puppet/modules/blackfire/.gitignore @@ -0,0 +1,5 @@ +.idea/ +.vagrant/ +pkg/ +Gemfile.lock +log diff --git a/puphpet/puppet/modules/blackfire/.travis.yml b/puphpet/puppet/modules/blackfire/.travis.yml index f3288ef..6e38a43 100644 --- a/puphpet/puppet/modules/blackfire/.travis.yml +++ b/puphpet/puppet/modules/blackfire/.travis.yml @@ -2,6 +2,9 @@ sudo: false language: ruby bundler_args: --no-deployment +before_script: + - puppet --version + script: - bundle exec rake validate - bundle exec rake lint @@ -10,12 +13,22 @@ script: matrix: fast_finish: true include: - - rvm: 2.1.5 - env: PUPPET_VERSION="~> 3.7.5" DEPLOY="yes" + - rvm: 2.2.3 + env: PUPPET_VERSION="~> 4.3" + - rvm: 2.2.3 + env: PUPPET_VERSION="~> 4.2.0" + - rvm: 2.2.3 + env: PUPPET_VERSION="~> 4.1.0" + - rvm: 2.2.3 + env: PUPPET_VERSION="~> 4.0.0" + - rvm: 2.1.7 + env: PUPPET_VERSION="~> 3.8" DEPLOY="yes" + - rvm: 2.0.0 + env: PUPPET_VERSION="~> 3.7.0" - rvm: 1.9.3 env: PUPPET_VERSION="~> 3.4.0" - rvm: 1.9.3 - env: PUPPET_VERSION="~> 3.0" + env: PUPPET_VERSION="~> 3.0.0" before_deploy: - bundle exec puppet module build diff --git a/puphpet/puppet/modules/blackfire/CHANGELOG.md b/puphpet/puppet/modules/blackfire/CHANGELOG.md new file mode 100644 index 0000000..95df11f --- /dev/null +++ b/puphpet/puppet/modules/blackfire/CHANGELOG.md @@ -0,0 +1,24 @@ +# 1.4.0 (2015.12.05) + +* Puppet 4 compatibility +* Handle log_level passed as a string (@jtreminio) +* Added apt to manifest as a dependency + + +# 1.3.0 (2015.06.01) + +* Added support for puppetlabs-apt 2.0 +* Added support for Debian 8 +* CentOS bugfixes + + +# 1.2.2 (2015.04.08) + +* Bugfixes + + +# 1.2.1 (2015.04.06) + +* Fixed refreshes +* Debian 6 support + diff --git a/puphpet/puppet/modules/blackfire/Gemfile b/puphpet/puppet/modules/blackfire/Gemfile index 91ce6ea..0f1f8b7 100644 --- a/puphpet/puppet/modules/blackfire/Gemfile +++ b/puphpet/puppet/modules/blackfire/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' -puppetversion = ENV.key?('PUPPET_VERSION') ? ENV['PUPPET_VERSION'] : ['>= 3.4'] +puppetversion = ENV.key?('PUPPET_VERSION') ? ENV['PUPPET_VERSION'] : ['~> 3.7.0'] gem 'puppet', puppetversion gem 'puppetlabs_spec_helper', '>= 0.1.0' gem 'puppet-lint', '>= 0.3.2' diff --git a/puphpet/puppet/modules/blackfire/LICENSE b/puphpet/puppet/modules/blackfire/LICENSE new file mode 100644 index 0000000..8a8fe67 --- /dev/null +++ b/puphpet/puppet/modules/blackfire/LICENSE @@ -0,0 +1,13 @@ +Copyright 2015 Sergey Novikov + +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. diff --git a/puphpet/puppet/modules/blackfire/README.md b/puphpet/puppet/modules/blackfire/README.md index 9e25de9..c54b23e 100644 --- a/puphpet/puppet/modules/blackfire/README.md +++ b/puphpet/puppet/modules/blackfire/README.md @@ -1,6 +1,8 @@ Puppet module for installing, configuring and managing [Blackfire PHP profiler](https://blackfire.io/). [![Build Status](https://travis-ci.org/s12v/puppet-blackfire.svg?branch=master)](https://travis-ci.org/s12v/puppet-blackfire) +[![Puppet Forge](https://img.shields.io/puppetforge/dt/s12v/blackfire.svg)](https://forge.puppetlabs.com/s12v/blackfire) + # blackfire @@ -10,7 +12,7 @@ This module is currently tested on: - Ubuntu (14.04, 12.04, 10.04) - Centos (7.0, 6.6) - - Debian (7.8, 6.0) + - Debian (8.0, 7.8, 6.0) It may work on other distros. @@ -104,10 +106,10 @@ class { 'blackfire': - `bundle exec rake validate` - Check syntax of Ruby files and call :syntax and :metadata / Validate manifests, templates, and ruby files - `bundle exec rake lint` - Check puppet manifests with puppet-lint / Run puppet-lint - - `bundle exec rake spec` - Run spec tests in a clean fixtures directory + - `bundle exec rake spec` - Run spec tests in a clean fixtures directory (using [spec_helper](https://github.com/puppetlabs/puppetlabs_spec_helper)) ### Acceptance testing with beaker - - `bundle exec rake beaker_nodes` - List available beaker nodesets + - `bundle exec rake beaker_nodes` - List available [beaker](https://github.com/puppetlabs/beaker) nodesets - `BLACKFIRE_SERVER_ID=... BLACKFIRE_SERVER_TOKEN=... bundle exec rake beaker` - Run beaker acceptance tests (default nodeset) - `BEAKER_set=centos-70-x64 BLACKFIRE_SERVER_ID=... BLACKFIRE_SERVER_TOKEN=... bundle exec rake beaker` - Run beaker acceptance tests for the nodeset diff --git a/puphpet/puppet/modules/blackfire/manifests/agent.pp b/puphpet/puppet/modules/blackfire/manifests/agent.pp index cb63783..d9feaa5 100644 --- a/puphpet/puppet/modules/blackfire/manifests/agent.pp +++ b/puphpet/puppet/modules/blackfire/manifests/agent.pp @@ -19,6 +19,8 @@ } $params = merge($default_params, $::blackfire::agent) + $log_level = 0 + $params['log_level'] + validate_bool($params['manage']) validate_string($params['version']) validate_bool($params['manage_service']) @@ -27,8 +29,8 @@ validate_string($params['server_token']) validate_string($params['socket']) validate_string($params['log_file']) - if $params['log_level'] < 1 or $params['log_level'] > 4 { - fail 'Ivalid log_level. Valid levels are: 4 - debug, 3 - info, 2 - warning, 1 - error' + if $log_level < 1 or $log_level > 4 { + fail 'Invalid log_level. Valid levels are: 4 - debug, 3 - info, 2 - warning, 1 - error' } validate_string($params['collector']) validate_string($params['http_proxy']) diff --git a/puphpet/puppet/modules/blackfire/manifests/init.pp b/puphpet/puppet/modules/blackfire/manifests/init.pp index c78116c..524de61 100644 --- a/puphpet/puppet/modules/blackfire/manifests/init.pp +++ b/puphpet/puppet/modules/blackfire/manifests/init.pp @@ -9,7 +9,7 @@ validate_string($server_id) validate_string($server_token) - if !$server_id or !$server_token { + if empty($server_id) or empty($server_token) { fail 'server_id and server_token are required. Get them on https://blackfire.io/account/agents' } validate_hash($agent) diff --git a/puphpet/puppet/modules/blackfire/manifests/php.pp b/puphpet/puppet/modules/blackfire/manifests/php.pp index a835995..8789cf0 100644 --- a/puphpet/puppet/modules/blackfire/manifests/php.pp +++ b/puphpet/puppet/modules/blackfire/manifests/php.pp @@ -12,6 +12,7 @@ agent_timeout => 0.25, } $params = merge($default_params, $::blackfire::params) + $log_level = 0 + $params['log_level'] validate_bool($params['manage']) validate_string($params['version']) @@ -19,7 +20,7 @@ validate_string($params['server_token']) validate_string($params['socket']) validate_string($params['log_file']) - if $params['log_level'] < 1 or $params['log_level'] > 4 { + if $log_level < 1 or $log_level > 4 { fail 'Ivalid log_level. Valid levels are: 4 - debug, 3 - info, 2 - warning, 1 - error' } diff --git a/puphpet/puppet/modules/blackfire/manifests/php/config.pp b/puphpet/puppet/modules/blackfire/manifests/php/config.pp index 79114ba..f4f9a84 100644 --- a/puphpet/puppet/modules/blackfire/manifests/php/config.pp +++ b/puphpet/puppet/modules/blackfire/manifests/php/config.pp @@ -5,7 +5,7 @@ 'debian': { if ( ($::operatingsystem == 'Ubuntu' and $::operatingsystemrelease < '14.04') - or ($::operatingsystem == 'Debian' and $::operatingsystemmajrelease < 7) + or ($::operatingsystem == 'Debian' and $::operatingsystemmajrelease < '7') ) { $ini_path = '/etc/php5/conf.d/blackfire.ini' } else { diff --git a/puphpet/puppet/modules/blackfire/manifests/repo.pp b/puphpet/puppet/modules/blackfire/manifests/repo.pp index d9a6719..fa31027 100644 --- a/puphpet/puppet/modules/blackfire/manifests/repo.pp +++ b/puphpet/puppet/modules/blackfire/manifests/repo.pp @@ -8,13 +8,30 @@ class { 'apt': } } - apt::source { 'blackfire': - location => 'http://packages.blackfire.io/debian', - release => 'any', - repos => 'main', - key => 'D59097AB', - key_source => 'https://packagecloud.io/gpg.key', - include_src => false, + if defined('apt::setting') { + # apt >= 2.0 + apt::source { 'blackfire': + location => 'http://packages.blackfire.io/debian', + release => 'any', + repos => 'main', + key => { + source => 'https://packagecloud.io/gpg.key', + id => '418A7F2FB0E1E6E7EABF6FE8C2E73424D59097AB', + }, + } + # trigger apt-get update before installing packages + Exec['apt_update'] -> Class['::blackfire::agent'] + Exec['apt_update'] -> Class['::blackfire::php'] + } else { + # apt >= 1.x < 2.0 + apt::source { 'blackfire': + location => 'http://packages.blackfire.io/debian', + release => 'any', + repos => 'main', + key => 'D59097AB', + key_source => 'https://packagecloud.io/gpg.key', + include_src => false, + } } } 'redhat': { diff --git a/puphpet/puppet/modules/blackfire/metadata.json b/puphpet/puppet/modules/blackfire/metadata.json index ad0486c..1b27aa6 100644 --- a/puphpet/puppet/modules/blackfire/metadata.json +++ b/puphpet/puppet/modules/blackfire/metadata.json @@ -1,6 +1,6 @@ { "name": "s12v-blackfire", - "version": "1.2.2", + "version": "1.4.0", "author": "Sergey Novikov", "summary": "Module for managing and configuring Blackfire PHP Profiler", "license": "Apache-2.0", @@ -14,11 +14,11 @@ }, { "name": "puppetlabs/inifile", - "version_requirement": ">= 1.0.0" + "version_requirement": ">= 1.0.0 < 2.0.0" }, { "name": "puppetlabs/stdlib", - "version_requirement": ">= 4.0.0" + "version_requirement": ">= 4.0.0 < 5.0.0" } ], "requirements": [ @@ -28,7 +28,7 @@ }, { "name": "puppet", - "version_requirement": "3.x" + "version_requirement": ">=3.0.0 <5.0.0" } ], "operatingsystem_support": [ @@ -42,7 +42,7 @@ }, { "operatingsystem": "Debian", - "operatingsystemrelease": [ "6", "7" ] + "operatingsystemrelease": [ "6", "7", "8" ] }, { "operatingsystem": "Ubuntu", diff --git a/puphpet/puppet/modules/blackfire/spec/acceptance/agent_spec.rb b/puphpet/puppet/modules/blackfire/spec/acceptance/agent_spec.rb index d61419d..99432c2 100644 --- a/puphpet/puppet/modules/blackfire/spec/acceptance/agent_spec.rb +++ b/puphpet/puppet/modules/blackfire/spec/acceptance/agent_spec.rb @@ -7,16 +7,16 @@ describe 'running puppet code' do - it 'server_id and server_token are not empty' do + it 'requires server_id and server_token' do expect(server_id).not_to be_empty expect(server_token).not_to be_empty end - it 'we have copied the puppet module' do + it 'contains the puppet module' do shell("ls #{default['distmoduledir']}/blackfire/metadata.json", {:acceptable_exit_codes => 0}) end - it 'should work with no errors' do + it 'should work without errors' do pp = <<-EOS class { 'blackfire': server_id => '#{server_id}', @@ -45,11 +45,11 @@ class { 'blackfire': it { should be_running } end - it 'CLI is installed' do + it 'contains blackfire CLI' do shell("blackfire version", {:acceptable_exit_codes => 0}) end - it 'PHP extension is installed' do + it 'contains PHP extension' do shell("php -m | grep blackfire", {:acceptable_exit_codes => 0}) end diff --git a/puphpet/puppet/modules/blackfire/spec/acceptance/nodesets/debian-80-x64.yml b/puphpet/puppet/modules/blackfire/spec/acceptance/nodesets/debian-80-x64.yml new file mode 100644 index 0000000..50d0c92 --- /dev/null +++ b/puphpet/puppet/modules/blackfire/spec/acceptance/nodesets/debian-80-x64.yml @@ -0,0 +1,11 @@ +HOSTS: + debian-80-x64: + roles: + - master + platform: debian-8-amd64 + box: debian/jessie64 + hypervisor: vagrant +CONFIG: + log_level: verbose + type: foss + php_cli_package: php5-cli diff --git a/puphpet/puppet/modules/blackfire/spec/classes/init_spec.rb b/puphpet/puppet/modules/blackfire/spec/classes/init_spec.rb index 1ff10b6..381cb8d 100644 --- a/puphpet/puppet/modules/blackfire/spec/classes/init_spec.rb +++ b/puphpet/puppet/modules/blackfire/spec/classes/init_spec.rb @@ -5,7 +5,7 @@ context "on #{os}" do let(:facts) { facts } - context 'fail with defaults for all parameters' do + context 'with default parameters' do it do expect { should compile @@ -13,19 +13,53 @@ end end - context 'with minimum set of parameters' do + context 'with minimum parameters (server id and token)' do let(:params) do { - :server_id => 'foo', - :server_token => 'bar' + :server_id => 'foo', + :server_token => 'bar', } end - it { should compile } - it { should contain_class('blackfire') } - it { should contain_class('blackfire::repo') } - it { should contain_class('blackfire::agent') } - it { should contain_class('blackfire::php') } + context 'with minimum set of parameters' do + it { should compile } + it { should contain_class('blackfire') } + it { should contain_class('blackfire::repo') } + it { should contain_class('blackfire::agent') } + it { should contain_class('blackfire::php') } + end + + context 'agent package' do + it { should contain_package('blackfire-agent').with(:ensure => 'latest') } + end + + context 'agent configuration' do + it { should contain_ini_setting('server-id').with( + :path => '/etc/blackfire/agent', + :value => 'foo' + )} + it { should contain_ini_setting('server-token').with( + :path => '/etc/blackfire/agent', + :value => 'bar' + )} + end + + context 'agent service' do + it { should contain_service('blackfire-agent').with(:ensure => 'running') } + end + + context 'probe package' do + it { should contain_package('blackfire-php').with(:ensure => 'latest') } + end + + context 'probe configuration' do + it { should contain_ini_setting('blackfire.server_id').with( + :value => 'foo' + )} + it { should contain_ini_setting('blackfire.server_token').with( + :value => 'bar' + )} + end end end diff --git a/puphpet/puppet/modules/composer/.gitignore b/puphpet/puppet/modules/composer/.gitignore new file mode 100644 index 0000000..0d733ca --- /dev/null +++ b/puphpet/puppet/modules/composer/.gitignore @@ -0,0 +1,12 @@ +spec/fixtures/modules/* +spec/fixtures/puppet/common.yaml +.bundle/ +vendor/ +Gemfile.lock +pkg/ +modules/ +.vagrant +.ruby-version + +# IDE ignores +.idea diff --git a/puphpet/puppet/modules/composer/templates/install.erb b/puphpet/puppet/modules/composer/templates/install.erb index c407889..7e2efbf 100644 --- a/puphpet/puppet/modules/composer/templates/install.erb +++ b/puphpet/puppet/modules/composer/templates/install.erb @@ -6,5 +6,6 @@ <% unless @scripts %> --no-scripts<% end -%> <% unless @interaction %> --no-interaction<% end -%> <% if @dev %> --dev<% end -%> +<% unless @dev %> --no-dev<% end -%> <% if @verbose %> -v<% end -%> <% if @dry_run %> --dry-run<% end -%> diff --git a/puphpet/puppet/modules/concat/.gitignore b/puphpet/puppet/modules/concat/.gitignore new file mode 100644 index 0000000..b5b7a00 --- /dev/null +++ b/puphpet/puppet/modules/concat/.gitignore @@ -0,0 +1,7 @@ +pkg/ +Gemfile.lock +vendor/ +spec/fixtures/ +.vagrant/ +.bundle/ +coverage/ diff --git a/puphpet/puppet/modules/datacat/Changes b/puphpet/puppet/modules/datacat/Changes new file mode 100644 index 0000000..838ce4a --- /dev/null +++ b/puphpet/puppet/modules/datacat/Changes @@ -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 diff --git a/puphpet/puppet/modules/datacat/Gemfile b/puphpet/puppet/modules/datacat/Gemfile new file mode 100644 index 0000000..76e5abe --- /dev/null +++ b/puphpet/puppet/modules/datacat/Gemfile @@ -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 diff --git a/puphpet/puppet/modules/datacat/NOTES.md b/puphpet/puppet/modules/datacat/NOTES.md new file mode 100644 index 0000000..c527444 --- /dev/null +++ b/puphpet/puppet/modules/datacat/NOTES.md @@ -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' diff --git a/puphpet/puppet/modules/datacat/README.md b/puphpet/puppet/modules/datacat/README.md new file mode 100644 index 0000000..7260703 --- /dev/null +++ b/puphpet/puppet/modules/datacat/README.md @@ -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. diff --git a/puphpet/puppet/modules/datacat/Rakefile b/puphpet/puppet/modules/datacat/Rakefile new file mode 100644 index 0000000..4847ddd --- /dev/null +++ b/puphpet/puppet/modules/datacat/Rakefile @@ -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 diff --git a/puphpet/puppet/modules/datacat/TODO.md b/puphpet/puppet/modules/datacat/TODO.md new file mode 100644 index 0000000..0843d94 --- /dev/null +++ b/puphpet/puppet/modules/datacat/TODO.md @@ -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', + } diff --git a/puphpet/puppet/modules/datacat/checksums.json b/puphpet/puppet/modules/datacat/checksums.json new file mode 100644 index 0000000..9a1335a --- /dev/null +++ b/puphpet/puppet/modules/datacat/checksums.json @@ -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 diff --git a/puphpet/puppet/modules/datacat/lib/puppet/parser/functions/template_body.rb b/puphpet/puppet/modules/datacat/lib/puppet/parser/functions/template_body.rb new file mode 100644 index 0000000..44b40d6 --- /dev/null +++ b/puphpet/puppet/modules/datacat/lib/puppet/parser/functions/template_body.rb @@ -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 diff --git a/puphpet/puppet/modules/datacat/lib/puppet/provider/datacat_collector/datacat_collector.rb b/puphpet/puppet/modules/datacat/lib/puppet/provider/datacat_collector/datacat_collector.rb new file mode 100644 index 0000000..c5cbf20 --- /dev/null +++ b/puphpet/puppet/modules/datacat/lib/puppet/provider/datacat_collector/datacat_collector.rb @@ -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 diff --git a/puphpet/puppet/modules/datacat/lib/puppet/provider/datacat_fragment/datacat_fragment.rb b/puphpet/puppet/modules/datacat/lib/puppet/provider/datacat_fragment/datacat_fragment.rb new file mode 100644 index 0000000..d69ce09 --- /dev/null +++ b/puphpet/puppet/modules/datacat/lib/puppet/provider/datacat_fragment/datacat_fragment.rb @@ -0,0 +1,3 @@ +Puppet::Type.type(:datacat_fragment).provide(:datacat_fragment) do + mk_resource_methods +end diff --git a/puphpet/puppet/modules/datacat/lib/puppet/type/datacat_collector.rb b/puphpet/puppet/modules/datacat/lib/puppet/type/datacat_collector.rb new file mode 100644 index 0000000..e4ba3de --- /dev/null +++ b/puphpet/puppet/modules/datacat/lib/puppet/type/datacat_collector.rb @@ -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 diff --git a/puphpet/puppet/modules/datacat/lib/puppet/type/datacat_fragment.rb b/puphpet/puppet/modules/datacat/lib/puppet/type/datacat_fragment.rb new file mode 100644 index 0000000..2f3031c --- /dev/null +++ b/puphpet/puppet/modules/datacat/lib/puppet/type/datacat_fragment.rb @@ -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 diff --git a/puphpet/puppet/modules/datacat/lib/puppet_x/richardc/datacat.rb b/puphpet/puppet/modules/datacat/lib/puppet_x/richardc/datacat.rb new file mode 100644 index 0000000..f28fad6 --- /dev/null +++ b/puphpet/puppet/modules/datacat/lib/puppet_x/richardc/datacat.rb @@ -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 diff --git a/puphpet/puppet/modules/datacat/manifests/init.pp b/puphpet/puppet/modules/datacat/manifests/init.pp new file mode 100644 index 0000000..a6e2f94 --- /dev/null +++ b/puphpet/puppet/modules/datacat/manifests/init.pp @@ -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 + } + } +} diff --git a/puphpet/puppet/modules/datacat/metadata.json b/puphpet/puppet/modules/datacat/metadata.json new file mode 100644 index 0000000..e513532 --- /dev/null +++ b/puphpet/puppet/modules/datacat/metadata.json @@ -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": [ + + ] +} diff --git a/puphpet/puppet/modules/datacat/spec/classes/demo1_spec.rb b/puphpet/puppet/modules/datacat/spec/classes/demo1_spec.rb new file mode 100644 index 0000000..988d577 --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/classes/demo1_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/datacat/spec/defines/datacat_spec.rb b/puphpet/puppet/modules/datacat/spec/defines/datacat_spec.rb new file mode 100644 index 0000000..77d5c4b --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/defines/datacat_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo1/manifests/init.pp b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo1/manifests/init.pp new file mode 100644 index 0000000..4f0f1e9 --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo1/manifests/init.pp @@ -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 }, + } +} + diff --git a/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo1/templates/sheeps.erb b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo1/templates/sheeps.erb new file mode 100644 index 0000000..b3781a8 --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo1/templates/sheeps.erb @@ -0,0 +1,3 @@ +# This is a super simple demonstration - baah! + +<%= @data.to_yaml %> diff --git a/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo2/manifests/init.pp b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo2/manifests/init.pp new file mode 100644 index 0000000..90310e0 --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo2/manifests/init.pp @@ -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 ] }, + } +} + diff --git a/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo2/templates/merging.erb b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo2/templates/merging.erb new file mode 100644 index 0000000..b05594f --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo2/templates/merging.erb @@ -0,0 +1,2 @@ +data.foo should be a merged array <%= @data['foo'].join(', ') %> +and we can uniq it <%= @data['foo'].uniq.join(', ') %> diff --git a/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo3/manifests/init.pp b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo3/manifests/init.pp new file mode 100644 index 0000000..1e19438 --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo3/manifests/init.pp @@ -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 ], + }, + } +} diff --git a/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo3/templates/hostgroups.cfg.erb b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo3/templates/hostgroups.cfg.erb new file mode 100644 index 0000000..53bbbcb --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/fixtures/modules/demo3/templates/hostgroups.cfg.erb @@ -0,0 +1,7 @@ +# hostgroups.cfg.erb +<% @data.keys.sort.each do |hostgroup| %> +define hostgroup { + name <%= hostgroup %> + members <%= @data[hostgroup].sort.join(',') %> +} +<% end %> diff --git a/puphpet/puppet/modules/datacat/spec/fixtures/modules/issue1/manifests/init.pp b/puphpet/puppet/modules/datacat/spec/fixtures/modules/issue1/manifests/init.pp new file mode 100644 index 0000000..b5c4283 --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/fixtures/modules/issue1/manifests/init.pp @@ -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", + } +} diff --git a/puphpet/puppet/modules/datacat/spec/fixtures/modules/issue1/templates/refers_to_scope.erb b/puphpet/puppet/modules/datacat/spec/fixtures/modules/issue1/templates/refers_to_scope.erb new file mode 100644 index 0000000..e4756c7 --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/fixtures/modules/issue1/templates/refers_to_scope.erb @@ -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") %> diff --git a/puphpet/puppet/modules/datacat/spec/fixtures/modules/template_body/templates/test1.erb b/puphpet/puppet/modules/datacat/spec/fixtures/modules/template_body/templates/test1.erb new file mode 100644 index 0000000..7b6637f --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/fixtures/modules/template_body/templates/test1.erb @@ -0,0 +1 @@ +Goodbye cruel world diff --git a/puphpet/puppet/modules/datacat/spec/functions/template_body_spec.rb b/puphpet/puppet/modules/datacat/spec/functions/template_body_spec.rb new file mode 100644 index 0000000..496c0df --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/functions/template_body_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/datacat/spec/spec_helper.rb b/puphpet/puppet/modules/datacat/spec/spec_helper.rb new file mode 100644 index 0000000..2c6f566 --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/spec_helper.rb @@ -0,0 +1 @@ +require 'puppetlabs_spec_helper/module_spec_helper' diff --git a/puphpet/puppet/modules/datacat/spec/spec_helper_system.rb b/puphpet/puppet/modules/datacat/spec/spec_helper_system.rb new file mode 100644 index 0000000..cba2ad7 --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/spec_helper_system.rb @@ -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 diff --git a/puphpet/puppet/modules/datacat/spec/system/basic_spec.rb b/puphpet/puppet/modules/datacat/spec/system/basic_spec.rb new file mode 100644 index 0000000..627547a --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/system/basic_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/datacat/spec/unit/type/datacat_collector_spec.rb b/puphpet/puppet/modules/datacat/spec/unit/type/datacat_collector_spec.rb new file mode 100644 index 0000000..46d7abd --- /dev/null +++ b/puphpet/puppet/modules/datacat/spec/unit/type/datacat_collector_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/.fixtures.yml b/puphpet/puppet/modules/elasticsearch/.fixtures.yml index e16c408..d750f45 100644 --- a/puphpet/puppet/modules/elasticsearch/.fixtures.yml +++ b/puphpet/puppet/modules/elasticsearch/.fixtures.yml @@ -1,5 +1,13 @@ fixtures: repositories: - stdlib: git://github.com/puppetlabs/puppetlabs-stdlib.git + 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}" diff --git a/puphpet/puppet/modules/elasticsearch/.gitignore b/puphpet/puppet/modules/elasticsearch/.gitignore new file mode 100644 index 0000000..47a5fab --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/.gitignore @@ -0,0 +1,12 @@ +.swp +spec/fixtures/manifests +spec/fixtures/modules +.bundle +.vendor +.vagrant +.ruby-version +pkg/ +spec/reports/ +spec/logs +log +*.lock diff --git a/puphpet/puppet/modules/elasticsearch/.pmtignore b/puphpet/puppet/modules/elasticsearch/.pmtignore new file mode 100644 index 0000000..b5e79ed --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/.pmtignore @@ -0,0 +1,6 @@ +spec/ +Rakefile +junit/ +logs/ +Gemfile +Gemfile.lock diff --git a/puphpet/puppet/modules/elasticsearch/.travis.yml b/puphpet/puppet/modules/elasticsearch/.travis.yml deleted file mode 100644 index c4a322e..0000000 --- a/puphpet/puppet/modules/elasticsearch/.travis.yml +++ /dev/null @@ -1,33 +0,0 @@ -language: ruby -rvm: - - 1.8.7 - - 1.9.3 - - 2.0.0 -script: - - "rake lint" - - "rake parser_validate" - - "rake template_verify" - - "rake spec SPEC_OPTS='--format documentation'" -env: - - PUPPET_VERSION="~> 2.7.0" - - PUPPET_VERSION="~> 3.0.0" - - PUPPET_VERSION="~> 3.1.0" - - PUPPET_VERSION="~> 3.2.0" - - PUPPET_VERSION="~> 3.3.0" -matrix: - allow_failures: - - rvm: 2.0.0 -gemfile: Gemfile -notifications: - email: - recipients: - - richard.pijnenburg@elasticsearch.com - on_success: change - on_failure: always - hipchat: - rooms: - secure: "gFaED3lu9MRrmoojO2iagrfOaKAbCeQSqVZ9TsIo+qkqem8hwOsMuxsYQ9evPbPbanXQoVNALXTd4fgQW16+hfg/ClqI3nDtVZZJSy0W+U0yVZtz9TXFpi9Q/Z4TwK5TMdNMjemt0l2idY2SE3leHBZEeaIAGfLf0v38tCsNI84=" - template: - - '@electrical %{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message} %{build_url}' - on_success: change - on_failure: always diff --git a/puphpet/puppet/modules/elasticsearch/CHANGELOG b/puphpet/puppet/modules/elasticsearch/CHANGELOG deleted file mode 100644 index 90a59fc..0000000 --- a/puphpet/puppet/modules/elasticsearch/CHANGELOG +++ /dev/null @@ -1,91 +0,0 @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/CHANGELOG.md b/puphpet/puppet/modules/elasticsearch/CHANGELOG.md new file mode 100644 index 0000000..e7be456 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/CHANGELOG.md @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/CONTRIBUTING.md b/puphpet/puppet/modules/elasticsearch/CONTRIBUTING.md index 13f29e3..80f5cdd 100644 --- a/puphpet/puppet/modules/elasticsearch/CONTRIBUTING.md +++ b/puphpet/puppet/modules/elasticsearch/CONTRIBUTING.md @@ -2,17 +2,45 @@ If you have a bugfix or new feature that you would like to contribute to this pu 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 Elasticsearch repositories is similar. +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.elasticsearch.org/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. +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. Rebase 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. -4. Submit a pull request +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. diff --git a/puphpet/puppet/modules/elasticsearch/Gemfile b/puphpet/puppet/modules/elasticsearch/Gemfile index 95b8d66..68c056e 100644 --- a/puphpet/puppet/modules/elasticsearch/Gemfile +++ b/puphpet/puppet/modules/elasticsearch/Gemfile @@ -1,7 +1,32 @@ source 'https://rubygems.org' -puppetversion = ENV['PUPPET_VERSION'] +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 'rspec-puppet' -gem 'puppetlabs_spec_helper', '>= 0.1.0' +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 diff --git a/puphpet/puppet/modules/elasticsearch/LICENSE b/puphpet/puppet/modules/elasticsearch/LICENSE index f8b711d..619edcc 100644 --- a/puphpet/puppet/modules/elasticsearch/LICENSE +++ b/puphpet/puppet/modules/elasticsearch/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012-2014 Elasticsearch +Copyright (c) 2012-2015 Elasticsearch Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/puphpet/puppet/modules/elasticsearch/Modulefile b/puphpet/puppet/modules/elasticsearch/Modulefile deleted file mode 100644 index 44aae1c..0000000 --- a/puphpet/puppet/modules/elasticsearch/Modulefile +++ /dev/null @@ -1,9 +0,0 @@ -name 'elasticsearch-elasticsearch' -version '0.2.2' -source 'https://github.com/elasticsearch/puppet-elasticsearch' -author 'elasticsearch' -license 'Apache License, Version 2.0' -summary 'Module for managing and configuring Elasticsearch nodes' -description 'Module for managing and configuring Elasticsearch nodes' -project_page 'https://github.com/elasticsearch/puppet-elasticsearch' -dependency 'puppetlabs/stdlib', '>= 3.0.0' diff --git a/puphpet/puppet/modules/elasticsearch/README.md b/puphpet/puppet/modules/elasticsearch/README.md index 12a1275..80737b6 100644 --- a/puphpet/puppet/modules/elasticsearch/README.md +++ b/puphpet/puppet/modules/elasticsearch/README.md @@ -1,203 +1,534 @@ -# puppet-elasticsearch +#Elasticsearch Puppet module -A puppet module for managing elasticsearch nodes +####Table of Contents -http://www.elasticsearch.org/ +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) -[![Build Status](https://travis-ci.org/elasticsearch/puppet-elasticsearch.png?branch=master)](https://travis-ci.org/elasticsearch/puppet-elasticsearch) -## Usage -Installation, make sure service is running and will be started at boot time: +##Overview - class { 'elasticsearch': } +This module manages Elasticsearch (http://www.elasticsearch.org/overview/elasticsearch/) -Install a certain version: +##Module description - class { 'elasticsearch': - version => '0.90.3' - } +The elasticsearch module sets up Elasticsearch instances and can manage plugins and templates. -This assumes an elasticsearch package is already available to your distribution's package manager. To install it in a different way: +This module has been tested against all versions of ES 1.x and 2.x -To download from http/https/ftp source: +##Setup - class { 'elasticsearch': - package_url => 'https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-0.90.7.deb' - } +###The module manages the following -To download from a puppet:// source: +* Elasticsearch repository files. +* Elasticsearch package. +* Elasticsearch configuration file. +* Elasticsearch service. +* Elasticsearch plugins. +* Elasticsearch templates. - class { 'elasticsearch': - package_url => 'puppet:///path/to/elasticsearch-0.90.7.deb' - } +###Requirements -Or use a local file source: +* 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/) - class { 'elasticsearch': - package_url => 'file:/path/to/elasticsearch-0.90.7.deb' - } +#### Repository management +When using the repository management you will need the following dependency modules: -Automatic upgrade of the software ( default set to false ): +* Debian/Ubuntu: [Puppetlabs/apt](http://forge.puppetlabs.com/puppetlabs/apt) +* OpenSuSE: [Darin/zypprepo](https://forge.puppetlabs.com/darin/zypprepo) - class { 'elasticsearch': - autoupgrade => true - } +##Usage -Removal/decommissioning: +###Main class - class { 'elasticsearch': - ensure => 'absent' - } +####Install a specific version -Install everything but disable service(s) afterwards: +```puppet +class { 'elasticsearch': + version => '1.4.2' +} +``` - class { 'elasticsearch': - status => 'disabled' - } +Note: This will only work when using the repository. -Disable automated restart of Elasticsearch on config file change: +####Automatic upgrade of the software ( default set to false ) +```puppet +class { 'elasticsearch': + autoupgrade => true +} +``` - class { 'elasticsearch': - restart_on_change => false - } +####Removal/decommissioning +```puppet +class { 'elasticsearch': + ensure => 'absent' +} +``` -For the config variable a hash needs to be passed: +####Install everything but disable service(s) afterwards +```puppet +class { 'elasticsearch': + status => 'disabled' +} +``` - class { 'elasticsearch': - config => { - 'node' => { - 'name' => 'elasticsearch001' - }, - 'index' => { - 'number_of_replicas' => '0', - 'number_of_shards' => '5' - }, - 'network' => { - 'host' => $::ipaddress - } - } - } +###Instances -Short write up of the config hash is also possible. +This module works with the concept of instances. For service to start you need to specify at least one instance. -Instead of writing the full hash representation: +####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 - class { 'elasticsearch': - config => { - 'cluster' => { - 'name' => 'ClusterName', - 'routing' => { - 'allocation' => { - 'awareness' => { - 'attributes' => 'rack' - } - } - } - } - } - } +Install a variety of [clients/bindings](http://www.elasticsearch.org/guide/en/elasticsearch/client/community/current/clients.html): -You can write the dotted key naming: +####Python - class { 'elasticsearch': - config => { - 'cluster' => { - 'name' => 'ClusterName', - 'routing.allocation.awareness.attributes' => 'rack' - } - } - } +```puppet +elasticsearch::python { 'rawes': } +``` +####Ruby +```puppet +elasticsearch::ruby { 'elasticsearch': } +``` -## Manage templates +###Connection Validator -### Add a new template +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', +} +``` -This will install and/or replace the template in Elasticearch +A common use would be for example : - elasticsearch::template { 'templatename': - file => 'puppet:///path/to/template.json' - } +```puppet +class { 'kibana4' : + require => Es_Instance_Conn_Validator['myinstance'], +} +``` -### Delete a template +###Package installation - elasticsearch::template { 'templatename': - ensure => 'absent' - } +There are 2 different ways of installing the software -### Host +####Repository - Default it uses localhost:9200 as host. you can change this with the 'host' and 'port' variables +This option allows you to use an existing repository for package installation. +The `repo_version` corresponds with the major version of Elasticsearch. - elasticsearch::template { 'templatename': - host => $::ipaddress, - port => 9200 - } +```puppet +class { 'elasticsearch': + manage_repo => true, + repo_version => '1.4', +} +``` -## Bindings / clients +####Remote package source -Install a variety of [clients/bindings](http://www.elasticsearch.org/guide/clients/): +When a repository is not available or preferred you can install the packages from a remote source: -### Python +#####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). - elasticsearch::python { 'rawes': } +#####puppet:// +```puppet +class { 'elasticsearch': + package_url => 'puppet:///path/to/elasticsearch-1.4.2.deb' +} +``` -### Ruby +#####Local file +```puppet +class { 'elasticsearch': + package_url => 'file:/path/to/elasticsearch-1.4.2.deb' +} +``` - elasticsearch::ruby { 'elasticsearch': } +###Java installation -## Plugins +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. -Install [a variety of plugins](http://www.elasticsearch.org/guide/clients/): +```puppet +class { 'elasticsearch': + java_install => true +} +``` -### From official repository: +Specify a particular Java package/version to be installed: - elasticsearch::plugin{'mobz/elasticsearch-head': - module_dir => 'head' - } +```puppet +class { 'elasticsearch': + java_install => true, + java_package => 'packagename' +} +``` -### From custom url: +###Service management - elasticsearch::plugin{ 'elasticsearch-jetty': - module_dir => 'jetty', - url => 'https://oss-es-plugins.s3.amazonaws.com/elasticsearch-jetty/elasticsearch-jetty-0.90.0.zip' - } +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). -## Java install -For those that have no separate module for installation of java: +####Defaults File - class { 'elasticsearch': - java_install => true - } +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. -If you want a specific java package/version: +#####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': - java_install => true, - java_package => 'packagename' - } +class { 'elasticsearch': + init_defaults => $config_hash +} +``` -## Service providers +Note: `init_defaults` hash can be passed to the main class and to the instance. -Currently only the 'init' service provider is supported but others can be implemented quite easy. +##Advanced features -### init +###Package version pinning -#### Defaults file +The module supports pinning the package version to avoid accidental upgrades that are not done by Puppet. +To enable this feature: -You can populate the defaults file ( /etc/defaults/elasticsearch or /etc/sysconfig/elasticsearch ) +```puppet +class { 'elasticsearch': + package_pin => true, + version => '1.5.2', +} +``` -##### hash representation +In this example we pin the package version to 1.5.2. - class { 'elasticsearch': - init_defaults => { 'ES_USER' => 'elasticsearch', 'ES_GROUP' => 'elasticsearch' } - } -##### file source +###Data directories - class { 'elasticsearch': - init_defaults_file => 'puppet:///path/to/defaults' - } +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/). diff --git a/puphpet/puppet/modules/elasticsearch/Rakefile b/puphpet/puppet/modules/elasticsearch/Rakefile index 425e032..4e1e379 100644 --- a/puphpet/puppet/modules/elasticsearch/Rakefile +++ b/puphpet/puppet/modules/elasticsearch/Rakefile @@ -1,7 +1,28 @@ require 'rubygems' require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet-lint' -require './spec/lib/template_check_task.rb' -require './spec/lib/parser_validate_task.rb' -PuppetLint.configuration.send("disable_80chars") -PuppetLint.configuration.send("disable_class_inherits_from_params_class") + +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}" diff --git a/puphpet/puppet/modules/elasticsearch/lib/facter/es_facts.rb b/puphpet/puppet/modules/elasticsearch/lib/facter/es_facts.rb new file mode 100644 index 0000000..d9b4bca --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/lib/facter/es_facts.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/lib/puppet/parser/functions/array_suffix.rb b/puphpet/puppet/modules/elasticsearch/lib/puppet/parser/functions/array_suffix.rb new file mode 100644 index 0000000..0f2da68 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/lib/puppet/parser/functions/array_suffix.rb @@ -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 : diff --git a/puphpet/puppet/modules/elasticsearch/lib/puppet/parser/functions/plugin_dir.rb b/puphpet/puppet/modules/elasticsearch/lib/puppet/parser/functions/plugin_dir.rb new file mode 100644 index 0000000..94c1ce1 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/lib/puppet/parser/functions/plugin_dir.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/lib/puppet/provider/elasticsearch_plugin/plugin.rb b/puphpet/puppet/modules/elasticsearch/lib/puppet/provider/elasticsearch_plugin/plugin.rb new file mode 100644 index 0000000..00dd49e --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/lib/puppet/provider/elasticsearch_plugin/plugin.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb b/puphpet/puppet/modules/elasticsearch/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb new file mode 100644 index 0000000..3cd1ef6 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/lib/puppet/provider/es_instance_conn_validator/tcp_port.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/lib/puppet/type/elasticsearch_plugin.rb b/puphpet/puppet/modules/elasticsearch/lib/puppet/type/elasticsearch_plugin.rb new file mode 100644 index 0000000..145880f --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/lib/puppet/type/elasticsearch_plugin.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/lib/puppet/type/es_instance_conn_validator.rb b/puphpet/puppet/modules/elasticsearch/lib/puppet/type/es_instance_conn_validator.rb new file mode 100644 index 0000000..5ecd14d --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/lib/puppet/type/es_instance_conn_validator.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/lib/puppet/util/es_instance_validator.rb b/puphpet/puppet/modules/elasticsearch/lib/puppet/util/es_instance_validator.rb new file mode 100644 index 0000000..e097314 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/lib/puppet/util/es_instance_validator.rb @@ -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 + diff --git a/puphpet/puppet/modules/elasticsearch/manifests/config.pp b/puphpet/puppet/modules/elasticsearch/manifests/config.pp index a26886d..a7b5d83 100644 --- a/puphpet/puppet/modules/elasticsearch/manifests/config.pp +++ b/puphpet/puppet/modules/elasticsearch/manifests/config.pp @@ -20,7 +20,7 @@ # # === Authors # -# * Richard Pijnenburg +# * Richard Pijnenburg # class elasticsearch::config { @@ -28,7 +28,7 @@ File { owner => $elasticsearch::elasticsearch_user, - group => $elasticsearch::elasticsearch_group + group => $elasticsearch::elasticsearch_group, } Exec { @@ -43,46 +43,97 @@ false => undef, } - file { $elasticsearch::confdir: + file { $elasticsearch::configdir: ensure => directory, mode => '0644', - purge => $elasticsearch::purge_confdir, - force => $elasticsearch::purge_confdir } - file { "${elasticsearch::confdir}/elasticsearch.yml": - ensure => file, - content => template("${module_name}/etc/elasticsearch/elasticsearch.yml.erb"), + file { $elasticsearch::params::logdir: + ensure => 'directory', + group => undef, mode => '0644', - notify => $notify_service + recurse => true, } - exec { 'mkdir_templates_elasticsearch': - command => "mkdir -p ${elasticsearch::confdir}/templates_import", - creates => "${elasticsearch::confdir}/templates_import" + file { $elasticsearch::params::homedir: + ensure => 'directory', } - file { "${elasticsearch::confdir}/templates_import": + file { "${elasticsearch::params::homedir}/bin": + ensure => 'directory', + recurse => true, + mode => '0755', + } + + file { $elasticsearch::datadir: ensure => 'directory', - mode => '0644', - require => Exec['mkdir_templates_elasticsearch'] } - if ( $elasticsearch::datadir != undef ) { - file { $elasticsearch::datadir: + file { "${elasticsearch::homedir}/lib": + ensure => 'directory', + recurse => true, + } + + if $elasticsearch::params::pid_dir { + file { $elasticsearch::params::pid_dir: ensure => 'directory', - owner => $elasticsearch::elasticsearch_user, - group => $elasticsearch::elasticsearch_group, - mode => '0770', + 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::confdir: - ensure => 'absent', - recurse => true, - force => true + file { $elasticsearch::plugindir: + ensure => 'absent', + force => true, + backup => false, } } diff --git a/puphpet/puppet/modules/elasticsearch/manifests/init.pp b/puphpet/puppet/modules/elasticsearch/manifests/init.pp index fabfd78..768cf4c 100644 --- a/puphpet/puppet/modules/elasticsearch/manifests/init.pp +++ b/puphpet/puppet/modules/elasticsearch/manifests/init.pp @@ -58,7 +58,7 @@ # Defaults to true, which will restart the application on any config # change. Setting to false disables the automatic restart. # -# [*confdir*] +# [*configdir*] # Path to directory containing the elasticsearch configuration. # Use this setting if your packages deviate from the norm (/etc/elasticsearch) # @@ -70,6 +70,118 @@ # 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 params.pp manifest file if you need more # technical information about them. @@ -92,36 +204,52 @@ # # === Authors # -# * Richard Pijnenburg +# * Richard Pijnenburg # 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, - $purge_package_dir = $elasticsearch::params::purge_package_dir, - $elasticsearch_user = $elasticsearch::params::elasticsearch_user, - $elasticsearch_group = $elasticsearch::params::elasticsearch_group, - $purge_confdir = $elasticsearch::params::purge_confdir, - $service_provider = 'init', - $init_defaults = undef, - $init_defaults_file = undef, - $init_template = undef, - $config = {}, - $confdir = $elasticsearch::params::confdir, - $datadir = undef, - $plugindir = $elasticsearch::params::plugindir, - $plugintool = $elasticsearch::params::plugintool, - $java_install = false, - $java_package = undef + $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': } - anchor {'elasticsearch::end': } #### Validate parameters @@ -143,22 +271,58 @@ validate_bool($restart_on_change) # purge conf dir - validate_bool($purge_confdir) + validate_bool($purge_configdir) - if ! ($service_provider in $elasticsearch::params::service_providers) { - fail("\"${service_provider}\" is not a valid provider for \"${::operatingsystem}\"") + 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.') } - # validate config hash - validate_hash($config) + 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) @@ -167,17 +331,73 @@ # configuration class { 'elasticsearch::config': } - # service(s) - class { 'elasticsearch::service': } + # 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 { 'elasticsearch::java': } + class { '::java': + package => $java_package, + distribution => 'jre', + } - # ensure we first java java and then manage the service + # ensure we first install java, the package and then the rest Anchor['elasticsearch::begin'] - -> Class['elasticsearch::java'] - -> Class['elasticsearch::service'] + -> 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 @@ -188,20 +408,17 @@ Anchor['elasticsearch::begin'] -> Class['elasticsearch::package'] -> Class['elasticsearch::config'] - - # we need the software and a working configuration before running a service - Class['elasticsearch::package'] -> Class['elasticsearch::service'] - Class['elasticsearch::config'] -> Class['elasticsearch::service'] - - Class['elasticsearch::service'] -> Anchor['elasticsearch::end'] + -> Elasticsearch::Plugin <| |> + -> Elasticsearch::Instance <| |> + -> Elasticsearch::Template <| |> } else { # make sure all services are getting stopped before software removal Anchor['elasticsearch::begin'] - -> Class['elasticsearch::service'] + -> Elasticsearch::Instance <| |> + -> Class['elasticsearch::config'] -> Class['elasticsearch::package'] - -> Anchor['elasticsearch::end'] } diff --git a/puphpet/puppet/modules/elasticsearch/manifests/instance.pp b/puphpet/puppet/modules/elasticsearch/manifests/instance.pp new file mode 100644 index 0000000..f1e14fc --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/manifests/instance.pp @@ -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 present or +# absent. If set to absent: +# * 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 present. +# +# [*status*] +# String to define the status of the service. Possible values: +# * enabled: Service is running and will be started at boot time. +# * disabled: Service is stopped and will not be started at boot +# time. +# * running: 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. +# * unmanaged: 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 enabled. 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 service.pp 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 +# +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, + } + +} diff --git a/puphpet/puppet/modules/elasticsearch/manifests/java.pp b/puphpet/puppet/modules/elasticsearch/manifests/java.pp deleted file mode 100644 index 8d5149d..0000000 --- a/puphpet/puppet/modules/elasticsearch/manifests/java.pp +++ /dev/null @@ -1,50 +0,0 @@ -# == Class: elasticsearch::java -# -# This class exists to install java if its not managed from an other module -# -# -# === Parameters -# -# This class does not provide any parameters. -# -# -# === Examples -# -# This class may be imported by other classes to use its functionality: -# class { 'elasticsearch::java': } -# -# It is not intended to be used directly by external resources like node -# definitions or other modules. -# -# -# === Authors -# -# * Richard Pijnenburg -# -class elasticsearch::java { - - if $elasticsearch::java_package == undef { - # Default Java package - case $::operatingsystem { - 'CentOS', 'Fedora', 'Scientific', 'RedHat', 'Amazon', 'OracleLinux': { - $package = 'java-1.7.0-openjdk' - } - 'Debian', 'Ubuntu': { - $package = 'openjdk-7-jre-headless' - } - default: { - fail("\"${module_name}\" provides no java package - for \"${::operatingsystem}\"") - } - } - } else { - $package = $elasticsearch::java_package - } - - ## Install the java package unless already specified somewhere else - if !defined(Package[$package]) { - package { $package: - ensure => present - } - } -} diff --git a/puphpet/puppet/modules/elasticsearch/manifests/package.pp b/puphpet/puppet/modules/elasticsearch/manifests/package.pp index 1cb5295..5e3caa9 100644 --- a/puphpet/puppet/modules/elasticsearch/manifests/package.pp +++ b/puphpet/puppet/modules/elasticsearch/manifests/package.pp @@ -20,16 +20,40 @@ # # === Authors # -# * Richard Pijnenburg +# * Richard Pijnenburg # 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 { @@ -41,29 +65,19 @@ } else { # install specific version - $package_ensure = $elasticsearch::version + $package_ensure = $elasticsearch::pkg_version } # action if ($elasticsearch::package_url != undef) { - $package_dir = $elasticsearch::package_dir - - # 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; + case $elasticsearch::package_provider { + 'package': { $before = Package[$elasticsearch::package_name] } + default: { fail("software provider \"${elasticsearch::package_provider}\".") } } - file { $package_dir: - ensure => 'directory', - purge => $elasticsearch::purge_package_dir, - force => $elasticsearch::purge_package_dir, - require => Exec['create_package_dir_elasticsearch'], - } + $package_dir = $elasticsearch::package_dir $filenameArray = split($elasticsearch::package_url, '/') $basefilename = $filenameArray[-1] @@ -74,39 +88,50 @@ $extArray = split($basefilename, '\.') $ext = $extArray[-1] + $pkg_source = "${package_dir}/${basefilename}" + case $protocol_type { - puppet: { + 'puppet': { - file { "${package_dir}/${basefilename}": - ensure => present, + file { $pkg_source: + ensure => file, source => $elasticsearch::package_url, require => File[$package_dir], backup => false, - before => Package[$elasticsearch::params::package] + before => $before, } } - ftp, https, http: { + '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::dlcmd} ${package_dir}/${basefilename} ${elasticsearch::package_url} 2> /dev/null", - path => ['/usr/bin', '/bin'], - creates => "${package_dir}/${basefilename}", - require => File[$package_dir], - before => Package[$elasticsearch::params::package] + 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: { + 'file': { $source_path = $sourceArray[1] - file { "${package_dir}/${basefilename}": - ensure => present, + file { $pkg_source: + ensure => file, source => $source_path, require => File[$package_dir], backup => false, - before => Package[$elasticsearch::params::package] + before => $before, } } @@ -115,31 +140,38 @@ } } - case $ext { - 'deb': { $pkg_provider = 'dpkg' } - 'rpm': { $pkg_provider = 'rpm' } - default: { fail("Unknown file extention \"${ext}\".") } - } + if ($elasticsearch::package_provider == 'package') { - $pkg_source = "${package_dir}/${basefilename}" + case $ext { + 'deb': { Package { provider => 'dpkg', source => $pkg_source } } + 'rpm': { Package { provider => 'rpm', source => $pkg_source } } + default: { fail("Unknown file extention \"${ext}\".") } + } + + } - } else { - $pkg_source = undef - $pkg_provider = undef } # Package removal } else { - $pkg_source = undef - $pkg_provider = undef + if ($::operatingsystem == 'OpenSuSE') { + Package { + provider => 'rpm', + } + } $package_ensure = 'purged' + } - package { $elasticsearch::params::package: - ensure => $package_ensure, - source => $pkg_source, - provider => $pkg_provider + if ($elasticsearch::package_provider == 'package') { + + package { $elasticsearch::package_name: + ensure => $package_ensure, + } + + } else { + fail("\"${elasticsearch::package_provider}\" is not supported") } } diff --git a/puphpet/puppet/modules/elasticsearch/manifests/params.pp b/puphpet/puppet/modules/elasticsearch/manifests/params.pp index aea527f..0e2d76b 100644 --- a/puphpet/puppet/modules/elasticsearch/manifests/params.pp +++ b/puphpet/puppet/modules/elasticsearch/manifests/params.pp @@ -43,37 +43,77 @@ # restart on configuration change? $restart_on_change = true - # Package dir. Temporary place to download the package to for installation - $package_dir = '/var/lib/elasticsearch' + # Purge configuration directory + $purge_configdir = false - # User and Group for the files and user to run the service as. - $elasticsearch_user = 'elasticsearch' - $elasticsearch_group = 'elasticsearch' + $purge_package_dir = false - # Purge configuration directory - $purge_confdir = true + # package download timeout + $package_dl_timeout = 600 # 300 seconds is default of puppet - ## init service provider + $default_logging_level = 'INFO' - # configuration directory - $confdir = '/etc/elasticsearch' + $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', + } - # plugins directory - $plugindir = '/usr/share/elasticsearch/plugins' + #### Internal module values - # plugins helper binary - $plugintool = '/usr/share/elasticsearch/bin/plugin' + # 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 - $dlcmd = 'wget -O' - $purge_package_dir = false + 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}\"") + } + } - #### Internal module values + # 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': { + 'RedHat', 'CentOS', 'Fedora', 'Scientific', 'Amazon', 'OracleLinux', 'SLC': { # main application $package = [ 'elasticsearch' ] } @@ -81,6 +121,9 @@ # main application $package = [ 'elasticsearch' ] } + 'OpenSuSE': { + $package = [ 'elasticsearch' ] + } default: { fail("\"${module_name}\" provides no package default value for \"${::operatingsystem}\"") @@ -89,29 +132,84 @@ # service parameters case $::operatingsystem { - 'RedHat', 'CentOS', 'Fedora', 'Scientific', 'Amazon', 'OracleLinux': { + 'RedHat', 'CentOS', 'Fedora', 'Scientific', 'OracleLinux', 'SLC': { $service_name = 'elasticsearch' $service_hasrestart = true $service_hasstatus = true $service_pattern = $service_name - $service_providers = [ 'init' ] $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' + } + } - 'Debian', 'Ubuntu': { + '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 - $service_providers = [ 'init' ] $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' ] + $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 diff --git a/puphpet/puppet/modules/elasticsearch/manifests/plugin.pp b/puphpet/puppet/modules/elasticsearch/manifests/plugin.pp index 025c302..5e8dc01 100644 --- a/puphpet/puppet/modules/elasticsearch/manifests/plugin.pp +++ b/puphpet/puppet/modules/elasticsearch/manifests/plugin.pp @@ -12,7 +12,7 @@ # Directory name where the module will be installed # Value type is string # Default value: None -# This variable is required +# This variable is deprecated # # [*ensure*] # Whether the plugin will be installed or removed. @@ -27,6 +27,28 @@ # 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 # @@ -43,54 +65,83 @@ # # * Matteo Sessa # * Dennis Konert +# * Richard Pijnenburg # define elasticsearch::plugin( - $module_dir, + $instances, + $module_dir = undef, $ensure = 'present', - $url = '' + $url = undef, + $source = undef, + $proxy_host = undef, + $proxy_port = undef, ) { - Exec { - path => [ '/bin', '/usr/bin', '/usr/local/bin' ], - cwd => '/', - } + include elasticsearch $notify_service = $elasticsearch::restart_on_change ? { false => undef, - default => Service['elasticsearch'], + default => Elasticsearch::Service[$instances], + } + + if ($module_dir != undef) { + warning("module_dir settings is deprecated for plugin ${name}. The directory is now auto detected.") } - if ($module_dir != '') { - validate_string($module_dir) - } else { - fail("module_dir undefined for plugin ${name}") + # 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) { - if ($url != '') { + $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) - $install_cmd = "${elasticsearch::plugintool} -install ${name} -url ${url}" - $exec_rets = [0,1] - } else { - $install_cmd = "${elasticsearch::plugintool} -install ${name}" - $exec_rets = [0,] } case $ensure { 'installed', 'present': { - exec {"install_plugin_${name}": - command => $install_cmd, - creates => "${elasticsearch::plugindir}/${module_dir}", - returns => $exec_rets, - notify => $notify_service, - require => Class['elasticsearch::package'] + + elasticsearch_plugin { $name: + ensure => 'present', + source => $file_source, + url => $url, + proxy_args => $proxy, + notify => $notify_service, + } + + } + 'absent': { + elasticsearch_plugin { $name: + ensure => absent, } } default: { - exec {"remove_plugin_${name}": - command => "${elasticsearch::plugintool} --remove ${module_dir}", - onlyif => "test -d ${elasticsearch::plugindir}/${module_dir}", - notify => $notify_service, - } + fail("${ensure} is not a valid ensure command.") } } } diff --git a/puphpet/puppet/modules/elasticsearch/manifests/python.pp b/puphpet/puppet/modules/elasticsearch/manifests/python.pp index e1d91a9..fee783a 100644 --- a/puphpet/puppet/modules/elasticsearch/manifests/python.pp +++ b/puphpet/puppet/modules/elasticsearch/manifests/python.pp @@ -3,7 +3,6 @@ # there are many python bindings for elasticsearch. This provides all # the ones we know about http://www.elasticsearch.org/guide/clients/ # -# # === Parameters # # [*ensure*] @@ -19,17 +18,14 @@ # (e.g. removal of created users, services, changed log settings, ...). # * This is thus destructive and should be used with care. # Defaults to present. - -# # # === Examples # # elasticsearch::python { 'pyes':; } # -# # === Authors # -# * Richard Pijnenburg +# * Richard Pijnenburg # define elasticsearch::python ( $ensure = 'present' @@ -65,8 +61,9 @@ } } - package { $name: + package { "python_${name}": ensure => $ensure, + name => $name, provider => $provider, } diff --git a/puphpet/puppet/modules/elasticsearch/manifests/repo.pp b/puphpet/puppet/modules/elasticsearch/manifests/repo.pp new file mode 100644 index 0000000..36cd549 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/manifests/repo.pp @@ -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 +# * Richard Pijnenburg +# +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}\".") + } + } +} diff --git a/puphpet/puppet/modules/elasticsearch/manifests/ruby.pp b/puphpet/puppet/modules/elasticsearch/manifests/ruby.pp index 3e35f41..aba0bd7 100644 --- a/puphpet/puppet/modules/elasticsearch/manifests/ruby.pp +++ b/puphpet/puppet/modules/elasticsearch/manifests/ruby.pp @@ -3,7 +3,6 @@ # there are many ruby bindings for elasticsearch. This provides all # the ones we know about http://www.elasticsearch.org/guide/clients/ # -# # === Parameters # # [*ensure*] @@ -19,14 +18,11 @@ # (e.g. removal of created users, services, changed log settings, ...). # * This is thus destructive and should be used with care. # Defaults to present. - -# # # === Examples # # elasticsearch::ruby { 'elasticsearch':; } # -# # === Authors # # * Richard Pijnenburg @@ -54,13 +50,17 @@ 'elasticsearch': { $provider = 'gem' } + 'flex': { + $provider = 'gem' + } default: { fail("unknown ruby client package '${name}'") } } - package { $name: + package { "ruby_${name}": ensure => $ensure, + name => $name, provider => $provider, } diff --git a/puphpet/puppet/modules/elasticsearch/manifests/script.pp b/puphpet/puppet/modules/elasticsearch/manifests/script.pp new file mode 100644 index 0000000..b234869 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/manifests/script.pp @@ -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 present or +# absent. If set to absent: +# * 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 present. +# +# [*source*] +# Puppet source of the script +# Value type is string +# Default value: undef +# This variable is mandatory +# +# === Authors +# +# * Richard Pijnenburg +# +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', + } +} diff --git a/puphpet/puppet/modules/elasticsearch/manifests/service.pp b/puphpet/puppet/modules/elasticsearch/manifests/service.pp index 891f559..7cd0dfa 100644 --- a/puphpet/puppet/modules/elasticsearch/manifests/service.pp +++ b/puphpet/puppet/modules/elasticsearch/manifests/service.pp @@ -10,32 +10,80 @@ # # === Parameters # -# This class does not provide any parameters. +# [*ensure*] +# String. Controls if the managed resources shall be present or +# absent. If set to absent: +# * 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 present. # +# [*status*] +# String to define the status of the service. Possible values: +# * enabled: Service is running and will be started at boot time. +# * disabled: Service is stopped and will not be started at boot +# time. +# * running: 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. +# * unmanaged: 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 enabled. 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 service.pp to check if this is the +# case). # -# === Examples +# [*init_defaults*] +# Defaults file content in hash representation # -# This class may be imported by other classes to use its functionality: -# class { 'elasticsearch::service': } -# -# It is not intended to be used directly by external resources like node -# definitions or other modules. +# [*init_defaults_file*] +# Defaults file as puppet resource # +# [*init_template*] +# Service file as a template # # === Authors # -# * Richard Pijnenburg +# * Richard Pijnenburg # -class elasticsearch::service { +define elasticsearch::service( + $ensure = $elasticsearch::ensure, + $status = $elasticsearch::status, + $init_defaults_file = undef, + $init_defaults = undef, + $init_template = undef, +) { - case $elasticsearch::service_provider { + case $elasticsearch::real_service_provider { - init: { - elasticsearch::service::init { 'elasticsearch': } + '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::service_provider}") + fail("Unknown service provider ${elasticsearch::real_service_provider}") } } diff --git a/puphpet/puppet/modules/elasticsearch/manifests/service/init.pp b/puphpet/puppet/modules/elasticsearch/manifests/service/init.pp index 2db645c..0d37e1d 100644 --- a/puphpet/puppet/modules/elasticsearch/manifests/service/init.pp +++ b/puphpet/puppet/modules/elasticsearch/manifests/service/init.pp @@ -10,23 +10,64 @@ # # === Parameters # -# This class does not provide any parameters. +# [*ensure*] +# String. Controls if the managed resources shall be present or +# absent. If set to absent: +# * 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 present. # +# [*status*] +# String to define the status of the service. Possible values: +# * enabled: Service is running and will be started at boot time. +# * disabled: Service is stopped and will not be started at boot +# time. +# * running: 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. +# * unmanaged: 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 enabled. 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 service.pp to check if this is the +# case). # -# === Examples +# [*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 +# * Richard Pijnenburg # -define elasticsearch::service::init{ +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 $elasticsearch::ensure == 'present' { + if $ensure == 'present' { - case $elasticsearch::status { + case $status { # make sure service is currently running, start it on boot 'enabled': { $service_ensure = 'running' @@ -52,7 +93,7 @@ # note: don't forget to update the parameter check in init.pp if you # add a new or change an existing status. default: { - fail("\"${elasticsearch::status}\" is an unknown service status value") + fail("\"${status}\" is an unknown service status value") } } @@ -67,66 +108,88 @@ } $notify_service = $elasticsearch::restart_on_change ? { - true => Service[$name], + true => Service["elasticsearch-instance-${name}"], false => undef, } - if ( $elasticsearch::status != 'unmanaged' ) { + if ( $status != 'unmanaged' and $ensure == 'present' ) { # defaults file content. Either from a hash or file - if ($elasticsearch::init_defaults_file != undef) { - $defaults_content = undef - $defaults_source = $elasticsearch::init_defaults_file - } elsif ($elasticsearch::init_defaults != undef and is_hash($elasticsearch::init_defaults) ) { - $defaults_content = template("${module_name}/etc/sysconfig/defaults.erb") - $defaults_source = undef - } else { - $defaults_content = undef - $defaults_source = undef - } + 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, + } - # Check if we are going to manage the defaults file. - if ( $defaults_content != undef or $defaults_source != undef ) { + } elsif ($init_defaults != undef and is_hash($init_defaults) ) { - file { "${elasticsearch::params::defaults_location}/${name}": - ensure => $elasticsearch::ensure, - source => $defaults_source, - content => $defaults_content, - owner => 'root', - group => 'root', - mode => '0644', - before => Service[$name], - notify => $notify_service + 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 ($elasticsearch::init_template != undef) { + if ($init_template != undef) { - file { "/etc/init.d/${name}": - ensure => $elasticsearch::ensure, - content => template($elasticsearch::init_template), + file { "/etc/init.d/elasticsearch-${name}": + ensure => $ensure, + content => template($init_template), owner => 'root', group => 'root', mode => '0755', - before => Service[$name], - notify => $notify_service + 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}"], + } + } - # action - service { $name: - ensure => $service_ensure, - enable => $service_enable, - name => $elasticsearch::params::service_name, - hasstatus => $elasticsearch::params::service_hasstatus, - hasrestart => $elasticsearch::params::service_hasrestart, - pattern => $elasticsearch::params::service_pattern, + + 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, + } + } } diff --git a/puphpet/puppet/modules/elasticsearch/manifests/service/systemd.pp b/puphpet/puppet/modules/elasticsearch/manifests/service/systemd.pp new file mode 100644 index 0000000..fb7912f --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/manifests/service/systemd.pp @@ -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. +# +# Note: "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 present or +# absent. If set to absent: +# * 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 present. +# +# [*status*] +# String to define the status of the service. Possible values: +# * enabled: Service is running and will be started at boot time. +# * disabled: Service is stopped and will not be started at boot +# time. +# * running: 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. +# * unmanaged: 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 enabled. 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 service.pp 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 +# +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, + } + + } + +} diff --git a/puphpet/puppet/modules/elasticsearch/manifests/template.pp b/puphpet/puppet/modules/elasticsearch/manifests/template.pp index b8ab2a6..4de9316 100644 --- a/puphpet/puppet/modules/elasticsearch/manifests/template.pp +++ b/puphpet/puppet/modules/elasticsearch/manifests/template.pp @@ -4,22 +4,30 @@ # # === Parameters # +# [*ensure*] +# String. Controls if the managed resources shall be present or +# absent. If set to absent: +# * 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 present. +# # [*file*] # File path of the template ( json file ) # Value type is string # Default value: undef # This variable is optional # -# [*replace*] -# Set to 'true' if you intend to replace the existing template -# Value type is boolean -# Default value: false -# This variable is optional -# -# [*delete*] -# Set to 'true' if you intend to delete the existing template -# Value type is boolean -# Default value: false +# [*content*] +# Contents of the template ( json ) +# Value type is string +# Default value: undef # This variable is optional # # [*host*] @@ -36,11 +44,12 @@ # # === Authors # -# * Richard Pijnenburg +# * Richard Pijnenburg # define elasticsearch::template( $ensure = 'present', $file = undef, + $content = undef, $host = 'localhost', $port = 9200 ) { @@ -59,8 +68,8 @@ Exec { path => [ '/bin', '/usr/bin', '/usr/local/bin' ], cwd => '/', - tries => 3, - try_sleep => 10 + tries => 6, + try_sleep => 10, } # Build up the url @@ -70,10 +79,11 @@ if ($ensure == 'present') { - # Fail when no file is supplied - if $file == undef { - fail('The variable "file" cannot be empty when inserting or updating a template') - + # 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}" ] } @@ -90,23 +100,44 @@ command => "curl -s -XDELETE ${es_url}", onlyif => "test $(curl -s '${es_url}?pretty=true' | wc -l) -gt 1", notify => $insert_notify, - refreshonly => true + refreshonly => true, } - if ($ensure == 'present') { + if ($ensure == 'absent') { - # place the template file - file { "${elasticsearch::confdir}/templates_import/elasticsearch-template-${name}.json": - ensure => 'present', - source => $file, + # 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 => Exec[ 'mkdir_templates' ], + 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 -s -XPUT ${es_url} -d @${elasticsearch::confdir}/templates_import/elasticsearch-template-${name}.json", + 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 + refreshonly => true, + loglevel => 'debug', } } diff --git a/puphpet/puppet/modules/elasticsearch/metadata.json b/puphpet/puppet/modules/elasticsearch/metadata.json new file mode 100644 index 0000000..883fbfa --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/metadata.json @@ -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" + } + ] +} diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/001_basic_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/001_basic_spec.rb new file mode 100644 index 0000000..00c21e0 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/001_basic_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/002_class_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/002_class_spec.rb new file mode 100644 index 0000000..4486724 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/002_class_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/003_template_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/003_template_spec.rb new file mode 100644 index 0000000..ae5ab45 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/003_template_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/004_plugin_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/004_plugin_spec.rb new file mode 100644 index 0000000..be5f333 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/004_plugin_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/009_datapath_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/009_datapath_spec.rb new file mode 100644 index 0000000..a3d1d6e --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/009_datapath_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/010_pkg_url_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/010_pkg_url_spec.rb new file mode 100644 index 0000000..7275bd2 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/010_pkg_url_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/011_service_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/011_service_spec.rb new file mode 100644 index 0000000..07361c6 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/011_service_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/012_instances_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/012_instances_spec.rb new file mode 100644 index 0000000..ef7592a --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/012_instances_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/013_config_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/013_config_spec.rb new file mode 100644 index 0000000..d084545 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/013_config_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/014_hiera_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/014_hiera_spec.rb new file mode 100644 index 0000000..8c30a50 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/014_hiera_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/015_staged_removal.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/015_staged_removal.rb new file mode 100644 index 0000000..59d7fe9 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/015_staged_removal.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/016_package_pin_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/016_package_pin_spec.rb new file mode 100644 index 0000000..08526bd --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/016_package_pin_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/017_restart_on_change_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/017_restart_on_change_spec.rb new file mode 100644 index 0000000..88cf1ca --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/017_restart_on_change_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/020_usergroup_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/020_usergroup_spec.rb new file mode 100644 index 0000000..c5cfad8 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/020_usergroup_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/021_es2x_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/021_es2x_spec.rb new file mode 100644 index 0000000..f119fac --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/021_es2x_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/integration001.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/integration001.rb new file mode 100644 index 0000000..4de6807 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/integration001.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/centos-6-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/centos-6-x64.yml new file mode 100644 index 0000000..dfa73bf --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/centos-6-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/centos-7-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/centos-7-x64.yml new file mode 100644 index 0000000..e1ad5c8 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/centos-7-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-6-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-6-x64.yml new file mode 100644 index 0000000..e75328e --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-6-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-7-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-7-x64.yml new file mode 100644 index 0000000..0b23911 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-7-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-8-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-8-x64.yml new file mode 100644 index 0000000..acc224c --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/debian-8-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/opensuse-121-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/opensuse-121-x64.yml new file mode 100644 index 0000000..9c5b49c --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/opensuse-121-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/opensuse-131-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/opensuse-131-x64.yml new file mode 100644 index 0000000..442c652 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/opensuse-131-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/sles-11sp3-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/sles-11sp3-x64.yml new file mode 100644 index 0000000..afdfe56 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/sles-11sp3-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1204-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1204-x64.yml new file mode 100644 index 0000000..31c5777 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1204-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1210-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1210-x64.yml new file mode 100644 index 0000000..b402399 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1210-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1304-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1304-x64.yml new file mode 100644 index 0000000..b0f805d --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1304-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml new file mode 100644 index 0000000..cf97145 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml new file mode 100644 index 0000000..4e9b7ec --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/acceptance/xplugins001.rb b/puphpet/puppet/modules/elasticsearch/spec/acceptance/xplugins001.rb new file mode 100644 index 0000000..8618101 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/acceptance/xplugins001.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/classes/000_elasticsearch_init_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/classes/000_elasticsearch_init_spec.rb new file mode 100644 index 0000000..019ebc1 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/classes/000_elasticsearch_init_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/classes/001_elasticsearch_init_debian_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/classes/001_elasticsearch_init_debian_spec.rb deleted file mode 100644 index dd4b5c1..0000000 --- a/puphpet/puppet/modules/elasticsearch/spec/classes/001_elasticsearch_init_debian_spec.rb +++ /dev/null @@ -1,219 +0,0 @@ -require 'spec_helper' - -describe 'elasticsearch', :type => 'class' do - - [ 'Debian', 'Ubuntu'].each do |distro| - - context "on #{distro} OS" do - - let :facts do { - :operatingsystem => distro - } end - - context 'main class tests' do - - # init.pp - it { should contain_class('elasticsearch::package') } - it { should contain_class('elasticsearch::config') } - it { should contain_class('elasticsearch::service') } - - end - - context 'package installation' do - - context 'via repository' do - - context 'with default settings' do - - it { should contain_package('elasticsearch').with(:ensure => 'present') } - - end - - context 'with specified version' do - - let :params do { - :version => '1.0' - } end - - it { should contain_package('elasticsearch').with(:ensure => '1.0') } - end - - context 'with auto upgrade enabled' do - - let :params do { - :autoupgrade => true - } end - - it { should contain_package('elasticsearch').with(:ensure => 'latest') } - end - - end - - context 'when setting package version and package_url' do - - let :params do { - :version => '0.90.10', - :package_url => 'puppet:///path/to/some/elasticsearch-0.90.10.deb' - } end - - it { expect { should raise_error(Puppet::Error) } } - - end - - context 'via package_url setting' do - - context 'using puppet:/// schema' do - - let :params do { - :package_url => 'puppet:///path/to/package.deb' - } end - - it { should contain_file('/var/lib/elasticsearch/package.deb').with(:source => 'puppet:///path/to/package.deb', :backup => false) } - it { should contain_package('elasticsearch').with(:ensure => 'present', :source => '/var/lib/elasticsearch/package.deb', :provider => 'dpkg') } - end - - context 'using http:// schema' do - - let :params do { - :package_url => 'http://www.domain.com/path/to/package.deb' - } end - - it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /var/lib/elasticsearch') } - it { should contain_file('/var/lib/elasticsearch').with(:purge => false, :force => false, :require => "Exec[create_package_dir_elasticsearch]") } - it { should contain_exec('download_package_elasticsearch').with(:command => 'wget -O /var/lib/elasticsearch/package.deb http://www.domain.com/path/to/package.deb 2> /dev/null', :require => 'File[/var/lib/elasticsearch]') } - it { should contain_package('elasticsearch').with(:ensure => 'present', :source => '/var/lib/elasticsearch/package.deb', :provider => 'dpkg') } - end - - context 'using https:// schema' do - - let :params do { - :package_url => 'https://www.domain.com/path/to/package.deb' - } end - - it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /var/lib/elasticsearch') } - it { should contain_file('/var/lib/elasticsearch').with(:purge => false, :force => false, :require => 'Exec[create_package_dir_elasticsearch]') } - it { should contain_exec('download_package_elasticsearch').with(:command => 'wget -O /var/lib/elasticsearch/package.deb https://www.domain.com/path/to/package.deb 2> /dev/null', :require => 'File[/var/lib/elasticsearch]') } - it { should contain_package('elasticsearch').with(:ensure => 'present', :source => '/var/lib/elasticsearch/package.deb', :provider => 'dpkg') } - end - - context 'using ftp:// schema' do - - let :params do { - :package_url => 'ftp://www.domain.com/path/to/package.deb' - } end - - it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /var/lib/elasticsearch') } - it { should contain_file('/var/lib/elasticsearch').with(:purge => false, :force => false, :require => 'Exec[create_package_dir_elasticsearch]') } - it { should contain_exec('download_package_elasticsearch').with(:command => 'wget -O /var/lib/elasticsearch/package.deb ftp://www.domain.com/path/to/package.deb 2> /dev/null', :require => 'File[/var/lib/elasticsearch]') } - it { should contain_package('elasticsearch').with(:ensure => 'present', :source => '/var/lib/elasticsearch/package.deb', :provider => 'dpkg') } - end - - context 'using file:// schema' do - - let :params do { - :package_url => 'file:/path/to/package.deb' - } end - - it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /var/lib/elasticsearch') } - it { should contain_file('/var/lib/elasticsearch').with(:purge => false, :force => false, :require => 'Exec[create_package_dir_elasticsearch]') } - it { should contain_file('/var/lib/elasticsearch/package.deb').with(:source => '/path/to/package.deb', :backup => false) } - it { should contain_package('elasticsearch').with(:ensure => 'present', :source => '/var/lib/elasticsearch/package.deb', :provider => 'dpkg') } - end - - end - - end # package - - context 'service setup' do - - context 'with provider \'init\'' do - - context 'and default settings' do - - it { should contain_service('elasticsearch').with(:ensure => 'running') } - - end - - context 'and set defaults via hash param' do - - let :params do { - :init_defaults => { 'SERVICE_USER' => 'root', 'SERVICE_GROUP' => 'root' } - } end - - it { should contain_file('/etc/default/elasticsearch').with(:content => "### MANAGED BY PUPPET ###\n\nSERVICE_GROUP=root\nSERVICE_USER=root\n", :notify => 'Service[elasticsearch]') } - - end - - context 'and set defaults via file param' do - - let :params do { - :init_defaults_file => 'puppet:///path/to/elasticsearch.defaults' - } end - - it { should contain_file('/etc/default/elasticsearch').with(:source => 'puppet:///path/to/elasticsearch.defaults', :notify => 'Service[elasticsearch]') } - - end - - context 'no service restart when defaults change' do - - let :params do { - :init_defaults => { 'SERVICE_USER' => 'root', 'SERVICE_GROUP' => 'root' }, - :restart_on_change => false - } end - - it { should contain_file('/etc/default/elasticsearch').with(:content => "### MANAGED BY PUPPET ###\n\nSERVICE_GROUP=root\nSERVICE_USER=root\n").without_notify } - - end - - context 'and set init file via template' do - - let :params do { - :init_template => "elasticsearch/etc/init.d/elasticsearch.Debian.erb" - } end - - it { should contain_file('/etc/init.d/elasticsearch').with(:notify => 'Service[elasticsearch]') } - - end - - context 'No service restart when restart_on_change is false' do - - let :params do { - :init_template => "elasticsearch/etc/init.d/elasticsearch.Debian.erb", - :restart_on_change => false - } end - - it { should contain_file('/etc/init.d/elasticsearch').without_notify } - - end - - context 'when its unmanaged do nothing with it' do - - let :params do { - :status => 'unmanaged' - } end - - it { should contain_service('elasticsearch').with(:ensure => nil, :enable => false) } - - end - - end # provider init - - end # Services - - context 'when setting the module to absent' do - - let :params do { - :ensure => 'absent' - } end - - it { should contain_file('/etc/elasticsearch').with(:ensure => 'absent', :force => true, :recurse => true) } - it { should contain_package('elasticsearch').with(:ensure => 'purged') } - it { should contain_service('elasticsearch').with(:ensure => 'stopped', :enable => false) } - - end - - end - - end - -end diff --git a/puphpet/puppet/modules/elasticsearch/spec/classes/001_hiera_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/classes/001_hiera_spec.rb new file mode 100644 index 0000000..00025c9 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/classes/001_hiera_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/classes/002_elasticsearch_init_redhat_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/classes/002_elasticsearch_init_redhat_spec.rb deleted file mode 100644 index 9151b20..0000000 --- a/puphpet/puppet/modules/elasticsearch/spec/classes/002_elasticsearch_init_redhat_spec.rb +++ /dev/null @@ -1,219 +0,0 @@ -require 'spec_helper' - -describe 'elasticsearch', :type => 'class' do - - [ 'RedHat', 'CentOS', 'Fedora', 'Scientific', 'Amazon', 'OracleLinux' ].each do |distro| - - context "on #{distro} OS" do - - let :facts do { - :operatingsystem => distro - } end - - context 'Main class' do - - # init.pp - it { should contain_class('elasticsearch::package') } - it { should contain_class('elasticsearch::config') } - it { should contain_class('elasticsearch::service') } - - end - - context 'package installation' do - - context 'via repository' do - - context 'with default settings' do - - it { should contain_package('elasticsearch').with(:ensure => 'present') } - - end - - context 'with specified version' do - - let :params do { - :version => '1.0' - } end - - it { should contain_package('elasticsearch').with(:ensure => '1.0') } - end - - context 'with auto upgrade enabled' do - - let :params do { - :autoupgrade => true - } end - - it { should contain_package('elasticsearch').with(:ensure => 'latest') } - end - - end - - context 'when setting package version and package_url' do - - let :params do { - :version => '0.90.10', - :package_url => 'puppet:///path/to/some/elasticsearch-0.90.10.rpm' - } end - - it { expect { should raise_error(Puppet::Error) } } - - end - - context 'via package_url setting' do - - context 'using puppet:/// schema' do - - let :params do { - :package_url => 'puppet:///path/to/package.rpm' - } end - - it { should contain_file('/var/lib/elasticsearch/package.rpm').with(:source => 'puppet:///path/to/package.rpm', :backup => false) } - it { should contain_package('elasticsearch').with(:ensure => 'present', :source => '/var/lib/elasticsearch/package.rpm', :provider => 'rpm') } - end - - context 'using http:// schema' do - - let :params do { - :package_url => 'http://www.domain.com/path/to/package.rpm' - } end - - it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /var/lib/elasticsearch') } - it { should contain_file('/var/lib/elasticsearch').with(:purge => false, :force => false, :require => "Exec[create_package_dir_elasticsearch]") } - it { should contain_exec('download_package_elasticsearch').with(:command => 'wget -O /var/lib/elasticsearch/package.rpm http://www.domain.com/path/to/package.rpm 2> /dev/null', :require => 'File[/var/lib/elasticsearch]') } - it { should contain_package('elasticsearch').with(:ensure => 'present', :source => '/var/lib/elasticsearch/package.rpm', :provider => 'rpm') } - end - - context 'using https:// schema' do - - let :params do { - :package_url => 'https://www.domain.com/path/to/package.rpm' - } end - - it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /var/lib/elasticsearch') } - it { should contain_file('/var/lib/elasticsearch').with(:purge => false, :force => false, :require => 'Exec[create_package_dir_elasticsearch]') } - it { should contain_exec('download_package_elasticsearch').with(:command => 'wget -O /var/lib/elasticsearch/package.rpm https://www.domain.com/path/to/package.rpm 2> /dev/null', :require => 'File[/var/lib/elasticsearch]') } - it { should contain_package('elasticsearch').with(:ensure => 'present', :source => '/var/lib/elasticsearch/package.rpm', :provider => 'rpm') } - end - - context 'using ftp:// schema' do - - let :params do { - :package_url => 'ftp://www.domain.com/path/to/package.rpm' - } end - - it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /var/lib/elasticsearch') } - it { should contain_file('/var/lib/elasticsearch').with(:purge => false, :force => false, :require => 'Exec[create_package_dir_elasticsearch]') } - it { should contain_exec('download_package_elasticsearch').with(:command => 'wget -O /var/lib/elasticsearch/package.rpm ftp://www.domain.com/path/to/package.rpm 2> /dev/null', :require => 'File[/var/lib/elasticsearch]') } - it { should contain_package('elasticsearch').with(:ensure => 'present', :source => '/var/lib/elasticsearch/package.rpm', :provider => 'rpm') } - end - - context 'using file:// schema' do - - let :params do { - :package_url => 'file:/path/to/package.rpm' - } end - - it { should contain_exec('create_package_dir_elasticsearch').with(:command => 'mkdir -p /var/lib/elasticsearch') } - it { should contain_file('/var/lib/elasticsearch').with(:purge => false, :force => false, :require => 'Exec[create_package_dir_elasticsearch]') } - it { should contain_file('/var/lib/elasticsearch/package.rpm').with(:source => '/path/to/package.rpm', :backup => false) } - it { should contain_package('elasticsearch').with(:ensure => 'present', :source => '/var/lib/elasticsearch/package.rpm', :provider => 'rpm') } - end - - end - - end # package - - context 'service setup' do - - context 'with provider \'init\'' do - - context 'and default settings' do - - it { should contain_service('elasticsearch').with(:ensure => 'running') } - - end - - context 'and set defaults via hash param' do - - let :params do { - :init_defaults => { 'SERVICE_USER' => 'root', 'SERVICE_GROUP' => 'root' } - } end - - it { should contain_file('/etc/sysconfig/elasticsearch').with(:content => "### MANAGED BY PUPPET ###\n\nSERVICE_GROUP=root\nSERVICE_USER=root\n", :notify => 'Service[elasticsearch]') } - - end - - context 'and set defaults via file param' do - - let :params do { - :init_defaults_file => 'puppet:///path/to/elasticsearch.defaults' - } end - - it { should contain_file('/etc/sysconfig/elasticsearch').with(:source => 'puppet:///path/to/elasticsearch.defaults', :notify => 'Service[elasticsearch]') } - - end - - context 'no service restart when defaults change' do - - let :params do { - :init_defaults => { 'SERVICE_USER' => 'root', 'SERVICE_GROUP' => 'root' }, - :restart_on_change => false - } end - - it { should contain_file('/etc/sysconfig/elasticsearch').with(:content => "### MANAGED BY PUPPET ###\n\nSERVICE_GROUP=root\nSERVICE_USER=root\n").without_notify } - - end - - context 'and set init file via template' do - - let :params do { - :init_template => "elasticsearch/etc/init.d/elasticsearch.RedHat.erb" - } end - - it { should contain_file('/etc/init.d/elasticsearch').with(:notify => 'Service[elasticsearch]') } - - end - - context 'No service restart when restart_on_change is false' do - - let :params do { - :init_template => "elasticsearch/etc/init.d/elasticsearch.RedHat.erb", - :restart_on_change => false - } end - - it { should contain_file('/etc/init.d/elasticsearch').without_notify } - - end - - context 'when its unmanaged do nothing with it' do - - let :params do { - :status => 'unmanaged' - } end - - it { should contain_service('elasticsearch').with(:ensure => nil, :enable => false) } - - end - - end - - end # Services - - context 'when setting the module to absent' do - - let :params do { - :ensure => 'absent' - } end - - it { should contain_file('/etc/elasticsearch').with(:ensure => 'absent', :force => true, :recurse => true) } - it { should contain_package('elasticsearch').with(:ensure => 'purged') } - it { should contain_service('elasticsearch').with(:ensure => 'stopped', :enable => false) } - - end - - end - - end - -end diff --git a/puphpet/puppet/modules/elasticsearch/spec/classes/004_elasticsearch_init_config_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/classes/004_elasticsearch_init_config_spec.rb deleted file mode 100644 index 2f01fb5..0000000 --- a/puphpet/puppet/modules/elasticsearch/spec/classes/004_elasticsearch_init_config_spec.rb +++ /dev/null @@ -1,112 +0,0 @@ -require 'spec_helper' - -describe 'elasticsearch', :type => 'class' do - - let :facts do { - :operatingsystem => 'CentOS' - } end - - context "config file content" do - - context "with nothing set" do - - let :params do { - } end - - it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n") } - - end - - context "set a value" do - - let :params do { - :config => { 'node' => { 'name' => 'test' } } - } end - - it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n---\nnode: \n name: test\n") } - - end - - context "set a value to true" do - - let :params do { - :config => { 'node' => { 'master' => true } } - } end - - it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n---\nnode: \n master: true\n") } - - end - - context "set a value to false" do - - let :params do { - :config => { 'node' => { 'data' => false } } - } end - - it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n---\nnode: \n data: false\n") } - - end - - context "deeper hash and multiple keys" do - - let :params do { - :config => { 'index' => { 'routing' => { 'allocation' => { 'include' => 'tag1', 'exclude' => [ 'tag2', 'tag3' ] } } }, 'node' => { 'name' => 'somename' } } - } end - - it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n---\nindex: \n routing: \n allocation: \n exclude: \n - tag2\n - tag3\n include: tag1\nnode: \n name: somename\n") } - - end - - context "Combination of full hash and shorted write up keys" do - - let :params do { - :config => { 'node' => { 'name' => 'NodeName', 'rack' => 46 }, 'boostrap.mlockall' => true, 'cluster' => { 'name' => 'ClusterName', 'routing.allocation.awareness.attributes' => 'rack' }, 'discovery.zen' => { 'ping.unicast.hosts'=> [ "host1", "host2" ], 'minimum_master_nodes' => 3, 'ping.multicast.enabled' => false }, 'gateway' => { 'expected_nodes' => 4, 'recover_after_nodes' => 3 }, 'network.host' => '123.123.123.123' } - } end - - it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:content => "### MANAGED BY PUPPET ###\n---\nboostrap: \n mlockall: true\ncluster: \n name: ClusterName\n routing: \n allocation: \n awareness: \n attributes: rack\ndiscovery: \n zen: \n minimum_master_nodes: 3\n ping: \n multicast: \n enabled: false\n unicast: \n hosts: \n - host1\n - host2\ngateway: \n expected_nodes: 4\n recover_after_nodes: 3\nnetwork: \n host: 123.123.123.123\nnode: \n name: NodeName\n rack: 46\n") } - - end - - end - - context "service restarts" do - - let :facts do { - :operatingsystem => 'CentOS' - } end - - context "does not restart when restart_on_change is false" do - let :params do { - :config => { 'node' => { 'name' => 'test' } }, - :restart_on_change => false, - } end - - it { should contain_file('/etc/elasticsearch/elasticsearch.yml').without_notify } - end - - context "should happen restart_on_change is true (default)" do - let :params do { - :config => { 'node' => { 'name' => 'test' } }, - :restart_on_change => true, - } end - - it { should contain_file('/etc/elasticsearch/elasticsearch.yml').with(:notify => "Class[Elasticsearch::Service]") } - end - - end - - context 'data directory' do - let(:facts) do { - :operatingsystem => 'CentOS' - } end - - context 'should allow creating datadir' do - let(:params) do { - :datadir => '/foo' - } end - - it { should contain_file('/foo').with(:ensure => 'directory') } - end - - end -end diff --git a/puphpet/puppet/modules/elasticsearch/spec/classes/005_elasticsearch_java_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/classes/005_elasticsearch_java_spec.rb deleted file mode 100644 index d511087..0000000 --- a/puphpet/puppet/modules/elasticsearch/spec/classes/005_elasticsearch_java_spec.rb +++ /dev/null @@ -1,120 +0,0 @@ -require 'spec_helper' - -describe 'elasticsearch', :type => 'class' do - - context "install java" do - - let :params do { - :java_install => true, - :config => { 'node' => { 'name' => 'test' } } - } end - - context "On Debian OS" do - - let :facts do { - :operatingsystem => 'Debian' - } end - - it { should contain_package('openjdk-7-jre-headless') } - - end - - context "On Ubuntu OS" do - - let :facts do { - :operatingsystem => 'Ubuntu' - } end - - it { should contain_package('openjdk-7-jre-headless') } - - end - - context "On CentOS OS " do - - let :facts do { - :operatingsystem => 'CentOS' - } end - - it { should contain_package('java-1.7.0-openjdk') } - - end - - context "On RedHat OS " do - - let :facts do { - :operatingsystem => 'Redhat' - } end - - it { should contain_package('java-1.7.0-openjdk') } - - end - - context "On Fedora OS " do - - let :facts do { - :operatingsystem => 'Fedora' - } end - - it { should contain_package('java-1.7.0-openjdk') } - - end - - context "On Scientific OS " do - - let :facts do { - :operatingsystem => 'Scientific' - } end - - it { should contain_package('java-1.7.0-openjdk') } - - end - - context "On Amazon OS " do - - let :facts do { - :operatingsystem => 'Amazon' - } end - - it { should contain_package('java-1.7.0-openjdk') } - - end - - context "On OracleLinux OS " do - - let :facts do { - :operatingsystem => 'OracleLinux' - } end - - it { should contain_package('java-1.7.0-openjdk') } - - end - - context "On an unknown OS" do - - let :facts do { - :operatingsystem => 'Windows' - } end - - it { expect { should raise_error(Puppet::Error) } } - - end - - context "Custom java package" do - - let :facts do { - :operatingsystem => 'CentOS' - } end - - let :params do { - :java_install => true, - :java_package => 'java-1.6.0-openjdk', - :config => { 'node' => { 'name' => 'test' } } - } end - - it { should contain_package('java-1.6.0-openjdk') } - - end - - end - -end diff --git a/puphpet/puppet/modules/elasticsearch/spec/classes/005_elasticsearch_repo_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/classes/005_elasticsearch_repo_spec.rb new file mode 100644 index 0000000..1b34da5 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/classes/005_elasticsearch_repo_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/classes/003_elasticsearch_init_unknown_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/classes/010_elasticsearch_init_unkown_spec.rb similarity index 100% rename from puphpet/puppet/modules/elasticsearch/spec/classes/003_elasticsearch_init_unknown_spec.rb rename to puphpet/puppet/modules/elasticsearch/spec/classes/010_elasticsearch_init_unkown_spec.rb diff --git a/puphpet/puppet/modules/elasticsearch/spec/classes/099_coverage_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/classes/099_coverage_spec.rb new file mode 100644 index 0000000..12513b8 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/classes/099_coverage_spec.rb @@ -0,0 +1 @@ +at_exit { RSpec::Puppet::Coverage.report! } diff --git a/puphpet/puppet/modules/elasticsearch/spec/defines/001_elasticsearch_python_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/defines/001_elasticsearch_python_spec.rb index 56d0428..cd44209 100644 --- a/puphpet/puppet/modules/elasticsearch/spec/defines/001_elasticsearch_python_spec.rb +++ b/puphpet/puppet/modules/elasticsearch/spec/defines/001_elasticsearch_python_spec.rb @@ -2,7 +2,11 @@ describe 'elasticsearch::python', :type => 'define' do - let(:facts) { {:operatingsystem => 'CentOS' }} + let :facts do { + :operatingsystem => 'CentOS', + :kernel => 'Linux', + :osfamily => 'RedHat' + } end [ 'pyes', 'rawes', 'pyelasticsearch', 'ESClient', 'elasticutils', 'elasticsearch' ].each do |pythonlib| @@ -10,7 +14,8 @@ let(:title) { pythonlib } - it { should contain_package(pythonlib).with(:provider => 'pip') } + it { should contain_elasticsearch__python(pythonlib) } + it { should contain_package("python_#{pythonlib}").with(:provider => 'pip', :name => pythonlib) } end diff --git a/puphpet/puppet/modules/elasticsearch/spec/defines/002_elasticsearch_ruby_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/defines/002_elasticsearch_ruby_spec.rb index 6de94f7..8eb6a58 100644 --- a/puphpet/puppet/modules/elasticsearch/spec/defines/002_elasticsearch_ruby_spec.rb +++ b/puphpet/puppet/modules/elasticsearch/spec/defines/002_elasticsearch_ruby_spec.rb @@ -2,15 +2,20 @@ describe 'elasticsearch::ruby', :type => 'define' do - let(:facts) { {:operatingsystem => 'CentOS' }} + let :facts do { + :operatingsystem => 'CentOS', + :kernel => 'Linux', + :osfamily => 'RedHat' + } end - [ 'tire', 'stretcher', 'elastic_searchable', 'elasticsearch'].each do |rubylib| + [ 'tire', 'stretcher', 'elastic_searchable', 'elasticsearch', 'flex'].each do |rubylib| context "installation of library #{rubylib}" do let(:title) { rubylib } - it { should contain_package(rubylib).with(:provider => 'gem') } + it { should contain_elasticsearch__ruby(rubylib) } + it { should contain_package("ruby_#{rubylib}").with(:provider => 'gem', :name => rubylib) } end diff --git a/puphpet/puppet/modules/elasticsearch/spec/defines/003_elasticsearch_template_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/defines/003_elasticsearch_template_spec.rb index 527fb11..d164265 100644 --- a/puphpet/puppet/modules/elasticsearch/spec/defines/003_elasticsearch_template_spec.rb +++ b/puphpet/puppet/modules/elasticsearch/spec/defines/003_elasticsearch_template_spec.rb @@ -2,8 +2,16 @@ describe 'elasticsearch::template', :type => 'define' do + let :facts do { + :operatingsystem => 'CentOS', + :kernel => 'Linux', + :osfamily => 'RedHat', + :operatingsystemmajrelease => '6', + :scenario => '', + :common => '' + } end + let(:title) { 'foo' } - let(:facts) { {:operatingsystem => 'CentOS' }} let(:pre_condition) { 'class {"elasticsearch": config => { "node" => {"name" => "test" }}}'} context "Add a template" do @@ -13,8 +21,9 @@ :file => 'puppet:///path/to/foo.json', } end - it { should contain_file('/etc/elasticsearch/templates_import/elasticsearch-template-foo.json').with(:source => 'puppet:///path/to/foo.json', :notify => "Exec[delete_template_foo]", :require => "Exec[mkdir_templates]") } - it { should contain_exec('insert_template_foo').with(:command => 'curl -s -XPUT http://localhost:9200/_template/foo -d @/etc/elasticsearch/templates_import/elasticsearch-template-foo.json', :unless => 'test $(curl -s \'http://localhost:9200/_template/foo?pretty=true\' | wc -l) -gt 1') } + 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 @@ -23,7 +32,8 @@ :ensure => 'absent' } end - it { should_not contain_file('/etc/elasticsearch/templates_import/elasticsearch-template-foo.json').with(:source => 'puppet:///path/to/foo.json') } + 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 @@ -33,11 +43,22 @@ let :params do { :file => 'puppet:///path/to/foo.json', :host => 'otherhost', - :port => '9201' + :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_file('/etc/elasticsearch/templates_import/elasticsearch-template-foo.json').with(:source => 'puppet:///path/to/foo.json') } - it { should contain_exec('insert_template_foo').with(:command => 'curl -s -XPUT http://otherhost:9201/_template/foo -d @/etc/elasticsearch/templates_import/elasticsearch-template-foo.json', :unless => 'test $(curl -s \'http://otherhost:9201/_template/foo?pretty=true\' | wc -l) -gt 1') } + 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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/defines/004_elasticsearch_plugin_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/defines/004_elasticsearch_plugin_spec.rb index dcf2170..1438d5c 100644 --- a/puphpet/puppet/modules/elasticsearch/spec/defines/004_elasticsearch_plugin_spec.rb +++ b/puphpet/puppet/modules/elasticsearch/spec/defines/004_elasticsearch_plugin_spec.rb @@ -2,28 +2,74 @@ describe 'elasticsearch::plugin', :type => 'define' do - let(:title) { 'mobz/elasticsearch-head' } - let(:facts) { {:operatingsystem => 'CentOS' }} + 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 "Add a plugin" do + context 'with module_dir' do - let :params do { - :ensure => 'present', - :module_dir => 'head', - } end + 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 - it { should contain_exec('install_plugin_mobz/elasticsearch-head').with(:command => '/usr/share/elasticsearch/bin/plugin -install mobz/elasticsearch-head', :creates => '/usr/share/elasticsearch/plugins/head') } end - context "Remove a plugin" do + context 'with url' do + + context "Add a plugin with full name" do - let :params do { - :ensure => 'absent', - :module_dir => 'head' - } end + 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 - it { should contain_exec('remove_plugin_mobz/elasticsearch-head').with(:command => '/usr/share/elasticsearch/bin/plugin --remove head', :onlyif => 'test -d /usr/share/elasticsearch/plugins/head') } 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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/defines/005_elasticsearch_instance_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/defines/005_elasticsearch_instance_spec.rb new file mode 100644 index 0000000..b4ef74a --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/defines/005_elasticsearch_instance_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/defines/006_elasticsearch_script_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/defines/006_elasticsearch_script_spec.rb new file mode 100644 index 0000000..f585389 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/defines/006_elasticsearch_script_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/defines/010_elasticsearch_service_init_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/defines/010_elasticsearch_service_init_spec.rb new file mode 100644 index 0000000..ae7e143 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/defines/010_elasticsearch_service_init_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/defines/011_elasticsearch_service_system_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/defines/011_elasticsearch_service_system_spec.rb new file mode 100644 index 0000000..0880899 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/defines/011_elasticsearch_service_system_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/fixtures/facts/facts_url1.json b/puphpet/puppet/modules/elasticsearch/spec/fixtures/facts/facts_url1.json new file mode 100644 index 0000000..bf5056a --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/fixtures/facts/facts_url1.json @@ -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" +} diff --git a/puphpet/puppet/modules/elasticsearch/spec/fixtures/facts/facts_url2.json b/puphpet/puppet/modules/elasticsearch/spec/fixtures/facts/facts_url2.json new file mode 100644 index 0000000..407517e --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/fixtures/facts/facts_url2.json @@ -0,0 +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}]}}} diff --git a/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hiera.yaml b/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hiera.yaml new file mode 100644 index 0000000..954cef4 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hiera.yaml @@ -0,0 +1,8 @@ +--- +:backends: yaml +:yaml: + :datadir: spec/fixtures/hiera/hieradata +:hierarchy: +- ! '%{scenario}' +- envs/%{common} +:logger: console diff --git a/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/envs/defaultinstance.yaml b/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/envs/defaultinstance.yaml new file mode 100644 index 0000000..9a66d51 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/envs/defaultinstance.yaml @@ -0,0 +1,5 @@ +--- +elasticsearch::instances: + default: + config: + node.name: 'default' diff --git a/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/multipleinstances.yaml b/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/multipleinstances.yaml new file mode 100644 index 0000000..9781b68 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/multipleinstances.yaml @@ -0,0 +1,8 @@ +--- +elasticsearch::instances: + es-01: + config: + node.name: 'es-01' + es-02: + config: + node.name: 'es-02' diff --git a/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleinstance.yaml b/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleinstance.yaml new file mode 100644 index 0000000..8df1930 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleinstance.yaml @@ -0,0 +1,5 @@ +--- +elasticsearch::instances: + es-01: + config: + node.name: 'es-01' diff --git a/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleplugin.yaml b/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleplugin.yaml new file mode 100644 index 0000000..2b5548f --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/fixtures/hiera/hieradata/singleplugin.yaml @@ -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' diff --git a/puphpet/puppet/modules/elasticsearch/spec/functions/es_facts_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/functions/es_facts_spec.rb new file mode 100644 index 0000000..d998696 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/functions/es_facts_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/functions/plugin_dir_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/functions/plugin_dir_spec.rb new file mode 100644 index 0000000..ab4cff1 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/functions/plugin_dir_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/lib/parser_validate_task.rb b/puphpet/puppet/modules/elasticsearch/spec/lib/parser_validate_task.rb deleted file mode 100644 index 27ab764..0000000 --- a/puphpet/puppet/modules/elasticsearch/spec/lib/parser_validate_task.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'find' -require 'pathname' -require 'rake' -require 'rspec/core/rake_task' - -desc "run Puppet parser validate" -task :parser_validate do - - pwd = ENV["PWD"] - puppet_file_paths = [] - Find.find(pwd) do |path| - puppet_file_paths << path if path =~ /.*\.pp$/ - end - - exit_code = 0 - puppet_file_paths.each do |puppetfile| - - pwdpath = Pathname.new(pwd) - pn = Pathname.new(puppetfile) - rel_path = pn.relative_path_from(pwdpath) - - print "Validating #{rel_path}.... " - $stdout.flush - - result = `puppet parser validate #{puppetfile}` - if $?.exitstatus == 0 - res = 'OK' - else - res = 'ERR' - end - - puts "#{res}" - - if $?.exitstatus != 0 - exit_code = 1 - end - end - exit exit_code - -end diff --git a/puphpet/puppet/modules/elasticsearch/spec/lib/template_check_task.rb b/puphpet/puppet/modules/elasticsearch/spec/lib/template_check_task.rb deleted file mode 100644 index f474823..0000000 --- a/puphpet/puppet/modules/elasticsearch/spec/lib/template_check_task.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'find' -require 'pathname' -require 'rake' -require 'rspec/core/rake_task' - -desc "Verify puppet templates" -task :template_verify do - - pwd = ENV["PWD"] - erb_file_paths = [] - Find.find(pwd) do |path| - erb_file_paths << path if path =~ /.*\.erb$/ - end - - exit_code = 0 - erb_file_paths.each do |erbfile| - - pwdpath = Pathname.new(pwd) - pn = Pathname.new(erbfile) - rel_path = pn.relative_path_from(pwdpath) - - result = `erb -P -x -T '-' #{erbfile} | ruby -c` - puts "Verifying #{rel_path}.... #{result}" - - if $?.exitstatus != 0 - exit_code = 1 - end - end - exit exit_code - -end diff --git a/puphpet/puppet/modules/elasticsearch/spec/spec_acceptance_common.rb b/puphpet/puppet/modules/elasticsearch/spec/spec_acceptance_common.rb new file mode 100644 index 0000000..5e90f87 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/spec_acceptance_common.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/spec_acceptance_integration.rb b/puphpet/puppet/modules/elasticsearch/spec/spec_acceptance_integration.rb new file mode 100644 index 0000000..c7135cf --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/spec_acceptance_integration.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/spec_helper.rb b/puphpet/puppet/modules/elasticsearch/spec/spec_helper.rb index dc7e9f4..ef1ed44 100644 --- a/puphpet/puppet/modules/elasticsearch/spec/spec_helper.rb +++ b/puphpet/puppet/modules/elasticsearch/spec/spec_helper.rb @@ -1,2 +1,15 @@ -require 'rubygems' 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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/spec_helper_acceptance.rb b/puphpet/puppet/modules/elasticsearch/spec/spec_helper_acceptance.rb new file mode 100644 index 0000000..bc1eca8 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/spec_helper_acceptance.rb @@ -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' diff --git a/puphpet/puppet/modules/elasticsearch/spec/unit/provider/plugin_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/unit/provider/plugin_spec.rb new file mode 100644 index 0000000..35e8758 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/unit/provider/plugin_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/spec/unit/type/plugin_spec.rb b/puphpet/puppet/modules/elasticsearch/spec/unit/type/plugin_spec.rb new file mode 100644 index 0000000..cdc6c08 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/spec/unit/type/plugin_spec.rb @@ -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 + diff --git a/puphpet/puppet/modules/elasticsearch/templates/etc/elasticsearch/elasticsearch.yml.erb b/puphpet/puppet/modules/elasticsearch/templates/etc/elasticsearch/elasticsearch.yml.erb index b93ccdc..4d5ff62 100644 --- a/puphpet/puppet/modules/elasticsearch/templates/etc/elasticsearch/elasticsearch.yml.erb +++ b/puphpet/puppet/modules/elasticsearch/templates/etc/elasticsearch/elasticsearch.yml.erb @@ -6,14 +6,14 @@ depth.times { spacer += " "} hash.keys.sort.each do |sorted_key| @yml_string += spacer + sorted_key + ": " - if hash[sorted_key].is_a?(Array) + 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) + elsif hash[sorted_key].is_a?(::Hash) @yml_string += "\n" recursive_hash_to_yml_string(hash[sorted_key], depth+1) else @@ -33,7 +33,7 @@ return_vals << stuff end else - if val.is_a?(Hash) + if val.is_a?(::Hash) transform(val).each do |stuff| return_vals << { key => stuff } end @@ -52,12 +52,12 @@ target = dup hash.keys.each do |key| - if hash[key].is_a? Hash and self[key].is_a? Hash + 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) + if hash[key].is_a?(::Array) && target[key].is_a?(::Array) target[key] = target[key] + hash[key] else target[key] = hash[key] @@ -71,12 +71,12 @@ # initial string @yml_string = "### MANAGED BY PUPPET ###\n" - if !scope.lookupvar('elasticsearch::config').empty? + if !@data.empty? @yml_string += "---\n" ## Transform shorted keys into full write up - transformed_config = transform(scope.lookupvar('elasticsearch::config')) + transformed_config = transform(@data) # Merge it back into a hash tmphash = { } diff --git a/puphpet/puppet/modules/elasticsearch/templates/etc/elasticsearch/logging.yml.erb b/puphpet/puppet/modules/elasticsearch/templates/etc/elasticsearch/logging.yml.erb new file mode 100644 index 0000000..e24d414 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/templates/etc/elasticsearch/logging.yml.erb @@ -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" diff --git a/puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.Debian.erb b/puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.Debian.erb index 220c2f8..cccc8db 100644 --- a/puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.Debian.erb +++ b/puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.Debian.erb @@ -1,27 +1,27 @@ #!/bin/sh # -# /etc/init.d/elasticsearch -- startup script for Elasticsearch +# /etc/init.d/elasticsearch-<%= @name %> -- startup script for Elasticsearch # # Written by Miquel van Smoorenburg . # Modified for Debian GNU/Linux by Ian Murdock . # Modified for Tomcat by Stefan Gybas . # Modified for Tomcat6 by Thierry Carrez . # Additional improvements by Jason Brittain . -# Modified by Nicolas Huray for ElasticSearch . +# Modified by Nicolas Huray for Elasticsearch . # ### BEGIN INIT INFO -# Provides: elasticsearch +# 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 -# Description: Starts elasticsearch using start-stop-daemon +# 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 -DESC="ElasticSearch Server" +NAME=elasticsearch-<%= @name %> +DESC="Elasticsearch Server <%= @name %>" DEFAULT=/etc/default/$NAME if [ `id -u` -ne 0 ]; then @@ -39,12 +39,13 @@ fi # The following variables can be overwritten in $DEFAULT -# Run ElasticSearch as this user ID and group ID +# 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-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" +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 @@ -54,7 +55,7 @@ for jdir in $JDK_DIRS; do done export JAVA_HOME -# Directory where the ElasticSearch binary distribution resides +# Directory where the Elasticsearch binary distribution resides ES_HOME=/usr/share/$NAME # Heap Size (defaults to 256m min, 1g max) @@ -75,21 +76,24 @@ MAX_OPEN_FILES=65535 # Maximum amount of locked memory #MAX_LOCKED_MEMORY= -# ElasticSearch log directory +# Elasticsearch log directory LOG_DIR=/var/log/$NAME -# ElasticSearch data directory +# Elasticsearch data directory DATA_DIR=/var/lib/$NAME -# ElasticSearch work directory +# Elasticsearch work directory WORK_DIR=/tmp/$NAME -# ElasticSearch configuration directory +# Elasticsearch configuration directory CONF_DIR=/etc/$NAME -# ElasticSearch configuration file (elasticsearch.yml) +# 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 @@ -100,12 +104,14 @@ fi # Define other required variables PID_FILE=/var/run/$NAME.pid DAEMON=$ES_HOME/bin/elasticsearch -DAEMON_OPTS="-p $PID_FILE -Des.default.config=$CONF_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" +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 @@ -153,14 +159,18 @@ case "$1" in 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 + if [ -f "$PID_FILE" ]; then start-stop-daemon --stop --pidfile "$PID_FILE" \ --user "$ES_USER" \ --retry=TERM/20/KILL/5 >/dev/null diff --git a/puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.RedHat.erb b/puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.RedHat.erb index 8d61151..3cab1f5 100644 --- a/puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.RedHat.erb +++ b/puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.RedHat.erb @@ -1,13 +1,13 @@ #!/bin/sh # -# elasticsearch +# elasticsearch<%= @name %> # # chkconfig: 2345 80 20 -# description: Starts and stops a single elasticsearch instance on this system +# description: Starts and stops a single elasticsearch instance on this system # ### BEGIN INIT INFO -# Provides: Elasticsearch +# Provides: Elasticsearch-<%= @name %> # Required-Start: $network $named # Required-Stop: $network $named # Default-Start: 2 3 4 5 @@ -32,7 +32,7 @@ if [ -f /etc/rc.d/init.d/functions ]; then fi exec="/usr/share/elasticsearch/bin/elasticsearch" -prog="elasticsearch" +prog="elasticsearch-<%= @name %>" pidfile=/var/run/elasticsearch/${prog}.pid [ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog @@ -41,11 +41,14 @@ 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 +if [ -n $USER ] && [ -z $ES_USER ] ; then ES_USER=$USER fi @@ -53,7 +56,7 @@ checkJava() { if [ -x "$JAVA_HOME/bin/java" ]; then JAVA="$JAVA_HOME/bin/java" else - JAVA=$(which java) + JAVA=`which java` fi if [ ! -x "$JAVA" ]; then @@ -76,13 +79,16 @@ start() { 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 -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 + 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 @@ -92,7 +98,7 @@ start() { stop() { echo -n $"Stopping $prog: " # stop it here, often "killproc $prog" - killproc -p $pidfile $prog + killproc -p $pidfile -d 20 $prog retval=$? echo [ $retval -eq 0 ] && rm -f $lockfile diff --git a/puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.systemd.erb b/puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.systemd.erb new file mode 100644 index 0000000..e725462 --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/templates/etc/init.d/elasticsearch.systemd.erb @@ -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 diff --git a/puphpet/puppet/modules/elasticsearch/templates/etc/sysconfig/defaults.erb b/puphpet/puppet/modules/elasticsearch/templates/etc/sysconfig/defaults.erb index b4e8af6..7dad4e0 100644 --- a/puphpet/puppet/modules/elasticsearch/templates/etc/sysconfig/defaults.erb +++ b/puphpet/puppet/modules/elasticsearch/templates/etc/sysconfig/defaults.erb @@ -1,5 +1,3 @@ -### MANAGED BY PUPPET ### - -<% scope.lookupvar('elasticsearch::init_defaults').sort.map do |key, value| -%> -<%= key %>=<%= value %> +<% @new_init_defaults.sort.map do |key, value| -%> +set <%= key %> '<%= value %>' <% end -%> diff --git a/puphpet/puppet/modules/elasticsearch/templates/usr/lib/tmpfiles.d/elasticsearch.conf.erb b/puphpet/puppet/modules/elasticsearch/templates/usr/lib/tmpfiles.d/elasticsearch.conf.erb new file mode 100644 index 0000000..ec6197d --- /dev/null +++ b/puphpet/puppet/modules/elasticsearch/templates/usr/lib/tmpfiles.d/elasticsearch.conf.erb @@ -0,0 +1 @@ +d <%= @pid_dir %> 0755 <%= @user %> <%= @group %> - - diff --git a/puphpet/puppet/modules/epel/Gemfile b/puphpet/puppet/modules/epel/Gemfile index 8bed6ce..4f4151a 100644 --- a/puphpet/puppet/modules/epel/Gemfile +++ b/puphpet/puppet/modules/epel/Gemfile @@ -1,16 +1,35 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -group :development, :test do - gem 'rake', :require => false - gem 'rspec-puppet', :require => false - gem 'puppetlabs_spec_helper', :require => false - gem 'puppet-lint', :require => false - gem 'puppet-syntax', :require => false - gem 'rspec-system-puppet', '~>2.0.0' +group :test do + gem "rake" + gem "puppet", ENV['PUPPET_GEM_VERSION'] || '~> 3.8.0' + gem "rspec", '< 3.2.0' + gem "rspec-puppet", :git => 'https://github.com/rodjek/rspec-puppet.git' + gem "puppetlabs_spec_helper" + gem "metadata-json-lint" + gem "rspec-puppet-facts" + gem 'rubocop', '0.33.0' + gem 'simplecov' + gem 'simplecov-console' + + gem "puppet-lint-absolute_classname-check" + gem "puppet-lint-leading_zero-check" + gem "puppet-lint-trailing_comma-check" + gem "puppet-lint-version_comparison-check" + gem "puppet-lint-classes_and_types_beginning_with_digits-check" + gem "puppet-lint-unquoted_string-check" +end + +group :development do + gem "travis" + gem "travis-lint" + gem "puppet-blacksmith" + gem "guard-rake" +end + +group :system_tests do + gem "beaker" + gem "beaker-rspec" + gem "beaker-puppet_install_helper" end -if puppetversion = ENV['PUPPET_GEM_VERSION'] - gem 'puppet', puppetversion, :require => false -else - gem 'puppet', :require => false -end \ No newline at end of file diff --git a/puphpet/puppet/modules/epel/Gemfile.lock b/puphpet/puppet/modules/epel/Gemfile.lock new file mode 100644 index 0000000..f31eead --- /dev/null +++ b/puphpet/puppet/modules/epel/Gemfile.lock @@ -0,0 +1,436 @@ +GIT + remote: https://github.com/rodjek/rspec-puppet.git + revision: 6d812bca89930354457d9fa06bafb28c62a17ccd + specs: + rspec-puppet (2.2.1.pre) + rspec + +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (2.2.8) + activesupport (4.2.5) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.3.8) + ast (2.1.0) + astrolabe (1.3.1) + parser (~> 2.2) + autoparse (0.3.3) + addressable (>= 2.3.1) + extlib (>= 0.9.15) + multi_json (>= 1.0.0) + aws-sdk (1.66.0) + aws-sdk-v1 (= 1.66.0) + aws-sdk-v1 (1.66.0) + json (~> 1.4) + nokogiri (>= 1.4.4) + backports (3.6.7) + beaker (2.29.1) + aws-sdk (~> 1.57) + beaker-answers (~> 0.0) + beaker-hiera (~> 0.0) + docker-api + fission (~> 0.4) + fog (~> 1.25, < 1.35.0) + fog-google (~> 0.0.9) + google-api-client (~> 0.8) + hocon (~> 0.1) + inifile (~> 2.0) + json (~> 1.8) + mime-types (~> 2.99) + minitest (~> 5.4) + net-scp (~> 1.2) + net-ssh (~> 2.9) + open_uri_redirections (~> 0.2.1) + rbvmomi (~> 1.8) + rsync (~> 1.0.9) + stringify-hash (~> 0.0) + unf (~> 0.1) + beaker-answers (0.3.2) + require_all (~> 1.3.2) + stringify-hash (~> 0.0.0) + beaker-hiera (0.1.1) + stringify-hash (~> 0.0.0) + beaker-puppet_install_helper (0.4.0) + beaker (~> 2.0) + beaker-rspec (4.0.0) + beaker (~> 2.0) + rspec + serverspec (~> 1.0) + specinfra (~> 1.0) + builder (3.2.2) + coderay (1.1.0) + colorize (0.7.7) + diff-lcs (1.2.5) + docile (1.1.5) + docker-api (1.23.0) + excon (>= 0.38.0) + json + domain_name (0.5.25) + unf (>= 0.0.5, < 1.0.0) + ethon (0.8.0) + ffi (>= 1.3.0) + excon (0.45.4) + extlib (0.9.16) + facter (2.4.4) + CFPropertyList (~> 2.2.6) + facterdb (0.3.0) + facter + jgrep + json + faraday (0.9.2) + multipart-post (>= 1.2, < 3) + faraday_middleware (0.10.0) + faraday (>= 0.7.4, < 0.10) + ffi (1.9.10) + fission (0.5.0) + CFPropertyList (~> 2.2) + fog (1.34.0) + fog-atmos + fog-aws (>= 0.6.0) + fog-brightbox (~> 0.4) + fog-core (~> 1.32) + fog-dynect (~> 0.0.2) + fog-ecloud (~> 0.1) + fog-google (>= 0.0.2) + fog-json + fog-local + fog-powerdns (>= 0.1.1) + fog-profitbricks + fog-radosgw (>= 0.0.2) + fog-riakcs + fog-sakuracloud (>= 0.0.4) + fog-serverlove + fog-softlayer + fog-storm_on_demand + fog-terremark + fog-vmfusion + fog-voxel + fog-xml (~> 0.1.1) + ipaddress (~> 0.5) + nokogiri (~> 1.5, >= 1.5.11) + fog-atmos (0.1.0) + fog-core + fog-xml + fog-aws (0.7.6) + fog-core (~> 1.27) + fog-json (~> 1.0) + fog-xml (~> 0.1) + ipaddress (~> 0.8) + fog-brightbox (0.10.0) + fog-core (~> 1.22) + fog-json + inflecto (~> 0.0.2) + fog-core (1.35.0) + builder + excon (~> 0.45) + formatador (~> 0.2) + fog-dynect (0.0.2) + fog-core + fog-json + fog-xml + fog-ecloud (0.3.0) + fog-core + fog-xml + fog-google (0.0.9) + fog-core + fog-json + fog-xml + fog-json (1.0.2) + fog-core (~> 1.0) + multi_json (~> 1.10) + fog-local (0.2.1) + fog-core (~> 1.27) + fog-powerdns (0.1.1) + fog-core (~> 1.27) + fog-json (~> 1.0) + fog-xml (~> 0.1) + fog-profitbricks (0.0.5) + fog-core + fog-xml + nokogiri + fog-radosgw (0.0.4) + fog-core (>= 1.21.0) + fog-json + fog-xml (>= 0.0.1) + fog-riakcs (0.1.0) + fog-core + fog-json + fog-xml + fog-sakuracloud (1.4.0) + fog-core + fog-json + fog-serverlove (0.1.2) + fog-core + fog-json + fog-softlayer (1.0.2) + fog-core + fog-json + fog-storm_on_demand (0.1.1) + fog-core + fog-json + fog-terremark (0.1.0) + fog-core + fog-xml + fog-vmfusion (0.1.0) + fission + fog-core + fog-voxel (0.1.0) + fog-core + fog-xml + fog-xml (0.1.2) + fog-core + nokogiri (~> 1.5, >= 1.5.11) + formatador (0.2.5) + gh (0.14.0) + addressable + backports + faraday (~> 0.8) + multi_json (~> 1.0) + net-http-persistent (>= 2.7) + net-http-pipeline + google-api-client (0.8.6) + activesupport (>= 3.2) + addressable (~> 2.3) + autoparse (~> 0.3) + extlib (~> 0.9) + faraday (~> 0.9) + googleauth (~> 0.3) + launchy (~> 2.4) + multi_json (~> 1.10) + retriable (~> 1.4) + signet (~> 0.6) + googleauth (0.4.2) + faraday (~> 0.9) + jwt (~> 1.4) + logging (~> 2.0) + memoist (~> 0.12) + multi_json (~> 1.11) + signet (~> 0.6) + guard (2.13.0) + formatador (>= 0.2.4) + listen (>= 2.7, <= 4.0) + lumberjack (~> 1.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.9.12) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-rake (1.0.0) + guard + rake + hiera (1.3.4) + json_pure + highline (1.7.8) + hirb (0.7.3) + hocon (0.9.3) + http-cookie (1.0.2) + domain_name (~> 0.5) + i18n (0.7.0) + inflecto (0.0.2) + inifile (2.0.2) + ipaddress (0.8.0) + jgrep (1.4.0) + json + json (1.8.3) + json_pure (1.8.3) + jwt (1.5.2) + launchy (2.4.3) + addressable (~> 2.3) + listen (3.0.5) + rb-fsevent (>= 0.9.3) + rb-inotify (>= 0.9) + little-plugger (1.1.4) + logging (2.0.0) + little-plugger (~> 1.1) + multi_json (~> 1.10) + lumberjack (1.0.9) + memoist (0.13.0) + metaclass (0.0.4) + metadata-json-lint (0.0.11) + json + spdx-licenses (~> 1.0) + method_source (0.8.2) + mime-types (2.99) + mini_portile2 (2.0.0) + minitest (5.8.3) + mocha (1.1.0) + metaclass (~> 0.0.1) + multi_json (1.11.2) + multipart-post (2.0.0) + nenv (0.2.0) + net-http-persistent (2.9.4) + net-http-pipeline (1.0.1) + net-scp (1.2.1) + net-ssh (>= 2.6.5) + net-ssh (2.9.2) + netrc (0.11.0) + nokogiri (1.6.7) + mini_portile2 (~> 2.0.0.rc2) + notiffany (0.0.8) + nenv (~> 0.1) + shellany (~> 0.0) + open_uri_redirections (0.2.1) + parser (2.2.3.0) + ast (>= 1.1, < 3.0) + powerpack (0.1.1) + pry (0.9.12.6) + coderay (~> 1.0) + method_source (~> 0.8) + slop (~> 3.4) + puppet (3.8.4) + facter (> 1.6, < 3) + hiera (~> 1.0) + json_pure + puppet-blacksmith (3.3.1) + puppet (>= 2.7.16) + rest-client + puppet-lint (1.1.0) + puppet-lint-absolute_classname-check (0.1.3) + puppet-lint (~> 1.0) + puppet-lint-classes_and_types_beginning_with_digits-check (0.1.0) + puppet-lint (~> 1.0) + puppet-lint-leading_zero-check (0.1.0) + puppet-lint (~> 1.0) + puppet-lint-trailing_comma-check (0.3.1) + puppet-lint (~> 1.0) + puppet-lint-unquoted_string-check (0.2.5) + puppet-lint (~> 1.0) + puppet-lint-version_comparison-check (0.1.2) + puppet-lint (~> 1.0) + puppet-syntax (2.0.0) + rake + puppetlabs_spec_helper (0.10.3) + mocha + puppet-lint + puppet-syntax + rake + rspec-puppet + pusher-client (0.6.2) + json + websocket (~> 1.0) + rainbow (2.0.0) + rake (10.4.2) + rb-fsevent (0.9.6) + rb-inotify (0.9.5) + ffi (>= 0.5.0) + rbvmomi (1.8.2) + builder + nokogiri (>= 1.4.1) + trollop + require_all (1.3.3) + rest-client (1.8.0) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 3.0) + netrc (~> 0.7) + retriable (1.4.1) + rspec (2.99.0) + rspec-core (~> 2.99.0) + rspec-expectations (~> 2.99.0) + rspec-mocks (~> 2.99.0) + rspec-core (2.99.2) + rspec-expectations (2.99.2) + diff-lcs (>= 1.1.3, < 2.0) + rspec-its (1.0.1) + rspec-core (>= 2.99.0.beta1) + rspec-expectations (>= 2.99.0.beta1) + rspec-mocks (2.99.4) + rspec-puppet-facts (1.3.0) + facter + facterdb (>= 0.3.0) + json + puppet + rsync (1.0.9) + rubocop (0.33.0) + astrolabe (~> 1.3) + parser (>= 2.2.2.5, < 3.0) + powerpack (~> 0.1) + rainbow (>= 1.99.1, < 3.0) + ruby-progressbar (~> 1.4) + ruby-progressbar (1.7.5) + serverspec (1.16.0) + highline + net-ssh + rspec (~> 2.99) + rspec-its + specinfra (~> 1.27) + shellany (0.0.1) + signet (0.6.1) + addressable (~> 2.3) + extlib (~> 0.9) + faraday (~> 0.9) + jwt (~> 1.5) + multi_json (~> 1.10) + simplecov (0.11.0) + docile (~> 1.1.0) + json (~> 1.8) + simplecov-html (~> 0.10.0) + simplecov-console (0.2.0) + colorize + hirb + simplecov + simplecov-html (0.10.0) + slop (3.6.0) + spdx-licenses (1.0.0) + json + specinfra (1.27.5) + stringify-hash (0.0.2) + thor (0.19.1) + thread_safe (0.3.5) + travis (1.8.0) + addressable (~> 2.3) + backports + faraday (~> 0.9) + faraday_middleware (~> 0.9, >= 0.9.1) + gh (~> 0.13) + highline (~> 1.6) + launchy (~> 2.1) + pry (~> 0.9, < 0.10) + pusher-client (~> 0.4) + typhoeus (~> 0.6, >= 0.6.8) + travis-lint (2.0.0) + json + trollop (2.1.2) + typhoeus (0.8.0) + ethon (>= 0.8.0) + tzinfo (1.2.2) + thread_safe (~> 0.1) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.1) + websocket (1.2.2) + +PLATFORMS + ruby + +DEPENDENCIES + beaker + beaker-puppet_install_helper + beaker-rspec + guard-rake + metadata-json-lint + puppet (~> 3.8.0) + puppet-blacksmith + puppet-lint-absolute_classname-check + puppet-lint-classes_and_types_beginning_with_digits-check + puppet-lint-leading_zero-check + puppet-lint-trailing_comma-check + puppet-lint-unquoted_string-check + puppet-lint-version_comparison-check + puppetlabs_spec_helper + rake + rspec (< 3.2.0) + rspec-puppet! + rspec-puppet-facts + rubocop (= 0.33.0) + simplecov + simplecov-console + travis + travis-lint + +BUNDLED WITH + 1.10.6 diff --git a/puphpet/puppet/modules/epel/README.md b/puphpet/puppet/modules/epel/README.md index 1230083..4cf6708 100644 --- a/puphpet/puppet/modules/epel/README.md +++ b/puphpet/puppet/modules/epel/README.md @@ -39,11 +39,11 @@ going. I am also the owner of the epel-release package, so in general this module should stay fairly up to date with the official upstream package. I just got sick of coding Puppet modules and basically having an assumption -that EPEL was setup or installed. I can now depend on this module instead. +that EPEL was setup or installed. I can now depend on this module instead. I realize it is fairly trivial to get EPEL setup. Every now-and-then however the path to epel-release changes because something changes in the package (mass -rebuild, rpm build macros updates, etc). This module will bypass the changing +rebuild, rpm build macros updates, etc). This module will bypass the changing URL and just setup the package mirrors. This does mean that if you are looking for RPM macros that are normally @@ -56,6 +56,28 @@ included with EPEL release, this will not have them. # ChangeLog +======= + + + 1.2.2 + * Add dep on stdlib for getvar function call + + 1.2.1 + * Minor fix that lets facter 1.6 still work + * Enforce strict variables + + 1.2.0 + * Rework testing to use TravisCI + * If you specify a baseurl, disable mirrorlist + + 1.1.1 + * Ensure that GPG keys are using short IDs (issue #33) + + 1.1.0 + * Default URLs to be https + * Add ability to include/exclude packages + + 1.0.2 * Update README with usage section. * Fix regression when os_maj_version fact was required * Ready for 1.0 - replace Modulefile with metadata.json @@ -67,6 +89,8 @@ included with EPEL release, this will not have them. * This is commonly used on Puppet Enterprise 3.x * This was tested using Puppet 3.3.0 on Centos5/6 * This was tested using Puppet 3.1.1 on Amazon's AWS Linux + * This was tested using Puppet 3.8 and Puppet 4 now as well! + * Note Ruby 2.2 and Puppet 3.8 are not yet friends. * I assume it will work on any RHEL variant (Amazon Linux is debatable as a variant) * Amazon Linux compatability not promised, as EPEL doesn't always work with it. @@ -74,16 +98,17 @@ included with EPEL release, this will not have them. * No functionality has been introduced that should break Puppet 2.6 or 2.7, but I am no longer testing these versions of Puppet as they are end-of-lifed from Puppet Labs. * This also assumes a facter of greater than 1.7.0 -- at least from a testing perspective. + * I'm not actively fixing bugs for anything in facter < 2 or puppet < 3.8 ## Unit tests Install the necessary gems - bundle install + bundle install --path vendor --without system_tests Run the RSpec and puppet-lint tests - bundle exec rake ci + bundle exec rake test ## System tests @@ -101,13 +126,20 @@ Apache Software License 2.0 * Chad Metcalf * Ewoud Kohl van Wijngaarden * Joseph Swick + * Mickaël Canévet * Matthaus Owens * Michael Stahnke * Michael Stahnke + * Nick Le Mouton * Pro Cabales * Proletaryo Cabales + * Rob Nelson + * Robert Story * Stefan Goethals * Tim Rupp * Trey Dockendorf * Troy Bollinger * Vlastimil Holer + +# Alternatives +If you're on CentOS 7, you can just `yum install epel-release` as it's in centos-extras. diff --git a/puphpet/puppet/modules/epel/Rakefile b/puphpet/puppet/modules/epel/Rakefile index 8056da0..2479ec4 100644 --- a/puphpet/puppet/modules/epel/Rakefile +++ b/puphpet/puppet/modules/epel/Rakefile @@ -1,34 +1,59 @@ +require 'rubygems' +require 'bundler/setup' + require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet/version' +require 'puppet/vendor/semantic/lib/semantic' unless Puppet.version.to_f < 3.6 require 'puppet-lint/tasks/puppet-lint' require 'puppet-syntax/tasks/puppet-syntax' -require 'rspec-system/rake_task' +require 'metadata-json-lint/rake_task' +require 'rubocop/rake_task' -task :default do - sh %{rake -T} +# These gems aren't always present, for instance +# on Travis with --without development +begin + require 'puppet_blacksmith/rake_tasks' +rescue LoadError # rubocop:disable Lint/HandleExceptions end -# Disable specific puppet-lint checks +RuboCop::RakeTask.new + exclude_paths = [ + "bundle/**/*", "pkg/**/*", "vendor/**/*", "spec/**/*", ] Rake::Task[:lint].clear + +PuppetLint.configuration.relative = true +PuppetLint.configuration.disable_80chars +PuppetLint.configuration.disable_class_inherits_from_params_class +PuppetLint.configuration.disable_class_parameter_defaults +PuppetLint.configuration.fail_on_warnings = true + PuppetLint::RakeTask.new :lint do |config| config.ignore_paths = exclude_paths - config.fail_on_warnings = true - config.log_format = "%{path}:%{linenumber}:%{check}:%{KIND}:%{message}" - config.disable_checks = ['80chars', 'class_inherits_from_params_class'] - #config.relative = true end -PuppetLint.configuration.relative = true PuppetSyntax.exclude_paths = exclude_paths -desc "Run rspec-puppet and puppet-lint tasks" -task :ci => [ +desc "Run acceptance tests" +RSpec::Core::RakeTask.new(:acceptance) do |t| + t.pattern = 'spec/acceptance' +end + +desc "Populate CONTRIBUTORS file" +task :contributors do + system("git log --format='%aN' | sort -u > CONTRIBUTORS") +end + +desc "Run syntax, lint, and spec tests." +task :test => [ + :metadata_lint, :syntax, :lint, + :rubocop, :spec, ] diff --git a/puphpet/puppet/modules/epel/checksums.json b/puphpet/puppet/modules/epel/checksums.json index e4c3d9f..3173c57 100644 --- a/puphpet/puppet/modules/epel/checksums.json +++ b/puphpet/puppet/modules/epel/checksums.json @@ -1,27 +1,28 @@ { - "Gemfile": "6ce1af927934995b67026beef67a6968", + "Gemfile": "869291f4658771f13435477eeb1a7058", + "Gemfile.lock": "afb9ac0f103ee2a0dd7f18bea393cac5", "LICENSE": "94f0b1430ad7e59227ccabf8232f81d5", - "README.md": "df353b3fcda1c0d81452fba7bde2b033", - "Rakefile": "bd793caa9d09295ca72db7ea4c644196", + "README.md": "cdea036cf2ccfb09063fd09c1117816e", + "Rakefile": "da9b01265a5ba19f41d723d376d5864b", "files/RPM-GPG-KEY-EPEL-5": "0466c259781def56dafe0a2cdc9de0c5", "files/RPM-GPG-KEY-EPEL-6": "d865e6b948a74cb03bc3401c0b01b785", "files/RPM-GPG-KEY-EPEL-7": "58fa8ae27c89f37b08429f04fd4a88cc", - "manifests/init.pp": "59fb3600cc12973d26f570a0966bd037", - "manifests/params.pp": "78a7da5f59d2773a69edae060a849f98", - "manifests/rpm_gpg_key.pp": "69086f12752a14b200e462afaa59a93c", - "metadata.json": "d64586abb152ae0b1472d128f0d66e61", - "spec/classes/epel_spec.rb": "94ffd25862024766d4bd77258f1af670", - "spec/classes/shared_base.rb": "3da138d7d6f8f80ca25d3789c88f8fac", - "spec/classes/shared_debuginfo.rb": "1aab2853e8ebca13576041589bca105d", + "manifests/init.pp": "d46a9aea1cc964487aa74bf7e7eb4431", + "manifests/params.pp": "8e271ea80e3eec73a350bcac809a2014", + "manifests/rpm_gpg_key.pp": "802b10226193de2fb5d8b5aebbd5d436", + "metadata.json": "03a903f192ed4619e51645637e11bbed", + "spec/classes/epel_spec.rb": "7f2fac8720e5e7fe37daa60c231e53f9", + "spec/classes/shared_base.rb": "c25da4905ce3660bafd364af02495e71", + "spec/classes/shared_debuginfo.rb": "dff797c10c17023d8c79af857cd9a301", "spec/classes/shared_gpgkey.rb": "014db1c9505e7612f0880fd7ba1df912", - "spec/classes/shared_source.rb": "233bc17c5bd8e32539da3e05239f187b", - "spec/classes/shared_testing.rb": "3846d608a58e01effbbb561b2fc0be6b", - "spec/classes/shared_testing_debuginfo.rb": "630c721801d715cd707219985d402b68", - "spec/classes/shared_testing_source.rb": "4fa0d65bd296e77e5688db9f5ced86bd", - "spec/defines/rpm_gpg_key_spec.rb": "c6febe02bc0a7a0c775160023a06b32c", + "spec/classes/shared_source.rb": "fadf9e25736b4ec6d34a37f5d1e8501c", + "spec/classes/shared_testing.rb": "81304e23484b371b0943880d843fc702", + "spec/classes/shared_testing_debuginfo.rb": "bc603db04c73cb5f4475bcb77d7adf56", + "spec/classes/shared_testing_source.rb": "9d2a6f8b0b6e73267ef1caea4ca2df6b", + "spec/defines/rpm_gpg_key_spec.rb": "c72ff01940d28df26a960eee122bf473", "spec/spec_helper.rb": "a5ad64bd67aa3fe2512fa7ba505c8e8b", "spec/spec_helper_system.rb": "d24a7ffdf4b67dbbd3ef5687292f51cf", "spec/system/basic_spec.rb": "49db07e43f690ac32a841b3125939450", "spec/system/usage_spec.rb": "68f7bd38e911009d74487c5f86b48555", - "tests/init.pp": "7c69b7adf2ba141cb62cfc9e0704d59e" + "tests/init.pp": "964d2df016bcb1c39760e8b32b6f1a0a" } \ No newline at end of file diff --git a/puphpet/puppet/modules/epel/manifests/init.pp b/puphpet/puppet/modules/epel/manifests/init.pp index bd8450f..88796dd 100644 --- a/puphpet/puppet/modules/epel/manifests/init.pp +++ b/puphpet/puppet/modules/epel/manifests/init.pp @@ -17,37 +17,49 @@ $epel_proxy = $epel::params::epel_proxy, $epel_enabled = $epel::params::epel_enabled, $epel_gpgcheck = $epel::params::epel_gpgcheck, + $epel_exclude = undef, + $epel_includepkgs = undef, $epel_testing_baseurl = $epel::params::epel_testing_baseurl, $epel_testing_failovermethod = $epel::params::epel_testing_failovermethod, $epel_testing_proxy = $epel::params::epel_testing_proxy, $epel_testing_enabled = $epel::params::epel_testing_enabled, $epel_testing_gpgcheck = $epel::params::epel_testing_gpgcheck, + $epel_testing_exclude = undef, + $epel_testing_includepkgs = undef, $epel_source_mirrorlist = $epel::params::epel_source_mirrorlist, $epel_source_baseurl = $epel::params::epel_source_baseurl, $epel_source_failovermethod = $epel::params::epel_source_failovermethod, $epel_source_proxy = $epel::params::epel_source_proxy, $epel_source_enabled = $epel::params::epel_source_enabled, $epel_source_gpgcheck = $epel::params::epel_source_gpgcheck, + $epel_source_exclude = undef, + $epel_source_includepkgs = undef, $epel_debuginfo_mirrorlist = $epel::params::epel_debuginfo_mirrorlist, $epel_debuginfo_baseurl = $epel::params::epel_debuginfo_baseurl, $epel_debuginfo_failovermethod = $epel::params::epel_debuginfo_failovermethod, $epel_debuginfo_proxy = $epel::params::epel_debuginfo_proxy, $epel_debuginfo_enabled = $epel::params::epel_debuginfo_enabled, $epel_debuginfo_gpgcheck = $epel::params::epel_debuginfo_gpgcheck, + $epel_debuginfo_exclude = undef, + $epel_debuginfo_includepkgs = undef, $epel_testing_source_baseurl = $epel::params::epel_testing_source_baseurl, $epel_testing_source_failovermethod = $epel::params::epel_testing_source_failovermethod, $epel_testing_source_proxy = $epel::params::epel_testing_source_proxy, $epel_testing_source_enabled = $epel::params::epel_testing_source_enabled, $epel_testing_source_gpgcheck = $epel::params::epel_testing_source_gpgcheck, + $epel_testing_source_exclude = undef, + $epel_testing_source_includepkgs = undef, $epel_testing_debuginfo_baseurl = $epel::params::epel_testing_debuginfo_baseurl, $epel_testing_debuginfo_failovermethod = $epel::params::epel_testing_debuginfo_failovermethod, $epel_testing_debuginfo_proxy = $epel::params::epel_testing_debuginfo_proxy, $epel_testing_debuginfo_enabled = $epel::params::epel_testing_debuginfo_enabled, $epel_testing_debuginfo_gpgcheck = $epel::params::epel_testing_debuginfo_gpgcheck, + $epel_testing_debuginfo_exclude = undef, + $epel_testing_debuginfo_includepkgs = undef, $os_maj_release = $epel::params::os_maj_release, ) inherits epel::params { - if $::osfamily == 'RedHat' and $::operatingsystem !~ /Fedora|Amazon/ { + if "${::osfamily}" == 'RedHat' and "${::operatingsystem}" !~ /Fedora|Amazon/ { # lint:ignore:only_variable_string yumrepo { 'epel-testing': baseurl => $epel_testing_baseurl, failovermethod => $epel_testing_failovermethod, @@ -56,6 +68,8 @@ gpgcheck => $epel_testing_gpgcheck, gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-${os_maj_release}", descr => "Extra Packages for Enterprise Linux ${os_maj_release} - Testing - \$basearch ", + exclude => $epel_testing_exclude, + includepkgs => $epel_testing_includepkgs, } yumrepo { 'epel-testing-debuginfo': @@ -66,6 +80,8 @@ gpgcheck => $epel_testing_debuginfo_gpgcheck, gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-${os_maj_release}", descr => "Extra Packages for Enterprise Linux ${os_maj_release} - Testing - \$basearch - Debug", + exclude => $epel_testing_debuginfo_exclude, + includepkgs => $epel_testing_debuginfo_includepkgs, } yumrepo { 'epel-testing-source': @@ -76,10 +92,17 @@ gpgcheck => $epel_testing_source_gpgcheck, gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-${os_maj_release}", descr => "Extra Packages for Enterprise Linux ${os_maj_release} - Testing - \$basearch - Source", + exclude => $epel_testing_source_exclude, + includepkgs => $epel_testing_source_includepkgs, } yumrepo { 'epel': - mirrorlist => $epel_mirrorlist, + # lint:ignore:selector_inside_resource + mirrorlist => $epel_baseurl ? { + 'absent' => $epel_mirrorlist, + default => 'absent', + }, + # lint:endignore baseurl => $epel_baseurl, failovermethod => $epel_failovermethod, proxy => $epel_proxy, @@ -87,10 +110,17 @@ gpgcheck => $epel_gpgcheck, gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-${os_maj_release}", descr => "Extra Packages for Enterprise Linux ${os_maj_release} - \$basearch", + exclude => $epel_exclude, + includepkgs => $epel_includepkgs, } yumrepo { 'epel-debuginfo': - mirrorlist => $epel_debuginfo_mirrorlist, + # lint:ignore:selector_inside_resource + mirrorlist => $epel_debuginfo_baseurl ? { + 'absent' => $epel_debuginfo_mirrorlist, + default => 'absent', + }, + # lint:endignore baseurl => $epel_debuginfo_baseurl, failovermethod => $epel_debuginfo_failovermethod, proxy => $epel_debuginfo_proxy, @@ -98,10 +128,17 @@ gpgcheck => $epel_debuginfo_gpgcheck, gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-${os_maj_release}", descr => "Extra Packages for Enterprise Linux ${os_maj_release} - \$basearch - Debug", + exclude => $epel_debuginfo_exclude, + includepkgs => $epel_debuginfo_includepkgs, } yumrepo { 'epel-source': - mirrorlist => $epel_source_mirrorlist, + # lint:ignore:selector_inside_resource + mirrorlist => $epel_source_baseurl ? { + 'absent' => $epel_source_mirrorlist, + default => 'absent', + }, + # lint:endignore baseurl => $epel_source_baseurl, failovermethod => $epel_source_failovermethod, proxy => $epel_source_proxy, @@ -109,6 +146,8 @@ gpgcheck => $epel_source_gpgcheck, gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-${os_maj_release}", descr => "Extra Packages for Enterprise Linux ${os_maj_release} - \$basearch - Source", + exclude => $epel_source_exclude, + includepkgs => $epel_source_includepkgs, } file { "/etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-${os_maj_release}": @@ -124,7 +163,7 @@ before => Yumrepo['epel','epel-source','epel-debuginfo','epel-testing','epel-testing-source','epel-testing-debuginfo'], } - } elsif $::osfamily == 'RedHat' and $::operatingsystem == 'Amazon' { + } elsif "${::osfamily}" == 'RedHat' and "${::operatingsystem}" == 'Amazon' { # lint:ignore:only_variable_string yumrepo { 'epel': enabled => $epel_enabled, gpgcheck => $epel_gpgcheck, @@ -132,5 +171,4 @@ } else { notice ("Your operating system ${::operatingsystem} will not have the EPEL repository applied") } - } diff --git a/puphpet/puppet/modules/epel/manifests/params.pp b/puphpet/puppet/modules/epel/manifests/params.pp index 2516a9f..ffe6127 100644 --- a/puphpet/puppet/modules/epel/manifests/params.pp +++ b/puphpet/puppet/modules/epel/manifests/params.pp @@ -8,42 +8,42 @@ # the most specific declaration of proxy. $proxy = 'absent' - if $::operatingsystemmajrelease { + if getvar('::operatingsystemmajrelease') { $os_maj_release = $::operatingsystemmajrelease } else { - $os_versions = split($::operatingsystemrelease, '[.]') + $os_versions = split("${::operatingsystemrelease}", '[.]') # lint:ignore:only_variable_string $os_maj_release = $os_versions[0] } - $epel_mirrorlist = "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-${os_maj_release}&arch=\$basearch" + $epel_mirrorlist = "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-${os_maj_release}&arch=\$basearch" $epel_baseurl = 'absent' $epel_failovermethod = 'priority' $epel_proxy = $proxy $epel_enabled = '1' $epel_gpgcheck = '1' - $epel_testing_baseurl = "http://download.fedoraproject.org/pub/epel/testing/${os_maj_release}/\$basearch" + $epel_testing_baseurl = "https://download.fedoraproject.org/pub/epel/testing/${os_maj_release}/\$basearch" $epel_testing_failovermethod = 'priority' $epel_testing_proxy = $proxy $epel_testing_enabled = '0' $epel_testing_gpgcheck = '1' - $epel_source_mirrorlist = "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-${os_maj_release}&arch=\$basearch" + $epel_source_mirrorlist = "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-${os_maj_release}&arch=\$basearch" $epel_source_baseurl = 'absent' $epel_source_failovermethod = 'priority' $epel_source_proxy = $proxy $epel_source_enabled = '0' $epel_source_gpgcheck = '1' - $epel_debuginfo_mirrorlist = "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-${os_maj_release}&arch=\$basearch" + $epel_debuginfo_mirrorlist = "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-${os_maj_release}&arch=\$basearch" $epel_debuginfo_baseurl = 'absent' $epel_debuginfo_failovermethod = 'priority' $epel_debuginfo_proxy = $proxy $epel_debuginfo_enabled = '0' $epel_debuginfo_gpgcheck = '1' - $epel_testing_source_baseurl = "http://download.fedoraproject.org/pub/epel/testing/${os_maj_release}/SRPMS" + $epel_testing_source_baseurl = "https://download.fedoraproject.org/pub/epel/testing/${os_maj_release}/SRPMS" $epel_testing_source_failovermethod = 'priority' $epel_testing_source_proxy = $proxy $epel_testing_source_enabled = '0' $epel_testing_source_gpgcheck = '1' - $epel_testing_debuginfo_baseurl = "http://download.fedoraproject.org/pub/epel/testing/${os_maj_release}/\$basearch/debug" + $epel_testing_debuginfo_baseurl = "https://download.fedoraproject.org/pub/epel/testing/${os_maj_release}/\$basearch/debug" $epel_testing_debuginfo_failovermethod = 'priority' $epel_testing_debuginfo_proxy = $proxy $epel_testing_debuginfo_enabled = '0' diff --git a/puphpet/puppet/modules/epel/manifests/rpm_gpg_key.pp b/puphpet/puppet/modules/epel/manifests/rpm_gpg_key.pp index ee0604d..f3ade7a 100644 --- a/puphpet/puppet/modules/epel/manifests/rpm_gpg_key.pp +++ b/puphpet/puppet/modules/epel/manifests/rpm_gpg_key.pp @@ -21,7 +21,7 @@ exec { "import-${name}": path => '/bin:/usr/bin:/sbin:/usr/sbin', command => "rpm --import ${path}", - unless => "rpm -q gpg-pubkey-$(echo $(gpg --throw-keyids < ${path}) | cut --characters=11-18 | tr '[A-Z]' '[a-z]')", + unless => "rpm -q gpg-pubkey-$(echo $(gpg --throw-keyids --keyid-format short < ${path}) | cut --characters=11-18 | tr '[A-Z]' '[a-z]')", require => File[$path], logoutput => 'on_failure', } diff --git a/puphpet/puppet/modules/epel/metadata.json b/puphpet/puppet/modules/epel/metadata.json index b8af3ca..328d712 100644 --- a/puphpet/puppet/modules/epel/metadata.json +++ b/puphpet/puppet/modules/epel/metadata.json @@ -1,9 +1,9 @@ { "name": "stahnma-epel", - "version": "1.0.2", + "version": "1.2.2", "author": "stahnma", "summary": "Setup the EPEL package repo", - "license": "Apache License, Version 2.0", + "license": "Apache-2.0", "source": "http://github.com/stahnma/puppet-module-epel", "project_page": "http://github.com/stahnma/puppet-module-epel", "issues_url": "https://github.com/stahnma/puppet-module-epel/issues", @@ -61,6 +61,6 @@ ], "description": "Setup the EPEL package repo on Centos/RHEL et al", "dependencies": [ - + {"name":"puppetlabs/stdlib","version_requirement":">= 3.0.0"} ] } diff --git a/puphpet/puppet/modules/epel/spec/classes/epel_spec.rb b/puphpet/puppet/modules/epel/spec/classes/epel_spec.rb index 0522b7c..0b915d1 100644 --- a/puphpet/puppet/modules/epel/spec/classes/epel_spec.rb +++ b/puphpet/puppet/modules/epel/spec/classes/epel_spec.rb @@ -28,14 +28,15 @@ it_behaves_like :epel_testing_source_7 it_behaves_like :epel_testing_debuginfo_7 - context 'epel_baseurl => http://example.com/epel/7/x87_74' do - let(:params) {{ :epel_baseurl => "http://example.com/epel/7/x87_74" }} - it { should contain_yumrepo('epel').with('baseurl' => 'http://example.com/epel/7/x87_74') } + context 'epel_baseurl => https://example.com/epel/7/x87_74' do + let(:params) {{ :epel_baseurl => "https://example.com/epel/7/x87_74" }} + it { should contain_yumrepo('epel').with('baseurl' => 'https://example.com/epel/7/x87_74') } + it { should contain_yumrepo('epel').with('mirrorlist' => 'absent') } end - + context 'epel_mirrorlist => absent' do let(:params) {{ :epel_mirrorlist => 'absent' }} - it { should contain_yumrepo('epel').with('mirrorlist' => 'absent') } + it { should contain_yumrepo('epel').with('mirrorlist' => 'absent') } end context 'operatingsystemmajrelease undef' do @@ -58,8 +59,8 @@ context 'operatingsystemmajrelease => 6' do let :facts do default_facts.merge({ - :operatingsystemrelease => '6.4', - :operatingsystemmajrelease => '6', + :operatingsystemrelease => '6.4', + :operatingsystemmajrelease => '6', }) end @@ -71,14 +72,15 @@ it_behaves_like :epel_testing_source_6 it_behaves_like :epel_testing_debuginfo_6 - context 'epel_baseurl => http://example.com/epel/6/x86_64' do - let(:params) {{ :epel_baseurl => "http://example.com/epel/6/x86_64" }} - it { should contain_yumrepo('epel').with('baseurl' => 'http://example.com/epel/6/x86_64') } + context 'epel_baseurl => https://example.com/epel/6/x86_64' do + let(:params) {{ :epel_baseurl => "https://example.com/epel/6/x86_64" }} + it { should contain_yumrepo('epel').with('baseurl' => 'https://example.com/epel/6/x86_64') } + it { should contain_yumrepo('epel').with('mirrorlist' => 'absent') } end - + context 'epel_mirrorlist => absent' do let(:params) {{ :epel_mirrorlist => 'absent' }} - it { should contain_yumrepo('epel').with('mirrorlist' => 'absent') } + it { should contain_yumrepo('epel').with('mirrorlist' => 'absent') } end context 'operatingsystemmajrelease undef' do @@ -101,8 +103,8 @@ context 'operatingsystemmajrelease => 5' do let :facts do default_facts.merge({ - :operatingsystemrelease => '5.9', - :operatingsystemmajrelease => '5', + :operatingsystemrelease => '5.9', + :operatingsystemmajrelease => '5', }) end @@ -119,7 +121,7 @@ context 'operatingsystem => Amazon' do let :facts do default_facts.merge({ - :operatingsystem => 'Amazon', + :operatingsystem => 'Amazon', }) end @@ -131,8 +133,8 @@ it do should contain_yumrepo('epel').with({ - 'enabled' => '1', - 'gpgcheck' => '1', + 'enabled' => '1', + 'gpgcheck' => '1', }) end end diff --git a/puphpet/puppet/modules/epel/spec/classes/shared_base.rb b/puphpet/puppet/modules/epel/spec/classes/shared_base.rb index e23c54f..0882f8e 100644 --- a/puphpet/puppet/modules/epel/spec/classes/shared_base.rb +++ b/puphpet/puppet/modules/epel/spec/classes/shared_base.rb @@ -16,7 +16,7 @@ it do should contain_yumrepo('epel').with({ - 'mirrorlist' => "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-7&arch=$basearch", + 'mirrorlist' => "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-7&arch=$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7", 'descr' => "Extra Packages for Enterprise Linux 7 - $basearch", }) @@ -28,7 +28,7 @@ it do should contain_yumrepo('epel').with({ - 'mirrorlist' => "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-6&arch=$basearch", + 'mirrorlist' => "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-6&arch=$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6", 'descr' => "Extra Packages for Enterprise Linux 6 - $basearch", }) @@ -40,7 +40,7 @@ it do should contain_yumrepo('epel').with({ - 'mirrorlist' => "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-5&arch=$basearch", + 'mirrorlist' => "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-5&arch=$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-5", 'descr' => "Extra Packages for Enterprise Linux 5 - $basearch", }) diff --git a/puphpet/puppet/modules/epel/spec/classes/shared_debuginfo.rb b/puphpet/puppet/modules/epel/spec/classes/shared_debuginfo.rb index f1f2902..7fb5c9c 100644 --- a/puphpet/puppet/modules/epel/spec/classes/shared_debuginfo.rb +++ b/puphpet/puppet/modules/epel/spec/classes/shared_debuginfo.rb @@ -16,7 +16,7 @@ it do should contain_yumrepo('epel-debuginfo').with({ - 'mirrorlist' => "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-7&arch=$basearch", + 'mirrorlist' => "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-7&arch=$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7", 'descr' => "Extra Packages for Enterprise Linux 7 - $basearch - Debug", }) @@ -28,7 +28,7 @@ it do should contain_yumrepo('epel-debuginfo').with({ - 'mirrorlist' => "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-6&arch=$basearch", + 'mirrorlist' => "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-6&arch=$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6", 'descr' => "Extra Packages for Enterprise Linux 6 - $basearch - Debug", }) @@ -40,7 +40,7 @@ it do should contain_yumrepo('epel-debuginfo').with({ - 'mirrorlist' => "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-5&arch=$basearch", + 'mirrorlist' => "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-5&arch=$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-5", 'descr' => "Extra Packages for Enterprise Linux 5 - $basearch - Debug", }) diff --git a/puphpet/puppet/modules/epel/spec/classes/shared_source.rb b/puphpet/puppet/modules/epel/spec/classes/shared_source.rb index b662e97..2756283 100644 --- a/puphpet/puppet/modules/epel/spec/classes/shared_source.rb +++ b/puphpet/puppet/modules/epel/spec/classes/shared_source.rb @@ -16,7 +16,7 @@ it do should contain_yumrepo('epel-source').with({ - 'mirrorlist' => "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-7&arch=$basearch", + 'mirrorlist' => "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-7&arch=$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7", 'descr' => "Extra Packages for Enterprise Linux 7 - $basearch - Source", }) @@ -28,7 +28,7 @@ it do should contain_yumrepo('epel-source').with({ - 'mirrorlist' => "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-6&arch=$basearch", + 'mirrorlist' => "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-6&arch=$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6", 'descr' => "Extra Packages for Enterprise Linux 6 - $basearch - Source", }) @@ -40,7 +40,7 @@ it do should contain_yumrepo('epel-source').with({ - 'mirrorlist' => "http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-5&arch=$basearch", + 'mirrorlist' => "https://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-5&arch=$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-5", 'descr' => "Extra Packages for Enterprise Linux 5 - $basearch - Source", }) diff --git a/puphpet/puppet/modules/epel/spec/classes/shared_testing.rb b/puphpet/puppet/modules/epel/spec/classes/shared_testing.rb index 9bc51ee..d0c6a79 100644 --- a/puphpet/puppet/modules/epel/spec/classes/shared_testing.rb +++ b/puphpet/puppet/modules/epel/spec/classes/shared_testing.rb @@ -16,7 +16,7 @@ it do should contain_yumrepo('epel-testing').with({ - 'baseurl' => "http://download.fedoraproject.org/pub/epel/testing/7/$basearch", + 'baseurl' => "https://download.fedoraproject.org/pub/epel/testing/7/$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7", 'descr' => "Extra Packages for Enterprise Linux 7 - Testing - $basearch ", }) @@ -28,7 +28,7 @@ it do should contain_yumrepo('epel-testing').with({ - 'baseurl' => "http://download.fedoraproject.org/pub/epel/testing/6/$basearch", + 'baseurl' => "https://download.fedoraproject.org/pub/epel/testing/6/$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6", 'descr' => "Extra Packages for Enterprise Linux 6 - Testing - $basearch ", }) @@ -40,7 +40,7 @@ it do should contain_yumrepo('epel-testing').with({ - 'baseurl' => "http://download.fedoraproject.org/pub/epel/testing/5/$basearch", + 'baseurl' => "https://download.fedoraproject.org/pub/epel/testing/5/$basearch", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-5", 'descr' => "Extra Packages for Enterprise Linux 5 - Testing - $basearch ", }) diff --git a/puphpet/puppet/modules/epel/spec/classes/shared_testing_debuginfo.rb b/puphpet/puppet/modules/epel/spec/classes/shared_testing_debuginfo.rb index 5ed56fb..e9c4e3e 100644 --- a/puphpet/puppet/modules/epel/spec/classes/shared_testing_debuginfo.rb +++ b/puphpet/puppet/modules/epel/spec/classes/shared_testing_debuginfo.rb @@ -16,7 +16,7 @@ it do should contain_yumrepo('epel-testing-debuginfo').with({ - 'baseurl' => "http://download.fedoraproject.org/pub/epel/testing/7/$basearch/debug", + 'baseurl' => "https://download.fedoraproject.org/pub/epel/testing/7/$basearch/debug", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7", 'descr' => "Extra Packages for Enterprise Linux 7 - Testing - $basearch - Debug", }) @@ -28,7 +28,7 @@ it do should contain_yumrepo('epel-testing-debuginfo').with({ - 'baseurl' => "http://download.fedoraproject.org/pub/epel/testing/6/$basearch/debug", + 'baseurl' => "https://download.fedoraproject.org/pub/epel/testing/6/$basearch/debug", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6", 'descr' => "Extra Packages for Enterprise Linux 6 - Testing - $basearch - Debug", }) @@ -40,7 +40,7 @@ it do should contain_yumrepo('epel-testing-debuginfo').with({ - 'baseurl' => "http://download.fedoraproject.org/pub/epel/testing/5/$basearch/debug", + 'baseurl' => "https://download.fedoraproject.org/pub/epel/testing/5/$basearch/debug", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-5", 'descr' => "Extra Packages for Enterprise Linux 5 - Testing - $basearch - Debug", }) diff --git a/puphpet/puppet/modules/epel/spec/classes/shared_testing_source.rb b/puphpet/puppet/modules/epel/spec/classes/shared_testing_source.rb index 9eef2eb..5b8bbc9 100644 --- a/puphpet/puppet/modules/epel/spec/classes/shared_testing_source.rb +++ b/puphpet/puppet/modules/epel/spec/classes/shared_testing_source.rb @@ -16,7 +16,7 @@ it do should contain_yumrepo('epel-testing-source').with({ - 'baseurl' => "http://download.fedoraproject.org/pub/epel/testing/7/SRPMS", + 'baseurl' => "https://download.fedoraproject.org/pub/epel/testing/7/SRPMS", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7", 'descr' => "Extra Packages for Enterprise Linux 7 - Testing - $basearch - Source", }) @@ -28,7 +28,7 @@ it do should contain_yumrepo('epel-testing-source').with({ - 'baseurl' => "http://download.fedoraproject.org/pub/epel/testing/6/SRPMS", + 'baseurl' => "https://download.fedoraproject.org/pub/epel/testing/6/SRPMS", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6", 'descr' => "Extra Packages for Enterprise Linux 6 - Testing - $basearch - Source", }) @@ -40,7 +40,7 @@ it do should contain_yumrepo('epel-testing-source').with({ - 'baseurl' => "http://download.fedoraproject.org/pub/epel/testing/5/SRPMS", + 'baseurl' => "https://download.fedoraproject.org/pub/epel/testing/5/SRPMS", 'gpgkey' => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-5", 'descr' => "Extra Packages for Enterprise Linux 5 - Testing - $basearch - Source", }) diff --git a/puphpet/puppet/modules/epel/spec/defines/rpm_gpg_key_spec.rb b/puphpet/puppet/modules/epel/spec/defines/rpm_gpg_key_spec.rb index 3be830b..07fe2ef 100644 --- a/puphpet/puppet/modules/epel/spec/defines/rpm_gpg_key_spec.rb +++ b/puphpet/puppet/modules/epel/spec/defines/rpm_gpg_key_spec.rb @@ -21,7 +21,7 @@ should contain_exec("import-#{title}").with({ 'path' => '/bin:/usr/bin:/sbin:/usr/sbin', 'command' => "rpm --import #{params[:path]}", - 'unless' => "rpm -q gpg-pubkey-$(echo $(gpg --throw-keyids < #{params[:path]}) | cut --characters=11-18 | tr '[A-Z]' '[a-z]')", + 'unless' => "rpm -q gpg-pubkey-$(echo $(gpg --throw-keyids --keyid-format short < #{params[:path]}) | cut --characters=11-18 | tr '[A-Z]' '[a-z]')", 'require' => "File[#{params[:path]}]", 'logoutput' => 'on_failure', }) @@ -48,7 +48,7 @@ should contain_exec("import-#{title}").with({ 'path' => '/bin:/usr/bin:/sbin:/usr/sbin', 'command' => "rpm --import #{params[:path]}", - 'unless' => "rpm -q gpg-pubkey-$(echo $(gpg --throw-keyids < #{params[:path]}) | cut --characters=11-18 | tr '[A-Z]' '[a-z]')", + 'unless' => "rpm -q gpg-pubkey-$(echo $(gpg --throw-keyids --keyid-format short < #{params[:path]}) | cut --characters=11-18 | tr '[A-Z]' '[a-z]')", 'require' => "File[#{params[:path]}]", 'logoutput' => 'on_failure', }) @@ -75,7 +75,7 @@ should contain_exec("import-#{title}").with({ 'path' => '/bin:/usr/bin:/sbin:/usr/sbin', 'command' => "rpm --import #{params[:path]}", - 'unless' => "rpm -q gpg-pubkey-$(echo $(gpg --throw-keyids < #{params[:path]}) | cut --characters=11-18 | tr '[A-Z]' '[a-z]')", + 'unless' => "rpm -q gpg-pubkey-$(echo $(gpg --throw-keyids --keyid-format short < #{params[:path]}) | cut --characters=11-18 | tr '[A-Z]' '[a-z]')", 'require' => "File[#{params[:path]}]", 'logoutput' => 'on_failure', }) diff --git a/puphpet/puppet/modules/epel/tests/init.pp b/puphpet/puppet/modules/epel/tests/init.pp index c2e61d4..bf0041d 100644 --- a/puphpet/puppet/modules/epel/tests/init.pp +++ b/puphpet/puppet/modules/epel/tests/init.pp @@ -1,3 +1,3 @@ # And by test, I mean, run this thing for me using Puppet apply and I'll check # it out. -include 'epel' +include '::epel' diff --git a/puphpet/puppet/modules/erlang/.gitignore b/puphpet/puppet/modules/erlang/.gitignore new file mode 100644 index 0000000..3a9dd57 --- /dev/null +++ b/puphpet/puppet/modules/erlang/.gitignore @@ -0,0 +1,5 @@ +pkg +spec/fixtures +tests +.rspec_system +.bundle diff --git a/puphpet/puppet/modules/erlang/.travis.yml b/puphpet/puppet/modules/erlang/.travis.yml index cd412bf..9153ffd 100644 --- a/puphpet/puppet/modules/erlang/.travis.yml +++ b/puphpet/puppet/modules/erlang/.travis.yml @@ -2,22 +2,29 @@ language: ruby bundler_args: --without development before_install: rm Gemfile.lock || true +sudo: false rvm: - 1.8.7 - 1.9.3 - 2.0.0 + - 2.1.0 + - 2.2 script: bundle exec rake test env: - - PUPPET_VERSION="~> 2.7.0" - - PUPPET_VERSION="~> 3.1.0" - - PUPPET_VERSION="~> 3.2.0" - - PUPPET_VERSION="~> 3.3.0" - - PUPPET_VERSION="~> 3.4.0" + - PUPPET_GEM_VERSION="~> 3.6.0" + - PUPPET_GEM_VERSION="~> 3.7.0" + - PUPPET_GEM_VERSION="~> 3.8.0" + - PUPPET_GEM_VERSION="~> 4.0.0" + - PUPPET_GEM_VERSION="~> 4.1.0" matrix: exclude: - - rvm: 2.0.0 - env: PUPPET_VERSION="~> 2.7.0" - - rvm: 2.0.0 - env: PUPPET_VERSION="~> 3.1.0" - - rvm: 1.9.3 - env: PUPPET_VERSION="~> 2.7.0" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 4.0.0" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 4.1.0" + - rvm: 2.2 + env: PUPPET_GEM_VERSION="~> 3.6.0" + - rvm: 2.2 + env: PUPPET_GEM_VERSION="~> 3.7.0" + - rvm: 2.2 + env: PUPPET_GEM_VERSION="~> 3.8.0" diff --git a/puphpet/puppet/modules/erlang/Gemfile b/puphpet/puppet/modules/erlang/Gemfile index 39ba7f9..f044d76 100644 --- a/puphpet/puppet/modules/erlang/Gemfile +++ b/puphpet/puppet/modules/erlang/Gemfile @@ -1,8 +1,7 @@ -source "http://rubygems.org" - +source "https://rubygems.org" gem "rake" -gem "puppet", ENV['PUPPET_VERSION'] || '~> 3.2.0' +gem "puppet", ENV['PUPPET_GEM_VERSION'] || '~> 3.8.0' gem "puppet-lint" gem "rspec-puppet", '~> 1.0.0' gem "puppetlabs_spec_helper" diff --git a/puphpet/puppet/modules/erlang/Gemfile.lock b/puphpet/puppet/modules/erlang/Gemfile.lock index d719aa9..dddc649 100644 --- a/puphpet/puppet/modules/erlang/Gemfile.lock +++ b/puphpet/puppet/modules/erlang/Gemfile.lock @@ -1,66 +1,161 @@ GEM remote: http://rubygems.org/ specs: + CFPropertyList (2.3.1) builder (3.2.2) diff-lcs (1.2.5) - excon (0.31.0) - facter (1.7.5) - fog (1.20.0) + domain_name (0.5.24) + unf (>= 0.0.5, < 1.0.0) + excon (0.45.3) + facter (1.7.6) + fission (0.5.0) + CFPropertyList (~> 2.2) + fog (1.32.0) + fog-atmos + fog-aws (>= 0.6.0) + fog-brightbox (~> 0.4) + fog-core (~> 1.32) + fog-ecloud (= 0.1.1) + fog-google (>= 0.0.2) + fog-json + fog-local + fog-powerdns (>= 0.1.1) + fog-profitbricks + fog-radosgw (>= 0.0.2) + fog-riakcs + fog-sakuracloud (>= 0.0.4) + fog-serverlove + fog-softlayer + fog-storm_on_demand + fog-terremark + fog-vmfusion + fog-voxel + fog-xml (~> 0.1.1) + ipaddress (~> 0.5) + nokogiri (~> 1.5, >= 1.5.11) + fog-atmos (0.1.0) + fog-core + fog-xml + fog-aws (0.6.0) + fog-core (~> 1.27) + fog-json (~> 1.0) + fog-xml (~> 0.1) + ipaddress (~> 0.8) + fog-brightbox (0.7.2) + fog-core (~> 1.22) + fog-json + inflecto (~> 0.0.2) + fog-core (1.32.0) builder - excon (~> 0.31.0) - formatador (~> 0.2.0) + excon (~> 0.45) + formatador (~> 0.2) mime-types - multi_json (~> 1.0) net-scp (~> 1.1) net-ssh (>= 2.1.3) - nokogiri (>= 1.5.11) - formatador (0.2.4) - hiera (1.3.2) + fog-ecloud (0.1.1) + fog-core + fog-xml + fog-google (0.0.6) + fog-core + fog-json + fog-xml + fog-json (1.0.2) + fog-core (~> 1.0) + multi_json (~> 1.10) + fog-local (0.2.1) + fog-core (~> 1.27) + fog-powerdns (0.1.1) + fog-core (~> 1.27) + fog-json (~> 1.0) + fog-xml (~> 0.1) + fog-profitbricks (0.0.3) + fog-core + fog-xml + nokogiri + fog-radosgw (0.0.4) + fog-core (>= 1.21.0) + fog-json + fog-xml (>= 0.0.1) + fog-riakcs (0.1.0) + fog-core + fog-json + fog-xml + fog-sakuracloud (1.0.1) + fog-core + fog-json + fog-serverlove (0.1.2) + fog-core + fog-json + fog-softlayer (0.4.7) + fog-core + fog-json + fog-storm_on_demand (0.1.1) + fog-core + fog-json + fog-terremark (0.1.0) + fog-core + fog-xml + fog-vmfusion (0.1.0) + fission + fog-core + fog-voxel (0.1.0) + fog-core + fog-xml + fog-xml (0.1.2) + fog-core + nokogiri (~> 1.5, >= 1.5.11) + formatador (0.2.5) + hiera (1.3.4) json_pure - json_pure (1.8.1) + http-cookie (1.0.2) + domain_name (~> 0.5) + inflecto (0.0.2) + ipaddress (0.8.0) + json_pure (1.8.2) kwalify (0.7.2) metaclass (0.0.4) mime-types (1.25.1) - mocha (1.0.0) + mocha (1.1.0) metaclass (~> 0.0.1) - multi_json (1.8.4) - net-scp (1.1.2) + multi_json (1.11.2) + net-scp (1.2.1) net-ssh (>= 2.6.5) - net-ssh (2.8.0) + net-ssh (2.9.2) + netrc (0.10.3) nokogiri (1.5.11) - puppet (3.2.4) - facter (~> 1.6) + puppet (3.8.1) + facter (> 1.6, < 3) hiera (~> 1.0) - rgen (~> 0.6.5) - puppet-blacksmith (2.0.2) - nokogiri + json_pure + puppet-blacksmith (3.3.1) puppet (>= 2.7.16) rest-client - puppet-lint (0.3.2) - puppet-syntax (1.1.0) - puppet (>= 2.7.0) + puppet-lint (1.1.0) + puppet-syntax (2.0.0) rake - puppetlabs_spec_helper (0.4.1) - mocha (>= 0.10.5) + puppetlabs_spec_helper (0.10.3) + mocha + puppet-lint + puppet-syntax rake - rspec (>= 2.9.0) - rspec-puppet (>= 0.1.1) - rake (10.1.1) - rbvmomi (1.8.1) + rspec-puppet + rake (10.4.2) + rbvmomi (1.8.2) builder nokogiri (>= 1.4.1) trollop - rest-client (1.6.7) - mime-types (>= 1.16) - rgen (0.6.6) - rspec (2.14.1) - rspec-core (~> 2.14.0) - rspec-expectations (~> 2.14.0) - rspec-mocks (~> 2.14.0) - rspec-core (2.14.8) - rspec-expectations (2.14.5) + rest-client (1.8.0) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 3.0) + netrc (~> 0.7) + rspec (2.99.0) + rspec-core (~> 2.99.0) + rspec-expectations (~> 2.99.0) + rspec-mocks (~> 2.99.0) + rspec-core (2.99.2) + rspec-expectations (2.99.2) diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.14.6) + rspec-mocks (2.99.4) rspec-puppet (1.0.1) rspec rspec-system (2.8.0) @@ -75,15 +170,18 @@ GEM systemu (~> 2.5) rspec-system-puppet (2.2.1) rspec-system (~> 2.0) - systemu (2.6.3) - trollop (2.0) - vagrant-wrapper (1.2.1.1) + systemu (2.6.5) + trollop (2.1.2) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.1) + vagrant-wrapper (2.0.2) PLATFORMS ruby DEPENDENCIES - puppet (~> 3.2.0) + puppet (~> 3.8.0) puppet-blacksmith puppet-lint puppet-syntax diff --git a/puphpet/puppet/modules/erlang/Modulefile b/puphpet/puppet/modules/erlang/Modulefile deleted file mode 100644 index 9ca1ef7..0000000 --- a/puphpet/puppet/modules/erlang/Modulefile +++ /dev/null @@ -1,10 +0,0 @@ -name 'garethr-erlang' -version '0.3.0' -source 'git://github.com/garethr/garethr-erlang.git' -author 'Gareth Rushgrove' -summary 'Module for installing erlang from official repos' -description 'Install one of the official erlang packages' -license 'Apache License, Version 2.0' -dependency 'puppetlabs/apt' -dependency 'puppetlabs/stdlib' -dependency 'stahnma/epel' diff --git a/puphpet/puppet/modules/erlang/manifests/params.pp b/puphpet/puppet/modules/erlang/manifests/params.pp index 9358326..9b610aa 100644 --- a/puphpet/puppet/modules/erlang/manifests/params.pp +++ b/puphpet/puppet/modules/erlang/manifests/params.pp @@ -8,19 +8,27 @@ case $::osfamily { 'Debian' : { - $key_signature = 'D208507CA14F4FCA' + $key_signature = '434975BD900CCBE4F7EE1B1ED208507CA14F4FCA' $package_name = 'erlang-nox' + $local_repo_location = undef $remote_repo_key_location = 'http://packages.erlang-solutions.com/debian/erlang_solutions.asc' $remote_repo_location = 'http://packages.erlang-solutions.com/debian' $repos = 'contrib' } 'RedHat', 'SUSE', 'Archlinux' : { - $package_name = 'erlang' + $key_signature = undef + $package_name = 'erlang' if $::operatingsystemrelease =~ /^5/ { $local_repo_location = '/etc/yum.repos.d/epel-erlang.repo' - $remote_repo_location = 'http://repos.fedorapeople.org/repos/peter/erlang/epel-erlang.repo' + $remote_repo_location = 'https://repos.fedorapeople.org/repos/peter/erlang/epel-erlang.repo' + } else { + $local_repo_location = undef + $remote_repo_location = undef } + + $remote_repo_key_location = undef + $repos = undef } default : { fail("The ${module_name} module is not supported on an ${::osfamily} based system.") diff --git a/puphpet/puppet/modules/erlang/metadata.json b/puphpet/puppet/modules/erlang/metadata.json new file mode 100644 index 0000000..43118d3 --- /dev/null +++ b/puphpet/puppet/modules/erlang/metadata.json @@ -0,0 +1,55 @@ +{ + "name": "garethr-erlang", + "version": "0.3.0", + "author": "Gareth Rushgrove", + "summary": "Install one of the official erlang packages", + "license": "Apache-2.0", + "source": "https://github.com/garethr/puppet-erlang", + "project_page": "https://github.com/garethr/puppet-erlang", + "issues_url": "https://github.com/garethr/puppet-erlang", + "operatingsystem_support": [ + { + "operatingsystem": "RedHat", + "operatingsystemrelease": [ + "5", + "6" + ] + }, + { + "operatingsystem": "CentOS", + "operatingsystemrelease": [ + "5", + "6" + ] + }, + { + "operatingsystem": "Debian", + "operatingsystemrelease": [ + "6", + "7" + ] + }, + { + "operatingsystem": "Ubuntu", + "operatingsystemrelease": [ + "12.04", + "14.04" + ] + } + ], + "requirements": [ + { + "name": "pe", + "version_requirement": "3.x" + }, + { + "name": "puppet", + "version_requirement": "3.x" + } + ], + "dependencies": [ + { "name": "puppetlabs/stdlib", "version_requirement": ">=2.0.0 <5.0.0" }, + { "name": "puppetlabs/apt", "version_requirement": ">=2.1.0" }, + { "name": "stahnma/epel", "version_requirement": ">=1.0.0 <2.0.0" } + ] +} diff --git a/puphpet/puppet/modules/erlang/spec/classes/erlang_spec.rb b/puphpet/puppet/modules/erlang/spec/classes/erlang_spec.rb index 8708eb1..3a17738 100644 --- a/puphpet/puppet/modules/erlang/spec/classes/erlang_spec.rb +++ b/puphpet/puppet/modules/erlang/spec/classes/erlang_spec.rb @@ -15,7 +15,7 @@ it { should contain_package('erlang-nox').with_ensure('present') } it { should contain_apt__source('erlang').with( 'key_source' => 'http://packages.erlang-solutions.com/debian/erlang_solutions.asc', - 'key' => 'D208507CA14F4FCA' + 'key' => '434975BD900CCBE4F7EE1B1ED208507CA14F4FCA' ) } end @@ -62,7 +62,7 @@ context 'with no parameters' do it { should contain_package('erlang').with_ensure('present') } it { should contain_exec('erlang-repo-download').with( - 'command' => 'curl -o /etc/yum.repos.d/epel-erlang.repo http://repos.fedorapeople.org/repos/peter/erlang/epel-erlang.repo', + 'command' => 'curl -o /etc/yum.repos.d/epel-erlang.repo https://repos.fedorapeople.org/repos/peter/erlang/epel-erlang.repo', 'path' => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin' ) } diff --git a/puphpet/puppet/modules/firewall/.gitignore b/puphpet/puppet/modules/firewall/.gitignore new file mode 100644 index 0000000..9a9567b --- /dev/null +++ b/puphpet/puppet/modules/firewall/.gitignore @@ -0,0 +1,9 @@ +pkg/ +Gemfile.lock +# TODO: Ignore this for now until we decide what to do with it +spec/fixtures/manifests/ +.ruby-version +.rspec_system +.bundle +.vagrant +vendor/ diff --git a/puphpet/puppet/modules/gnupg/.fixtures.yml b/puphpet/puppet/modules/gnupg/.fixtures.yml new file mode 100644 index 0000000..6e8f2c7 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/.fixtures.yml @@ -0,0 +1,4 @@ +fixtures: + symlinks: + gnupg: "#{source_dir}" + diff --git a/puphpet/puppet/modules/gnupg/.gitignore b/puphpet/puppet/modules/gnupg/.gitignore new file mode 100644 index 0000000..529f45a --- /dev/null +++ b/puphpet/puppet/modules/gnupg/.gitignore @@ -0,0 +1,9 @@ +.project +spec/fixtures +.rspec_system +pkg/* +log/* +.DS_Store +Gemfile.lock +junit/* +.vagrant/ diff --git a/puphpet/puppet/modules/gnupg/.nodeset.yml b/puphpet/puppet/modules/gnupg/.nodeset.yml new file mode 100644 index 0000000..c9a6e5a --- /dev/null +++ b/puphpet/puppet/modules/gnupg/.nodeset.yml @@ -0,0 +1,27 @@ +--- +default_set: 'centos-64-x64' +sets: + 'centos-59-x64': + nodes: + "main.foo.vm": + prefab: 'centos-59-x64' + 'centos-64-x64': + nodes: + "main.foo.vm": + prefab: 'centos-64-x64' + 'debian-607-x64': + nodes: + "main.foo.vm": + prefab: 'debian-607-x64' + 'debian-70rc1-x64': + nodes: + "main.foo.vm": + prefab: 'debian-70rc1-x64' + 'ubuntu-server-10044-x64': + nodes: + "main.foo.vm": + prefab: 'ubuntu-server-10044-x64' + 'ubuntu-server-12042-x64': + nodes: + "main.foo.vm": + prefab: 'ubuntu-server-12042-x64' diff --git a/puphpet/puppet/modules/gnupg/.travis.yml b/puphpet/puppet/modules/gnupg/.travis.yml new file mode 100644 index 0000000..23e9b34 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/.travis.yml @@ -0,0 +1,17 @@ +--- +language: ruby +bundler_args: --without system_tests +script: "bundle exec rake test SPEC_OPTS='--format documentation'" +matrix: + fast_finish: true + include: + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.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" +notifications: + email: dejan@golja.org diff --git a/puphpet/puppet/modules/gnupg/CHANGELOG b/puphpet/puppet/modules/gnupg/CHANGELOG new file mode 100644 index 0000000..097667e --- /dev/null +++ b/puphpet/puppet/modules/gnupg/CHANGELOG @@ -0,0 +1,43 @@ +2015-07-04 - Dejan Golja - 1.2.1 +* remove (present|absent) restriction on $package_ensure +* add support for SLES + +2015-05-16 - Dejan Golja - 1.2.0 +* autorequire user type when using gnupg_key (tnx to tcinel@atlassian.com) +* added two new custom facts: + * gnupg_command - get full path to gpg exe + * gnupg_installed - determine if gpg exe exists on system + +2015-03-24 - Dejan Golja - 1.1.1 +* supports username with - + +2015-02-21 - Dejan Golja - 1.1.0 +* properly supports private key (added new paramater key_type + for gnupg_key type) +* added new parameter key_content for gnupg_key type + to make it easier integrate hiera lookups. More info check README + +Special thanks to Tobias Clemson (https://github.com/tobyclemson) + +2014-10-20 - Dejan Golja - 1.0.0 +* remove support for puppet 2.7.x due to the native type +* added beaker system spec tests +* Update type definition so it uses Puppet::Util::Execution.execute + instead of Puppet::Util::SUIDManager.run_and_capture (deprecated) +* bump version to 1.0.0 + +2014-10-07 - Dejan Golja - 0.0.5 +* bugfix for https keys + +2014-08-17 - Dejan Golja - 0.0.4 +* Update metadata.json and removed Modulefile due to + as of Puppet 3.6 the Modulefile has been deprecated + +2014-03-16 - Dejan Golja - 0.0.3 +* Added Puppet Forge Search by Module Compatibility + +2013-10-22 - Dejan Golja - 0.0.2 +* public release for Forge + +2013-10-12 - Dejan Golja - 0.0.1 +* initial beta version not released to the public diff --git a/puphpet/puppet/modules/gnupg/CONTRIBUTING.md b/puphpet/puppet/modules/gnupg/CONTRIBUTING.md new file mode 100644 index 0000000..dbf159c --- /dev/null +++ b/puphpet/puppet/modules/gnupg/CONTRIBUTING.md @@ -0,0 +1,216 @@ +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: + + * 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 +--------------- + +This 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://projects.puppetlabs.com/projects/puppet/wiki/Getting_Help) + +* [Writing tests](http://projects.puppetlabs.com/projects/puppet/wiki/Development_Writing_Tests) + +* [Patchwork](https://patchwork.puppetlabs.com) + +* [Contributor License Agreement](https://projects.puppetlabs.com/contributor_licenses/sign) + +* [General GitHub documentation](http://help.github.com/) + +* [GitHub pull request documentation](http://help.github.com/send-pull-requests/) + diff --git a/puphpet/puppet/modules/gnupg/Gemfile b/puphpet/puppet/modules/gnupg/Gemfile new file mode 100644 index 0000000..e37a38f --- /dev/null +++ b/puphpet/puppet/modules/gnupg/Gemfile @@ -0,0 +1,33 @@ +source ENV['GEM_SOURCE'] || "https://rubygems.org" + +group :development, :test do + gem 'rake', :require => false + gem 'rspec-core','~> 3.1.7', :require => false + gem 'rspec-puppet', :require => false + gem 'puppetlabs_spec_helper', :require => false + gem 'puppet-lint', :require => false + gem 'puppet_facts', :require => false + gem 'json', :require => false + gem 'metadata-json-lint', :require => false +end + +group :system_tests do + gem 'beaker', '~> 2.4', :require => false + gem 'beaker-rspec', :require => false + gem 'serverspec', :require => false + gem 'rspec-system-puppet', :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 diff --git a/puphpet/puppet/modules/gnupg/LICENSE b/puphpet/puppet/modules/gnupg/LICENSE new file mode 100644 index 0000000..5abff44 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/LICENSE @@ -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 Dejan Golja + + 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. diff --git a/puphpet/puppet/modules/gnupg/README.md b/puphpet/puppet/modules/gnupg/README.md new file mode 100644 index 0000000..3ce4c79 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/README.md @@ -0,0 +1,225 @@ +#GnuPG puppet module + +####Table of Contents + +1. [Overview](##overview) +2. [Installation](##Installation) +3. [Usage - Configuration options and additional functionality](@#usage) +4. [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) +7. [License](##license) + +##Overview + +Install GnuPG on Ubuntu/Debian/RedHat/CentOS/Amazon AMI and manage users public keys. + +Tested with Tavis CI + +NOTE: For puppet 2.7.x supported module please use version 0.X.X + +[![Build Status](https://travis-ci.org/n1tr0g/golja-gnupg.png)](https://travis-ci.org/n1tr0g/golja-gnupg) [![Puppet Forge](http://img.shields.io/puppetforge/v/golja/gnupg.svg)](https://forge.puppetlabs.com/golja/gnupg) + +##Installation + + $ puppet module install golja/gnupg + +##Usage + +####Install GnuPG package + + include '::gnupg' + +####Add public key 20BC0A86 from PGP server from hkp://pgp.mit.edu/ to user root + +```puppet +gnupg_key { 'hkp_server_20BC0A86': + ensure => present, + key_id => '20BC0A86', + user => 'root', + key_server => 'hkp://pgp.mit.edu/', + key_type => public, +} +``` + +####Add public key D50582E6 from standard http URI to user foo + +```puppet +gnupg_key { 'jenkins_foo_key': + ensure => present, + key_id => 'D50582E6', + user => 'foo', + key_source => 'http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key', + key_type => public, +} +``` + +####Add public key D50582E6 from puppet fileserver to user foo + +```puppet +gnupg_key { 'jenkins_foo_key': + ensure => present, + key_id => 'D50582E6', + user => 'foo', + key_source => 'puppet:///modules/gnupg/D50582E6.key', + key_type => public, +} +``` + +####Add public key D50582E6 from puppet fileserver to user bar via a string value + +```puppet +gnupg_key { 'jenkins_foo_key': + ensure => present, + key_id => 'D50582E6', + user => 'bar', + key_content => '-----BEGIN BROKEN PUBLIC KEY BLOCK-----...', + key_type => public, +} +``` +*Note*: You should use hiera lookup to get the key content + +####Remove public key 20BC0A86 from user root + +```puppet +gnupg_key {'root_remove': + ensure => absent, + key_id => '20BC0A86', + user => 'root', + key_type => public, +} +``` + +###Remove both private and public key 20BC0A66 + +```puppet +gnupg_key {'root_remove': + ensure => absent, + key_id => '20BC0A66', + user => 'root', + key_type => both, +} +``` + +##Reference + +###Classes + +####gnupg + +#####`package_ensure` + +Valid value present/absent. In most cases you should never uninstall this package, +because most of the modern Linux distros rely on gnupg for package verification, etc +Default: present + +#####`package_name` + +Name of the GnuPG package. Default value determined by $::osfamily/$::operatingsystem facts + +####gnupg_key + +#####`ensure` + +**REQUIRED** - Valid value present/absent + +#####`user` + +**REQUIRED** - System username for who to store the public key. Also define the location of the +pubring (default ${HOME}/.gnupg/) + +#####`key_id` + +**REQUIRED** - Key ID. Usually the traditional 8-character key ID. Also accepted the +long more accurate (but less convenient) 16-character key ID. Accept only hexadecimal +values. + +#####`key_source` + +**REQUIRED** if `key_server` or `key_content` is not defined and `ensure` is present. +A source file containing PGP key. Values can be URIs pointing to remote files, +or fully qualified paths to files available on the local system. + +The available URI schemes are *puppet*, *https*, *http* and *file*. *Puppet* +URIs will retrieve files from Puppet's built-in file server, and are +usually formatted as: + +puppet:///modules/name_of_module/filename + +#####`key_server` + +**REQUIRED** if `key_source` or `key_content` is not defined and `ensure` is present. + +PGP key server from where to retrieve the public key. Valid URI schemes are +*http*, *https*, *ldap* and *hkp*. + +#####`key_content` + +**REQUIRED** if `key_server` or `key_source` is not defined and `ensure` is present. + +Provide the content of the key as a string. This is useful when the key is stored as a +hiera property and the consumer doesn't want to have to write that content to a file +before the gnupg_key resource executes. + + +#####`key_type` + +**OPTIONAL** - key type. Valid values (public|private|both). Default: public + +PGP key server from where to retrieve the public key. Valid URI schemes are +*http*, *https*, *ldap* and *hkp*. + + +### Tests + +There are two types of tests distributed with the module. Unit tests with rspec-puppet and system tests using rspec-system or beaker. + +For unit testing, make sure you have: + +* rake +* bundler + +Install the necessary gems: + + bundle install --path=vendor + +And then run the unit tests: + + bundle exec rake spec + + +If you want to run the system tests, make sure you also have: + +* vagrant > 1.3.x +* Virtualbox > 4.2.10 + +Then run the tests using: + + bundle exec rake spec:system + +To run the tests on different operating systems, see the sets available in .nodeset.yml and run the specific set with the following syntax: + + RSPEC_SET=debian-607-x64 bundle exec rake spec:system + +Alernatively you can run beaker tests using: + + bundle exec rake beaker + +##Limitations + +This module has been tested on: + +* Debian 6/7 +* Ubuntu 12+ +* RedHat 5/6/7 +* CentOS 5/6/7 +* Amazon AMI + +##Development + +Please see CONTRIBUTING.md + +## License + +See LICENSE file + diff --git a/puphpet/puppet/modules/gnupg/Rakefile b/puphpet/puppet/modules/gnupg/Rakefile new file mode 100644 index 0000000..4de9b1a --- /dev/null +++ b/puphpet/puppet/modules/gnupg/Rakefile @@ -0,0 +1,15 @@ +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' + +PuppetLint.configuration.send('relative') +PuppetLint.configuration.send("disable_80chars") +PuppetLint.configuration.send('disable_class_parameter_defaults') +PuppetLint.configuration.send('disable_class_inherits_from_params_class') +PuppetLint.configuration.send('disable_documentation') +PuppetLint.configuration.log_format = "%{path}:%{linenumber}:%{check}:%{KIND}:%{message}" +PuppetLint.configuration.fail_on_warnings = true +PuppetLint.configuration.ignore_paths = ["pkg/**/*", "vendor/**/*", "spec/**/*"] + +desc "Run syntax, lint, and beaker tests." +task :test => [:validate, :lint, :spec] + diff --git a/puphpet/puppet/modules/gnupg/files/broken.public.key b/puphpet/puppet/modules/gnupg/files/broken.public.key new file mode 100644 index 0000000..c9169d7 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/files/broken.public.key @@ -0,0 +1,30 @@ +-----BEGIN BROKEN PUBLIC KEY BLOCK----- +Version: GnuPG/MacGPG2 v2.0.22 (Darwin) + +mQENBFTnQ0QBCACx0qbkYotSSCCGAKspC8MKO+dEkna/+DA+TQ/kdtB6LV3LLTEj +xmjz7GSThEr+0nLOv17Ox9UtmZ4arH74CKo4LGognzDvaY5xEXV5SBfQAl5pYYhy +WRL7HwyGdUgeTJK/pNU7xRS4G91DuerRJauND1z+n38P6/dIdUy9PYrYSEN3NCn5 +0CP+SplEb8fDHNlLSZgBY43p1w944+ptHnp1NCU5BfYZl+dCd10iGYIE+v9K+F2r +ZOYMAvtlT4dEU8No/kkbqo2oVlvkORGydNYKlgz2+ZnAehGhK69uPhOGlUolyKA5 +LuwZnFo937D0Ia7jIlA6sRA5pOPKbe80mjA3ABEBAAG0MVRlc3QgS2V5IChHbnVQ +RyBQdXBwZXQgTW9kdWxlKSA8dGVzdEBleGFtcGxlLmNvbT6JATgEEwECACIFAlTn +Q0QCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEGATXCaSb6m50u0H/3u7 +ZVieNuCHr4NSHN/rlG04cXBU20GbRPE4xXp1HqT/17B5TgeW3nvh1swB9sTn3tQ8 +bkF0cVDi10xL8rOHnmoPCdTopZ987ZVsQoGwObHWXrpMOFhA1aHYWYDPNXxc+Hf2 +hUWflXnyqWdo00uLsRFy9KS9HisreJ1L3M1vsXHXQKsVVWrrt+Lkz9Xc4EJ2Fn/G +L336dAQTonUOPCjrgBMOnlgl3v0ApBD3PGCkqO34kzz5cOxGBkL7TN751wkbPZ1I +KAzBj0LSF5Z89PLL5Mfo6NsSouUdIbCX8sZEi6NeHL13u1jRfERUaOeuDS1gqUyb +8gKJKeNddjTSTZEyVtC5AQ0EVOdDRAEIANPfqn+qbfr8PL5wy9f0SaJJh2UmqwcH +dxZLkMQVuK+l7Gxz5qXctcDoj/DMTRGFlreH344D9QO6XGJDRDIVjS2owNf/atCY +1fF5M32BEJMKT87jg7Ycy3F+s6w9WMTuUAjok7Ojc883ph+pwqN8fT0lG64Qa0tS +oqlhx/+Q2hxEv7z6P+jHB3L4tpJsUF3Amjej4DBAkGhUWN6UgjEIaiUVjURtqzS2 +MUB22fP8hMvxUKFDkz2D490OiX2+79U9z5YrPw8FjsSjCRnCXkOBIuNRmrddAdyM +WfNx2QX+H/MPShNB+TZdXJ7eXlp5OuM/Zj/i4vzGRdEw9JemMGhCJqsAEQEAAYkB +HwQYAQIACQUCVOdDRAIbDAAKCRBgE1wmkm+puQmiB/9czjtf9srBKj3PS13rkdjO +Hc5TaswBhnJ1lRUTssGN1hxUonjwsVO3gFtgcyv1MjXPUPi6yhC+4jdhG47Ja3zi +0TFHQm3ECL6Z+YOun6ohYpUzvuoqI/H2NRM+BYlvD2fnSCgE3RUm3V8duL40CcX1 +8wGIS9Vo9/0H97XdS8tWQBLBty2LgX+LLKxzu59rEOU3pNlf09eMiJi6Riwi5gHf +m8zv8omg5bF0pjFa2MK5297wn7i0dJlqCj7Cpr/FgHlGSZFlTqeKmusVJ/J7Kl/M +pzwCDQQeWmx8WXxZ0IUTKQYjmUZrYLelWzfxbuW3ZbK8sK+GDhS6n2H0AqhHiFl6 +=LuvV +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/gnupg/files/random.key b/puphpet/puppet/modules/gnupg/files/random.key new file mode 100644 index 0000000..58cedf9 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/files/random.key @@ -0,0 +1,28 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: SKS 1.1.0 + +mQENBFJFfvUBCADJ0TdGQazYBrTWeTXTnzdY0AqjKY+GlqB83Qfk1BLEhEZRGYsg9R4uSFB5 +7Ey6A5JOP9TjfCflgUiifScQjtnT9492fwdxa610KFVSVlfuXAM3YwZVcxv0H7rZOQyS7lzT +jCEZnGM+9hwsa0Zo6i/b+2ZTQ8cePYK57mrdTbl8nWSfNov4h4x94D9joiyaZurC04JKuh1O +RhT2NuTg5VcyoHsMiGtcIMVnjOgM6YjY7QbaNbPN0WTzzEUQ0VWPJsE+4V0ZUbSIKLt/fTXx +3SFEBe+ECHPER0xSgMYz/v5VukSH0Pyh++mMbRESjmgDkBfd5euTx3W3bMl0KOMGMA0XABEB +AAG0JkRlamFuIERhc2ljIDxkZWphbi5kYXNpY0B2bGF0YWNvbS5jb20+iQE/BBMBAgApBQJS +RX71AhsjBQkFo5qABwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQPM6LxSC8CobrOwf/ +T80AG3az4YHNy0uFdsBhpTY/PiSk5kc22jwGYPXBmj5tbfXt3rkxurZxw/YRwLS3fyXP/3n7 +tyLLBEvTqr8pxx91LgRV4lyHv+6tGT3+DZPRp5SNxky6D74HsrYq3nk52LaMqcx235vsPrxQ +24dpmWoR8ZWWv8wxT0bK3YUO0xiAm/OMCdHp3D9QW3tOiMUuGwQ7lRDUOqEIEeBLysy7uAK7 +TbaAY3jafv4E02k0orhJwFQR7gRBg53aDzb2RtMEaYCegsHurmOr1/mgChPNlvF7sliQNJM+ +QQBeggr4qSevrPW/rARt2o03M2Gw3K9JuPkWptBnBfmgF4juSA6bgrkBDQRSRX71AQgA2V4d +FmZxKdWkeb8K80OVEi18oPx54U8mfETRuUOSo4BjoMmUVsq9pZnfM6NU226M4JhVbPDrKe5h +a6itHabeeaKRSY2LVoqzr2wJmrATHf3j7wQW3hARzsFMCLXblGCHK6Stp9rvvUxiDL0z1b6t +l/7Qw+yQO0i8O2suH2ERdNxQHqoLxp+MQD1BVekHZpdho/R4V1rX49NxuPS5XyfPXj92agXP +PoWPjeKnHioUEBXsTiP71pxdY34T8NZqR2T1lw/BFWzVufFJB/3cTiwBfaZu+pjoq4EbE7K0 +9FdR4OU4BAyzw0Q1bsA5+Y3dDoONu9iQKznM50R4myv2SFZkXwARAQABiQElBBgBAgAPBQJS +RX71AhsMBQkFo5qAAAoJEDzOi8UgvAqGnt4H/Al8RyvUBTPdaByCxhggNNlzTYLk7rPwZm0d +CryQNoI6R0CmI8/33c74y1Pwrc8fnUjddGqh5VOSJe2REBmvu/+WCZaMlMeRRPzIzW49NzPp +j1zkK8jGXoKeaWFzVPfM4tPReNBnLhTegM+buUFB/w9SvKuFnyQvmYhOEUkTdphUjoVXiztE +lp8MI78ONkKJF9yd0Gcbfv1N+ggHrKpyNh497b0P+FJMNic1cS79DVWzM08BQagl/+DgAyES +Vt6XHYw6Jvw+nzJHFkX3TylgfSRbWtnBYGxJa54aQNmS2pYW3atKRxNJjn2uiiUQWuGqhmX1 +GsCLLsqleF8Hb4O6Wag= +=vG4P +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/gnupg/files/random.private.key b/puphpet/puppet/modules/gnupg/files/random.private.key new file mode 100644 index 0000000..1357b7e --- /dev/null +++ b/puphpet/puppet/modules/gnupg/files/random.private.key @@ -0,0 +1,58 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG/MacGPG2 v2.0.22 (Darwin) + +lQOYBFTnQ0QBCACx0qbkYotSSCCGAKspC8MKO+dEkna/+DA+TQ/kdtB6LV3LLTEj +xmjz7GSThEr+0nLOv17Ox9UtmZ4arH74CKo4LGognzDvaY5xEXV5SBfQAl5pYYhy +WRL7HwyGdUgeTJK/pNU7xRS4G91DuerRJauND1z+n38P6/dIdUy9PYrYSEN3NCn5 +0CP+SplEb8fDHNlLSZgBY43p1w944+ptHnp1NCU5BfYZl+dCd10iGYIE+v9K+F2r +ZOYMAvtlT4dEU8No/kkbqo2oVlvkORGydNYKlgz2+ZnAehGhK69uPhOGlUolyKA5 +LuwZnFo937D0Ia7jIlA6sRA5pOPKbe80mjA3ABEBAAEAB/oDZ9nra4Roky9lnEiq +6hSWXcGsULPL3G3WxkoPdu5qO0kzFXlTSpRYVkbc2RPzSnDeyyUpMlmVBylTMHTk +Eje/CKwQVjbX4akpOuDe7ZsLJah3kzcg8todYMxax49AiU3m3rojbBRdVvyctJ2t +229W2HGlrMSrDOVjsrTBYRbc1TPxdym9SRZM9OU8ZVN8f7p97usIONXe1wIo6mTI +zBZBXPO1KiFgfN2ZIKPdfIgFkbXUMGwUMhAYePVSE3RlUWeuHgS0uMQsX2BVDPw6 +KIylaFyUgLXDCqzrgmi4v6IJTCbxE8LpdTbuHDGHuBKp9OseWLHSGroIxJv6APMq +lqHBBADFGxGSYqz/x9dMAGjI9SoNiSL291YiFi3MvVcNTh7tT646Nm8JazdmQEuk +N90L6zvkmgapluxU0JF90WDf5YZR72rxjAtsvjnyyIhyW8L63YJxYf/G38Kbb9Fu +hwG0Ad/3btRRqJmQYtw9D2Eh46JRF0wFlxTzjJv5miQWfZQNdwQA5vSa8/Wa0Amb +nK5671blTXnd0s9oZrEu4vTRN29iMBWbLt655QrsiXCquJVPJ9zRacduIWkvqUq6 +prx2qjRACJGItE/+ID2E7kXg1ebestXZctF1O1IHC/YjTteYQ/+WgsSLRXGofC3E +o/JxJ9J6UfJa5cFgu3UfD+5+S/oQo0ED/iTpkv8lV3cubLEySMvb44REZUb+5jHT +FAR+TC06PmkHCAKd/1LlO4Zw7n+Tl4W+QBoWjmmsVyPTxq4NJ+lINgWXzqmdG6SW +BGIpN8Trjfz0tzH5num6Etm03Izh5nIzzd2WEKQtzgeLUD6w99sINoOPiKw+lc03 +psPYsILA9fhBR6+0MVRlc3QgS2V5IChHbnVQRyBQdXBwZXQgTW9kdWxlKSA8dGVz +dEBleGFtcGxlLmNvbT6JATgEEwECACIFAlTnQ0QCGwMGCwkIBwMCBhUIAgkKCwQW +AgMBAh4BAheAAAoJEGATXCaSb6m50u0H/3u7ZVieNuCHr4NSHN/rlG04cXBU20Gb +RPE4xXp1HqT/17B5TgeW3nvh1swB9sTn3tQ8bkF0cVDi10xL8rOHnmoPCdTopZ98 +7ZVsQoGwObHWXrpMOFhA1aHYWYDPNXxc+Hf2hUWflXnyqWdo00uLsRFy9KS9Hisr +eJ1L3M1vsXHXQKsVVWrrt+Lkz9Xc4EJ2Fn/GL336dAQTonUOPCjrgBMOnlgl3v0A +pBD3PGCkqO34kzz5cOxGBkL7TN751wkbPZ1IKAzBj0LSF5Z89PLL5Mfo6NsSouUd +IbCX8sZEi6NeHL13u1jRfERUaOeuDS1gqUyb8gKJKeNddjTSTZEyVtCdA5gEVOdD +RAEIANPfqn+qbfr8PL5wy9f0SaJJh2UmqwcHdxZLkMQVuK+l7Gxz5qXctcDoj/DM +TRGFlreH344D9QO6XGJDRDIVjS2owNf/atCY1fF5M32BEJMKT87jg7Ycy3F+s6w9 +WMTuUAjok7Ojc883ph+pwqN8fT0lG64Qa0tSoqlhx/+Q2hxEv7z6P+jHB3L4tpJs +UF3Amjej4DBAkGhUWN6UgjEIaiUVjURtqzS2MUB22fP8hMvxUKFDkz2D490OiX2+ +79U9z5YrPw8FjsSjCRnCXkOBIuNRmrddAdyMWfNx2QX+H/MPShNB+TZdXJ7eXlp5 +OuM/Zj/i4vzGRdEw9JemMGhCJqsAEQEAAQAH/jwpk18MFI3D6TXEjsWEKxKHoYgx ++jeVQZYVoAZmCprp2SAUqyZm7T9ZamIciTfUAK+dx/eqHP1RgmEuq6MzJnMUK6pJ +71lLRNj8KwhUyVGPiIj9Zs2kEIrqSPe8NcQ5zYUyEZrda4moSiZMjKXiuCdQLbN4 +Gxd44BKL3wAtcBm9URH/Bkza+rDx+8a1zVGVAwoS3lSdhMBVjnGFuREkX3S48FSu +WxrL69d677CcD5pTU5L4eH/oEm/M/dVusTnKPs5rnfsGrhv5Kj6GiRr6yftkIlJB +Rr1bZHo+RQrK5K0Xx+vayb0dWlzvXQURW8CNPYnsaQWceJC6G2iAOVjNDM0EANUk +MfPb5bGYjQ4qNU1LWHd6vR/KElsmDNMxXlBMHrhH24Izl7aPMrEEEKuiYkBvrLl/ +SN4oAzQ6Kdro188PXcBOJ7dFJQxiDPa9SObOTSu4/kFMaIqxLmlUDTq30HwdgXPj +wsvBY1QWymqhmywUSDdqkY/9kqFnvJr7fL6rr2xNBAD+ejbfuiGsaNvi8eGSDQC6 +IEWoi7XHgyL7N5sXEGzcYIa6Rc8kbWahlTTsetyMpSL6WonIBzx9pbGWuqSpZuM4 +63Dott0IsZlrHXBRGs+gcUJJ1VM4Qm2B8Yr+rpWJJZ3x+n9QWDQyHPzuacGFy7nc +y21xbP+ngSB9NAfoglf61wP9GjMjrr4oPgj3rXxQXWrd+J+hUUN8DkbQbmeXfgR0 +LdFuXdVj9YHT6JDTuyzDZjgraCOJdWE3wkdyoOK3ZMYxq9ZW5Np4W9c+eQU0fIx6 +N31D+PhTh9Qzp32tQLOj2AoG+HlZhn/qFGWruNngXt3mxwthqAtYqXi71mzdYIZW +c24/k4kBHwQYAQIACQUCVOdDRAIbDAAKCRBgE1wmkm+puQmiB/9czjtf9srBKj3P +S13rkdjOHc5TaswBhnJ1lRUTssGN1hxUonjwsVO3gFtgcyv1MjXPUPi6yhC+4jdh +G47Ja3zi0TFHQm3ECL6Z+YOun6ohYpUzvuoqI/H2NRM+BYlvD2fnSCgE3RUm3V8d +uL40CcX18wGIS9Vo9/0H97XdS8tWQBLBty2LgX+LLKxzu59rEOU3pNlf09eMiJi6 +Riwi5gHfm8zv8omg5bF0pjFa2MK5297wn7i0dJlqCj7Cpr/FgHlGSZFlTqeKmusV +J/J7Kl/MpzwCDQQeWmx8WXxZ0IUTKQYjmUZrYLelWzfxbuW3ZbK8sK+GDhS6n2H0 +AqhHiFl6 +=9q5t +-----END PGP PRIVATE KEY BLOCK----- diff --git a/puphpet/puppet/modules/gnupg/files/random.public.key b/puphpet/puppet/modules/gnupg/files/random.public.key new file mode 100644 index 0000000..794da99 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/files/random.public.key @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG/MacGPG2 v2.0.22 (Darwin) + +mQENBFTnQ0QBCACx0qbkYotSSCCGAKspC8MKO+dEkna/+DA+TQ/kdtB6LV3LLTEj +xmjz7GSThEr+0nLOv17Ox9UtmZ4arH74CKo4LGognzDvaY5xEXV5SBfQAl5pYYhy +WRL7HwyGdUgeTJK/pNU7xRS4G91DuerRJauND1z+n38P6/dIdUy9PYrYSEN3NCn5 +0CP+SplEb8fDHNlLSZgBY43p1w944+ptHnp1NCU5BfYZl+dCd10iGYIE+v9K+F2r +ZOYMAvtlT4dEU8No/kkbqo2oVlvkORGydNYKlgz2+ZnAehGhK69uPhOGlUolyKA5 +LuwZnFo937D0Ia7jIlA6sRA5pOPKbe80mjA3ABEBAAG0MVRlc3QgS2V5IChHbnVQ +RyBQdXBwZXQgTW9kdWxlKSA8dGVzdEBleGFtcGxlLmNvbT6JATgEEwECACIFAlTn +Q0QCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEGATXCaSb6m50u0H/3u7 +ZVieNuCHr4NSHN/rlG04cXBU20GbRPE4xXp1HqT/17B5TgeW3nvh1swB9sTn3tQ8 +bkF0cVDi10xL8rOHnmoPCdTopZ987ZVsQoGwObHWXrpMOFhA1aHYWYDPNXxc+Hf2 +hUWflXnyqWdo00uLsRFy9KS9HisreJ1L3M1vsXHXQKsVVWrrt+Lkz9Xc4EJ2Fn/G +L336dAQTonUOPCjrgBMOnlgl3v0ApBD3PGCkqO34kzz5cOxGBkL7TN751wkbPZ1I +KAzBj0LSF5Z89PLL5Mfo6NsSouUdIbCX8sZEi6NeHL13u1jRfERUaOeuDS1gqUyb +8gKJKeNddjTSTZEyVtC5AQ0EVOdDRAEIANPfqn+qbfr8PL5wy9f0SaJJh2UmqwcH +dxZLkMQVuK+l7Gxz5qXctcDoj/DMTRGFlreH344D9QO6XGJDRDIVjS2owNf/atCY +1fF5M32BEJMKT87jg7Ycy3F+s6w9WMTuUAjok7Ojc883ph+pwqN8fT0lG64Qa0tS +oqlhx/+Q2hxEv7z6P+jHB3L4tpJsUF3Amjej4DBAkGhUWN6UgjEIaiUVjURtqzS2 +MUB22fP8hMvxUKFDkz2D490OiX2+79U9z5YrPw8FjsSjCRnCXkOBIuNRmrddAdyM +WfNx2QX+H/MPShNB+TZdXJ7eXlp5OuM/Zj/i4vzGRdEw9JemMGhCJqsAEQEAAYkB +HwQYAQIACQUCVOdDRAIbDAAKCRBgE1wmkm+puQmiB/9czjtf9srBKj3PS13rkdjO +Hc5TaswBhnJ1lRUTssGN1hxUonjwsVO3gFtgcyv1MjXPUPi6yhC+4jdhG47Ja3zi +0TFHQm3ECL6Z+YOun6ohYpUzvuoqI/H2NRM+BYlvD2fnSCgE3RUm3V8duL40CcX1 +8wGIS9Vo9/0H97XdS8tWQBLBty2LgX+LLKxzu59rEOU3pNlf09eMiJi6Riwi5gHf +m8zv8omg5bF0pjFa2MK5297wn7i0dJlqCj7Cpr/FgHlGSZFlTqeKmusVJ/J7Kl/M +pzwCDQQeWmx8WXxZ0IUTKQYjmUZrYLelWzfxbuW3ZbK8sK+GDhS6n2H0AqhHiFl6 +=LuvV +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/gnupg/lib/facter/gnupg_command.rb b/puphpet/puppet/modules/gnupg/lib/facter/gnupg_command.rb new file mode 100644 index 0000000..fd9462d --- /dev/null +++ b/puphpet/puppet/modules/gnupg/lib/facter/gnupg_command.rb @@ -0,0 +1,18 @@ +# Fact: gnupg_command +# +# Purpose: get full path to gpg exe +# +# Resolution: +# Tests for presence of gpg, returns nil if not present +# returns output of which gpg +# +# Caveats: +# none +# +# Notes: +# None +Facter.add(:gnupg_command) do + setcode do + Facter::Util::Resolution.which('gpg') + end +end diff --git a/puphpet/puppet/modules/gnupg/lib/facter/gnupg_installed.rb b/puphpet/puppet/modules/gnupg/lib/facter/gnupg_installed.rb new file mode 100644 index 0000000..54eba47 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/lib/facter/gnupg_installed.rb @@ -0,0 +1,18 @@ +# Fact: gnupg_installed +# +# Purpose: determine if gpg exe exists on system +# +# Resolution: +# Tests for presence of gpg, returns false if not present +# returns true if which gpg finds an exe +# +# Caveats: +# none +# +# Notes: +# None +Facter.add(:gnupg_installed) do + setcode do + !Facter.value(:gnupg_command).nil? + end +end diff --git a/puphpet/puppet/modules/gnupg/lib/puppet/provider/gnupg_key/gnupg.rb b/puphpet/puppet/modules/gnupg/lib/puppet/provider/gnupg_key/gnupg.rb new file mode 100644 index 0000000..d206d50 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/lib/puppet/provider/gnupg_key/gnupg.rb @@ -0,0 +1,166 @@ +require 'etc' +require 'tmpdir' +require 'puppet/file_serving/content' + +Puppet::Type.type(:gnupg_key).provide(:gnupg) do + + @doc = 'Provider for gnupg_key type.' + + defaultfor :kernel => 'Linux' + confine :kernel => 'Linux' + + def self.instances + [] + end + + # although we do not use the commands class it's used to detect if the gpg and awk commands are installed on the system + commands :gpg => 'gpg' + commands :awk => 'awk' + + def remove_key + begin + fingerprint_command = "gpg --fingerprint --with-colons #{resource[:key_id]} | awk -F: '$1 == \"fpr\" {print $10;}'" + fingerprint = Puppet::Util::Execution.execute(fingerprint_command, :uid => user_id) + rescue Puppet::ExecutionFailure => e + raise Puppet::Error, "Could not determine fingerprint for #{resource[:key_id]} for user #{resource[:user]}: #{fingerprint}" + end + + if resource[:key_type] == :public + command = "gpg --batch --yes --delete-key #{fingerprint}" + elsif resource[:key_type] == :private + command = "gpg --batch --yes --delete-secret-key #{fingerprint}" + elsif resource[:key_type] == :both + command = "gpg --batch --yes --delete-secret-and-public-key #{fingerprint}" + end + + begin + output = Puppet::Util::Execution.execute(command, :uid => user_id) + rescue Puppet::ExecutionFailure => e + raise Puppet::Error, "Could not remove #{resource[:key_id]} for user #{resource[:user]}: #{output}" + end + end + + # where most of the magic happens + # TODO implement dry-run to check if the key_id match the content of the file + def add_key + if resource[:key_server] + add_key_from_key_server + elsif resource[:key_source] + add_key_from_key_source + elsif resource[:key_content] + add_key_from_key_content + end + end + + def add_key_from_key_server + command = "gpg --keyserver #{resource[:key_server]} --recv-keys #{resource[:key_id]}" + begin + output = Puppet::Util::Execution.execute(command, :uid => user_id, :failonfail => true) + rescue Puppet::ExecutionFailure => e + raise Puppet::Error, "Key #{resource[:key_id]} does not exist on #{resource[:key_server]}" + end + end + + def add_key_from_key_source + if Puppet::Util.absolute_path?(resource[:key_source]) + add_key_at_path + else + add_key_at_url + end + end + + def add_key_from_key_content + path = create_temporary_file(user_id, resource[:key_content]) + command = "gpg --import #{path}" + begin + output = Puppet::Util::Execution.execute(command, :uid => user_id, :failonfail => true) + rescue Puppet::ExecutionFailure => e + raise Puppet::Error, "Error while importing key #{resource[:key_id]} using key content:\n#{output}}" + end + end + + def add_key_at_path + if File.file?(resource[:key_source]) + command = "gpg --import #{resource[:key_source]}" + begin + output = Puppet::Util::Execution.execute(command, :uid => user_id, :failonfail => true) + rescue Puppet::ExecutionFailure => e + raise Puppet::Error, "Error while importing key #{resource[:key_id]} from #{resource[:key_source]}" + end + elsif + raise Puppet::Error, "Local file #{resource[:key_source]} for #{resource[:key_id]} does not exists" + end + end + + def add_key_at_url + uri = URI.parse(URI.escape(resource[:key_source])) + case uri.scheme + when /https/ + command = "wget -O- #{resource[:key_source]} | gpg --import" + when /http/ + command = "gpg --fetch-keys #{resource[:key_source]}" + when 'puppet' + path = create_temporary_file user_id, puppet_content + command = "gpg --import #{path}" + end + begin + output = Puppet::Util::Execution.execute(command, :uid => user_id, :failonfail => true) + rescue Puppet::ExecutionFailure => e + raise Puppet::Error, "Error while importing key #{resource[:key_id]} from #{resource[:key_source]}:\n#{output}}" + end + end + + def user_id + begin + Etc.getpwnam(resource[:user]).uid + rescue => e + raise Puppet::Error, "User #{resource[:user]} does not exists" + end + end + + def create_temporary_file user_id, content + Puppet::Util::SUIDManager.asuser(user_id) do + tmpfile = Tempfile.open(['golja-gnupg', 'key']) + tmpfile.write(content) + tmpfile.flush + break tmpfile.path.to_s + end + end + + def puppet_content + # Look up (if necessary) and return remote content. + return @content if @content + unless tmp = Puppet::FileServing::Content.indirection.find(resource[:key_source], :environment => resource.catalog.environment, :links => :follow) + fail "Could not find any content at %s" % resource[:key_source] + end + @content = tmp.content + end + + def exists? + # public and both can be grouped since private can't be present without public, + # both only applies to delete and delete still has something to do if only + # one of the keys is present + if resource[:key_type] == :public || resource[:key_type] == :both + command = "gpg --list-keys --with-colons #{resource[:key_id]}" + elsif resource[:key_type] == :private + command = "gpg --list-secret-keys --with-colons #{resource[:key_id]}" + end + + output = Puppet::Util::Execution.execute(command, :uid => user_id) + if output.exitstatus == 0 + return true + elsif output.exitstatus == 2 + return false + else + raise Puppet::Error, "Non recognized exit status from GnuPG #{output.exitstatus} #{output}" + end + end + + def create + add_key + end + + def destroy + remove_key + end +end diff --git a/puphpet/puppet/modules/gnupg/lib/puppet/type/gnupg_key.rb b/puphpet/puppet/modules/gnupg/lib/puppet/type/gnupg_key.rb new file mode 100644 index 0000000..510e958 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/lib/puppet/type/gnupg_key.rb @@ -0,0 +1,153 @@ +require 'uri' +Puppet::Type.newtype(:gnupg_key) do + @doc = "Manage PGP public keys with GnuPG" + + ensurable + + autorequire(:package) do + ["gnupg", "gnupg2"] + end + + autorequire(:user) do + self[:user] + end + + KEY_SOURCES = [:key_source, :key_server, :key_content] + + KEY_CONTENT_REGEXES = { + :public => ["-----BEGIN PGP PUBLIC KEY BLOCK-----", "-----END PGP PUBLIC KEY BLOCK-----"], + :private => ["-----BEGIN PGP PRIVATE KEY BLOCK-----", "-----END PGP PRIVATE KEY BLOCK-----"] + } + + validate do + creator_count = 0 + KEY_SOURCES.each do |param| + creator_count += 1 unless self[param].nil? + end + + if creator_count > 1 + raise ArgumentError, "You cannot specify more than one of #{KEY_SOURCES.collect { |p| p.to_s}.join(", ")}, " + + "much to learn, you still have." + end + + if creator_count == 0 && self[:ensure] == :present + raise ArgumentError, "You need to specify at least one of #{KEY_SOURCES.collect { |p| p.to_s}.join(", ")}, " + + "much to learn, you still have." + end + + if self[:ensure] == :present && self[:key_type] == :both + raise ArgumentError, "A key type of 'both' is invalid when ensure is 'present'." + end + + [:public, :private].each do |type| + if self[:key_content] && self[:key_type] == type + key_lines = self[:key_content].strip.lines.to_a + + first_line = key_lines.first.strip + last_line = key_lines.last.strip + + unless first_line == KEY_CONTENT_REGEXES[type][0] && last_line == KEY_CONTENT_REGEXES[type][1] + raise ArgumentError, "Provided key content does not look like a #{type} key." + end + end + end + end + + newparam(:name, :namevar => true) do + desc "This attribute is currently used as a + system-wide primary key - namevar and therefore has to be unique." + end + + newparam(:user) do + desc "The user account in which the PGP public key should be installed. + Usually it's stored in HOME/.gnupg/ dir" + + validate do |value| + # freebsd/linux username limitation + unless value =~ /^[a-z_][a-z0-9_-]*[$]?/ + raise ArgumentError, "Invalid username format for #{value}" + end + end + end + + newparam(:key_source) do + desc <<-'EOT' + A source file containing PGP key. Values can be URIs pointing to remote files, + or fully qualified paths to files available on the local system. + + The available URI schemes are *puppet*, *https*, *http* and *file*. *Puppet* + URIs will retrieve files from Puppet's built-in file server, and are + usually formatted as: + + `puppet:///modules/name_of_module/filename` + EOT + + validate do |source| + + raise ArgumentError, "Arrays not accepted as an source parameter" if source.is_a?(Array) + break if Puppet::Util.absolute_path?(source) + + begin + uri = URI.parse(URI.escape(source)) + rescue => detail + raise ArgumentError, "Could not understand source #{source}: #{detail}" + end + + raise ArgumentError, "Cannot use relative URLs '#{source}'" unless uri.absolute? + raise ArgumentError, "Cannot use opaque URLs '#{source}'" unless uri.hierarchical? + raise ArgumentError, "Cannot use URLs of type '#{uri.scheme}' as source for fileserving" unless %w{file puppet https http}.include?(uri.scheme) + end + + munge do |source| + if %w{file}.include?(URI.parse(URI.escape(source)).scheme) + URI.parse(URI.escape(source)).path + else + source + end + end + + end + + newparam(:key_server) do + desc "PGP key server from where to retrieve the public key" + + validate do |server| + if server + uri = URI.parse(URI.escape(server)) + unless uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS) || + uri.is_a?(URI::LDAP) || %w{hkp}.include?(uri.scheme) + raise ArgumentError, "Invalid keyserver value #{server}" + end + end + end + + end + + newparam(:key_content) do + desc "Key content. The result of exporting the key using ASCII armor. + Can be either a public or private key." + end + + newparam(:key_id) do + desc "Key ID. Usually the traditional 8-character key ID. Also accepted the + long more accurate (but less convenient) 16-character key ID." + + validate do |value| + unless (value.length == 8 or value.length == 16) and value =~ /^[0-9A-Fa-f]+$/ + raise ArgumentError, "Invalid key id #{value}" + end + end + + munge do |value| + value.upcase.intern + end + end + + newparam(:key_type) do + desc "The type of the key(s) being managed." + + newvalues(:public, :private, :both) + + defaultto :public + end +end diff --git a/puphpet/puppet/modules/gnupg/manifests/init.pp b/puphpet/puppet/modules/gnupg/manifests/init.pp new file mode 100644 index 0000000..427d8f7 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/manifests/init.pp @@ -0,0 +1,29 @@ +# == Class: gnupg +# +# Manage gnupg and public key entries +# +# === Parameters +# +# [*package_ensure*] +# Remove or install the s3tools package. Possible values +# present or absent, however most of modern Linux distros relays on +# gnupg so you shouldn't remove the package +# +# [*package_name*] +# name of the package usually gnupg/gnupg2 depends of the distro +# +# === Examples +# +# include gnupg +# +# === Authors +# +# Dejan Golja +# +class gnupg( + $package_ensure = $gnupg::params::package_ensure, + $package_name = $gnupg::params::package_name, +) inherits gnupg::params { + + class {'::gnupg::install': } +} diff --git a/puphpet/puppet/modules/gnupg/manifests/install.pp b/puphpet/puppet/modules/gnupg/manifests/install.pp new file mode 100644 index 0000000..1916794 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/manifests/install.pp @@ -0,0 +1,9 @@ +# +class gnupg::install { + + package { 'gnupg': + ensure => $gnupg::package_ensure, + name => $gnupg::package_name, + } + +} \ No newline at end of file diff --git a/puphpet/puppet/modules/gnupg/manifests/params.pp b/puphpet/puppet/modules/gnupg/manifests/params.pp new file mode 100644 index 0000000..70e5773 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/manifests/params.pp @@ -0,0 +1,30 @@ +# PRIVATE CLASS: do not use directly +class gnupg::params { + + $package_ensure = 'present' + + case $::osfamily { + 'Debian': { + $package_name ='gnupg' + } + 'RedHat': { + $package_name = 'gnupg2' + } + 'Suse': { + $package_name = 'gpg2' + } + + 'Linux': { + if $::operatingsystem == 'Amazon' { + $package_name = 'gnupg2' + } + else { + fail("Osfamily ${::osfamily} with operating system ${::operatingsystem} is not supported") + } + } + default: { + fail("Osfamily ${::osfamily} is not supported") + } + } + +} diff --git a/puphpet/puppet/modules/gnupg/metadata.json b/puphpet/puppet/modules/gnupg/metadata.json new file mode 100644 index 0000000..cd3027e --- /dev/null +++ b/puphpet/puppet/modules/gnupg/metadata.json @@ -0,0 +1,67 @@ +{ + "name": "golja-gnupg", + "version": "1.2.1", + "author": "Dejan Golja", + "summary": "Manage gnupg package and public keys", + "license": "Apache-2.0", + "source": "git://github.com/n1tr0g/golja-gnupg.git", + "project_page": "https://github.com/n1tr0g/golja-gnupg", + "issues_url": "https://github.com/n1tr0g/golja-gnupg/issues", + "operatingsystem_support": [ + { + "operatingsystem": "RedHat", + "operatingsystemrelease": [ + "5", + "6", + "7" + ] + }, + { + "operatingsystem": "CentOS", + "operatingsystemrelease": [ + "5", + "6", + "7" + ] + }, + { + "operatingsystem": "Debian", + "operatingsystemrelease": [ + "6", + "7" + ] + }, + { + "operatingsystem": "SLES", + "operatingsystemrelease": [ + "11", + "12" + ] + }, + { + "operatingsystem": "Ubuntu", + "operatingsystemrelease": [ + "10.04", + "12.04", + "14.04" + ] + } + ], + "requirements": [ + { + "name": "puppet", + "version_requirement": ">=3.0.0 <4.0.0" + }, + { + "name": "pe", + "version_requirement": ">=3.0.0 <4.0.0" + } + ], + "tags": [ + "gnupg", + "pgp" + ], + "dependencies": [ + + ] +} diff --git a/puphpet/puppet/modules/gnupg/spec/acceptance/class_spec.rb b/puphpet/puppet/modules/gnupg/spec/acceptance/class_spec.rb new file mode 100644 index 0000000..c0cc09b --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/acceptance/class_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper_acceptance' + +describe 'gnupg class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do + case fact('osfamily') + when 'RedHat' + package_name = 'gnupg2' + when 'Debian' + package_name = 'gnupg' + end + + context 'default parameters' do + it 'should work with no errors' do + pp = <<-EOS + class { 'gnupg': } + 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 + + end + +end \ No newline at end of file diff --git a/puphpet/puppet/modules/gnupg/spec/acceptance/gnupg_key_install_spec.rb b/puphpet/puppet/modules/gnupg/spec/acceptance/gnupg_key_install_spec.rb new file mode 100644 index 0000000..b514dd1 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/acceptance/gnupg_key_install_spec.rb @@ -0,0 +1,388 @@ +require 'spec_helper_acceptance' + +describe 'install gnupg keys' do + before :all do + pp = "class { 'gnupg': }" + apply_manifest(pp, :catch_failures => true) + end + + it 'should install a public key from a http URL address' do + pp = <<-EOS + gnupg_key { 'jenkins_key': + ensure => present, + user => 'root', + key_type => public, + key_source => 'http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key', + key_id => 'D50582E6', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg installed the key + gpg("--list-keys D50582E6") do |r| + expect(r.stdout).to match(/D50582E6/) + expect(r.exit_code).to eq(0) + end + + # clean up + gpg("--batch --delete-key 150FDE3F7787E7D11EF4E12A9B7D32F2D50582E6") {} + end + + it 'should install a public key from a https URL address' do + pp = <<-EOS + gnupg_key { 'newrelic_key': + ensure => present, + user => 'root', + key_type => public, + key_source => 'https://download.newrelic.com/548C16BF.gpg', + key_id => '548C16BF', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg installed the key + gpg("--list-keys 548C16BF") do |r| + expect(r.stdout).to match(/548C16BF/) + expect(r.exit_code).to eq(0) + end + + # clean up + gpg("--batch --delete-key B60A3EC9BC013B9C23790EC8B31B29E5548C16BF") {} + end + + it 'should install a public key from a key server' do + pp = <<-EOS + gnupg_key { 'root_key_foo': + ensure => present, + user => 'root', + key_type => public, + key_server => 'hkp://pgp.mit.edu/', + key_id => '20BC0A86', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg installed the key + gpg("--list-keys 20BC0A86") do |r| + expect(r.stdout).to match(/20BC0A86/) + expect(r.exit_code).to eq(0) + end + + # clean up + gpg("--batch --delete-key 58AA73E230EB06B2A2DE8A873CCE8BC520BC0A86") {} + end + + + it 'should delete a public key' do + scp_to master, 'files/random.public.key', '/tmp/random.public.key' + gpg("--import /tmp/random.public.key") {} + + pp = <<-EOS + gnupg_key { 'bye_bye_key': + ensure => absent, + user => root, + key_type => public, + key_id => 926FA9B9, + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg deleted the key + gpg("--list-keys 926FA9B9", :acceptable_exit_codes => [0, 2]) do |r| + expect(r.stdout).to_not match(/926FA9B9/) + end + end + + it 'should install public key from the puppet fileserver/module repository' do + pp = <<-EOS + gnupg_key { 'add_key_by_remote_source': + ensure => present, + user => root, + key_type => public, + key_id => 926FA9B9, + key_source => "puppet:///modules/gnupg/random.public.key", + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg installed the key + gpg("--list-keys 926FA9B9") do |r| + expect(r.stdout).to match(/926FA9B9/) + expect(r.exit_code).to eq(0) + end + + # clean up + gpg("--batch --delete-key 7F2A6D3944CDFE31A47ECC2A60135C26926FA9B9") {} + end + + it 'should install public key from a local file path' do + scp_to master, 'files/random.public.key', '/tmp/random.public.key' + + pp = <<-EOS + gnupg_key { 'add_key_by_local_file_path': + ensure => present, + user => root, + key_type => public, + key_id => 926FA9B9, + key_source => "/tmp/random.public.key", + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg installed the key + gpg("--list-keys 926FA9B9") do |r| + expect(r.stdout).to match(/926FA9B9/) + expect(r.exit_code).to eq(0) + end + + # clean up + gpg("--batch --delete-key 7F2A6D3944CDFE31A47ECC2A60135C26926FA9B9") {} + end + + it 'should install public key from a local file URL address' do + scp_to master, 'files/random.public.key', '/tmp/random.public.key' + + pp = <<-EOS + gnupg_key { 'add_key_by_local_file_url': + ensure => present, + user => root, + key_type => public, + key_id => 926FA9B9, + key_source => "file:///tmp/random.public.key", + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg installed the key + gpg("--list-keys 926FA9B9") do |r| + expect(r.stdout).to match(/926FA9B9/) + expect(r.exit_code).to eq(0) + end + + # clean up + gpg("--batch --delete-key 7F2A6D3944CDFE31A47ECC2A60135C26926FA9B9") {} + end + + it 'should install public key using string key content' do + key = File.read('files/random.public.key') + + pp = <<-EOS + gnupg_key { 'public_key_from_string_content': + ensure => present, + user => root, + key_id => 926FA9B9, + key_type => public, + key_content => "#{key}" + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg installed the key + gpg("--list-keys 926FA9B9") do |r| + expect(r.stdout).to match(/926FA9B9/) + expect(r.exit_code).to eq(0) + end + + # clean up + gpg("--batch --delete-key 7F2A6D3944CDFE31A47ECC2A60135C26926FA9B9") {} + end + + + it 'should not install public key using string because key content is invalid' do + key = File.read('files/broken.public.key') + + pp = <<-EOS + gnupg_key { 'public_key_from_invalid_string_content': + ensure => present, + user => root, + key_id => 926FA9B9, + key_type => public, + key_content => "#{key}" + } + EOS + + apply_manifest(pp, :expect_failures => true) + end + + it 'should not install a key, because local resource does not exists' do + pp = <<-EOS + gnupg_key { 'jenkins_key': + ensure => present, + user => 'root', + key_type => public, + key_source => '/santa/claus/does/not/exists/org/sorry/kids.key', + key_id => '40404040', + } + EOS + + apply_manifest(pp, :expect_failures => true) + end + + it 'should fail to install a public key, because there is no content at the supplied URL address' do + pp = <<-EOS + gnupg_key { 'jenkins_key': + ensure => present, + user => 'root', + key_type => public, + key_source => 'http://foo.com/key-not-there.key', + key_id => '40404040', + } + EOS + + apply_manifest(pp, :expect_failures => true) + end + + it 'should install private key from a local file path' do + scp_to master, 'files/random.private.key', '/tmp/random.private.key' + + pp = <<-EOS + gnupg_key { 'add_private_key_by_local_file_path': + ensure => present, + user => root, + key_id => 926FA9B9, + key_type => private, + key_source => '/tmp/random.private.key' + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg installed the key + gpg("--list-secret-keys 926FA9B9") do |r| + expect(r.stdout).to match(/926FA9B9/) + expect(r.exit_code).to eq(0) + end + + # clean up + gpg("--batch --delete-secret-and-public-key 7F2A6D3944CDFE31A47ECC2A60135C26926FA9B9") + end + + it 'should install private key from a local file URL address' do + scp_to master, 'files/random.private.key', '/tmp/random.private.key' + + pp = <<-EOS + gnupg_key { 'add_private_key_by_local_file_path': + ensure => present, + user => root, + key_id => 926FA9B9, + key_type => private, + key_source => 'file:///tmp/random.private.key' + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg installed the key + gpg("--list-secret-keys 926FA9B9") do |r| + expect(r.stdout).to match(/926FA9B9/) + expect(r.exit_code).to eq(0) + end + + # clean up + gpg("--batch --delete-secret-and-public-key 7F2A6D3944CDFE31A47ECC2A60135C26926FA9B9") + end + + it 'should install private key using string key content' do + key = File.read('files/random.private.key') + + pp = <<-EOS + gnupg_key { 'private_key_from_string_content': + ensure => present, + user => root, + key_id => 926FA9B9, + key_type => private, + key_content => "#{key}" + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg installed the key + gpg("--list-secret-keys 926FA9B9") do |r| + expect(r.stdout).to match(/926FA9B9/) + expect(r.exit_code).to eq(0) + end + + # clean up + gpg("--batch --delete-secret-and-public-key 7F2A6D3944CDFE31A47ECC2A60135C26926FA9B9") {} + end + + it 'should delete a private key' do + # importing a private key imports the public key as well + scp_to master, 'files/random.private.key', '/tmp/random.private.key' + gpg("--import /tmp/random.private.key") {} + + pp = <<-EOS + gnupg_key { 'bye_bye_key': + ensure => absent, + user => root, + key_id => 926FA9B9, + key_type => private + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg deleted the public key + gpg("--list-secret-keys 926FA9B9", :acceptable_exit_codes => [0, 2]) do |r| + expect(r.stdout).to_not match(/926FA9B9/) + end + + # check that gnupg left the public key + gpg("--list-keys 926FA9B9") do |r| + expect(r.stdout).to match(/926FA9B9/) + expect(r.exit_code).to eq(0) + end + + # clean up + gpg("--batch --delete-key 7F2A6D3944CDFE31A47ECC2A60135C26926FA9B9") + end + + it 'should delete both public and private key for key_id' do + # importing a private key imports the public key as well + scp_to master, 'files/random.private.key', '/tmp/random.private.key' + gpg("--import /tmp/random.private.key") {} + + pp = <<-EOS + gnupg_key { 'bye_bye_key': + ensure => absent, + user => root, + key_id => 926FA9B9, + key_type => both + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + + # check that gnupg deleted the public key + gpg("--list-secret-keys 926FA9B9", :acceptable_exit_codes => [0, 2]) do |r| + expect(r.stdout).to_not match(/926FA9B9/) + end + + # check that gnupg left the public key + gpg("--list-keys 926FA9B9", :acceptable_exit_codes => [0, 2]) do |r| + expect(r.stdout).to_not match(/926FA9B9/) + end + end +end diff --git a/puphpet/puppet/modules/apache/spec/acceptance/nodesets/centos-59-x64.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/centos-59-x64.yml similarity index 100% rename from puphpet/puppet/modules/apache/spec/acceptance/nodesets/centos-59-x64.yml rename to puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/centos-59-x64.yml diff --git a/puphpet/puppet/modules/apache/spec/acceptance/nodesets/centos-64-x64-pe.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/centos-64-x64-pe.yml similarity index 100% rename from puphpet/puppet/modules/apache/spec/acceptance/nodesets/centos-64-x64-pe.yml rename to puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/centos-64-x64-pe.yml diff --git a/puphpet/puppet/modules/apache/spec/acceptance/nodesets/centos-64-x64.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/centos-64-x64.yml similarity index 100% rename from puphpet/puppet/modules/apache/spec/acceptance/nodesets/centos-64-x64.yml rename to puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/centos-64-x64.yml diff --git a/puphpet/puppet/modules/apache/spec/acceptance/nodesets/centos-65-x64.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/centos-65-x64.yml similarity index 100% rename from puphpet/puppet/modules/apache/spec/acceptance/nodesets/centos-65-x64.yml rename to puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/centos-65-x64.yml diff --git a/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-607-x64.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-607-x64.yml new file mode 100644 index 0000000..e642e09 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-607-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-70rc1-x64.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-70rc1-x64.yml new file mode 100644 index 0000000..cbbbfb2 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-70rc1-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-73-i386.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-73-i386.yml new file mode 100644 index 0000000..a38902d --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-73-i386.yml @@ -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 diff --git a/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-73-x64.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-73-x64.yml new file mode 100644 index 0000000..f9cf0c9 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/debian-73-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/default.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/default.yml new file mode 100644 index 0000000..ce47212 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/default.yml @@ -0,0 +1,11 @@ +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: + log_level: debug + type: git diff --git a/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml new file mode 100644 index 0000000..5ca1514 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml new file mode 100644 index 0000000..d065b30 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml new file mode 100644 index 0000000..f4b2366 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml new file mode 100644 index 0000000..cba1cd0 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/gnupg/spec/classes/gnupg_init_spec.rb b/puphpet/puppet/modules/gnupg/spec/classes/gnupg_init_spec.rb new file mode 100644 index 0000000..0838683 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/classes/gnupg_init_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe 'gnupg', :type => :class do + + ['RedHat', 'Debian', 'Linux', 'Suse'].each do |system| + if system == 'Linux' + let(:facts) {{ :osfamily => 'Linux', :operatingsystem => 'Amazon' }} + else + let(:facts) {{ :osfamily => system }} + end + + it { expect contain_class('gnupg::install') } + + describe "gnupg on system #{system}" do + + context "when enabled" do + let(:params) {{ + :package_ensure => 'present', + :package_name => 'gnupg' + }} + + it { expect contain_package('gnupg').with({ + 'ensure' => 'present'}) + } + end + + context 'when disabled' do + let(:params) {{ + :package_ensure => 'absent', + :package_name => 'gnupg' + }} + + it { expect contain_package('gnupg').with({ + 'ensure' => 'absent'}) + } + end + end + end +end diff --git a/puphpet/puppet/modules/gnupg/spec/spec.opts b/puphpet/puppet/modules/gnupg/spec/spec.opts new file mode 100644 index 0000000..91cd642 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/spec.opts @@ -0,0 +1,6 @@ +--format +s +--colour +--loadby +mtime +--backtrace diff --git a/puphpet/puppet/modules/gnupg/spec/spec_helper.rb b/puphpet/puppet/modules/gnupg/spec/spec_helper.rb new file mode 100644 index 0000000..f64ca3e --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/spec_helper.rb @@ -0,0 +1,3 @@ +require 'rubygems' +require 'puppetlabs_spec_helper/module_spec_helper' + diff --git a/puphpet/puppet/modules/gnupg/spec/spec_helper_acceptance.rb b/puphpet/puppet/modules/gnupg/spec/spec_helper_acceptance.rb new file mode 100644 index 0000000..a3c593d --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/spec_helper_acceptance.rb @@ -0,0 +1,48 @@ +require 'beaker-rspec/spec_helper' +require 'beaker-rspec/helpers/serverspec' + + +unless ENV['RS_PROVISION'] == 'no' + # This will install the latest available package on el and deb based + # systems fail on windows and osx, and install via gem on other *nixes + foss_opts = { :default_action => 'gem_install' } + if default.is_pe?; then install_pe; else install_puppet( foss_opts ); end + + hosts.each do |host| + if host['platform'] =~ /debian/ + on host, 'echo \'export PATH=/var/lib/gems/1.8/bin/:${PATH}\' >> ~/.bashrc' + end + + on host, "mkdir -p #{host['distmoduledir']}" + end +end + +UNSUPPORTED_PLATFORMS = ['Suse','windows','AIX','Solaris'] + +module LocalHelpers + def gpg(gpg_cmd, options = {:user => 'root', :acceptable_exit_codes => [0]}, &block) + user = options.delete(:user) + gpg = "gpg #{gpg_cmd}" + shell("su #{user} -c \"#{gpg}\"", options, &block) + end +end + +RSpec.configure do |c| + # Project root + proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) + + # Readable test descriptions + c.formatter = :documentation + + # Include in our local helpers, because some puppet images run + # as diffrent users + c.include ::LocalHelpers + + # Configure all nodes in nodeset + c.before :suite do + # Install module and dependencies + hosts.each do |host| + copy_module_to(host, :source => proj_root, :module_name => 'gnupg') + end + end +end diff --git a/puphpet/puppet/modules/gnupg/spec/spec_helper_system.rb b/puphpet/puppet/modules/gnupg/spec/spec_helper_system.rb new file mode 100644 index 0000000..e37e880 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/spec_helper_system.rb @@ -0,0 +1,66 @@ +require 'rspec-system/spec_helper' +require 'rspec-system-puppet/helpers' +require 'rspec-system-serverspec/helpers' +require 'tempfile' + +include Serverspec::Helper::RSpecSystem +include Serverspec::Helper::DetectOS +include RSpecSystemPuppet::Helpers + +class String + # Provide ability to remove indentation from strings, for the purpose of + # left justifying heredoc blocks. + def unindent + gsub(/^#{scan(/^\s*/).min_by{|l|l.length}}/, "") + end +end + +module LocalHelpers + include RSpecSystem::Util + + def gpg(gpg_cmd, user = 'root', &block) + gpg = "gpg #{gpg_cmd}" + shell("su #{shellescape(user)} -c #{shellescape(gpg)}", &block) + end +end + +RSpec.configure do |c| + # Project root + proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) + + # Enable colour + c.tty = true + + # Include in our local helpers, because some puppet images run + # as diffrent users + c.include ::LocalHelpers + + # Puppet helpers + c.include RSpecSystemPuppet::Helpers + c.extend RSpecSystemPuppet::Helpers + + # This is where we 'setup' the nodes before running our tests + c.before :suite do + # Install puppet + puppet_install + + # Install my module from the current working copy + puppet_module_install(:source => proj_root, :module_name => 'gnupg') + shell 'whoami' + shell 'puppet module list' + + # disable hiera warnings + file = Tempfile.new('foo') + begin + file.write(<<-EOS) +--- +:logger: noop + EOS + file.close + rcp(:sp => file.path, :dp => '/etc/puppet/hiera.yaml') + ensure + file.unlink + end + end +end + diff --git a/puphpet/puppet/modules/gnupg/spec/system/gnupg_key_install_spec.rb b/puphpet/puppet/modules/gnupg/spec/system/gnupg_key_install_spec.rb new file mode 100644 index 0000000..775a08d --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/system/gnupg_key_install_spec.rb @@ -0,0 +1,152 @@ +require 'spec_helper_system' + +describe 'gnupg_key install' do + + before :all do + puppet_apply("class {'gnupg': } ") do |r| + r.exit_code.should == 0 + end + end + + it 'should install a public key from a HTTP URL address' do + pp = <<-EOS.unindent + gnupg_key { 'jenkins_key': + ensure => present, + user => 'root', + key_source => 'http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key', + key_id => 'D50582E6', + } + EOS + + puppet_apply(pp) do |r| + r.exit_code.should == 2 + r.refresh + r.exit_code.should == 0 + end + + # check that gnupg installed the key + gpg("--list-keys D50582E6") do |r| + r.stdout.should =~ /D50582E6/ + r.stderr.should == '' + r.exit_code == 0 + end + end + + it 'should install a public key from a HTTPS URL address' do + pp = <<-EOS.unindent + gnupg_key { 'newrelic_key': + ensure => present, + user => 'root', + key_source => 'https://download.newrelic.com/548C16BF.gpg', + key_id => '548C16BF', + } + EOS + + puppet_apply(pp) do |r| + r.exit_code.should == 2 + r.refresh + r.exit_code.should == 0 + end + + # check that gnupg installed the key + gpg("--list-keys 548C16BF") do |r| + r.stdout.should =~ /548C16BF/ + r.stderr.should == '' + r.exit_code == 0 + end + end + + it 'should install a public key from a key server' do + pp = <<-EOS.unindent + gnupg_key { 'root_key_foo': + ensure => present, + user => 'root', + key_server => 'hkp://pgp.mit.edu/', + key_id => '20BC0A86', + } + EOS + + puppet_apply(pp) do |r| + r.exit_code.should == 2 + r.refresh + r.exit_code.should == 0 + end + + # check that gnupg installed the key + gpg("--list-keys 20BC0A86") do |r| + r.stdout.should =~ /20BC0A86/ + r.stderr.should == '' + r.exit_code == 0 + end + end + + it 'should remove public key 20BC0A86' do + pp = <<-EOS.unindent + gnupg_key { 'bye_bye_key': + ensure => absent, + key_id => 20BC0A86, + user => root, + } + EOS + + puppet_apply(pp) do |r| + r.exit_code.should == 2 + r.refresh + r.exit_code.should == 0 + end + end + + it 'should install public key from the puppet fileserver/module repository' do + pp = <<-EOS.unindent + gnupg_key {'add_key_by_remote_source': + ensure => present, + key_id => 20BC0A86, + user => root, + key_source => "puppet:///modules/gnupg/random.key", + } + EOS + + puppet_apply(pp) do |r| + r.exit_code.should == 2 + r.refresh + r.exit_code.should == 0 + end + + # check that gnupg installed the key + gpg("--list-keys 20BC0A86") do |r| + r.stdout.should =~ /20BC0A86/ + r.stderr.should == '' + r.exit_code == 0 + end + end + + it 'should not install a public key, because local resource does not exists' do + pp = <<-EOS.unindent + gnupg_key { 'jenkins_key': + ensure => present, + user => 'root', + key_source => '/santa/claus/does/not/exists/org/sorry/kids.key', + key_id => '40404040', + } + EOS + + puppet_apply(pp) do |r| + r.exit_code.should == 4 + end + end + + it 'should fail to install a public key, because there is no content at the supplied URL address' do + pp = <<-EOS.unindent + gnupg_key { 'jenkins_key': + ensure => present, + user => 'root', + key_source => 'http://foo.com/key-not-there.key', + key_id => '40404040', + } + EOS + + puppet_apply(pp) do |r| + r.exit_code.should == 4 + end + end +end diff --git a/puphpet/puppet/modules/gnupg/spec/system/install_spec.rb b/puphpet/puppet/modules/gnupg/spec/system/install_spec.rb new file mode 100644 index 0000000..1a4e906 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/system/install_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper_system' + +describe 'install gnupg:' do + + it 'test loading class with no arguments' do + pp = <<-EOS.unindent + class {'gnupg':} + EOS + + puppet_apply(pp) do |r| + r.exit_code.should == 0 + r.refresh + r.exit_code.should == 0 + end + end +end diff --git a/puphpet/puppet/modules/gnupg/spec/unit/puppet/type/gnupg_key_spec.rb b/puphpet/puppet/modules/gnupg/spec/unit/puppet/type/gnupg_key_spec.rb new file mode 100644 index 0000000..ff61e92 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/spec/unit/puppet/type/gnupg_key_spec.rb @@ -0,0 +1,127 @@ +require 'puppet' +require 'puppet/type/gnupg_key' +describe Puppet::Type.type(:gnupg_key) do + + before :each do + @gnupg_key = Puppet::Type.type(:gnupg_key).new(:name => 'foo') + end + + it 'should accept a user' do + @gnupg_key[:user] = 'root' + expect(@gnupg_key[:user]).to eq 'root' + end + + it 'should require a key_source or key_server if ensure present' do + expect { + Puppet::Type.type(:gnupg_key).new(:name => 'foo', :user => 'root', :ensure => 'present') + }.to raise_error(/You need to specify at least one of*/) + end + + it 'should ignore key_source or key_server value if ensure absent' do + @gnupg_key[:ensure] = 'absent' + expect(@gnupg_key[:ensure]). to eq :absent + end + + it 'should require a name' do + expect { + Puppet::Type.type(:gnupg_key).new({}) + }.to raise_error(Puppet::Error, 'Title or name must be provided') + end + + it 'should not allow invalid formated user' do + expect { + @gnupg_key[:user] = '1foo' + }.to raise_error(Puppet::Error, /Invalid username format for*/) + end + + it 'should accept user names with dashes' do + @gnupg_key[:user] = 'foo-bar' + end + + ['http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key', 'ldap://keys.puppetlabs.com', 'hkp://pgp.mit.edu/'].each do |val| + it "should accept key_server #{val}" do + @gnupg_key[:key_server] = val + expect(@gnupg_key[:key_server]).to eq val.to_s + end + end + + ['puppet:///modules/gnupg/random.key', 'http://www.puppetlabs.com/key.key', 'https://www.puppetlabs.com/key.key', 'file:///etc/foo.key', '/etc/foo.key'].each do |val| + it "should accept key_source #{val}" do + @gnupg_key[:key_source] = val + expect(@gnupg_key[:key_source]).to eq val.to_s.gsub("file://", "") + end + end + + it "should not accept invalid formated key_source URI" do + expect { + @gnupg_key[:key_source] = 'httk://foo.bar/' + }.to raise_error(Puppet::Error) + end + + ['20BC0A86', 'D50582e6', '20BC0a86', '9B7D32F2D50582E6', '3CCe8BC520bc0A86'].each do |val| + it "should allow key_id with #{val}" do + @gnupg_key[:key_id] = val + expect(@gnupg_key[:key_id]).to eq val.upcase.intern + end + end + + ['ABCD', '1234567G', 'ASA1321', 'q321asd'].each do |val| + it "should not allow key_id with #{val}" do + expect { + @gnupg_key[:key_id] = val + }.to raise_error(/Invalid key id*/) + end + end + + [:public, :private, :both].each do |val| + it "should allow key_type with #{val}" do + @gnupg_key[:key_type] = val + expect(@gnupg_key[:key_type]).to eq val + end + end + + it "should have a key_type of public by default" do + expect(@gnupg_key[:key_type]).to eq :public + end + + [:special, :other].each do |val| + it "should not allow invalid key_type of #{val}" do + expect { + @gnupg_key[:key_type] = val + }.to raise_error(Puppet::Error) + end + end + + it "should not allow key_type of both when ensure is present" do + expect { + Puppet::Type.type(:gnupg_key).new(:name => "key", :ensure => 'present', :key_type => 'both', :key_source => "http://www.example.com") + }.to raise_error(/A key type of 'both' is invalid when ensure is 'present'\./) + end + + it "should allow key_content with armored public key" do + key = File.read('files/random.public.key') + resource = Puppet::Type.type(:gnupg_key).new(:name => "key", :key_type => 'public', :key_content => key) + expect(resource[:key_content]).to eq key + end + + it "should allow key_content with armored private key" do + key = File.read('files/random.private.key') + resource = Puppet::Type.type(:gnupg_key).new(:name => "key", :key_type => 'private', :key_content => key) + expect(resource[:key_content]).to eq key + end + + it "should not allow key_content that does not look like a public key when key_type is public" do + key = "I am not a public key" + expect { + Puppet::Type.type(:gnupg_key).new(:name => "key", :key_type => 'public', :key_content => key) + }.to raise_error(/Provided key content does not look like a public key\./) + end + + it "should not allow key_content that does not look like a private key when key_type is private" do + key = "I am not a private key" + expect { + Puppet::Type.type(:gnupg_key).new(:name => "key", :key_type => 'private', :key_content => key) + }.to raise_error(/Provided key content does not look like a private key\./) + end + +end diff --git a/puphpet/puppet/modules/gnupg/tests/gnupg_key.pp b/puphpet/puppet/modules/gnupg/tests/gnupg_key.pp new file mode 100644 index 0000000..a3b9a21 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/tests/gnupg_key.pp @@ -0,0 +1,40 @@ +gnupg_key { 'root_key_foo': + ensure => present, + user => 'root', + key_server => 'hkp://pgp.mit.edu/', + key_id => '20BC0A86', +} + +gnupg_key { 'jenkins_key': + ensure => present, + user => 'root', + key_id => 'D50582E6', + key_source => 'http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key', +} + +gnupg_key {'root_remove': + ensure => absent, + key_id => D50582E6, + user => root, +} + +gnupg_key {'add_key_by_remote_source': + ensure => present, + key_id => F657C4B7, + user => root, + key_source => 'puppet:///modules/gnupg/random.key', +} + +gnupg_key {'add_key_by_local_source': + ensure => present, + key_id => F657C4B7, + user => root, + key_source => '/home/foo/public.key', +} + +gnupg_key {'add_key_by_local_source_file': + ensure => present, + key_id => F657C4B5, + user => root, + key_source => 'file:///home/foo/public.key', +} \ No newline at end of file diff --git a/puphpet/puppet/modules/gnupg/tests/init.pp b/puphpet/puppet/modules/gnupg/tests/init.pp new file mode 100644 index 0000000..1277628 --- /dev/null +++ b/puphpet/puppet/modules/gnupg/tests/init.pp @@ -0,0 +1 @@ +include gnupg diff --git a/puphpet/puppet/modules/inifile/.gitignore b/puphpet/puppet/modules/inifile/.gitignore new file mode 100644 index 0000000..b5b7a00 --- /dev/null +++ b/puphpet/puppet/modules/inifile/.gitignore @@ -0,0 +1,7 @@ +pkg/ +Gemfile.lock +vendor/ +spec/fixtures/ +.vagrant/ +.bundle/ +coverage/ diff --git a/puphpet/puppet/modules/java/.gitignore b/puphpet/puppet/modules/java/.gitignore new file mode 100644 index 0000000..b5db85e --- /dev/null +++ b/puphpet/puppet/modules/java/.gitignore @@ -0,0 +1,9 @@ +pkg/ +Gemfile.lock +vendor/ +spec/fixtures/ +.vagrant/ +.bundle/ +coverage/ +.idea/ +*.iml diff --git a/puphpet/puppet/modules/locales/.gitignore b/puphpet/puppet/modules/locales/.gitignore new file mode 100644 index 0000000..0f9c769 --- /dev/null +++ b/puphpet/puppet/modules/locales/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +pkg/ +*.swp diff --git a/puphpet/puppet/modules/mailcatcher/.fixtures.yml b/puphpet/puppet/modules/mailcatcher/.fixtures.yml deleted file mode 100644 index 0d21abb..0000000 --- a/puphpet/puppet/modules/mailcatcher/.fixtures.yml +++ /dev/null @@ -1,5 +0,0 @@ -fixtures: - repositories: - stdlib: "git://github.com/puppetlabs/puppetlabs-stdlib.git" - symlinks: - mailcatcher: "#{source_dir}" diff --git a/puphpet/puppet/modules/mailcatcher/.travis.yml b/puphpet/puppet/modules/mailcatcher/.travis.yml deleted file mode 100644 index 08a65c8..0000000 --- a/puphpet/puppet/modules/mailcatcher/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- -branches: - only: - - master -language: ruby -bundler_args: --without development -script: "bundle exec rake spec SPEC_OPTS='--format documentation'" -rvm: -- 1.8.7 -- 1.9.3 -- 2.0.0 -env: - matrix: - - PUPPET_GEM_VERSION="~> 2.7.0" - - PUPPET_GEM_VERSION="~> 3.0.0" - - PUPPET_GEM_VERSION="~> 3.1.0" - - PUPPET_GEM_VERSION="~> 3.2.0" -matrix: - exclude: - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 2.7.0" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 2.7.0" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3.0.0" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3.1.0" - - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 3.2.0" -notifications: - email: false \ No newline at end of file diff --git a/puphpet/puppet/modules/mailcatcher/Gemfile b/puphpet/puppet/modules/mailcatcher/Gemfile deleted file mode 100644 index 170516d..0000000 --- a/puphpet/puppet/modules/mailcatcher/Gemfile +++ /dev/null @@ -1,12 +0,0 @@ -source 'https://rubygems.org' -puppetversion = ENV.key?('PUPPET_VERSION') ? "= #{ENV['PUPPET_VERSION']}" : ['>= 2.7'] - -gem 'puppet', puppetversion - -group :test do - gem 'rake', '>= 0.9.0' - gem 'rspec', '>= 2.8.0' - gem 'rspec-puppet', '>= 0.1.1' - gem 'puppetlabs_spec_helper', '>= 0.4.1' - gem 'puppet-lint' -end diff --git a/puphpet/puppet/modules/mailcatcher/Modulefile b/puphpet/puppet/modules/mailcatcher/Modulefile deleted file mode 100644 index 54de3a1..0000000 --- a/puphpet/puppet/modules/mailcatcher/Modulefile +++ /dev/null @@ -1,13 +0,0 @@ -name 'actionjack-mailcatcher' -version '0.1.5' -source 'https://github.com/actionjack/puppet-mailcatcher' -author 'actionjack' -license 'Apache License, Version 2.0' -summary 'Install and configure the mailcatcher application.' -description "This puppet module is used to install and configure the mailcatcher -application. -MailCatcher runs a super simple SMTP server which catches any message sent to it -to display in a web interface." -project_page 'https://github.com/actionjack/puppet-mailcatcher' - -dependency 'puppetlabs/stdlib', '>= 2.2.1' diff --git a/puphpet/puppet/modules/mailcatcher/README.md b/puphpet/puppet/modules/mailcatcher/README.md deleted file mode 100644 index 12d569a..0000000 --- a/puphpet/puppet/modules/mailcatcher/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Mailcatcher - -[![Build Status](https://travis-ci.org/actionjack/puppet-mailcatcher.png?branch=master)](https://travis-ci.org/actionjack/puppet-mailcatcher) - -This puppet module is used to install and configure the mailcatcher application. -MailCatcher runs a super simple SMTP server which catches any message sent to it to display in a web interface. -http://mailcatcher.me/ - -* * * - -## Configuration - - -## Dependencies - -Current dependencies are: - - * 'puppetlabs/stdlib', '>= 2.1.0' - -## Usage - - - -```ruby -class {'mailcatcher': } -``` - -## Documentation - -This module is written in puppetdoc compliant format so details on configuration and usage can be found by executing: - -```bash -$ puppet doc manifest/init.pp -``` diff --git a/puphpet/puppet/modules/mailcatcher/Rakefile b/puphpet/puppet/modules/mailcatcher/Rakefile deleted file mode 100644 index e0e78cf..0000000 --- a/puphpet/puppet/modules/mailcatcher/Rakefile +++ /dev/null @@ -1,6 +0,0 @@ -require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet-lint/tasks/puppet-lint' - -PuppetLint.configuration.send('disable_class_inherits_from_params_class') -PuppetLint.configuration.send("disable_80chars") -PuppetLint.configuration.log_format = "%{path}:%{linenumber}:%{check}:%{KIND}:%{message}" diff --git a/puphpet/puppet/modules/mailcatcher/manifests/config.pp b/puphpet/puppet/modules/mailcatcher/manifests/config.pp deleted file mode 100644 index c4a2792..0000000 --- a/puphpet/puppet/modules/mailcatcher/manifests/config.pp +++ /dev/null @@ -1,18 +0,0 @@ -# class mailcatcher::config -# -class mailcatcher::config { - user { 'mailcatcher': - ensure => present, - comment => 'Mailcatcher Mock Smtp Service User', - home => '/var/spool/mailcatcher', - shell => '/bin/true', - } - - file { $mailcatcher::params::log_path: - ensure => directory, - owner => 'mailcatcher', - group => 'mailcatcher', - mode => 0755, - require => User['mailcatcher'] - } -} diff --git a/puphpet/puppet/modules/mailcatcher/manifests/init.pp b/puphpet/puppet/modules/mailcatcher/manifests/init.pp deleted file mode 100644 index 31c5d34..0000000 --- a/puphpet/puppet/modules/mailcatcher/manifests/init.pp +++ /dev/null @@ -1,64 +0,0 @@ -# == Class: mailcatcher -# -# Install and configure Mailcatcher. -# MailCatcher runs a super simple SMTP server which catches any message sent to -# it to display in a web interface. -# http://mailcatcher.me/ -# -# === Parameters -# -# Document parameters here. -# -# [*smtp_ip*] -# What IP address the mailcatcher smtp service should listen on. -# The default is 127.0.0.1 -# -# [*smtp_port*] -# What TCP Port the mailcatcher smtp service should listen on. -# The default is 1025 -# -# [*http_ip*] -# What IP address the mailcatcher web mail client service should listen on. -# The default is 0.0.0.0 -# -# [*http_port*] -# What TCP Port the mailcatcher web mail client service should listen on. -# The default is 1080 -# -# [*mailcatcher_path*] -# Path to the mailcatcher program. -# The default is '/usr/local/bin' -# -# === Examples -# -# [*default*] -# -# class { mailcatcher: } -# -# [*listen on all ethernet adapters*] -# -# class { mailcatcher: -# smtp_ip => '0.0.0.0' -# } -# -# === Authors -# -# Martin Jackson -# -# === Copyright -# -# Copyright 2013 Martin Jackson, unless otherwise noted. -# -class mailcatcher ( - $smtp_ip = $mailcatcher::params::smtp_ip, - $smtp_port = $mailcatcher::params::smtp_port, - $http_ip = $mailcatcher::params::http_ip, - $http_port = $mailcatcher::params::http_port, - $mailcatcher_path = $mailcatcher::params::mailcatcher_path, - $log_path = $mailcatcher::params::log_path -) inherits mailcatcher::params { - - class {'mailcatcher::package': } -> - class {'mailcatcher::config': } - -} diff --git a/puphpet/puppet/modules/mailcatcher/manifests/package.pp b/puphpet/puppet/modules/mailcatcher/manifests/package.pp deleted file mode 100644 index 6d66fb8..0000000 --- a/puphpet/puppet/modules/mailcatcher/manifests/package.pp +++ /dev/null @@ -1,17 +0,0 @@ -# class mailcatcher::package -# -class mailcatcher::package { - each( $mailcatcher::params::packages ) |$package| { - if ! defined(Package[$package]) { - package { $package: - ensure => present - } - } - } - - package { 'mailcatcher': - ensure => present, - provider => 'gem', - require => Package[$mailcatcher::params::packages] - } -} diff --git a/puphpet/puppet/modules/mailcatcher/manifests/params.pp b/puphpet/puppet/modules/mailcatcher/manifests/params.pp deleted file mode 100644 index a21d6b0..0000000 --- a/puphpet/puppet/modules/mailcatcher/manifests/params.pp +++ /dev/null @@ -1,22 +0,0 @@ -# class mailcatcher::params -# -class mailcatcher::params { - $smtp_ip = '0.0.0.0' - $smtp_port = '1025' - $http_ip = '0.0.0.0' - $http_port = '1080' - $mailcatcher_path = '/usr/local/bin' - $log_path = '/var/log/mailcatcher' - - case $::osfamily { - 'Debian': { - $packages = ['ruby-dev', 'sqlite3', 'libsqlite3-dev', 'rubygems'] - } - 'Redhat': { - $packages = ['ruby-devel', 'sqlite', 'sqlite-devel', 'ruby-sqlite3', 'rubygems'] - } - default: { - fail("${::osfamily} is not supported.") - } - } -} diff --git a/puphpet/puppet/modules/mailcatcher/spec/classes/mailcatcher_spec.rb b/puphpet/puppet/modules/mailcatcher/spec/classes/mailcatcher_spec.rb deleted file mode 100644 index 4ae17bd..0000000 --- a/puphpet/puppet/modules/mailcatcher/spec/classes/mailcatcher_spec.rb +++ /dev/null @@ -1,41 +0,0 @@ -require 'spec_helper' - -describe 'mailcatcher', :type => :class do - context "As a Web Operations Engineer" do - context 'When I install the mailcatcher base class on Ubuntu' do - let :facts do { - :osfamily => 'Debian', - :operatingsystem => 'Ubuntu' - } - end - - describe 'by default it' do - it { should contain_package('ruby-dev') } - it { should contain_package('sqlite3') } - it { should contain_package('libsqlite3-dev') } - it { should contain_package('rubygems') } - it { should contain_package('mailcatcher').with({ 'provider' => 'gem'}) } - it { should contain_user('mailcatcher') } - it 'should contain a properly formatted start up configuration for upstart' do - should contain_file('/etc/init/mailcatcher.conf').with_content(/exec\s+nohup\s+\/usr\/local\/bin\/mailcatcher\s+--http-ip\s+0\.0\.0\.0\s+--http-port\s+1080\s+--smtp-ip\s+0\.0\.0\.0\s+--smtp-port\s+1025\s+-f/) - end - it { should contain_file('/etc/init/mailcatcher.conf').with({ :notify => 'Class[Mailcatcher::Service]'})} - it { should contain_file('/var/log/mailcatcher').with({ - :ensure => 'directory', - :owner => 'mailcatcher', - :group => 'mailcatcher', - :mode => '0755', - :require => 'User[mailcatcher]' - })} - it { should contain_service('mailcatcher').with({ - :ensure => 'running', - :provider => 'upstart', - :hasstatus => true, - :hasrestart => true, - :require => 'Class[Mailcatcher::Config]', - })} - - end - end - end -end diff --git a/puphpet/puppet/modules/mailcatcher/spec/spec_helper.rb b/puphpet/puppet/modules/mailcatcher/spec/spec_helper.rb deleted file mode 100644 index 3d92005..0000000 --- a/puphpet/puppet/modules/mailcatcher/spec/spec_helper.rb +++ /dev/null @@ -1 +0,0 @@ -require 'puppetlabs_spec_helper/module_spec_helper' \ No newline at end of file diff --git a/puphpet/puppet/modules/mailcatcher/templates/etc/init/mailcatcher.conf.erb b/puphpet/puppet/modules/mailcatcher/templates/etc/init/mailcatcher.conf.erb deleted file mode 100644 index 4cd663f..0000000 --- a/puphpet/puppet/modules/mailcatcher/templates/etc/init/mailcatcher.conf.erb +++ /dev/null @@ -1,16 +0,0 @@ -# mailcatcher - mock smtp server -# -# mailCatcher runs a super simple SMTP server which catches any -# message sent to it to display in a web interface. - -description "mock smtp server" - -start on startup -stop on shutdown - -setuid mailcatcher -setgid mailcatcher - -script - exec nohup <%= @mailcatcher_path %>/mailcatcher<%= @options.join(' ') %> -f >> /var/log/mailcatcher/mailcatcher.log 2>&1 -end script diff --git a/puphpet/puppet/modules/mailcatcher/tests/init.pp b/puphpet/puppet/modules/mailcatcher/tests/init.pp deleted file mode 100644 index adead28..0000000 --- a/puphpet/puppet/modules/mailcatcher/tests/init.pp +++ /dev/null @@ -1,12 +0,0 @@ -# The baseline for module testing used by Puppet Labs is that each manifest -# should have a corresponding test manifest that declares that class or defined -# type. -# -# Tests are then run by using puppet apply --noop (to check for compilation -# errors and view a log of events) or by fully applying the test in a virtual -# environment (to compare the resulting system state to the desired state). -# -# Learn more about module testing here: -# http://docs.puppetlabs.com/guides/tests_smoke.html -# -include mailcatcher diff --git a/puphpet/puppet/modules/mongodb/.fixtures.yml b/puphpet/puppet/modules/mongodb/.fixtures.yml index e48e20a..5ef41aa 100644 --- a/puphpet/puppet/modules/mongodb/.fixtures.yml +++ b/puphpet/puppet/modules/mongodb/.fixtures.yml @@ -1,6 +1,8 @@ fixtures: repositories: "stdlib": "git://github.com/puppetlabs/puppetlabs-stdlib.git" - "apt": "git://github.com/puppetlabs/puppetlabs-apt.git" + "apt": + repo: "git://github.com/puppetlabs/puppetlabs-apt.git" + branch: "1.8.x" symlinks: "mongodb": "#{source_dir}" diff --git a/puphpet/puppet/modules/mongodb/.gitignore b/puphpet/puppet/modules/mongodb/.gitignore new file mode 100644 index 0000000..ac231ef --- /dev/null +++ b/puphpet/puppet/modules/mongodb/.gitignore @@ -0,0 +1,11 @@ +pkg/ +Gemfile.lock +vendor/ +spec/fixtures/ +.vagrant/ +.bundle/ +coverage/ +.idea/ +*.iml +.ruby-* +log/ diff --git a/puphpet/puppet/modules/mongodb/.sync.yml b/puphpet/puppet/modules/mongodb/.sync.yml new file mode 100644 index 0000000..ac83790 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/.sync.yml @@ -0,0 +1,9 @@ +--- +.travis.yml: + extras: + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0" +spec/spec_helper.rb: + unmanaged: true diff --git a/puphpet/puppet/modules/mongodb/.travis.yml b/puphpet/puppet/modules/mongodb/.travis.yml index f6eff1c..7e8ed57 100644 --- a/puphpet/puppet/modules/mongodb/.travis.yml +++ b/puphpet/puppet/modules/mongodb/.travis.yml @@ -1,33 +1,24 @@ -branches: - only: - - master +--- +sudo: false language: ruby -before_install: - - gem update bundler - - bundle --version - - gem update --system 2.1.11 - - gem --version -bundler_args: --without development -script: "bundle exec rake spec SPEC_OPTS='--format documentation'" -after_success: - - git clone -q git://github.com/puppetlabs/ghpublisher.git .forge-release - - .forge-release/publish -rvm: - - 1.8.7 - - 1.9.3 - - 2.0.0 -env: - matrix: - - PUPPET_GEM_VERSION="~> 2.7.0" - - PUPPET_GEM_VERSION="~> 3.3.0" - global: - - PUBLISHER_LOGIN=puppetlabs - - secure: "iUYpjvk33JffZB9lVRqjuwRWesvcvmTknh908xnf60rUOA0QbGEPXxQY+LsQJEIimVsMA22fV6vp9BcqMEjO7OfK2MvAWsEWU/lG+kisFqhWDRf96sADE7k/RvPWJeB2xe+lWXK7Eh26jgctNfk4NptX1X1MjGmdzEvH7Aq79/w=" +bundler_args: --without system_tests +script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake spec SPEC_OPTS='--format documentation'" matrix: - exclude: - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 2.7.0" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 2.7.0" + fast_finish: true + include: + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 3.0" + - rvm: 1.9.3 + env: PUPPET_GEM_VERSION="~> 3.0" + - rvm: 2.1.5 + env: PUPPET_GEM_VERSION="~> 3.0" + - rvm: 2.1.5 + env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes" + - rvm: 2.1.6 + env: PUPPET_GEM_VERSION="~> 4.0" STRICT_VARIABLES="yes" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0" notifications: email: false diff --git a/puphpet/puppet/modules/mongodb/CHANGELOG b/puphpet/puppet/modules/mongodb/CHANGELOG deleted file mode 100644 index 92a220f..0000000 --- a/puphpet/puppet/modules/mongodb/CHANGELOG +++ /dev/null @@ -1,74 +0,0 @@ -##2014-05-27 - Release 0.8.0 - -This feature features a rewritten mongodb_replset{} provider, includes several -important bugfixes, ruby 1.8 support, and two new features. - -####Features -- Rewritten mongodb_replset{}, featuring puppet resource support, prefetching, -and flushing. -- Add Ruby 1.8 compatibility. -- Adds `syslog`, allowing you to configure mongodb to send all logging to the hosts syslog. -- Add mongodb::replset, a wrapper class for hiera users. -- Improved testing! - -####Bugfixes -- Fixes the package names to work since 10gen renamed them again. -- Fix provider name in the README. -- Disallow `nojournal` and `journal` to be set at the same time. -- Changed - to = for versioned install on Ubuntu. - -####Known Bugs -* No known bugs - -2014-1-29 - Version 0.7.0 - -Summary: - -Added Replica Set Type and Provider - -2014-1-17 - Version 0.6.0 - -Summary: - -Added support for installing MongoDB client on -RHEL family systems. - -2014-01-10 Version 0.5.0 - -Summary: - -Added types for providers for Mongo users and databases. - -2013-12 Version 0.4.0 - -Major refactoring of the MongoDB module. Includes a new 'mongodb::globals' -that consolidates many shared parameters into one location. This is an -API-breaking release in anticipation of a 1.0 release. - -2013-10-31 - Version 0.3.0 - -Summary: - -Adds a number of parameters and fixes some platform -specific bugs in module deployment. - -2013-09-25 - Version 0.2.0 - -Summary: - -This release fixes a duplicate parameter. - -Fixes: -- Fix a duplicated parameter. - -2012-07-13 Puppet Labs - 0.1.0 -* Add support for RHEL/CentOS -* Change default mongodb install location to OS repo - -2012-05-29 Puppet Labs - 0.0.2 -* Fix Modulefile typo. -* Remove repo pin. -* Update spec tests and add travis support. - -2012-05-03 Puppet Labs - 0.0.1 -* Initial Release. diff --git a/puphpet/puppet/modules/mongodb/CHANGELOG.md b/puphpet/puppet/modules/mongodb/CHANGELOG.md new file mode 100644 index 0000000..218d0e9 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/CHANGELOG.md @@ -0,0 +1,129 @@ +## Unreleased +### Summary +- support setting a proxy for yum repositories with or without user/password authentication + +## 2015-06-22 - Release 0.11.0 +### Summary + +#### Features +- Add arbiter support to to `mongodb_replset` +- Add `mongod_service_manage`, `mongos_service_manage`, and `ipv6` to `mongodb::globals` +- Add `service_manage`, `unitxsocketprefix`, `pidfilepath`, `logpath`, `fork`, `bind_ip`, `port`, and `restart` to `mongodb::mongos` class +- Add `key`, `ipv6`, `service_manage`, and `restart` to `mongodb::server` class +- Allow mongodb\_conn\_validator to take an array of nodes via composite namevar + +#### Bugfixes +- Update to long apt repo key and bump compatibility to include apt 2 +- Fix `nohttpinterface` on >= 2.6 +- Fix connection validation when bind\_ip is 0.0.0.0 +- Fix mongodb\_conn\_validator to use default port in shard mode + +##2015-01-13 - Release 0.10.0 +###Summary + +This release adds a number of significant features and several bug fixes. + +####Features +- Adds support for sharding +- Adds support for RHEL 7 +- Adds rudimentary support for SSL configuration +- Adds support for the enterprise repository + +####Bugfixes +- Fixes support for running on non-default ports +- Fixes the idempotency of password setting (for mongo 2.6) + +##2014-11-25 - Release 0.9.0 +###Summary + +This release has a number of new parameters, support for 2.6, improved providers, and several bugfixes. + +####Features +- New parameters: `mongodb::globals` + - `$service_ensure` + - `$service_enable` +- New parameters: `mongodb` + - `$quiet` +- New parameters: `mongodb::server` + - `$service_ensure` + - `$service_enable` + - `$quiet` + - `$config_content` +- Support for mongodb 2.6 +- Reimplement `mongodb_user` and `mongodb_database` provider +- Added `mongodb_conn_validator` type + +####Bugfixes +- Use hkp for the apt keyserver +- Fix mongodb database existance check +- Fix `$server_package_name` problem (MODULES-690) +- Make sure `pidfilepath` doesn't have any spaces +- Providers need the client command before they can work (MODULES-1285) + +##2014-05-27 - Release 0.8.0 +###Summary + +This feature features a rewritten mongodb_replset{} provider, includes several +important bugfixes, ruby 1.8 support, and two new features. + +####Features +- Rewritten mongodb_replset{}, featuring puppet resource support, prefetching, +and flushing. +- Add Ruby 1.8 compatibility. +- Adds `syslog`, allowing you to configure mongodb to send all logging to the hosts syslog. +- Add mongodb::replset, a wrapper class for hiera users. +- Improved testing! + +####Bugfixes +- Fixes the package names to work since 10gen renamed them again. +- Fix provider name in the README. +- Disallow `nojournal` and `journal` to be set at the same time. +- Changed - to = for versioned install on Ubuntu. + +##2014-1-29 - Release 0.7.0 +###Summary + +Added Replica Set Type and Provider + +##2014-1-17 - Release 0.6.0 +###Summary + +Added support for installing MongoDB client on +RHEL family systems. + +##2014-01-10 Release 0.5.0 +###Summary + +Added types for providers for Mongo users and databases. + +##2013-12 Release 0.4.0 + +Major refactoring of the MongoDB module. Includes a new 'mongodb::globals' +that consolidates many shared parameters into one location. This is an +API-breaking release in anticipation of a 1.0 release. + +##2013-10-31 - Release 0.3.0 +###Summary + +Adds a number of parameters and fixes some platform +specific bugs in module deployment. + +##2013-09-25 - Release 0.2.0 +###Summary + +This release fixes a duplicate parameter. + +####Bugfixes +- Fix a duplicated parameter. + +##2012-07-13 - Release 0.1.0 +- Add support for RHEL/CentOS +- Change default mongodb install location to OS repo + +##2012-05-29 - Release 0.0.2 +- Fix Modulefile typo. +- Remove repo pin. +- Update spec tests and add travis support. + +##2012-05-03 - Release 0.0.1 +- Initial Release. diff --git a/puphpet/puppet/modules/mongodb/CONTRIBUTING.md b/puphpet/puppet/modules/mongodb/CONTRIBUTING.md new file mode 100644 index 0000000..f1cbde4 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/CONTRIBUTING.md @@ -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/) + diff --git a/puphpet/puppet/modules/mongodb/Gemfile b/puphpet/puppet/modules/mongodb/Gemfile index 39abe86..2b1b7cd 100644 --- a/puphpet/puppet/modules/mongodb/Gemfile +++ b/puphpet/puppet/modules/mongodb/Gemfile @@ -1,19 +1,47 @@ -source ENV['GEM_SOURCE'] || 'https://rubygems.org' +source ENV['GEM_SOURCE'] || "https://rubygems.org" -group :test, :development do - gem 'rspec-puppet', :require => false - gem 'rake', :require => false +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 'serverspec', :require => false - gem 'puppet-lint', :require => false - gem 'pry', :require => false gem 'simplecov', :require => false - gem 'beaker', :require => false - gem 'beaker-rspec', :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 +end + + + +if facterversion = ENV['FACTER_GEM_VERSION'] + gem 'facter', facterversion, :require => false +else + gem 'facter', :require => false end -if puppetversion = ENV['PUPPET_VERSION'] +if puppetversion = ENV['PUPPET_GEM_VERSION'] gem 'puppet', puppetversion, :require => false else gem 'puppet', :require => false end + +# vim:ft=ruby diff --git a/puphpet/puppet/modules/mongodb/Modulefile b/puphpet/puppet/modules/mongodb/Modulefile deleted file mode 100644 index e2eb827..0000000 --- a/puphpet/puppet/modules/mongodb/Modulefile +++ /dev/null @@ -1,12 +0,0 @@ -name 'puppetlabs-mongodb' -version '0.8.0' -source 'git@github.com:puppetlabs/puppetlabs-mongodb.git' -author 'puppetlabs' -license 'Apache License Version 2.0' -summary 'mongodb puppet module' -description '10gen mongodb puppet module' -project_page 'https://github.com/puppetlabs/puppetlabs-mongodb' - -## Add dependencies, if any: -dependency 'puppetlabs/apt', '>= 1.0.0' -dependency 'puppetlabs/stdlib', '>= 2.2.0' diff --git a/puphpet/puppet/modules/mongodb/README.md b/puphpet/puppet/modules/mongodb/README.md index 2bc16bb..5753fa8 100644 --- a/puphpet/puppet/modules/mongodb/README.md +++ b/puphpet/puppet/modules/mongodb/README.md @@ -19,9 +19,9 @@ Installs MongoDB on RHEL/Ubuntu/Debian from OS repo, or alternatively from ### Deprecation Warning ### -This release is a major refactoring of the module which means that the API may -have changed in backwards incompatible ways. If your project depends on the old API, -please pin your dependencies to 0.3 version to ensure your environments don't break. +This module is still in beta which means the API is subject to change in +backwards incompatible ways. If your project depends on an old API, please pin +your dependencies to the necessary version to ensure your environments don't break. The current module design is undergoing review for potential 1.0 release. We welcome any feedback with regard to the APIs and patterns used in this release. @@ -45,6 +45,7 @@ For the 0.6 release, the MongoDB module now supports basic replicaset features * MongoDB configuration files. * MongoDB service. * MongoDB client. +* MongoDB sharding support (mongos) * 10gen/mongodb apt/yum repository. ###Beginning with MongoDB @@ -62,13 +63,22 @@ class {'::mongodb::server': For Red Hat family systems, the client can be installed in a similar fashion: -``` -puppet class {'::mongodb::client':} +```puppet +class {'::mongodb::client':} ``` Note that for Debian/Ubuntu family systems the client is installed with the server. Using the client class will by default install the server. +If one plans to configure sharding for a Mongo deployment, the module offer +the `mongos` installation. `mongos` can be installed the following way : + +```puppet +class {'::mongodb::mongos' : + configdb => ['configsvr1.example.com:27018'], +} +``` + Although most distros come with a prepacked MongoDB server we recommend to use the 10gen/MongoDB software repository, because most of the current OS packages are outdated and not appropriate for a production environment. @@ -82,6 +92,32 @@ class {'::mongodb::server': }-> class {'::mongodb::client': } ``` +If you don't want to use the 10gen/MongoDB software repository or the OS packages, +you can point the module to a custom one. +To install MongoDB from a custom repository: + +```puppet +class {'::mongodb::globals': + manage_package_repo => true, + repo_location => 'http://example.com/repo' +}-> +class {'::mongodb::server': }-> +class {'::mongodb::client': } +``` + +Having a local copy of MongoDB repository (that is managed by your private modules) +you can still enjoy the charms of `mongodb::params` that manage packages. +To disable managing of repository, but still enable managing packages: + +```puppet +class {'::mongodb::globals': + manage_package_repo => false, + manage_package => true, +}-> +class {'::mongodb::server': }-> +class {'::mongodb::client': } +``` + ## Usage Most of the interaction for the server is done via `mongodb::server`. For @@ -116,6 +152,7 @@ Unsafe plain text password could be used with 'password' parameter instead of 'p * `mongodb::server`: Installs and configure MongoDB * `mongodb::client`: Installs the MongoDB client shell (for Red Hat family systems) * `mongodb::globals`: Configure main settings in a global way +* `mongodb::mongos`: Installs and configure Mongos server (for sharding support) ####Private classes * `mongodb::repo`: Manage 10gen/MongoDB software repository @@ -125,6 +162,9 @@ Unsafe plain text password could be used with 'password' parameter instead of 'p * `mongodb::server::install`: Install MongoDB software packages * `mongodb::server::service`: Manages service * `mongodb::client::install`: Installs the MongoDB client software package +* `mongodb::mongos::config`: Configures Mongos configuration files +* `mongodb::mongos::install`: Install Mongos software packages +* `mongodb::mongos::service`: Manages Mongos service ####Class: mongodb::globals *Note:* most server specific defaults should be overridden in the `mongodb::server` @@ -155,6 +195,14 @@ This setting can be used to override the default status check command for your MongoDB service. If not specified, the module will use whatever service name is the default for your OS distro. +##### `mongod_service_manage` +This setting can be used to override the default management of the mongod service. +By default the module will manage the mongod process. + +##### `mongos_service_manage` +This setting can be used to override the default management of the mongos service. +By default the module will manage the mongos process. + #####`user` This setting can be used to override the default MongoDB user and owner of the service and related files in the file system. If not specified, the module will @@ -165,6 +213,10 @@ This setting can be used to override the default MongoDB user group to be used for related files in the file system. If not specified, the module will use the default for your OS distro. +#####`ipv6` +This setting is used to configure MongoDB to turn on ipv6 support. If not specified +and ipv6 address is passed to MongoDB bind_ip it will just fail. + #####`bind_ip` This setting can be used to configure MonogDB process to bind to and listen for connections from applications on this address. If not specified, the @@ -176,6 +228,19 @@ The version of MonogDB to install/manage. This is a simple way of providing a specific version such as '2.2' or '2.4' for example. If not specified, the module will use the default for your OS distro. +#####`repo_location` +This setting can be used to override the default MongoDB repository location. +If not specified, the module will use the default repository for your OS distro. + +#####`repo_proxy` +This will allow you to set a proxy for your repository in case you are behind a corporate firewall. Currently this is only supported with yum repositories + +#####`proxy_username` +This sets the username for the proxyserver, should authentication be required + +#####`proxy_password` +This sets the password for the proxyserver, should authentication be required + ####Class: mongodb::server Most of the parameters manipulate the mongod.conf file. @@ -203,6 +268,10 @@ Specify the path to a file name for the log file that will hold all diagnostic logging information. Unless specified, mongod will output all log information to the standard output. +#####`ipv6` +This setting has to be true to configure MongoDB to turn on ipv6 support. If not specified +and ipv6 address is passed to MongoDB bind_ip it will just fail. + #####`bind_ip` Set this option to configure the mongod or mongos process to bind to and listen for connections from applications on this address. If not specified, the module @@ -328,13 +397,43 @@ MMS identifier for mms monitoring. Default: None #####`mms_interval` MMS interval for mms monitoring. Default: None +#####`configsvr` +Use this setting to enable config server mode for mongod. + +#####`shardsvr` +Use this setting to enable shard server mode for mongod. + #####`replset` Use this setting to configure replication with replica sets. Specify a replica set name as an argument to this set. All hosts must have the same set name. +#####`replset_members` +An array of member hosts for the replica set. +Mutually exclusive with `replset_config` param. + +#####`replset_config` +A hash that is used to configure the replica set. +Mutually exclusive with `replset_members` param. + +```puppet +class mongodb::server { + replset => 'rsmain', + replset_config => { 'rsmain' => { ensure => present, members => ['host1:27017', 'host2:27017', 'host3:27017'] } } + +} +``` + #####`rest` Set to true to enable a simple REST interface. Default: false +#####`quiet` +Runs the mongod or mongos instance in a quiet mode that attempts to limit the +amount of output. This option suppresses : "output from database commands, including drop, dropIndexes, diagLogging, validate, and clean", "replication activity", "connection accepted events" and "connection closed events". +Default: false + +> For production systems this option is **not** recommended as it may make tracking +problems during particular connections much more difficult. + #####`slowms` Sets the threshold for mongod to consider a query “slow” for the database profiler. Default: 100 ms @@ -343,6 +442,10 @@ Default: 100 ms Specify the path to a key file to store authentication information. This option is only useful for the connection between replica set members. Default: None +#####'key' +Specify the key contained within the keyfile. This option +is only useful for the connection between replica set members. Default: None + #####`master` Set to true to configure the current instance to act as master instance in a replication configuration. Default: False *Note*: deprecated – use replica sets @@ -371,6 +474,101 @@ Used with the slave setting to specify the master instance from which this slave instance will replicate. Default: <> *Note*: deprecated – use replica sets +#####`ssl` +Set to true to enable ssl. Default: <> +*Important*: You need to have ssl_key and ssl_ca set as well and files +need to pre-exist on node. + +#####`ssl_key` +Default: <> + +#####`ssl_ca` +Default: <> + +#####`service_manage` +Whether or not the MongoDB service resource should be part of the catalog. +Default: true + +#####`storage_engine` +Only needed for MongoDB 3.x versions, where it's possible to select the +'wiredTiger' engine in addition to the default 'mmapv1' engine. If not set, the +config is left out and mongo will default to 'mmapv1'. +You should not set this for MongoDB versions < 3.x + +#####`restart` +Specifies whether the service should be restarted on config changes. Default: 'true' + +#####`create_admin` +Allows to create admin user for admin database. +Redefine these parameters if needed: + +#####`admin_username` +Administrator user name + +#####`admin_password` +Administrator user password + +#####`admin_roles` +Administrator user roles + +#####`store_creds` +Store admin credentials in mongorc.js file. Uses with `create_admin` parameter + + +####Class: mongodb::mongos +class. This class should only be used if you want to implement sharding within +your mongodb deployment. + +This class allows you to configure the mongos daemon (responsible for routing) +on your platform. + +#####`ensure` +Used to ensure that the package is installed and the service is running, or that the package is absent/purged and the service is stopped. Valid values are true/false/present/absent/purged. + +#####`config` +Path of the config file. If not specified, the module will use the default +for your OS distro. + +#####`config_content` +Path to the config template if the default doesn't match one needs. + +#####`configdb` +Array of the config servers IP addresses the mongos should connect to. + +#####`service_manage` +Whether or not the MongoDB sharding service resource should be part of the catalog. +Default: true + +#####`service_name` +This setting can be used to override the default Mongos service name. If not +specified, the module will use whatever service name is the default for your OS distro. + +#####`service_provider` +This setting can be used to override the default Mongos service provider. If +not specified, the module will use whatever service provider is the default for +your OS distro. + +#####`service_status` +This setting can be used to override the default status check command for +your Mongos service. If not specified, the module will use whatever service +name is the default for your OS distro. + +#####`service_enable` +This setting can be used to specify if the service should be enable at boot + +#####`service_ensure` +This setting can be used to specify if the service should be running + +#####`package_ensure` +This setting can be used to specify if puppet should install the package or not + +#####`package_name` +This setting can be used to specify the name of the package that should be installed. +If not specified, the module will use whatever service name is the default for your OS distro. + +#####`restart` +Specifies whether the service should be restarted on config changes. Default: 'true' + ### Definitions #### Definition: mongodb:db @@ -409,8 +607,12 @@ The maximum amount of two second tries to wait MongoDB startup. Default: 10 #### Provider: mongodb_user 'mongodb_user' can be used to create and manage users within MongoDB database. +*Note:* if replica set is enabled, replica initialization has to come before +any user operations. + ```puppet mongodb_user { testuser: + name => 'testuser', ensure => present, password_hash => mongodb_password('testuser', 'p@ssw0rd'), database => testdb, @@ -419,6 +621,9 @@ mongodb_user { testuser: require => Class['mongodb::server'], } ``` +#####`username` +Name of the mongodb user. + #####`password_hash` Hex encoded md5 hash of "$username:mongo:$password". @@ -452,7 +657,29 @@ Array of 'host:port' of the replicaset members. It currently only adds members without options. -## Limitation +#### Provider: mongodb_shard +'mongodb_shard' can be used to create and manage MongoDB shards. +*Note:* Removing a shard is not yet supported. Shard can only be added. + +```puppet +mongodb_shard { 'rsmain': + member => 'rsmain/host1:27017', + keys => [{'rsmain.foo' => {'name' => 1}}], +} +``` +#####`member` +Member of the shard in the form; + +* [hostname] +* [hostname]:[port] +* [replica-set-name]/[hostname] +* [replica-set-name]/[hostname]:port + +#####`keys` +Sharding keys for a specific database. This variable should be an array +of sharding keys. + +## Limitations This module has been tested on: @@ -460,13 +687,17 @@ This module has been tested on: * Debian 6.* (squeeze) * Ubuntu 12.04.2 (precise) * Ubuntu 10.04.4 LTS (lucid) -* RHEL 5/6 -* CentOS 5/6 +* RHEL 5/6/7 +* CentOS 5/6/7 For a full list of tested operating systems please have a look at the [.nodeset.xml](https://github.com/puppetlabs/puppetlabs-mongodb/blob/master/.nodeset.yml) definition. This module should support `service_ensure` separate from the `ensure` value on `Class[mongodb::server]` but it does not yet. +### Apt module support + +While this module supports both 1.x and 2.x versions of the puppetlabs-apt module, it does not support puppetlabs-apt 2.0.0 or 2.0.1. + ## Development Puppet Labs modules on the Puppet Forge are open projects, and community diff --git a/puphpet/puppet/modules/mongodb/Rakefile b/puphpet/puppet/modules/mongodb/Rakefile index cd3d379..181157e 100644 --- a/puphpet/puppet/modules/mongodb/Rakefile +++ b/puphpet/puppet/modules/mongodb/Rakefile @@ -1 +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"] diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb.rb b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb.rb new file mode 100644 index 0000000..6bbc350 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb.rb @@ -0,0 +1,168 @@ +require 'yaml' +require 'json' +class Puppet::Provider::Mongodb < Puppet::Provider + + # Without initvars commands won't work. + initvars + commands :mongo => 'mongo' + + # Optional defaults file + def self.mongorc_file + if File.file?("#{Facter.value(:root_home)}/.mongorc.js") + "load('#{Facter.value(:root_home)}/.mongorc.js'); " + else + nil + end + end + + def mongorc_file + self.class.mongorc_file + end + + def self.get_mongod_conf_file + if File.exists? '/etc/mongod.conf' + file = '/etc/mongod.conf' + else + file = '/etc/mongodb.conf' + end + file + end + + def self.get_conn_string + file = get_mongod_conf_file + # The mongo conf is probably a key-value store, even though 2.6 is + # supposed to use YAML, because the config template is applied + # based on $::mongodb::globals::version which is the user will not + # necessarily set. This attempts to get the port from both types of + # config files. + config = YAML.load_file(file) + if config.kind_of?(Hash) # Using a valid YAML file for mongo 2.6 + bindip = config['net.bindIp'] + port = config['net.port'] + shardsvr = config['sharding.clusterRole'] + confsvr = config['sharding.clusterRole'] + else # It has to be a key-value config file + config = {} + File.readlines(file).collect do |line| + k,v = line.split('=') + config[k.rstrip] = v.lstrip.chomp if k and v + end + bindip = config['bind_ip'] + port = config['port'] + shardsvr = config['shardsvr'] + confsvr = config['confsvr'] + end + + if bindip + first_ip_in_list = bindip.split(',').first + if first_ip_in_list.eql? '0.0.0.0' + ip_real = '127.0.0.1' + else + ip_real = first_ip_in_list + end + end + + if port + port_real = port + elsif !port and (confsvr.eql? 'configsvr' or confsvr.eql? 'true') + port_real = 27019 + elsif !port and (shardsvr.eql? 'shardsvr' or shardsvr.eql? 'true') + port_real = 27018 + else + port_real = 27017 + end + + "#{ip_real}:#{port_real}" + end + + def self.db_ismaster + cmd_ismaster = 'printjson(db.isMaster())' + if mongorc_file + cmd_ismaster = mongorc_file + cmd_ismaster + end + out = mongo(['admin', '--quiet', '--host', get_conn_string, '--eval', cmd_ismaster]) + out.gsub!(/ObjectId\(([^)]*)\)/, '\1') + out.gsub!(/ISODate\((.+?)\)/, '\1 ') + out.gsub!(/^Error\:.+/, '') + res = JSON.parse out + + return res['ismaster'] + end + + def db_ismaster + self.class.db_ismaster + end + + def self.auth_enabled + auth_enabled = false + file = get_mongod_conf_file + config = YAML.load_file(file) + if config.kind_of?(Hash) + auth_enabled = config['security.authorization'] + else # It has to be a key-value store + config = {} + File.readlines(file).collect do |line| + k,v = line.split('=') + config[k.rstrip] = v.lstrip.chomp if k and v + end + auth_enabled = config['auth'] + end + return auth_enabled + end + + # Mongo Command Wrapper + def self.mongo_eval(cmd, db = 'admin', retries = 10, host = nil) + retry_count = retries + retry_sleep = 3 + if mongorc_file + cmd = mongorc_file + cmd + end + + out = nil + retry_count.times do |n| + begin + if host + out = mongo([db, '--quiet', '--host', host, '--eval', cmd]) + else + out = mongo([db, '--quiet', '--host', get_conn_string, '--eval', cmd]) + end + rescue => e + Puppet.debug "Request failed: '#{e.message}' Retry: '#{n}'" + sleep retry_sleep + next + end + break + end + + if !out + raise Puppet::ExecutionFailure, "Could not evalute MongoDB shell command: #{cmd}" + end + + out.gsub!(/ObjectId\(([^)]*)\)/, '\1') + out.gsub!(/^Error\:.+/, '') + out + end + + def mongo_eval(cmd, db = 'admin', retries = 10, host = nil) + self.class.mongo_eval(cmd, db, retries, host) + end + + # Mongo Version checker + def self.mongo_version + @@mongo_version ||= self.mongo_eval('db.version()') + end + + def mongo_version + self.class.mongo_version + end + + def self.mongo_24? + v = self.mongo_version + ! v[/^2\.4\./].nil? + end + + def mongo_24? + self.class.mongo_24? + end + +end diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_conn_validator/tcp_port.rb b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_conn_validator/tcp_port.rb new file mode 100644 index 0000000..e220ae5 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_conn_validator/tcp_port.rb @@ -0,0 +1,53 @@ +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__),"..","..","..")) +require 'puppet/util/mongodb_validator' + +# This file contains a provider for the resource type `mongodb_conn_validator`, +# which validates the mongodb connection by attempting an https connection. + +Puppet::Type.type(:mongodb_conn_validator).provide(:tcp_port) do + desc "A provider for the resource type `mongodb_conn_validator`, + which validates the mongodb connection by attempting an https + connection to the mongodb server. Uses the puppet SSL certificate + setup from the local puppet environment to authenticate." + + 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 mongodb server to start up; + # especially on the first install. Therefore, our first connection attempt + # may fail. Here we have somewhat arbitrarily chosen to retry every 4 + # seconds until the configurable timeout has expired. + Puppet.debug("Failed to connect to mongodb; sleeping 4 seconds before retry") + sleep 4 + success = validator.attempt_connection + end + + if success + Puppet.debug("Connected to mongodb in #{Time.now - start_time} seconds.") + else + Puppet.notice("Failed to connect to mongodb 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 mongodb server! (#{@validator.mongodb_server}:#{@validator.mongodb_port})" + end + + private + + # @api private + def validator + @validator ||= Puppet::Util::MongodbValidator.new(resource[:name], resource[:server], resource[:port]) + end + +end + diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_database/mongodb.rb b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_database/mongodb.rb index 0acc769..895276b 100644 --- a/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_database/mongodb.rb +++ b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_database/mongodb.rb @@ -1,36 +1,48 @@ -Puppet::Type.type(:mongodb_database).provide(:mongodb) do +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mongodb')) +Puppet::Type.type(:mongodb_database).provide(:mongodb, :parent => Puppet::Provider::Mongodb) do desc "Manages MongoDB database." defaultfor :kernel => 'Linux' - commands :mongo => 'mongo' - - def block_until_mongodb(tries = 10) - begin - mongo('--quiet', '--eval', 'db.getMongo()') - rescue => e - debug('MongoDB server not ready, retrying') - sleep 2 - if (tries -= 1) > 0 - retry - else - raise e + def self.instances + require 'json' + dbs = JSON.parse mongo_eval('printjson(db.getMongo().getDBs())') + + dbs['databases'].collect do |db| + new(:name => db['name'], + :ensure => :present) + end + end + + # Assign prefetched dbs based on name. + def self.prefetch(resources) + dbs = instances + resources.keys.each do |name| + if provider = dbs.find { |db| db.name == name } + resources[name].provider = provider end end end def create - mongo(@resource[:name], '--quiet', '--eval', "db.dummyData.insert({\"created_by_puppet\": 1})") + if db_ismaster + mongo_eval('db.dummyData.insert({"created_by_puppet": 1})', @resource[:name]) + else + Puppet.warning 'Database creation is available only from master host' + end end def destroy - mongo(@resource[:name], '--quiet', '--eval', 'db.dropDatabase()') + if db_ismaster + mongo_eval('db.dropDatabase()', @resource[:name]) + else + Puppet.warning 'Database removal is available only from master host' + end end def exists? - block_until_mongodb(@resource[:tries]) - mongo("--quiet", "--eval", 'db.getMongo().getDBNames()').split(",").include?(@resource[:name]) + !(@property_hash[:ensure] == :absent or @property_hash[:ensure].nil?) end end diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_replset/mongo.rb b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_replset/mongo.rb index d77afe3..035849e 100644 --- a/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_replset/mongo.rb +++ b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_replset/mongo.rb @@ -2,7 +2,8 @@ # Author: François Charlier # -Puppet::Type.type(:mongodb_replset).provide(:mongo) do +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mongodb')) +Puppet::Type.type(:mongodb_replset).provide(:mongo, :parent => Puppet::Provider::Mongodb) do desc "Manage hosts members for a replicaset." @@ -14,8 +15,6 @@ false end - commands :mongo => 'mongo' - mk_resource_methods def initialize(resource={}) @@ -66,23 +65,43 @@ def flush private def db_ismaster(host) - mongo_command("db.isMaster()", host) + mongo_command('db.isMaster()', host) end def rs_initiate(conf, master) - return mongo_command("rs.initiate(#{conf})", master) + if auth_enabled + return mongo_command("rs.initiate(#{conf})", initialize_host) + else + return mongo_command("rs.initiate(#{conf})", master) + end end def rs_status(host) - mongo_command("rs.status()", host) + mongo_command('rs.status()', host) end def rs_add(host, master) - mongo_command("rs.add(\"#{host}\")", master) + mongo_command("rs.add('#{host}')", master) end def rs_remove(host, master) - mongo_command("rs.remove(\"#{host}\")", master) + mongo_command("rs.remove('#{host}')", master) + end + + def rs_arbiter + @resource[:arbiter] + end + + def rs_add_arbiter(host, master) + mongo_command("rs.addArb('#{host}')", master) + end + + def auth_enabled + self.class.auth_enabled + end + + def initialize_host + @resource[:initialize_host] end def master_host(hosts) @@ -96,7 +115,8 @@ def master_host(hosts) end def self.get_replset_properties - output = mongo_command('rs.conf()') + conn_string = get_conn_string + output = mongo_command('rs.conf()', conn_string) if output['members'] members = output['members'].collect do |val| val['host'] @@ -115,6 +135,7 @@ def self.get_replset_properties end def alive_members(hosts) + alive = [] hosts.select do |host| begin Puppet.debug "Checking replicaset member #{host} ..." @@ -122,24 +143,29 @@ def alive_members(hosts) if status.has_key?('errmsg') and status['errmsg'] == 'not running with --replSet' raise Puppet::Error, "Can't configure replicaset #{self.name}, host #{host} is not supposed to be part of a replicaset." end + + if auth_enabled and status.has_key?('errmsg') and (status['errmsg'].include? "unauthorized" or status['errmsg'].include? "not authorized") + Puppet.warning "Host #{host} is available, but you are unauthorized because of authentication is enabled: #{auth_enabled}" + alive.push(host) + end + if status.has_key?('set') if status['set'] != self.name raise Puppet::Error, "Can't configure replicaset #{self.name}, host #{host} is already part of another replicaset." end # This node is alive and supposed to be a member of our set - Puppet.debug "Host #{self.name} is available for replset #{status['set']}" - true + Puppet.debug "Host #{host} is available for replset #{status['set']}" + alive.push(host) elsif status.has_key?('info') - Puppet.debug "Host #{self.name} is alive but unconfigured: #{status['info']}" - true + Puppet.debug "Host #{host} is alive but unconfigured: #{status['info']}" + alive.push(host) end rescue Puppet::ExecutionFailure Puppet.warning "Can't connect to replicaset member #{host}." - - false end end + return alive end def set_members @@ -156,19 +182,23 @@ def set_members # Find the alive members so we don't try to add dead members to the replset alive_hosts = alive_members(@property_flush[:members]) dead_hosts = @property_flush[:members] - alive_hosts - raise Puppet::Error, "Can't connect to any member of replicaset #{self.name}." if alive_hosts.empty? Puppet.debug "Alive members: #{alive_hosts.inspect}" Puppet.debug "Dead members: #{dead_hosts.inspect}" unless dead_hosts.empty? + raise Puppet::Error, "Can't connect to any member of replicaset #{self.name}." if alive_hosts.empty? else alive_hosts = [] end - if @property_flush[:ensure] == :present and @property_hash[:ensure] != :present + if @property_flush[:ensure] == :present and @property_hash[:ensure] != :present and !master_host(alive_hosts) Puppet.debug "Initializing the replset #{self.name}" # Create a replset configuration hostconf = alive_hosts.each_with_index.map do |host,id| - "{ _id: #{id}, host: \"#{host}\" }" + arbiter_conf = "" + if rs_arbiter == host + arbiter_conf = ", arbiterOnly: \"true\"" + end + "{ _id: #{id}, host: \"#{host}\"#{arbiter_conf} }" end.join(',') conf = "{ _id: \"#{self.name}\", members: [ #{hostconf} ] }" @@ -177,13 +207,42 @@ def set_members if output['ok'] == 0 raise Puppet::Error, "rs.initiate() failed for replicaset #{self.name}: #{output['errmsg']}" end + + # Check that the replicaset has finished initialization + retry_limit = 10 + retry_sleep = 3 + + retry_limit.times do |n| + begin + if db_ismaster(alive_hosts[0])['ismaster'] + Puppet.debug 'Replica set initialization has successfully ended' + return + else + Puppet.debug "Wainting for replica initialization. Retry: #{n}" + sleep retry_sleep + next + end + end + end + raise Puppet::Error, "rs.initiate() failed for replicaset #{self.name}: host #{alive_hosts[0]} didn't become master" + else # Add members to an existing replset + Puppet.debug "Adding member to existing replset #{self.name}" if master = master_host(alive_hosts) - current_hosts = db_ismaster(master)['hosts'] + master_data = db_ismaster(master) + current_hosts = master_data['hosts'] + current_hosts = current_hosts + master_data['arbiters'] if master_data.has_key?('arbiters') + Puppet.debug "Current Hosts are: #{current_hosts.inspect}" newhosts = alive_hosts - current_hosts + Puppet.debug "New Hosts are: #{newhosts.inspect}" newhosts.each do |host| - output = rs_add(host, master) + output = {} + if rs_arbiter == host + output = rs_add_arbiter(host, master) + else + output = rs_add(host, master) + end if output['ok'] == 0 raise Puppet::Error, "rs.add() failed to add host to replicaset #{self.name}: #{output['errmsg']}" end @@ -195,28 +254,15 @@ def set_members end def mongo_command(command, host, retries=4) - self.class.mongo_command(command,host,retries) + self.class.mongo_command(command, host, retries) end def self.mongo_command(command, host=nil, retries=4) - # Allow waiting for mongod to become ready - # Wait for 2 seconds initially and double the delay at each retry - wait = 2 begin - args = Array.new - args << '--quiet' - args << ['--host',host] if host - args << ['--eval',"printjson(#{command})"] - output = mongo(args.flatten) + output = mongo_eval("printjson(#{command})", 'admin', retries, host) rescue Puppet::ExecutionFailure => e - if e =~ /Error: couldn't connect to server/ and wait <= 2**max_wait - info("Waiting #{wait} seconds for mongod to become available") - sleep wait - wait *= 2 - retry - else - raise - end + Puppet.debug "Got an exception: #{e}" + raise end # Dirty hack to remove JavaScript objects @@ -226,7 +272,9 @@ def self.mongo_command(command, host=nil, retries=4) #Hack to avoid non-json empty sets output = "{}" if output == "null\n" + # Parse the JSON output and return JSON.parse(output) + end end diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_shard/mongo.rb b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_shard/mongo.rb new file mode 100644 index 0000000..f745f00 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_shard/mongo.rb @@ -0,0 +1,236 @@ +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mongodb')) +Puppet::Type.type(:mongodb_shard).provide(:mongo, :parent => Puppet::Provider::Mongodb ) do + + desc "Manage mongodb sharding." + + confine :true => + begin + require 'json' + true + rescue LoadError + false + end + + mk_resource_methods + + commands :mongo => 'mongo' + + def initialize(value={}) + super(value) + @property_flush = {} + end + + def destroy + @property_flush[:ensure] = :absent + end + + def create + @property_flush[:ensure] = :present + @property_flush[:member] = resource.should(:member) + @property_flush[:keys] = resource.should(:keys) + end + + def sh_addshard member + return mongo_command("sh.addShard(\"#{member}\")", '127.0.0.1:27017') + end + + def sh_shardcollection shard_key + collection = shard_key.keys.first + keys = shard_key.values.first.collect do |key, value| + "\"#{key}\": #{value.to_s}" + end + + return mongo_command("sh.shardCollection(\"#{collection}\", {#{keys.join(',')}})", '127.0.0.1:27017') + end + + def sh_enablesharding member + return mongo_command("sh.enableSharding(\"#{member}\")", '127.0.0.1:27017') + end + + def self.prefetch(resources) + instances.each do |prov| + if resource = resources[prov.name] + resource.provider = prov + end + end + end + + def flush + set_member + @property_hash = self.class.get_shard_properties(resource[:name]) + end + + def set_member + if @property_flush[:ensure] == :absent + # a shard can't be removed easily at this time + return + end + + if @property_flush[:ensure] == :present and @property_hash[:ensure] != :present + Puppet.debug "Adding the shard #{self.name}" + output = sh_addshard(@property_flush[:member]) + if output['ok'] == 0 + raise Puppet::Error, "sh.addShard() failed for shard #{self.name}: #{output['errmsg']}" + end + output = sh_enablesharding(self.name) + if output['ok'] == 0 + raise Puppet::Error, "sh.enableSharding() failed for shard #{self.name}: #{output['errmsg']}" + end + if @property_flush[:keys] + @property_flush[:keys].each do |key| + output = sh_shardcollection(key) + if output['ok'] == 0 + raise Puppet::Error, "sh.shardCollection() failed for shard #{self.name}: #{output['errmsg']}" + end + end + end + end + end + + + def self.instances + instances = get_shards_properties.collect do |shard| + new (shard) + end + end + + def self.get_shard_collection_details obj, shard_name + collection_array = [] + obj.each do |database| + if database['_id'].eql? shard_name and ! database['shards'].nil? + collection_array = database['shards'].collect do |collection| + { collection.keys.first => collection.values.first['shardkey']} + end + end + end + collection_array + end + + def self.get_shard_properties shard + properties = {} + output = mongo_command('sh.status()') + output['shards'].each do |s| + if s['_id'] == shard + properties = { + :name => s['_id'], + :ensure => :present, + :member => s['host'], + :keys => get_shard_collection_details(output['databases'], s['_id']), + :provider => :mongo, + } + end + end + properties + end + + def self.get_shards_properties + output = mongo_command('sh.status()') + if output['shards'].size > 0 + properties = output['shards'].collect do |shard| + { + :name => shard['_id'], + :ensure => :present, + :member => shard['host'], + :keys => get_shard_collection_details(output['databases'], shard['_id']), + :provider => :mongo, + } + end + else + properties = [] + end + Puppet.debug("MongoDB shard properties: #{properties.inspect}") + properties + end + + def exists? + @property_hash[:ensure] == :present + end + + def mongo_command(command, host, retries=4) + self.class.mongo_command(command,host,retries) + end + + def self.mongo_command(command, host=nil, retries=4) + # Allow waiting for mongod to become ready + # Wait for 2 seconds initially and double the delay at each retry + wait = 2 + begin + args = Array.new + args << '--quiet' + args << ['--host',host] if host + args << ['--eval',"printjson(#{command})"] + output = mongo(args.flatten) + rescue Puppet::ExecutionFailure => e + if e =~ /Error: couldn't connect to server/ and wait <= 2**max_wait + info("Waiting #{wait} seconds for mongod to become available") + sleep wait + wait *= 2 + retry + else + raise + end + end + + # NOTE (spredzy) : sh.status() + # does not return a json stream + # we jsonify it so it is easier + # to parse and deal with it + if command == 'sh.status()' + myarr = output.split("\n") + myarr.shift + myarr.pop + myarr.pop + final_stream = [] + prev_line = nil + in_shard_list = 0 + in_chunk = 0 + myarr.each do |line| + line.gsub!(/sharding version:/, '{ "sharding version":') + line.gsub!(/shards:/, ',"shards":[') + line.gsub!(/databases:/, '], "databases":[') + line.gsub!(/"clusterId" : ObjectId\("(.*)"\)/, '"clusterId" : "ObjectId(\'\1\')"') + line.gsub!(/\{ "_id" :/, ",{ \"_id\" :") if /_id/ =~ prev_line + # Modification for shard + line = '' if line =~ /on :.*Timestamp/ + if line =~ /_id/ and in_shard_list == 1 + in_shard_list = 0 + last_line = final_stream.pop.strip + proper_line = "#{last_line}]}," + final_stream << proper_line + end + if line =~ /shard key/ and in_shard_list == 1 + shard_name = final_stream.pop.strip + proper_line = ",{\"#{shard_name}\":" + final_stream << proper_line + end + if line =~ /shard key/ and in_shard_list == 0 + in_shard_list = 1 + shard_name = final_stream.pop.strip + id_line = "#{final_stream.pop[0..-2]}, \"shards\": " + proper_line = "[{\"#{shard_name}\":" + final_stream << id_line + final_stream << proper_line + end + if in_chunk == 1 + in_chunk = 0 + line = "\"#{line.strip}\"}}" + end + if line =~ /chunks/ and in_chunk == 0 + in_chunk = 1 + end + line.gsub!(/shard key/, '{"shard key"') + line.gsub!(/chunks/, ',"chunks"') + final_stream << line if line.size > 0 + prev_line = line + end + final_stream << ' ] }' if in_shard_list == 1 + final_stream << ' ] }' + output = final_stream.join("\n") + end + + #Hack to avoid non-json empty sets + output = "{}" if output == "null\n" + output.gsub!(/\s*/, '') + JSON.parse(output) + end +end diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_user/mongodb.rb b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_user/mongodb.rb index 10e0bf7..e8c33dc 100644 --- a/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_user/mongodb.rb +++ b/puphpet/puppet/modules/mongodb/lib/puppet/provider/mongodb_user/mongodb.rb @@ -1,48 +1,160 @@ -Puppet::Type.type(:mongodb_user).provide(:mongodb) do +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mongodb')) +Puppet::Type.type(:mongodb_user).provide(:mongodb, :parent => Puppet::Provider::Mongodb) do desc "Manage users for a MongoDB database." defaultfor :kernel => 'Linux' - commands :mongo => 'mongo' + def self.instances + require 'json' - def block_until_mongodb(tries = 10) - begin - mongo('--quiet', '--eval', 'db.getMongo()') - rescue - debug('MongoDB server not ready, retrying') - sleep 2 - retry unless (tries -= 1) <= 0 + if db_ismaster + if mongo_24? + dbs = JSON.parse mongo_eval('printjson(db.getMongo().getDBs()["databases"].map(function(db){return db["name"]}))') || 'admin' + + allusers = [] + + dbs.each do |db| + users = JSON.parse mongo_eval('printjson(db.system.users.find().toArray())', db) + + allusers += users.collect do |user| + new(:name => user['_id'], + :ensure => :present, + :username => user['user'], + :database => db, + :roles => user['roles'].sort, + :password_hash => user['pwd']) + end + end + return allusers + else + users = JSON.parse mongo_eval('printjson(db.system.users.find().toArray())') + + users.collect do |user| + new(:name => user['_id'], + :ensure => :present, + :username => user['user'], + :database => user['db'], + :roles => from_roles(user['roles'], user['db']), + :password_hash => user['credentials']['MONGODB-CR']) + end + end + else + Puppet.warning 'User info is available only from master host' + return [] end end + # Assign prefetched users based on username and database, not on id and name + def self.prefetch(resources) + users = instances + resources.each do |name, resource| + if provider = users.find { |user| user.username == resource[:username] and user.database == resource[:database] } + resources[name].provider = provider + end + end + end + + mk_resource_methods + def create - mongo(@resource[:database], '--eval', "db.system.users.insert({user:\"#{@resource[:name]}\", pwd:\"#{@resource[:password_hash]}\", roles: #{@resource[:roles].inspect}})") + if db_ismaster + if mongo_24? + user = { + :user => @resource[:username], + :pwd => @resource[:password_hash], + :roles => @resource[:roles] + } + + mongo_eval("db.addUser(#{user.to_json})", @resource[:database]) + else + cmd_json=<<-EOS.gsub(/^\s*/, '').gsub(/$\n/, '') + { + "createUser": "#{@resource[:username]}", + "pwd": "#{@resource[:password_hash]}", + "customData": {"createdBy": "Puppet Mongodb_user['#{@resource[:name]}']"}, + "roles": #{@resource[:roles].to_json}, + "digestPassword": false + } + EOS + + mongo_eval("db.runCommand(#{cmd_json})", @resource[:database]) + end + + @property_hash[:ensure] = :present + @property_hash[:username] = @resource[:username] + @property_hash[:database] = @resource[:database] + @property_hash[:password_hash] = '' + @property_hash[:roles] = @resource[:roles] + + exists? ? (return true) : (return false) + else + Puppet.warning 'User creation is available only from master host' + end end + def destroy - mongo(@resource[:database], '--quiet', '--eval', "db.removeUser(\"#{@resource[:name]}\")") + if db_ismaster + if mongo_24? + mongo_eval("db.removeUser('#{@resource[:username]}')") + else + mongo_eval("db.dropUser('#{@resource[:username]}')") + end + else + mongo_eval("db.dropUser('#{@resource[:username]}')") + end end def exists? - block_until_mongodb(@resource[:tries]) - mongo(@resource[:database], '--quiet', '--eval', "db.system.users.find({user:\"#{@resource[:name]}\"}).count()").strip.eql?('1') - end - - def password_hash - mongo(@resource[:database], '--quiet', '--eval', "db.system.users.findOne({user:\"#{@resource[:name]}\"})[\"pwd\"]").strip + !(@property_hash[:ensure] == :absent or @property_hash[:ensure].nil?) end def password_hash=(value) - mongo(@resource[:database], '--quiet', '--eval', "db.system.users.update({user:\"#{@resource[:name]}\"}, { $set: {pwd:\"#{value}\"}})") + if db_ismaster + cmd_json=<<-EOS.gsub(/^\s*/, '').gsub(/$\n/, '') + { + "updateUser": "#{@resource[:username]}", + "pwd": "#{@resource[:password_hash]}", + "digestPassword": false + } + EOS + mongo_eval("db.runCommand(#{cmd_json})", @resource[:database]) + else + Puppet.warning 'User password operations are available only from master host' + end end - def roles - mongo(@resource[:database], '--quiet', '--eval', "db.system.users.findOne({user:\"#{@resource[:name]}\"})[\"roles\"]").strip.split(",").sort + def roles=(roles) + if db_ismaster + if mongo_24? + mongo_eval("db.system.users.update({user:'#{@resource[:username]}'}, { $set: {roles: #{@resource[:roles].to_json}}})") + else + grant = roles-@property_hash[:roles] + if grant.length > 0 + mongo_eval("db.getSiblingDB('#{@resource[:database]}').grantRolesToUser('#{@resource[:username]}', #{grant. to_json})") + end + + revoke = @property_hash[:roles]-roles + if revoke.length > 0 + mongo_eval("db.getSiblingDB('#{@resource[:database]}').revokeRolesFromUser('#{@resource[:username]}', #{revoke.to_json})") + end + end + else + Puppet.warning 'User roles operations are available only from master host' + end end - def roles=(value) - mongo(@resource[:database], '--quiet', '--eval', "db.system.users.update({user:\"#{@resource[:name]}\"}, { $set: {roles: #{@resource[:roles].inspect}}})") + private + + def self.from_roles(roles, db) + roles.map do |entry| + if entry['db'] == db + entry['role'] + else + "#{entry['role']}@#{entry['db']}" + end + end.sort end end diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_conn_validator.rb b/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_conn_validator.rb new file mode 100644 index 0000000..9158ef3 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_conn_validator.rb @@ -0,0 +1,45 @@ +Puppet::Type.newtype(:mongodb_conn_validator) do + + @doc = "Verify that a connection can be successfully established between a node + and the mongodb server. Its primary use is as a precondition to + prevent configuration changes from being applied if the mongodb + server cannot be reached, but 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. It can also be the connection string to test (ie. 127.0.0.1:27017)' + end + + newparam(:server) do + desc 'An array containing DNS names or IP addresses of the server where mongodb should be running.' + defaultto '127.0.0.1' + munge do |value| + Array(value).first + end + end + + newparam(:port) do + desc 'The port that the mongodb server should be listening on.' + defaultto '27017' + end + + newparam(:timeout) do + desc 'The max number of seconds that the validator should wait before giving up and deciding that puppetdb 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 diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_database.rb b/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_database.rb index 45c0f8f..8be5f2e 100644 --- a/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_database.rb +++ b/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_database.rb @@ -18,7 +18,7 @@ end autorequire(:package) do - 'mongodb' + 'mongodb_client' end autorequire(:service) do diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_replset.rb b/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_replset.rb index 8115ef0..3717b24 100644 --- a/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_replset.rb +++ b/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_replset.rb @@ -17,6 +17,15 @@ desc "The name of the replicaSet" end + newparam(:arbiter) do + desc "The replicaSet arbiter" + end + + newparam(:initialize_host) do + desc "Host to use for Replicaset initialization" + defaultto '127.0.0.1' + end + newproperty(:members, :array_matching => :all) do desc "The replicaSet members" @@ -26,7 +35,7 @@ def insync?(is) end autorequire(:package) do - 'mongodb' + 'mongodb_client' end autorequire(:service) do diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_shard.rb b/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_shard.rb new file mode 100644 index 0000000..b903a84 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_shard.rb @@ -0,0 +1,39 @@ +# +# Author: Emilien Macchi +# + +Puppet::Type.newtype(:mongodb_shard) do + @doc = "Manage a MongoDB Shard" + + ensurable do + defaultto :present + + newvalue(:present) do + provider.create + end + end + + newparam(:name) do + desc "The name of the shard" + end + + newproperty(:member) do + desc "The shard member" + end + + newproperty(:keys, :array_matching => :all) do + desc "The sharding keys" + + def insync?(is) + is.sort == should.sort + end + end + + autorequire(:package) do + 'mongodb_client' + end + + autorequire(:service) do + 'mongodb' + end +end diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_user.rb b/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_user.rb index 7f7e97b..aee39ef 100644 --- a/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_user.rb +++ b/puphpet/puppet/modules/mongodb/lib/puppet/type/mongodb_user.rb @@ -10,13 +10,18 @@ def initialize(*args) end newparam(:name, :namevar=>true) do + desc "The name of the resource." + end + + newproperty(:username) do desc "The name of the user." + defaultto { @resource[:name] } end - newparam(:database) do + newproperty(:database) do desc "The user's target database." defaultto do - fail("Parameter 'database' must be set") + fail("Parameter 'database' must be set") if provider.database == :absent end newvalues(/^\w+$/) end @@ -48,13 +53,13 @@ def is_to_s(value) newproperty(:password_hash) do desc "The password hash of the user. Use mongodb_password() for creating hash." defaultto do - fail("Property 'password_hash' must be set. Use mongodb_password() for creating hash.") + fail("Property 'password_hash' must be set. Use mongodb_password() for creating hash.") if provider.database == :absent end newvalue(/^\w+$/) end autorequire(:package) do - 'mongodb' + 'mongodb_client' end autorequire(:service) do diff --git a/puphpet/puppet/modules/mongodb/lib/puppet/util/mongodb_validator.rb b/puphpet/puppet/modules/mongodb/lib/puppet/util/mongodb_validator.rb new file mode 100644 index 0000000..58fe942 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/lib/puppet/util/mongodb_validator.rb @@ -0,0 +1,49 @@ +require 'socket' +require 'timeout' +require 'ipaddr' +require 'uri' + +module Puppet + module Util + class MongodbValidator + attr_reader :mongodb_server + attr_reader :mongodb_port + + def initialize(mongodb_resource_name, mongodb_server, mongodb_port) + begin + # NOTE (spredzy) : By relying on the uri module + # we rely on its well tested interface to parse + # both IPv4 and IPv6 based URL with a port specified. + # Unfortunately URI needs a scheme, hence the http + # string here to make the string URI compliant. + uri = URI("http://#{mongodb_resource_name}") + @mongodb_server = IPAddr.new(uri.host).to_s + @mongodb_port = uri.port + rescue + @mongodb_server = IPAddr.new(mongodb_server).to_s + @mongodb_port = mongodb_port + end + end + + # Utility method; attempts to make an https connection to the mongodb server. + # 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(@mongodb_server, @mongodb_port).close + true + rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e + Puppet.debug "Unable to connect to mongodb server (#{@mongodb_server}:#{@mongodb_port}): #{e.message}" + false + end + end + rescue Timeout::Error + false + end + end + end +end + diff --git a/puphpet/puppet/modules/mongodb/manifests/client.pp b/puphpet/puppet/modules/mongodb/manifests/client.pp index de1b339..63a800c 100644 --- a/puphpet/puppet/modules/mongodb/manifests/client.pp +++ b/puphpet/puppet/modules/mongodb/manifests/client.pp @@ -9,18 +9,10 @@ # is repository dependent. # class mongodb::client ( - $ensure = $mongodb::params::ensure_client, + $ensure = $mongodb::params::package_ensure_client, $package_name = $mongodb::params::client_package_name, ) inherits mongodb::params { - case $::osfamily { - 'RedHat', 'Linux': { - class { 'mongodb::client::install': } - } - 'Debian': { - warning ('Debian client is included by default with server. Please use ::mongodb::server to install the mongo client for Debian family systems.') - } - default: { - # no action taken, failure happens in params.pp - } - } + anchor { '::mongodb::client::start': } -> + class { '::mongodb::client::install': } -> + anchor { '::mongodb::client::end': } } diff --git a/puphpet/puppet/modules/mongodb/manifests/client/install.pp b/puphpet/puppet/modules/mongodb/manifests/client/install.pp index 6da2600..f63efc1 100644 --- a/puphpet/puppet/modules/mongodb/manifests/client/install.pp +++ b/puphpet/puppet/modules/mongodb/manifests/client/install.pp @@ -18,9 +18,11 @@ } } - package { 'mongodb_client': - ensure => $my_package_ensure, - name => $package_name, - tag => 'mongodb', + if $package_name { + package { 'mongodb_client': + ensure => $my_package_ensure, + name => $package_name, + tag => 'mongodb', + } } } diff --git a/puphpet/puppet/modules/mongodb/manifests/db.pp b/puphpet/puppet/modules/mongodb/manifests/db.pp index 708f5d7..3cc3eed 100644 --- a/puphpet/puppet/modules/mongodb/manifests/db.pp +++ b/puphpet/puppet/modules/mongodb/manifests/db.pp @@ -19,9 +19,8 @@ ) { mongodb_database { $name: - ensure => present, - tries => $tries, - require => Class['mongodb::server'], + ensure => present, + tries => $tries } if $password_hash { @@ -32,9 +31,10 @@ fail("Parameter 'password_hash' or 'password' should be provided to mongodb::db.") } - mongodb_user { $user: + mongodb_user { "User ${user} on db ${name}": ensure => present, password_hash => $hash, + username => $user, database => $name, roles => $roles, require => Mongodb_database[$name], diff --git a/puphpet/puppet/modules/mongodb/manifests/globals.pp b/puphpet/puppet/modules/mongodb/manifests/globals.pp index fb04df6..85f418b 100644 --- a/puphpet/puppet/modules/mongodb/manifests/globals.pp +++ b/puphpet/puppet/modules/mongodb/manifests/globals.pp @@ -2,26 +2,47 @@ # details. class mongodb::globals ( - $server_package_name = undef, - $client_package_name = undef, + $server_package_name = undef, + $client_package_name = undef, + $mongos_package_name = undef, - $service_name = undef, - $service_provider = undef, - $service_status = undef, + $mongod_service_manage = undef, + $service_enable = undef, + $service_ensure = undef, + $service_name = undef, + $mongos_service_manage = undef, + $mongos_service_enable = undef, + $mongos_service_ensure = undef, + $mongos_service_status = undef, + $mongos_service_name = undef, + $service_provider = undef, + $service_status = undef, - $user = undef, - $group = undef, - $bind_ip = undef, + $user = undef, + $group = undef, + $ipv6 = undef, + $bind_ip = undef, - $version = undef, + $version = undef, - $manage_package_repo = undef, + $manage_package_repo = undef, + $manage_package = undef, + $repo_proxy = undef, + $proxy_username = undef, + $proxy_password = undef, + + $repo_location = undef, + $use_enterprise_repo = undef, + + $pidfilepath = undef, ) { # Setup of the repo only makes sense globally, so we are doing it here. if($manage_package_repo) { class { '::mongodb::repo': - ensure => present, + ensure => present, + repo_location => $repo_location, + proxy => $repo_proxy, } } } diff --git a/puphpet/puppet/modules/mongodb/manifests/init.pp b/puphpet/puppet/modules/mongodb/manifests/init.pp index d489731..3b80594 100644 --- a/puphpet/puppet/modules/mongodb/manifests/init.pp +++ b/puphpet/puppet/modules/mongodb/manifests/init.pp @@ -38,7 +38,6 @@ $enable_10gen = undef, $init = $mongodb::params::service_provider, - $location = '', $packagename = undef, $version = undef, $servicename = $mongodb::params::service_name, @@ -46,7 +45,7 @@ $logpath = $mongodb::params::logpath, $logappend = true, $fork = $mongodb::params::fork, - $port = 27017, + $port = undef, $dbpath = $mongodb::params::dbpath, $journal = undef, $nojournal = undef, @@ -72,10 +71,15 @@ $only = undef, $master = undef, $source = undef, + $configsvr = undef, + $shardsvr = undef, $replset = undef, $rest = undef, + $quiet = undef, $slowms = undef, $keyfile = undef, + $key = undef, + $ipv6 = undef, $bind_ip = undef, $pidfilepath = undef ) inherits mongodb::params { @@ -96,7 +100,7 @@ settings to mongodb::server. Please verify this works in a safe test environment.': } - class { 'mongodb::server': + class { '::mongodb::server': package_name => $packagename, logpath => $logpath, logappend => $logappend, @@ -125,10 +129,15 @@ only => $only, master => $master, source => $source, + configsvr => $configsvr, + shardsvr => $shardsvr, replset => $replset, rest => $rest, + quiet => $quiet, slowms => $slowms, keyfile => $keyfile, + key => $key, + ipv6 => $ipv6, bind_ip => $bind_ip, pidfilepath => $pidfilepath, } diff --git a/puphpet/puppet/modules/mongodb/manifests/mongos.pp b/puphpet/puppet/modules/mongodb/manifests/mongos.pp new file mode 100644 index 0000000..d5aa62d --- /dev/null +++ b/puphpet/puppet/modules/mongodb/manifests/mongos.pp @@ -0,0 +1,48 @@ +# This installs a Mongo Shard daemon. See README.md for more details. +class mongodb::mongos ( + $ensure = $mongodb::params::mongos_ensure, + $config = $mongodb::params::mongos_config, + $config_content = undef, + $configdb = $mongodb::params::mongos_configdb, + $service_manage = $mongodb::params::mongos_service_manage, + $service_provider = $mongodb::params::mongos_service_provider, + $service_name = $mongodb::params::mongos_service_name, + $service_enable = $mongodb::params::mongos_service_enable, + $service_ensure = $mongodb::params::mongos_service_ensure, + $service_status = $mongodb::params::mongos_service_status, + $package_ensure = $mongodb::params::package_ensure_mongos, + $package_name = $mongodb::params::mongos_package_name, + $unixsocketprefix = $mongodb::params::mongos_unixsocketprefix, + $pidfilepath = $mongodb::params::mongos_pidfilepath, + $logpath = $mongodb::params::mongos_logpath, + $fork = $mongodb::params::mongos_fork, + $bind_ip = undef, + $port = undef, + $restart = $mongodb::params::mongos_restart, +) inherits mongodb::params { + + if ($ensure == 'present' or $ensure == true) { + if $restart { + anchor { 'mongodb::mongos::start': }-> + class { 'mongodb::mongos::install': }-> + # If $restart is true, notify the service on config changes (~>) + class { 'mongodb::mongos::config': }~> + class { 'mongodb::mongos::service': }-> + anchor { 'mongodb::mongos::end': } + } else { + anchor { 'mongodb::mongos::start': }-> + class { 'mongodb::mongos::install': }-> + # If $restart is false, config changes won't restart the service (->) + class { 'mongodb::mongos::config': }-> + class { 'mongodb::mongos::service': }-> + anchor { 'mongodb::mongos::end': } + } + } else { + anchor { 'mongodb::mongos::start': }-> + class { '::mongodb::mongos::service': }-> + class { '::mongodb::mongos::config': }-> + class { '::mongodb::mongos::install': }-> + anchor { 'mongodb::mongos::end': } + } + +} diff --git a/puphpet/puppet/modules/mongodb/manifests/mongos/config.pp b/puphpet/puppet/modules/mongodb/manifests/mongos/config.pp new file mode 100644 index 0000000..1b9bc23 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/manifests/mongos/config.pp @@ -0,0 +1,27 @@ +# PRIVATE CLASS: do not call directly +class mongodb::mongos::config ( + $ensure = $mongodb::mongos::ensure, + $config = $mongodb::mongos::config, + $config_content = $mongodb::mongos::config_content, + $configdb = $mongodb::mongos::configdb, +) { + + if ($ensure == 'present' or $ensure == true) { + + #Pick which config content to use + if $config_content { + $config_content_real = $config_content + } else { + $config_content_real = template('mongodb/mongodb-shard.conf.erb') + } + + file { $config: + content => $config_content_real, + owner => 'root', + group => 'root', + mode => '0644', + } + + } + +} diff --git a/puphpet/puppet/modules/mongodb/manifests/mongos/install.pp b/puphpet/puppet/modules/mongodb/manifests/mongos/install.pp new file mode 100644 index 0000000..e9285af --- /dev/null +++ b/puphpet/puppet/modules/mongodb/manifests/mongos/install.pp @@ -0,0 +1,32 @@ +# PRIVATE CLASS: do not call directly +class mongodb::mongos::install ( + $package_ensure = $mongodb::mongos::package_ensure, + $package_name = $mongodb::mongos::package_name, +) { + + case $package_ensure { + true: { + $my_package_ensure = 'present' + } + false: { + $my_package_ensure = 'absent' + } + 'absent': { + $my_package_ensure = 'absent' + } + 'purged': { + $my_package_ensure = 'purged' + } + default: { + $my_package_ensure = $package_ensure + } + } + + if !defined(Package[$package_name]) { + package { 'mongodb_mongos': + ensure => $my_package_ensure, + name => $package_name, + } + } + +} diff --git a/puphpet/puppet/modules/mongodb/manifests/mongos/service.pp b/puphpet/puppet/modules/mongodb/manifests/mongos/service.pp new file mode 100644 index 0000000..552fcaf --- /dev/null +++ b/puphpet/puppet/modules/mongodb/manifests/mongos/service.pp @@ -0,0 +1,72 @@ +# PRIVATE CLASS: do not call directly +class mongodb::mongos::service ( + $service_manage = $mongodb::mongos::service_manage, + $service_name = $mongodb::mongos::service_name, + $service_enable = $mongodb::mongos::service_enable, + $service_ensure = $mongodb::mongos::service_ensure, + $service_status = $mongodb::mongos::service_status, + $service_provider = $mongodb::mongos::service_provider, + $bind_ip = $mongodb::mongos::bind_ip, + $port = $mongodb::mongos::port, +) { + + $service_ensure_real = $service_ensure ? { + 'absent' => false, + 'purged' => false, + 'stopped' => false, + default => true + } + + if $port { + $port_real = $port + } else { + $port_real = '27017' + } + + if $bind_ip == '0.0.0.0' { + $bind_ip_real = '127.0.0.1' + } else { + $bind_ip_real = $bind_ip + } + + if $::osfamily == 'RedHat' { + file { '/etc/sysconfig/mongos' : + ensure => file, + owner => 'root', + group => 'root', + mode => '0755', + content => 'OPTIONS="--quiet -f /etc/mongodb-shard.conf"', + before => Service['mongos'], + } + } + + file { '/etc/init.d/mongos' : + ensure => file, + content => template("mongodb/mongos/${::osfamily}/mongos.erb"), + owner => 'root', + group => 'root', + mode => '0755', + before => Service['mongos'], + } + + if $service_manage { + service { 'mongos': + ensure => $service_ensure_real, + name => $service_name, + enable => $service_enable, + provider => $service_provider, + hasstatus => true, + status => $service_status, + } + + if $service_ensure_real { + mongodb_conn_validator { 'mongos': + server => $bind_ip_real, + port => $port_real, + timeout => '240', + require => Service['mongos'], + } + } + } + +} diff --git a/puphpet/puppet/modules/mongodb/manifests/params.pp b/puphpet/puppet/modules/mongodb/manifests/params.pp index 5afc484..0926f39 100644 --- a/puphpet/puppet/modules/mongodb/manifests/params.pp +++ b/puphpet/puppet/modules/mongodb/manifests/params.pp @@ -1,80 +1,190 @@ # PRIVATE CLASS: do not use directly class mongodb::params inherits mongodb::globals { - $ensure = true - $service_status = $service_status - $ensure_client = true + $ensure = true + $mongos_ensure = true + $ipv6 = undef + $service_manage = pick($mongodb::globals::mongod_service_manage, true) + $service_enable = pick($mongodb::globals::service_enable, true) + $service_ensure = pick($mongodb::globals::service_ensure, 'running') + $service_status = $mongodb::globals::service_status + $restart = true + $create_admin = false + $admin_username = 'admin' + $store_creds = false + $rcfile = "${::root_home}/.mongorc.js" + + $mongos_service_manage = pick($mongodb::globals::mongos_service_manage, true) + $mongos_service_enable = pick($mongodb::globals::mongos_service_enable, true) + $mongos_service_ensure = pick($mongodb::globals::mongos_service_ensure, 'running') + $mongos_service_status = $mongodb::globals::mongos_service_status + $mongos_configdb = '127.0.0.1:27019' + $mongos_restart = true + + $manage_package = pick($mongodb::globals::manage_package, $mongodb::globals::manage_package_repo, false) # Amazon Linux's OS Family is 'Linux', operating system 'Amazon'. case $::osfamily { 'RedHat', 'Linux': { - if $mongodb::globals::manage_package_repo { - $user = pick($user, 'mongod') - $group = pick($group, 'mongod') - if $::mongodb::globals::version { - $server_package_name = "mongodb-org-server-${::mongodb::globals::version}" - $client_package_name = "mongodb-org-${::mongodb::globals::version}" + if $manage_package { + $user = pick($::mongodb::globals::user, 'mongod') + $group = pick($::mongodb::globals::group, 'mongod') + if ($::mongodb::globals::version == undef) { + $server_package_name = pick($::mongodb::globals::server_package_name, 'mongodb-org-server') + $client_package_name = pick($::mongodb::globals::client_package_name, 'mongodb-org-shell') + $mongos_package_name = pick($::mongodb::globals::mongos_package_name, 'mongodb-org-mongos') + $package_ensure = true + $package_ensure_client = true + $package_ensure_mongos = true } else { - $server_package_name = 'mongodb-org-server' - $client_package_name = 'mongodb-org' + # check if the version is greater than 2.6 + if(versioncmp($::mongodb::globals::version, '2.6.0') >= 0) { + $server_package_name = pick($::mongodb::globals::server_package_name, 'mongodb-org-server') + $client_package_name = pick($::mongodb::globals::client_package_name, 'mongodb-org-shell') + $mongos_package_name = pick($::mongodb::globals::mongos_package_name, 'mongodb-org-mongos') + $package_ensure = $::mongodb::globals::version + $package_ensure_client = $::mongodb::globals::version + $package_ensure_mongos = $::mongodb::globals::version + } else { + $server_package_name = pick($::mongodb::globals::server_package_name, 'mongodb-10gen') + $client_package_name = pick($::mongodb::globals::client_package_name, 'mongodb-10gen') + $mongos_package_name = pick($::mongodb::globals::mongos_package_name, 'mongodb-10gen') + $package_ensure = $::mongodb::globals::version + $package_ensure_client = $::mongodb::globals::version #this is still needed in case they are only installing the client + $package_ensure_mongos = $::mongodb::globals::version + } } - $service_name = pick($service_name, 'mongod') - $config = '/etc/mongod.conf' - $dbpath = '/var/lib/mongo' - $logpath = '/var/log/mongodb/mongod.log' - $pidfilepath = '/var/run/mongodb/mongod.pid' - $bind_ip = pick($bind_ip, ['127.0.0.1']) - $fork = true + $service_name = pick($::mongodb::globals::service_name, 'mongod') + $mongos_service_name = pick($::mongodb::globals::mongos_service_name, 'mongos') + $config = '/etc/mongod.conf' + $mongos_config = '/etc/mongodb-shard.conf' + $dbpath = '/var/lib/mongodb' + $logpath = '/var/log/mongodb/mongod.log' + $pidfilepath = '/var/run/mongodb/mongod.pid' + $bind_ip = pick($::mongodb::globals::bind_ip, ['127.0.0.1']) + $fork = true + $mongos_pidfilepath = undef + $mongos_unixsocketprefix = undef + $mongos_logpath = undef + $mongos_fork = undef } else { # RedHat/CentOS doesn't come with a prepacked mongodb # so we assume that you are using EPEL repository. - $user = pick($user, 'mongodb') - $group = pick($group, 'mongodb') - $server_package_name = pick($server_package_name, 'mongodb-server') - $client_package_name = pick($client_package_name, 'mongodb') - - $service_name = pick($service_name, 'mongod') - $config = '/etc/mongodb.conf' + if ($::mongodb::globals::version == undef) { + $package_ensure = true + $package_ensure_client = true + $package_ensure_mongos = true + } else { + $package_ensure = $::mongodb::globals::version + $package_ensure_client = $::mongodb::globals::version + $package_ensure_mongos = $::mongodb::globals::version + } + $user = pick($::mongodb::globals::user, 'mongodb') + $group = pick($::mongodb::globals::group, 'mongodb') + $server_package_name = pick($::mongodb::globals::server_package_name, 'mongodb-server') + $client_package_name = pick($::mongodb::globals::client_package_name, 'mongodb') + $mongos_package_name = pick($::mongodb::globals::mongos_package_name, 'mongodb-server') + $service_name = pick($::mongodb::globals::service_name, 'mongod') $dbpath = '/var/lib/mongodb' $logpath = '/var/log/mongodb/mongodb.log' - $bind_ip = pick($bind_ip, ['127.0.0.1']) - $pidfilepath = '/var/run/mongodb/mongodb.pid' + $bind_ip = pick($::mongodb::globals::bind_ip, ['127.0.0.1']) + if ($::operatingsystem == 'fedora' and versioncmp($::operatingsystemrelease, '22') >= 0 or + $::operatingsystem != 'fedora' and versioncmp($::operatingsystemrelease, '7.0') >= 0) { + $config = '/etc/mongod.conf' + $mongos_config = '/etc/mongos.conf' + $pidfilepath = '/var/run/mongodb/mongod.pid' + $mongos_pidfilepath = '/var/run/mongodb/mongos.pid' + $mongos_unixsocketprefix = '/var/run/mongodb' + $mongos_logpath = '/var/log/mongodb/mongodb-shard.log' + $mongos_fork = true + } else { + $config = '/etc/mongodb.conf' + $mongos_config = '/etc/mongodb-shard.conf' + $pidfilepath = '/var/run/mongodb/mongodb.pid' + $mongos_pidfilepath = undef + $mongos_unixsocketprefix = undef + $mongos_logpath = undef + $mongos_fork = undef + } $fork = true $journal = true } } 'Debian': { - if $mongodb::globals::manage_package_repo { - $user = pick($user, 'mongodb') - $group = pick($group, 'mongodb') - if $::mongodb::globals::version { - $server_package_name = "mongodb-10gen=${::mongodb::globals::version}" + if $manage_package { + $user = pick($::mongodb::globals::user, 'mongodb') + $group = pick($::mongodb::globals::group, 'mongodb') + if ($::mongodb::globals::version == undef) { + $server_package_name = pick($::mongodb::globals::server_package_name, 'mongodb-org-server') + $client_package_name = pick($::mongodb::globals::client_package_name, 'mongodb-org-shell') + $mongos_package_name = pick($::mongodb::globals::mongos_package_name, 'mongodb-org-mongos') + $package_ensure = true + $package_ensure_client = true + $package_ensure_mongos = true + $service_name = pick($::mongodb::globals::service_name, 'mongod') + $config = '/etc/mongod.conf' } else { - $server_package_name = 'mongodb-10gen' + # check if the version is greater than 2.6 + if(versioncmp($::mongodb::globals::version, '2.6.0') >= 0) { + $server_package_name = pick($::mongodb::globals::server_package_name, 'mongodb-org-server') + $client_package_name = pick($::mongodb::globals::client_package_name, 'mongodb-org-shell') + $mongos_package_name = pick($::mongodb::globals::mongos_package_name, 'mongodb-org-mongos') + $package_ensure = $::mongodb::globals::version + $package_ensure_client = $::mongodb::globals::version + $package_ensure_mongos = $::mongodb::globals::version + $service_name = pick($::mongodb::globals::service_name, 'mongod') + $config = '/etc/mongod.conf' + } else { + $server_package_name = pick($::mongodb::globals::server_package_name, 'mongodb-10gen') + $client_package_name = pick($::mongodb::globals::client_package_name, 'mongodb-10gen') + $mongos_package_name = pick($::mongodb::globals::mongos_package_name, 'mongodb-10gen') + $package_ensure = $::mongodb::globals::version + $package_ensure_client = $::mongodb::globals::version #this is still needed in case they are only installing the client + $service_name = pick($::mongodb::globals::service_name, 'mongodb') + $config = '/etc/mongodb.conf' + } } - $service_name = 'mongodb' - $config = '/etc/mongodb.conf' - $dbpath = '/var/lib/mongodb' - $logpath = '/var/log/mongodb/mongodb.log' - $bind_ip = ['127.0.0.1'] + $mongos_service_name = pick($::mongodb::globals::mongos_service_name, 'mongos') + $mongos_config = '/etc/mongodb-shard.conf' + $dbpath = '/var/lib/mongodb' + $logpath = '/var/log/mongodb/mongodb.log' + $pidfilepath = '/var/run/mongod.pid' + $bind_ip = pick($::mongodb::globals::bind_ip, ['127.0.0.1']) } else { # although we are living in a free world, # I would not recommend to use the prepacked # mongodb server on Ubuntu 12.04 or Debian 6/7, # because its really outdated - $user = pick($user, 'mongodb') - $group = pick($group, 'mongodb') - $server_package_name = pick($server_package_name, 'mongodb-server') - $client_package_name = pick($client_package_name, 'mongodb') - $service_name = pick($service_name, 'mongodb') + if ($::mongodb::globals::version == undef) { + $package_ensure = true + $package_ensure_client = true + $package_ensure_mongos = true + } else { + $package_ensure = $::mongodb::globals::version + $package_ensure_client = $::mongodb::globals::version + $package_ensure_mongos = $::mongodb::globals::version + } + $user = pick($::mongodb::globals::user, 'mongodb') + $group = pick($::mongodb::globals::group, 'mongodb') + $server_package_name = pick($::mongodb::globals::server_package_name, 'mongodb-server') + $client_package_name = $::mongodb::globals::client_package_name + $mongos_package_name = pick($::mongodb::globals::mongos_package_name, 'mongodb-server') + $service_name = pick($::mongodb::globals::service_name, 'mongodb') + $mongos_service_name = pick($::mongodb::globals::mongos_service_name, 'mongos') $config = '/etc/mongodb.conf' + $mongos_config = '/etc/mongodb-shard.conf' $dbpath = '/var/lib/mongodb' $logpath = '/var/log/mongodb/mongodb.log' - $bind_ip = pick($bind_ip, ['127.0.0.1']) - $pidfilepath = undef + $bind_ip = pick($::mongodb::globals::bind_ip, ['127.0.0.1']) + $pidfilepath = $::mongodb::globals::pidfilepath } # avoid using fork because of the init scripts design - $fork = undef + $fork = undef + $journal = undef + $mongos_pidfilepath = undef + $mongos_unixsocketprefix = undef + $mongos_logpath = undef + $mongos_fork = undef } default: { fail("Osfamily ${::osfamily} and ${::operatingsystem} is not supported") @@ -82,6 +192,16 @@ } case $::operatingsystem { + 'Debian': { + case $::operatingsystemmajrelease { + '8': { + $service_provider = pick($service_provider, 'systemd') + } + default: { + $service_provider = pick($service_provider, 'debian') + } + } + } 'Ubuntu': { $service_provider = pick($service_provider, 'upstart') } @@ -89,5 +209,4 @@ $service_provider = undef } } - } diff --git a/puphpet/puppet/modules/mongodb/manifests/replset.pp b/puphpet/puppet/modules/mongodb/manifests/replset.pp index ce4a025..0c6cc29 100644 --- a/puphpet/puppet/modules/mongodb/manifests/replset.pp +++ b/puphpet/puppet/modules/mongodb/manifests/replset.pp @@ -7,4 +7,9 @@ if $sets { create_resources(mongodb_replset, $sets) } + + # Order replset before any DB's and shard config + Mongodb_replset <| |> -> Mongodb_database <| |> + Mongodb_replset <| |> -> Mongodb_shard <| |> + Mongodb_replset <| |> -> Mongodb_user <| |> } diff --git a/puphpet/puppet/modules/mongodb/manifests/repo.pp b/puphpet/puppet/modules/mongodb/manifests/repo.pp index ecd6de1..70b6f6c 100644 --- a/puphpet/puppet/modules/mongodb/manifests/repo.pp +++ b/puphpet/puppet/modules/mongodb/manifests/repo.pp @@ -1,25 +1,52 @@ # PRIVATE CLASS: do not use directly class mongodb::repo ( - $ensure = $mongodb::params::ensure, + $ensure = $mongodb::params::ensure, + $version = $mongodb::params::version, + $repo_location = undef, + $proxy = undef, + $proxy_username = undef, + $proxy_password = undef, ) inherits mongodb::params { case $::osfamily { 'RedHat', 'Linux': { - $location = $::architecture ? { - 'x86_64' => 'http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/', - 'i686' => 'http://downloads-distro.mongodb.org/repo/redhat/os/i686/', - 'i386' => 'http://downloads-distro.mongodb.org/repo/redhat/os/i686/', - default => undef + if ($repo_location != undef){ + $location = $repo_location + $description = 'MongoDB Custom Repository' + } elsif $mongodb::globals::use_enterprise_repo == true { + $location = 'https://repo.mongodb.com/yum/redhat/$releasever/mongodb-enterprise/stable/$basearch/' + $description = 'MongoDB Enterprise Repository' } - class { 'mongodb::repo::yum': } + elsif (versioncmp($version, '3.0.0') >= 0) { + $mongover = split($version, '[.]') + $location = $::architecture ? { + 'x86_64' => "http://repo.mongodb.org/yum/redhat/${::operatingsystemmajrelease}/mongodb-org/${mongover[0]}.${mongover[1]}/x86_64/", + default => undef + } + } + else { + $location = $::architecture ? { + 'x86_64' => 'http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/', + 'i686' => 'http://downloads-distro.mongodb.org/repo/redhat/os/i686/', + 'i386' => 'http://downloads-distro.mongodb.org/repo/redhat/os/i686/', + default => undef + } + $description = 'MongoDB/10gen Repository' + } + + class { '::mongodb::repo::yum': } } 'Debian': { - $location = $::operatingsystem ? { - 'Debian' => 'http://downloads-distro.mongodb.org/repo/debian-sysvinit', - 'Ubuntu' => 'http://downloads-distro.mongodb.org/repo/ubuntu-upstart', - default => undef + if ($repo_location != undef){ + $location = $repo_location + }else{ + $location = $::operatingsystem ? { + 'Debian' => 'http://downloads-distro.mongodb.org/repo/debian-sysvinit', + 'Ubuntu' => 'http://downloads-distro.mongodb.org/repo/ubuntu-upstart', + default => undef + } } - class { 'mongodb::repo::apt': } + class { '::mongodb::repo::apt': } } default: { diff --git a/puphpet/puppet/modules/mongodb/manifests/repo/apt.pp b/puphpet/puppet/modules/mongodb/manifests/repo/apt.pp index e8f4b81..eff08ca 100644 --- a/puphpet/puppet/modules/mongodb/manifests/repo/apt.pp +++ b/puphpet/puppet/modules/mongodb/manifests/repo/apt.pp @@ -6,19 +6,19 @@ include ::apt if($::mongodb::repo::ensure == 'present' or $::mongodb::repo::ensure == true) { - apt::source { 'downloads-distro.mongodb.org': + apt::source { 'mongodb': location => $::mongodb::repo::location, release => 'dist', repos => '10gen', - key => '9ECBEC467F0CEB10', - key_server => 'keyserver.ubuntu.com', + key => '492EAFE8CD016A07919F1D2B9ECBEC467F0CEB10', + key_server => 'hkp://keyserver.ubuntu.com:80', include_src => false, } - Apt::Source['downloads-distro.mongodb.org']->Package<|tag == 'mongodb'|> + Apt::Source['mongodb']->Package<|tag == 'mongodb'|> } else { - apt::source { 'downloads-distro.mongodb.org': + apt::source { 'mongodb': ensure => absent, } } diff --git a/puphpet/puppet/modules/mongodb/manifests/repo/yum.pp b/puphpet/puppet/modules/mongodb/manifests/repo/yum.pp index 3a3f6b5..6046e9a 100644 --- a/puphpet/puppet/modules/mongodb/manifests/repo/yum.pp +++ b/puphpet/puppet/modules/mongodb/manifests/repo/yum.pp @@ -5,10 +5,13 @@ if($::mongodb::repo::ensure == 'present' or $::mongodb::repo::ensure == true) { yumrepo { 'mongodb': - descr => 'MongoDB/10gen Repository', - baseurl => $::mongodb::repo::location, - gpgcheck => '0', - enabled => '1', + descr => $::mongodb::repo::description, + baseurl => $::mongodb::repo::location, + gpgcheck => '0', + enabled => '1', + proxy => $::mongodb::repo::proxy, + proxy_username => $::mongodb::repo::proxy_username, + proxy_password => $::mongodb::repo::proxy_password, } Yumrepo['mongodb'] -> Package<|tag == 'mongodb'|> } diff --git a/puphpet/puppet/modules/mongodb/manifests/server.pp b/puphpet/puppet/modules/mongodb/manifests/server.pp index 04c576a..e51668e 100644 --- a/puphpet/puppet/modules/mongodb/manifests/server.pp +++ b/puphpet/puppet/modules/mongodb/manifests/server.pp @@ -8,19 +8,24 @@ $config = $mongodb::params::config, $dbpath = $mongodb::params::dbpath, $pidfilepath = $mongodb::params::pidfilepath, + $rcfile = $mongodb::params::rcfile, + $service_manage = $mongodb::params::service_manage, $service_provider = $mongodb::params::service_provider, $service_name = $mongodb::params::service_name, + $service_enable = $mongodb::params::service_enable, + $service_ensure = $mongodb::params::service_ensure, $service_status = $mongodb::params::service_status, - $package_ensure = $ensure, + $package_ensure = $mongodb::params::package_ensure, $package_name = $mongodb::params::server_package_name, $logpath = $mongodb::params::logpath, $bind_ip = $mongodb::params::bind_ip, + $ipv6 = undef, $logappend = true, $fork = $mongodb::params::fork, - $port = 27017, + $port = undef, $journal = $mongodb::params::journal, $nojournal = undef, $smallfiles = undef, @@ -47,11 +52,33 @@ $mms_name = undef, $mms_interval = undef, $replset = undef, + $replset_config = undef, + $replset_members = undef, + $configsvr = undef, + $shardsvr = undef, $rest = undef, + $quiet = undef, $slowms = undef, $keyfile = undef, + $key = undef, $set_parameter = undef, $syslog = undef, + $config_content = undef, + $ssl = undef, + $ssl_key = undef, + $ssl_ca = undef, + $restart = $mongodb::params::restart, + $storage_engine = undef, + + $create_admin = $mongodb::params::create_admin, + $admin_username = $mongodb::params::admin_username, + $admin_password = undef, + $store_creds = $mongodb::params::store_creds, + $admin_roles = ['userAdmin', 'readWrite', 'dbAdmin', + 'dbAdminAnyDatabase', 'readAnyDatabase', + 'readWriteAnyDatabase', 'userAdminAnyDatabase', + 'clusterAdmin', 'clusterManager', 'clusterMonitor', + 'hostManager', 'root', 'restore'], # Deprecated parameters $master = undef, @@ -61,17 +88,88 @@ ) inherits mongodb::params { + if $ssl { + validate_string($ssl_key, $ssl_ca) + } + if ($ensure == 'present' or $ensure == true) { - anchor { 'mongodb::server::start': }-> - class { 'mongodb::server::install': }-> - class { 'mongodb::server::config': }-> - class { 'mongodb::server::service': }-> - anchor { 'mongodb::server::end': } + if $restart { + anchor { 'mongodb::server::start': }-> + class { 'mongodb::server::install': }-> + # If $restart is true, notify the service on config changes (~>) + class { 'mongodb::server::config': }~> + class { 'mongodb::server::service': }-> + anchor { 'mongodb::server::end': } + } else { + anchor { 'mongodb::server::start': }-> + class { 'mongodb::server::install': }-> + # If $restart is false, config changes won't restart the service (->) + class { 'mongodb::server::config': }-> + class { 'mongodb::server::service': }-> + anchor { 'mongodb::server::end': } + } } else { anchor { 'mongodb::server::start': }-> - class { 'mongodb::server::service': }-> - class { 'mongodb::server::config': }-> - class { 'mongodb::server::install': }-> + class { '::mongodb::server::service': }-> + class { '::mongodb::server::config': }-> + class { '::mongodb::server::install': }-> anchor { 'mongodb::server::end': } } + + if $create_admin { + validate_string($admin_password) + + mongodb::db { 'admin': + user => $admin_username, + password => $admin_password, + roles => $admin_roles + } + + # Make sure it runs at the correct point + Anchor['mongodb::server::end'] -> Mongodb::Db['admin'] + + # Make sure it runs before other DB creation + Mongodb::Db['admin'] -> Mongodb::Db <| title != 'admin' |> + } + + # Set-up replicasets + if $replset { + # Check that we've got either a members array or a replset_config hash + if $replset_members and $replset_config { + fail('You can provide either replset_members or replset_config, not both.') + } elsif !$replset_members and !$replset_config { + # No members or config provided. Warn about it. + warning('Replset specified, but no replset_members or replset_config provided.') + } else { + if $replset_config { + validate_hash($replset_config) + + # Copy it to REAL value + $replset_config_REAL = $replset_config + + } else { + validate_array($replset_members) + + # Build up a config hash + $replset_config_REAL = { + "${replset}" => { + 'ensure' => 'present', + 'members' => $replset_members + } + } + } + + # Wrap the replset class + class { 'mongodb::replset': + sets => $replset_config_REAL + } + Anchor['mongodb::server::end'] -> Class['mongodb::replset'] + + # Make sure that the ordering is correct + if $create_admin { + Class['mongodb::replset'] -> Mongodb::Db['admin'] + } + + } + } } diff --git a/puphpet/puppet/modules/mongodb/manifests/server/config.pp b/puphpet/puppet/modules/mongodb/manifests/server/config.pp index 2056c14..6c9df38 100644 --- a/puphpet/puppet/modules/mongodb/manifests/server/config.pp +++ b/puphpet/puppet/modules/mongodb/manifests/server/config.pp @@ -4,6 +4,7 @@ $user = $mongodb::server::user $group = $mongodb::server::group $config = $mongodb::server::config + $config_content = $mongodb::server::config_content $dbpath = $mongodb::server::dbpath $pidfilepath = $mongodb::server::pidfilepath @@ -17,6 +18,11 @@ $cpu = $mongodb::server::cpu $auth = $mongodb::server::auth $noath = $mongodb::server::noauth + $create_admin = $mongodb::server::create_admin + $admin_username = $mongodb::server::admin_username + $admin_password = $mongodb::server::admin_password + $store_creds = $mongodb::server::store_creds + $rcfile = $mongodb::server::rcfile $verbose = $mongodb::server::verbose $verbositylevel = $mongodb::server::verbositylevel $objcheck = $mongodb::server::objcheck @@ -37,15 +43,25 @@ $slave = $mongodb::server::slave $only = $mongodb::server::only $source = $mongodb::server::source + $configsvr = $mongodb::server::configsvr + $shardsvr = $mongodb::server::shardsvr $replset = $mongodb::server::replset $rest = $mongodb::server::rest + $quiet = $mongodb::server::quiet $slowms = $mongodb::server::slowms $keyfile = $mongodb::server::keyfile + $key = $mongodb::server::key + $ipv6 = $mongodb::server::ipv6 $bind_ip = $mongodb::server::bind_ip $directoryperdb = $mongodb::server::directoryperdb $profile = $mongodb::server::profile $set_parameter = $mongodb::server::set_parameter $syslog = $mongodb::server::syslog + $ssl = $mongodb::server::ssl + $ssl_key = $mongodb::server::ssl_key + $ssl_ca = $mongodb::server::ssl_ca + $storage_engine = $mongodb::server::storage_engine + $version = $mongodb::server::version File { owner => $user, @@ -63,13 +79,124 @@ else { $noauth = true } + if $keyfile and $key { + validate_string($key) + validate_re($key,'.{6}') + file { $keyfile: + content => $key, + owner => $user, + group => $group, + mode => '0400', + } + } + + if empty($storage_engine) { + $storage_engine_internal = undef + } else { + $storage_engine_internal = $storage_engine + } + + + #Pick which config content to use + if $config_content { + $cfg_content = $config_content + } elsif (versioncmp($version, '2.6.0') >= 0) { + # Template uses: + # - $auth + # - $bind_ip + # - $configsvr + # - $dbpath + # - $directoryperdb + # - $fork + # - $ipv6 + # - $jounal + # - $keyfile + # - $logappend + # - $logpath + # - $maxconns + # - $nohttpinteface + # - $nojournal + # - $noprealloc + # - $noscripting + # - $nssize + # - $objcheck + # - $oplog_size + # - $pidfilepath + # - $port + # - $profile + # - $quota + # - $quotafiles + # - $replset + # - $rest + # - $set_parameter + # - $shardsvr + # - $slowms + # - $smallfiles + # - $syslog + # - $verbose + # - $verbositylevel + $cfg_content = template('mongodb/mongodb.conf.2.6.erb') + } else { + # Fall back to oldest most basic config + # Template uses: + # - $auth + # - $bind_ip + # - $configsvr + # - $cpu + # - $dbpath + # - $diaglog + # - $directoryperdb + # - $fork + # - $ipv6 + # - $jounal + # - $keyfile + # - $logappend + # - $logpath + # - $master + # - $maxconns + # - $mms_interval + # - $mms_name + # - $mms_token + # - $noauth + # - $nohints + # - $nohttpinteface + # - $nojournal + # - $noprealloc + # - $noscripting + # - $notablescan + # - $nssize + # - $objcheck + # - $only + # - $oplog_size + # - $pidfilepath + # - $port + # - $profile + # - $quiet + # - $quota + # - $quotafiles + # - $replset + # - $rest + # - $set_parameter + # - $shardsvr + # - $slave + # - $slowms + # - $smallfiles + # - $source + # - $ssl + # - $ssl_ca + # - $ssl_key + # - storage_engine_internal + # - $syslog + # - $verbose + # - $verbositylevel + $cfg_content = template('mongodb/mongodb.conf.erb') + } file { $config: - content => template('mongodb/mongodb.conf.erb'), + content => $cfg_content, owner => 'root', group => 'root', mode => '0644', - notify => Class['mongodb::server::service'] } file { $dbpath: @@ -89,4 +216,18 @@ ensure => absent } } + + if $auth and $store_creds { + file { $rcfile: + ensure => present, + content => template('mongodb/mongorc.js.erb'), + owner => 'root', + group => 'root', + mode => '0644' + } + } else { + file { $rcfile: + ensure => absent + } + } } diff --git a/puphpet/puppet/modules/mongodb/manifests/server/install.pp b/puphpet/puppet/modules/mongodb/manifests/server/install.pp index 46b0e74..8adc24d 100644 --- a/puphpet/puppet/modules/mongodb/manifests/server/install.pp +++ b/puphpet/puppet/modules/mongodb/manifests/server/install.pp @@ -27,8 +27,8 @@ } package { 'mongodb_server': - ensure => $my_package_ensure, - name => $package_name, - tag => 'mongodb', + ensure => $my_package_ensure, + name => $package_name, + tag => 'mongodb', } } diff --git a/puphpet/puppet/modules/mongodb/manifests/server/service.pp b/puphpet/puppet/modules/mongodb/manifests/server/service.pp index 8cb4a48..3411b23 100644 --- a/puphpet/puppet/modules/mongodb/manifests/server/service.pp +++ b/puphpet/puppet/modules/mongodb/manifests/server/service.pp @@ -1,23 +1,59 @@ # PRIVATE CLASS: do not call directly class mongodb::server::service { - $ensure = $mongodb::server::ensure + $ensure = $mongodb::server::service_ensure + $service_manage = $mongodb::server::service_manage + $service_enable = $mongodb::server::service_enable $service_name = $mongodb::server::service_name $service_provider = $mongodb::server::service_provider $service_status = $mongodb::server::service_status + $bind_ip = $mongodb::server::bind_ip + $port = $mongodb::server::port + $configsvr = $mongodb::server::configsvr + $shardsvr = $mongodb::server::shardsvr + + if !$port { + if $configsvr { + $port_real = 27019 + } elsif $shardsvr { + $port_real = 27018 + } else { + $port_real = 27017 + } + } else { + $port_real = $port + } + + if $bind_ip == '0.0.0.0' { + $bind_ip_real = '127.0.0.1' + } else { + $bind_ip_real = $bind_ip + } $service_ensure = $ensure ? { - present => true, - absent => false, - purged => false, - default => $ensure + 'absent' => false, + 'purged' => false, + 'stopped' => false, + default => true } - service { 'mongodb': - ensure => $service_ensure, - name => $service_name, - enable => $service_ensure, - provider => $service_provider, - hasstatus => true, - status => $service_status, + if $service_manage { + service { 'mongodb': + ensure => $service_ensure, + name => $service_name, + enable => $service_enable, + provider => $service_provider, + hasstatus => true, + status => $service_status, + } + + if $service_ensure { + mongodb_conn_validator { 'mongodb': + server => $bind_ip_real, + port => $port_real, + timeout => '240', + require => Service['mongodb'], + } + } } + } diff --git a/puphpet/puppet/modules/mongodb/manifests/shardsvr.pp b/puphpet/puppet/modules/mongodb/manifests/shardsvr.pp new file mode 100644 index 0000000..e8adbbf --- /dev/null +++ b/puphpet/puppet/modules/mongodb/manifests/shardsvr.pp @@ -0,0 +1,11 @@ +# Wrapper class useful for hiera based deployments + +class mongodb::shardsvr( + $shards = undef +) { + + if $shards { + create_resources(mongodb_shard, $shards) + } + +} diff --git a/puphpet/puppet/modules/mongodb/metadata.json b/puphpet/puppet/modules/mongodb/metadata.json new file mode 100644 index 0000000..27116bf --- /dev/null +++ b/puphpet/puppet/modules/mongodb/metadata.json @@ -0,0 +1,46 @@ +{ + "name": "puppetlabs-mongodb", + "version": "0.11.0", + "author": "puppetlabs", + "summary": "Installs MongoDB on RHEL/Ubuntu/Debian.", + "license": "Apache-2.0", + "source": "https://github.com/puppetlabs/puppetlabs-mongodb", + "project_page": "https://github.com/puppetlabs/puppetlabs-mongodb", + "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", + "operatingsystem_support": [ + { + "operatingsystem": "RedHat", + "operatingsystemrelease": [ + "5", + "6", + "7" + ] + }, + { + "operatingsystem": "CentOS", + "operatingsystemrelease": [ + "5", + "6", + "7" + ] + }, + { + "operatingsystem": "Debian", + "operatingsystemrelease": [ + "6", + "7" + ] + }, + { + "operatingsystem": "Ubuntu", + "operatingsystemrelease": [ + "10.04", + "12.04" + ] + } + ], + "dependencies": [ + {"name":"puppetlabs/apt","version_requirement":">= 1.0.0 <3.0.0"}, + {"name":"puppetlabs/stdlib","version_requirement":">= 2.2.0 <5.0.0"} + ] +} diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/database_spec.rb b/puphpet/puppet/modules/mongodb/spec/acceptance/database_spec.rb new file mode 100644 index 0000000..32a98ed --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/database_spec.rb @@ -0,0 +1,99 @@ +require 'spec_helper_acceptance' + +describe 'mongodb_database' do + case fact('osfamily') + when 'RedHat' + version = "'2.6.6-1'" + when 'Debian' + version = "'2.6.6'" + end + shared_examples 'normal tests' do |tengen, version| + context "when manage_package_repo is #{tengen} and version is #{version}" do + describe 'creating a database' do + context 'with default port' do + after :all do + puts "XXX uninstalls mongodb because changing the port with tengen doesn't work because they have a crappy init script" + pp = <<-EOS + class {'mongodb::globals': manage_package_repo => #{tengen}, } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => absent, + service_ensure => stopped, + service_enable => false + } + -> class { 'mongodb::client': ensure => absent, } + EOS + apply_manifest(pp, :catch_failures => true) + end + it 'should compile with no errors' do + pp = <<-EOS + class { 'mongodb::globals': manage_package_repo => #{tengen}, version => #{version.nil? ? 'undef' : version} } + -> class { 'mongodb::server': } + -> class { 'mongodb::client': } + -> mongodb::db { 'testdb1': + user => 'testuser', + password => 'testpass', + } + -> mongodb::db { 'testdb2': + user => 'testuser', + password => 'testpass', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + it 'should create the databases' do + shell("mongo testdb1 --eval 'printjson(db.getMongo().getDBs())'") + shell("mongo testdb2 --eval 'printjson(db.getMongo().getDBs())'") + end + end + + # MODULES-878 + context 'with custom port' do + after :all do + puts "XXX uninstalls mongodb because changing the port with tengen doesn't work because they have a crappy init script" + pp = <<-EOS + class {'mongodb::globals': manage_package_repo => #{tengen}, } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => absent, + service_ensure => stopped, + service_enable => false + } + -> class { 'mongodb::client': ensure => absent, } + EOS + apply_manifest(pp, :catch_failures => true) + end + it 'should work with no errors' do + pp = <<-EOS + class { 'mongodb::globals': manage_package_repo => #{tengen}, } + -> class { 'mongodb::server': port => 27018 } + -> class { 'mongodb::client': } + -> mongodb::db { 'testdb1': + user => 'testuser', + password => 'testpass', + } + -> mongodb::db { 'testdb2': + user => 'testuser', + password => 'testpass', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + it 'should create the database' do + shell("mongo testdb1 --port 27018 --eval 'printjson(db.getMongo().getDBs())'") + shell("mongo testdb2 --port 27018 --eval 'printjson(db.getMongo().getDBs())'") + end + end + end + end + end + + it_behaves_like 'normal tests', false, nil + it_behaves_like 'normal tests', true, nil # This will give a key-value config file even though the version will be 2.6 + it_behaves_like 'normal tests', true, version # This will give the YAML config file for 2.6 +end diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/mongos_spec.rb b/puphpet/puppet/modules/mongodb/spec/acceptance/mongos_spec.rb new file mode 100644 index 0000000..cea72f1 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/mongos_spec.rb @@ -0,0 +1,110 @@ +require 'spec_helper_acceptance' + +describe 'mongodb::mongos class' do + + shared_examples 'normal tests' do |tengen| + if tengen + package_name = 'mongodb-org-mongos' + else + package_name = 'mongodb-server' + end + service_name = 'mongos' + config_file = '/etc/mongodb-shard.conf' + + client_name = 'mongo --version' + + context "default parameters with 10gen => #{tengen}" do + after :all do + if tengen + puts "XXX uninstalls mongodb and mongos because changing the port with tengen doesn't work because they have a crappy init script" + pp = <<-EOS + class {'mongodb::globals': manage_package_repo => #{tengen}, } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => absent, + service_ensure => stopped, + service_enable => false + } + -> class { 'mongodb::client': ensure => absent, } + -> class { 'mongodb::mongos': + ensure => absent, + package_ensure => absent, + service_ensure => stopped, + service_enable => false + } + EOS + apply_manifest(pp, :catch_failures => true) + end + end + + it 'should work with no errors' do + pp = <<-EOS + class { 'mongodb::globals': manage_package_repo => #{tengen}, + } -> class { 'mongodb::server': + configsvr => true, + } + -> class { 'mongodb::client': } + -> class { 'mongodb::mongos': + configdb => ['127.0.0.1:27019'], + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe package(package_name) do + it { is_expected.to be_installed } + end + + describe file(config_file) do + it { is_expected.to be_file } + end + + describe service(service_name) do + it { is_expected.to be_enabled } + it { is_expected.to be_running } + end + + describe port(27017) do + it { is_expected.to be_listening } + end + + describe port(27019) do + it { is_expected.to be_listening } + end + + describe command(client_name) do + describe '#exit_status' do + subject { super().exit_status } + it { is_expected.to eq 0 } + end + end + end + + describe "uninstalling with 10gen => #{tengen}" do + it 'uninstalls mongodb' do + pp = <<-EOS + class {'mongodb::globals': manage_package_repo => #{tengen}, } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => absent, + service_ensure => stopped, + service_enable => false + } + -> class { 'mongodb::client': ensure => absent, } + -> class { 'mongodb::mongos': + ensure => absent, + package_ensure => absent, + service_ensure => stopped, + service_enable => false + } + EOS + apply_manifest(pp, :catch_failures => true) + end + end + end + + it_behaves_like 'normal tests', false + it_behaves_like 'normal tests', true +end diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-59-x64.yml b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-59-x64.yml new file mode 100644 index 0000000..2ad90b8 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-59-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-65-x64.yml b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-65-x64.yml new file mode 100644 index 0000000..4e2cb80 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-65-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-7-vcloud.yml b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-7-vcloud.yml new file mode 100644 index 0000000..1cecb6b --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-7-vcloud.yml @@ -0,0 +1,15 @@ +HOSTS: + 'centos-7-vcloud': + roles: + - master + platform: el-7-x86_64 + hypervisor: vcloud + template: centos-7-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/ diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-7-x64.yml b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-7-x64.yml new file mode 100644 index 0000000..983238c --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/centos-7-x64.yml @@ -0,0 +1,9 @@ +HOSTS: + centos-7-x64: + roles: + - master + platform: el-7-x86_64 + box : puppetlabs/centos-7.0-64-nocm + hypervisor : vagrant +CONFIG: + type: foss diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/debian-607-x64.yml b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/debian-607-x64.yml new file mode 100644 index 0000000..4668f5f --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/debian-607-x64.yml @@ -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 \ No newline at end of file diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/debian-70rc1-x64.yml b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/debian-70rc1-x64.yml new file mode 100644 index 0000000..750d299 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/debian-70rc1-x64.yml @@ -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 \ No newline at end of file diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-64-x64.yml b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-64-x64.yml index 05540ed..5bcd477 100644 --- a/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-64-x64.yml +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-64-x64.yml @@ -1,10 +1,17 @@ HOSTS: - centos-64-x64: + 'master': roles: - master platform: el-6-x86_64 + hypervisor : vagrant box : centos-64-x64-vbox4210-nocm box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box + 'slave': + roles: + - master + platform: el-6-x86_64 hypervisor : vagrant + box : centos-64-x64-vbox4210-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210-nocm.box CONFIG: type: foss diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-7-vcloud.yml b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-7-vcloud.yml new file mode 100644 index 0000000..a7adb16 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-7-vcloud.yml @@ -0,0 +1,21 @@ +HOSTS: + 'master': + roles: + - master + platform: el-7-x86_64 + hypervisor: vcloud + template: centos-7-x86_64 + 'slave': + roles: + - slave + platform: el-7-x86_64 + hypervisor: vcloud + template: centos-7-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/ diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-7-x64.yml b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-7-x64.yml new file mode 100644 index 0000000..877ccbb --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/multi-centos-7-x64.yml @@ -0,0 +1,15 @@ +HOSTS: + 'master': + roles: + - master + platform: el-7-x86_64 + hypervisor : vagrant + box : puppetlabs/centos-7.0-64-nocm + 'slave': + roles: + - slave + platform: el-7-x86_64 + hypervisor : vagrant + box : puppetlabs/centos-7.0-64-nocm +CONFIG: + type: foss diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml new file mode 100644 index 0000000..cba1cd0 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/replset_spec.rb b/puphpet/puppet/modules/mongodb/spec/acceptance/replset_spec.rb index 8be5a0f..8489670 100644 --- a/puphpet/puppet/modules/mongodb/spec/acceptance/replset_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/replset_spec.rb @@ -9,10 +9,14 @@ pp = <<-EOS class { 'mongodb::globals': } -> class { 'mongodb::server': - ensure => purged, + ensure => absent, + package_ensure => absent, + service_ensure => stopped } if $::osfamily == 'RedHat' { - class { 'mongodb::client': } + class { 'mongodb::client': + ensure => absent + } } EOS @@ -66,4 +70,133 @@ class { 'mongodb::client': } end end end + + describe 'mongodb_replset resource with auth => true' do + after :all do + # Have to drop the DB to disable replsets for further testing + on hosts, %{mongo local --verbose --eval 'db.dropDatabase()'} + + pp = <<-EOS + class { 'mongodb::globals': } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => absent, + service_ensure => stopped + } + if $::osfamily == 'RedHat' { + class { 'mongodb::client': + ensure => absent + } + } + EOS + + apply_manifest_on(hosts.reverse, pp, :catch_failures => true) + end + + it 'configures mongo on both nodes' do + pp = <<-EOS + class { 'mongodb::globals': + version => '2.6.9-1', + manage_package_repo => true + } -> + class { 'mongodb::server': + admin_username => 'admin', + admin_password => 'password', + auth => true, + bind_ip => '0.0.0.0', + replset => 'test', + keyfile => '/var/lib/mongodb/mongodb-keyfile', + key => '+dxlTrury7xtD0FRqFf3YWGnKqWAtlyauuemxuYuyz9POPUuX1Uj3chGU8MFMHa7 +UxASqex7NLMALQXHL+Th4T3dyb6kMZD7KiMcJObO4M+JLiX9drcTiifsDEgGMi7G +vYn3pWSm5TTDrHJw7RNWfMHw3sHk0muGQcO+0dWv3sDJ6SiU8yOKRtYcTEA15GbP +ReDZuHFy1T1qhk5NIt6pTtPGsZKSm2wAWIOa2f2IXvpeQHhjxP8aDFb3fQaCAqOD +R7hrimqq0Nickfe8RLA89iPXyadr/YeNBB7w7rySatQBzwIbBUVGNNA5cxCkwyx9 +E5of3xi7GL9xNxhQ8l0JEpofd4H0y0TOfFDIEjc7cOnYlKAHzBgog4OcFSILgUaF +kHuTMtv0pj+MMkW2HkeXETNII9XE1+JiZgHY08G7yFEJy87ttUoeKmpbI6spFz5U +4K0amj+N6SOwXaS8uwp6kCqay0ERJLnw+7dKNKZIZdGCrrBxcZ7wmR/wLYrxvHhZ +QpeXTxgD5ebwCR0cf3Xnb5ql5G/HHKZDq8LTFHwELNh23URGPY7K7uK+IF6jSEhq +V2H3HnWV9teuuJ5he9BB/pLnyfjft6KUUqE9HbaGlX0f3YBk/0T3S2ESN4jnfRTQ +ysAKvQ6NasXkzqXktu8X4fS5QNqrFyqKBZSWxttfJBKXnT0TxamCKLRx4AgQglYo +3KRoyfxXx6G+AjP1frDJxFAFEIgEFqRk/FFuT/y9LpU+3cXYX1Gt6wEatgmnBM3K +g+Bybk5qHv1b7M8Tv9/I/BRXcpLHeIkMICMY8sVPGmP8xzL1L3i0cws8p5h0zPBa +YG/QX0BmltAni8owgymFuyJgvr/gaRX4WHbKFD+9nKpqJ3ocuVNuCDsxDqLsJEME +nc1ohyB0lNt8lHf1U00mtgDSV3fwo5LkwhRi6d+bDBTL/C6MZETMLdyCqDlTdUWG +YXIsJ0gYcu9XG3mx10LbdPJvxSMg' + + } + if $::osfamily == 'RedHat' { + include mongodb::client + } + EOS + + apply_manifest_on(hosts.reverse, pp, :catch_failures => true) + apply_manifest_on(hosts.reverse, pp, :catch_changes => true) + end + + it 'sets up the replset with puppet' do + pp = <<-EOS + class { 'mongodb::globals': + version => '2.6.9-1', + manage_package_repo => true + } -> + class { 'mongodb::server': + create_admin => true, + admin_username => 'admin', + admin_password => 'password', + auth => true, + bind_ip => '0.0.0.0', + replset => 'test', + keyfile => '/var/lib/mongodb/mongodb-keyfile', + key => '+dxlTrury7xtD0FRqFf3YWGnKqWAtlyauuemxuYuyz9POPUuX1Uj3chGU8MFMHa7 +UxASqex7NLMALQXHL+Th4T3dyb6kMZD7KiMcJObO4M+JLiX9drcTiifsDEgGMi7G +vYn3pWSm5TTDrHJw7RNWfMHw3sHk0muGQcO+0dWv3sDJ6SiU8yOKRtYcTEA15GbP +ReDZuHFy1T1qhk5NIt6pTtPGsZKSm2wAWIOa2f2IXvpeQHhjxP8aDFb3fQaCAqOD +R7hrimqq0Nickfe8RLA89iPXyadr/YeNBB7w7rySatQBzwIbBUVGNNA5cxCkwyx9 +E5of3xi7GL9xNxhQ8l0JEpofd4H0y0TOfFDIEjc7cOnYlKAHzBgog4OcFSILgUaF +kHuTMtv0pj+MMkW2HkeXETNII9XE1+JiZgHY08G7yFEJy87ttUoeKmpbI6spFz5U +4K0amj+N6SOwXaS8uwp6kCqay0ERJLnw+7dKNKZIZdGCrrBxcZ7wmR/wLYrxvHhZ +QpeXTxgD5ebwCR0cf3Xnb5ql5G/HHKZDq8LTFHwELNh23URGPY7K7uK+IF6jSEhq +V2H3HnWV9teuuJ5he9BB/pLnyfjft6KUUqE9HbaGlX0f3YBk/0T3S2ESN4jnfRTQ +ysAKvQ6NasXkzqXktu8X4fS5QNqrFyqKBZSWxttfJBKXnT0TxamCKLRx4AgQglYo +3KRoyfxXx6G+AjP1frDJxFAFEIgEFqRk/FFuT/y9LpU+3cXYX1Gt6wEatgmnBM3K +g+Bybk5qHv1b7M8Tv9/I/BRXcpLHeIkMICMY8sVPGmP8xzL1L3i0cws8p5h0zPBa +YG/QX0BmltAni8owgymFuyJgvr/gaRX4WHbKFD+9nKpqJ3ocuVNuCDsxDqLsJEME +nc1ohyB0lNt8lHf1U00mtgDSV3fwo5LkwhRi6d+bDBTL/C6MZETMLdyCqDlTdUWG +YXIsJ0gYcu9XG3mx10LbdPJvxSMg' + } + if $::osfamily == 'RedHat' { + include mongodb::client + } + mongodb_replset { 'test': + auth_enabled => true, + members => [#{hosts.collect{|x|"'#{x}:27017'"}.join(',')}], + before => Mongodb_user['admin'] + } + EOS + apply_manifest_on(hosts_as('master'), pp, :catch_failures => true) + apply_manifest_on(hosts_as('master'), pp, :catch_changes => true) + on(hosts_as('master'), 'mongo --quiet --eval "load(\'/root/.mongorc.js\');printjson(rs.conf())"') do |r| + expect(r.stdout).to match /#{hosts[0]}:27017/ + expect(r.stdout).to match /#{hosts[1]}:27017/ + end + end + + it 'inserts data on the master' do + sleep(30) + on hosts_as('master'), %{mongo test --verbose --eval 'load("/root/.mongorc.js");db.dummyData.insert({"created_by_puppet": 1})'} + end + + it 'checks the data on the master' do + on hosts_as('master'), %{mongo test --verbose --eval 'load("/root/.mongorc.js");printjson(db.dummyData.findOne())'} do |r| + expect(r.stdout).to match /created_by_puppet/ + end + end + + it 'checks the data on the slave' do + sleep(10) + on hosts_as('slave'), %{mongo test --verbose --eval 'load("/root/.mongorc.js");rs.slaveOk();printjson(db.dummyData.findOne())'} do |r| + expect(r.stdout).to match /created_by_puppet/ + end + end + end end diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/server_spec.rb b/puphpet/puppet/modules/mongodb/spec/acceptance/server_spec.rb index c1132f5..a8dee97 100644 --- a/puphpet/puppet/modules/mongodb/spec/acceptance/server_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/server_spec.rb @@ -10,9 +10,9 @@ service_name = 'mongod' config_file = '/etc/mongod.conf' when 'Debian' - package_name = 'mongodbdb-org-10gen' - service_name = 'mongodb' - config_file = '/etc/mongodb.conf' + package_name = 'mongodb-org-server' + service_name = 'mongod' + config_file = '/etc/mongod.conf' end else case fact('osfamily') @@ -35,7 +35,12 @@ puts "XXX uninstalls mongodb because changing the port with tengen doesn't work because they have a crappy init script" pp = <<-EOS class {'mongodb::globals': manage_package_repo => #{tengen}, } - -> class { 'mongodb::server': ensure => absent, } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => absent, + service_ensure => stopped, + service_enable => false + } -> class { 'mongodb::client': ensure => absent, } EOS apply_manifest(pp, :catch_failures => true) @@ -43,47 +48,37 @@ class {'mongodb::globals': manage_package_repo => #{tengen}, } end it 'should work with no errors' do - case fact('osfamily') - when 'RedHat' - pp = <<-EOS - class { 'mongodb::globals': manage_package_repo => #{tengen}, } - -> class { 'mongodb::server': } - -> class { 'mongodb::client': } - EOS - when 'Debian' - pp = <<-EOS - class { 'mongodb::globals': manage_package_repo => #{tengen}, } - -> class { 'mongodb::server': } - EOS - end + pp = <<-EOS + class { 'mongodb::globals': manage_package_repo => #{tengen}, } + -> class { 'mongodb::server': } + -> class { 'mongodb::client': } + EOS apply_manifest(pp, :catch_failures => true) apply_manifest(pp, :catch_changes => true) end describe package(package_name) do - it { should be_installed } + it { is_expected.to be_installed } end describe file(config_file) do - it { should be_file } + it { is_expected.to be_file } end describe service(service_name) do - it { should be_enabled } - it { should be_running } + it { is_expected.to be_enabled } + it { is_expected.to be_running } end describe port(27017) do - it do - sleep(20) - should be_listening - end + it { is_expected.to be_listening } end describe command(client_name) do - it do - should return_exit_status 0 + describe '#exit_status' do + subject { super().exit_status } + it { is_expected.to eq 0 } end end end @@ -93,6 +88,7 @@ class { 'mongodb::globals': manage_package_repo => #{tengen}, } pp = <<-EOS class { 'mongodb::globals': manage_package_repo => #{tengen}, } -> class { 'mongodb::server': port => 27018, } + -> class { 'mongodb::client': } EOS apply_manifest(pp, :catch_failures => true) @@ -100,8 +96,119 @@ class { 'mongodb::globals': manage_package_repo => #{tengen}, } end describe port(27018) do - sleep(20) - it { sleep 5 ; should be_listening } + it { is_expected.to be_listening } + end + end + + describe "uninstalling with 10gen => #{tengen}" do + it 'uninstalls mongodb' do + pp = <<-EOS + class {'mongodb::globals': manage_package_repo => #{tengen}, } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => absent, + service_ensure => stopped, + service_enable => false + } + -> class { 'mongodb::client': ensure => absent, } + EOS + apply_manifest(pp, :catch_failures => true) + end + end + end + + shared_examples 'auth tests' do |tengen| + if tengen + case fact('osfamily') + when 'RedHat' + package_name = 'mongodb-org-server' + service_name = 'mongod' + config_file = '/etc/mongod.conf' + when 'Debian' + package_name = 'mongodb-org-server' + service_name = 'mongod' + config_file = '/etc/mongod.conf' + end + else + case fact('osfamily') + when 'RedHat' + package_name = 'mongodb-server' + service_name = 'mongod' + config_file = '/etc/mongodb.conf' + when 'Debian' + package_name = 'mongodb-server' + service_name = 'mongodb' + config_file = '/etc/mongodb.conf' + end + end + + client_name = 'mongo --version' + + auth_enabled = 'mongo --quiet --eval "db.serverCmdLineOpts().code"' + admin_login = "mongo admin --quiet --eval \"load('/root/.mongorc.js');printjson(db.getUser('admin')['customData'])\"" + + context "default parameters with 10gen => #{tengen} and auth => true" do + it 'should work with no errors with authentication enabled' do + pp = <<-EOS + class { 'mongodb::globals': manage_package_repo => #{tengen}, } + -> class { 'mongodb::server': + auth => true, + create_admin => true, + store_creds => true, + admin_username => 'admin', + admin_password => 'password' + } + class { 'mongodb::client': } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe package(package_name) do + it { is_expected.to be_installed } + end + + describe file(config_file) do + it { is_expected.to be_file } + end + + describe service(service_name) do + it { is_expected.to be_enabled } + it { is_expected.to be_running } + end + + describe port(27017) do + it { is_expected.to be_listening } + end + + describe command(auth_enabled) do + describe '#stdout' do + subject { super().stdout.strip } + it { is_expected.to eq "13" } + end + end + + describe file('/root/.mongorc.js') do + it { is_expected.to be_file } + it { is_expected.to be_owned_by 'root' } + it { is_expected.to be_grouped_into 'root' } + it { is_expected.to be_mode 644 } + it { is_expected.to contain 'db.auth(\'admin\', \'password\')' } + end + + describe command(admin_login) do + describe '#stdout' do + subject { super().stdout.strip } + it { is_expected.to match "{ \"createdBy\" : \"Puppet Mongodb_user['User admin on db admin']\" }"} + end + end + + describe command(client_name) do + describe '#exit_status' do + subject { super().exit_status } + it { is_expected.to eq 0 } + end end end @@ -109,7 +216,12 @@ class { 'mongodb::globals': manage_package_repo => #{tengen}, } it 'uninstalls mongodb' do pp = <<-EOS class {'mongodb::globals': manage_package_repo => #{tengen}, } - -> class { 'mongodb::server': ensure => absent, } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => absent, + service_ensure => stopped, + service_enable => false + } -> class { 'mongodb::client': ensure => absent, } EOS apply_manifest(pp, :catch_failures => true) @@ -119,4 +231,5 @@ class {'mongodb::globals': manage_package_repo => #{tengen}, } it_behaves_like 'normal tests', false it_behaves_like 'normal tests', true + it_behaves_like 'auth tests', true end diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/sharding_spec.rb b/puphpet/puppet/modules/mongodb/spec/acceptance/sharding_spec.rb new file mode 100644 index 0000000..c51f2f2 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/sharding_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper_acceptance' + +if hosts.length > 1 + describe 'mongodb_shard resource' do + + it 'configures the shard server' do + pp = <<-EOS + class { 'mongodb::globals': } + -> class { 'mongodb::server': + bind_ip => '0.0.0.0', + replset => 'foo', + shardsvr => true, + }-> + mongodb_replset { 'foo' : + members => ["shard:27018"], + } + if $::osfamily == 'RedHat' { + class { 'mongodb::client': } + } + EOS + + apply_manifest_on(hosts_as('shard'), pp, :catch_failures => true) + apply_manifest_on(hosts_as('shard'), pp, :catch_changes => true) + end + + it 'configures the router server' do + pp = <<-EOS + class { 'mongodb::globals': } + -> class { 'mongodb::server': + bind_ip => '0.0.0.0', + configsvr => true, + } -> + class { 'mongodb::mongos' : + configdb => ["router:27019"], + } -> + exec { '/bin/sleep 20' : + } -> + mongodb_shard { 'foo': + member => 'foo/shard:27018', + keys => [{'foo.toto' => {'name' => 1}}] + } + if $::osfamily == 'RedHat' { + class { 'mongodb::client': } + } + EOS + + apply_manifest_on(hosts_as('router'), pp, :catch_failures => true) + on(hosts_as('router'), 'mongo --quiet --eval "printjson(sh.status())"') do |r| + expect(r.stdout).to match /foo\/shard:27018/ + expect(r.stdout).to match /foo\.toto/ + end + end + + end +end diff --git a/puphpet/puppet/modules/mongodb/spec/acceptance/user_spec.rb b/puphpet/puppet/modules/mongodb/spec/acceptance/user_spec.rb new file mode 100644 index 0000000..3e20093 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/acceptance/user_spec.rb @@ -0,0 +1,99 @@ +require 'spec_helper_acceptance' + +describe 'mongodb_database' do + case fact('osfamily') + when 'RedHat' + version = "'2.6.6-1'" + when 'Debian' + version = "'2.6.6'" + end + shared_examples 'normal tests' do |version| + context "when version is #{version.nil? ? 'nil' : version}" do + describe 'creating a database' do + context 'with default port' do + after :all do + puts "XXX uninstalls mongodb because changing the port with tengen doesn't work because they have a crappy init script" + pp = <<-EOS + class {'mongodb::globals': manage_package_repo => true, } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => absent, + service_ensure => stopped, + service_enable => false + } + -> class { 'mongodb::client': ensure => absent, } + EOS + apply_manifest(pp, :catch_failures => true) + end + it 'should compile with no errors' do + pp = <<-EOS + class { 'mongodb::globals': manage_package_repo => true, version => #{version.nil? ? 'undef' : version} } + -> class { 'mongodb::server': } + -> class { 'mongodb::client': } + -> mongodb_database { 'testdb': ensure => present } + -> + mongodb_user {'testuser': + ensure => present, + password_hash => mongodb_password('testuser', 'passw0rd'), + database => 'testdb', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + it 'should create the user' do + shell("mongo testdb --quiet --eval 'db.auth(\"testuser\",\"passw0rd\")'") do |r| + expect(r.stdout.chomp).to eq("1") + end + end + end + + # MODULES-878 + context 'with custom port' do + after :all do + puts "XXX uninstalls mongodb because changing the port with tengen doesn't work because they have a crappy init script" + pp = <<-EOS + class {'mongodb::globals': manage_package_repo => true, } + -> class { 'mongodb::server': + ensure => absent, + package_ensure => absent, + service_ensure => stopped, + service_enable => false + } + -> class { 'mongodb::client': ensure => absent, } + EOS + apply_manifest(pp, :catch_failures => true) + end + it 'should work with no errors' do + pp = <<-EOS + class { 'mongodb::globals': manage_package_repo => true, } + -> class { 'mongodb::server': port => 27018 } + -> class { 'mongodb::client': } + -> mongodb_database { 'testdb': ensure => present } + -> + mongodb_user {'testuser': + ensure => present, + password_hash => mongodb_password('testuser', 'passw0rd'), + database => 'testdb', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + it 'should create the user' do + shell("mongo testdb --quiet --port 27018 --eval 'db.auth(\"testuser\",\"passw0rd\")'") do |r| + expect(r.stdout.chomp).to eq("1") + end + end + end + end + end + end + + it_behaves_like 'normal tests', nil # This will give a key-value config file even though the version will be 2.6 + it_behaves_like 'normal tests', version # This will give the YAML config file for 2.6 +end diff --git a/puphpet/puppet/modules/mongodb/spec/classes/client_install_spec.rb b/puphpet/puppet/modules/mongodb/spec/classes/client_install_spec.rb index 5fe4bfa..8f0ea97 100644 --- a/puphpet/puppet/modules/mongodb/spec/classes/client_install_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/classes/client_install_spec.rb @@ -4,7 +4,7 @@ describe 'it should create package' do let(:pre_condition) { ["class mongodb::client { $ensure = true $package_name = 'mongodb' }", "include mongodb::client"]} it { - should contain_package('mongodb_client').with({ + is_expected.to contain_package('mongodb_client').with({ :ensure => 'present', :name => 'mongodb', }) diff --git a/puphpet/puppet/modules/mongodb/spec/classes/mongos_config_spec.rb b/puphpet/puppet/modules/mongodb/spec/classes/mongos_config_spec.rb new file mode 100644 index 0000000..d998759 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/classes/mongos_config_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe 'mongodb::mongos::config' do + + describe 'it should create mongos configuration file' do + + let :facts do + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + } + end + + let :pre_condition do + "class { 'mongodb::mongos': }" + end + + it { + is_expected.to contain_file('/etc/mongodb-shard.conf') + } + end + +end diff --git a/puphpet/puppet/modules/mongodb/spec/classes/mongos_install_spec.rb b/puphpet/puppet/modules/mongodb/spec/classes/mongos_install_spec.rb new file mode 100644 index 0000000..7410408 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/classes/mongos_install_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe 'mongodb::mongos::install', :type => :class do + + describe 'it should include package' do + + let :facts do + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + } + end + + let :pre_condition do + "class { 'mongodb::mongos': + configdb => ['127.0.0.1:27019'], + package_name => 'mongo-foo', + }" + end + + it { + is_expected.to contain_package('mongodb_mongos').with({ + :ensure => 'present', + :name => 'mongo-foo', + }) + } + end + +end diff --git a/puphpet/puppet/modules/mongodb/spec/classes/mongos_service_spec.rb b/puphpet/puppet/modules/mongodb/spec/classes/mongos_service_spec.rb new file mode 100644 index 0000000..b955829 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/classes/mongos_service_spec.rb @@ -0,0 +1,100 @@ +require 'spec_helper' + +describe 'mongodb::mongos::service', :type => :class do + + context 'on Debian with service_manage set to true' do + let :facts do + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + } + end + + let :pre_condition do + "class { 'mongodb::mongos': + configdb => ['127.0.0.1:27019'], + }" + end + + describe 'include init script' do + it { is_expected.to contain_file('/etc/init.d/mongos') } + end + + describe 'configure the mongos service' do + it { is_expected.to contain_service('mongos') } + end + + end + + context 'on Debian with service_manage set to false' do + let :facts do + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + } + end + + let :pre_condition do + "class { 'mongodb::mongos': + configdb => ['127.0.0.1:27019'], + service_manage => false, + }" + end + + describe 'configure the mongos service' do + it { should_not contain_service('mongos') } + end + + end + + context 'on RedHat with service_manage set to true' do + let :facts do + { + :osfamily => 'RedHat', + :operatingsystem => 'RedHat', + } + end + + let :pre_condition do + "class { 'mongodb::mongos': + configdb => ['127.0.0.1:27019'], + }" + end + + describe 'include mongos sysconfig file' do + it { is_expected.to contain_file('/etc/sysconfig/mongos') } + end + + describe 'include init script' do + it { is_expected.to contain_file('/etc/init.d/mongos') } + end + + describe 'configure the mongos service' do + it { is_expected.to contain_service('mongos') } + end + + end + + context 'on RedHat with service_manage set to false' do + let :facts do + { + :osfamily => 'RedHat', + :operatingsystem => 'RedHat', + } + end + + let :pre_condition do + "class { 'mongodb::mongos': + configdb => ['127.0.0.1:27019'], + service_manage => false, + }" + end + + describe 'configure the mongos service' do + it { should_not contain_service('mongos') } + end + + end + + +end diff --git a/puphpet/puppet/modules/mongodb/spec/classes/mongos_spec.rb b/puphpet/puppet/modules/mongodb/spec/classes/mongos_spec.rb new file mode 100644 index 0000000..0e6d7b3 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/classes/mongos_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe 'mongodb::mongos' do + let :facts do + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + } + end + + let :params do + { + :configdb => ['127.0.0.1:27019'] + } + end + + context 'with defaults' do + it { is_expected.to contain_class('mongodb::mongos::install') } + it { is_expected.to contain_class('mongodb::mongos::config') } + it { is_expected.to contain_class('mongodb::mongos::service') } + end + + context 'when deploying on Solaris' do + let :facts do + { :osfamily => 'Solaris' } + end + it { expect { is_expected.to raise_error(Puppet::Error) } } + end + +end diff --git a/puphpet/puppet/modules/mongodb/spec/classes/repo_spec.rb b/puphpet/puppet/modules/mongodb/spec/classes/repo_spec.rb index aa051e9..eeb0937 100644 --- a/puphpet/puppet/modules/mongodb/spec/classes/repo_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/classes/repo_spec.rb @@ -12,7 +12,7 @@ end it { - should contain_class('mongodb::repo::apt') + is_expected.to contain_class('mongodb::repo::apt') } end @@ -25,8 +25,34 @@ end it { - should contain_class('mongodb::repo::yum') + is_expected.to contain_class('mongodb::repo::yum') } end + context 'when yumrepo has a proxy set' do + let :facts do + { + :osfamily => 'RedHat', + :operatingsystem => 'RedHat', + } + end + let :params do + { + :proxy => 'http://proxy-server:8080', + :proxy_username => 'proxyuser1', + :proxy_password => 'proxypassword1', + } + end + it { + is_expected.to contain_class('mongodb::repo::yum') + } + it do + should contain_yumrepo('mongodb').with({ + 'enabled' => '1', + 'proxy' => 'http://proxy-server:8080', + 'proxy_username' => 'proxyuser1', + 'proxy_password' => 'proxypassword1', + }) + end + end end diff --git a/puphpet/puppet/modules/mongodb/spec/classes/server_config_spec.rb b/puphpet/puppet/modules/mongodb/spec/classes/server_config_spec.rb index db05b88..e630fc1 100644 --- a/puphpet/puppet/modules/mongodb/spec/classes/server_config_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/classes/server_config_spec.rb @@ -3,73 +3,93 @@ describe 'mongodb::server::config', :type => :class do describe 'with preseted variables' do - let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' }", "include mongodb::server"]} + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' }", "include mongodb::server"]} it { - should contain_file('/etc/mongod.conf') + is_expected.to contain_file('/etc/mongod.conf') } end describe 'with default values' do - let(:pre_condition) {[ "class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $ensure = present $user = 'mongod' $group = 'mongod' $port = 29017 $bind_ip = ['0.0.0.0'] $fork = true $logpath ='/var/log/mongo/mongod.log' $logappend = true }", "include mongodb::server" ]} + let(:pre_condition) {[ "class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $create_admin = false $rcfile = '/root/.mongorc.js' $store_creds = true $ensure = present $user = 'mongod' $group = 'mongod' $port = 29017 $bind_ip = ['0.0.0.0'] $fork = true $logpath ='/var/log/mongo/mongod.log' $logappend = true }", "include mongodb::server" ]} it { - should contain_file('/etc/mongod.conf').with({ + is_expected.to contain_file('/etc/mongod.conf').with({ :mode => '0644', :owner => 'root', :group => 'root' }) - should contain_file('/etc/mongod.conf').with_content(/^dbpath=\/var\/lib\/mongo/) - should contain_file('/etc/mongod.conf').with_content(/bind_ip\s=\s0\.0\.0\.0/) - should contain_file('/etc/mongod.conf').with_content(/^port = 29017$/) - should contain_file('/etc/mongod.conf').with_content(/^logappend=true/) - should contain_file('/etc/mongod.conf').with_content(/^logpath=\/var\/log\/mongo\/mongod\.log/) - should contain_file('/etc/mongod.conf').with_content(/^fork=true/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/^dbpath=\/var\/lib\/mongo/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/bind_ip\s=\s0\.0\.0\.0/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/^port = 29017$/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/^logappend=true/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/^logpath=\/var\/log\/mongo\/mongod\.log/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/^fork=true/) + + is_expected.to contain_file('/root/.mongorc.js').with({ :ensure => 'absent' }) } end describe 'with absent ensure' do - let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $ensure = absent }", "include mongodb::server"]} + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = absent }", "include mongodb::server"]} it { - should contain_file('/etc/mongod.conf').with({ :ensure => 'absent' }) + is_expected.to contain_file('/etc/mongod.conf').with({ :ensure => 'absent' }) } end + describe 'when specifying storage_engine' do + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.monogrc.js' $ensure = present $version='3.0.3' $storage_engine = 'SomeEngine' $storage_engine_internal = 'SomeEngine' $user = 'mongod' $group = 'mongod' $port = 29017 $bind_ip = ['0.0.0.0'] $fork = true $logpath ='/var/log/mongo/mongod.log' $logappend = true}", "include mongodb::server"]} + + it { + is_expected.to contain_file('/etc/mongod.conf').with_content(/storage.engine:\sSomeEngine/) + } + end + + describe 'with specific bind_ip values and ipv6' do + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = present $bind_ip = ['127.0.0.1', 'fd00:beef:dead:55::143'] $ipv6 = true }", "include mongodb::server"]} + + it { + is_expected.to contain_file('/etc/mongod.conf').with_content(/bind_ip\s=\s127\.0\.0\.1\,fd00:beef:dead:55::143/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/ipv6=true/) + } + end + describe 'with specific bind_ip values' do - let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $ensure = present $bind_ip = ['127.0.0.1', '10.1.1.13']}", "include mongodb::server"]} + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = present $bind_ip = ['127.0.0.1', '10.1.1.13']}", "include mongodb::server"]} it { - should contain_file('/etc/mongod.conf').with_content(/bind_ip\s=\s127\.0\.0\.1\,10\.1\.1\.13/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/bind_ip\s=\s127\.0\.0\.1\,10\.1\.1\.13/) } end describe 'when specifying auth to true' do - let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $auth = true $dbpath = '/var/lib/mongo' $ensure = present }", "include mongodb::server"]} + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $auth = true $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = present }", "include mongodb::server"]} it { - should contain_file('/etc/mongod.conf').with_content(/^auth=true/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/^auth=true/) + is_expected.to contain_file('/root/.mongorc.js') } end describe 'when specifying set_parameter value' do - let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $set_parameter = 'textSearchEnable=true' $dbpath = '/var/lib/mongo' $ensure = present }", "include mongodb::server"]} + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $set_parameter = 'textSearchEnable=true' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = present }", "include mongodb::server"]} it { - should contain_file('/etc/mongod.conf').with_content(/^setParameter = textSearchEnable=true/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/^setParameter = textSearchEnable=true/) } end describe 'with journal:' do context 'on true with i686 architecture' do - let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $ensure = present $journal = true }", "include mongodb::server"]} + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = present $journal = true }", "include mongodb::server"]} let (:facts) { { :architecture => 'i686' } } it { - should contain_file('/etc/mongod.conf').with_content(/^journal = true/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/^journal = true/) } end end @@ -78,39 +98,62 @@ describe 'with quota to' do context 'true and without quotafiles' do - let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $ensure = present $quota = true }", "include mongodb::server"]} + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = present $quota = true }", "include mongodb::server"]} it { - should contain_file('/etc/mongod.conf').with_content(/^quota = true/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/^quota = true/) } end context 'true and with quotafiles' do - let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $ensure = present $quota = true $quotafiles = 1 }", "include mongodb::server"]} + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = present $quota = true $quotafiles = 1 }", "include mongodb::server"]} it { - should contain_file('/etc/mongod.conf').with_content(/quota = true/) - should contain_file('/etc/mongod.conf').with_content(/quotaFiles = 1/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/quota = true/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/quotaFiles = 1/) } end end describe 'when specifying syslog value' do context 'it should be set to true' do - let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $ensure = present $syslog = true }", "include mongodb::server"]} + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = present $syslog = true }", "include mongodb::server"]} it { - should contain_file('/etc/mongod.conf').with_content(/^syslog = true/) + is_expected.to contain_file('/etc/mongod.conf').with_content(/^syslog = true/) } end context 'if logpath is also set an error should be raised' do - let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $ensure = present $syslog = true $logpath ='/var/log/mongo/mongod.log' }", "include mongodb::server"]} + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = present $syslog = true $logpath ='/var/log/mongo/mongod.log' }", "include mongodb::server"]} it { - expect { should contain_file('/etc/mongod.conf') }.to raise_error(Puppet::Error, /You cannot use syslog with logpath/) + expect { is_expected.to contain_file('/etc/mongod.conf') }.to raise_error(Puppet::Error, /You cannot use syslog with logpath/) } end end + describe 'with store_creds' do + context 'true' do + let(:pre_condition) { ["class mongodb::server { $admin_username = 'admin' $admin_password = 'password' $auth = true $store_creds = true $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = present }", "include mongodb::server"]} + + it { + is_expected.to contain_file('/root/.mongorc.js'). + with_ensure('present'). + with_owner('root'). + with_group('root'). + with_mode('0644'). + with_content(/db.auth\('admin', 'password'\)/) + } + end + + context 'false' do + let(:pre_condition) { ["class mongodb::server { $config = '/etc/mongod.conf' $dbpath = '/var/lib/mongo' $rcfile = '/root/.mongorc.js' $ensure = present $store_creds = false }", "include mongodb::server"]} + + it { + is_expected.to contain_file('/root/.mongorc.js').with_ensure('absent') + } + end + end + end diff --git a/puphpet/puppet/modules/mongodb/spec/classes/server_install_spec.rb b/puphpet/puppet/modules/mongodb/spec/classes/server_install_spec.rb index 5ca01a9..f0c4140 100644 --- a/puphpet/puppet/modules/mongodb/spec/classes/server_install_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/classes/server_install_spec.rb @@ -6,7 +6,7 @@ let(:pre_condition) { ["class mongodb::server { $package_ensure = true $dbpath = '/var/lib/mongo' $user = 'mongodb' $package_name = 'mongodb-server' }", "include mongodb::server"]} it { - should contain_package('mongodb_server').with({ + is_expected.to contain_package('mongodb_server').with({ :ensure => 'present', :name => 'mongodb-server', }) diff --git a/puphpet/puppet/modules/mongodb/spec/classes/server_spec.rb b/puphpet/puppet/modules/mongodb/spec/classes/server_spec.rb index c74e7f0..15f34de 100644 --- a/puphpet/puppet/modules/mongodb/spec/classes/server_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/classes/server_spec.rb @@ -9,15 +9,153 @@ end context 'with defaults' do - it { should contain_class('mongodb::server::install') } - it { should contain_class('mongodb::server::config') } + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('mongodb::server::install'). + that_comes_before('Class[mongodb::server::config]') } + it { is_expected.to contain_class('mongodb::server::config'). + that_notifies('Class[mongodb::server::service]') } + it { is_expected.to contain_class('mongodb::server::service') } + end + + context 'with create_admin => true' do + let(:params) do + { + :create_admin => true, + :admin_username => 'admin', + :admin_password => 'password' + } + end + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('mongodb::server::install'). + that_comes_before('Class[mongodb::server::config]') } + it { is_expected.to contain_class('mongodb::server::config'). + that_notifies('Class[mongodb::server::service]') } + it { is_expected.to contain_class('mongodb::server::service') } + + it { + is_expected.to contain_mongodb__db('admin').with({ + 'user' => 'admin', + 'password' => 'password', + 'roles' => ["userAdmin", "readWrite", "dbAdmin", "dbAdminAnyDatabase", + "readAnyDatabase", "readWriteAnyDatabase", "userAdminAnyDatabase", + "clusterAdmin", "clusterManager", "clusterMonitor", "hostManager", + "root", "restore"] + }).that_requires('Anchor[mongodb::server::end]') + } end context 'when deploying on Solaris' do let :facts do { :osfamily => 'Solaris' } end - it { expect { should raise_error(Puppet::Error) } } + it { expect { is_expected.to raise_error(Puppet::Error) } } end -end \ No newline at end of file + context 'setting nohttpinterface' do + it "isn't set when undef" do + is_expected.to_not contain_file('/etc/mongodb.conf').with_content(/nohttpinterface/) + end + context "sets nohttpinterface to true when true" do + let(:params) do + { :nohttpinterface => true, } + end + it { is_expected.to contain_file('/etc/mongodb.conf').with_content(/nohttpinterface = true/) } + end + context "sets nohttpinterface to false when false" do + let(:params) do + { :nohttpinterface => false, } + end + it { is_expected.to contain_file('/etc/mongodb.conf').with_content(/nohttpinterface = false/) } + end + context "on >= 2.6" do + let(:pre_condition) do + "class { 'mongodb::globals': version => '2.6.6', }" + end + it "isn't set when undef" do + is_expected.to_not contain_file('/etc/mongodb.conf').with_content(/net\.http\.enabled/) + end + context "sets net.http.enabled false when true" do + let(:params) do + { :nohttpinterface => true, } + end + it { is_expected.to contain_file('/etc/mongodb.conf').with_content(/net\.http\.enabled: false/) } + end + context "sets net.http.enabled true when false" do + let(:params) do + { :nohttpinterface => false, } + end + it { is_expected.to contain_file('/etc/mongodb.conf').with_content(/net\.http\.enabled: true/) } + end + end + end + + context 'when setting up replicasets' do + context 'should fail if providing both replica_sets and replset_members' do + let(:params) do + { + :replset => 'rsTest', + :replset_members => [ + 'mongo1:27017', + 'mongo2:27017', + 'mongo3:27017' + ], + :replica_sets => {} + } + end + + it { expect { is_expected.to raise_error(/Puppet::Error: You can provide either replset_members or replica_sets, not both/) } } + end + + context 'should setup using replica_sets hash' do + let(:rsConf) do + { + 'rsTest' => { + 'members' => [ + 'mongo1:27017', + 'mongo2:27017', + 'mongo3:27017', + ], + 'arbiter' => 'mongo3:27017' + } + } + end + + let(:params) do + { + :replset => 'rsTest', + :replset_config => rsConf + } + end + + it { is_expected.to contain_class('mongodb::replset').with_sets(rsConf) } + end + + context 'should setup using replset_members' do + let(:rsConf) do + { + 'rsTest' => { + 'ensure' => 'present', + 'members' => [ + 'mongo1:27017', + 'mongo2:27017', + 'mongo3:27017' + ] + } + } + end + + let(:params) do + { + :replset => 'rsTest', + :replset_members => [ + 'mongo1:27017', + 'mongo2:27017', + 'mongo3:27017' + ] + } + end + + it { is_expected.to contain_class('mongodb::replset').with_sets(rsConf) } + end + end +end diff --git a/puphpet/puppet/modules/mongodb/spec/defines/db_spec.rb b/puphpet/puppet/modules/mongodb/spec/defines/db_spec.rb index 65a6f10..4d1746b 100644 --- a/puphpet/puppet/modules/mongodb/spec/defines/db_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/defines/db_spec.rb @@ -10,34 +10,31 @@ } it 'should contain mongodb_database with mongodb::server requirement' do - should contain_mongodb_database('testdb')\ - .with_require('Class[Mongodb::Server]') + is_expected.to contain_mongodb_database('testdb') end it 'should contain mongodb_user with mongodb_database requirement' do - should contain_mongodb_user('testuser')\ - .with_require('Mongodb_database[testdb]') - end - - it 'should contain mongodb_user with proper database name' do - should contain_mongodb_user('testuser')\ - .with_database('testdb') + is_expected.to contain_mongodb_user('User testuser on db testdb').with({ + 'username' => 'testuser', + 'database' => 'testdb', + 'require' => 'Mongodb_database[testdb]', + }) end it 'should contain mongodb_user with proper roles' do params.merge!({'roles' => ['testrole1', 'testrole2']}) - should contain_mongodb_user('testuser')\ + is_expected.to contain_mongodb_user('User testuser on db testdb')\ .with_roles(["testrole1", "testrole2"]) end it 'should prefer password_hash instead of password' do params.merge!({'password_hash' => 'securehash'}) - should contain_mongodb_user('testuser')\ + is_expected.to contain_mongodb_user('User testuser on db testdb')\ .with_password_hash('securehash') end it 'should contain mongodb_database with proper tries param' do params.merge!({'tries' => 5}) - should contain_mongodb_database('testdb').with_tries(5) + is_expected.to contain_mongodb_database('testdb').with_tries(5) end end diff --git a/puphpet/puppet/modules/mongodb/spec/spec.opts b/puphpet/puppet/modules/mongodb/spec/spec.opts new file mode 100644 index 0000000..91cd642 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/spec.opts @@ -0,0 +1,6 @@ +--format +s +--colour +--loadby +mtime +--backtrace diff --git a/puphpet/puppet/modules/mongodb/spec/spec_helper.rb b/puphpet/puppet/modules/mongodb/spec/spec_helper.rb index 2c6f566..0b30d1f 100644 --- a/puphpet/puppet/modules/mongodb/spec/spec_helper.rb +++ b/puphpet/puppet/modules/mongodb/spec/spec_helper.rb @@ -1 +1,7 @@ require 'puppetlabs_spec_helper/module_spec_helper' + +RSpec.configure do |config| + config.mock_with :rspec do |c| + c.syntax = :expect + end +end diff --git a/puphpet/puppet/modules/mongodb/spec/spec_helper_acceptance.rb b/puphpet/puppet/modules/mongodb/spec/spec_helper_acceptance.rb index c1c09a9..5e2af52 100755 --- a/puphpet/puppet/modules/mongodb/spec/spec_helper_acceptance.rb +++ b/puphpet/puppet/modules/mongodb/spec/spec_helper_acceptance.rb @@ -26,14 +26,19 @@ # Configure all nodes in nodeset c.before :suite do - puppet_module_install(:source => proj_root, :module_name => 'mongodb') + hosts.each do |host| + copy_module_to(host, :source => proj_root, :module_name => 'mongodb') + end on hosts, 'puppet module install puppetlabs-stdlib' on hosts, 'puppet module install puppetlabs-apt' case fact('osfamily') when 'RedHat' on hosts, 'puppet module install stahnma-epel' apply_manifest_on hosts, 'include epel' + if fact('operatingsystemrelease') =~ /^7/ + on hosts, 'yum install -y iptables-services' + end + on hosts, 'service iptables stop' end - on hosts, 'service iptables stop' end end diff --git a/puphpet/puppet/modules/mongodb/spec/unit/mongodb_password_spec.rb b/puphpet/puppet/modules/mongodb/spec/unit/mongodb_password_spec.rb index 5b0b825..0b92fc3 100644 --- a/puphpet/puppet/modules/mongodb/spec/unit/mongodb_password_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/unit/mongodb_password_spec.rb @@ -8,20 +8,20 @@ let(:scope) { PuppetlabsSpec::PuppetInternals.scope } it 'should exist' do - Puppet::Parser::Functions.function('mongodb_password').should == 'function_mongodb_password' + expect(Puppet::Parser::Functions.function('mongodb_password')).to eq('function_mongodb_password') end it 'should raise a ParseError if there no arguments' do - lambda { scope.function_mongodb_password([]) }.should( raise_error(Puppet::ParseError)) + expect { scope.function_mongodb_password([]) }.to( raise_error(Puppet::ParseError)) end it 'should raise a ParseError if there is more than 2 arguments' do - lambda { scope.function_mongodb_password(%w(foo bar baz)) }.should( raise_error(Puppet::ParseError)) + expect { scope.function_mongodb_password(%w(foo bar baz)) }.to( raise_error(Puppet::ParseError)) end it 'should convert password into a hash' do result = scope.function_mongodb_password(%w(user pass)) - result.should(eq('e0c4a7b97d4db31f5014e9694e567d6b')) + expect(result).to(eq('e0c4a7b97d4db31f5014e9694e567d6b')) end end diff --git a/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_database/mongodb_spec.rb b/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_database/mongodb_spec.rb index 4376ada..e8cfe9c 100644 --- a/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_database/mongodb_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_database/mongodb_spec.rb @@ -1,7 +1,28 @@ require 'spec_helper' +require 'tempfile' describe Puppet::Type.type(:mongodb_database).provider(:mongodb) do + let(:raw_dbs) { + { + "databases" => [ + { + "name" => "admin", + "sizeOnDisk" => 83886080, + "empty" => false + }, { + "name" => "local", + "sizeOnDisk" => 83886080, + "empty" => false + } + ], + "totalSize" => 251658240, + "ok" => 1 + }.to_json + } + + let(:parsed_dbs) { %w(admin local) } + let(:resource) { Puppet::Type.type(:mongodb_database).new( { :ensure => :present, :name => 'new_database', @@ -11,24 +32,40 @@ let(:provider) { resource.provider } + before :each do + tmp = Tempfile.new('test') + @mongodconffile = tmp.path + allow(provider.class).to receive(:get_mongod_conf_file).and_return(@mongodconffile) + provider.class.stubs(:mongo_eval).with('printjson(db.getMongo().getDBs())').returns(raw_dbs) + allow(provider.class).to receive(:db_ismaster).and_return(true) + end + + let(:instance) { provider.class.instances.first } + + describe 'self.instances' do + it 'returns an array of dbs' do + dbs = provider.class.instances.collect {|x| x.name } + expect(parsed_dbs).to match_array(dbs) + end + end + describe 'create' do it 'makes a database' do - provider.expects(:mongo) + provider.expects(:mongo_eval) provider.create end end describe 'destroy' do it 'removes a database' do - provider.expects(:mongo) + provider.expects(:mongo_eval) provider.destroy end end describe 'exists?' do it 'checks if database exists' do - provider.expects(:mongo).at_least(2).returns("db1,new_database,db2") - provider.exists?.should be_true + instance.exists? end end diff --git a/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_replset/mongodb_spec.rb b/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_replset/mongodb_spec.rb index 51b3f9e..b52c124 100644 --- a/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_replset/mongodb_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_replset/mongodb_spec.rb @@ -4,6 +4,7 @@ # require 'spec_helper' +require 'tempfile' describe Puppet::Type.type(:mongodb_replset).provider(:mongo) do @@ -21,21 +22,58 @@ let(:provider) { described_class.new(resource) } describe '#create' do + before :each do + tmp = Tempfile.new('test') + @mongodconffile = tmp.path + allow(provider.class).to receive(:get_mongod_conf_file).and_return(@mongodconffile) + allow(provider.class).to receive(:mongo).and_return(< "Config now saved locally. Should come online in about a minute.", - "ok" => 1 } ) + allow(provider.class).to receive(:get_replset_properties) + allow(provider).to receive(:alive_members).and_return(valid_members) + allow(provider).to receive(:master_host).and_return(false) + expect(provider).to receive('rs_initiate').with("{ _id: \"rs_test\", members: [ { _id: 0, host: \"mongo1:27017\" },{ _id: 1, host: \"mongo2:27017\" },{ _id: 2, host: \"mongo3:27017\" } ] }", "mongo1:27017").and_return({ + "info" => "Config now saved locally. Should come online in about a minute.", + "ok" => 1, + }) + allow(provider).to receive(:db_ismaster).and_return('{"ismaster" : true}') + provider.create + provider.flush + end + + it 'should create a replicaset with arbiter' do + allow(provider.class).to receive(:get_replset_properties) + allow(provider).to receive(:alive_members).and_return(valid_members) + allow(provider).to receive(:master_host).and_return(false) + allow(provider).to receive(:rs_arbiter).and_return('mongo3:27017') + expect(provider).to receive('rs_initiate').with("{ _id: \"rs_test\", members: [ { _id: 0, host: \"mongo1:27017\" },{ _id: 1, host: \"mongo2:27017\" },{ _id: 2, host: \"mongo3:27017\", arbiterOnly: \"true\" } ] }", "mongo1:27017").and_return({ + "info" => "Config now saved locally. Should come online in about a minute.", + "ok" => 1, + }) + allow(provider).to receive(:db_ismaster).and_return('{"ismaster" : true}') provider.create provider.flush end end describe '#exists?' do + before :each do + tmp = Tempfile.new('test') + @mongodconffile = tmp.path + allow(provider.class).to receive(:get_mongod_conf_file).and_return(@mongodconffile) + end + describe 'when the replicaset does not exist' do it 'returns false' do - provider.class.stubs(:mongo).returns(< "rs_test" }) - provider.expects('rs_add').times(2).returns({ 'ok' => 1 }) + allow(provider.class).to receive(:get_replset_properties) + allow(provider).to receive(:rs_status).and_return({ 'set' => 'rs_test' }) + expect(provider).to receive('rs_add').twice.and_return({ 'ok' => 1 }) provider.members=(valid_members) provider.flush end it 'raises an error when the master host is not available' do - provider.stubs(:rs_status).returns({ "set" => "rs_test" }) - provider.stubs(:db_ismaster).returns({ "primary" => false }) + allow(provider).to receive(:rs_status).and_return({ "set" => "rs_test" }) + allow(provider).to receive(:db_ismaster).and_return({ "primary" => false }) provider.members=(valid_members) expect { provider.flush }.to raise_error(Puppet::Error, "Can't find master host for replicaset #{resource[:name]}.") end it 'raises an error when at least one member is not running with --replSet' do - provider.stubs(:rs_status).returns({ "ok" => 0, "errmsg" => "not running with --replSet" }) + allow(provider).to receive(:rs_status).and_return({ "ok" => 0, "errmsg" => "not running with --replSet" }) provider.members=(valid_members) expect { provider.flush }.to raise_error(Puppet::Error, /is not supposed to be part of a replicaset\.$/) end it 'raises an error when at least one member is configured with another replicaset name' do - provider.stubs(:rs_status).returns({ "set" => "rs_another" }) + allow(provider).to receive(:rs_status).and_return({ "set" => "rs_another" }) provider.members=(valid_members) expect { provider.flush }.to raise_error(Puppet::Error, /is already part of another replicaset\.$/) end it 'raises an error when no member is available' do - provider.class.stubs(:mongo_command).raises(Puppet::ExecutionFailure, < :present, + :name => 'rs_test', + :member => 'rs_test/mongo1:27018', + :keys => [], + :provider => :mongo + } + ) + end + + let(:provider) { resource.provider } + let(:instance) { provider.class.instances.first } + + let(:parsed_shards) { %w(rs_test) } + + let(:raw_shards) do + { + "sharding version" => { + "_id" => 1, + "version" => 4, + "minCompatibleVersion" => 4, + "currentVersion" => 5, + "clusterId" => "ObjectId(\'548e9110f3aca177c94c5e49\')" + }, + "shards" => [ + { "_id" => "rs_test", "host" => "rs_test/mongo1:27018" } + ], + "databases" => [ + { "_id" => "admin", "partitioned" => false, "primary" => "config" }, + { "_id" => "test", "partitioned" => false, "primary" => "rs_test" }, + { "_id" => "rs_test", "partitioned" => true, "primary" => "rs_test" } + ] + } + end + + before :each do + provider.class.stubs(:mongo_command).with('sh.status()').returns(raw_shards) + end + + describe 'self.instances' do + + it 'should create a shard' do + shards = provider.class.instances.collect { |x| x.name } + expect(parsed_shards).to match_array(shards) + end + + end + + describe '#create' do + it 'makes a shard' do + provider.expects('sh_addshard').with("rs_test/mongo1:27018").returns( + { "shardAdded" => "rs_test", + "ok" => 1 } + ) + provider.expects('sh_enablesharding').with("rs_test").returns( + { "ok" => 1 } + ) + provider.create + provider.flush + end + end + + describe 'destroy' do + it 'removes a shard' do + end + end + + describe 'exists?' do + it 'checks if shard exists' do + instance.exists? + end + end + +end diff --git a/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_user/mongodb_spec.rb b/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_user/mongodb_spec.rb index 997b6ca..13bb6db 100644 --- a/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_user/mongodb_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/unit/puppet/provider/mongodb_user/mongodb_spec.rb @@ -1,7 +1,17 @@ require 'spec_helper' +require 'json' +require 'tempfile' describe Puppet::Type.type(:mongodb_user).provider(:mongodb) do + let(:raw_users) do + [ + { '_id' => 'admin.root', 'user' => 'root', 'db' => 'admin', 'credentials' => { 'MONGODB-CR' => 'pass' }, 'roles' => [ { 'role' => 'role2', 'db' => 'admin' }, { 'role' => 'role1', 'db' => 'admin' } ] } + ].to_json + end + + let(:parsed_users) { %w(root) } + let(:resource) { Puppet::Type.type(:mongodb_user).new( { :ensure => :present, :name => 'new_user', @@ -14,52 +24,118 @@ let(:provider) { resource.provider } + before :each do + tmp = Tempfile.new('test') + @mongodconffile = tmp.path + allow(provider.class).to receive(:get_mongod_conf_file).and_return(@mongodconffile) + provider.class.stubs(:mongo_eval).with('printjson(db.system.users.find().toArray())').returns(raw_users) + provider.class.stubs(:mongo_version).returns('2.6.x') + allow(provider.class).to receive(:db_ismaster).and_return(true) + end + + let(:instance) { provider.class.instances.first } + + describe 'self.instances' do + it 'returns an array of users' do + usernames = provider.class.instances.collect {|x| x.username } + expect(parsed_users).to match_array(usernames) + end + end + + describe 'empty self.instances from slave' do + it 'doesn`t retrun array of users' do + allow(provider.class).to receive(:db_ismaster).and_return(false) + expect(provider.class.instances).to match_array([]) + end + end + + describe 'create' do it 'creates a user' do - provider.expects(:mongo) + cmd_json=<<-EOS.gsub(/^\s*/, '').gsub(/$\n/, '') + { + "createUser": "new_user", + "pwd": "pass", + "customData": {"createdBy": "Puppet Mongodb_user['new_user']"}, + "roles": ["role1","role2"], + "digestPassword": false + } + EOS + + provider.expects(:mongo_eval).with("db.runCommand(#{cmd_json})", 'new_database') provider.create end end describe 'destroy' do it 'removes a user' do - provider.expects(:mongo) + provider.expects(:mongo_eval).with("db.dropUser('new_user')") provider.destroy end end describe 'exists?' do it 'checks if user exists' do - provider.expects(:mongo).at_least(2).returns("1") - provider.exists?.should be_true + expect(provider.exists?).to eql false end end describe 'password_hash' do it 'returns a password_hash' do - provider.expects(:mongo).returns("pass\n") - provider.password_hash.should == "pass" + expect(instance.password_hash).to eq("pass") end end describe 'password_hash=' do it 'changes a password_hash' do - provider.expects(:mongo) + cmd_json=<<-EOS.gsub(/^\s*/, '').gsub(/$\n/, '') + { + "updateUser": "new_user", + "pwd": "pass", + "digestPassword": false + } + EOS + provider.expects(:mongo_eval). + with("db.runCommand(#{cmd_json})", 'new_database') provider.password_hash=("newpass") end end describe 'roles' do it 'returns a sorted roles' do - provider.expects(:mongo).returns("role2,role1\n") - provider.roles.should == ['role1','role2'] + expect(instance.roles).to eq(['role1', 'role2']) end end describe 'roles=' do - it 'changes a roles' do - provider.expects(:mongo) - provider.roles=(['role3','role4']) + it 'changes nothing' do + resource.provider.set(:name => 'new_user', :ensure => :present, :roles => ['role1','role2']) + provider.expects(:mongo_eval).times(0) + provider.roles=(['role1', 'role2']) + end + + it 'grant a role' do + resource.provider.set(:name => 'new_user', :ensure => :present, :roles => ['role1','role2']) + provider.expects(:mongo_eval). + with("db.getSiblingDB('new_database').grantRolesToUser('new_user', [\"role3\"])") + provider.roles=(['role1', 'role2', 'role3']) + end + + it 'revokes a role' do + resource.provider.set(:name => 'new_user', :ensure => :present, :roles => ['role1','role2']) + provider.expects(:mongo_eval). + with("db.getSiblingDB('new_database').revokeRolesFromUser('new_user', [\"role1\"])") + provider.roles=(['role2']) + end + + it 'exchanges a role' do + resource.provider.set(:name => 'new_user', :ensure => :present, :roles => ['role1','role2']) + provider.expects(:mongo_eval). + with("db.getSiblingDB('new_database').revokeRolesFromUser('new_user', [\"role1\"])") + provider.expects(:mongo_eval). + with("db.getSiblingDB('new_database').grantRolesToUser('new_user', [\"role3\"])") + + provider.roles=(['role2', 'role3']) end end diff --git a/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_database_spec.rb b/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_database_spec.rb index 245a1be..6939966 100644 --- a/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_database_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_database_spec.rb @@ -7,12 +7,12 @@ end it 'should accept a database name' do - @db[:name].should == 'test' + expect(@db[:name]).to eq('test') end it 'should accept a tries parameter' do @db[:tries] = 5 - @db[:tries].should == 5 + expect(@db[:tries]).to eq(5) end it 'should require a name' do diff --git a/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_replset_spec.rb b/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_replset_spec.rb index f9b72d4..43fb8a8 100644 --- a/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_replset_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_replset_spec.rb @@ -11,12 +11,12 @@ end it 'should accept a replica set name' do - @replset[:name].should == 'test' + expect(@replset[:name]).to eq('test') end it 'should accept a members array' do @replset[:members] = ['mongo1:27017', 'mongo2:27017'] - @replset[:members].should == ['mongo1:27017', 'mongo2:27017'] + expect(@replset[:members]).to eq(['mongo1:27017', 'mongo2:27017']) end it 'should require a name' do diff --git a/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_shard_spec.rb b/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_shard_spec.rb new file mode 100644 index 0000000..206a58f --- /dev/null +++ b/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_shard_spec.rb @@ -0,0 +1,29 @@ +require 'puppet' +require 'puppet/type/mongodb_shard' +describe Puppet::Type.type(:mongodb_shard) do + + before :each do + @shard = Puppet::Type.type(:mongodb_shard).new(:name => 'test') + end + + it 'should accept a shard name' do + expect(@shard[:name]).to eq('test') + end + + it 'should accept a member' do + @shard[:member] = 'rs_test/mongo1:27017' + expect(@shard[:member]).to eq('rs_test/mongo1:27017') + end + + it 'should accept a keys array' do + @shard[:keys] = [{'foo.bar' => {'name' => 1}}] + expect(@shard[:keys]).to eq([{'foo.bar' => {'name' => 1}}]) + end + + it 'should require a name' do + expect { + Puppet::Type.type(:mongodb_shard).new({}) + }.to raise_error(Puppet::Error, 'Title or name must be provided') + end + +end diff --git a/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_user_spec.rb b/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_user_spec.rb index c822265..26a8c49 100644 --- a/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_user_spec.rb +++ b/puphpet/puppet/modules/mongodb/spec/unit/puppet/type/mongodb_user_spec.rb @@ -10,30 +10,30 @@ end it 'should accept a user name' do - @user[:name].should == 'test' + expect(@user[:name]).to eq('test') end it 'should accept a database name' do - @user[:database].should == 'testdb' + expect(@user[:database]).to eq('testdb') end it 'should accept a tries parameter' do @user[:tries] = 5 - @user[:tries].should == 5 + expect(@user[:tries]).to eq(5) end it 'should accept a password' do @user[:password_hash] = 'foo' - @user[:password_hash].should == 'foo' + expect(@user[:password_hash]).to eq('foo') end it 'should use default role' do - @user[:roles].should == ['dbAdmin'] + expect(@user[:roles]).to eq(['dbAdmin']) end it 'should accept a roles array' do @user[:roles] = ['role1', 'role2'] - @user[:roles].should == ['role1', 'role2'] + expect(@user[:roles]).to eq(['role1', 'role2']) end it 'should require a name' do @@ -61,7 +61,7 @@ :database => 'testdb', :password_hash => 'pass', :roles => ['b', 'a']) - @user[:roles].should == ['a', 'b'] + expect(@user[:roles]).to eq(['a', 'b']) end end diff --git a/puphpet/puppet/modules/mongodb/templates/mongodb-shard.conf.erb b/puphpet/puppet/modules/mongodb/templates/mongodb-shard.conf.erb new file mode 100644 index 0000000..5825ddc --- /dev/null +++ b/puphpet/puppet/modules/mongodb/templates/mongodb-shard.conf.erb @@ -0,0 +1,21 @@ +<% if @configdb -%> +configdb = <%= Array(@configdb).join(',') %> +<% end -%> +<% if @bind_ip -%> +bind_ip = <%= @bind_ip %> +<% end -%> +<% if @port -%> +port = <%= @port %> +<% end -%> +<% if @fork -%> +fork = <%= @fork %> +<% end -%> +<% if @pidfilepath -%> +pidfilepath = <%= @pidfilepath %> +<% end -%> +<% if @logpath -%> +logpath = <%= @logpath %> +<% end -%> +<% if @unixsocketprefix -%> +unixSocketPrefix = <%= @unixsocketprefix %> +<% end -%> diff --git a/puphpet/puppet/modules/mongodb/templates/mongodb.conf.2.6.erb b/puphpet/puppet/modules/mongodb/templates/mongodb.conf.2.6.erb new file mode 100644 index 0000000..293f809 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/templates/mongodb.conf.2.6.erb @@ -0,0 +1,137 @@ +# mongo.conf - generated from Puppet + +# System Log + +<% if @logpath -%> +systemLog.path: <%= @logpath %> +systemLog.destination: file +<% if @logappend -%> +systemLog.logAppend: <%= @logappend %> +<% end -%> +<% elsif @syslog -%> +systemLog.destination: syslog +<% end -%> +<% if @verbose -%> +systemLog.quiet: false +<% else -%> +systemLog.quiet: true +<% end -%> +<% if @verbositylevel == "v" -%> +systemLog.verbosity: 1 +<% elsif @verbositylevel == "vv" -%> +systemLog.verbosity: 2 +<% elsif @verbositylevel == "vvv" -%> +systemLog.verbosity: 3 +<% elsif @verbositylevel == "vvvv" -%> +systemLog.verbosity: 4 +<% elsif @verbositylevel == "vvvvv" -%> +systemLog.verbosity: 5 +<% end -%> + +#Process Management +<% if @fork -%> +processManagement.fork: <%= @fork %> +<% end -%> +<% if @pidfilepath -%> +processManagement.pidFilePath: <%= @pidfilepath %> +<% end -%> + +#Storage +storage.dbPath: <%= @dbpath %> +<% if @nojournal -%> +storage.journal.enabled: false +<% elsif @journal -%> +storage.journal.enabled: true +<% end -%> +<% if @noprealloc -%> +storage.preallocDataFiles: <%= !@noprealloc %> +<% end -%> +<% if @nssize -%> +storage.nsSize: <%= @nssize %> +<% end -%> +<% if @directoryperdb -%> +storage.directoryPerDB: <%= @directoryperdb %> +<% end -%> +<% if @smallfiles -%> +storage.smallFiles: <%= @smallfiles %> +<% end -%> +<% if @quota -%> +storage.quota.enforced: <%= @quota %> +<% if @quotafiles -%> +storage.quota.maxFilesPerDB: <%= @quotafiles %> +<% end -%> +<% end -%> +<% if @storage_engine_internal -%> +storage.engine: <%= @storage_engine_internal %> +<% end -%> + + +#Security +<% if @auth -%> +security.authorization: enabled +<% else -%> +security.authorization: disabled +<% end -%> +<% if @keyfile -%> +security.keyFile: <%= @keyfile %> +<% end -%> +<% if @noscripting -%> +security.javascriptEnabled: <%= @noscripting %> +<% end -%> + + +# Net +<% if @ipv6 -%> +net.ipv6=<%= @ipv6 %> +<% end -%> +<% if @bind_ip -%> +net.bindIp: <%= Array(@bind_ip).join(',') %> +<% end -%> +<% if @port -%> +net.port: <%= @port %> +<% end -%> +<% if @objcheck -%> +net.wireObjectCheck: <%= @objcheck %> +<% end -%> +<% if @rest -%> +net.http.RESTInterfaceEnabled: true +<% end -%> +<% if @maxconns -%> +net.maxIncomingConnections: <%= @maxconns %> +<% end -%> +<% if ! @nohttpinterface.nil? -%> +net.http.enabled: <%= ! @nohttpinterface %> +<% end -%> + +#Replication +<% if @replset -%> +replication.replSetName: <%= @replset %> +<% end -%> +<% if @oplog_size -%> +replication.oplogSizeMB: <%= @oplog_size %> +<% end -%> + +# Sharding +<% if @configsvr -%> +sharding.clusterRole: configsvr +<% end -%> +<% if @shardsvr -%> +sharding.clusterRole: shardsvr +<% end -%> + +#Operation Profiling +<% if @profile == "0" -%> +operationProfiling.mode: off +<% elsif @profile == "1" -%> +operationProfiling.mode: slowOp +<% elsif @profile == "2" -%> +operationProfiling.mode: all +<% end -%> +<% if @slowms -%> +operationProfiling.slowOpThresholdMs: <%= @slowms %> +<% end -%> + + +<% if @set_parameter -%> +setParameter: <%= @set_parameter %> +<% end -%> diff --git a/puphpet/puppet/modules/mongodb/templates/mongodb.conf.erb b/puphpet/puppet/modules/mongodb/templates/mongodb.conf.erb index 85d8105..35ecc2e 100644 --- a/puphpet/puppet/modules/mongodb/templates/mongodb.conf.erb +++ b/puphpet/puppet/modules/mongodb/templates/mongodb.conf.erb @@ -8,6 +8,9 @@ logpath=<%= @logpath %> logappend=<%= @logappend %> <% end -%> <% end -%> +<% if @ipv6 -%> +ipv6=<%= @ipv6 %> +<% end -%> <% if @bind_ip -%> # Set this option to configure the mongod or mongos process to bind to and # listen for connections from applications on this address. @@ -18,11 +21,13 @@ bind_ip = <%= Array(@bind_ip).join(',') %> # fork and run in background fork=<%= @fork %> <% end -%> +<% if @port -%> port = <%= @port %> +<% end -%> dbpath=<%= @dbpath %> <% if @pidfilepath -%> # location of pidfile -pidfilepath = <%= @pidfilepath %> +pidfilepath=<%= @pidfilepath %> <% end -%> <% if @nojournal and not @journal -%> # Disables write-ahead journaling @@ -82,7 +87,7 @@ oplogSize = <%= @oplog_size %> # Ignore query hints nohints = <%= @nohints %> <% end -%> -<% if @nohttpinterface -%> +<% if ! @nohttpinterface.nil? -%> # Disable the HTTP interface (Defaults to localhost:27018). nohttpinterface = <%= @nohttpinterface %> <% end -%> @@ -133,6 +138,14 @@ master = <%= @master %> # files in a distinct folder. directoryperdb = <%= @directoryperdb %> <% end -%> +<% if @configsvr -%> +# Is the mongod instance a configuration server +configsvr = <%= @configsvr %> +<% end -%> +<% if @shardsvr -%> +# Is the mongod instance a shard server +shardsvr = <%= @shardsvr %> +<% end -%> <% if @replset -%> # Configure ReplicaSet membership replSet = <%= @replset %> @@ -161,12 +174,17 @@ slowms = <%= @slowms %> # Specify the path to a key file to store authentication information. keyFile = <%= @keyfile %> <% end -%> -<% if @directoryperdb -%> -directoryperdb = <%= @directoryperdb %> -<% end -%> <% if @set_parameter -%> setParameter = <%= @set_parameter %> <% end -%> <% if @syslog -%> syslog = <%= @syslog %> <% end -%> +<% if @quiet -%> +quiet = <%= @quiet %> +<% end -%> +<% if @ssl -%> +sslOnNormalPorts = true +sslPEMKeyFile = <%= @ssl_key %> +sslCAFile = <%= @ssl_ca %> +<% end -%> diff --git a/puphpet/puppet/modules/mongodb/templates/mongorc.js.erb b/puphpet/puppet/modules/mongodb/templates/mongorc.js.erb new file mode 100644 index 0000000..d9b46c3 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/templates/mongorc.js.erb @@ -0,0 +1,27 @@ +function authRequired() { + try { + if (db.serverCmdLineOpts().code == 13) { + return true; + } + return false; + } + catch (err) { + return false; + } +} + +if (authRequired()) { + try { +<% if @replset -%> + rs.slaveOk() +<% end -%> + var prev_db = db + db = db.getSiblingDB('admin') + db.auth('<%= @admin_username %>', '<%= @admin_password %>') + db = db.getSiblingDB(prev_db) + } + catch (err) { + // This isn't catching authentication errors as I'd expect... + return; + } +} diff --git a/puphpet/puppet/modules/mongodb/templates/mongos/Debian/mongos.erb b/puphpet/puppet/modules/mongodb/templates/mongos/Debian/mongos.erb new file mode 100644 index 0000000..98dada2 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/templates/mongos/Debian/mongos.erb @@ -0,0 +1,266 @@ +#!/bin/sh +# +# init.d script with LSB support. +# +# Copyright (c) 2007 Javier Fernandez-Sanguino +# +# This is free software; you may redistribute it and/or modify +# it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2, +# or (at your option) any later version. +# +# This is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License with +# the Debian operating system, in /usr/share/common-licenses/GPL; if +# not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA +# +### BEGIN INIT INFO +# Provides: mongos +# Required-Start: $network $local_fs $remote_fs +# Required-Stop: $network $local_fs $remote_fs +# Should-Start: $named +# Should-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: An object/document-oriented database +# Description: MongoDB is a high-performance, open source, schema-free +# document-oriented data store that's easy to deploy, manage +# and use. It's network accessible, written in C++ and offers +# the following features: +# +# * Collection oriented storage - easy storage of object- +# style data +# * Full index support, including on inner objects +# * Query profiling +# * Replication and fail-over support +# * Efficient storage of binary data including large +# objects (e.g. videos) +# * Automatic partitioning for cloud-level scalability +# +# High performance, scalability, and reasonable depth of +# functionality are the goals for the project. +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/bin/mongos +DESC=database + +NAME=mongos +# Defaults. Can be overridden by the /etc/default/$NAME +# Other configuration options are located in $CONF file. See here for more: +# http://dochub.mongodb.org/core/configurationoptions +CONF=/etc/mongodb-shard.conf +PIDFILE=/var/run/$NAME.pid +ENABLE_MONGOD=yes + +# Include mongodb defaults if available +if [ -f /etc/default/$NAME ] ; then + . /etc/default/$NAME +fi + +# Handle NUMA access to CPUs (SERVER-3574) +# This verifies the existence of numactl as well as testing that the command works +NUMACTL_ARGS="--interleave=all" +if which numactl >/dev/null 2>/dev/null && numactl $NUMACTL_ARGS ls / >/dev/null 2>/dev/null +then + NUMACTL="`which numactl` -- $NUMACTL_ARGS" + DAEMON_OPTS=${DAEMON_OPTS:-"--config $CONF"} +else + NUMACTL="" + DAEMON_OPTS="-- "${DAEMON_OPTS:-"--config $CONF"} +fi + +if test ! -x $DAEMON; then + echo "Could not find $DAEMON" + exit 0 +fi + +if test "x$ENABLE_MONGOD" != "xyes"; then + exit 0 +fi + +. /lib/lsb/init-functions + +STARTTIME=1 +DIETIME=10 # Time to wait for the server to die, in seconds + # If this value is set too low you might not + # let some servers to die gracefully and + # 'restart' will not work + +DAEMONUSER=${DAEMONUSER:-mongodb} + +set -e + +running_pid() { +# Check if a given process pid's cmdline matches a given name + pid=$1 + name=$2 + [ -z "$pid" ] && return 1 + [ ! -d /proc/$pid ] && return 1 + cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1` + # Is this the expected server + [ "$cmd" != "$name" ] && return 1 + return 0 +} + +running() { +# Check if the process is running looking at /proc +# (works for all users) + + # No pidfile, probably no daemon present + [ ! -f "$PIDFILE" ] && return 1 + pid=`cat $PIDFILE` + running_pid $pid $DAEMON || return 1 + return 0 +} + +start_server() { + # Recommended ulimit values for mongod or mongos + # See http://docs.mongodb.org/manual/reference/ulimit/#recommended-settings + # + ulimit -f unlimited + ulimit -t unlimited + ulimit -v unlimited + ulimit -n 64000 + ulimit -m unlimited + + # In dash, ulimit takes -p for maximum user processes + # In bash, it's -u + if readlink /proc/$$/exe | grep -q dash + then + ulimit -p 32000 + else + ulimit -u 32000 + fi + + # Start the process using the wrapper + start-stop-daemon --background --start --quiet --pidfile $PIDFILE \ + --make-pidfile --chuid $DAEMONUSER \ + --exec $NUMACTL $DAEMON $DAEMON_OPTS + errcode=$? + return $errcode +} + +stop_server() { +# Stop the process using the wrapper + start-stop-daemon --stop --quiet --pidfile $PIDFILE \ + --retry 300 \ + --user $DAEMONUSER \ + --exec $DAEMON + errcode=$? + return $errcode +} + +force_stop() { +# Force the process to die killing it manually + [ ! -e "$PIDFILE" ] && return + if running ; then + kill -15 $pid + # Is it really dead? + sleep "$DIETIME"s + if running ; then + kill -9 $pid + sleep "$DIETIME"s + if running ; then + echo "Cannot kill $NAME (pid=$pid)!" + exit 1 + fi + fi + fi + rm -f $PIDFILE +} + + +case "$1" in + start) + log_daemon_msg "Starting $DESC" "$NAME" + # Check if it's running first + if running ; then + log_progress_msg "apparently already running" + log_end_msg 0 + exit 0 + fi + if start_server ; then + # NOTE: Some servers might die some time after they start, + # this code will detect this issue if STARTTIME is set + # to a reasonable value + [ -n "$STARTTIME" ] && sleep $STARTTIME # Wait some time + if running ; then + # It's ok, the server started and is running + log_end_msg 0 + else + # It is not running after we did start + log_end_msg 1 + fi + else + # Either we could not start it + log_end_msg 1 + fi + ;; + stop) + log_daemon_msg "Stopping $DESC" "$NAME" + if running ; then + # Only stop the server if we see it running + errcode=0 + stop_server || errcode=$? + log_end_msg $errcode + else + # If it's not running don't do anything + log_progress_msg "apparently not running" + log_end_msg 0 + exit 0 + fi + ;; + force-stop) + # First try to stop gracefully the program + $0 stop + if running; then + # If it's still running try to kill it more forcefully + log_daemon_msg "Stopping (force) $DESC" "$NAME" + errcode=0 + force_stop || errcode=$? + log_end_msg $errcode + fi + ;; + restart|force-reload) + log_daemon_msg "Restarting $DESC" "$NAME" + errcode=0 + stop_server || errcode=$? + # Wait some sensible amount, some server need this + [ -n "$DIETIME" ] && sleep $DIETIME + start_server || errcode=$? + [ -n "$STARTTIME" ] && sleep $STARTTIME + running || errcode=$? + log_end_msg $errcode + ;; + status) + + log_daemon_msg "Checking status of $DESC" "$NAME" + if running ; then + log_progress_msg "running" + log_end_msg 0 + else + log_progress_msg "apparently not running" + log_end_msg 1 + exit 1 + fi + ;; + # MongoDB can't reload its configuration. + reload) + log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon" + log_warning_msg "cannot re-read the config file (use restart)." + ;; + + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|force-stop|restart|force-reload|status}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/puphpet/puppet/modules/mongodb/templates/mongos/RedHat/mongos.erb b/puphpet/puppet/modules/mongodb/templates/mongos/RedHat/mongos.erb new file mode 100644 index 0000000..757175b --- /dev/null +++ b/puphpet/puppet/modules/mongodb/templates/mongos/RedHat/mongos.erb @@ -0,0 +1,106 @@ +#!/bin/bash + +# mongos - Startup script for mongos + +# chkconfig: 35 85 15 +# description: Mongo Router Process for sharding +# processname: mongos +# config: /etc/mongodb-shard.conf +# pidfile: /var/run/mongodb/mongos.pid + +. /etc/rc.d/init.d/functions + +# mongos will read mongodb-shard.conf for configuration settings + +# Add variable to support multiple instances of mongos +# The instance name is by default the name of this init script +# In this way another instance can be created by just copying this init script +# and creating a config file with the same name and a .conf extension +# For Example: +# /etc/init.d/mongos2 +# /etc/mongos2.conf +# Optionally also create a sysconfig file to override env variables below +# /etc/sysconfig/mongos2 +INSTANCE=`basename $0` + +# By default OPTIONS just points to the /etc/mongod.conf config file +# This can be overriden in /etc/sysconfig/mongod +OPTIONS=" -f /etc/mongodb-shard.conf" + +PID_PATH=/var/run/mongodb +PID_FILE=${PID_PATH}/${INSTANCE}.pid +MONGO_BIN=/usr/bin/mongos +MONGO_USER=<%=@user%> +MONGO_GROUP=<%=@group%> +MONGO_ULIMIT=12000 +MONGO_LOCK_FILE=/var/lock/subsys/${INSTANCE} + +# Source sysconfig options so that above values can be overriden +SYSCONFIG="/etc/sysconfig/${INSTANCE}" +if [ -f "$SYSCONFIG" ]; then + . "$SYSCONFIG" || true +fi + +# Create mongo pids path if it does not exist +if [ ! -d "${PID_PATH}" ]; then + mkdir -p "${PID_PATH}" + chown "${MONGO_USER}:${MONGO_GROUP}" "${PID_PATH}" +fi + +start() +{ + echo -n $"Starting ${INSTANCE}: " + ulimit -n $MONGO_ULIMIT + touch ${PID_FILE} + touch '/var/log/mongodb/mongodb-shard.log' + chown "${MONGO_USER}:${MONGO_GROUP}" "${PID_FILE}" + chown "${MONGO_USER}:${MONGO_GROUP}" '/var/log/mongodb/mongodb-shard.log' + daemon --user "$MONGO_USER" --pidfile $PID_FILE "$MONGO_BIN $OPTIONS --pidfilepath=$PID_FILE >>/var/log/mongodb/mongodb-shard.log 2>&1 &" + RETVAL=$? + echo + [ $RETVAL -eq 0 ] && touch $MONGO_LOCK_FILE + return $RETVAL +} + +stop() +{ + echo -n $"Stopping ${INSTANCE}: " + killproc -p $PID_FILE -t30 -TERM $MONGO_BIN + RETVAL=$? + echo + [ $RETVAL -eq 0 ] && rm -f $MONGO_LOCK_FILE + [ $RETVAL -eq 0 ] && rm -f $PID_FILE + return $RETVAL +} + +restart () { + stop + # TODO need to wait for process to stop before continuing + start +} + +RETVAL=0 + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart|reload|force-reload) + restart + ;; + condrestart) + [ -f $MONGO_LOCK_FILE ] && restart || : + ;; + status) + status -p $PID_FILE $MONGO_BIN + RETVAL=$? + ;; + *) + echo "Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart}" + RETVAL=1 +esac + +exit $RETVAL diff --git a/puphpet/puppet/modules/mongodb/tests/client.pp b/puphpet/puppet/modules/mongodb/tests/client.pp new file mode 100644 index 0000000..061c8c1 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/tests/client.pp @@ -0,0 +1,2 @@ +class { '::mongodb::globals': manage_package_repo => true }-> +class { '::mongodb::client': } diff --git a/puphpet/puppet/modules/mongodb/tests/globals.pp b/puphpet/puppet/modules/mongodb/tests/globals.pp index 8166214..1de72bc 100644 --- a/puphpet/puppet/modules/mongodb/tests/globals.pp +++ b/puphpet/puppet/modules/mongodb/tests/globals.pp @@ -1,3 +1,3 @@ -class { 'mongodb::globals': +class { '::mongodb::globals': manage_package_repo => true } diff --git a/puphpet/puppet/modules/mongodb/tests/replicaset.pp b/puphpet/puppet/modules/mongodb/tests/replicaset.pp index a758b8d..61aa721 100644 --- a/puphpet/puppet/modules/mongodb/tests/replicaset.pp +++ b/puphpet/puppet/modules/mongodb/tests/replicaset.pp @@ -7,10 +7,8 @@ bind_ip => ['0.0.0.0'], replset => 'rsmain' } -} - -node /mongo1/ inherits default { mongodb_replset{'rsmain': - members => ['mongo1:27017', 'mongo2:27017', 'mongo3:27017'] + members => ['mongo1:27017', 'mongo2:27017', 'mongo3:27017' ], + arbiter => 'mongo3:27017', } } diff --git a/puphpet/puppet/modules/mongodb/tests/server.pp b/puphpet/puppet/modules/mongodb/tests/server.pp index 95106eb..32d1230 100644 --- a/puphpet/puppet/modules/mongodb/tests/server.pp +++ b/puphpet/puppet/modules/mongodb/tests/server.pp @@ -1,2 +1,2 @@ -class { 'mongodb::globals': manage_package_repo => true }-> -class { 'mongodb::server': } +class { '::mongodb::globals': manage_package_repo => true }-> +class { '::mongodb::server': } diff --git a/puphpet/puppet/modules/mongodb/tests/sharding.pp b/puphpet/puppet/modules/mongodb/tests/sharding.pp new file mode 100644 index 0000000..0470ae8 --- /dev/null +++ b/puphpet/puppet/modules/mongodb/tests/sharding.pp @@ -0,0 +1,59 @@ +node 'mongos' { + + class {'::mongodb::globals': + manage_package_repo => true, + }-> + class {'::mongodb::server': + configsvr => true, + bind_ip => $::ipaddress, + }-> + class {'::mongodb::client': + }-> + class {'::mongodb::mongos': + configdb => ["${::ipaddress}:27019"], + }-> + mongodb_shard { 'rs1' : + member => 'rs1/mongod1:27018', + keys => [{ + 'rs1.foo' => { + 'name' => 1 + } + }], + } + +} + +node 'mongod1' { + + class {'::mongodb::globals': + manage_package_repo => true, + }-> + class {'::mongodb::server': + shardsvr => true, + replset => 'rs1', + bind_ip => $::ipaddress, + }-> + class {'::mongodb::client': + } + mongodb_replset{'rs1': + members => ['mongod1:27018', 'mongod2:27018'], + } +} + +node 'mongod2' { + + class {'::mongodb::globals': + manage_package_repo => true, + }-> + class {'::mongodb::server': + shardsvr => true, + replset => 'rs1', + bind_ip => $::ipaddress, + }-> + class {'::mongodb::client': + } + mongodb_replset{'rs1': + members => ['mongod1:27018', 'mongod2:27018'], + } + +} diff --git a/puphpet/puppet/modules/mysql/.gitignore b/puphpet/puppet/modules/mysql/.gitignore new file mode 100644 index 0000000..b5db85e --- /dev/null +++ b/puphpet/puppet/modules/mysql/.gitignore @@ -0,0 +1,9 @@ +pkg/ +Gemfile.lock +vendor/ +spec/fixtures/ +.vagrant/ +.bundle/ +coverage/ +.idea/ +*.iml diff --git a/puphpet/puppet/modules/nginx/.gitignore b/puphpet/puppet/modules/nginx/.gitignore new file mode 100644 index 0000000..91807af --- /dev/null +++ b/puphpet/puppet/modules/nginx/.gitignore @@ -0,0 +1,9 @@ +files/server_test.crt +files/server_test.pem +pkg/ +.librarian/ +.tmp/ +pkg/ +Gemfile.lock +spec/fixtures/ +/metadata.json diff --git a/puphpet/puppet/modules/nginx/manifests/resource/location.pp b/puphpet/puppet/modules/nginx/manifests/resource/location.pp index 5bd7c16..4f51401 100644 --- a/puphpet/puppet/modules/nginx/manifests/resource/location.pp +++ b/puphpet/puppet/modules/nginx/manifests/resource/location.pp @@ -79,6 +79,8 @@ # [*priority*] - Location priority. Default: 500. User priority # 401-499, 501-599. If the priority is higher than the default priority, # the location will be defined after root, or before root. +# [*set*] - An array of variables to set +# [*rewrites*] - Rewrite rules for the location # # # Actions: @@ -151,7 +153,9 @@ $auth_basic = undef, $auth_basic_user_file = undef, $rewrite_rules = [], - $priority = 500 + $rewrites = {}, + $priority = 500, + $set = [], ) { include nginx::params @@ -265,6 +269,7 @@ if ($priority < 401) or ($priority > 899) { fail('$priority must be in the range 401-899.') } + validate_hash($rewrites) # # Shared Variables $ensure_real = $ensure ? { @@ -285,7 +290,7 @@ if (($www_root == undef) and ($proxy == undef) and ($location_alias == undef) and ($stub_status == undef) and ($fastcgi == undef) and ($location_custom_cfg == undef)) { fail('Cannot create a location reference without a www_root, proxy, location_alias, fastcgi, stub_status, or location_custom_cfg defined') } - if (($www_root != undef) and ($proxy != undef)) { + if (($www_root != undef) and ($proxy != undef) and $proxy_redirect != 'off' and $proxy_set_header == undef) { fail('Cannot define both directory and proxy in a virtual host') } @@ -321,6 +326,7 @@ target => $config_file, content => join([ template('nginx/vhost/location_header.erb'), + template('nginx/vhost/locations/set.erb'), $content_real, template('nginx/vhost/location_footer.erb') ], ''), @@ -338,6 +344,7 @@ target => $config_file, content => join([ template('nginx/vhost/location_header.erb'), + template('nginx/vhost/locations/set.erb'), $content_real, template('nginx/vhost/location_footer.erb') ], ''), diff --git a/puphpet/puppet/modules/nginx/manifests/resource/vhost.pp b/puphpet/puppet/modules/nginx/manifests/resource/vhost.pp index a22b76c..ab5259a 100644 --- a/puphpet/puppet/modules/nginx/manifests/resource/vhost.pp +++ b/puphpet/puppet/modules/nginx/manifests/resource/vhost.pp @@ -133,6 +133,7 @@ # [*owner*] - Defines owner of the .conf file # [*group*] - Defines group of the .conf file # [*mode*] - Defines mode of the .conf file +# [*rewrites*] - Rewrite rules for the server # Actions: # # Requires: @@ -229,6 +230,7 @@ $owner = $nginx::config::global_owner, $group = $nginx::config::global_group, $mode = $nginx::config::global_mode, + $rewrites = {}, ) { validate_re($ensure, '^(present|absent)$', @@ -423,6 +425,7 @@ $name_sanitized = regsubst($name, ' ', '_', 'G') $config_file = "${vhost_dir}/${name_sanitized}.conf" + validate_hash($rewrites) File { ensure => $ensure ? { diff --git a/puphpet/puppet/modules/nginx/templates/vhost/location_header.erb b/puphpet/puppet/modules/nginx/templates/vhost/location_header.erb index e6c4cdd..e6deb86 100644 --- a/puphpet/puppet/modules/nginx/templates/vhost/location_header.erb +++ b/puphpet/puppet/modules/nginx/templates/vhost/location_header.erb @@ -47,3 +47,14 @@ <%= line %> <%- end -%> <% end %> +<% if (defined? @rewrites) -%> + <%- @rewrites.each do |i, rewrite| -%> + <%- if (rewrite['when'] && !rewrite['when'].empty?) -%> + if (<%= rewrite['when'] %>) { + rewrite "<%= rewrite['regex'] %>" <%= rewrite['target'] %>; + } + <%- else -%> + rewrite <%= rewrite['regex'] %> <%= rewrite['target'] -%>; + <%- end -%> + <%- end -%> +<% end %> diff --git a/puphpet/puppet/modules/nginx/templates/vhost/locations/set.erb b/puphpet/puppet/modules/nginx/templates/vhost/locations/set.erb new file mode 100644 index 0000000..3a89976 --- /dev/null +++ b/puphpet/puppet/modules/nginx/templates/vhost/locations/set.erb @@ -0,0 +1,3 @@ +<% if (defined? @set) && @set.count > 0 -%> + set<% @set.each do |s| -%> <%= s %><% end -%>; +<% end -%> diff --git a/puphpet/puppet/modules/nginx/templates/vhost/vhost_header.erb b/puphpet/puppet/modules/nginx/templates/vhost/vhost_header.erb index 20a4a6a..25f64db 100644 --- a/puphpet/puppet/modules/nginx/templates/vhost/vhost_header.erb +++ b/puphpet/puppet/modules/nginx/templates/vhost/vhost_header.erb @@ -16,6 +16,17 @@ server { <% if (defined? @rewrite) && (@rewrite.split.join.length > 0) -%> rewrite <%= @rewrite %>; <% end -%> +<% if (defined? @rewrites) -%> + <%- @rewrites.each do |i, rewrite| -%> + <%- if (rewrite['when'] && !rewrite['when'].empty?) -%> + if (<%= rewrite['when'] %>) { + rewrite "<%= rewrite['regex'] %>" <%= rewrite['target'] %>; + } + <%- else -%> + rewrite <%= rewrite['regex'] %> <%= rewrite['target'] %>; + <%- end -%> + <%- end -%> +<% end -%> <% if defined? @auth_basic -%> auth_basic "<%= @auth_basic %>"; <% end -%> @@ -91,4 +102,3 @@ server { access_log <%= @access_log_real %>; error_log <%= @error_log_real %>; - diff --git a/puphpet/puppet/modules/nginx/templates/vhost/vhost_ssl_header.erb b/puphpet/puppet/modules/nginx/templates/vhost/vhost_ssl_header.erb index c44161f..9818a16 100644 --- a/puphpet/puppet/modules/nginx/templates/vhost/vhost_ssl_header.erb +++ b/puphpet/puppet/modules/nginx/templates/vhost/vhost_ssl_header.erb @@ -13,6 +13,18 @@ server { <%- end %> server_name <%= @rewrite_www_to_non_www ? @server_name[0].gsub(/^www\./, '') : @server_name.join(" ") %>; + <% if (defined? @rewrites) %> + <%- @rewrites.each do |i, rewrite| -%> + <%- if (rewrite['when'] && !rewrite['when'].empty?) -%> + if (<%= rewrite['when'] %>) { + rewrite "<%= rewrite['regex'] %>" <%= rewrite['target'] %>; + } + <%- else -%> + rewrite <%= rewrite['regex'] %> <%= rewrite['target'] %>; + <%- end -%> + <%- end -%> + <% end %> + ssl on; ssl_certificate <%= scope.lookupvar('nginx::config::conf_dir') %>/<%= @name.gsub(' ', '_') %>.crt; diff --git a/puphpet/puppet/modules/ntp/.gitignore b/puphpet/puppet/modules/ntp/.gitignore new file mode 100644 index 0000000..b5db85e --- /dev/null +++ b/puphpet/puppet/modules/ntp/.gitignore @@ -0,0 +1,9 @@ +pkg/ +Gemfile.lock +vendor/ +spec/fixtures/ +.vagrant/ +.bundle/ +coverage/ +.idea/ +*.iml diff --git a/puphpet/puppet/modules/ntp/.sync.yml b/puphpet/puppet/modules/ntp/.sync.yml new file mode 100644 index 0000000..ac83790 --- /dev/null +++ b/puphpet/puppet/modules/ntp/.sync.yml @@ -0,0 +1,9 @@ +--- +.travis.yml: + extras: + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0" +spec/spec_helper.rb: + unmanaged: true diff --git a/puphpet/puppet/modules/ntp/.travis.yml b/puphpet/puppet/modules/ntp/.travis.yml index fe5850a..7e8ed57 100644 --- a/puphpet/puppet/modules/ntp/.travis.yml +++ b/puphpet/puppet/modules/ntp/.travis.yml @@ -1,31 +1,24 @@ --- -branches: - only: - - master +sudo: false language: ruby -bundler_args: --without development -script: "bundle exec rake spec SPEC_OPTS='--format documentation'" -rvm: -- 1.8.7 -- 1.9.3 -- 2.0.0 -env: - matrix: - - PUPPET_GEM_VERSION="~> 2.7.0" - - PUPPET_GEM_VERSION="~> 3.0.0" - - PUPPET_GEM_VERSION="~> 3.1.0" - - PUPPET_GEM_VERSION="~> 3.2.0" +bundler_args: --without system_tests +script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake spec SPEC_OPTS='--format documentation'" matrix: - exclude: - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 2.7.0" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 2.7.0" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3.0.0" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3.1.0" - - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 3.2.0" + fast_finish: true + include: + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 3.0" + - rvm: 1.9.3 + env: PUPPET_GEM_VERSION="~> 3.0" + - rvm: 2.1.5 + env: PUPPET_GEM_VERSION="~> 3.0" + - rvm: 2.1.5 + env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes" + - rvm: 2.1.6 + env: PUPPET_GEM_VERSION="~> 4.0" STRICT_VARIABLES="yes" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0" notifications: email: false diff --git a/puphpet/puppet/modules/ntp/CHANGELOG.md b/puphpet/puppet/modules/ntp/CHANGELOG.md index cfcac42..67faec9 100644 --- a/puphpet/puppet/modules/ntp/CHANGELOG.md +++ b/puphpet/puppet/modules/ntp/CHANGELOG.md @@ -1,3 +1,118 @@ +## Supported Release 4.1.1 +### Summary +This is a bugfix release to address security vulnerability CVE-2013-5211. + +#### Bugfixes +- Changes the default behavior to disable monitoring as part of the solution for CVE-2013-5211. + +## 2015-07-21 - Supported Release 4.1.0 +### Summary +This release updates metadata to support new version of puppet enterprise, as well as new features, bugfixes, and test improvements. + +#### Features +- Adds Solaris 10 support +- Adds Fedora 20, 21, 22 compatibility + +#### Bugfixes +- Fix default configuration for Debian (MODULES-2087) +- Fix to ensure log file is created before service starts +- Fixes SLES params for SLES 10, 11, 12 + +## 2015-05-26 - Supported Release 4.0.0 +### Summary +This release drops puppet 2.7 support and older stdlib support. It also includes the addition of 12 new properties, as well as numerous bug fixes and other improvements. + +#### Backwards-incompatible changes +- UDLC (Undisciplined local clock) is now no longer enabled by default on anything (previous was enabled on non-virtual). +- Puppet 2.7 no longer supported +- puppetlabs-stdlib less than 4.5.0 no longer supported + +#### Features +- Readme, Metadata, and Contribution documentation improvements +- Acceptance test improvements +- Added the `broadcastclient` property +- Added the `disable_auth` property +- Added `broadcastclient` property +- Added `disable_auth` property +- Added `fudge` property +- Added `peers` property +- Added `udlc_stratum` property +- Added `tinker` property +- Added `minpoll` property +- Added `maxpoll` property +- Added `stepout` property +- Added `leapfile` property + +#### Bugfixes +- Removing equal sign as delimiter in ntp.conf for the logfile parameter. +- Add package_manage parameter, which is set to false by default on FreeBSD +- Fixed an issue with the `is_virtual` property +- Fixed debian wheezy issue +- Fix for Redhat to disable ntp restart due to dhcp ntp server updates + +##2014-11-04 - Supported Release 3.3.0 +###Summary + +This release adds support for SLES 12. + +####Features +- Added support for SLES 12 + +##2014-10-02 - Supported Release 3.2.1 +###Summary + +This is a bug-fix release addressing the security concerns of setting /etc/ntp to mode 0755 recursively. + +####Bugfixes +- Do not recursively set ownership/mode of /etc/ntp + +##2014-09-10 - Supported Release 3.2.0 +###Summary + +This is primarily a feature release. It adds a few new parameters to class `ntp` +and adds support for Solaris 11. + +####Features +- Add the `$interfaces` parameter to `ntp` +- Add support for Solaris 10 and 11 +- Synchronized files with modulesync +- Test updates +- Add the `$iburst_enable` parameter to `ntp` + +####Bugfixes +- Fixes for strict variables +- Remove dependency on stdlib4 + +##2014-06-06 - Release 3.1.2 +###Summary + +This is a supported release. This release fixes a manifest typo. + +##2014-06-06 - Release 3.1.1 +###Summary + +This is a bugfix release to get around dependency issues in PMT 3.6. This +version has a dependency on puppetlabs-stdlib >= 4 so PE3.2.x is no longer +supported. + +####Bugfixes +- Remove deprecated Modulefile as it was causing duplicate dependencies with PMT. + +##2014-05-14 - Release 3.1.0 +###Summary + +This release adds `disable_monitor` so you can disable the monitor functionality +of NTP, which was recently used in NTP amplification attacks. It also adds +support for RHEL7 and Ubuntu 14.04. + +####Features +- Add `disable_monitor` + +####Bugfixes + +#####Known Bugs +* No known bugs + ##2014-04-09 - Supported Release 3.0.4 ###Summary This is a supported release. diff --git a/puphpet/puppet/modules/ntp/CONTRIBUTING.md b/puphpet/puppet/modules/ntp/CONTRIBUTING.md index a2b1d77..f1cbde4 100644 --- a/puphpet/puppet/modules/ntp/CONTRIBUTING.md +++ b/puphpet/puppet/modules/ntp/CONTRIBUTING.md @@ -1,9 +1,220 @@ -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. +Checklist (and a short version for the impatient) +================================================= -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. + * 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/) -You can read the complete module contribution guide [on the Puppet Labs wiki.](http://projects.puppetlabs.com/projects/module-site/wiki/Module_contributing) diff --git a/puphpet/puppet/modules/ntp/Gemfile b/puphpet/puppet/modules/ntp/Gemfile index 7f86b2d..bfe64b1 100644 --- a/puphpet/puppet/modules/ntp/Gemfile +++ b/puphpet/puppet/modules/ntp/Gemfile @@ -1,13 +1,42 @@ source ENV['GEM_SOURCE'] || "https://rubygems.org" -group :development, :test do - gem 'rake', :require => false +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 'puppet-lint', :require => false - gem 'serverspec', :require => false - gem 'beaker', :require => false - gem 'beaker-rspec', :require => false - gem 'specinfra', '>=0.7.0' + 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'] diff --git a/puphpet/puppet/modules/ntp/Modulefile b/puphpet/puppet/modules/ntp/Modulefile deleted file mode 100644 index fc43632..0000000 --- a/puphpet/puppet/modules/ntp/Modulefile +++ /dev/null @@ -1,11 +0,0 @@ -name 'puppetlabs-ntp' -version '3.0.4' -source 'git://github.com/puppetlabs/puppetlabs-ntp' -author 'Puppet Labs' -license 'Apache Version 2.0' -summary 'NTP Module' -description 'NTP Module for Debian, Ubuntu, CentOS, RHEL, OEL, Fedora, FreeBSD, ArchLinux and Gentoo.' -project_page 'http://github.com/puppetlabs/puppetlabs-ntp' - -## Add dependencies, if any: -dependency 'puppetlabs/stdlib', '>= 0.1.6' diff --git a/puphpet/puppet/modules/ntp/README.markdown b/puphpet/puppet/modules/ntp/README.markdown index e25e3c4..5ee8373 100644 --- a/puphpet/puppet/modules/ntp/README.markdown +++ b/puphpet/puppet/modules/ntp/README.markdown @@ -5,9 +5,6 @@ 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 ntp](#setup) - * [What ntp affects](#what-ntp-affects) - * [Setup requirements](#setup-requirements) - * [Beginning with ntp](#beginning-with-ntp) 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) @@ -23,16 +20,9 @@ The ntp module handles installing, configuring, and running NTP across a range o ##Setup -###What ntp affects - -* ntp package. -* ntp configuration file. -* ntp service. - ###Beginning with ntp -`include '::ntp'` is enough to get you up and running. If you wish to pass in -parameters specifying which servers to use, then: +`include '::ntp'` is enough to get you up and running. If you wish to pass in parameters specifying which servers to use, then: ```puppet class { '::ntp': @@ -42,8 +32,7 @@ class { '::ntp': ##Usage -All interaction with the ntp module can do be done through the main ntp class. -This means you can simply toggle the options in `::ntp` to have full functionality of the module. +All interaction with the ntp module can be done through the main ntp class. This means you can simply toggle the options in `::ntp` to have full functionality of the module. ###I just want NTP, what's the minimum I need? @@ -68,13 +57,48 @@ class { '::ntp': } ``` +###I just want to install a client that can't be queried + +```puppet +class { '::ntp': + servers => ['ntp1.corp.com', 'ntp2.corp.com'], + restrict => [ + 'default ignore', + '-6 default ignore', + '127.0.0.1', + '-6 ::1', + 'ntp1.corp.com nomodify notrap nopeer noquery', + 'ntp1.corp.com nomodify notrap nopeer noquery' + ], +} +``` + +###I only want to listen on specific interfaces, not on 0.0.0.0 + +Restricting ntp to a specific interface is especially useful on Openstack nodes which may have numerous virtual interfaces. + +```puppet +class { '::ntp': + servers => [ 'ntp1.corp.com', 'ntp2.corp.com' ], + interfaces => ['127.0.0.1', '1.2.3.4'] +} +``` + ###I'd like to opt out of having the service controlled; we use another tool for that. ```puppet class { '::ntp': servers => [ 'ntp1.corp.com', 'ntp2.corp.com' ], restrict => ['127.0.0.1'], - manage_service => false, + service_manage => false, +} +``` + +###I'd like to configure and run ntp, but I don't need to install it. + +```puppet +class { '::ntp': + package_manage => false, } ``` @@ -84,7 +108,7 @@ class { '::ntp': class { '::ntp': servers => [ 'ntp1.corp.com', 'ntp2.corp.com' ], restrict => ['127.0.0.1'], - manage_service => false, + service_manage => false, config_template => 'different/module/custom.template.erb', } ``` @@ -105,123 +129,178 @@ class { '::ntp': ###Parameters -The following parameters are available in the ntp module: +The following parameters are available in the `::ntp` class: ####`autoupdate` -**Deprecated:** This parameter determined whether the ntp module should be -automatically updated to the latest version available. Replaced by `package_ensure`. +**Deprecated; replaced by the `package_ensure` parameter**. Tells Puppet whether to keep the ntp module updated to the latest version available. Valid options: 'true' or 'false'. Default value: 'false' + +####`broadcastclient` + +Enable reception of broadcast server messages to any local interface. ####`config` -Sets the file that ntp configuration is written into. +Specifies a file for ntp's configuration info. Valid options: string containing an absolute path. Default value: '/etc/ntp.conf' (or '/etc/inet/ntp.conf' on Solaris) ####`config_template` -Determines which template Puppet should use for the ntp configuration. +Specifies a file to act as a template for the config file. Valid options: string containing a path (absolute, or relative to the module path). Default value: 'ntp/ntp.conf.erb' + +####`disable_auth` + +Do not require cryptographic authentication for broadcast client, multicast +client and symmetric passive associations. + +####`disable_monitor` + +Disables the monitoring facility in NTP. Valid options: 'true' or 'false'. Default value: 'true' ####`driftfile` -Sets the location of the drift file for ntp. +Specifies an NTP driftfile. Valid options: string containing an absolute path. Default value: '/var/lib/ntp/drift' (except on AIX and Solaris) + +#### `fudge` + +Used to provide additional information for individual clock drivers. Valid options: array containing strings that follow the `fudge` command. Default value: [ ] + +####`iburst_enable` + +Specifies whether to enable the iburst option for every NTP peer. Valid options: 'true' or 'false'. Default value: 'false' (except on AIX and Debian) + +####`interfaces` + +Specifies one or more network interfaces for NTP to listen on. Valid options: array. Default value: [ ] ####`keys_controlkey` -The key to use as the control key. +Provides a control key to be used by NTP. Valid options: string. Default value: ' ' ####`keys_enable` -Whether the ntp keys functionality is enabled. +Tells Puppet whether to enable key-based authentication. Valid options: 'true' or 'false'. Default value: 'false' ####`keys_file` -Location of the keys file. +Specifies an NTP keys file. Valid options: string containing an absolute path. Default value: '/etc/ntp/keys' (except on AIX, SLES, and Solaris) ####`keys_requestkey` -Which of the keys is the request key. +Provides a request key to be used by NTP. Valid options: string. Default value: ' ' + +#### `keys_trusted`: +Provides one or more keys to be trusted by NTP. Valid options: array of keys. Default value: [ ] + +#### `leapfile` + +Specifies a leap second file for NTP to use. Valid options: string containing an absolute path. Default value: ' ' + +#### `logfile` + +Specifies a log file for NTP to use instead of syslog. Valid options: string containing an absolute path. Default value: ' ' + +####`minpoll` + +Tells Puppet to use non-standard minimal poll interval of upstream servers. Valid options: 3 to 16. Default option: undef. -#### `keys_trusted` +####`maxpoll` -Array of trusted keys. +Tells Puppet to use non-standard maximal poll interval of upstream servers. Valid options: 3 to 16. Default option: undef, except FreeBSD (on FreeBSD `maxpoll` set 9 by default). ####`package_ensure` -Sets the ntp package to be installed. Can be set to 'present', 'latest', or a specific version. +Tells Puppet whether the NTP package should be installed, and what version. Valid options: 'present', 'latest', or a specific version number. Default value: 'present' + +####`package_manage` + +Tells Puppet whether to manage the NTP package. Valid options: 'true' or 'false'. Default value: 'true' ####`package_name` -Determines the name of the package to install. +Tells Puppet what NTP package to manage. Valid options: string. Default value: 'ntp' (except on AIX and Solaris) ####`panic` -Determines if ntp should 'panic' in the event of a very large clock skew. -This defaults to false for virtual machines, as they don't do a great job with keeping time. +Specifies whether NTP should "panic" in the event of a very large clock skew. Applies only if `tinker` option set to "true" or in case your environment is in virtual machine. Valid options: unsigned shortint digit. Default value: 0 if environment is virtual, undef in all other cases. + +####`peers` + +List of ntp servers which the local clock can be synchronised against, or which can synchronise against the local clock. ####`preferred_servers` -List of ntp servers to prefer. Will append 'prefer' for any server in this list -that also appears in the servers list. +Specifies one or more preferred peers. Puppet will append 'prefer' to each matching item in the `servers` array. Valid options: array. Default value: [ ] ####`restrict` -Sets the restrict options in the ntp configuration. The lines are -prefixed with 'restrict', so you just need to list the rest of the restriction. +Specifies one or more `restrict` options for the NTP configuration. Puppet will prefix each item with 'restrict', so you only need to list the content of the restriction. Valid options: array. Default value for most operating systems: + +~~~~ +[ + 'default kod nomodify notrap nopeer noquery', + '-6 default kod nomodify notrap nopeer noquery', + '127.0.0.1', + '-6 ::1', +] +~~~~ + +Default value for AIX systems: + +~~~~ +[ + 'default nomodify notrap nopeer noquery', + '127.0.0.1', +] +~~~~ ####`servers` -Selects the servers to use for ntp peers. +Specifies one or more servers to be used as NTP peers. Valid options: array. Default value: varies by operating system ####`service_enable` -Determines if the service should be enabled at boot. +Tells Puppet whether to enable the NTP service at boot. Valid options: 'true' or 'false'. Default value: 'true' ####`service_ensure` -Determines if the service should be running or not. +Tells Puppet whether the NTP service should be running. Valid options: 'running' or 'stopped'. Default value: 'running' ####`service_manage` -Selects whether Puppet should manage the service. +Tells Puppet whether to manage the NTP service. Valid options: 'true' or 'false'. Default value: 'true' ####`service_name` -Selects the name of the ntp service for Puppet to manage. +Tells Puppet what NTP service to manage. Valid options: string. Default value: varies by operating system -####`udlc` +####`stepout` -Enables configs for undisciplined local clock, regardless of -status as a virtual machine. +Tells puppet to change stepout. Applies only if `tinker` value is 'true'. Valid options: unsigned shortint digit. Default value: undef. +####`tinker` -##Limitations +Tells Puppet to enable tinker options. Valid options: 'true' of 'false'. Default value: 'false' + +####`udlc` + +Specifies whether to configure ntp to use the undisciplined local clock as a time source. Valid options: 'true' or 'false'. Default value: 'false' -This module has been built on and tested against Puppet 2.7 and higher. +####`udlc_stratum` -The module has been tested on: +Specifies the stratum the server should operate at when using the undisciplined local clock as the time source. It is strongly suggested that this value be set to no less than 10 where ntpd may be accessible outside your immediate, controlled network. Default value: 10 -* RedHat Enterprise Linux 5/6 -* Debian 6/7 -* CentOS 5/6 -* Ubuntu 12.04 -* Gentoo -* Arch Linux -* FreeBSD +##Limitations -Testing on other platforms has been light and cannot be guaranteed. +This module has been tested on [all PE-supported platforms](https://forge.puppetlabs.com/supported#compat-matrix), and no issues have been identified. Additionally, it is tested (but not supported) on Solaris 10 and Fedora 20-22. ##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. +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. +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. -You can read the complete module contribution guide [on the Puppet Labs wiki.](http://projects.puppetlabs.com/projects/module-site/wiki/Module_contributing) +For more information, see our [module contribution guide.](https://docs.puppetlabs.com/forge/contributing.html) ###Contributors -The list of contributors can be found at: [https://github.com/puppetlabs/puppetlabs-ntp/graphs/contributors](https://github.com/puppetlabs/puppetlabs-ntp/graphs/contributors) +To see who's already involved, see the [list of contributors.](https://github.com/puppetlabs/puppetlabs-ntp/graphs/contributors) diff --git a/puphpet/puppet/modules/ntp/Rakefile b/puphpet/puppet/modules/ntp/Rakefile index cd3d379..181157e 100644 --- a/puphpet/puppet/modules/ntp/Rakefile +++ b/puphpet/puppet/modules/ntp/Rakefile @@ -1 +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"] diff --git a/puphpet/puppet/modules/ntp/lib/puppet/parser/functions/ntp_dirname.rb b/puphpet/puppet/modules/ntp/lib/puppet/parser/functions/ntp_dirname.rb new file mode 100644 index 0000000..06cdb7c --- /dev/null +++ b/puphpet/puppet/modules/ntp/lib/puppet/parser/functions/ntp_dirname.rb @@ -0,0 +1,15 @@ +module Puppet::Parser::Functions + newfunction(:ntp_dirname, :type => :rvalue, :doc => <<-EOS + Returns the dirname of a path. + EOS + ) do |arguments| + + raise(Puppet::ParseError, "ntp_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 : diff --git a/puphpet/puppet/modules/ntp/manifests/config.pp b/puphpet/puppet/modules/ntp/manifests/config.pp index fbb01fe..34ffcbd 100644 --- a/puphpet/puppet/modules/ntp/manifests/config.pp +++ b/puphpet/puppet/modules/ntp/manifests/config.pp @@ -1,24 +1,31 @@ # class ntp::config inherits ntp { - if $keys_enable { - # Workaround for the lack of dirname() in stdlib 3.2. - $directory = inline_template('<%= File.dirname(keys_file) %>') + if $ntp::keys_enable { + $directory = ntp_dirname($ntp::keys_file) file { $directory: - ensure => directory, - owner => 0, - group => 0, - mode => '0755', - recurse => true, + ensure => directory, + owner => 0, + group => 0, + mode => '0755', } } - file { $config: + file { $ntp::config: ensure => file, owner => 0, group => 0, mode => '0644', - content => template($config_template), + content => template($ntp::config_template), + } + + if $ntp::logfile { + file { $ntp::logfile: + ensure => 'file', + owner => 'ntp', + group => 'ntp', + mode => '0664', + } } } diff --git a/puphpet/puppet/modules/ntp/manifests/init.pp b/puphpet/puppet/modules/ntp/manifests/init.pp index 74c9d7c..1eea5a0 100644 --- a/puphpet/puppet/modules/ntp/manifests/init.pp +++ b/puphpet/puppet/modules/ntp/manifests/init.pp @@ -1,44 +1,73 @@ class ntp ( $autoupdate = $ntp::params::autoupdate, + $broadcastclient = $ntp::params::broadcastclient, $config = $ntp::params::config, $config_template = $ntp::params::config_template, + $disable_auth = $ntp::params::disable_auth, + $disable_monitor = $ntp::params::disable_monitor, + $fudge = $ntp::params::fudge, $driftfile = $ntp::params::driftfile, + $leapfile = $ntp::params::leapfile, + $logfile = $ntp::params::logfile, + $iburst_enable = $ntp::params::iburst_enable, $keys_enable = $ntp::params::keys_enable, $keys_file = $ntp::params::keys_file, $keys_controlkey = $ntp::params::keys_controlkey, $keys_requestkey = $ntp::params::keys_requestkey, $keys_trusted = $ntp::params::keys_trusted, + $minpoll = $ntp::params::minpoll, + $maxpoll = $ntp::params::maxpoll, $package_ensure = $ntp::params::package_ensure, + $package_manage = $ntp::params::package_manage, $package_name = $ntp::params::package_name, $panic = $ntp::params::panic, + $peers = $ntp::params::peers, $preferred_servers = $ntp::params::preferred_servers, $restrict = $ntp::params::restrict, + $interfaces = $ntp::params::interfaces, $servers = $ntp::params::servers, $service_enable = $ntp::params::service_enable, $service_ensure = $ntp::params::service_ensure, $service_manage = $ntp::params::service_manage, $service_name = $ntp::params::service_name, - $udlc = $ntp::params::udlc + $stepout = $ntp::params::stepout, + $tinker = $ntp::params::tinker, + $udlc = $ntp::params::udlc, + $udlc_stratum = $ntp::params::udlc_stratum, ) inherits ntp::params { + validate_bool($broadcastclient) validate_absolute_path($config) validate_string($config_template) + validate_bool($disable_auth) + validate_bool($disable_monitor) validate_absolute_path($driftfile) + if $logfile { validate_absolute_path($logfile) } + if $leapfile { validate_absolute_path($leapfile) } + validate_bool($iburst_enable) validate_bool($keys_enable) validate_re($keys_controlkey, ['^\d+$', '']) validate_re($keys_requestkey, ['^\d+$', '']) validate_array($keys_trusted) + if $minpoll { validate_numeric($minpoll, 16, 3) } + if $maxpoll { validate_numeric($maxpoll, 16, 3) } validate_string($package_ensure) + validate_bool($package_manage) validate_array($package_name) - validate_bool($panic) + if $panic { validate_numeric($panic, 65535, 0) } validate_array($preferred_servers) validate_array($restrict) + validate_array($interfaces) validate_array($servers) + validate_array($fudge) validate_bool($service_enable) validate_string($service_ensure) validate_bool($service_manage) validate_string($service_name) + if $stepout { validate_numeric($stepout, 65535, 0) } + validate_bool($tinker) validate_bool($udlc) + validate_array($peers) if $autoupdate { notice('autoupdate parameter has been deprecated and replaced with package_ensure. Set this to latest for the same behavior as autoupdate => true.') diff --git a/puphpet/puppet/modules/ntp/manifests/install.pp b/puphpet/puppet/modules/ntp/manifests/install.pp index 098949c..9709d70 100644 --- a/puphpet/puppet/modules/ntp/manifests/install.pp +++ b/puphpet/puppet/modules/ntp/manifests/install.pp @@ -1,9 +1,12 @@ # class ntp::install inherits ntp { - package { 'ntp': - ensure => $package_ensure, - name => $package_name, + if $ntp::package_manage { + + package { $ntp::package_name: + ensure => $ntp::package_ensure, + } + } } diff --git a/puphpet/puppet/modules/ntp/manifests/params.pp b/puphpet/puppet/modules/ntp/manifests/params.pp index b8ae503..b0459eb 100644 --- a/puphpet/puppet/modules/ntp/manifests/params.pp +++ b/puphpet/puppet/modules/ntp/manifests/params.pp @@ -6,172 +6,290 @@ $keys_controlkey = '' $keys_requestkey = '' $keys_trusted = [] + $logfile = undef + $minpoll = undef + $leapfile = undef $package_ensure = 'present' + $peers = [] $preferred_servers = [] $service_enable = true $service_ensure = 'running' $service_manage = true + $stepout = undef $udlc = false + $udlc_stratum = '10' + $interfaces = [] + $disable_auth = false + $disable_monitor = true + $broadcastclient = false - # On virtual machines allow large clock skews. - $panic = str2bool($::is_virtual) ? { - true => false, - default => true, + # Allow a list of fudge options + $fudge = [] + + $default_config = '/etc/ntp.conf' + $default_keys_file = '/etc/ntp/keys' + $default_driftfile = '/var/lib/ntp/drift' + $default_package_name = ['ntp'] + $default_service_name = 'ntpd' + + $package_manage = $::osfamily ? { + 'FreeBSD' => false, + default => true, + } + + if str2bool($::is_virtual) { + $tinker = true + $panic = 0 + } + else { + $tinker = false + $panic = undef } case $::osfamily { 'AIX': { - $config = '/etc/ntp.conf' - $keysfile = '/etc/ntp.keys' - $driftfile = '/etc/ntp.drift' - $package_name = [ 'bos.net.tcp.client' ] - $restrict = [ + $config = $default_config + $keys_file = '/etc/ntp.keys' + $driftfile = '/etc/ntp.drift' + $package_name = [ 'bos.net.tcp.client' ] + $restrict = [ 'default nomodify notrap nopeer noquery', '127.0.0.1', ] - $service_name = 'xntpd' - $servers = [ - '0.debian.pool.ntp.org iburst', - '1.debian.pool.ntp.org iburst', - '2.debian.pool.ntp.org iburst', - '3.debian.pool.ntp.org iburst', + $service_name = 'xntpd' + $iburst_enable = true + $servers = [ + '0.debian.pool.ntp.org', + '1.debian.pool.ntp.org', + '2.debian.pool.ntp.org', + '3.debian.pool.ntp.org', ] + $maxpoll = undef } 'Debian': { - $config = '/etc/ntp.conf' - $keys_file = '/etc/ntp/keys' - $driftfile = '/var/lib/ntp/drift' - $package_name = [ 'ntp' ] - $restrict = [ - 'default kod nomodify notrap nopeer noquery', + $config = $default_config + $keys_file = $default_keys_file + $driftfile = $default_driftfile + $package_name = $default_package_name + $restrict = [ + '-4 default kod nomodify notrap nopeer noquery', '-6 default kod nomodify notrap nopeer noquery', '127.0.0.1', - '-6 ::1', + '::1', ] $service_name = 'ntp' + $iburst_enable = true $servers = [ - '0.debian.pool.ntp.org iburst', - '1.debian.pool.ntp.org iburst', - '2.debian.pool.ntp.org iburst', - '3.debian.pool.ntp.org iburst', + '0.debian.pool.ntp.org', + '1.debian.pool.ntp.org', + '2.debian.pool.ntp.org', + '3.debian.pool.ntp.org', ] + $maxpoll = undef } 'RedHat': { - $config = '/etc/ntp.conf' - $driftfile = '/var/lib/ntp/drift' - $keys_file = '/etc/ntp/keys' - $package_name = [ 'ntp' ] - $restrict = [ - 'default kod nomodify notrap nopeer noquery', - '-6 default kod nomodify notrap nopeer noquery', - '127.0.0.1', - '-6 ::1', - ] - $service_name = 'ntpd' - $servers = [ - '0.centos.pool.ntp.org', - '1.centos.pool.ntp.org', - '2.centos.pool.ntp.org', - ] + $config = $default_config + $keys_file = $default_keys_file + $driftfile = $default_driftfile + $package_name = $default_package_name + $service_name = $default_service_name + $maxpoll = undef + + case $::operatingsystem { + 'Fedora': { + $restrict = [ + 'default nomodify notrap nopeer noquery', + '127.0.0.1', + '::1', + ] + $iburst_enable = true + $servers = [ + '0.fedora.pool.ntp.org', + '1.fedora.pool.ntp.org', + '2.fedora.pool.ntp.org', + '3.fedora.pool.ntp.org', + ] + } + default: { + $restrict = [ + 'default kod nomodify notrap nopeer noquery', + '-6 default kod nomodify notrap nopeer noquery', + '127.0.0.1', + '-6 ::1', + ] + $iburst_enable = false + $servers = [ + '0.centos.pool.ntp.org', + '1.centos.pool.ntp.org', + '2.centos.pool.ntp.org', + ] + } + } } - 'SuSE': { - $config = '/etc/ntp.conf' + 'Suse': { + if $::operatingsystem == 'SLES' { + case $::operatingsystemmajrelease { + '10': { + $service_name = 'ntp' + $keys_file = '/etc/ntp.keys' + $package_name = [ 'xntp' ] + } + '11': { + $service_name = 'ntp' + $keys_file = $default_keys_file + $package_name = $default_package_name + } + '12': { + $service_name = 'ntpd' + $keys_file = '/etc/ntp.keys' + $package_name = $default_package_name + } + default: { + fail("The ${module_name} module is not supported on an ${::operatingsystem} ${::operatingsystemmajrelease} distribution.") + } + } + } else { + $service_name = 'ntp' + $keys_file = $default_keys_file + $package_name = $default_package_name + } + $config = $default_config $driftfile = '/var/lib/ntp/drift/ntp.drift' - $keys_file = '/etc/ntp/keys' - $package_name = [ 'ntp' ] - $restrict = [ + $restrict = [ 'default kod nomodify notrap nopeer noquery', '-6 default kod nomodify notrap nopeer noquery', '127.0.0.1', '-6 ::1', ] - $service_name = 'ntp' + $iburst_enable = false $servers = [ '0.opensuse.pool.ntp.org', '1.opensuse.pool.ntp.org', '2.opensuse.pool.ntp.org', '3.opensuse.pool.ntp.org', ] + $maxpoll = undef } 'FreeBSD': { - $config = '/etc/ntp.conf' + $config = $default_config $driftfile = '/var/db/ntpd.drift' - $keys_file = '/etc/ntp/keys' + $keys_file = $default_keys_file $package_name = ['net/ntp'] - $restrict = [ + $restrict = [ 'default kod nomodify notrap nopeer noquery', '-6 default kod nomodify notrap nopeer noquery', '127.0.0.1', '-6 ::1', ] - $service_name = 'ntpd' + $service_name = $default_service_name + $iburst_enable = true $servers = [ - '0.freebsd.pool.ntp.org iburst maxpoll 9', - '1.freebsd.pool.ntp.org iburst maxpoll 9', - '2.freebsd.pool.ntp.org iburst maxpoll 9', - '3.freebsd.pool.ntp.org iburst maxpoll 9', + '0.freebsd.pool.ntp.org', + '1.freebsd.pool.ntp.org', + '2.freebsd.pool.ntp.org', + '3.freebsd.pool.ntp.org', ] + $maxpoll = 9 } 'Archlinux': { - $config = '/etc/ntp.conf' - $driftfile = '/var/lib/ntp/drift' - $keys_file = '/etc/ntp/keys' - $package_name = [ 'ntp' ] - $restrict = [ + $config = $default_config + $keys_file = $default_keys_file + $driftfile = '/var/lib/ntp/ntp.drift' + $package_name = $default_package_name + $service_name = $default_service_name + $restrict = [ 'default kod nomodify notrap nopeer noquery', '-6 default kod nomodify notrap nopeer noquery', '127.0.0.1', '-6 ::1', ] - $service_name = 'ntpd' + $iburst_enable = false $servers = [ + '0.arch.pool.ntp.org', + '1.arch.pool.ntp.org', + '2.arch.pool.ntp.org', + '3.arch.pool.ntp.org', + ] + $maxpoll = undef + } + 'Solaris': { + $config = '/etc/inet/ntp.conf' + $driftfile = '/var/ntp/ntp.drift' + $keys_file = '/etc/inet/ntp.keys' + if $::operatingsystemrelease =~ /^(5\.10|10|10_u\d+)$/ + { + # Solaris 10 + $package_name = [ 'SUNWntpr', 'SUNWntpu' ] + $restrict = [ + 'default nomodify notrap nopeer noquery', + '127.0.0.1', + ] + } else { + # Solaris 11... + $package_name = [ 'service/network/ntp' ] + $restrict = [ + 'default kod nomodify notrap nopeer noquery', + '-6 default kod nomodify notrap nopeer noquery', + '127.0.0.1', + '-6 ::1', + ] + } + $service_name = 'network/ntp' + $iburst_enable = false + $servers = [ '0.pool.ntp.org', '1.pool.ntp.org', '2.pool.ntp.org', + '3.pool.ntp.org', ] + $maxpoll = undef } - # Gentoo was added as its own $::osfamily in Facter 1.7.0 + # Gentoo was added as its own $::osfamily in Facter 1.7.0 'Gentoo': { - $config = '/etc/ntp.conf' - $driftfile = '/var/lib/ntp/drift' - $keys_file = '/etc/ntp/keys' + $config = $default_config + $keys_file = $default_keys_file + $driftfile = $default_driftfile $package_name = ['net-misc/ntp'] - $restrict = [ + $service_name = $default_service_name + $restrict = [ 'default kod nomodify notrap nopeer noquery', '-6 default kod nomodify notrap nopeer noquery', '127.0.0.1', '-6 ::1', ] - $service_name = 'ntpd' + $iburst_enable = false $servers = [ '0.gentoo.pool.ntp.org', '1.gentoo.pool.ntp.org', '2.gentoo.pool.ntp.org', '3.gentoo.pool.ntp.org', ] + $maxpoll = undef } 'Linux': { - # Account for distributions that don't have $::osfamily specific settings. - # Before Facter 1.7.0 Gentoo did not have its own $::osfamily + # Account for distributions that don't have $::osfamily specific settings. + # Before Facter 1.7.0 Gentoo did not have its own $::osfamily case $::operatingsystem { 'Gentoo': { - $config = '/etc/ntp.conf' - $driftfile = '/var/lib/ntp/drift' - $keys_file = '/etc/ntp/keys' + $config = $default_config + $keys_file = $default_keys_file + $driftfile = $default_driftfile + $service_name = $default_service_name $package_name = ['net-misc/ntp'] - $restrict = [ + $restrict = [ 'default kod nomodify notrap nopeer noquery', '-6 default kod nomodify notrap nopeer noquery', '127.0.0.1', '-6 ::1', ] - $service_name = 'ntpd' + $iburst_enable = false $servers = [ '0.gentoo.pool.ntp.org', '1.gentoo.pool.ntp.org', '2.gentoo.pool.ntp.org', '3.gentoo.pool.ntp.org', ] + $maxpoll = undef } default: { fail("The ${module_name} module is not supported on an ${::operatingsystem} distribution.") diff --git a/puphpet/puppet/modules/ntp/manifests/service.pp b/puphpet/puppet/modules/ntp/manifests/service.pp index 3f1ada0..6bc951b 100644 --- a/puphpet/puppet/modules/ntp/manifests/service.pp +++ b/puphpet/puppet/modules/ntp/manifests/service.pp @@ -1,15 +1,15 @@ # class ntp::service inherits ntp { - if ! ($service_ensure in [ 'running', 'stopped' ]) { + if ! ($ntp::service_ensure in [ 'running', 'stopped' ]) { fail('service_ensure parameter must be running or stopped') } - if $service_manage == true { + if $ntp::service_manage == true { service { 'ntp': - ensure => $service_ensure, - enable => $service_enable, - name => $service_name, + ensure => $ntp::service_ensure, + enable => $ntp::service_enable, + name => $ntp::service_name, hasstatus => true, hasrestart => true, } diff --git a/puphpet/puppet/modules/ntp/metadata.json b/puphpet/puppet/modules/ntp/metadata.json index 81b2675..8fb88de 100644 --- a/puphpet/puppet/modules/ntp/metadata.json +++ b/puphpet/puppet/modules/ntp/metadata.json @@ -1,37 +1,63 @@ { + "name": "puppetlabs-ntp", + "version": "4.1.1", + "author": "Puppet Labs", + "summary": "Installs, configures, and manages the NTP service.", + "license": "Apache Version 2.0", + "source": "https://github.com/puppetlabs/puppetlabs-ntp", + "project_page": "https://github.com/puppetlabs/puppetlabs-ntp", + "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", + "dependencies": [ + {"name":"puppetlabs/stdlib","version_requirement":">= 4.6.0 < 5.0.0"} + ], + "data_provider": null, "operatingsystem_support": [ { "operatingsystem": "RedHat", "operatingsystemrelease": [ "5", - "6" + "6", + "7" ] }, { "operatingsystem": "CentOS", "operatingsystemrelease": [ "5", - "6" + "6", + "7" ] }, { "operatingsystem": "OracleLinux", "operatingsystemrelease": [ "5", - "6" + "6", + "7" ] }, { "operatingsystem": "Scientific", "operatingsystemrelease": [ "5", - "6" + "6", + "7" + ] + }, + { + "operatingsystem": "Fedora", + "operatingsystemrelease": [ + "20", + "21", + "22" ] }, { "operatingsystem": "SLES", "operatingsystemrelease": [ - "11 SP1" + "10 SP4", + "11 SP1", + "12" ] }, { @@ -45,7 +71,14 @@ "operatingsystem": "Ubuntu", "operatingsystemrelease": [ "10.04", - "12.04" + "12.04", + "14.04" + ] + }, + { + "operatingsystem": "Solaris", + "operatingsystemrelease": [ + "11" ] }, { @@ -60,25 +93,12 @@ "requirements": [ { "name": "pe", - "version_requirement": "3.2.x" + "version_requirement": ">= 3.7.0 < 2015.3.0" }, { "name": "puppet", - "version_requirement": "3.x" + "version_requirement": ">= 3.0.0 < 5.0.0" } ], - "name": "puppetlabs-ntp", - "version": "3.0.4", - "source": "git://github.com/puppetlabs/puppetlabs-ntp", - "author": "Puppet Labs", - "license": "Apache Version 2.0", - "summary": "NTP Module", - "description": "NTP Module for Debian, Ubuntu, CentOS, RHEL, OEL, Fedora, FreeBSD, ArchLinux and Gentoo.", - "project_page": "http://github.com/puppetlabs/puppetlabs-ntp", - "dependencies": [ - { - "name": "puppetlabs/stdlib", - "version_requirement": ">= 0.1.6" - } - ] + "description": "NTP Module for Debian, Ubuntu, CentOS, RHEL, OEL, Fedora, FreeBSD, ArchLinux and Gentoo." } diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/class_spec.rb b/puphpet/puppet/modules/ntp/spec/acceptance/class_spec.rb index e61f9db..41f5b71 100644 --- a/puphpet/puppet/modules/ntp/spec/acceptance/class_spec.rb +++ b/puphpet/puppet/modules/ntp/spec/acceptance/class_spec.rb @@ -6,10 +6,11 @@ # Apply twice to ensure no errors the second time. apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stderr).to eq("") + expect(r.stderr).not_to match(/error/i) end apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stderr).to eq("") + expect(r.stderr).not_to eq(/error/i) + expect(r.exit_code).to be_zero end end @@ -19,7 +20,7 @@ pp = "class { 'ntp': service_ensure => stopped }" apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stderr).to eq("") + expect(r.stderr).not_to match(/error/i) end end end @@ -29,7 +30,7 @@ pp = "class { 'ntp': service_ensure => running }" apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stderr).to eq("") + expect(r.stderr).not_to match(/error/i) end end end diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/disable_monitoring_spec.rb b/puphpet/puppet/modules/ntp/spec/acceptance/disable_monitoring_spec.rb new file mode 100644 index 0000000..e86c9b8 --- /dev/null +++ b/puphpet/puppet/modules/ntp/spec/acceptance/disable_monitoring_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper_acceptance' + +if (fact('osfamily') == 'Solaris') + config = '/etc/inet/ntp.conf' +else + config = '/etc/ntp.conf' +end + +describe "ntp class with disable_monitor:", :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do + context 'should run successfully' do + pp = "class { 'ntp': disable_monitor => true }" + + it 'runs twice' do + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file("#{config}") do + its(:content) { should match('disable monitor') } + end + end + + context 'should run successfully' do + pp = "class { 'ntp': disable_monitor => false }" + + it 'runs twice' do + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file("#{config}") do + its(:content) { should_not match('disable monitor') } + end + end + +end diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/centos-59-x64.yml b/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/centos-59-x64.yml new file mode 100644 index 0000000..2ad90b8 --- /dev/null +++ b/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/centos-59-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/fedora-21-x64.yml b/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/fedora-21-x64.yml new file mode 100644 index 0000000..3f54b75 --- /dev/null +++ b/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/fedora-21-x64.yml @@ -0,0 +1,9 @@ +HOSTS: + fedora-21: + roles: + - master + platform: fedora-21-x86_64 + box: chef/fedora-21 + hypervisor: vagrant +CONFIG: + type: foss diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/sles-12-64.yml b/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/sles-12-64.yml new file mode 100644 index 0000000..00c147a --- /dev/null +++ b/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/sles-12-64.yml @@ -0,0 +1,20 @@ +--- +HOSTS: + czriitzephrrlzw: + roles: + - master + - database + - dashboard + - agent + - default + platform: sles-12-x86_64 + template: sles-12-x86_64 + hypervisor: vcloud +CONFIG: + 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/ + pe_dir: http://enterprise.delivery.puppetlabs.net/3.4/preview diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml new file mode 100644 index 0000000..cba1cd0 --- /dev/null +++ b/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml @@ -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 diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/ubuntu-server-14042-x64.yml b/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/ubuntu-server-14042-x64.yml new file mode 100644 index 0000000..da3a6d4 --- /dev/null +++ b/puphpet/puppet/modules/ntp/spec/acceptance/nodesets/ubuntu-server-14042-x64.yml @@ -0,0 +1,16 @@ +HOSTS: + ubuntu1404: + roles: + - agent + platform: ubuntu-14.04-amd64 + template: ubuntu-1404-x86_64 + hypervisor: vcloud +CONFIG: + type: foss + keyfile: ~/.ssh/id_rsa-acceptance + 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/ diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/ntp_config_spec.rb b/puphpet/puppet/modules/ntp/spec/acceptance/ntp_config_spec.rb index 196ba76..b93133e 100644 --- a/puphpet/puppet/modules/ntp/spec/acceptance/ntp_config_spec.rb +++ b/puphpet/puppet/modules/ntp/spec/acceptance/ntp_config_spec.rb @@ -2,26 +2,39 @@ case fact('osfamily') when 'FreeBSD' - line = '0.freebsd.pool.ntp.org iburst maxpoll 9' + line = '0.freebsd.pool.ntp.org maxpoll 9 iburst' when 'Debian' line = '0.debian.pool.ntp.org iburst' when 'RedHat' - line = '0.centos.pool.ntp.org' -when 'SuSE' + case fact('operatingsystem') + when 'Fedora' + line = '0.fedora.pool.ntp.org' + else + line = '0.centos.pool.ntp.org' + end +when 'Suse' line = '0.opensuse.pool.ntp.org' when 'Gentoo' line = '0.gentoo.pool.ntp.org' when 'Linux' case fact('operatingsystem') when 'ArchLinux' - line = '0.pool.ntp.org' + line = '0.arch.pool.ntp.org' when 'Gentoo' line = '0.gentoo.pool.ntp.org' end +when 'Solaris' + line = '0.pool.ntp.org' when 'AIX' line = '0.debian.pool.ntp.org iburst' end +if (fact('osfamily') == 'Solaris') + config = '/etc/inet/ntp.conf' +else + config = '/etc/ntp.conf' +end + describe 'ntp::config class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do it 'sets up ntp.conf' do apply_manifest(%{ @@ -29,8 +42,8 @@ class { 'ntp': } }, :catch_failures => true) end - describe file('/etc/ntp.conf') do + describe file("#{config}") do it { should be_file } - it { should contain line } + its(:content) { should match line } end end diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/ntp_install_spec.rb b/puphpet/puppet/modules/ntp/spec/acceptance/ntp_install_spec.rb index 1a451bb..29aac22 100644 --- a/puphpet/puppet/modules/ntp/spec/acceptance/ntp_install_spec.rb +++ b/puphpet/puppet/modules/ntp/spec/acceptance/ntp_install_spec.rb @@ -14,8 +14,19 @@ end when 'AIX' packagename = 'bos.net.tcp.client' +when 'Solaris' + case fact('operatingsystemrelease') + when '5.10' + packagename = ['SUNWntpr','SUNWntpu'] + when '5.11' + packagename = 'service/network/ntp' + end else - packagename = 'ntp' + if fact('operatingsystem') == 'SLES' and fact('operatingsystemmajrelease') == '12' + servicename = 'ntpd' + else + servicename = 'ntp' + end end describe 'ntp::install class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do @@ -25,7 +36,9 @@ class { 'ntp': } }, :catch_failures => true) end - describe package(packagename) do - it { should be_installed } + Array(packagename).each do |package| + describe package(package) do + it { should be_installed } + end end end diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/ntp_parameters_spec.rb b/puphpet/puppet/modules/ntp/spec/acceptance/ntp_parameters_spec.rb index 71a6b20..2ac554d 100644 --- a/puphpet/puppet/modules/ntp/spec/acceptance/ntp_parameters_spec.rb +++ b/puphpet/puppet/modules/ntp/spec/acceptance/ntp_parameters_spec.rb @@ -14,8 +14,25 @@ end when 'AIX' packagename = 'bos.net.tcp.client' +when 'Solaris' + case fact('operatingsystemrelease') + when '5.10' + packagename = ['SUNWntpr','SUNWntpu'] + when '5.11' + packagename = 'service/network/ntp' + end +else + if fact('operatingsystem') == 'SLES' and fact('operatingsystemmajrelease') == '12' + servicename = 'ntpd' + else + servicename = 'ntp' + end +end + +if (fact('osfamily') == 'Solaris') + config = '/etc/inet/ntp.conf' else - packagename = 'ntp' + config = '/etc/ntp.conf' end describe "ntp class:", :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do @@ -23,7 +40,7 @@ pp = "class { 'ntp': }" apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stderr).to eq("") + expect(r.stderr).not_to match(/error/i) end end @@ -60,9 +77,9 @@ apply_manifest(pp, :catch_failures => true) end - describe file('/etc/ntp.conf') do + describe file("#{config}") do it { should be_file } - it { should contain 'testcontent' } + its(:content) { should match 'testcontent' } end end @@ -72,9 +89,9 @@ apply_manifest(pp, :catch_failures => true) end - describe file('/etc/ntp.conf') do + describe file("#{config}") do it { should be_file } - it { should contain 'driftfile /tmp/driftfile' } + its(:content) { should match 'driftfile /tmp/driftfile' } end end @@ -95,12 +112,12 @@ class { 'ntp': apply_manifest(pp, :catch_failures => true) end - describe file('/etc/ntp.conf') do + describe file("#{config}") do it { should be_file } - it { should contain 'keys /etc/ntp/keys' } - it { should contain 'controlkey /etc/ntp/controlkey' } - it { should contain 'requestkey 1' } - it { should contain 'trustedkey 1 2' } + its(:content) { should match 'keys /etc/ntp/keys' } + its(:content) { should match 'controlkey /etc/ntp/controlkey' } + its(:content) { should match 'requestkey 1' } + its(:content) { should match 'trustedkey 1 2' } end end @@ -109,44 +126,46 @@ class { 'ntp': pp = <<-EOS class { 'ntp': package_ensure => present, - package_name => ['#{packagename}'], + package_name => #{Array(packagename).inspect}, } EOS apply_manifest(pp, :catch_failures => true) end - describe package(packagename) do - it { should be_installed } + Array(packagename).each do |package| + describe package(package) do + it { should be_installed } + end end end - describe 'panic => false' do - it 'enables the tinker panic setting' do + describe 'panic => 0' do + it 'disables the tinker panic setting' do pp = <<-EOS class { 'ntp': - panic => false, + panic => 0, } EOS apply_manifest(pp, :catch_failures => true) end - describe file('/etc/ntp.conf') do - it { should contain 'tinker panic' } + describe file("#{config}") do + its(:content) { should match 'tinker panic 0' } end end - describe 'panic => true' do - it 'disables the tinker panic setting' do + describe 'panic => 1' do + it 'enables the tinker panic setting' do pp = <<-EOS class { 'ntp': - panic => true, + panic => 1, } EOS apply_manifest(pp, :catch_failures => true) end - describe file('/etc/ntp.conf') do - it { should_not contain 'tinker panic 0' } + describe file("#{config}") do + its(:content) { should match 'tinker panic 1' } end end @@ -156,9 +175,21 @@ class { 'ntp': apply_manifest(pp, :catch_failures => true) end - describe file('/etc/ntp.conf') do + describe file("#{config}") do + it { should be_file } + its(:content) { should match '127.127.1.0' } + end + end + + describe 'udlc_stratum' do + it 'sets the stratum value when using udlc' do + pp = "class { 'ntp': udlc => true, udlc_stratum => 10 }" + apply_manifest(pp, :catch_failures => true) + end + + describe file("#{config}") do it { should be_file } - it { should contain '127.127.1.0' } + its(:content) { should match 'stratum 10' } end end diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/ntp_service_spec.rb b/puphpet/puppet/modules/ntp/spec/acceptance/ntp_service_spec.rb index cac12de..73edd65 100644 --- a/puphpet/puppet/modules/ntp/spec/acceptance/ntp_service_spec.rb +++ b/puphpet/puppet/modules/ntp/spec/acceptance/ntp_service_spec.rb @@ -1,14 +1,35 @@ require 'spec_helper_acceptance' +require 'specinfra' case fact('osfamily') -when 'RedHat', 'FreeBSD', 'Linux', 'Gentoo' - servicename = 'ntpd' -when 'AIX' - servicename = 'xntpd' -else - servicename = 'ntp' + when 'RedHat', 'FreeBSD', 'Linux', 'Gentoo' + servicename = 'ntpd' + when 'Solaris' + servicename = 'network/ntp' + when 'AIX' + servicename = 'xntpd' + else + if fact('operatingsystem') == 'SLES' and fact('operatingsystemmajrelease') == '12' + servicename = 'ntpd' + else + servicename = 'ntp' + end +end +shared_examples 'running' do + describe service(servicename) do + if !(fact('operatingsystem') == 'SLES' && fact('operatingsystemmajrelease') == '12') + it { should be_running } + it { should be_enabled } + else + # hack until we either update SpecInfra or come up with alternative + it { + output = shell('service ntpd status') + expect(output.stdout).to match(/Active\:\s+active\s+\(running\)/) + expect(output.stdout).to match(/^\s+Loaded.*enabled\)$/) + } + end + end end - describe 'ntp::service class', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do describe 'basic test' do it 'sets up the service' do @@ -17,10 +38,7 @@ class { 'ntp': } }, :catch_failures => true) end - describe service(servicename) do - it { should be_enabled } - it { should be_running } - end + it_should_behave_like 'running' end describe 'service parameters' do @@ -35,29 +53,37 @@ class { 'ntp': EOS apply_manifest(pp, :catch_failures => true) end - - describe service(servicename) do - it { should be_running } - it { should be_enabled } - end + it_should_behave_like 'running' end +end - describe 'service is unmanaged' do - it 'shouldnt stop the service' do - pp = <<-EOS +describe 'service is unmanaged' do + it 'shouldnt stop the service' do + pp = <<-EOS class { 'ntp': service_enable => false, service_ensure => stopped, service_manage => false, service_name => '#{servicename}' } - EOS - apply_manifest(pp, :catch_failures => true) - end + EOS + apply_manifest(pp, :catch_failures => true) + end - describe service(servicename) do + describe service(servicename) do + if !(fact('operatingsystem') == 'SLES' && fact('operatingsystemmajrelease') == '12') it { should be_running } it { should be_enabled } + else + # hack until we either update SpecInfra or come up with alternative + output = shell('service ntpd status', :acceptable_exit_codes => [0, 3]) + it 'should be disabled' do + expect(output.stdout).to match(/^\s+Loaded.*disabled\)$/) + end + it 'should be stopped' do + expect(output.stdout).to match(/Active\:\s+inactive/) + end end end end + diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/preferred_servers_spec.rb b/puphpet/puppet/modules/ntp/spec/acceptance/preferred_servers_spec.rb index 7994ace..0727527 100644 --- a/puphpet/puppet/modules/ntp/spec/acceptance/preferred_servers_spec.rb +++ b/puphpet/puppet/modules/ntp/spec/acceptance/preferred_servers_spec.rb @@ -1,5 +1,11 @@ require 'spec_helper_acceptance' +if (fact('osfamily') == 'Solaris') + config = '/etc/inet/ntp.conf' +else + config = '/etc/ntp.conf' +end + describe 'preferred servers', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do pp = <<-EOS class { '::ntp': @@ -10,15 +16,15 @@ class { '::ntp': it 'applies cleanly' do apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stderr).to eq("") + expect(r.stderr).not_to match(/error/i) end end - describe file('/etc/ntp.conf') do + describe file("#{config}") do it { should be_file } - it { should contain 'server a' } - it { should contain 'server b' } - it { should contain 'server c prefer' } - it { should contain 'server d prefer' } + its(:content) { should match 'server a' } + its(:content) { should match 'server b' } + its(:content) { should match /server c (iburst\s|)prefer/ } + its(:content) { should match /server d (iburst\s|)prefer/ } end end diff --git a/puphpet/puppet/modules/ntp/spec/acceptance/restrict_spec.rb b/puphpet/puppet/modules/ntp/spec/acceptance/restrict_spec.rb index 753b1b3..b919a6b 100644 --- a/puphpet/puppet/modules/ntp/spec/acceptance/restrict_spec.rb +++ b/puphpet/puppet/modules/ntp/spec/acceptance/restrict_spec.rb @@ -1,20 +1,25 @@ require 'spec_helper_acceptance' +if (fact('osfamily') == 'Solaris') + config = '/etc/inet/ntp.conf' +else + config = '/etc/ntp.conf' +end + describe "ntp class with restrict:", :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do context 'should run successfully' do - pp = "class { 'ntp': restrict => ['test restrict']}" - it 'runs twice' do + pp = "class { 'ntp': restrict => ['test restrict']}" 2.times do apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stderr).to be_empty + expect(r.stderr).not_to match(/error/i) end end end end - describe file('/etc/ntp.conf') do - it { should contain('test restrict') } + describe file("#{config}") do + its(:content) { should match('test restrict') } end end diff --git a/puphpet/puppet/modules/ntp/spec/classes/ntp_spec.rb b/puphpet/puppet/modules/ntp/spec/classes/ntp_spec.rb index 5535d9b..fd936fe 100644 --- a/puphpet/puppet/modules/ntp/spec/classes/ntp_spec.rb +++ b/puphpet/puppet/modules/ntp/spec/classes/ntp_spec.rb @@ -1,157 +1,535 @@ require 'spec_helper' describe 'ntp' do + let(:facts) {{ :is_virtual => 'false' }} - ['Debian', 'RedHat','SuSE', 'FreeBSD', 'Archlinux', 'Gentoo', 'Gentoo (Facter < 1.7)'].each do |system| - if system == 'Gentoo (Facter < 1.7)' - let(:facts) {{ :osfamily => 'Linux', :operatingsystem => 'Gentoo' }} - else - let(:facts) {{ :osfamily => system }} - end + ['Debian', 'RedHat', 'Fedora', 'Suse', 'FreeBSD', 'Archlinux', 'Gentoo', 'Gentoo (Facter < 1.7)'].each do |system| + context "when on system #{system}" do + if system == 'Gentoo (Facter < 1.7)' + let :facts do + super().merge({ :osfamily => 'Linux', :operatingsystem => 'Gentoo' }) + end + elsif system == 'Suse' + let :facts do + super().merge({ :osfamily => system,:operatingsystem => 'SLES',:operatingsystemmajrelease => '11' }) + end + elsif system == 'Fedora' + let :facts do + super().merge({ :osfamily => 'RedHat', :operatingsystem => system ,:operatingsystemmajrelease => '22' }) + end + else + let :facts do + super().merge({ :osfamily => system }) + end + end - it { should include_class('ntp::install') } - it { should include_class('ntp::config') } - it { should include_class('ntp::service') } + it { should contain_class('ntp::install') } + it { should contain_class('ntp::config') } + it { should contain_class('ntp::service') } - describe "ntp::config on #{system}" do - it { should contain_file('/etc/ntp.conf').with_owner('0') } - it { should contain_file('/etc/ntp.conf').with_group('0') } - it { should contain_file('/etc/ntp.conf').with_mode('0644') } + describe "ntp::config on #{system}" do + it { should contain_file('/etc/ntp.conf').with_owner('0') } + it { should contain_file('/etc/ntp.conf').with_group('0') } + it { should contain_file('/etc/ntp.conf').with_mode('0644') } - describe 'allows template to be overridden' do - let(:params) {{ :config_template => 'my_ntp/ntp.conf.erb' }} - it { should contain_file('/etc/ntp.conf').with({ - 'content' => /server foobar/}) - } - end + describe 'allows template to be overridden' do + let(:params) {{ :config_template => 'my_ntp/ntp.conf.erb' }} + it { should contain_file('/etc/ntp.conf').with({ + 'content' => /server foobar/}) + } + end - describe "keys for osfamily #{system}" do - context "when enabled" do + describe "keys for osfamily #{system}" do + context "when enabled" do + let(:params) {{ + :keys_enable => true, + :keys_file => '/etc/ntp/ntp.keys', + :keys_trusted => ['1', '2', '3'], + :keys_controlkey => '2', + :keys_requestkey => '3', + }} + + it { should contain_file('/etc/ntp').with({ + 'ensure' => 'directory'}) + } + it { should contain_file('/etc/ntp.conf').with({ + 'content' => /trustedkey 1 2 3/}) + } + it { should contain_file('/etc/ntp.conf').with({ + 'content' => /controlkey 2/}) + } + it { should contain_file('/etc/ntp.conf').with({ + 'content' => /requestkey 3/}) + } + end + end + + context "when disabled" do let(:params) {{ - :keys_enable => true, + :keys_enable => false, :keys_file => '/etc/ntp/ntp.keys', :keys_trusted => ['1', '2', '3'], :keys_controlkey => '2', :keys_requestkey => '3', }} - it { should contain_file('/etc/ntp').with({ + it { should_not contain_file('/etc/ntp').with({ 'ensure' => 'directory'}) } - it { should contain_file('/etc/ntp.conf').with({ + it { should_not contain_file('/etc/ntp.conf').with({ 'content' => /trustedkey 1 2 3/}) } - it { should contain_file('/etc/ntp.conf').with({ + it { should_not contain_file('/etc/ntp.conf').with({ 'content' => /controlkey 2/}) } - it { should contain_file('/etc/ntp.conf').with({ + it { should_not contain_file('/etc/ntp.conf').with({ 'content' => /requestkey 3/}) } end - end - context "when disabled" do - let(:params) {{ - :keys_enable => false, - :keys_file => '/etc/ntp/ntp.keys', - :keys_trusted => ['1', '2', '3'], - :keys_controlkey => '2', - :keys_requestkey => '3', - }} - - it { should_not contain_file('/etc/ntp').with({ - 'ensure' => 'directory'}) - } - it { should_not contain_file('/etc/ntp.conf').with({ - 'content' => /trustedkey 1 2 3/}) - } - it { should_not contain_file('/etc/ntp.conf').with({ - 'content' => /controlkey 2/}) - } - it { should_not contain_file('/etc/ntp.conf').with({ - 'content' => /requestkey 3/}) - } - end + describe 'preferred servers' do + context "when set" do + let(:params) {{ + :servers => ['a', 'b', 'c', 'd'], + :preferred_servers => ['a', 'b'], + :iburst_enable => false, + }} + + it { should contain_file('/etc/ntp.conf').with({ + 'content' => /server a prefer( maxpoll 9)?\nserver b prefer( maxpoll 9)?\nserver c( maxpoll 9)?\nserver d( maxpoll 9)?/}) + } + end + context "when not set" do + let(:params) {{ + :servers => ['a', 'b', 'c', 'd'], + :preferred_servers => [] + }} + + it { should_not contain_file('/etc/ntp.conf').with({ + 'content' => /server a prefer/}) + } + end + end + describe 'specified interfaces' do + context "when set" do + let(:params) {{ + :servers => ['a', 'b', 'c', 'd'], + :interfaces => ['127.0.0.1', 'a.b.c.d'] + }} + + it { should contain_file('/etc/ntp.conf').with({ + 'content' => /interface ignore wildcard\ninterface listen 127.0.0.1\ninterface listen a.b.c.d/}) + } + end + context "when not set" do + let(:params) {{ + :servers => ['a', 'b', 'c', 'd'], + }} + + it { should_not contain_file('/etc/ntp.conf').with({ + 'content' => /interface ignore wildcard/}) + } + end + end + describe 'with parameter disable_auth' do + context 'when set to true' do + let(:params) {{ + :disable_auth => true, + }} + + it 'should contain disable auth setting' do + should contain_file('/etc/ntp.conf').with({ + 'content' => /^disable auth\n/, + }) + end + end + context 'when set to false' do + let(:params) {{ + :disable_auth => false, + }} + + it 'should not contain disable auth setting' do + should_not contain_file('/etc/ntp.conf').with({ + 'content' => /^disable auth\n/, + }) + end + end + end + describe 'with parameter disable_monitor' do + context 'default' do + let(:params) {{ + }} + + it 'should contain disable monitor setting' do + should contain_file('/etc/ntp.conf').with({ + 'content' => /^disable monitor\n/, + }) + end + end + context 'when set to true' do + let(:params) {{ + :disable_monitor => true, + }} + + it 'should contain disable monitor setting' do + should contain_file('/etc/ntp.conf').with({ + 'content' => /^disable monitor\n/, + }) + end + end + context 'when set to false' do + let(:params) {{ + :disable_monitor => false, + }} + + it 'should not contain disable monitor setting' do + should_not contain_file('/etc/ntp.conf').with({ + 'content' => /^disable monitor\n/, + }) + end + end + end + describe 'with parameter broadcastclient' do + context 'when set to true' do + let(:params) {{ + :broadcastclient => true, + }} + + it 'should contain broadcastclient setting' do + should contain_file('/etc/ntp.conf').with({ + 'content' => /^broadcastclient\n/, + }) + end + end + context 'when set to false' do + let(:params) {{ + :broadcastclient => false, + }} + + it 'should not contain broadcastclient setting' do + should_not contain_file('/etc/ntp.conf').with({ + 'content' => /^broadcastclient\n/, + }) + end + end + end - describe 'preferred servers' do - context "when set" do - let(:params) {{ - :servers => ['a', 'b', 'c', 'd'], - :preferred_servers => ['a', 'b'] - }} + describe "ntp::install on #{system}" do + let(:params) {{ :package_ensure => 'present', :package_name => ['ntp'], :package_manage => true, }} - it { should contain_file('/etc/ntp.conf').with({ - 'content' => /server a prefer\nserver b prefer\nserver c\nserver d/}) - } + it { should contain_package('ntp').with( + :ensure => 'present' + )} + + describe 'should allow package ensure to be overridden' do + let(:params) {{ :package_ensure => 'latest', :package_name => ['ntp'], :package_manage => true, }} + it { should contain_package('ntp').with_ensure('latest') } + end + + describe 'should allow the package name to be overridden' do + let(:params) {{ :package_ensure => 'present', :package_name => ['hambaby'], :package_manage => true, }} + it { should contain_package('hambaby') } + end + + describe 'should allow the package to be unmanaged' do + let(:params) {{ :package_manage => false, :package_name => ['ntp'], }} + it { should_not contain_package('ntp') } + end end - context "when not set" do + + describe 'ntp::service' do let(:params) {{ - :servers => ['a', 'b', 'c', 'd'], - :preferred_servers => [] + :service_manage => true, + :service_enable => true, + :service_ensure => 'running', + :service_name => 'ntp' }} - it { should_not contain_file('/etc/ntp.conf').with({ - 'content' => /server a prefer/}) - } + describe 'with defaults' do + it { should contain_service('ntp').with( + :enable => true, + :ensure => 'running', + :name => 'ntp' + )} + end + + describe 'service_ensure' do + describe 'when overridden' do + let(:params) {{ :service_name => 'ntp', :service_ensure => 'stopped' }} + it { should contain_service('ntp').with_ensure('stopped') } + end + end + + describe 'service_manage' do + let(:params) {{ + :service_manage => false, + :service_enable => true, + :service_ensure => 'running', + :service_name => 'ntpd', + }} + + it 'when set to false' do + should_not contain_service('ntp').with({ + 'enable' => true, + 'ensure' => 'running', + 'name' => 'ntpd' + }) + end + end end - end - describe "ntp::install on #{system}" do - let(:params) {{ :package_ensure => 'present', :package_name => ['ntp'], }} + describe 'with parameter iburst_enable' do + context 'when set to true' do + let(:params) {{ + :iburst_enable => true, + }} + + it do + should contain_file('/etc/ntp.conf').with({ + 'content' => /iburst/, + }) + end + end - it { should contain_package('ntp').with( - :ensure => 'present', - :name => 'ntp' - )} + context 'when set to false' do + let(:params) {{ + :iburst_enable => false, + }} - describe 'should allow package ensure to be overridden' do - let(:params) {{ :package_ensure => 'latest', :package_name => ['ntp'] }} - it { should contain_package('ntp').with_ensure('latest') } + it do + should_not contain_file('/etc/ntp.conf').with({ + 'content' => /iburst\n/, + }) + end + end end - describe 'should allow the package name to be overridden' do - let(:params) {{ :package_ensure => 'present', :package_name => ['hambaby'] }} - it { should contain_package('ntp').with_name('hambaby') } + describe 'with tinker parameter changed' do + describe 'when set to false' do + context 'when panic or stepout not overriden' do + let(:params) {{ + :tinker => false, + }} + + it do + should_not contain_file('/etc/ntp.conf').with({ + 'content' => /^tinker /, + }) + end + end + + context 'when panic overriden' do + let(:params) {{ + :tinker => false, + :panic => 257, + }} + + it do + should_not contain_file('/etc/ntp.conf').with({ + 'content' => /^tinker /, + }) + end + end + + context 'when stepout overriden' do + let(:params) {{ + :tinker => false, + :stepout => 5, + }} + + it do + should_not contain_file('/etc/ntp.conf').with({ + 'content' => /^tinker /, + }) + end + end + + context 'when panic and stepout overriden' do + let(:params) {{ + :tinker => false, + :panic => 257, + :stepout => 5, + }} + + it do + should_not contain_file('/etc/ntp.conf').with({ + 'content' => /^tinker /, + }) + end + end + end + describe 'when set to true' do + context 'when only tinker set to true' do + let(:params) {{ + :tinker => true, + }} + + it do + should_not contain_file('/etc/ntp.conf').with({ + 'content' => /^tinker /, + }) + end + end + + context 'when panic changed' do + let(:params) {{ + :tinker => true, + :panic => 257, + }} + + it do + should contain_file('/etc/ntp.conf').with({ + 'content' => /^tinker panic 257\n/, + }) + end + end + + context 'when stepout changed' do + let(:params) {{ + :tinker => true, + :stepout => 5, + }} + + it do + should contain_file('/etc/ntp.conf').with({ + 'content' => /^tinker stepout 5\n/, + }) + end + end + + context 'when panic and stepout changed' do + let(:params) {{ + :tinker => true, + :panic => 257, + :stepout => 5, + }} + + it do + should contain_file('/etc/ntp.conf').with({ + 'content' => /^tinker panic 257 stepout 5\n/, + }) + end + end + end end - end - describe 'ntp::service' do - let(:params) {{ - :service_manage => true, - :service_enable => true, - :service_ensure => 'running', - :service_name => 'ntp' - }} - - describe 'with defaults' do - it { should contain_service('ntp').with( - :enable => true, - :ensure => 'running', - :name => 'ntp' - )} + describe 'with parameters minpoll or maxpoll changed from default' do + context 'when minpoll changed from default' do + let(:params) {{ + :minpoll => 3, + }} + + it do + should contain_file('/etc/ntp.conf').with({ + 'content' => /minpoll 3/, + }) + end + end + + context 'when maxpoll changed from default' do + let(:params) {{ + :maxpoll => 12, + }} + + it do + should contain_file('/etc/ntp.conf').with({ + 'content' => /maxpoll 12\n/, + }) + end + end + + context 'when minpoll and maxpoll changed from default simultaneously' do + let(:params) {{ + :minpoll => 3, + :maxpoll => 12, + }} + + it do + should contain_file('/etc/ntp.conf').with({ + 'content' => /minpoll 3 maxpoll 12\n/, + }) + end + end end - describe 'service_ensure' do - describe 'when overridden' do - let(:params) {{ :service_name => 'ntp', :service_ensure => 'stopped' }} - it { should contain_service('ntp').with_ensure('stopped') } + describe 'with parameter leapfile' do + context 'when set to true' do + let(:params) {{ + :servers => ['a', 'b', 'c', 'd'], + :leapfile => '/etc/leap-seconds.3629404800', + }} + + it 'should contain leapfile setting' do + should contain_file('/etc/ntp.conf').with({ + 'content' => /^leapfile \/etc\/leap-seconds\.3629404800\n/, + }) + end + end + + context 'when set to false' do + let(:params) {{ + :servers => ['a', 'b', 'c', 'd'], + }} + + it 'should not contain a leapfile line' do + should_not contain_file('/etc/ntp.conf').with({ + 'content' => /leapfile /, + }) + end end end - describe 'service_manage' do - let(:params) {{ - :service_manage => false, - :service_enable => true, - :service_ensure => 'running', - :service_name => 'ntpd', - }} + describe 'with parameter logfile' do + context 'when set to true' do + let(:params) {{ + :servers => ['a', 'b', 'c', 'd'], + :logfile => '/var/log/foobar.log', + }} + + it 'should contain logfile setting' do + should contain_file('/etc/ntp.conf').with({ + 'content' => /^logfile \/var\/log\/foobar\.log\n/, + }) + end + end - it 'when set to false' do - should_not contain_service('ntp').with({ - 'enable' => true, - 'ensure' => 'running', - 'name' => 'ntpd' - }) + context 'when set to false' do + let(:params) {{ + :servers => ['a', 'b', 'c', 'd'], + }} + + it 'should not contain a logfile line' do + should_not contain_file('/etc/ntp.conf').with({ + 'content' => /logfile /, + }) + end + end + end + + describe 'peers' do + context 'when empty' do + let(:params) do + { + :peers => [] + } + end + + it 'should not contain a peer line' do + should contain_file('/etc/ntp.conf').without_content(/^peer/) + end + end + + context 'set' do + let(:params) do + { + :peers => ['foo', 'bar'], + } + end + + it 'should contain the peer lines' do + should contain_file('/etc/ntp.conf').with_content(/peer foo/) + should contain_file('/etc/ntp.conf').with_content(/peer bar/) + end end end end @@ -159,8 +537,10 @@ context 'ntp::config' do describe "for operating system Gentoo (Facter < 1.7)" do - let(:facts) {{ :operatingsystem => 'Gentoo', - :osfamily => 'Linux' }} + let :facts do + super().merge({ :operatingsystem => 'Gentoo', + :osfamily => 'Linux' }) + end it 'uses the NTP pool servers by default' do should contain_file('/etc/ntp.conf').with({ @@ -170,7 +550,9 @@ end describe "on osfamily Gentoo" do - let(:facts) {{ :osfamily => 'Gentoo' }} + let :facts do + super().merge({ :osfamily => 'Gentoo' }) + end it 'uses the NTP pool servers by default' do should contain_file('/etc/ntp.conf').with({ @@ -180,17 +562,21 @@ end describe "on osfamily Debian" do - let(:facts) {{ :osfamily => 'debian' }} + let :facts do + super().merge({ :osfamily => 'debian' }) + end it 'uses the debian ntp servers by default' do should contain_file('/etc/ntp.conf').with({ - 'content' => /server \d.debian.pool.ntp.org iburst/, + 'content' => /server \d.debian.pool.ntp.org iburst\n/, }) end end describe "on osfamily RedHat" do - let(:facts) {{ :osfamily => 'RedHat' }} + let :facts do + super().merge({ :osfamily => 'RedHat' }) + end it 'uses the redhat ntp servers by default' do should contain_file('/etc/ntp.conf').with({ @@ -199,18 +585,22 @@ end end - describe "on osfamily SuSE" do - let(:facts) {{ :osfamily => 'SuSE' }} + describe "on osfamily Suse" do + let :facts do + super().merge({ :osfamily => 'Suse', :operatingsystem => 'SLES',:operatingsystemmajrelease => '11' }) + end it 'uses the opensuse ntp servers by default' do should contain_file('/etc/ntp.conf').with({ 'content' => /server \d.opensuse.pool.ntp.org/, - }) + }) end end describe "on osfamily FreeBSD" do - let(:facts) {{ :osfamily => 'FreeBSD' }} + let :facts do + super().merge({ :osfamily => 'FreeBSD' }) + end it 'uses the freebsd ntp servers by default' do should contain_file('/etc/ntp.conf').with({ @@ -220,29 +610,59 @@ end describe "on osfamily ArchLinux" do - let(:facts) {{ :osfamily => 'ArchLinux' }} + let :facts do + super().merge({ :osfamily => 'ArchLinux' }) + end - it 'uses the NTP pool servers by default' do + it 'uses the ArchLinux NTP servers by default' do should contain_file('/etc/ntp.conf').with({ + 'content' => /server \d.arch.pool.ntp.org/, + }) + end + end + + describe "on osfamily Solaris and operatingsystemrelease 5.10" do + let :facts do + super().merge({ :osfamily => 'Solaris', :operatingsystemrelease => '5.10' }) + end + + it 'uses the NTP pool servers by default' do + should contain_file('/etc/inet/ntp.conf').with({ + 'content' => /server \d.pool.ntp.org/, + }) + end + end + + describe "on osfamily Solaris and operatingsystemrelease 5.11" do + let :facts do + super().merge({ :osfamily => 'Solaris', :operatingsystemrelease => '5.11' }) + end + + it 'uses the NTP pool servers by default' do + should contain_file('/etc/inet/ntp.conf').with({ 'content' => /server \d.pool.ntp.org/, }) end end describe "for operating system family unsupported" do - let(:facts) {{ + let :facts do + super().merge({ :osfamily => 'unsupported', - }} + }) + end - it { expect{ subject }.to raise_error( - /^The ntp module is not supported on an unsupported based system./ + it { expect{ catalogue }.to raise_error( + /The ntp module is not supported on an unsupported based system./ )} end end describe 'for virtual machines' do - let(:facts) {{ :osfamily => 'Archlinux', - :is_virtual => 'true' }} + let :facts do + super().merge({ :osfamily => 'Archlinux', + :is_virtual => 'true' }) + end it 'should not use local clock as a time source' do should_not contain_file('/etc/ntp.conf').with({ @@ -258,8 +678,10 @@ end describe 'for physical machines' do - let(:facts) {{ :osfamily => 'Archlinux', - :is_virtual => 'false' }} + let :facts do + super().merge({ :osfamily => 'Archlinux', + :is_virtual => 'false' }) + end it 'disallows large clock skews' do should_not contain_file('/etc/ntp.conf').with({ @@ -268,5 +690,4 @@ end end end - end diff --git a/puphpet/puppet/modules/ntp/spec/spec_helper.rb b/puphpet/puppet/modules/ntp/spec/spec_helper.rb index 2c6f566..270d2ac 100644 --- a/puphpet/puppet/modules/ntp/spec/spec_helper.rb +++ b/puphpet/puppet/modules/ntp/spec/spec_helper.rb @@ -1 +1,28 @@ require 'puppetlabs_spec_helper/module_spec_helper' + +RSpec.configure do |c| + c.include PuppetlabsSpec::Files + + 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 Gem::Version.new(`puppet --version`) >= Gem::Version.new('3.5') + Puppet.settings[:strict_variables]=true + end + if ENV['PARSER'] + Puppet.settings[:parser]=ENV['PARSER'] + end + end + + c.after :each do + PuppetlabsSpec::Files.cleanup + end +end diff --git a/puphpet/puppet/modules/ntp/spec/spec_helper_acceptance.rb b/puphpet/puppet/modules/ntp/spec/spec_helper_acceptance.rb index 3d99cc3..729a1f8 100644 --- a/puphpet/puppet/modules/ntp/spec/spec_helper_acceptance.rb +++ b/puphpet/puppet/modules/ntp/spec/spec_helper_acceptance.rb @@ -1,16 +1,37 @@ require 'beaker-rspec' +require 'beaker/puppet_install_helper' -UNSUPPORTED_PLATFORMS = [ 'windows', 'Solaris' ] +UNSUPPORTED_PLATFORMS = ['windows', 'Darwin'] + +unless ENV['RS_PROVISION'] == 'no' or ENV['BEAKER_provision'] == 'no' + + run_puppet_install_helper -unless ENV['RS_PROVISION'] == 'no' hosts.each do |host| - # Install Puppet - if host.is_pe? - install_pe + # 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 -b 4.6.0 https://github.com/puppetlabs/puppetlabs-stdlib #{destdir}/stdlib" else - install_package host, 'rubygems' - on host, 'gem install puppet --no-ri --no-rdoc' - on host, "mkdir -p #{host['distmoduledir']}" + on host, puppet('module install puppetlabs-stdlib') + end + + # Need to disable update of ntp servers from DHCP, as subsequent restart of ntp causes test failures + if fact_on(host, 'osfamily') == 'Debian' + on host, 'dpkg-divert --divert /etc/dhcp-ntp.bak --local --rename --add /etc/dhcp/dhclient-exit-hooks.d/ntp' + on host, 'dpkg-divert --divert /etc/dhcp3-ntp.bak --local --rename --add /etc/dhcp3/dhclient-exit-hooks.d/ntp' + elsif fact_on(host, 'osfamily') == 'RedHat' + on host, 'echo "PEERNTP=no" >> /etc/sysconfig/network' end end end @@ -24,11 +45,11 @@ # Configure all nodes in nodeset c.before :suite do - # Install module and dependencies - puppet_module_install(:source => proj_root, :module_name => 'ntp') hosts.each do |host| - shell("/bin/touch #{default['puppetpath']}/hiera.yaml") - shell('puppet module install puppetlabs-stdlib', :acceptable_exit_codes => [0,1]) + on host, "mkdir -p #{host['distmoduledir']}/ntp" + %w(lib manifests templates metadata.json).each do |file| + scp_to host, "#{proj_root}/#{file}", "#{host['distmoduledir']}/ntp" + end end end end diff --git a/puphpet/puppet/modules/ntp/templates/ntp.conf.erb b/puphpet/puppet/modules/ntp/templates/ntp.conf.erb index d24126c..c913569 100644 --- a/puphpet/puppet/modules/ntp/templates/ntp.conf.erb +++ b/puphpet/puppet/modules/ntp/templates/ntp.conf.erb @@ -1,9 +1,18 @@ # ntp.conf: Managed by puppet. # -<% if @panic == false -%> -# Keep ntpd from panicking in the event of a large clock skew -# when a VM guest is suspended and resumed. -tinker panic 0 +<% if @tinker == true and (@panic or @stepout) -%> +# Enable next tinker options: +# panic - keep ntpd from panicking in the event of a large clock skew +# when a VM guest is suspended and resumed; +# stepout - allow ntpd change offset faster +tinker<% if @panic -%> panic <%= @panic %><% end %><% if @stepout -%> stepout <%= @stepout %><% end %> +<% end -%> + +<% if @disable_monitor == true -%> +disable monitor +<% end -%> +<% if @disable_auth == true -%> +disable auth <% end -%> <% if @restrict != [] -%> @@ -11,24 +20,55 @@ tinker panic 0 # permit the source to query or modify the service on this system. <% @restrict.flatten.each do |restrict| -%> restrict <%= restrict %> -<% end %> +<% end -%> +<% end -%> + +<% if @interfaces != [] -%> +# Ignore wildcard interface and only listen on the following specified +# interfaces +interface ignore wildcard +<% @interfaces.flatten.each do |interface| -%> +interface listen <%= interface %> +<% end -%> +<% end -%> + +<% if @broadcastclient == true -%> +broadcastclient <% end -%> +# Set up servers for ntpd with next options: +# server - IP address or DNS name of upstream NTP server +# iburst - allow send sync packages faster if upstream unavailable +# prefer - select preferrable server +# minpoll - set minimal update frequency +# maxpoll - set maximal update frequency <% [@servers].flatten.each do |server| -%> -server <%= server %><% if @preferred_servers.include?(server) -%> prefer<% end %> +server <%= server %><% if @iburst_enable == true -%> iburst<% end %><% if @preferred_servers.include?(server) -%> prefer<% end %><% if @minpoll -%> minpoll <%= @minpoll %><% end %><% if @maxpoll -%> maxpoll <%= @maxpoll %><% end %> <% end -%> -<% if scope.lookupvar('::is_virtual') == "false" or @udlc -%> +<% if @udlc -%> # Undisciplined Local Clock. This is a fake driver intended for backup -# and when no outside source of synchronized time is available. -server 127.127.1.0 -fudge 127.127.1.0 stratum 10 +# and when no outside source of synchronized time is available. +server 127.127.1.0 +fudge 127.127.1.0 stratum <%= @udlc_stratum %> restrict 127.127.1.0 <% end -%> # Driftfile. driftfile <%= @driftfile %> +<% unless @logfile.nil? -%> +# Logfile +logfile <%= @logfile %> +<% end -%> + +<% unless @peers.empty? -%> +# Peers +<% [@peers].flatten.each do |peer| -%> +peer <%= peer %> +<% end -%> +<% end -%> + <% if @keys_enable -%> keys <%= @keys_file %> <% unless @keys_trusted.empty? -%> @@ -40,4 +80,13 @@ requestkey <%= @keys_requestkey %> <% if @keys_controlkey != '' -%> controlkey <%= @keys_controlkey %> <% end -%> + +<% end -%> +<% [@fudge].flatten.each do |entry| -%> +fudge <%= entry %> +<% end -%> + +<% unless @leapfile.nil? -%> +# Leapfile +leapfile <%= @leapfile %> <% end -%> diff --git a/puphpet/puppet/modules/php/.fixtures.yml b/puphpet/puppet/modules/php/.fixtures.yml index ca99607..6297887 100644 --- a/puphpet/puppet/modules/php/.fixtures.yml +++ b/puphpet/puppet/modules/php/.fixtures.yml @@ -4,7 +4,8 @@ fixtures: "monitor": "git://github.com/example42/puppet-monitor.git" "firewall": "git://github.com/example42/puppet-firewall.git" "iptables": "git://github.com/example42/puppet-iptables.git" - "concat": "git://github.com/example42/puppet-concat.git" + "concat": "git://github.com/puppetlabs/puppetlabs-concat.git" + "stdlib": "git://github.com/puppetlabs/puppetlabs-stdlib.git" symlinks: "php": "#{source_dir}" diff --git a/puphpet/puppet/modules/php/.gemfile b/puphpet/puppet/modules/php/.gemfile index 459723a..c30bb71 100644 --- a/puphpet/puppet/modules/php/.gemfile +++ b/puphpet/puppet/modules/php/.gemfile @@ -1,6 +1,7 @@ -source :rubygems +source 'https://rubygems.org' puppetversion = ENV['PUPPET_VERSION'] gem 'puppet', puppetversion, :require => false gem 'puppet-lint' +gem 'rspec', '~> 3.1.0', :platforms => :ruby_18 gem 'puppetlabs_spec_helper', '>= 0.1.0' diff --git a/puphpet/puppet/modules/php/.gitignore b/puphpet/puppet/modules/php/.gitignore new file mode 100644 index 0000000..6eebfd2 --- /dev/null +++ b/puphpet/puppet/modules/php/.gitignore @@ -0,0 +1,12 @@ +/.gradle +/.rvmrc +build +pkg/ +Session.vim +spec/fixtures +.*.sw[a-z] +*.un~ +.gemfile.lock +.bundle +vendor + diff --git a/puphpet/puppet/modules/php/.travis.yml b/puphpet/puppet/modules/php/.travis.yml index dffeca9..e0ee697 100644 --- a/puphpet/puppet/modules/php/.travis.yml +++ b/puphpet/puppet/modules/php/.travis.yml @@ -3,17 +3,21 @@ rvm: - 1.8.7 - 1.9.3 script: - - "rake spec SPEC_OPTS='--format documentation'" + - "bundle exec rake spec SPEC_OPTS='--format documentation'" env: - PUPPET_VERSION="~> 2.6.0" - PUPPET_VERSION="~> 2.7.0" - - PUPPET_VERSION="~> 3.0.0" - PUPPET_VERSION="~> 3.1.0" + - PUPPET_VERSION="~> 3.6.0" matrix: exclude: - rvm: 1.9.3 env: PUPPET_VERSION="~> 2.6.0" gemfile: .gemfile + allow_failures: + - rvm: 1.8.7 + env: PUPPET_VERSION="~> 2.6.0" + gemfile: .gemfile gemfile: .gemfile notifications: diff --git a/puphpet/puppet/modules/php/Modulefile b/puphpet/puppet/modules/php/Modulefile deleted file mode 100644 index 55ae208..0000000 --- a/puphpet/puppet/modules/php/Modulefile +++ /dev/null @@ -1,9 +0,0 @@ -name 'example42-php' -version '2.0.17' -author 'Alessandro Franceschi' -license 'Apache2' -project_page 'http://www.example42.com' -source 'https://github.com/example42/puppet-php' -summary 'Puppet module for php' -description 'This module installs and manages php. Check README.rdoc for details. Puppi is required for some common functions: you can install them without using the whole module. Monitor and firewall dependencies are needed only if the relevant features are enabled' -dependency 'example42/puppi', '>= 2.0.0' diff --git a/puphpet/puppet/modules/php/README.md b/puphpet/puppet/modules/php/README.md index a211dcb..f2ba24e 100644 --- a/puphpet/puppet/modules/php/README.md +++ b/puphpet/puppet/modules/php/README.md @@ -38,7 +38,7 @@ For detailed info about the logic and usage patterns of Example42 modules check audit_only => true } -* Install php in an nginx environment +* Define nginx service to be notified on changes class { 'php': service => 'nginx' @@ -68,6 +68,28 @@ For detailed info about the logic and usage patterns of Example42 modules check module_prefix => "php-" } +## USAGE - Module Configuration + +* Configure php module to all SAPI + + php::mod { "mcrypt": } + + *__Note:__ `[name]` is filename without `.ini` extension from `/etc/php5/mods-available/.ini`* + +* Configure multiple php module to all SAPI + + $mods = ["mcrypt", "mongo"] + php::mod { "$mods": } + +* Unconfigure php module to all SAPI + + php::mod { "xdebug" + disable => true, + } + +* Installing and configuring a Module. This will guarantee correct execution order in your classes + + php::module { 'sqlite': } -> php::mod { 'sqlite3': } ## USAGE - Pear Management @@ -111,6 +133,12 @@ For detailed info about the logic and usage patterns of Example42 modules check php::pecl::config { http_proxy: value => "myproxy:8080" } +* Auto-answer prompts for unattended-installation (where configure might used used for instance) + + php::pecl::module { 'stomp': + use_package => 'false', + auto_answer => 'no\\n\\n', + } ## USAGE - Overrides and Customizations * Use custom sources for main config file. diff --git a/puphpet/puppet/modules/php/lib/facter/php_fact_extension_dir.rb b/puphpet/puppet/modules/php/lib/facter/php_fact_extension_dir.rb index 7138a32..c430f8e 100644 --- a/puphpet/puppet/modules/php/lib/facter/php_fact_extension_dir.rb +++ b/puphpet/puppet/modules/php/lib/facter/php_fact_extension_dir.rb @@ -1,5 +1,5 @@ Facter.add("php_fact_extension_dir") do setcode do - Facter::Util::Resolution.exec('php-config --extension-dir') || nil + Facter::Util::Resolution.exec('php -r "ini_alter(\'date.timezone\',\'UTC\'); phpinfo();"|grep \'^extension_dir\'|awk \'{ print $3 }\'') || nil end end diff --git a/puphpet/puppet/modules/php/lib/facter/php_fact_version.rb b/puphpet/puppet/modules/php/lib/facter/php_fact_version.rb index c164c34..3b90dd7 100644 --- a/puphpet/puppet/modules/php/lib/facter/php_fact_version.rb +++ b/puphpet/puppet/modules/php/lib/facter/php_fact_version.rb @@ -1,5 +1,5 @@ Facter.add("php_fact_version") do setcode do - Facter::Util::Resolution.exec('php-config --version') || nil + Facter::Util::Resolution.exec('php -v|awk \'{ print $2 }\'|head -n1') || nil end end diff --git a/puphpet/puppet/modules/php/manifests/augeas.pp b/puphpet/puppet/modules/php/manifests/augeas.pp index 722d65d..d68239f 100644 --- a/puphpet/puppet/modules/php/manifests/augeas.pp +++ b/puphpet/puppet/modules/php/manifests/augeas.pp @@ -65,12 +65,14 @@ $changes = $ensure ? { present => [ "set '${entry}' '${value}'" ], absent => [ "rm '${entry}'" ], + require => Package[$php::package], } augeas { "php_ini-${name}": incl => $target, lens => 'Php.lns', changes => $changes, + require => Package[$php::package], } } diff --git a/puphpet/puppet/modules/php/manifests/devel.pp b/puphpet/puppet/modules/php/manifests/devel.pp index 634f35e..2268ae1 100644 --- a/puphpet/puppet/modules/php/manifests/devel.pp +++ b/puphpet/puppet/modules/php/manifests/devel.pp @@ -7,7 +7,8 @@ if $php::package_devel != '' and ! defined(Package[$php::package_devel]) { package { $php::package_devel : - ensure => $php::manage_package, + ensure => $php::manage_package, + install_options => $php::install_options, } } } diff --git a/puphpet/puppet/modules/php/manifests/ini.pp b/puphpet/puppet/modules/php/manifests/ini.pp index 2851aa4..37c0d2d 100644 --- a/puphpet/puppet/modules/php/manifests/ini.pp +++ b/puphpet/puppet/modules/php/manifests/ini.pp @@ -1,26 +1,67 @@ # = Define: php::ini # +# With this you can alter/add a php ini file for a specific sapi target +# or for both cli and apache2 (default for Ubuntu|Debian|Mint|SLES|OpenSuSE) +# +# == Parameters +# [*value*] +# String. Optional. Default: '' +# The value to be added to the ini file +# +# [*template*] +# String. Optional. Default: 'extra-ini.erb' +# Template to use +# +# [*target*] +# String. Optional. Default: 'extra.ini' +# The configuration filename +# +# [*sapi_target*] +# String. Optional. Default: 'all' +# The target sapi for the configuration file. +# Bu default it will try to apply the configuration to both cli and http +# define php::ini ( - $value = '', - $template = 'extra-ini.erb', - $target = 'extra.ini', - $service = $php::service, - $config_dir = $php::config_dir + $value = '', + $template = 'php/extra-ini.erb', + $target = 'extra.ini', + $sapi_target = 'all', + $service = $php::service, + $config_dir = $php::config_dir, + $package = $php::package ) { include php - file { "${config_dir}/conf.d/${target}": - ensure => 'present', - content => template("php/${template}"), - require => Package['php'], - notify => Service[$service], + $http_sapi = $::operatingsystem ? { + /(?i:Ubuntu|Debian|Mint|SLES|OpenSuSE)/ => '/apache2/', + default => '/', } - file { "${config_dir}/cli/conf.d/${target}": - ensure => 'present', - content => template("php/${template}"), - require => Package['php'], + if ($sapi_target == 'all') { + + file { "${config_dir}${http_sapi}conf.d/${target}": + ensure => 'present', + content => template($template), + require => Package[$package], + before => File["${config_dir}/cli/conf.d/${target}"], + } + + file { "${config_dir}/cli/conf.d/${target}": + ensure => 'present', + content => template($template), + require => Package[$package], + notify => Service[$service], + } + + }else{ + file { "${config_dir}/${sapi_target}/conf.d/${target}": + ensure => 'present', + content => template($template), + require => Package[$package], + notify => Service[$service], + } + } } diff --git a/puphpet/puppet/modules/php/manifests/init.pp b/puphpet/puppet/modules/php/manifests/init.pp index 7370528..331193b 100644 --- a/puphpet/puppet/modules/php/manifests/init.pp +++ b/puphpet/puppet/modules/php/manifests/init.pp @@ -63,6 +63,16 @@ # Note that if the argument absent (see below) is set to true, the # package is removed, whatever the value of version parameter. # +# [*install_options*] +# The package install options to be passed to the package manager. Useful for +# setting advanced/custom options during package install/update. +# For example, adding a `--enablerepo` option to Yum or specifying a +# `--no-install-recommends` option during an Apt install. +# NOTE: The `install_options` package class parameter was added for Yum/Apt +# in Puppet 3.6. Its format of the option is an array, where each option in +# the array is either a string or a hash. +# Example: `install_options => ['-y', {'--enablerepo' => 'remi-php55'}]` +# # [*absent*] # Set to 'true' to remove package(s) installed by module # Can be defined also by the (top scope) variable $php_absent @@ -151,6 +161,7 @@ $augeas = params_lookup( 'augeas' ), $options = params_lookup( 'options' ), $version = params_lookup( 'version' ), + $install_options = params_lookup( 'install_options' ), $absent = params_lookup( 'absent' ), $monitor = params_lookup( 'monitor' , 'global' ), $monitor_tool = params_lookup( 'monitor_tool' , 'global' ), @@ -211,13 +222,14 @@ false => true, } - if ($php::source and $php::template) { + if ($php::source != '' and $php::source != false and $php::template != '' and + $php::template != false) { fail ('PHP: cannot set both source and template') } - if ($php::source and $php::bool_augeas) { + if ($php::source != '' and $php::source != false and $php::bool_augeas) { fail ('PHP: cannot set both source and augeas') } - if ($php::template and $php::bool_augeas) { + if ($php::template != '' and $php::template != false and $php::bool_augeas) { fail ('PHP: cannot set both template and augeas') } @@ -231,10 +243,15 @@ default => template($php::template), } + $realservice_autorestart = $bool_service_autorestart ? { + true => Service[$php::service], + false => undef, + } + ### Managed resources - package { 'php': - ensure => $php::manage_package, - name => $php::package, + package { $php::package: + ensure => $php::manage_package, + install_options => $php::install_options, } file { 'php.conf': @@ -243,21 +260,23 @@ mode => $php::config_file_mode, owner => $php::config_file_owner, group => $php::config_file_group, - require => Package['php'], + require => Package[$php::package], source => $php::manage_file_source, content => $php::manage_file_content, replace => $php::manage_file_replace, audit => $php::manage_audit, + notify => $realservice_autorestart, } # The whole php configuration directory can be recursively overriden - if $php::source_dir { + if $php::source_dir != '' and $php::source_dir != false { file { 'php.dir': ensure => directory, path => $php::config_dir, - require => Package['php'], + require => Package[$php::package], source => $php::source_dir, recurse => true, + links => follow, purge => $php::bool_source_dir_purge, force => $php::bool_source_dir_purge, replace => $php::manage_file_replace, @@ -267,7 +286,7 @@ ### Include custom class if $my_class is set - if $php::my_class { + if $php::my_class != '' and $php::my_class != false { include $php::my_class } diff --git a/puphpet/puppet/modules/php/manifests/mod.pp b/puphpet/puppet/modules/php/manifests/mod.pp new file mode 100644 index 0000000..5587694 --- /dev/null +++ b/puphpet/puppet/modules/php/manifests/mod.pp @@ -0,0 +1,69 @@ +# Define: php::mod +# +# This define configures php mods-available to all SAPI using php5{en,dis}mod +# +# == Parameters +# +# [*disable*] +# Set to 'true' to disable the php mod-availables to all SAPI using php5{dis}mod +# Default: false, i.e, Set the php mod-availables to all SAPI using php5{en}mod. +# +# [*service_autorestart*] +# whatever we want a module installation notify a service to restart. +# +# == Usage +# +# [name] is filename without .ini extension from /etc/php5/mods-available/.ini +# +# php::mod { "": } +# +# == Example +# +# This will configure php5-mcrypt module to all SAPI +# +# php::mod { "mcrypt": } +# +# $mods = ["mcrypt", "mongo"] +# php::mod { "$mods": } +# +# This will unconfigure php5-xdebug module to all SAPI +# +# php::mod { "xdebug": +# disable => true, +# } +# +# Note that you may include or declare the php class when using +# the php::module define +# +define php::mod ( + $disable = false, + $service_autorestart = '', + $path = '/usr/bin:/bin:/usr/sbin:/sbin', + $package = $php::package + ) { + + include php + + if $disable { + $php_mod_tool = 'php5dismod' + } else { + $php_mod_tool = 'php5enmod' + } + + $real_service_autorestart = $service_autorestart ? { + true => "Service[${php::service}]", + false => undef, + '' => $php::service_autorestart ? { + true => "Service[${php::service}]", + false => undef, + } + } + + exec { "php_mod_tool_${name}": + command => "${php_mod_tool} ${name}", + path => $path, + notify => $real_service_autorestart, + require => Package[$package], + } + +} diff --git a/puphpet/puppet/modules/php/manifests/module.pp b/puphpet/puppet/modules/php/manifests/module.pp index 714c1de..eeb622a 100644 --- a/puphpet/puppet/modules/php/manifests/module.pp +++ b/puphpet/puppet/modules/php/manifests/module.pp @@ -26,6 +26,9 @@ # [*module_prefix*] # If package name prefix isn't standard. # +# [*install_options*] +# An array of package manager install options. See $php::install_options +# # == Examples # php::module { 'gd': } # @@ -44,14 +47,16 @@ # define php::module ( $version = 'present', + $install_options = [], $service_autorestart = '', $module_prefix = '', - $absent = '' + $absent = '', + $package = $php::package ) { include php - if $absent { + if $absent != '' and $absent != false { $real_version = 'absent' } else { $real_version = $version @@ -68,17 +73,24 @@ $real_module_prefix = $module_prefix ? { '' => $php::module_prefix, + false => '', default => $module_prefix, } + $real_install_options = $install_options ? { + '' => $php::install_options, + default => $install_options, + } + $real_install_package = "${real_module_prefix}${name}" if defined(Package[$real_install_package]) == false { package { "PhpModule_${name}": - ensure => $real_version, - name => $real_install_package, - notify => $real_service_autorestart, - require => Package['php'], + ensure => $real_version, + name => $real_install_package, + notify => $real_service_autorestart, + install_options => $real_install_options, + require => Package[$package], } } diff --git a/puphpet/puppet/modules/php/manifests/params.pp b/puphpet/puppet/modules/php/manifests/params.pp index 4db3267..70c94e6 100644 --- a/puphpet/puppet/modules/php/manifests/params.pp +++ b/puphpet/puppet/modules/php/manifests/params.pp @@ -98,6 +98,7 @@ $version = 'present' $service_autorestart = true $absent = false + $install_options = [] ### General module variables that can have a site or per module default $puppi = false diff --git a/puphpet/puppet/modules/php/manifests/pear.pp b/puphpet/puppet/modules/php/manifests/pear.pp index a333a84..c69e09c 100644 --- a/puphpet/puppet/modules/php/manifests/pear.pp +++ b/puphpet/puppet/modules/php/manifests/pear.pp @@ -21,17 +21,27 @@ # Can be false if PEAR was already provided by another package or module. # Default: true # +# [*install_options*] +# An array of package manager install options. See $php::install_options +# class php::pear ( $package = $php::package_pear, $install_package = true, + $install_options = [], $version = 'present', $path = '/usr/bin:/usr/sbin:/bin:/sbin' ) inherits php { + $real_install_options = $install_options ? { + '' => $php::install_options, + default => $install_options, + } + if ( $install_package ) { package { 'php-pear': - ensure => $version, - name => $package, + ensure => $version, + name => $package, + install_options => $real_install_options, } } diff --git a/puphpet/puppet/modules/php/manifests/pear/module.pp b/puphpet/puppet/modules/php/manifests/pear/module.pp index 4d11b16..a64f378 100644 --- a/puphpet/puppet/modules/php/manifests/pear/module.pp +++ b/puphpet/puppet/modules/php/manifests/pear/module.pp @@ -7,6 +7,9 @@ # (default=true) - Tries to install pear module with the relevant OS package # If set to "no" it installs the module via pear command # +# [*install_options*] +# An array of package manager install options. See $php::install_options +# # [*preferred_state*] # (default="stable") - Define which preferred state to use when installing # Pear modules via pear via command line (when use_package=false) @@ -23,6 +26,7 @@ define php::pear::module ( $service = '', $use_package = true, + $install_options = [], $preferred_state = 'stable', $alldeps = false, $version = 'present', @@ -59,13 +63,13 @@ } $pear_exec_unless = $ensure ? { - present => "pear info ${pear_source}", + present => "pear shell-test ${pear_source} > 0", absent => undef } $pear_exec_onlyif = $ensure ? { present => undef, - absent => "pear info ${pear_source}", + absent => "pear shell-test ${pear_source} > 0", } $real_service = $service ? { @@ -88,13 +92,19 @@ } $package_name = "${real_module_prefix}${name}" + $real_install_options = $install_options ? { + '' => $php::install_options, + default => $install_options, + } + case $bool_use_package { true: { package { "pear-${name}": - ensure => $ensure, - name => $package_name, - notify => $real_service_autorestart, + ensure => $ensure, + name => $package_name, + install_options => $real_install_options, + notify => $real_service_autorestart, } } default: { diff --git a/puphpet/puppet/modules/php/manifests/pecl/module.pp b/puphpet/puppet/modules/php/manifests/pecl/module.pp index b47b10b..3e40b53 100644 --- a/puphpet/puppet/modules/php/manifests/pecl/module.pp +++ b/puphpet/puppet/modules/php/manifests/pecl/module.pp @@ -14,6 +14,9 @@ # Tries to install pecl module with the relevant package. # If set to "no" it installs the module via pecl command. Default: true # +# [*install_options*] +# An array of package manager install options. See $php::install_options +# # [*preferred_state*] # Define which preferred state to use when installing Pear modules via pecl # command line (when use_package=no). Default: true @@ -39,12 +42,14 @@ $service_autorestart = $php::bool_service_autorestart, $service = $php::service, $use_package = 'yes', + $install_options = [], $preferred_state = 'stable', $auto_answer = '\\n', $ensure = present, $path = '/usr/bin:/usr/sbin:/bin:/sbin', $verbose = false, $version = '', + $prefix = false, $config_file = $php::config_file) { include php @@ -60,21 +65,42 @@ undef => undef, } - $real_package_name = $::operatingsystem ? { - ubuntu => "php5-${name}", - debian => "php5-${name}", - default => "php-${name}", + $real_install_options = $install_options ? { + '' => $php::install_options, + default => $install_options, + } + + case $prefix { + false: { + $real_package_name = $::operatingsystem ? { + ubuntu => "php5-${name}", + debian => "php5-${name}", + default => "php-${name}", + } + } + default: { + $real_package_name = "${prefix}${name}" + } } case $use_package { yes: { package { "php-${name}": - ensure => $ensure, - name => $real_package_name, - notify => $manage_service_autorestart, + ensure => $ensure, + name => $real_package_name, + install_options => $real_install_options, + notify => $manage_service_autorestart, } } default: { + $pcre_dev_package_name = $::osfamily ? { + 'Debian' => 'libpcre3-dev', + 'RedHat' => 'pcre-devel', + default => 'pcre3-devel', + } + if $ensure and !defined(Package[$pcre_dev_package_name]) { + package { $pcre_dev_package_name : } + } $bool_verbose = any2bool($verbose) @@ -90,7 +116,7 @@ } $pecl_exec_command = $ensure ? { - present => "printf \"${auto_answer}\" | pecl -d preferred_state=${preferred_state} install ${name}${new_version}", + present => "printf \"${auto_answer}\" | pecl -d preferred_state=${preferred_state} install ${name}${new_version} && pecl info ${name}", absent => "pecl uninstall -n ${name}", } @@ -99,6 +125,11 @@ absent => undef } + $pecl_exec_require = $ensure ? { + present => [ Class['php::pear'], Class['php::devel'], Package[$pcre_dev_package_name]], + absent => [ Class['php::pear'], Class['php::devel']] + } + $pecl_exec_onlyif = $ensure ? { present => undef, absent => "pecl info ${name}", @@ -110,7 +141,8 @@ onlyif => $pecl_exec_onlyif, logoutput => $pecl_exec_logoutput, path => $path, - require => [ Class['php::pear'], Class['php::devel']], + require => $pecl_exec_require, + notify => $manage_service_autorestart, } if $php::bool_augeas == true { php::augeas { "augeas-${name}": diff --git a/puphpet/puppet/modules/php/metadata.json b/puphpet/puppet/modules/php/metadata.json new file mode 100644 index 0000000..8c67190 --- /dev/null +++ b/puphpet/puppet/modules/php/metadata.json @@ -0,0 +1,21 @@ +{ + "name": "example42-php", + "version": "2.0.25", + "summary": "Puppet module for php", + "author": "Alessandro Franceschi", + "description": "This module installs and manages php. Check README.rdoc for details. Puppi is required for some common functions: you can install them without using the whole module. Monitor and firewall dependencies are needed only if the relevant features are enabled", + "dependencies": [ + { + "name": "example42/puppi", + "version_requirement": ">= 2.0.0" + } + ], + "types": [ + + ], + "checksums": { + }, + "source": "https://github.com/example42/puppet-php", + "project_page": "http://www.example42.com", + "license": "Apache2" +} diff --git a/puphpet/puppet/modules/php/spec/classes/php_spec.rb b/puphpet/puppet/modules/php/spec/classes/php_spec.rb index be9a4e3..a57059c 100644 --- a/puphpet/puppet/modules/php/spec/classes/php_spec.rb +++ b/puphpet/puppet/modules/php/spec/classes/php_spec.rb @@ -25,50 +25,26 @@ describe 'Test customizations - template' do let(:params) { {:template => "php/spec.erb" , :options => { 'opt_a' => 'value_a' } } } - - it 'should generate a valid template' do - content = catalogue.resource('file', 'php.conf').send(:parameters)[:content] - content.should match "fqdn: rspec.example42.com" - end - it 'should generate a template that uses custom options' do - content = catalogue.resource('file', 'php.conf').send(:parameters)[:content] - content.should match "value_a" - end - + it { should contain_file('php.conf').with_content(/fqdn: rspec.example42.com/) } + it { should contain_file('php.conf').with_content(/value_a/) } end describe 'Test customizations - source' do let(:params) { {:source => "puppet://modules/php/spec" , :source_dir => "puppet://modules/php/dir/spec" , :source_dir_purge => true } } - - it 'should request a valid source ' do - content = catalogue.resource('file', 'php.conf').send(:parameters)[:source] - content.should == "puppet://modules/php/spec" - end - it 'should request a valid source dir' do - content = catalogue.resource('file', 'php.dir').send(:parameters)[:source] - content.should == "puppet://modules/php/dir/spec" - end - it 'should purge source dir if source_dir_purge is true' do - content = catalogue.resource('file', 'php.dir').send(:parameters)[:purge] - content.should == true - end + it { should contain_file('php.conf').with_source('puppet://modules/php/spec') } + it { should contain_file('php.dir').with_source('puppet://modules/php/dir/spec') } + it { should contain_file('php.dir').with_purge('true') } end describe 'Test customizations - custom class' do let(:params) { {:my_class => "php::spec" } } - it 'should automatically include a custom class' do - content = catalogue.resource('file', 'php.conf').send(:parameters)[:content] - content.should match "fqdn: rspec.example42.com" - end + it { should contain_file('php.conf').with_content(/fqdn: rspec.example42.com/) } end describe 'Test Puppi Integration' do let(:params) { {:puppi => true, :puppi_helper => "myhelper"} } - it 'should generate a puppi::ze define' do - content = catalogue.resource('puppi::ze', 'php').send(:parameters)[:helper] - content.should == "myhelper" - end + it { should contain_puppi__ze('php').with_helper('myhelper') } end diff --git a/puphpet/puppet/modules/php/spec/defines/php_pear_module_spec.rb b/puphpet/puppet/modules/php/spec/defines/php_pear_module_spec.rb index b093a8a..89e652a 100644 --- a/puphpet/puppet/modules/php/spec/defines/php_pear_module_spec.rb +++ b/puphpet/puppet/modules/php/spec/defines/php_pear_module_spec.rb @@ -39,7 +39,7 @@ it 'should install pear module with exec commands' do should contain_exec('pear-Crypt-CHAP').with( 'command' => 'pear -d preferred_state=stable install pear.php.net/Crypt-CHAP', - 'unless' => 'pear info pear.php.net/Crypt-CHAP' + 'unless' => 'pear shell-test pear.php.net/Crypt-CHAP > 0' ) end end diff --git a/puphpet/puppet/modules/postgresql/.fixtures.yml b/puphpet/puppet/modules/postgresql/.fixtures.yml index 5dbd5d0..44121bb 100644 --- a/puphpet/puppet/modules/postgresql/.fixtures.yml +++ b/puphpet/puppet/modules/postgresql/.fixtures.yml @@ -1,6 +1,8 @@ fixtures: repositories: - apt: "https://github.com/puppetlabs/puppetlabs-apt.git" + apt: + repo: "https://github.com/puppetlabs/puppetlabs-apt.git" + branch: "1.8.x" stdlib: "https://github.com/puppetlabs/puppetlabs-stdlib.git" firewall: "https://github.com/puppetlabs/puppetlabs-firewall.git" concat: "https://github.com/puppetlabs/puppetlabs-concat.git" diff --git a/puphpet/puppet/modules/postgresql/.gitignore b/puphpet/puppet/modules/postgresql/.gitignore new file mode 100644 index 0000000..b5db85e --- /dev/null +++ b/puphpet/puppet/modules/postgresql/.gitignore @@ -0,0 +1,9 @@ +pkg/ +Gemfile.lock +vendor/ +spec/fixtures/ +.vagrant/ +.bundle/ +coverage/ +.idea/ +*.iml diff --git a/puphpet/puppet/modules/postgresql/.sync.yml b/puphpet/puppet/modules/postgresql/.sync.yml index 330d6ff..ac83790 100644 --- a/puphpet/puppet/modules/postgresql/.sync.yml +++ b/puphpet/puppet/modules/postgresql/.sync.yml @@ -1,9 +1,9 @@ --- .travis.yml: extras: - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 3.5" STRICT_VARIABLES="yes" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3.5" STRICT_VARIABLES="yes" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0" spec/spec_helper.rb: unmanaged: true diff --git a/puphpet/puppet/modules/postgresql/.travis.yml b/puphpet/puppet/modules/postgresql/.travis.yml index da34ec6..7e8ed57 100644 --- a/puphpet/puppet/modules/postgresql/.travis.yml +++ b/puphpet/puppet/modules/postgresql/.travis.yml @@ -1,4 +1,5 @@ --- +sudo: false language: ruby bundler_args: --without system_tests script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake spec SPEC_OPTS='--format documentation'" @@ -6,16 +7,18 @@ matrix: fast_finish: true include: - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0" - - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0" + env: PUPPET_GEM_VERSION="~> 3.0" - rvm: 1.9.3 env: PUPPET_GEM_VERSION="~> 3.0" - - rvm: 2.0.0 + - rvm: 2.1.5 env: PUPPET_GEM_VERSION="~> 3.0" - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 3.5" STRICT_VARIABLES="yes" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3.5" STRICT_VARIABLES="yes" + - rvm: 2.1.5 + env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes" + - rvm: 2.1.6 + env: PUPPET_GEM_VERSION="~> 4.0" STRICT_VARIABLES="yes" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0" + - rvm: 1.8.7 + env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0" notifications: email: false diff --git a/puphpet/puppet/modules/postgresql/CHANGELOG.md b/puphpet/puppet/modules/postgresql/CHANGELOG.md index f36bf82..49ad2cc 100644 --- a/puphpet/puppet/modules/postgresql/CHANGELOG.md +++ b/puphpet/puppet/modules/postgresql/CHANGELOG.md @@ -1,3 +1,95 @@ +## 2015-09-01 - Supported Release 4.6.0 +### Summary +This release adds a proxy feature for yum, Postgis improvements, and decoupling pg_hba_rule from postgresql::server. + +#### Features +- Support setting a proxy for yum operations +- Allow for undefined PostGIS version +- Decouple pg_hba_rule from postgresql::server + +#### Bugfixes +- Fix postgis default package name on RedHat + +## 2015-07-27 - Supported Release 4.5.0 +### Summary +This release adds sequence grants, some postgresql 9.4 fixes, and `onlyif` to +the psql resource. + +### Features +- Add `onlyif` parameter to `postgresql_psql` +- Add unsupported compatibility with Ubuntu 15.04 +- Add unsupported compatibility with SLES 11/12 and OpenSuSE 13.2 +- Add `postgresql::server::grant::onlyif_exists` attribute +- Add `postgresql::server::table_grant::onlyif_exists` attribute +- Add granting permissions on sequences + +### Bugfixes +- Added docs for `postgresql::server::grant` +- Fix `pg_hba_conf_defaults => false` to not disable ipv4/ipv6 acls +- Fix 9.4 for `postgresql::server::pg_hba_rule` + +## 2015-07-07 - Supported Release 4.4.2 +### Summary +This release fixes a bug introduced in 4.4.0. + +#### Bugfixes +- Fixes `withenv` execution under Puppet 2.7. (MODULES-2185) + +## 2015-07-01 - Supported Release 4.4.1 +### Summary +This release fixes RHEL 7 & Fedora with manage_package_repo switched on. + +#### Bugfixes +- Ensure manage_package_repo variable is in scope for systemd-override file for RHEL7 + +## 2015-06-30 - Supported Release 4.4.0 +### Summary +This release has several new features, bugfixes, and test improvements. + +#### Features +- Adds a resource to manage recovery.conf. +- Adds a parameter that allows the specification of a validate connection script in `postgresql::client`. +- Adds support for plpython package management. +- Adds support for postgresql-docs management. +- Adds ability to make `postgresql::server::schema` titles unique. (MODULES-2049) +- Updates puppetlabs-apt module dependency to support version 2.1.0. + +#### Bugfixes +- Fix `postgresql_psql` parameter ordering to work on OpenBSD with Future Parser +- Fix setting postgres role password (MODULES-1869) +- Fix execution command with puppet <3.4 (MODULES-1923) +- Fix Puppet.newtype deprecation warning (MODULES-2007) +- Fix systemd override for manage_repo package versions +- Fix Copy snakeoil certificate and key instead of symlinking + +#### Test Improvements +- Allows setting BEAKER and BEAKER_RSPEC versions via environment variables. +- Enables Unit testing on Travis CI with Puppet 4. +- Cleans up spec_helper_acceptance.rb to use new puppet_install_helper gem. + +## 2015-03-24 - Supported Release 4.3.0 +### Summary +This release fixes compatibility with Puppet 4 and removes opportunities for local users to view the postgresql password. It also adds a new custom resource to aid in managing replication. + +#### Features +- Add `postgresql::server::logdir` parameter to manage the logdir +- Add `environment` parameter to `postgresql_psql` +- Add `postgresql_replication_slot` custom resource + +#### Bugfixes +- Fix for Puppet 4 +- Don't print postgresql\_psql password in command +- Allow `postgresql::validate_db_connection` for more than one host+port+database combo +- Fix service command on Debian 8 and up +- Fix `postgresql::server::extension` to work with custom user/group/port +- Fix `postgresql::server::initdb` to work with custom user/group/port +- Fix changing template1 encoding +- Fix default `postgresql::server::grant::object_name` value +- Fix idempotency of granting all tables in schema with `puppet::server::grant` +- Fix lint warnings +- Fix apt key to use 40 character key and bump puppetlabs-apt to >= 1.8.0 < 2.0.0 + + ##2015-03-10 - Supported Release 4.2.0 ###Summary diff --git a/puphpet/puppet/modules/postgresql/Gemfile b/puphpet/puppet/modules/postgresql/Gemfile index 62c5693..bfe64b1 100644 --- a/puphpet/puppet/modules/postgresql/Gemfile +++ b/puphpet/puppet/modules/postgresql/Gemfile @@ -1,21 +1,38 @@ 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', :require => false gem 'rspec-core', '3.1.7', :require => false - gem 'rspec-puppet', '~> 1.0', :require => false gem 'puppetlabs_spec_helper', :require => false - gem 'puppet-lint', :require => false gem 'simplecov', :require => false gem 'puppet_facts', :require => false gem 'json', :require => false end group :system_tests do - gem 'beaker-rspec', :require => false + 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 diff --git a/puphpet/puppet/modules/postgresql/README.md b/puphpet/puppet/modules/postgresql/README.md index 3690a11..737a25a 100644 --- a/puphpet/puppet/modules/postgresql/README.md +++ b/puphpet/puppet/modules/postgresql/README.md @@ -8,7 +8,7 @@ Table of Contents 2. [Module Description - What does the module do?](#module-description) 3. [Setup - The basics of getting started with PostgreSQL module](#setup) * [PE 3.2 supported module](#pe-32-supported-module) - * [Configuring the server](#configuring-the-server) + * [Configuring the server](#configuring-the-server) 4. [Usage - How to use the module for various tasks](#usage) 5. [Reference - The classes, defines,functions and facts available in this module](#reference) 6. [Limitations - OS compatibility, etc.](#limitations) @@ -131,10 +131,12 @@ Classes: * [postgresql::globals](#class-postgresqlglobals) * [postgresql::lib::devel](#class-postgresqllibdevel) * [postgresql::lib::java](#class-postgresqllibjava) +* [postgresql::lib::docs](#class-postgresqllibdocs) * [postgresql::lib::perl](#class-postgresqllibperl) * [postgresql::lib::python](#class-postgresqllibpython) * [postgresql::server](#class-postgresqlserver) * [postgresql::server::plperl](#class-postgresqlserverplperl) +* [postgresql::server::plpython](#class-postgresqlserverplpython) * [postgresql::server::contrib](#class-postgresqlservercontrib) * [postgresql::server::postgis](#class-postgresqlserverpostgis) @@ -147,12 +149,19 @@ Resources: * [postgresql::server::extension](#resource-postgresqlserverextension) * [postgresql::server::pg_hba_rule](#resource-postgresqlserverpg_hba_rule) * [postgresql::server::pg_ident_rule](#resource-postgresqlserverpg_ident_rule) +* [postgresql::server::recovery](#resource-postgresqlserverrecovery) * [postgresql::server::role](#resource-postgresqlserverrole) * [postgresql::server::schema](#resource-postgresqlserverschema) * [postgresql::server::table_grant](#resource-postgresqlservertable_grant) * [postgresql::server::tablespace](#resource-postgresqlservertablespace) * [postgresql::validate_db_connection](#resource-postgresqlvalidate_db_connection) +Custom Resources: + +* [postgresql\_psql](#custom-resource-postgresql_psql) +* [postgresql\_replication\_slot](#custom-resource-postgresql_replication_slot) +* [postgresql\_conf](#custom-resource-postgresql_conf) + Functions: * [postgresql\_password](#function-postgresql_password) @@ -198,12 +207,18 @@ This setting can be used to override the default postgresql devel package name. ####`java_package_name` This setting can be used to override the default postgresql java package name. If not specified, the module will use whatever package name is the default for your OS distro. +####`docs_package_name` +This setting can be used to override the default postgresql docs package name. If not specified, the module will use whatever package name is the default for your OS distro. + ####`perl_package_name` This setting can be used to override the default postgresql Perl package name. If not specified, the module will use whatever package name is the default for your OS distro. ####`plperl_package_name` This setting can be used to override the default postgresql PL/perl package name. If not specified, the module will use whatever package name is the default for your OS distro. +####`plpython_package_name` +This setting can be used to override the default postgresql PL/python package name. If not specified, the module will use whatever package name is the default for your OS distro. + ####`python_package_name` This setting can be used to override the default postgresql Python package name. If not specified, the module will use whatever package name is the default for your OS distro. @@ -240,6 +255,9 @@ Path to your `pg\_ident.conf` file. ####`postgresql_conf_path` Path to your `postgresql.conf` file. +####`recovery_conf_path` +Path to your `recovery.conf` file. + ####`pg_hba_conf_defaults` If false, disables the defaults supplied with the module for `pg\_hba.conf`. This is useful if you disagree with the defaults and wish to override them yourself. Be sure that your changes of course align with the rest of the module, as some access is required to perform basic `psql` operations for example. @@ -257,6 +275,9 @@ This setting can be used to override the default postgresql binaries directory f ####`xlogdir` This setting can be used to override the default postgresql xlog directory. If not specified the module will use initdb's default path. +####`logdir` +This setting can be used to override the default postgresql log directory. If not specified the module will use initdb's default path. + ####`user` This setting can be used to override the default postgresql super user and owner of postgresql related files in the file system. If not specified, the module will use the user name 'postgres'. @@ -280,6 +301,10 @@ This will set the default encoding encoding for all databases created with this ####`locale` This will set the default database locale for all databases created with this module. On certain operating systems this will be used during the `template1` initialization as well so it becomes a default outside of the module as well. Defaults to `undef` which is effectively `C`. +####`repo_proxy` +This will set the proxy option for the official PostgreSQL yum-repositories only, Debian is currently not supported. This is useful if your server is behind a corporate firewall and needs to use proxyservers for outside connectivity. + + #####Debian On Debian you'll need to ensure that the 'locales-all' package is installed for full functionality of Postgres. @@ -302,6 +327,9 @@ Value to pass through to the `package` resource when creating the server instanc ####`plperl_package_name` This sets the default package name for the PL/Perl extension. Defaults to utilising the operating system default. +####`plpython_package_name` +This sets the default package name for the PL/Python extension. Defaults to utilising the operating system default. + ####`service_manage` This setting selects whether Puppet should manage the service. Defaults to `true`. @@ -356,6 +384,9 @@ Path to your `pg\_ident.conf` file. ####`postgresql_conf_path` Path to your `postgresql.conf` file. +####`recovery_conf_path` +Path to your `recovery.conf` file. + ####`pg_hba_conf_defaults` If false, disables the defaults supplied with the module for `pg\_hba.conf`. This is useful if you di sagree with the defaults and wish to override them yourself. Be sure that your changes of course alig @@ -387,10 +418,16 @@ This value defaults to `true`. Whether or not manage the pg_hba.conf. If set to ####`manage_pg_ident_conf` This value defaults to `true`. Whether or not manage the pg_ident.conf. If set to `true`, puppet will overwrite this file. If set to `false`, puppet will not modify the file. +####`manage_recovery_conf` +This value defaults to `false`. Whether or not manage the recovery.conf. If set to `true`, puppet will overwrite this file. If set to `false`, puppet will not create the file. + ###Class: postgresql::client This class installs postgresql client software. Alter the following parameters if you have a custom version you would like to install (Note: don't forget to make sure to add any necessary yum or apt repositories if specifying a custom version): +####`validcon_script_path` +Path to validate connection script. Defaults to `/usr/local/bin/validate_postgresql_connection.sh`. + ####`package_name` The name of the postgresql client package. @@ -434,6 +471,15 @@ The name of the postgresql java package. ####`package_ensure` The ensure parameter passed on to postgresql java package resource. +###Class: postgresql::lib::docs +This class installs postgresql bindings for Postgres-Docs. Alter the following parameters if you have a custom version you would like to install (Note: don't forget to make sure to add any necessary yum or apt repositories if specifying a custom version): + +####`package_name` +The name of the postgresql docs package. + +####`package_ensure` +The ensure parameter passed on to postgresql docs package resource. + ###Class: postgresql::lib::perl This class installs the postgresql Perl libraries. For customer requirements you can customise the following parameters: @@ -444,6 +490,14 @@ The name of the postgresql perl package. ####`package_ensure` The ensure parameter passed on to postgresql perl package resource. +###Class: postgresql::server::plpython +This class installs the PL/Python procedural language for postgresql. + +####`package_name` +The name of the postgresql PL/Python package. + +####`package_ensure` +The ensure parameter passed on to postgresql PL/Python package resource. ###Class: postgresql::lib::python This class installs the postgresql Python libraries. For customer requirements you can customise the following parameters: @@ -596,6 +650,39 @@ If provided, this will install the given package prior to activating the extensi ####`package_ensure` By default, the package specified with `package_name` will be installed when the extension is activated, and removed when the extension is deactivated. You can override this behavior by setting the `ensure` value for the package. +###Resource: postgresql::server::grant +This defined type manages grant based access privileges for roles. Consult the PostgreSQL documentation for `grant` for more information. + +####`namevar` +Used to uniquely identify this resource, but functionality not used during grant. + +####`db` +Database of object which you are granting access on. + +####`role` +Role or user whom you are granting access for. + +####`privilege` +The privilege you are granting. Can be `ALL`, `ALL PRIVILEGES` or +`object_type` dependent string. + +####`object_type` +The type of object you are granting privileges on. Can be `DATABASE`, +`SCHEMA`, `SEQUENCE`, `ALL SEQUENCES IN SCHEMA`, `TABLE` or `ALL +TABLES IN SCHEMA`. + +####`object_name` +Object of type `object_type` on which to grant access. + +####`psql_db` +Database to execute the grant against. This should not ordinarily be changed from the default, which is `postgres`. + +####`psql_user` +OS user for running `psql`. Defaults to the default user for the module, usually `postgres`. + +####`port` +Port to use when connecting. Default to 'undef' which generally defaults to 5432 depending on your PostgreSQL packaging. + ###Resource: postgresql::server::pg\_hba\_rule This defined type allows you to create an access rule for `pg_hba.conf`. For more details see the [PostgreSQL documentation](http://www.postgresql.org/docs/8.2/static/auth-pg-hba-conf.html). @@ -617,6 +704,19 @@ This would create a ruleset in `pg_hba.conf` similar to: # Order: 150 host app app 200.1.2.0/24 md5 +By default, `pg_hba_rule` requires that you include `postgresql::server`, however, you can override that behavior by setting target and postgresql_version when declaring your rule. That might look like the following. + + postgresql::server::pg_hba_rule { 'allow application network to access app database': + description => "Open up postgresql for access from 200.1.2.0/24", + type => 'host', + database => 'app', + user => 'app', + address => '200.1.2.0/24', + auth_method => 'md5', + target => '/path/to/pg_hba.conf', + postgresql_version => '9.4', + } + ####`namevar` A unique identifier or short description for this rule. The namevar doesn't provide any functional usage, but it is stored in the comments of the produced `pg_hba.conf` so the originating resource can be identified. @@ -647,6 +747,8 @@ An order for placing the rule in `pg_hba.conf`. Defaults to `150`. ####`target` This provides the target for the rule, and is generally an internal only property. Use with caution. +####`postgresql_version` +Defaults to the version set in `postgresql::server`. Use this if you want to manage `pg_hba.conf` without managing the entire PostgreSQL instance. ###Resource: postgresql::server::pg\_ident\_rule This defined type allows you to create user name maps for `pg_ident.conf`. For more details see the [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/auth-username-maps.html). @@ -687,6 +789,65 @@ An order for placing the mapping in pg_ident.conf. Defaults to 150. ####`target` This provides the target for the rule, and is generally an internal only property. Use with caution. +###Resource: postgresql::server::recovery +This defined type allows you to create the content for `recovery.conf`. For more details see the [PostgreSQL documentation](http://www.postgresql.org/docs/9.4/static/recovery-config.html). + +For example: + + postgresql::server::recovery{ 'Create a recovery.conf file with the following defined parameters': + restore_command => 'cp /mnt/server/archivedir/%f %p', + archive_cleanup_command => undef, + recovery_end_command => undef, + recovery_target_name => 'daily backup 2015-01-26', + recovery_target_time => '2015-02-08 22:39:00 EST', + recovery_target_xid => undef, + recovery_target_inclusive => true, + recovery_target => 'immediate', + recovery_target_timeline => 'latest', + pause_at_recovery_target => true, + standby_mode => 'on', + primary_conninfo => 'host=localhost port=5432', + primary_slot_name => undef, + trigger_file => undef, + recovery_min_apply_delay => 0, + } + +This would create a `recovery.conf` config file, similar to this: + + restore_command = 'cp /mnt/server/archivedir/%f %p' + recovery_target_name = 'daily backup 2015-01-26' + recovery_target_time = '2015-02-08 22:39:00 EST' + recovery_target_inclusive = true + recovery_target = 'immediate' + recovery_target_timeline = 'latest' + pause_at_recovery_target = true + standby_mode = on + primary_conninfo = 'host=localhost port=5432' + recovery_min_apply_delay = 0 + + +Only the specified parameters will be recognize in the template! The `recovery.conf` will be only create if at least one parameter set and [manage_recovery_conf](#manage_recovery_conf) set to true. + +Every param value is a String set in the template with inverted comma except `recovery_target_inclusive`, `pause_at_recovery_target`, `standby_mode` and `recovery_min_apply_delay`. +`standby_mode` is special, String ('on'/'off') and Boolean (true/false) is allowed, but the postgres documentation says it's a Boolean. + +A detailed description of all above listed parameters can be found in the [PostgreSQL documentation](http://www.postgresql.org/docs/9.4/static/recovery-config.html). + +The parameters are grouped into these three sections: + + +#### [`Archive Recovery Parameters`](http://www.postgresql.org/docs/9.4/static/archive-recovery-settings.html) +In this section the `restore_command`, `archive_cleanup_command` and `recovery_end_command` parameters are listed. + +#### [`Recovery Target Settings`](http://www.postgresql.org/docs/9.4/static/recovery-target-settings.html) +In this section the `recovery_target_name`, `recovery_target_time`, `recovery_target_xid`, `recovery_target_inclusive`, `recovery_target`, `recovery_target_timeline` and `pause_at_recovery_target` parameters are listed. + +#### [`Standby Server Settings`](http://www.postgresql.org/docs/9.4/static/standby-settings.html) +In this section the `standby_mode`, `primary_conninfo`, `primary_slot_name`, `trigger_file` and `recovery_min_apply_delay` parameters are listed. + +####`target` +This provides the target for the rule, and is generally an internal only property. Use with caution. + ###Resource: postgresql::server::role This resource creates a role or user in PostgreSQL. @@ -843,6 +1004,74 @@ Upon failure, sets the number of attempts before giving up and failing the resou This will ensure the database is created before running the test. This only really works if your test is local. Defaults to `true`. +### Custom Resource: postgresql\_psql +This type allows puppet to run psql statements. + +#### `name` +An arbitrary tag for your own reference; the name of the message. This is the +namevar. + +#### `command` +The SQL command to execute via psql. Required. + +#### `cwd` +The working directory under which the psql command should be executed. Defaults +to '/tmp' + +#### `db` +The name of the database to execute the SQL command against. + +#### `environment` +Any additional environment variables you want to set for a SQL command. +Multiple environment variables should be specified as an array. + +#### `port` +The port of the database server to execute the SQL command against. + +#### `psql\_group` +The system user group account under which the psql command should be executed. +Defaults to 'postgres' + +#### `psql\_path` +The path to psql executable. Defaults to 'psql' + +#### `psql\_user` +The system user account under which the psql command should be executed. +Defaults to "postgres" + +#### `refreshonly` +If 'true', then the SQL will only be executed via a notify/subscribe event. +Valid values are true or false. Defaults to false. + +#### `search\_path` +The schema search path to use when executing the SQL command + +#### `unless` +An optional SQL command to execute prior to the main :command; this is +generally intended to be used for idempotency, to check for the existence of an +object in the database to determine whether or not the main SQL command needs +to be executed at all. + +### Custom Resource: postgresql\_conf +This type allows puppet to manage postgresql.conf parameters. + +#### `name` +The postgresql parameter name to manage. This is the namevar. + +#### `target` +The path to postgresql.conf. Defaults to '/etc/postgresql.conf' + +#### `value` +The value to set for this parameter. + +### Custom Resource: postgresql\_replication\_slot +This type allows to create and destroy replication slots +to register warm standby replication on a Postgresql +master server. + +#### `name` +The name of the slot to create. Must be a validt replication slot name. This is the namevar. + ###Function: postgresql\_password If you need to generate a postgres encrypted password, use `postgresql_password`. You can call it from your production manifests if you don't mind them containing the clear text versions of your passwords, or you can call it from the command line and then copy and paste the encrypted password into your manifest: @@ -866,6 +1095,10 @@ Current it is only actively tested with the following operating systems: Although patches are welcome for making it work with other OS distros, it is considered best effort. +### Apt module support + +While this module supports both 1.x and 2.x versions of the puppetlabs-apt module, it does not support puppetlabs-apt 2.0.0 or 2.0.1. + ### Postgis support Postgis is currently considered an unsupported feature as it doesn't work on diff --git a/puphpet/puppet/modules/postgresql/Rakefile b/puphpet/puppet/modules/postgresql/Rakefile index e3be95b..181157e 100644 --- a/puphpet/puppet/modules/postgresql/Rakefile +++ b/puphpet/puppet/modules/postgresql/Rakefile @@ -1,7 +1,7 @@ require 'puppetlabs_spec_helper/rake_tasks' require 'puppet-lint/tasks/puppet-lint' -PuppetLint.configuration.fail_on_warnings +PuppetLint.configuration.fail_on_warnings = true PuppetLint.configuration.send('relative') PuppetLint.configuration.send('disable_80chars') PuppetLint.configuration.send('disable_class_inherits_from_params_class') diff --git a/puphpet/puppet/modules/postgresql/lib/puppet/provider/postgresql_psql/ruby.rb b/puphpet/puppet/modules/postgresql/lib/puppet/provider/postgresql_psql/ruby.rb index 7dd69ac..60b4a0c 100644 --- a/puphpet/puppet/modules/postgresql/lib/puppet/provider/postgresql_psql/ruby.rb +++ b/puphpet/puppet/modules/postgresql/lib/puppet/provider/postgresql_psql/ruby.rb @@ -14,7 +14,7 @@ def run_sql_command(sql) command = [resource[:psql_path]] command.push("-d", resource[:db]) if resource[:db] command.push("-p", resource[:port]) if resource[:port] - command.push("-t", "-c", sql) + command.push("-t", "-c", '"' + sql.gsub('"', '\"') + '"') if resource[:cwd] Dir.chdir resource[:cwd] do @@ -27,9 +27,38 @@ def run_sql_command(sql) private + def get_environment + environment = {} + if envlist = resource[:environment] + envlist = [envlist] unless envlist.is_a? Array + envlist.each do |setting| + if setting =~ /^(\w+)=((.|\n)+)$/ + env_name = $1 + value = $2 + if environment.include?(env_name) || environment.include?(env_name.to_sym) + warning "Overriding environment setting '#{env_name}' with '#{value}'" + end + environment[env_name] = value + else + warning "Cannot understand environment setting #{setting.inspect}" + end + end + end + return environment + end + def run_command(command, user, group) - if Puppet::PUPPETVERSION.to_f < 3.4 - Puppet::Util::SUIDManager.run_and_capture(command, user, group) + command = command.join ' ' + environment = get_environment + if Puppet::PUPPETVERSION.to_f < 3.0 + require 'puppet/util/execution' + Puppet::Util::Execution.withenv environment do + Puppet::Util::SUIDManager.run_and_capture(command, user, group) + end + elsif Puppet::PUPPETVERSION.to_f < 3.4 + Puppet::Util.withenv environment do + Puppet::Util::SUIDManager.run_and_capture(command, user, group) + end else output = Puppet::Util::Execution.execute(command, { :uid => user, @@ -37,7 +66,7 @@ def run_command(command, user, group) :failonfail => false, :combine => true, :override_locale => true, - :custom_environment => {} + :custom_environment => environment }) [output, $CHILD_STATUS.dup] end diff --git a/puphpet/puppet/modules/postgresql/lib/puppet/provider/postgresql_replication_slot/ruby.rb b/puphpet/puppet/modules/postgresql/lib/puppet/provider/postgresql_replication_slot/ruby.rb new file mode 100644 index 0000000..cc49f7b --- /dev/null +++ b/puphpet/puppet/modules/postgresql/lib/puppet/provider/postgresql_replication_slot/ruby.rb @@ -0,0 +1,68 @@ +Puppet::Type.type(:postgresql_replication_slot).provide(:ruby) do + # For confinement + commands :psql => 'psql' + + def self.instances + run_sql_command('SELECT * FROM pg_replication_slots;')[0].split("\n").select { |l| l =~ /\|/ }.map do |l| + name, *others = l.strip.split(/\s+\|\s+/) + new({ + :name => name, + :ensure => :present, + }) + end + end + + def self.prefetch(resources) + instances.each do |i| + if slot = resources[i.name] + slot.provider = i + end + end + end + + def exists? + @property_hash[:ensure] == :present + end + + def create + output = self.class.run_sql_command("SELECT * FROM pg_create_physical_replication_slot('#{resource[:name]}');") + if output[1].success? + @property_hash[:ensure] = :present + else + raise Puppet::Error, "Failed to create replication slot #{resource[:name]}:\n#{output[0]}" + end + end + + def destroy + output = self.class.run_sql_command("SELECT pg_drop_replication_slot('#{resource[:name]}');") + if output[1].success? + @property_hash[:ensure] = :absent + else + raise Puppet::Error, "Failed to destroy replication slot #{resource[:name]}:\n#{output[0]}" + end + end + + private + + def self.run_sql_command(sql) + command = ['psql', '-t', '-c', sql] + + self.run_command(command, 'postgres', 'postgres') + end + + def self.run_command(command, user, group) + if Puppet::PUPPETVERSION.to_f < 3.4 + Puppet::Util::SUIDManager.run_and_capture(command, user, group) + else + output = Puppet::Util::Execution.execute(command, { + :uid => user, + :gid => group, + :failonfail => false, + :combine => true, + :override_locale => true, + :custom_environment => {} + }) + [output, $CHILD_STATUS.dup] + end + end +end diff --git a/puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_conf.rb b/puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_conf.rb index f227fd7..6dbaaee 100644 --- a/puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_conf.rb +++ b/puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_conf.rb @@ -1,31 +1,29 @@ -module Puppet - newtype(:postgresql_conf) do +Puppet::Type.newtype(:postgresql_conf) do - @doc = "This type allows puppet to manage postgresql.conf parameters." + @doc = "This type allows puppet to manage postgresql.conf parameters." - ensurable + ensurable - newparam(:name) do - desc "The postgresql parameter name to manage." - isnamevar + newparam(:name) do + desc "The postgresql parameter name to manage." + isnamevar - newvalues(/^[\w\.]+$/) - end - - newproperty(:value) do - desc "The value to set for this parameter." - end + newvalues(/^[\w\.]+$/) + end - newproperty(:target) do - desc "The path to postgresql.conf" - defaultto { - if @resource.class.defaultprovider.ancestors.include?(Puppet::Provider::ParsedFile) - @resource.class.defaultprovider.default_target - else - nil - end - } - end + newproperty(:value) do + desc "The value to set for this parameter." + end + newproperty(:target) do + desc "The path to postgresql.conf" + defaultto { + if @resource.class.defaultprovider.ancestors.include?(Puppet::Provider::ParsedFile) + @resource.class.defaultprovider.default_target + else + nil + end + } end + end diff --git a/puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_psql.rb b/puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_psql.rb index d724cf8..4cf817e 100644 --- a/puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_psql.rb +++ b/puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_psql.rb @@ -34,12 +34,7 @@ def sync # Return true if a matching row is found def matches(value) - if Puppet::PUPPETVERSION.to_f < 4 - output, status = provider.run_unless_sql_command(value) - else - output = provider.run_unless_sql_command(value) - status = output.exitcode - end + output, status = provider.run_unless_sql_command(value) self.fail("Error evaluating 'unless' clause, returned #{status}: '#{output}'") unless status == 0 result_count = output.strip.to_i @@ -48,6 +43,25 @@ def matches(value) end end + newparam(:onlyif) do + desc "An optional SQL command to execute prior to the main :command; " + + "this is generally intended to be used for idempotency, to check " + + "for the existence of an object in the database to determine whether " + + "or not the main SQL command needs to be executed at all." + + # Return true if a matching row is found + def matches(value) + output, status = provider.run_unless_sql_command(value) + status = output.exitcode if status.nil? + + self.fail("Error evaluating 'onlyif' clause, returned #{status}: '#{output}'") unless status == 0 + + result_count = output.strip.to_i + self.debug("Found #{result_count} row(s) executing 'onlyif' clause") + result_count > 0 + end + end + newparam(:db) do desc "The name of the database to execute the SQL command against." end @@ -80,6 +94,20 @@ def matches(value) defaultto("/tmp") end + newparam(:environment) do + desc "Any additional environment variables you want to set for a + SQL command. Multiple environment variables should be + specified as an array." + + validate do |values| + Array(values).each do |value| + unless value =~ /\w+=/ + raise ArgumentError, "Invalid environment setting '#{value}'" + end + end + end + end + newparam(:refreshonly, :boolean => true) do desc "If 'true', then the SQL will only be executed via a notify/subscribe event." @@ -88,7 +116,9 @@ def matches(value) end def should_run_sql(refreshing = false) + onlyif_param = @parameters[:onlyif] unless_param = @parameters[:unless] + return false if !onlyif_param.nil? && !onlyif_param.value.nil? && !onlyif_param.matches(onlyif_param.value) return false if !unless_param.nil? && !unless_param.value.nil? && unless_param.matches(unless_param.value) return false if !refreshing && @parameters[:refreshonly].value == :true true diff --git a/puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_replication_slot.rb b/puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_replication_slot.rb new file mode 100644 index 0000000..b5b317c --- /dev/null +++ b/puphpet/puppet/modules/postgresql/lib/puppet/type/postgresql_replication_slot.rb @@ -0,0 +1,16 @@ +Puppet::Type.newtype(:postgresql_replication_slot) do + @doc = "Manages Postgresql replication slots. + +This type allows to create and destroy replication slots +to register warm standby replication on a Postgresql +master server. +" + + ensurable + + newparam(:name) do + desc "The name of the slot to create. Must be a valid replication slot name." + isnamevar + newvalues /^[a-z0-9_]+$/ + end +end diff --git a/puphpet/puppet/modules/postgresql/manifests/client.pp b/puphpet/puppet/modules/postgresql/manifests/client.pp index d2b37aa..8cc6230 100644 --- a/puphpet/puppet/modules/postgresql/manifests/client.pp +++ b/puphpet/puppet/modules/postgresql/manifests/client.pp @@ -1,9 +1,11 @@ # Install client cli tool. See README.md for more details. class postgresql::client ( $file_ensure = 'file', + $validcon_script_path = $postgresql::params::validcon_script_path, $package_name = $postgresql::params::client_package_name, $package_ensure = 'present' ) inherits postgresql::params { + validate_absolute_path($validcon_script_path) validate_string($package_name) package { 'postgresql-client': @@ -12,7 +14,7 @@ tag => 'postgresql', } - file { '/usr/local/bin/validate_postgresql_connection.sh': + file { $validcon_script_path: ensure => $file_ensure, source => 'puppet:///modules/postgresql/validate_postgresql_connection.sh', owner => 0, diff --git a/puphpet/puppet/modules/postgresql/manifests/globals.pp b/puphpet/puppet/modules/postgresql/manifests/globals.pp index 5e88acf..98ca68b 100644 --- a/puphpet/puppet/modules/postgresql/manifests/globals.pp +++ b/puphpet/puppet/modules/postgresql/manifests/globals.pp @@ -1,50 +1,58 @@ # Class for setting cross-class global overrides. See README.md for more # details. class postgresql::globals ( - $client_package_name = undef, - $server_package_name = undef, - $contrib_package_name = undef, - $devel_package_name = undef, - $java_package_name = undef, - $perl_package_name = undef, - $plperl_package_name = undef, - $python_package_name = undef, - $postgis_package_name = undef, + $client_package_name = undef, + $server_package_name = undef, + $contrib_package_name = undef, + $devel_package_name = undef, + $java_package_name = undef, + $docs_package_name = undef, + $perl_package_name = undef, + $plperl_package_name = undef, + $plpython_package_name = undef, + $python_package_name = undef, + $postgis_package_name = undef, - $service_name = undef, - $service_provider = undef, - $service_status = undef, - $default_database = undef, + $service_name = undef, + $service_provider = undef, + $service_status = undef, + $default_database = undef, - $initdb_path = undef, - $createdb_path = undef, - $psql_path = undef, - $pg_hba_conf_path = undef, - $pg_ident_conf_path = undef, - $postgresql_conf_path = undef, + $validcon_script_path = undef, - $pg_hba_conf_defaults = undef, + $initdb_path = undef, + $createdb_path = undef, + $psql_path = undef, + $pg_hba_conf_path = undef, + $pg_ident_conf_path = undef, + $postgresql_conf_path = undef, + $recovery_conf_path = undef, - $datadir = undef, - $confdir = undef, - $bindir = undef, - $xlogdir = undef, + $pg_hba_conf_defaults = undef, - $user = undef, - $group = undef, + $datadir = undef, + $confdir = undef, + $bindir = undef, + $xlogdir = undef, + $logdir = undef, - $version = undef, - $postgis_version = undef, + $user = undef, + $group = undef, - $needs_initdb = undef, + $version = undef, + $postgis_version = undef, + $repo_proxy = undef, - $encoding = undef, - $locale = undef, + $needs_initdb = undef, - $manage_pg_hba_conf = undef, - $manage_pg_ident_conf = undef, + $encoding = undef, + $locale = undef, - $manage_package_repo = undef + $manage_pg_hba_conf = undef, + $manage_pg_ident_conf = undef, + $manage_recovery_conf = undef, + + $manage_package_repo = undef, ) { # We are determining this here, because it is needed by the package repo # class. @@ -63,6 +71,12 @@ /^5\./ => '8.1', default => undef, }, + default => $::operatingsystemrelease ? { + /^7\./ => '9.2', + /^6\./ => '8.4', + /^5\./ => '8.1', + default => undef, + }, }, 'Debian' => $::operatingsystem ? { 'Debian' => $::operatingsystemrelease ? { @@ -72,6 +86,7 @@ default => undef, }, 'Ubuntu' => $::operatingsystemrelease ? { + /^(15.04)$/ => '9.4', /^(14.10)$/ => '9.4', /^(14.04)$/ => '9.3', /^(11.10|12.04|12.10|13.04|13.10)$/ => '9.1', @@ -87,7 +102,13 @@ 'FreeBSD' => '93', 'OpenBSD' => '9.3', 'Suse' => $::operatingsystem ? { - 'SLES' => '91', + 'SLES' => $::operatingsystemrelease ? { + /11\.[0-4]/ => '91', + default => '93', + }, + 'OpenSuSE' => $::operatingsystemrelease ? { + '13.2' => '93', + }, default => undef, }, default => undef, @@ -109,12 +130,16 @@ '93' => '2.1', default => undef, } - $globals_postgis_version = pick($postgis_version, $default_postgis_version) + $globals_postgis_version = $postgis_version ? { + undef => $default_postgis_version, + default => $postgis_version, + } # Setup of the repo only makes sense globally, so we are doing this here. if($manage_package_repo) { class { 'postgresql::repo': - version => $globals_version + version => $globals_version, + proxy => $repo_proxy, } } } diff --git a/puphpet/puppet/modules/postgresql/manifests/lib/docs.pp b/puphpet/puppet/modules/postgresql/manifests/lib/docs.pp new file mode 100644 index 0000000..55825d1 --- /dev/null +++ b/puphpet/puppet/modules/postgresql/manifests/lib/docs.pp @@ -0,0 +1,16 @@ +# This class installs the postgresql-docs See README.md for more +# details. +class postgresql::lib::docs ( + $package_name = $postgresql::params::docs_package_name, + $package_ensure = 'present', +) inherits postgresql::params { + + validate_string($package_name) + + package { 'postgresql-docs': + ensure => $package_ensure, + name => $package_name, + tag => 'postgresql', + } + +} diff --git a/puphpet/puppet/modules/postgresql/manifests/params.pp b/puphpet/puppet/modules/postgresql/manifests/params.pp index a8fe1f6..4b1dfc9 100644 --- a/puphpet/puppet/modules/postgresql/manifests/params.pp +++ b/puphpet/puppet/modules/postgresql/manifests/params.pp @@ -16,6 +16,7 @@ $service_provider = $service_provider $manage_pg_hba_conf = pick($manage_pg_hba_conf, true) $manage_pg_ident_conf = pick($manage_pg_ident_conf, true) + $manage_recovery_conf = pick($manage_recovery_conf, false) $package_ensure = 'present' # Amazon Linux's OS Family is 'Linux', operating system 'Amazon'. @@ -29,35 +30,39 @@ $package_version = "${version_parts[0]}${version_parts[1]}" if $version == $postgresql::globals::default_version { - $client_package_name = pick($client_package_name, 'postgresql') - $server_package_name = pick($server_package_name, 'postgresql-server') - $contrib_package_name = pick($contrib_package_name,'postgresql-contrib') - $devel_package_name = pick($devel_package_name, 'postgresql-devel') - $java_package_name = pick($java_package_name, 'postgresql-jdbc') - $plperl_package_name = pick($plperl_package_name, 'postgresql-plperl') - $service_name = pick($service_name, 'postgresql') - $bindir = pick($bindir, '/usr/bin') - $datadir = $::operatingsystem ? { + $client_package_name = pick($client_package_name, 'postgresql') + $server_package_name = pick($server_package_name, 'postgresql-server') + $contrib_package_name = pick($contrib_package_name,'postgresql-contrib') + $devel_package_name = pick($devel_package_name, 'postgresql-devel') + $java_package_name = pick($java_package_name, 'postgresql-jdbc') + $docs_package_name = pick($docs_package_name, 'postgresql-docs') + $plperl_package_name = pick($plperl_package_name, 'postgresql-plperl') + $plpython_package_name = pick($plpython_package_name, 'postgresql-plpython') + $service_name = pick($service_name, 'postgresql') + $bindir = pick($bindir, '/usr/bin') + $datadir = $::operatingsystem ? { 'Amazon' => pick($datadir, '/var/lib/pgsql9/data'), default => pick($datadir, '/var/lib/pgsql/data'), } - $confdir = pick($confdir, $datadir) + $confdir = pick($confdir, $datadir) } else { - $client_package_name = pick($client_package_name, "postgresql${package_version}") - $server_package_name = pick($server_package_name, "postgresql${package_version}-server") - $contrib_package_name = pick($contrib_package_name,"postgresql${package_version}-contrib") - $devel_package_name = pick($devel_package_name, "postgresql${package_version}-devel") - $java_package_name = pick($java_package_name, "postgresql${package_version}-jdbc") - $plperl_package_name = pick($plperl_package_name, "postgresql${package_version}-plperl") - $service_name = pick($service_name, "postgresql-${version}") - $bindir = pick($bindir, "/usr/pgsql-${version}/bin") - $datadir = $::operatingsystem ? { + $client_package_name = pick($client_package_name, "postgresql${package_version}") + $server_package_name = pick($server_package_name, "postgresql${package_version}-server") + $contrib_package_name = pick($contrib_package_name,"postgresql${package_version}-contrib") + $devel_package_name = pick($devel_package_name, "postgresql${package_version}-devel") + $java_package_name = pick($java_package_name, "postgresql${package_version}-jdbc") + $docs_package_name = pick($docs_package_name, "postgresql${package_version}-docs") + $plperl_package_name = pick($plperl_package_name, "postgresql${package_version}-plperl") + $plpython_package_name = pick($plpython_package_name, "postgresql${package_version}-plpython") + $service_name = pick($service_name, "postgresql-${version}") + $bindir = pick($bindir, "/usr/pgsql-${version}/bin") + $datadir = $::operatingsystem ? { 'Amazon' => pick($datadir, "/var/lib/pgsql9/${version}/data"), default => pick($datadir, "/var/lib/pgsql/${version}/data"), } - $confdir = pick($confdir, $datadir) + $confdir = pick($confdir, $datadir) } - $psql_path = pick($psql_path, "${bindir}/psql") + $psql_path = pick($psql_path, "${bindir}/psql") $service_status = $service_status $service_reload = "service ${service_name} reload" @@ -67,7 +72,7 @@ $postgis_package_name = pick( $postgis_package_name, $::operatingsystemrelease ? { - /5/ => 'postgis', + /^5\./ => 'postgis', default => versioncmp($postgis_version, '2') ? { '-1' => "postgis${package_version}", default => "postgis2_${package_version}",} @@ -83,26 +88,27 @@ # Archlinux doesn't have a client-package but has a libs package which # pulls in postgresql server - $client_package_name = pick($client_package_name, 'postgresql') - $server_package_name = pick($server_package_name, 'postgresql-libs') - $java_package_name = pick($java_package_name, 'postgresql-jdbc') + $client_package_name = pick($client_package_name, 'postgresql') + $server_package_name = pick($server_package_name, 'postgresql-libs') + $java_package_name = pick($java_package_name, 'postgresql-jdbc') # Archlinux doesn't have develop packages - $devel_package_name = pick($devel_package_name, 'postgresql-devel') + $devel_package_name = pick($devel_package_name, 'postgresql-devel') # Archlinux does have postgresql-contrib but it isn't maintained - $contrib_package_name = pick($contrib_package_name,'undef') + $contrib_package_name = pick($contrib_package_name,'undef') # Archlinux postgresql package provides plperl - $plperl_package_name = pick($plperl_package_name, 'undef') - $service_name = pick($service_name, 'postgresql') - $bindir = pick($bindir, '/usr/bin') - $datadir = pick($datadir, '/var/lib/postgres/data') - $confdir = pick($confdir, $datadir) - $psql_path = pick($psql_path, "${bindir}/psql") + $plperl_package_name = pick($plperl_package_name, 'undef') + $plpython_package_name = pick($plpython_package_name, 'undef') + $service_name = pick($service_name, 'postgresql') + $bindir = pick($bindir, '/usr/bin') + $datadir = pick($datadir, '/var/lib/postgres/data') + $confdir = pick($confdir, $datadir) + $psql_path = pick($psql_path, "${bindir}/psql") - $service_status = $service_status - $service_reload = "service ${service_name} reload" - $python_package_name = pick($python_package_name, 'python-psycopg2') + $service_status = $service_status + $service_reload = "service ${service_name} reload" + $python_package_name = pick($python_package_name, 'python-psycopg2') # Archlinux does not have a perl::DBD::Pg package - $perl_package_name = pick($perl_package_name, 'undef') + $perl_package_name = pick($perl_package_name, 'undef') } 'Debian': { @@ -125,26 +131,32 @@ } } - $client_package_name = pick($client_package_name, "postgresql-client-${version}") - $server_package_name = pick($server_package_name, "postgresql-${version}") - $contrib_package_name = pick($contrib_package_name, "postgresql-contrib-${version}") + $client_package_name = pick($client_package_name, "postgresql-client-${version}") + $server_package_name = pick($server_package_name, "postgresql-${version}") + $contrib_package_name = pick($contrib_package_name, "postgresql-contrib-${version}") if versioncmp($postgis_version, '2') < 0 { $postgis_package_name = pick($postgis_package_name, "postgresql-${version}-postgis") } else { $postgis_package_name = pick($postgis_package_name, "postgresql-${version}-postgis-${postgis_version}") } - $devel_package_name = pick($devel_package_name, 'libpq-dev') - $java_package_name = pick($java_package_name, 'libpostgresql-jdbc-java') - $perl_package_name = pick($perl_package_name, 'libdbd-pg-perl') - $plperl_package_name = pick($plperl_package_name, "postgresql-plperl-${version}") - $python_package_name = pick($python_package_name, 'python-psycopg2') + $devel_package_name = pick($devel_package_name, 'libpq-dev') + $java_package_name = pick($java_package_name, 'libpostgresql-jdbc-java') + $perl_package_name = pick($perl_package_name, 'libdbd-pg-perl') + $plperl_package_name = pick($plperl_package_name, "postgresql-plperl-${version}") + $plpython_package_name = pick($plpython_package_name, "postgresql-plpython-${version}") + $python_package_name = pick($python_package_name, 'python-psycopg2') - $bindir = pick($bindir, "/usr/lib/postgresql/${version}/bin") - $datadir = pick($datadir, "/var/lib/postgresql/${version}/main") - $confdir = pick($confdir, "/etc/postgresql/${version}/main") - $service_status = pick($service_status, "/etc/init.d/${service_name} status | /bin/egrep -q 'Running clusters: .+|online'") - $service_reload = "service ${service_name} reload" - $psql_path = pick($psql_path, '/usr/bin/psql') + $bindir = pick($bindir, "/usr/lib/postgresql/${version}/bin") + $datadir = pick($datadir, "/var/lib/postgresql/${version}/main") + $confdir = pick($confdir, "/etc/postgresql/${version}/main") + if $::operatingsystem == 'Debian' and versioncmp($::operatingsystemrelease, '8.0') >= 0 { + # Jessie uses systemd + $service_status = pick($service_status, "/usr/sbin/service ${service_name}@*-main status") + } else { + $service_status = pick($service_status, "/etc/init.d/${service_name} status | /bin/egrep -q 'Running clusters: .+|online'") + } + $service_reload = "service ${service_name} reload" + $psql_path = pick($psql_path, '/usr/bin/psql') } 'FreeBSD': { @@ -205,10 +217,10 @@ $server_package_name = pick($server_package_name, "postgresql${version}-server") $contrib_package_name = pick($contrib_package_name, "postgresql${version}-contrib") $devel_package_name = pick($devel_package_name, "postgresql${version}-devel") - $java_package_name = pick($java_package_name, undef) - $perl_package_name = pick($plperl_package_name, undef) - $plperl_package_name = pick($plperl_package_name, undef) - $python_package_name = pick($python_package_name, undef) + $java_package_name = pick($java_package_name, "postgresql${version}-jdbc") + $perl_package_name = pick($plperl_package_name, 'perl-DBD-Pg') + $plperl_package_name = pick($plperl_package_name, "postgresql${version}-plperl") + $python_package_name = pick($python_package_name, 'python-psycopg2') $service_name = pick($service_name, 'postgresql') $bindir = pick($bindir, "/usr/lib/postgresql${version}/bin") @@ -239,11 +251,13 @@ } } + $validcon_script_path = pick($validcon_script_path, '/usr/local/bin/validate_postgresql_connection.sh') $initdb_path = pick($initdb_path, "${bindir}/initdb") $createdb_path = pick($createdb_path, "${bindir}/createdb") $pg_hba_conf_path = pick($pg_hba_conf_path, "${confdir}/pg_hba.conf") $pg_hba_conf_defaults = pick($pg_hba_conf_defaults, true) $pg_ident_conf_path = pick($pg_ident_conf_path, "${confdir}/pg_ident.conf") $postgresql_conf_path = pick($postgresql_conf_path, "${confdir}/postgresql.conf") + $recovery_conf_path = pick($recovery_conf_path, "${datadir}/recovery.conf") $default_database = pick($default_database, 'postgres') } diff --git a/puphpet/puppet/modules/postgresql/manifests/repo.pp b/puphpet/puppet/modules/postgresql/manifests/repo.pp index 28fe586..48e4fd0 100644 --- a/puphpet/puppet/modules/postgresql/manifests/repo.pp +++ b/puphpet/puppet/modules/postgresql/manifests/repo.pp @@ -1,6 +1,7 @@ # PRIVATE CLASS: do not use directly class postgresql::repo ( - $version = undef + $version = undef, + $proxy = undef, ) inherits postgresql::params { case $::osfamily { 'RedHat', 'Linux': { diff --git a/puphpet/puppet/modules/postgresql/manifests/repo/apt_postgresql_org.pp b/puphpet/puppet/modules/postgresql/manifests/repo/apt_postgresql_org.pp index e3ad07c..82accff 100644 --- a/puphpet/puppet/modules/postgresql/manifests/repo/apt_postgresql_org.pp +++ b/puphpet/puppet/modules/postgresql/manifests/repo/apt_postgresql_org.pp @@ -13,7 +13,7 @@ location => 'http://apt.postgresql.org/pub/repos/apt/', release => "${::lsbdistcodename}-pgdg", repos => "main ${postgresql::repo::version}", - key => 'ACCC4CF8', + key => 'B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8', key_source => 'https://www.postgresql.org/media/keys/ACCC4CF8.asc', include_src => false, } diff --git a/puphpet/puppet/modules/postgresql/manifests/repo/yum_postgresql_org.pp b/puphpet/puppet/modules/postgresql/manifests/repo/yum_postgresql_org.pp index afa71b5..5cfaf4b 100644 --- a/puphpet/puppet/modules/postgresql/manifests/repo/yum_postgresql_org.pp +++ b/puphpet/puppet/modules/postgresql/manifests/repo/yum_postgresql_org.pp @@ -23,6 +23,7 @@ enabled => 1, gpgcheck => 1, gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG-${package_version}", + proxy => $postgresql::repo::proxy, } Yumrepo['yum.postgresql.org'] -> Package<|tag == 'postgresql'|> diff --git a/puphpet/puppet/modules/postgresql/manifests/server.pp b/puphpet/puppet/modules/postgresql/manifests/server.pp index 43b1546..d4b2f30 100644 --- a/puphpet/puppet/modules/postgresql/manifests/server.pp +++ b/puphpet/puppet/modules/postgresql/manifests/server.pp @@ -7,6 +7,7 @@ $package_ensure = $postgresql::params::package_ensure, $plperl_package_name = $postgresql::params::plperl_package_name, + $plpython_package_name = $postgresql::params::plpython_package_name, $service_ensure = $postgresql::params::service_ensure, $service_enable = $postgresql::params::service_enable, @@ -30,9 +31,11 @@ $pg_hba_conf_path = $postgresql::params::pg_hba_conf_path, $pg_ident_conf_path = $postgresql::params::pg_ident_conf_path, $postgresql_conf_path = $postgresql::params::postgresql_conf_path, + $recovery_conf_path = $postgresql::params::recovery_conf_path, $datadir = $postgresql::params::datadir, $xlogdir = $postgresql::params::xlogdir, + $logdir = $postgresql::params::logdir, $pg_hba_conf_defaults = $postgresql::params::pg_hba_conf_defaults, @@ -46,6 +49,7 @@ $manage_pg_hba_conf = $postgresql::params::manage_pg_hba_conf, $manage_pg_ident_conf = $postgresql::params::manage_pg_ident_conf, + $manage_recovery_conf = $postgresql::params::manage_recovery_conf, #Deprecated $version = undef, diff --git a/puphpet/puppet/modules/postgresql/manifests/server/config.pp b/puphpet/puppet/modules/postgresql/manifests/server/config.pp index 2a1d80d..d12c500 100644 --- a/puphpet/puppet/modules/postgresql/manifests/server/config.pp +++ b/puphpet/puppet/modules/postgresql/manifests/server/config.pp @@ -9,13 +9,17 @@ $pg_hba_conf_path = $postgresql::server::pg_hba_conf_path $pg_ident_conf_path = $postgresql::server::pg_ident_conf_path $postgresql_conf_path = $postgresql::server::postgresql_conf_path + $recovery_conf_path = $postgresql::server::recovery_conf_path $pg_hba_conf_defaults = $postgresql::server::pg_hba_conf_defaults $user = $postgresql::server::user $group = $postgresql::server::group $version = $postgresql::server::_version + $manage_package_repo = $postgresql::server::manage_package_repo $manage_pg_hba_conf = $postgresql::server::manage_pg_hba_conf $manage_pg_ident_conf = $postgresql::server::manage_pg_ident_conf + $manage_recovery_conf = $postgresql::server::manage_recovery_conf $datadir = $postgresql::server::datadir + $logdir = $postgresql::server::logdir if ($manage_pg_hba_conf == true) { # Prepare the main pg_hba file @@ -66,12 +70,6 @@ order => '004', } - # ipv4acls are passed as an array of rule strings, here we transform - # them into a resources hash, and pass the result to create_resources - $ipv4acl_resources = postgresql_acls_to_resources_hash($ipv4acls, - 'ipv4acls', 10) - create_resources('postgresql::server::pg_hba_rule', $ipv4acl_resources) - postgresql::server::pg_hba_rule { 'allow access to all users': type => 'host', address => $ip_mask_allow_all_users, @@ -84,13 +82,20 @@ auth_method => 'md5', order => '101', } - - # ipv6acls are passed as an array of rule strings, here we transform - # them into a resources hash, and pass the result to create_resources - $ipv6acl_resources = postgresql_acls_to_resources_hash($ipv6acls, - 'ipv6acls', 102) - create_resources('postgresql::server::pg_hba_rule', $ipv6acl_resources) } + + # ipv4acls are passed as an array of rule strings, here we transform + # them into a resources hash, and pass the result to create_resources + $ipv4acl_resources = postgresql_acls_to_resources_hash($ipv4acls, + 'ipv4acls', 10) + create_resources('postgresql::server::pg_hba_rule', $ipv4acl_resources) + + + # ipv6acls are passed as an array of rule strings, here we transform + # them into a resources hash, and pass the result to create_resources + $ipv6acl_resources = postgresql_acls_to_resources_hash($ipv6acls, + 'ipv6acls', 102) + create_resources('postgresql::server::pg_hba_rule', $ipv6acl_resources) } # We must set a "listen_addresses" line in the postgresql.conf if we @@ -104,6 +109,12 @@ postgresql::server::config_entry { 'data_directory': value => $datadir, } + if $logdir { + postgresql::server::config_entry { 'log_directory': + value => $logdir, + } + + } # RedHat-based systems hardcode some PG* variables in the init script, and need to be overriden # in /etc/sysconfig/pgsql/postgresql. Create a blank file so we can manage it with augeas later. @@ -137,11 +148,22 @@ } } + if ($manage_recovery_conf == true) { + concat { $recovery_conf_path: + owner => $user, + group => $group, + force => true, # do not crash if there is no recovery conf file + mode => '0640', + warn => true, + notify => Class['postgresql::server::reload'], + } + } + if $::osfamily == 'RedHat' { if $::operatingsystemrelease =~ /^7/ or $::operatingsystem == 'Fedora' { file { 'systemd-override': ensure => present, - path => '/etc/systemd/system/postgresql.service', + path => "/etc/systemd/system/${postgresql::params::service_name}.service", owner => root, group => root, content => template('postgresql/systemd-override.erb'), diff --git a/puphpet/puppet/modules/postgresql/manifests/server/extension.pp b/puphpet/puppet/modules/postgresql/manifests/server/extension.pp index 1093011..726d9f6 100644 --- a/puphpet/puppet/modules/postgresql/manifests/server/extension.pp +++ b/puphpet/puppet/modules/postgresql/manifests/server/extension.pp @@ -5,16 +5,29 @@ $package_name = undef, $package_ensure = undef, ) { + $user = $postgresql::server::user + $group = $postgresql::server::group + $psql_path = $postgresql::server::psql_path + $port = $postgresql::server::port + + # Set the defaults for the postgresql_psql resource + Postgresql_psql { + psql_user => $user, + psql_group => $group, + psql_path => $psql_path, + port => $port, + } + case $ensure { 'present': { - $command = "CREATE EXTENSION ${name}" + $command = "CREATE EXTENSION \"${name}\"" $unless_comp = '=' $package_require = undef $package_before = Postgresql_psql["Add ${title} extension to ${database}"] } 'absent': { - $command = "DROP EXTENSION ${name}" + $command = "DROP EXTENSION \"${name}\"" $unless_comp = '!=' $package_require = Postgresql_psql["Add ${title} extension to ${database}"] $package_before = undef diff --git a/puphpet/puppet/modules/postgresql/manifests/server/grant.pp b/puphpet/puppet/modules/postgresql/manifests/server/grant.pp index e15b292..a24e343 100644 --- a/puphpet/puppet/modules/postgresql/manifests/server/grant.pp +++ b/puphpet/puppet/modules/postgresql/manifests/server/grant.pp @@ -2,12 +2,13 @@ define postgresql::server::grant ( $role, $db, - $privilege = undef, - $object_type = 'database', - $object_name = undef, - $psql_db = $postgresql::server::default_database, - $psql_user = $postgresql::server::user, - $port = $postgresql::server::port + $privilege = undef, + $object_type = 'database', + $object_name = undef, + $psql_db = $postgresql::server::default_database, + $psql_user = $postgresql::server::user, + $port = $postgresql::server::port, + $onlyif_exists = false, ) { $group = $postgresql::server::group $psql_path = $postgresql::server::psql_path @@ -18,6 +19,8 @@ $_object_name = $object_name } + validate_bool($onlyif_exists) + ## Munge the input values $_object_type = upcase($object_type) $_privilege = upcase($privilege) @@ -31,13 +34,15 @@ #'FUNCTION', #'PROCEDURAL LANGUAGE', 'SCHEMA', - #'SEQUENCE', + 'SEQUENCE', + 'ALL SEQUENCES IN SCHEMA', 'TABLE', 'ALL TABLES IN SCHEMA', #'TABLESPACE', #'VIEW', ) # You can use ALL TABLES IN SCHEMA by passing schema_name to object_name + # You can use ALL SEQUENCES IN SCHEMA by passing schema_name to object_name ## Validate that the object type's privilege is acceptable # TODO: this is a terrible hack; if they pass "ALL" as the desired privilege, @@ -59,6 +64,7 @@ 'ALL','ALL PRIVILEGES') $unless_function = 'has_database_privilege' $on_db = $psql_db + $onlyif_function = undef } 'SCHEMA': { $unless_privilege = $_privilege ? { @@ -69,6 +75,54 @@ validate_string($_privilege, 'CREATE', 'USAGE', 'ALL', 'ALL PRIVILEGES') $unless_function = 'has_schema_privilege' $on_db = $db + $onlyif_function = undef + } + 'SEQUENCE': { + $unless_privilege = $_privilege ? { + 'ALL' => 'USAGE', + default => $_privilege, + } + validate_string($unless_privilege,'USAGE','ALL','ALL PRIVILEGES') + $unless_function = 'has_sequence_privilege' + $on_db = $db + } + 'ALL SEQUENCES IN SCHEMA': { + validate_string($_privilege,'USAGE','ALL','ALL PRIVILEGES') + $unless_function = 'custom' + $on_db = $db + + $schema = $object_name + + $custom_privilege = $_privilege ? { + 'ALL' => 'USAGE', + 'ALL PRIVILEGES' => 'USAGE', + default => $_privilege, + } + + # This checks if there is a difference between the sequences in the + # specified schema and the sequences for which the role has the specified + # privilege. It uses the EXCEPT clause which computes the set of rows + # that are in the result of the first SELECT statement but not in the + # result of the second one. It then counts the number of rows from this + # operation. If this number is zero then the role has the specified + # privilege for all sequences in the schema and the whole query returns a + # single row, which satisfies the `unless` parameter of Postgresql_psql. + # If this number is not zero then there is at least one sequence for which + # the role does not have the specified privilege, making it necessary to + # execute the GRANT statement. + $custom_unless = "SELECT 1 FROM ( + SELECT sequence_name + FROM information_schema.sequences + WHERE sequence_schema='${schema}' + EXCEPT DISTINCT + SELECT object_name as sequence_name + FROM information_schema.role_usage_grants + WHERE object_type='SEQUENCE' + AND grantee='${role}' + AND object_schema='${schema}' + AND privilege_type='${custom_privilege}' + ) P + HAVING count(P.sequence_name) = 0" } 'TABLE': { $unless_privilege = $_privilege ? { @@ -79,12 +133,52 @@ 'TRUNCATE','REFERENCES','TRIGGER','ALL','ALL PRIVILEGES') $unless_function = 'has_table_privilege' $on_db = $db + $onlyif_function = $onlyif_exists ? { + true => 'table_exists', + default => undef, + } } 'ALL TABLES IN SCHEMA': { - validate_string($_privilege, 'SELECT', 'INSERT', 'UPDATE', 'REFERENCES', - 'ALL', 'ALL PRIVILEGES') - $unless_function = false # There is no way to test it simply + validate_string($_privilege,'SELECT','INSERT','UPDATE','DELETE', + 'TRUNCATE','REFERENCES','TRIGGER','ALL','ALL PRIVILEGES') + $unless_function = 'custom' $on_db = $db + $onlyif_function = undef + + $schema = $object_name + + # Again there seems to be no easy way in plain SQL to check if ALL + # PRIVILEGES are granted on a table. By convention we use INSERT + # here to represent ALL PRIVILEGES (truly terrible). + $custom_privilege = $_privilege ? { + 'ALL' => 'INSERT', + 'ALL PRIVILEGES' => 'INSERT', + default => $_privilege, + } + + # This checks if there is a difference between the tables in the + # specified schema and the tables for which the role has the specified + # privilege. It uses the EXCEPT clause which computes the set of rows + # that are in the result of the first SELECT statement but not in the + # result of the second one. It then counts the number of rows from this + # operation. If this number is zero then the role has the specified + # privilege for all tables in the schema and the whole query returns a + # single row, which satisfies the `unless` parameter of Postgresql_psql. + # If this number is not zero then there is at least one table for which + # the role does not have the specified privilege, making it necessary to + # execute the GRANT statement. + $custom_unless = "SELECT 1 FROM ( + SELECT table_name + FROM information_schema.tables + WHERE table_schema='${schema}' + EXCEPT DISTINCT + SELECT table_name + FROM information_schema.role_table_grants + WHERE grantee='${role}' + AND table_schema='${schema}' + AND privilege_type='${custom_privilege}' + ) P + HAVING count(P.table_name) = 0" } default: { fail("Missing privilege validation for object type ${_object_type}") @@ -109,11 +203,17 @@ } $_unless = $unless_function ? { - false => undef, - default => "SELECT 1 WHERE ${unless_function}('${role}', + false => undef, + 'custom' => $custom_unless, + default => "SELECT 1 WHERE ${unless_function}('${role}', '${_granted_object}', '${unless_privilege}')", } + $_onlyif = $onlyif_function ? { + 'table_exists' => "SELECT true FROM pg_tables WHERE tablename = '${_togrant_object}'", + default => undef, + } + $grant_cmd = "GRANT ${_privilege} ON ${_object_type} \"${_togrant_object}\" TO \"${role}\"" postgresql_psql { "grant:${name}": @@ -124,6 +224,7 @@ psql_group => $group, psql_path => $psql_path, unless => $_unless, + onlyif => $_onlyif, require => Class['postgresql::server'] } diff --git a/puphpet/puppet/modules/postgresql/manifests/server/initdb.pp b/puphpet/puppet/modules/postgresql/manifests/server/initdb.pp index 740fecc..b0df326 100644 --- a/puphpet/puppet/modules/postgresql/manifests/server/initdb.pp +++ b/puphpet/puppet/modules/postgresql/manifests/server/initdb.pp @@ -4,10 +4,21 @@ $initdb_path = $postgresql::server::initdb_path $datadir = $postgresql::server::datadir $xlogdir = $postgresql::server::xlogdir + $logdir = $postgresql::server::logdir $encoding = $postgresql::server::encoding $locale = $postgresql::server::locale $group = $postgresql::server::group $user = $postgresql::server::user + $psql_path = $postgresql::server::psql_path + $port = $postgresql::server::port + + # Set the defaults for the postgresql_psql resource + Postgresql_psql { + psql_user => $user, + psql_group => $group, + psql_path => $psql_path, + port => $port, + } # Make sure the data directory exists, and has the correct permissions. file { $datadir: @@ -27,6 +38,15 @@ } } + if($logdir) { + # Make sure the log directory exists, and has the correct permissions. + file { $logdir: + ensure => directory, + owner => $user, + group => $group, + } + } + if($needs_initdb) { # Build up the initdb command. # @@ -63,19 +83,25 @@ require => File[$require_before_initdb], } # The package will take care of this for us the first time, but if we - # ever need to init a new db we need to make these links explicitly + # ever need to init a new db we need to copy these files explicitly if $::operatingsystem == 'Debian' or $::operatingsystem == 'Ubuntu' { if $::operatingsystemrelease =~ /^6/ or $::operatingsystemrelease =~ /^7/ or $::operatingsystemrelease =~ /^10\.04/ or $::operatingsystemrelease =~ /^12\.04/ { file { 'server.crt': - ensure => link, + ensure => file, path => "${datadir}/server.crt", - target => '/etc/ssl/certs/ssl-cert-snakeoil.pem', + source => 'file:///etc/ssl/certs/ssl-cert-snakeoil.pem', + owner => $::postgresql::server::user, + group => $::postgresql::server::group, + mode => '0644', require => Exec['postgresql_initdb'], } file { 'server.key': - ensure => link, + ensure => file, path => "${datadir}/server.key", - target => '/etc/ssl/private/ssl-cert-snakeoil.key', + source => 'file:///etc/ssl/private/ssl-cert-snakeoil.key', + owner => $::postgresql::server::user, + group => $::postgresql::server::group, + mode => '0600', require => Exec['postgresql_initdb'], } } @@ -94,7 +120,7 @@ SET encoding = pg_char_to_encoding('${encoding}'), datistemplate = TRUE WHERE datname = 'template1'", unless => "SELECT datname FROM pg_database WHERE - datname = 'template1' AND pg_encoding_to_char(encoding) = '${encoding}'", + datname = 'template1' AND encoding = pg_char_to_encoding('${encoding}')", } } } diff --git a/puphpet/puppet/modules/postgresql/manifests/server/passwd.pp b/puphpet/puppet/modules/postgresql/manifests/server/passwd.pp index 637885d..358a044 100644 --- a/puphpet/puppet/modules/postgresql/manifests/server/passwd.pp +++ b/puphpet/puppet/modules/postgresql/manifests/server/passwd.pp @@ -12,22 +12,25 @@ # without specifying a password ('ident' or 'trust' security). This is # the default for pg_hba.conf. $escaped = postgresql_escape($postgres_password) - $env = "env PGPASSWORD='${postgres_password}'" exec { 'set_postgres_postgrespw': # This command works w/no password because we run it as postgres system # user - command => "${psql_path} -c 'ALTER ROLE \"${user}\" PASSWORD ${escaped}'", - user => $user, - group => $group, - logoutput => true, - cwd => '/tmp', + command => "${psql_path} -c \"ALTER ROLE \\\"${user}\\\" PASSWORD \${NEWPASSWD_ESCAPED}\"", + user => $user, + group => $group, + logoutput => true, + cwd => '/tmp', + environment => [ + "PGPASSWORD=${postgres_password}", + "NEWPASSWD_ESCAPED=${escaped}", + ], # With this command we're passing -h to force TCP authentication, which # does require a password. We specify the password via the PGPASSWORD # environment variable. If the password is correct (current), this # command will exit with an exit code of 0, which will prevent the main # command from running. - unless => "${env} ${psql_path} -h localhost -p ${port} -c 'select 1' > /dev/null", - path => '/usr/bin:/usr/local/bin:/bin', + unless => "${psql_path} -h localhost -p ${port} -c 'select 1' > /dev/null", + path => '/usr/bin:/usr/local/bin:/bin', } } } diff --git a/puphpet/puppet/modules/postgresql/manifests/server/pg_hba_rule.pp b/puphpet/puppet/modules/postgresql/manifests/server/pg_hba_rule.pp index 77aee0b..406568f 100644 --- a/puphpet/puppet/modules/postgresql/manifests/server/pg_hba_rule.pp +++ b/puphpet/puppet/modules/postgresql/manifests/server/pg_hba_rule.pp @@ -12,10 +12,19 @@ # Needed for testing primarily, support for multiple files is not really # working. - $target = $postgresql::server::pg_hba_conf_path + $target = $postgresql::server::pg_hba_conf_path, + $postgresql_version = $postgresql::server::_version ) { - if $postgresql::server::manage_pg_hba_conf == false { + #Allow users to manage pg_hba.conf even if they are not managing the whole PostgreSQL instance + if !defined( 'postgresql::server' ) { + $manage_pg_hba_conf = true + } + else { + $manage_pg_hba_conf = $postgresql::server::manage_pg_hba_conf + } + + if $manage_pg_hba_conf == false { fail('postgresql::server::manage_pg_hba_conf has been disabled, so this resource is now unused and redundant, either enable that option or remove this resource from your manifests') } else { validate_re($type, '^(local|host|hostssl|hostnossl)$', @@ -25,13 +34,14 @@ fail('You must specify an address property when type is host based') } - $allowed_auth_methods = $postgresql::server::_version ? { - '9.3' => ['trust', 'reject', 'md5', 'sha1', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], - '9.2' => ['trust', 'reject', 'md5', 'sha1', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], - '9.1' => ['trust', 'reject', 'md5', 'sha1', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], - '9.0' => ['trust', 'reject', 'md5', 'sha1', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'radius', 'cert', 'pam'], - '8.4' => ['trust', 'reject', 'md5', 'sha1', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'cert', 'pam'], - '8.3' => ['trust', 'reject', 'md5', 'sha1', 'crypt', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'pam'], + $allowed_auth_methods = $postgresql_version ? { + '9.4' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], + '9.3' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], + '9.2' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], + '9.1' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam'], + '9.0' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'radius', 'cert', 'pam'], + '8.4' => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'cert', 'pam'], + '8.3' => ['trust', 'reject', 'md5', 'crypt', 'password', 'gss', 'sspi', 'krb5', 'ident', 'ldap', 'pam'], '8.2' => ['trust', 'reject', 'md5', 'crypt', 'password', 'krb5', 'ident', 'ldap', 'pam'], '8.1' => ['trust', 'reject', 'md5', 'crypt', 'password', 'krb5', 'ident', 'pam'], default => ['trust', 'reject', 'md5', 'password', 'gss', 'sspi', 'krb5', 'ident', 'peer', 'ldap', 'radius', 'cert', 'pam', 'crypt'] diff --git a/puphpet/puppet/modules/postgresql/manifests/server/plpython.pp b/puphpet/puppet/modules/postgresql/manifests/server/plpython.pp new file mode 100644 index 0000000..962dbad --- /dev/null +++ b/puphpet/puppet/modules/postgresql/manifests/server/plpython.pp @@ -0,0 +1,19 @@ +# This class installs the PL/Python procedural language for postgresql. See +# README.md for more details. +class postgresql::server::plpython( + $package_ensure = 'present', + $package_name = $postgresql::server::plpython_package_name, +) { + package { 'postgresql-plpython': + ensure => $package_ensure, + name => $package_name, + tag => 'postgresql', + } + + anchor { 'postgresql::server::plpython::start': }-> + Class['postgresql::server::install']-> + Package['postgresql-plpython']-> + Class['postgresql::server::service']-> + anchor { 'postgresql::server::plpython::end': } + +} diff --git a/puphpet/puppet/modules/postgresql/manifests/server/recovery.pp b/puphpet/puppet/modules/postgresql/manifests/server/recovery.pp new file mode 100644 index 0000000..924866e --- /dev/null +++ b/puphpet/puppet/modules/postgresql/manifests/server/recovery.pp @@ -0,0 +1,38 @@ +# This resource manages the parameters that applies to the recovery.conf template. See README.md for more details. +define postgresql::server::recovery( + $restore_command = undef, + $archive_cleanup_command = undef, + $recovery_end_command = undef, + $recovery_target_name = undef, + $recovery_target_time = undef, + $recovery_target_xid = undef, + $recovery_target_inclusive = undef, + $recovery_target = undef, + $recovery_target_timeline = undef, + $pause_at_recovery_target = undef, + $standby_mode = undef, + $primary_conninfo = undef, + $primary_slot_name = undef, + $trigger_file = undef, + $recovery_min_apply_delay = undef, + $target = $postgresql::server::recovery_conf_path +) { + + if $postgresql::server::manage_recovery_conf == false { + fail('postgresql::server::manage_recovery_conf has been disabled, so this resource is now unused and redundant, either enable that option or remove this resource from your manifests') + } else { + if($restore_command == undef and $archive_cleanup_command == undef and $recovery_end_command == undef + and $recovery_target_name == undef and $recovery_target_time == undef and $recovery_target_xid == undef + and $recovery_target_inclusive == undef and $recovery_target == undef and $recovery_target_timeline == undef + and $pause_at_recovery_target == undef and $standby_mode == undef and $primary_conninfo == undef + and $primary_slot_name == undef and $trigger_file == undef and $recovery_min_apply_delay == undef) { + fail('postgresql::server::recovery use this resource but do not pass a parameter will avoid creating the recovery.conf, because it makes no sense.') + } + + # Create the recovery.conf content + concat::fragment { 'recovery.conf': + target => $target, + content => template('postgresql/recovery.conf'), + } + } +} diff --git a/puphpet/puppet/modules/postgresql/manifests/server/role.pp b/puphpet/puppet/modules/postgresql/manifests/server/role.pp index a117456..6b23aba 100644 --- a/puphpet/puppet/modules/postgresql/manifests/server/role.pp +++ b/puphpet/puppet/modules/postgresql/manifests/server/role.pp @@ -24,9 +24,11 @@ $superuser_sql = $superuser ? { true => 'SUPERUSER', default => 'NOSUPERUSER' } $replication_sql = $replication ? { true => 'REPLICATION', default => '' } if ($password_hash != false) { - $password_sql = "ENCRYPTED PASSWORD '${password_hash}'" + $environment = "NEWPGPASSWD=${password_hash}" + $password_sql = "ENCRYPTED PASSWORD '\$NEWPGPASSWD'" } else { $password_sql = '' + $environment = [] } Postgresql_psql { @@ -35,12 +37,17 @@ psql_user => $psql_user, psql_group => $psql_group, psql_path => $psql_path, - require => [ Postgresql_psql["CREATE ROLE \"${username}\" ${password_sql} ${login_sql} ${createrole_sql} ${createdb_sql} ${superuser_sql} ${replication_sql} CONNECTION LIMIT ${connection_limit}"], Class['postgresql::server'] ], + require => [ + Postgresql_psql["CREATE ROLE ${username} ENCRYPTED PASSWORD ****"], + Class['postgresql::server'], + ], } - postgresql_psql {"CREATE ROLE \"${username}\" ${password_sql} ${login_sql} ${createrole_sql} ${createdb_sql} ${superuser_sql} ${replication_sql} CONNECTION LIMIT ${connection_limit}": - unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}'", - require => Class['Postgresql::Server'], + postgresql_psql { "CREATE ROLE ${username} ENCRYPTED PASSWORD ****": + command => "CREATE ROLE \"${username}\" ${password_sql} ${login_sql} ${createrole_sql} ${createdb_sql} ${superuser_sql} ${replication_sql} CONNECTION LIMIT ${connection_limit}", + unless => "SELECT rolname FROM pg_roles WHERE rolname='${username}'", + environment => $environment, + require => Class['Postgresql::Server'], } postgresql_psql {"ALTER ROLE \"${username}\" ${superuser_sql}": @@ -86,8 +93,10 @@ $pwd_md5 = md5("${password_hash}${username}") $pwd_hash_sql = "md5${pwd_md5}" } - postgresql_psql {"ALTER ROLE \"${username}\" ${password_sql}": - unless => "SELECT usename FROM pg_shadow WHERE usename='${username}' and passwd='${pwd_hash_sql}'", + postgresql_psql { "ALTER ROLE ${username} ENCRYPTED PASSWORD ****": + command => "ALTER ROLE \"${username}\" ${password_sql}", + unless => "SELECT usename FROM pg_shadow WHERE usename='${username}' and passwd='${pwd_hash_sql}'", + environment => $environment, } } } diff --git a/puphpet/puppet/modules/postgresql/manifests/server/schema.pp b/puphpet/puppet/modules/postgresql/manifests/server/schema.pp index f2dd231..c4f84eb 100644 --- a/puphpet/puppet/modules/postgresql/manifests/server/schema.pp +++ b/puphpet/puppet/modules/postgresql/manifests/server/schema.pp @@ -31,7 +31,7 @@ port => $port, } - $schema_title = "Create Schema '${schema}'" + $schema_title = "Create Schema '${title}'" $authorization = $owner? { undef => '', default => "AUTHORIZATION \"${owner}\"", diff --git a/puphpet/puppet/modules/postgresql/manifests/server/table_grant.pp b/puphpet/puppet/modules/postgresql/manifests/server/table_grant.pp index 6a50f93..20114b3 100644 --- a/puphpet/puppet/modules/postgresql/manifests/server/table_grant.pp +++ b/puphpet/puppet/modules/postgresql/manifests/server/table_grant.pp @@ -5,18 +5,20 @@ $table, $db, $role, - $port = $postgresql::server::port, - $psql_db = undef, - $psql_user = undef + $port = $postgresql::server::port, + $psql_db = undef, + $psql_user = undef, + $onlyif_exists = false, ) { postgresql::server::grant { "table:${name}": - role => $role, - db => $db, - port => $port, - privilege => $privilege, - object_type => 'TABLE', - object_name => $table, - psql_db => $psql_db, - psql_user => $psql_user, + role => $role, + db => $db, + port => $port, + privilege => $privilege, + object_type => 'TABLE', + object_name => $table, + psql_db => $psql_db, + psql_user => $psql_user, + onlyif_exists => $onlyif_exists, } } diff --git a/puphpet/puppet/modules/postgresql/manifests/validate_db_connection.pp b/puphpet/puppet/modules/postgresql/manifests/validate_db_connection.pp index a09c4a9..e1c08e6 100644 --- a/puphpet/puppet/modules/postgresql/manifests/validate_db_connection.pp +++ b/puphpet/puppet/modules/postgresql/manifests/validate_db_connection.pp @@ -18,6 +18,7 @@ include postgresql::params $psql_path = $postgresql::params::psql_path + $validcon_script_path = $postgresql::client::validcon_script_path $cmd_init = "${psql_path} --tuples-only --quiet " $cmd_host = $database_host ? { @@ -40,14 +41,14 @@ undef => undef, default => "PGPASSWORD=${database_password}", } - $cmd = join([$cmd_init, $cmd_host, $cmd_user, $cmd_port, $cmd_dbname]) - $validate_cmd = "/usr/local/bin/validate_postgresql_connection.sh ${sleep} ${tries} '${cmd}'" + $cmd = join([$cmd_init, $cmd_host, $cmd_user, $cmd_port, $cmd_dbname], ' ') + $validate_cmd = "${validcon_script_path} ${sleep} ${tries} '${cmd}'" # This is more of a safety valve, we add a little extra to compensate for the # time it takes to run each psql command. $timeout = (($sleep + 2) * $tries) - $exec_name = "validate postgres connection for ${database_host}/${database_name}" + $exec_name = "validate postgres connection for ${database_username}@${database_host}:${database_port}/${database_name}" exec { $exec_name: command => "echo 'Unable to connect to defined database using: ${cmd}' && false", unless => $validate_cmd, diff --git a/puphpet/puppet/modules/postgresql/metadata.json b/puphpet/puppet/modules/postgresql/metadata.json index ab9f3cd..9272049 100644 --- a/puphpet/puppet/modules/postgresql/metadata.json +++ b/puphpet/puppet/modules/postgresql/metadata.json @@ -1,11 +1,11 @@ { "name": "puppetlabs-postgresql", - "version": "4.2.0", + "version": "4.6.0", "author": "Inkling/Puppet Labs", "summary": "Offers support for basic management of PostgreSQL databases.", "license": "Apache-2.0", - "source": "git://github.com/puppetlabs/puppet-postgresql.git", - "project_page": "https://github.com/puppetlabs/puppet-postgresql", + "source": "git://github.com/puppetlabs/puppetlabs-postgresql.git", + "project_page": "https://github.com/puppetlabs/puppetlabs-postgresql", "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", "operatingsystem_support": [ { @@ -59,16 +59,16 @@ "requirements": [ { "name": "pe", - "version_requirement": "3.x" + "version_requirement": ">= 3.0.0 < 2015.3.0" }, { "name": "puppet", - "version_requirement": "3.x" + "version_requirement": ">= 3.0.0 < 5.0.0" } ], "dependencies": [ {"name":"puppetlabs/stdlib","version_requirement":"4.x"}, - {"name":"puppetlabs/apt","version_requirement":">=1.1.0 <2.0.0"}, + {"name":"puppetlabs/apt","version_requirement":">=1.8.0 <3.0.0"}, {"name":"puppetlabs/concat","version_requirement":">= 1.1.0 <2.0.0"} ] } diff --git a/puphpet/puppet/modules/postgresql/spec/acceptance/db_spec.rb b/puphpet/puppet/modules/postgresql/spec/acceptance/db_spec.rb index ba9dc27..6435119 100644 --- a/puphpet/puppet/modules/postgresql/spec/acceptance/db_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/acceptance/db_spec.rb @@ -5,7 +5,9 @@ begin tmpdir = default.tmpdir('postgresql') pp = <<-EOS - class { 'postgresql::server': } + class { 'postgresql::server': + postgres_password => 'space password', + } postgresql::server::tablespace { 'postgresql_test_db': location => '#{tmpdir}', } -> @@ -20,6 +22,11 @@ class { 'postgresql::server': } apply_manifest(pp, :catch_failures => true) apply_manifest(pp, :catch_changes => true) + # Verify that the postgres password works + shell("echo 'localhost:*:*:postgres:space password' > /root/.pgpass") + shell("chmod 600 /root/.pgpass") + shell("psql -U postgres -h localhost --command='\\l'") + psql('--command="select datname from pg_database" postgresql_test_db') do |r| expect(r.stdout).to match(/postgresql_test_db/) expect(r.stderr).to eq('') diff --git a/puphpet/puppet/modules/postgresql/spec/acceptance/postgresql_psql_spec.rb b/puphpet/puppet/modules/postgresql/spec/acceptance/postgresql_psql_spec.rb index 1dd3ee4..34a258c 100644 --- a/puphpet/puppet/modules/postgresql/spec/acceptance/postgresql_psql_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/acceptance/postgresql_psql_spec.rb @@ -113,4 +113,71 @@ class { 'postgresql::server': } -> apply_manifest(pp, :expect_changes => true) end end + + it 'should not run some SQL when the onlyif query returns no rows' do + pp = <<-EOS + class { 'postgresql::server': } -> + postgresql_psql { 'foobar': + db => 'postgres', + psql_user => 'postgres', + command => 'select 1', + onlyif => 'select 1 where 1=2', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + it 'should run SQL when the onlyif query returns rows' do + pp = <<-EOS + class { 'postgresql::server': } -> + postgresql_psql { 'foobar': + db => 'postgres', + psql_user => 'postgres', + command => 'select * from pg_database limit 1', + onlyif => 'select 1 where 1=1', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :expect_changes => true) + end + + context 'with secure password passing by environment' do + it 'should run SQL that contanins password passed by environment' do + select = "select \\'$PASS_TO_EMBED\\'" + pp = <<-EOS.unindent + class { 'postgresql::server': } -> + postgresql_psql { 'password embedded by environment: #{select}': + db => 'postgres', + psql_user => 'postgres', + command => '#{select}', + environment => [ + 'PASS_TO_EMBED=pa$swD', + ], + } + EOS + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :expect_changes => false) + end + it 'should run SQL that contanins password passed by environment in check' do + select = "select 1 where \\'$PASS_TO_EMBED\\'=\\'passwD\\'" + pp = <<-EOS.unindent + class { 'postgresql::server': } -> + postgresql_psql { 'password embedded by environment in check: #{select}': + db => 'postgres', + psql_user => 'postgres', + command => 'invalid sql query', + unless => '#{select}', + environment => [ + 'PASS_TO_EMBED=passwD', + ], + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :expect_changes => false) + end + end end diff --git a/puphpet/puppet/modules/postgresql/spec/acceptance/server/recovery_spec.rb b/puphpet/puppet/modules/postgresql/spec/acceptance/server/recovery_spec.rb new file mode 100644 index 0000000..b27a5c5 --- /dev/null +++ b/puphpet/puppet/modules/postgresql/spec/acceptance/server/recovery_spec.rb @@ -0,0 +1,61 @@ +require 'spec_helper_acceptance' + +describe 'postgresql::server::recovery', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do + describe 'should manage recovery' do + after(:all) do + pp = <<-EOS.unindent + file { '/tmp/recovery.conf': + ensure => absent, + } + EOS + + apply_manifest(pp, :catch_failures => true) + end + + it 'adds conf file' do + pp = <<-EOS.unindent + class { 'postgresql::globals': + recovery_conf_path => '/tmp/recovery.conf', + manage_recovery_conf => true, + } + + class { 'postgresql::server': } + + # Create a recovery.conf file + postgresql::server::recovery { "recovery.conf": + restore_command => 'restore_command', + recovery_target_timeline => 'recovery_target_timeline', + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file('/tmp/recovery.conf') do + it { is_expected.to be_file } + it { is_expected.to contain /restore_command = 'restore_command'/ } + it { is_expected.to contain /recovery_target_timeline = 'recovery_target_timeline'/ } + end + end + + describe 'should not manage recovery' do + it 'does not add conf file' do + pp = <<-EOS.unindent + class { 'postgresql::globals': + manage_recovery_conf => false, + } + + class { 'postgresql::server': } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe file('/tmp/recovery.conf') do + it { is_expected.not_to be_file } + end + end +end + diff --git a/puphpet/puppet/modules/postgresql/spec/acceptance/z_alternative_pgdata_spec.rb b/puphpet/puppet/modules/postgresql/spec/acceptance/z_alternative_pgdata_spec.rb index bf1825a..29f09a0 100644 --- a/puphpet/puppet/modules/postgresql/spec/acceptance/z_alternative_pgdata_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/acceptance/z_alternative_pgdata_spec.rb @@ -4,8 +4,8 @@ # location properly. # Allow postgresql to use /tmp/* as a datadir -if fact('osfamily') == 'RedHat' - shell("setenforce 0") +if fact('osfamily') == 'RedHat' and fact('selinux') == 'true' + shell 'setenforce 0' end describe 'postgres::server', :unless => UNSUPPORTED_PLATFORMS.include?(fact('osfamily')) do diff --git a/puphpet/puppet/modules/postgresql/spec/spec_helper_acceptance.rb b/puphpet/puppet/modules/postgresql/spec/spec_helper_acceptance.rb index 14d0f84..2525ec3 100644 --- a/puphpet/puppet/modules/postgresql/spec/spec_helper_acceptance.rb +++ b/puphpet/puppet/modules/postgresql/spec/spec_helper_acceptance.rb @@ -1,5 +1,10 @@ require 'beaker-rspec/spec_helper' require 'beaker-rspec/helpers/serverspec' +require 'beaker/puppet_install_helper' + +run_puppet_install_helper + +UNSUPPORTED_PLATFORMS = ['AIX','windows','Solaris','Suse'] class String # Provide ability to remove indentation from strings, for the purpose of @@ -34,27 +39,6 @@ def psql(psql_cmd, user = 'postgres', exit_codes = [0,1], &block) shell("su #{shellescape(user)} -c #{shellescape(psql)}", :acceptable_exit_codes => exit_codes, &block) end -unless ENV['RS_PROVISION'] == 'no' or ENV['BEAKER_provision'] == 'no' - # This will install the latest available package on el and deb based - # systems fail on windows and osx, and install via gem on other *nixes - foss_opts = { :default_action => 'gem_install' } - - if default.is_pe?; then install_pe; else install_puppet( foss_opts ); end - - hosts.each do |host| - shell("mkdir -p #{host['distmoduledir']}") - if ! host.is_pe? - # Augeas is only used in one place, for Redhat. - if fact('osfamily') == 'RedHat' - install_package host, 'ruby-devel' - #install_package host, 'augeas-devel' - #install_package host, 'ruby-augeas' - end - end - end -end - -UNSUPPORTED_PLATFORMS = ['AIX','windows','Solaris','Suse'] RSpec.configure do |c| # Project root @@ -89,10 +73,19 @@ def psql(psql_cmd, user = 'postgres', exit_codes = [0,1], &block) apply_manifest_on(agents, pp, :catch_failures => false) end + # 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 + hosts.each do |host| on host, "/bin/touch #{default['puppetpath']}/hiera.yaml" on host, 'chmod 755 /root' - if fact('osfamily') == 'Debian' + if fact_on(host, 'osfamily') == 'Debian' on host, "echo \"en_US ISO-8859-1\nen_NG.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\n\" > /etc/locale.gen" on host, '/usr/sbin/locale-gen' on host, '/usr/sbin/update-locale' diff --git a/puphpet/puppet/modules/postgresql/spec/unit/classes/client_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/classes/client_spec.rb index 66d758f..3d63b46 100644 --- a/puphpet/puppet/modules/postgresql/spec/unit/classes/client_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/unit/classes/client_spec.rb @@ -12,8 +12,10 @@ describe 'with parameters' do let :params do { + :validcon_script_path => '/opt/bin/my-validate-con.sh', :package_ensure => 'absent', - :package_name => 'mypackage', + :package_name => 'mypackage', + :file_ensure => 'file' } end @@ -24,6 +26,15 @@ :tag => 'postgresql', }) end + + it 'should have specified validate connexion' do + should contain_file('/opt/bin/my-validate-con.sh').with({ + :ensure => 'file', + :owner => 0, + :group => 0, + :mode => '0755' + }) + end end describe 'with no parameters' do diff --git a/puphpet/puppet/modules/postgresql/spec/unit/classes/globals_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/classes/globals_spec.rb index dd2cfb8..ce79336 100644 --- a/puphpet/puppet/modules/postgresql/spec/unit/classes/globals_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/unit/classes/globals_spec.rb @@ -1,30 +1,67 @@ require 'spec_helper' describe 'postgresql::globals', :type => :class do - let :facts do - { - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6.0', - :lsbdistid => 'Debian', - :lsbdistcodename => 'squeeze', - } - end + context "on a debian 6" do + let (:facts) do + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + :operatingsystemrelease => '6.0', + :lsbdistid => 'Debian', + :lsbdistcodename => 'squeeze', + } + end - describe 'with no parameters' do - it 'should work' do - is_expected.to contain_class("postgresql::globals") + describe 'with no parameters' do + it 'should work' do + is_expected.to contain_class("postgresql::globals") + end + end + + describe 'manage_package_repo => true' do + let(:params) do + { + :manage_package_repo => true, + } + end + it 'should pull in class postgresql::repo' do + is_expected.to contain_class("postgresql::repo") + end end end - describe 'manage_package_repo => true' do - let(:params) do + context 'on redhat family systems' do + let (:facts) do { - :manage_package_repo => true, + :osfamily => 'RedHat', + :operatingsystem => 'RedHat', + :operatingsystemrelease => '7.1', } end - it 'should pull in class postgresql::repo' do - is_expected.to contain_class("postgresql::repo") + describe 'with no parameters' do + it 'should work' do + is_expected.to contain_class("postgresql::globals") + end + end + + describe 'manage_package_repo on RHEL => true' do + let(:params) do + { + :manage_package_repo => true, + :repo_proxy => 'http://proxy-server:8080', + } + end + + it 'should pull in class postgresql::repo' do + is_expected.to contain_class("postgresql::repo") + end + + it do + should contain_yumrepo('yum.postgresql.org').with( + 'enabled' => '1', + 'proxy' => 'http://proxy-server:8080' + ) + end end end end diff --git a/puphpet/puppet/modules/postgresql/spec/unit/classes/lib/pgdocs_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/classes/lib/pgdocs_spec.rb new file mode 100644 index 0000000..a751e98 --- /dev/null +++ b/puphpet/puppet/modules/postgresql/spec/unit/classes/lib/pgdocs_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe 'postgresql::lib::docs', :type => :class do + + describe 'on a redhat based os' do + let :facts do { + :osfamily => 'RedHat', + :operatingsystem => 'RedHat', + :operatingsystemrelease => '6.4', + } + end + it { is_expected.to contain_package('postgresql-docs').with( + :name => 'postgresql-docs', + :ensure => 'present', + :tag => 'postgresql' + )} + describe 'when parameters are supplied' do + let :params do + {:package_ensure => 'latest', :package_name => 'somepackage'} + end + it { is_expected.to contain_package('postgresql-docs').with( + :name => 'somepackage', + :ensure => 'latest', + :tag => 'postgresql' + )} + end + end + +end diff --git a/puphpet/puppet/modules/postgresql/spec/unit/classes/server/config_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/classes/server/config_spec.rb new file mode 100644 index 0000000..4e77c7e --- /dev/null +++ b/puphpet/puppet/modules/postgresql/spec/unit/classes/server/config_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe 'postgresql::server::config', :type => :class do + let (:pre_condition) do + "include postgresql::server" + end + + describe 'on RedHat 7' do + let :facts do + { + :osfamily => 'RedHat', + :operatingsystem => 'CentOS', + :operatingsystemrelease => '7.0', + :concat_basedir => tmpfilename('server'), + :kernel => 'Linux', + :id => 'root', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + } + end + it 'should have the correct systemd-override file' do + is_expected.to contain_file('systemd-override').with ({ + :ensure => 'present', + :path => '/etc/systemd/system/postgresql.service', + :owner => 'root', + :group => 'root', + }) + is_expected.to contain_file('systemd-override') \ + .with_content(/postgresql.service/) + end + + describe 'with manage_package_repo => true and a version' do + let (:pre_condition) do + <<-EOS + class { 'postgresql::globals': + manage_package_repo => true, + version => '9.4', + }-> + class { 'postgresql::server': } + EOS + end + + it 'should have the correct systemd-override file' do + is_expected.to contain_file('systemd-override').with ({ + :ensure => 'present', + :path => '/etc/systemd/system/postgresql-9.4.service', + :owner => 'root', + :group => 'root', + }) + is_expected.to contain_file('systemd-override') \ + .with_content(/postgresql-9.4.service/) + end + end + end +end + diff --git a/puphpet/puppet/modules/postgresql/spec/unit/classes/server/plpython_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/classes/server/plpython_spec.rb new file mode 100644 index 0000000..f2e1654 --- /dev/null +++ b/puphpet/puppet/modules/postgresql/spec/unit/classes/server/plpython_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe 'postgresql::server::plpython', :type => :class do + let :facts do + { + :osfamily => 'RedHat', + :operatingsystem => 'CentOS', + :operatingsystemrelease => '6.0', + :concat_basedir => tmpfilename('plpython'), + :kernel => 'Linux', + :id => 'root', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + } + end + + let :pre_condition do + "class { 'postgresql::server': }" + end + + describe 'on RedHat with no parameters' do + it { is_expected.to contain_class("postgresql::server::plpython") } + it 'should create package' do + is_expected.to contain_package('postgresql-plpython').with({ + :ensure => 'present', + :tag => 'postgresql', + }) + end + end + + describe 'with parameters' do + let :params do + { + :package_ensure => 'absent', + :package_name => 'mypackage', + } + end + + it { is_expected.to contain_class("postgresql::server::plpython") } + it 'should create package with correct params' do + is_expected.to contain_package('postgresql-plpython').with({ + :ensure => 'absent', + :name => 'mypackage', + :tag => 'postgresql', + }) + end + end +end diff --git a/puphpet/puppet/modules/postgresql/spec/unit/classes/server_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/classes/server_spec.rb index 1bba7c5..c29473a 100644 --- a/puphpet/puppet/modules/postgresql/spec/unit/classes/server_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/unit/classes/server_spec.rb @@ -26,12 +26,29 @@ end describe 'service_ensure => running' do - let(:params) {{ :service_ensure => 'running' }} + let(:params) do + { + :service_ensure => 'running', + :postgres_password => 'new-p@s$word-to-set' + } + end it { is_expected.to contain_class("postgresql::params") } it { is_expected.to contain_class("postgresql::server") } + it { is_expected.to contain_class("postgresql::server::passwd") } it 'should validate connection' do is_expected.to contain_postgresql__validate_db_connection('validate_service_is_running') end + it 'should set postgres password' do + is_expected.to contain_exec('set_postgres_postgrespw').with({ + 'command' => '/usr/bin/psql -c "ALTER ROLE \"postgres\" PASSWORD ${NEWPASSWD_ESCAPED}"', + 'user' => 'postgres', + 'environment' => [ + "PGPASSWORD=new-p@s$word-to-set", + "NEWPASSWD_ESCAPED=$$new-p@s$word-to-set$$" + ], + 'unless' => "/usr/bin/psql -h localhost -p 5432 -c 'select 1' > /dev/null", + }) + end end describe 'service_ensure => stopped' do diff --git a/puphpet/puppet/modules/postgresql/spec/unit/defines/server/extension_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/extension_spec.rb index 61d4569..306326d 100644 --- a/puphpet/puppet/modules/postgresql/spec/unit/defines/server/extension_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/extension_spec.rb @@ -29,7 +29,7 @@ it { is_expected.to contain_postgresql_psql('Add postgis extension to template_postgis').with({ :db => 'template_postgis', - :command => 'CREATE EXTENSION postgis', + :command => 'CREATE EXTENSION "postgis"', :unless => "SELECT t.count FROM (SELECT count(extname) FROM pg_extension WHERE extname = 'postgis') as t WHERE t.count = 1", }).that_requires('Postgresql::Server::Database[template_postgis]') } @@ -57,7 +57,7 @@ it { is_expected.to contain_postgresql_psql('Add postgis extension to template_postgis').with({ :db => 'template_postgis', - :command => 'DROP EXTENSION postgis', + :command => 'DROP EXTENSION "postgis"', :unless => "SELECT t.count FROM (SELECT count(extname) FROM pg_extension WHERE extname = 'postgis') as t WHERE t.count != 1", }).that_requires('Postgresql::Server::Database[template_postgis]') } @@ -77,7 +77,7 @@ it { is_expected.to contain_postgresql_psql('Add postgis extension to template_postgis').with({ :db => 'template_postgis', - :command => 'DROP EXTENSION postgis', + :command => 'DROP EXTENSION "postgis"', :unless => "SELECT t.count FROM (SELECT count(extname) FROM pg_extension WHERE extname = 'postgis') as t WHERE t.count != 1", }).that_requires('Postgresql::Server::Database[template_postgis]') } diff --git a/puphpet/puppet/modules/postgresql/spec/unit/defines/server/grant_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/grant_spec.rb index 5371663..13588d4 100644 --- a/puphpet/puppet/modules/postgresql/spec/unit/defines/server/grant_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/grant_spec.rb @@ -17,16 +17,63 @@ 'test' end - let :params do - { - :db => 'test', - :role => 'test', - } + context 'plain' do + let :params do + { + :db => 'test', + :role => 'test', + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to contain_postgresql__server__grant('test') } end - let :pre_condition do - "class {'postgresql::server':}" + context 'sequence' do + let :params do + { + :db => 'test', + :role => 'test', + :privilege => 'usage', + :object_type => 'sequence', + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to contain_postgresql__server__grant('test') } + it { is_expected.to contain_postgresql_psql('grant:test').with( + { + 'command' => "GRANT USAGE ON SEQUENCE \"test\" TO\n \"test\"", + 'unless' => "SELECT 1 WHERE has_sequence_privilege('test',\n 'test', 'USAGE')", + }) } end - it { is_expected.to contain_postgresql__server__grant('test') } + context 'all sequences' do + let :params do + { + :db => 'test', + :role => 'test', + :privilege => 'usage', + :object_type => 'all sequences in schema', + :object_name => 'public', + } + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + it { is_expected.to contain_postgresql__server__grant('test') } + it { is_expected.to contain_postgresql_psql('grant:test').with( + { + 'command' => "GRANT USAGE ON ALL SEQUENCES IN SCHEMA \"public\" TO\n \"test\"", + 'unless' => "SELECT 1 FROM (\n SELECT sequence_name\n FROM information_schema.sequences\n WHERE sequence_schema='public'\n EXCEPT DISTINCT\n SELECT object_name as sequence_name\n FROM information_schema.role_usage_grants\n WHERE object_type='SEQUENCE'\n AND grantee='test'\n AND object_schema='public'\n AND privilege_type='USAGE'\n ) P\n HAVING count(P.sequence_name) = 0", + }) } + end end diff --git a/puphpet/puppet/modules/postgresql/spec/unit/defines/server/pg_hba_rule_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/pg_hba_rule_spec.rb index 8ddfcd5..f36d27d 100644 --- a/puphpet/puppet/modules/postgresql/spec/unit/defines/server/pg_hba_rule_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/pg_hba_rule_spec.rb @@ -110,7 +110,7 @@ class { 'postgresql::server': } } end it 'should fail parsing when type is not valid' do - expect {subject}.to raise_error(Puppet::Error, + expect { catalogue }.to raise_error(Puppet::Error, /The type you specified \[invalid\] must be one of/) end end @@ -134,7 +134,7 @@ class { 'postgresql::server': } end it 'should fail parsing when auth_method is not valid' do - expect {subject}.to raise_error(Puppet::Error, + expect { catalogue }.to raise_error(Puppet::Error, /The auth_method you specified \[invalid\] must be one of/) end end @@ -161,8 +161,8 @@ class { 'postgresql::server': } end it 'should fail parsing when auth_method is not valid' do - expect {subject}.to raise_error(Puppet::Error, - /The auth_method you specified \[peer\] must be one of: trust, reject, md5, sha1, password, gss, sspi, krb5, ident, ldap, radius, cert, pam/) + expect { catalogue }.to raise_error(Puppet::Error, + /The auth_method you specified \[peer\] must be one of: trust, reject, md5, password, gss, sspi, krb5, ident, ldap, radius, cert, pam/) end end diff --git a/puphpet/puppet/modules/postgresql/spec/unit/defines/server/pg_ident_rule_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/pg_ident_rule_spec.rb index 5a633d2..71dfff8 100644 --- a/puphpet/puppet/modules/postgresql/spec/unit/defines/server/pg_ident_rule_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/pg_ident_rule_spec.rb @@ -59,7 +59,7 @@ class { 'postgresql::server': } } end it 'should fail because $manage_pg_ident_conf is false' do - expect {subject}.to raise_error(Puppet::Error, + expect { catalogue }.to raise_error(Puppet::Error, /postgresql::server::manage_pg_ident_conf has been disabled/) end end diff --git a/puphpet/puppet/modules/postgresql/spec/unit/defines/server/recovery_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/recovery_spec.rb new file mode 100644 index 0000000..8c78e3e --- /dev/null +++ b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/recovery_spec.rb @@ -0,0 +1,113 @@ +require 'spec_helper' + +describe 'postgresql::server::recovery', :type => :define do + let :facts do + { + :osfamily => 'Debian', + :operatingsystem => 'Debian', + :operatingsystemrelease => '6.0', + :kernel => 'Linux', + :concat_basedir => tmpfilename('recovery'), + :id => 'root', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + } + end + let :title do + 'test' + end + let :target do + tmpfilename('recovery') + end + + context 'managing recovery' do + let :pre_condition do + <<-EOS + class { 'postgresql::globals': + manage_recovery_conf => true, + } + class { 'postgresql::server': } + EOS + end + + let :params do + { + :restore_command => 'restore_command', + :recovery_target_timeline => 'recovery_target_timeline', + } + end + it do + is_expected.to contain_concat__fragment('recovery.conf').with({ + :content => /restore_command = 'restore_command'[\n]+recovery_target_timeline = 'recovery_target_timeline'/ + }) + end + end + context 'not managing recovery' do + let :pre_condition do + <<-EOS + class { 'postgresql::globals': + manage_recovery_conf => false, + } + class { 'postgresql::server': } + EOS + end + let :params do + { + :restore_command => '', + } + end + it 'should fail because $manage_recovery_conf is false' do + expect { catalogue }.to raise_error(Puppet::Error, + /postgresql::server::manage_recovery_conf has been disabled/) + end + end + context 'not managing recovery, missing param' do + let :pre_condition do + <<-EOS + class { 'postgresql::globals': + manage_recovery_conf => true, + } + class { 'postgresql::server': } + EOS + end + it 'should fail because no param set' do + expect { catalogue }.to raise_error(Puppet::Error, + /postgresql::server::recovery use this resource but do not pass a parameter will avoid creating the recovery.conf, because it makes no sense./) + end + end + + context 'managing recovery with all params' do + let :pre_condition do + <<-EOS + class { 'postgresql::globals': + manage_recovery_conf => true, + } + class { 'postgresql::server': } + EOS + end + + let :params do + { + :restore_command => 'restore_command', + :archive_cleanup_command => 'archive_cleanup_command', + :recovery_end_command => 'recovery_end_command', + :recovery_target_name => 'recovery_target_name', + :recovery_target_time => 'recovery_target_time', + :recovery_target_xid => 'recovery_target_xid', + :recovery_target_inclusive => true, + :recovery_target => 'recovery_target', + :recovery_target_timeline => 'recovery_target_timeline', + :pause_at_recovery_target => true, + :standby_mode => 'on', + :primary_conninfo => 'primary_conninfo', + :primary_slot_name => 'primary_slot_name', + :trigger_file => 'trigger_file', + :recovery_min_apply_delay => 0, + } + end + it do + is_expected.to contain_concat__fragment('recovery.conf').with({ + :content => /restore_command = 'restore_command'[\n]+archive_cleanup_command = 'archive_cleanup_command'[\n]+recovery_end_command = 'recovery_end_command'[\n]+recovery_target_name = 'recovery_target_name'[\n]+recovery_target_time = 'recovery_target_time'[\n]+recovery_target_xid = 'recovery_target_xid'[\n]+recovery_target_inclusive = true[\n]+recovery_target = 'recovery_target'[\n]+recovery_target_timeline = 'recovery_target_timeline'[\n]+pause_at_recovery_target = true[\n]+standby_mode = on[\n]+primary_conninfo = 'primary_conninfo'[\n]+primary_slot_name = 'primary_slot_name'[\n]+trigger_file = 'trigger_file'[\n]+recovery_min_apply_delay = 0[\n]+/ + }) + end + end +end diff --git a/puphpet/puppet/modules/postgresql/spec/unit/defines/server/role_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/role_spec.rb index f73b909..8f90855 100644 --- a/puphpet/puppet/modules/postgresql/spec/unit/defines/server/role_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/unit/defines/server/role_spec.rb @@ -19,7 +19,7 @@ let :params do { - :password_hash => 'test', + :password_hash => 'new-pa$s', } end @@ -28,4 +28,18 @@ end it { is_expected.to contain_postgresql__server__role('test') } + it 'should have create role for "test" user with password as ****' do + is_expected.to contain_postgresql_psql('CREATE ROLE test ENCRYPTED PASSWORD ****').with({ + 'command' => "CREATE ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1", + 'environment' => "NEWPGPASSWD=new-pa$s", + 'unless' => "SELECT rolname FROM pg_roles WHERE rolname='test'", + }) + end + it 'should have alter role for "test" user with password as ****' do + is_expected.to contain_postgresql_psql('ALTER ROLE test ENCRYPTED PASSWORD ****').with({ + 'command' => "ALTER ROLE \"test\" ENCRYPTED PASSWORD '$NEWPGPASSWD'", + 'environment' => "NEWPGPASSWD=new-pa$s", + 'unless' => "SELECT usename FROM pg_shadow WHERE usename='test' and passwd='md5b6f7fcbbabb4befde4588a26c1cfd2fa'", + }) + end end diff --git a/puphpet/puppet/modules/postgresql/spec/unit/defines/validate_db_connection_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/defines/validate_db_connection_spec.rb index a016a11..9cf5048 100644 --- a/puphpet/puppet/modules/postgresql/spec/unit/defines/validate_db_connection_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/unit/defines/validate_db_connection_spec.rb @@ -31,5 +31,36 @@ } end it { is_expected.to contain_postgresql__validate_db_connection('test') } + + it 'should have proper path for validate command' do + is_expected.to contain_exec('validate postgres connection for test@test:5432/test').with({ + :unless => %r'^/usr/local/bin/validate_postgresql_connection.sh\s+\d+' + }) + end end + + describe 'should work while specifying validate_connection in postgresql::client' do + + let :params do + { + :database_host => 'test', + :database_name => 'test', + :database_password => 'test', + :database_username => 'test', + :database_port => 5432 + } + end + + let :pre_condition do + "class { 'postgresql::client': validcon_script_path => '/opt/something/validate.sh' }" + end + + it 'should have proper path for validate command' do + is_expected.to contain_exec('validate postgres connection for test@test:5432/test').with({ + :unless => %r'^/opt/something/validate.sh\s+\d+' + }) + end + + end + end diff --git a/puphpet/puppet/modules/postgresql/spec/unit/puppet/provider/postgresql_psql/ruby_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/puppet/provider/postgresql_psql/ruby_spec.rb index 2282edf..b21a326 100644 --- a/puphpet/puppet/modules/postgresql/spec/unit/puppet/provider/postgresql_psql/ruby_spec.rb +++ b/puphpet/puppet/modules/postgresql/spec/unit/puppet/provider/postgresql_psql/ruby_spec.rb @@ -14,10 +14,10 @@ it "executes with the given psql_path on the given DB" do expect(provider).to receive(:run_command).with(['psql', '-d', - attributes[:db], '-t', '-c', 'SELECT something'], 'postgres', + attributes[:db], '-t', '-c', '"SELECT \'something\' as \"Custom column\""'], 'postgres', 'postgres') - provider.run_sql_command("SELECT something") + provider.run_sql_command('SELECT \'something\' as "Custom column"') end end describe "with psql_path and db" do @@ -32,10 +32,10 @@ it "executes with the given psql_path on the given DB" do expect(Dir).to receive(:chdir).with(attributes[:cwd]).and_yield expect(provider).to receive(:run_command).with([attributes[:psql_path], - '-d', attributes[:db], '-t', '-c', 'SELECT something'], + '-d', attributes[:db], '-t', '-c', '"SELECT \'something\' as \"Custom column\""'], attributes[:psql_user], attributes[:psql_group]) - provider.run_sql_command("SELECT something") + provider.run_sql_command('SELECT \'something\' as "Custom column"') end end describe "with search_path string" do @@ -45,10 +45,10 @@ it "executes with the given search_path" do expect(provider).to receive(:run_command).with(['psql', '-t', '-c', - 'set search_path to schema1; SELECT something'], + '"set search_path to schema1; SELECT \'something\' as \"Custom column\""'], 'postgres', 'postgres') - provider.run_sql_command("SELECT something") + provider.run_sql_command('SELECT \'something\' as "Custom column"') end end describe "with search_path array" do @@ -58,12 +58,12 @@ it "executes with the given search_path" do expect(provider).to receive(:run_command).with(['psql', '-t', '-c', - 'set search_path to schema1,schema2; SELECT something'], + '"set search_path to schema1,schema2; SELECT \'something\' as \"Custom column\""'], 'postgres', 'postgres' ) - provider.run_sql_command("SELECT something") + provider.run_sql_command('SELECT \'something\' as "Custom column"') end end end @@ -73,7 +73,7 @@ it "executes with the given port" do expect(provider).to receive(:run_command).with(["psql", "-p", "5555", - "-t", "-c", "SELECT something"], + "-t", "-c", "\"SELECT something\""], "postgres", "postgres") provider.run_sql_command("SELECT something") diff --git a/puphpet/puppet/modules/postgresql/spec/unit/puppet/provider/postgresql_replication_slot/ruby_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/puppet/provider/postgresql_replication_slot/ruby_spec.rb new file mode 100644 index 0000000..4fc8b55 --- /dev/null +++ b/puphpet/puppet/modules/postgresql/spec/unit/puppet/provider/postgresql_replication_slot/ruby_spec.rb @@ -0,0 +1,92 @@ +require 'spec_helper' + +type = Puppet::Type.type(:postgresql_replication_slot) +describe type.provider(:ruby) do + let(:name) { 'standby' } + let(:resource) do + type.new({ :name => name, :provider => :ruby }.merge attributes) + end + + let(:sql_instances) do + "abc | | physical | | | t | | | 0/3000420 +def | | physical | | | t | | | 0/3000420\n" + end + + class SuccessStatus + def success? + true + end + end + let(:success_status) { SuccessStatus.new } + + class FailStatus + def success? + false + end + end + let(:fail_status) { FailStatus.new } + + let(:provider) { resource.provider } + + context 'when listing instances' do + let(:attributes) do { } end + + it 'should list instances' do + provider.class.expects(:run_command).with( + ['psql', '-t', '-c', 'SELECT * FROM pg_replication_slots;'], + 'postgres', 'postgres').returns([sql_instances, nil]) + instances = provider.class.instances + expect(instances.size).to eq 2 + expect(instances[0].name).to eq 'abc' + expect(instances[1].name).to eq 'def' + end + end + + context 'when creating slot' do + let(:attributes) do { :ensure => 'present' } end + + context 'when creation works' do + it 'should call psql and succeed' do + provider.class.expects(:run_command).with( + ['psql', '-t', '-c', "SELECT * FROM pg_create_physical_replication_slot('standby');"], + 'postgres', 'postgres').returns([nil, success_status]) + + expect { provider.create }.not_to raise_error + end + end + + context 'when creation fails' do + it 'should call psql and fail' do + provider.class.expects(:run_command).with( + ['psql', '-t', '-c', "SELECT * FROM pg_create_physical_replication_slot('standby');"], + 'postgres', 'postgres').returns([nil, fail_status]) + + expect { provider.create }.to raise_error(Puppet::Error, /Failed to create replication slot standby:/) + end + end + end + + context 'when destroying slot' do + let(:attributes) do { :ensure => 'absent' } end + + context 'when destruction works' do + it 'should call psql and succeed' do + provider.class.expects(:run_command).with( + ['psql', '-t', '-c', "SELECT pg_drop_replication_slot('standby');"], + 'postgres', 'postgres').returns([nil, success_status]) + + expect { provider.destroy }.not_to raise_error + end + end + + context 'when destruction fails' do + it 'should call psql and fail' do + provider.class.expects(:run_command).with( + ['psql', '-t', '-c', "SELECT pg_drop_replication_slot('standby');"], + 'postgres', 'postgres').returns([nil, fail_status]) + + expect { provider.destroy }.to raise_error(Puppet::Error, /Failed to destroy replication slot standby:/) + end + end + end +end diff --git a/puphpet/puppet/modules/postgresql/spec/unit/puppet/type/postgresql_replication_slot_spec.rb b/puphpet/puppet/modules/postgresql/spec/unit/puppet/type/postgresql_replication_slot_spec.rb new file mode 100644 index 0000000..0d7c668 --- /dev/null +++ b/puphpet/puppet/modules/postgresql/spec/unit/puppet/type/postgresql_replication_slot_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe Puppet::Type.type(:postgresql_replication_slot) do + subject do + Puppet::Type.type(:postgresql_psql).new({:name => 'standby'}) + end + + it 'should have a name parameter' do + expect(subject[:name]).to eq 'standby' + end +end diff --git a/puphpet/puppet/modules/postgresql/templates/recovery.conf b/puphpet/puppet/modules/postgresql/templates/recovery.conf new file mode 100644 index 0000000..6fb4789 --- /dev/null +++ b/puphpet/puppet/modules/postgresql/templates/recovery.conf @@ -0,0 +1,47 @@ +<% if @restore_command %> +restore_command = '<%= @restore_command %>' +<% end %> +<% if @archive_cleanup_command %> +archive_cleanup_command = '<%= @archive_cleanup_command %>' +<% end %> +<% if @recovery_end_command %> +recovery_end_command = '<%= @recovery_end_command %>' +<% end %> + +<% if @recovery_target_name %> +recovery_target_name = '<%= @recovery_target_name %>' +<% end %> +<% if @recovery_target_time %> +recovery_target_time = '<%= @recovery_target_time %>' +<% end %> +<% if @recovery_target_xid %> +recovery_target_xid = '<%= @recovery_target_xid %>' +<% end %> +<% if @recovery_target_inclusive %> +recovery_target_inclusive = <%= @recovery_target_inclusive %> +<% end %> +<% if @recovery_target %> +recovery_target = '<%= @recovery_target %>' +<% end %> +<% if @recovery_target_timeline %> +recovery_target_timeline = '<%= @recovery_target_timeline %>' +<% end %> +<% if @pause_at_recovery_target %> +pause_at_recovery_target = <%= @pause_at_recovery_target %> +<% end %> + +<% if @standby_mode %> +standby_mode = <%= @standby_mode %> +<% end %> +<% if @primary_conninfo %> +primary_conninfo = '<%= @primary_conninfo %>' +<% end %> +<% if @primary_slot_name %> +primary_slot_name = '<%= @primary_slot_name %>' +<% end %> +<% if @trigger_file %> +trigger_file = '<%= @trigger_file %>' +<% end %> +<% if @recovery_min_apply_delay %> +recovery_min_apply_delay = <%= @recovery_min_apply_delay %> +<% end %> diff --git a/puphpet/puppet/modules/postgresql/templates/systemd-override.erb b/puphpet/puppet/modules/postgresql/templates/systemd-override.erb index 1afb2a8..3910058 100644 --- a/puphpet/puppet/modules/postgresql/templates/systemd-override.erb +++ b/puphpet/puppet/modules/postgresql/templates/systemd-override.erb @@ -1,4 +1,8 @@ +<% if @manage_package_repo and (scope.function_versioncmp([@version.to_s, '9.1']) >= 0) -%> +.include /lib/systemd/system/postgresql-<%= @version %>.service +<% else -%> .include /lib/systemd/system/postgresql.service +<% end -%> [Service] Environment=PGPORT=<%= @port %> Environment=PGDATA=<%= @datadir %> diff --git a/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/deep_merge.rb b/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/deep_merge.rb index 6c9144d..4c5de9f 100644 --- a/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/deep_merge.rb +++ b/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/deep_merge.rb @@ -1,4 +1,4 @@ -require 'active_support' +require 'deep_merge' module Puppet::Parser::Functions newfunction(:deep_merge, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args| @@ -12,7 +12,7 @@ module Puppet::Parser::Functions hashA = args[0] hashB = args[1] - return hashA.deep_merge(hashB) + return hashA.deep_merge!(hashB) end end diff --git a/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/merge_yaml.rb b/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/merge_yaml.rb index 9443028..a7b40a9 100644 --- a/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/merge_yaml.rb +++ b/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/merge_yaml.rb @@ -1,31 +1,24 @@ require 'yaml' -require 'active_support' +require 'deep_merge' module Puppet::Parser::Functions newfunction(:merge_yaml, :type => :rvalue, :doc => <<-'ENDHEREDOC') do |args| - Deep merges two YAML files using Hash#deep_merge + Deep merges two or more YAML files using Hash#deep_merge ENDHEREDOC if args.length < 2 raise Puppet::ParseError, ("merge_yaml(): wrong number of arguments (#{args.length}; must be at least 2)") end - fileA = args[0] - fileB = args[1] + generatedHash = { } - if File.file?(fileA) - hashA = YAML.load_file(fileA) - else - hashA = { } + args.each do |value| + if File.file?(value) + generatedHash.deep_merge!(YAML.load_file(value)) + end end - if File.file?(fileB) - hashB = YAML.load_file(fileB) - else - hashB = { } - end - - return hashA.deep_merge(hashB) + return generatedHash end end diff --git a/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/to_bool.rb b/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/to_bool.rb index d53482a..793550a 100644 --- a/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/to_bool.rb +++ b/puphpet/puppet/modules/puphpet/lib/puppet/parser/functions/to_bool.rb @@ -14,6 +14,14 @@ def to_bool end end +class Float + def to_bool + return false if self == 0 + return false if self == 0.0 + return true + end +end + class TrueClass def to_i; 1; end def to_bool; self; end @@ -27,3 +35,7 @@ def to_bool; self; end class NilClass def to_bool; false; end end + +class Symbol + def to_bool; false; end +end diff --git a/puphpet/puppet/modules/puphpet/manifests/adminer.pp b/puphpet/puppet/modules/puphpet/manifests/adminer.pp index 0d23275..1bdf7ef 100644 --- a/puphpet/puppet/modules/puphpet/manifests/adminer.pp +++ b/puphpet/puppet/modules/puphpet/manifests/adminer.pp @@ -1,15 +1,13 @@ class puphpet::adminer( $location, - $owner = 'www-data', - $php_package = 'php' + $owner = 'www-data' ) { if ! defined(File[$location]) { file { $location: replace => no, ensure => directory, - mode => 775, - require => Package[$php_package] + mode => '0775', } } diff --git a/puphpet/puppet/modules/puphpet/manifests/apache/proxy_fcgi.pp b/puphpet/puppet/modules/puphpet/manifests/apache/proxy_fcgi.pp index 58d4eca..80f4048 100644 --- a/puphpet/puppet/modules/puphpet/manifests/apache/proxy_fcgi.pp +++ b/puphpet/puppet/modules/puphpet/manifests/apache/proxy_fcgi.pp @@ -22,10 +22,10 @@ if ! defined(Class['::apache::mod::proxy_http']) { class { '::apache::mod::proxy_http': } } - if ! defined(::Apache::Mod['proxy_fcgi']) { + if ! defined(Apache::Mod['proxy_fcgi']) { ::apache::mod{ 'proxy_fcgi': } } - if ! defined(::Apache::Mod['actions']) { + if ! defined(Apache::Mod['actions']) { ::apache::mod{ 'actions': } } diff --git a/puphpet/puppet/modules/puphpet/manifests/apache/repo.pp b/puphpet/puppet/modules/puphpet/manifests/apache/repo.pp index 184ce46..efbaec6 100644 --- a/puphpet/puppet/modules/puphpet/manifests/apache/repo.pp +++ b/puphpet/puppet/modules/puphpet/manifests/apache/repo.pp @@ -4,18 +4,8 @@ class{ 'puphpet::apache::repo::debian': } } - if $::operatingsystem == 'ubuntu' and $::lsbdistcodename == 'precise' { - if ! defined(Apt::Key['4F4EA0AAE5267A6C']){ - ::apt::key { '4F4EA0AAE5267A6C': - key_server => 'hkp://keyserver.ubuntu.com:80' - } - } - - if ! defined(Apt::Ppa['ppa:ondrej/apache2']){ - ::apt::ppa { 'ppa:ondrej/apache2': - require => Apt::Key['4F4EA0AAE5267A6C'] - } - } + if $::operatingsystem == 'ubuntu' { + class{ 'puphpet::apache::repo::ubuntu': } } if $::osfamily == 'redhat' { diff --git a/puphpet/puppet/modules/puphpet/manifests/apache/repo/centos.pp b/puphpet/puppet/modules/puphpet/manifests/apache/repo/centos.pp index 973c040..8541bb3 100644 --- a/puphpet/puppet/modules/puphpet/manifests/apache/repo/centos.pp +++ b/puphpet/puppet/modules/puphpet/manifests/apache/repo/centos.pp @@ -1,37 +1,5 @@ -class puphpet::apache::repo::centos ( - $url = 'http://repo.puphpet.com/centos/httpd24/httpd-2.4.10-RPM-full.x86_64.tgz' -){ +class puphpet::apache::repo::centos { - $save_to = '/.puphpet-stuff/httpd-2.4.tgz' - $extract_to = '/.puphpet-stuff/httpd-2.4' - - $cmd = "wget --quiet --tries=5 --connect-timeout=10 -O '${save_to}' ${url}" - - exec { "download ${url}": - creates => $save_to, - command => $cmd, - timeout => 3600, - path => '/usr/bin', - } -> - exec { "untar ${save_to}": - creates => $extract_to, - command => "mkdir -p ${extract_to} && \ - tar xzf '${save_to}' -C ${extract_to} --strip-components=1", - cwd => '/.puphpet-stuff', - path => '/bin', - } -> - exec { 'install httpd-2.4.10': - creates => '/etc/httpd', - command => 'yum -y localinstall * --skip-broken', - cwd => $extract_to, - path => '/usr/bin', - } - - exec { 'rm /etc/httpd/conf.d/systemd.load': - path => ['/usr/bin', '/usr/sbin', '/bin'], - onlyif => 'test -f /etc/httpd/conf.d/systemd.load', - require => Class['apache'], - notify => Service['httpd'], - } + include ::puphpet::server::centos_ius } diff --git a/puphpet/puppet/modules/puphpet/manifests/apache/repo/debian.pp b/puphpet/puppet/modules/puphpet/manifests/apache/repo/debian.pp index c7b5ca6..2176be5 100644 --- a/puphpet/puppet/modules/puphpet/manifests/apache/repo/debian.pp +++ b/puphpet/puppet/modules/puphpet/manifests/apache/repo/debian.pp @@ -7,9 +7,11 @@ release => 'wheezy-experimental', repos => 'main', required_packages => 'debian-keyring debian-archive-keyring', - key => '9EB5E8A3DF17D0B3', - key_server => 'hkp://keyserver.ubuntu.com:80', - include_src => true + key => { + 'id' => '9EB5E8A3DF17D0B3', + 'server' => 'hkp://keyserver.ubuntu.com:80', + }, + include => { 'src' => true } } } diff --git a/puphpet/puppet/modules/puphpet/manifests/apache/repo/ubuntu.pp b/puphpet/puppet/modules/puphpet/manifests/apache/repo/ubuntu.pp new file mode 100644 index 0000000..a129eb4 --- /dev/null +++ b/puphpet/puppet/modules/puphpet/manifests/apache/repo/ubuntu.pp @@ -0,0 +1,22 @@ +# This depends on puppetlabs/apt: https://github.com/puppetlabs/puppetlabs-apt +# Adds Apache > 2.4.10 repo for Ubuntu +class puphpet::apache::repo::ubuntu { + + if ! defined(Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C']){ + ::apt::key { '14AA40EC0831756756D7F66C4F4EA0AAE5267A6C': + server => 'hkp://keyserver.ubuntu.com:80' + } + } + + # This repo contains Apache 2.4.10+ for Precise + if $::lsbdistcodename == 'precise' and !defined(Apt::Ppa['ppa:ondrej/php5']) { + ::apt::ppa { 'ppa:ondrej/php5': + require => Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C'] + } + } elsif ! defined(Apt::Ppa['ppa:ondrej/apache2']){ + ::apt::ppa { 'ppa:ondrej/apache2': + require => Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C'] + } + } + +} diff --git a/puphpet/puppet/modules/puphpet/manifests/hhvm.pp b/puphpet/puppet/modules/puphpet/manifests/hhvm.pp index 9000586..051601e 100644 --- a/puphpet/puppet/modules/puphpet/manifests/hhvm.pp +++ b/puphpet/puppet/modules/puphpet/manifests/hhvm.pp @@ -30,10 +30,15 @@ fail('Sorry, HHVM currently only works with Ubuntu 12.04, 13.10 and 14.04.') } - apt::key { '5D50B6BA': key_server => 'hkp://keyserver.ubuntu.com:80' } + apt::key { 'A6729974D728D7BA84154F8E4F7B93595D50B6BA': + server => 'hkp://keyserver.ubuntu.com:80' + } if $lsbdistcodename in ['lucid', 'precise'] { - apt::ppa { 'ppa:mapnik/boost': require => Apt::Key['5D50B6BA'], options => '' } + apt::ppa { 'ppa:mapnik/boost': + require => Apt::Key['A6729974D728D7BA84154F8E4F7B93595D50B6BA'], + options => '' + } } } 'centos': { @@ -62,17 +67,14 @@ case $::osfamily { 'debian': { - apt::key { 'hhvm': - key => '16d09fb4', - key_source => 'http://dl.hhvm.com/conf/hhvm.gpg.key', - } - apt::source { 'hhvm': location => "http://dl.hhvm.com/${os}", repos => 'main', required_packages => 'debian-keyring debian-archive-keyring', - include_src => false, - require => Apt::Key['hhvm'] + key => { + 'id' => '16d09fb4', + 'source' => 'http://dl.hhvm.com/conf/hhvm.gpg.key', + }, } } } diff --git a/puphpet/puppet/modules/puphpet/manifests/mariadb.pp b/puphpet/puppet/modules/puphpet/manifests/mariadb.pp index 7d91bcd..837a37d 100644 --- a/puphpet/puppet/modules/puphpet/manifests/mariadb.pp +++ b/puphpet/puppet/modules/puphpet/manifests/mariadb.pp @@ -24,9 +24,11 @@ release => $release, repos => 'main', required_packages => 'debian-keyring debian-archive-keyring', - key => '1BB943DB', - key_server => 'hkp://keyserver.ubuntu.com:80', - include_src => true + key => { + 'id' => '199369E5404BD5FC7D2FE43BCBCB082A1BB943DB', + 'server' => 'hkp://keyserver.ubuntu.com:80', + }, + include => { 'src' => true } } apt::pin { 'mariadb': diff --git a/puphpet/puppet/modules/puphpet/manifests/mysql/repo.pp b/puphpet/puppet/modules/puphpet/manifests/mysql/repo.pp index 36d0110..c843a16 100644 --- a/puphpet/puppet/modules/puphpet/manifests/mysql/repo.pp +++ b/puphpet/puppet/modules/puphpet/manifests/mysql/repo.pp @@ -15,27 +15,29 @@ release => $::lsbdistcodename, repos => 'all', required_packages => 'debian-keyring debian-archive-keyring', - key => '89DF5277', - key_server => 'hkp://keyserver.ubuntu.com:80', - include_src => true + key => { + 'id' => '89DF5277', + 'server' => 'hkp://keyserver.ubuntu.com:80', + }, + include => { 'src' => true } } } } 'ubuntu': { - if ! defined(Apt::Key['E5267A6C']){ - apt::key { 'E5267A6C': - key_server => 'hkp://keyserver.ubuntu.com:80' + if ! defined(Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C']){ + apt::key { '14AA40EC0831756756D7F66C4F4EA0AAE5267A6C': + server => 'hkp://keyserver.ubuntu.com:80' } } if $::lsbdistcodename in ['lucid', 'precise'] { apt::ppa { 'ppa:ondrej/mysql-5.5': - require => Apt::Key['E5267A6C'], + require => Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C'], options => '' } } else { apt::ppa { 'ppa:ondrej/mysql-5.5': - require => Apt::Key['E5267A6C'] + require => Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C'] } } } @@ -56,27 +58,29 @@ release => $::lsbdistcodename, repos => 'all', required_packages => 'debian-keyring debian-archive-keyring', - key => '89DF5277', - key_server => 'hkp://keyserver.ubuntu.com:80', - include_src => true + key => { + 'id' => '89DF5277', + 'server' => 'hkp://keyserver.ubuntu.com:80', + }, + include => { 'src' => true } } } } 'ubuntu': { - if ! defined(Apt::Key['E5267A6C']){ - apt::key { 'E5267A6C': - key_server => 'hkp://keyserver.ubuntu.com:80' + if ! defined(Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C']){ + apt::key { '14AA40EC0831756756D7F66C4F4EA0AAE5267A6C': + server => 'hkp://keyserver.ubuntu.com:80' } } if $::lsbdistcodename in ['lucid', 'precise'] { apt::ppa { 'ppa:ondrej/mysql-5.6': - require => Apt::Key['E5267A6C'], + require => Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C'], options => '' } } else { apt::ppa { 'ppa:ondrej/mysql-5.6': - require => Apt::Key['E5267A6C'] + require => Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C'] } } } diff --git a/puphpet/puppet/modules/puphpet/manifests/nginx.pp b/puphpet/puppet/modules/puphpet/manifests/nginx.pp index 7a28797..dee1635 100644 --- a/puphpet/puppet/modules/puphpet/manifests/nginx.pp +++ b/puphpet/puppet/modules/puphpet/manifests/nginx.pp @@ -23,7 +23,7 @@ '/var/log/nginx/log/host.error.log' ]: ensure => present, - mode => 0777, + mode => '0777', replace => 'no', require => File['/var/log/nginx/log'] } diff --git a/puphpet/puppet/modules/puphpet/manifests/nginx/upstream.pp b/puphpet/puppet/modules/puphpet/manifests/nginx/upstream.pp index f0f7c9d..a4c2767 100644 --- a/puphpet/puppet/modules/puphpet/manifests/nginx/upstream.pp +++ b/puphpet/puppet/modules/puphpet/manifests/nginx/upstream.pp @@ -1,7 +1,6 @@ # This depends on jfryman/nginx: https://github.com/jfryman/puppet-nginx.git # Creates a new upstream proxy entry define puphpet::nginx::upstream ( - $name, $fail_timeout = '10s', $members = [] ) { @@ -9,6 +8,7 @@ notify{ "Adding nginx upstream for ${name} with ${count} members.": withpath => true } + nginx::resource::upstream { $name: upstream_fail_timeout => $fail_timeout, members => $members diff --git a/puphpet/puppet/modules/puphpet/manifests/nodejs.pp b/puphpet/puppet/modules/puphpet/manifests/nodejs.pp index 3e368de..3739c5c 100644 --- a/puphpet/puppet/modules/puphpet/manifests/nodejs.pp +++ b/puphpet/puppet/modules/puphpet/manifests/nodejs.pp @@ -5,7 +5,7 @@ file { '/.puphpet-stuff/node_install.sh': ensure => present, owner => root, - mode => 0755, + mode => '0755', content => template("${module_name}/nodejs/install.erb"), } -> exec { 'install-node': diff --git a/puphpet/puppet/modules/puphpet/manifests/params.pp b/puphpet/puppet/modules/puphpet/manifests/params.pp index 455b010..f707b14 100644 --- a/puphpet/puppet/modules/puphpet/manifests/params.pp +++ b/puphpet/puppet/modules/puphpet/manifests/params.pp @@ -19,11 +19,6 @@ 'Redhat' => 'hhvm' } - $xdebug_package = $::osfamily ? { - 'Debian' => 'php5-xdebug', - 'Redhat' => 'php-pecl-xdebug' - } - $xhprof_package = $::osfamily ? { 'Debian' => $::operatingsystem ? { 'ubuntu' => false, diff --git a/puphpet/puppet/modules/puphpet/manifests/php/composer.pp b/puphpet/puppet/modules/puphpet/manifests/php/composer.pp index c1191f6..becc9cd 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/composer.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/composer.pp @@ -15,7 +15,7 @@ ensure => directory, owner => 'www-data', group => 'www-data', - mode => 0775, + mode => '0775', require => [ Group['www-data'], Group['www-user'] @@ -31,11 +31,10 @@ class { '::composer': target_dir => '/usr/local/bin', composer_file => 'composer', - download_method => 'curl', + download_method => 'wget', logoutput => false, tmp_path => '/tmp', php_package => $php_package, - curl_package => 'curl', suhosin_enabled => false, } diff --git a/puphpet/puppet/modules/puphpet/manifests/php/drush.pp b/puphpet/puppet/modules/puphpet/manifests/php/drush.pp index cfb5561..9179e22 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/drush.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/drush.pp @@ -22,6 +22,7 @@ composer::exec { 'drush': cmd => 'install', cwd => $drush_location, + dev => false, require => Vcsrepo[$drush_location], } -> exec { 'first drush run': diff --git a/puphpet/puppet/modules/puphpet/manifests/php/fpm/ini.pp b/puphpet/puppet/modules/puphpet/manifests/php/fpm/ini.pp index 1e487d8..cf74f6b 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/fpm/ini.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/fpm/ini.pp @@ -45,13 +45,21 @@ $pool_name = 'global' - case $fpm_version { - '7.0', '70', '7': { - $dir_name = 'php7' - } - default: { - $dir_name = 'php5' + if $fpm_version in ['7.0', '70', '7'] { + case $::operatingsystem { + # Debian and Ubuntu slightly differ + 'debian': { + $dir_name = 'php7' + } + 'ubuntu': { + $dir_name = 'php/7.0' + } + 'redhat', 'centos': { + $dir_name = 'php' + } } + } else { + $dir_name = 'php5' } case $::osfamily { @@ -65,9 +73,16 @@ $conf_filename = "${pool_dir}/php-fpm.conf" - $changes = $ensure ? { - present => [ "set '${pool_name}/${entry}' '${value}'" ], - absent => [ "rm '${pool_name}/${entry}'" ], + if '=' in $value { + $changes = $ensure ? { + present => [ "set '${pool_name}/${entry}' \"'${value}'\"" ], + absent => [ "rm \"'${pool_name}/${entry}'\"" ], + } + } else { + $changes = $ensure ? { + present => [ "set '${pool_name}/${entry}' '${value}'" ], + absent => [ "rm \"'${pool_name}/${entry}'\"" ], + } } augeas { "${pool_name}/${entry}: ${value}": diff --git a/puphpet/puppet/modules/puphpet/manifests/php/fpm/pool_ini.pp b/puphpet/puppet/modules/puphpet/manifests/php/fpm/pool_ini.pp index 0818582..5ae73c7 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/fpm/pool_ini.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/fpm/pool_ini.pp @@ -38,13 +38,21 @@ $php_fpm_service ) { - case $fpm_version { - '7.0', '70', '7': { - $dir_name = 'php7' - } - default: { - $dir_name = 'php5' + if $fpm_version in ['7.0', '70', '7'] { + case $::operatingsystem { + # Debian and Ubuntu slightly differ + 'debian': { + $dir_name = 'php7' + } + 'ubuntu': { + $dir_name = 'php/7.0' + } + 'redhat', 'centos': { + $dir_name = 'php' + } } + } else { + $dir_name = 'php5' } case $::osfamily { @@ -58,9 +66,16 @@ $conf_filename = delete("${pool_dir}/${pool_name}.conf", ' ') - $changes = $ensure ? { - present => [ "set '${pool_name}/${entry}' '${value}'" ], - absent => [ "rm '${pool_name}/${entry}'" ], + if '=' in $value { + $changes = $ensure ? { + present => [ "set '${pool_name}/${entry}' \"'${value}'\"" ], + absent => [ "rm \"'${pool_name}/${entry}'\"" ], + } + } else { + $changes = $ensure ? { + present => [ "set '${pool_name}/${entry}' '${value}'" ], + absent => [ "rm \"'${pool_name}/${entry}'\"" ], + } } if ! defined(File[$conf_filename]) { diff --git a/puphpet/puppet/modules/puphpet/manifests/php/ini.pp b/puphpet/puppet/modules/puphpet/manifests/php/ini.pp index 2f0ddb0..5297435 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/ini.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/ini.pp @@ -5,6 +5,10 @@ # # I have listed a bunch of places: # +# 5.3 +# CENTOS 6 +# CLI /etc/php.d +# FPM /etc/php.d # 5.4 # CENTOS 6 # CLI /etc/php.d @@ -26,8 +30,8 @@ # CENTOS 6 # N/A # UBUNTU 14.04 TRUSTY -# CLI /etc/php7/cli/conf.d -> /etc/php7/mods-available/* -# FPM /etc/php7/fpm/conf.d -> /etc/php7/mods-available/* +# CLI /etc/php7/cli/conf.d/* -> /etc/php7/mods-available/* +# FPM /etc/php7/fpm/conf.d/* -> /etc/php7/mods-available/* # define puphpet::php::ini ( $php_version, @@ -39,21 +43,39 @@ ) { $real_webserver = $webserver ? { - 'apache' => 'fpm', - 'httpd' => 'fpm', - 'apache2' => 'fpm', - 'nginx' => 'fpm', - 'php5-fpm' => 'fpm', - 'php7-fpm' => 'php7-fpm', - 'php-fpm' => 'fpm', - 'fpm' => 'fpm', - 'cgi' => 'cgi', - 'fcgi' => 'cgi', - 'fcgid' => 'cgi', - undef => undef, + 'apache' => 'fpm', + 'httpd' => 'fpm', + 'apache2' => 'fpm', + 'nginx' => 'fpm', + 'php53u-fpm' => 'php53u-fpm', + 'php5-fpm' => 'fpm', + 'php7-fpm' => 'php7-fpm', + 'php7.0-fpm' => 'fpm', + 'php-fpm' => 'fpm', + 'fpm' => 'fpm', + 'cgi' => 'cgi', + 'fcgi' => 'cgi', + 'fcgid' => 'cgi', + undef => undef, } case $php_version { + '5.3', '53': { + case $::osfamily { + 'redhat': { + $target_dir = '/etc/php.d' + $target_file = "${target_dir}/${ini_filename}" + + if ! defined(File[$target_file]) { + file { $target_file: + replace => no, + ensure => present, + } + } + } + default: { fail('This OS has not yet been defined for PHP 5.3!') } + } + } '5.4', '54': { case $::osfamily { 'debian': { @@ -155,27 +177,50 @@ '7.0', '70': { case $::osfamily { 'debian': { - $target_dir = '/etc/php7/mods-available' + $target_dir = '/etc/php/mods-available' $target_file = "${target_dir}/${ini_filename}" + $webserver_ini_location = $real_webserver ? { + 'cgi' => '/etc/php/7.0/cgi/conf.d', + 'fpm' => '/etc/php/7.0/fpm/conf.d', + undef => undef, + } + $cli_ini_location = '/etc/php/7.0/cli/conf.d' + if ! defined(File[$target_file]) { file { $target_file: replace => no, ensure => present, - require => File[$target_dir], } } - $symlink = "/etc/php7/mods-available/${ini_filename}" + if $webserver_ini_location != undef and ! defined(File["${webserver_ini_location}/${ini_filename}"]) { + file { "${webserver_ini_location}/${ini_filename}": + ensure => link, + target => $target_file, + require => File[$target_file], + } + } - if ! defined(File[$symlink]) { - file { $symlink: + if ! defined(File["${cli_ini_location}/${ini_filename}"]) { + file { "${cli_ini_location}/${ini_filename}": ensure => link, target => $target_file, require => File[$target_file], } } } + 'redhat': { + $target_dir = '/etc/php.d' + $target_file = "${target_dir}/${ini_filename}" + + if ! defined(File[$target_file]) { + file { $target_file: + replace => no, + ensure => present, + } + } + } default: { fail('This OS has not yet been defined for PHP 7.0!') } } } @@ -188,9 +233,16 @@ $notify_service = [] } - $changes = $ensure ? { - present => [ "set '${entry}' '${value}'" ], - absent => [ "rm '${entry}'" ], + if '=' in $value { + $changes = $ensure ? { + present => [ "set '${entry}' \"'${value}'\"" ], + absent => [ "rm \"'${entry}'\"" ], + } + } else { + $changes = $ensure ? { + present => [ "set '${entry}' '${value}'" ], + absent => [ "rm '${entry}'" ], + } } augeas { "${entry}: ${value}": diff --git a/puphpet/puppet/modules/puphpet/manifests/php/module.pp b/puphpet/puppet/modules/puphpet/manifests/php/module.pp index 0dbad35..fadab5e 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/module.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/module.pp @@ -8,7 +8,14 @@ $package = $::osfamily ? { 'Debian' => { - 'mbstring' => false, # Comes packaged with PHP, not available in repos + 'mbstring' => false, # Comes packaged with PHP, not available in repos + 'memcached' => $::operatingsystem ? { + 'ubuntu' => $puphpet::php::settings::version ? { + '70' => 'php-memcached', + default => 'php5-memcached', + }, + default => 'php5-memcached', + }, }, 'Redhat' => { # @@ -18,17 +25,20 @@ $downcase_name = downcase($name) if has_key($package, $downcase_name) { - $package_name = $package[$downcase_name] + $package_name = $package[$downcase_name] + $module_prefix = false } else { - $package_name = $name + $package_name = $name + $module_prefix = $puphpet::php::settings::prefix } - if $package_name and ! defined(::Php::Module[$package_name]) + if $package_name and ! defined(Php::Module[$package_name]) and $puphpet::php::settings::enable_modules { ::php::module { $package_name: service_autorestart => $service_autorestart, + module_prefix => $module_prefix, } } diff --git a/puphpet/puppet/modules/puphpet/manifests/php/pear.pp b/puphpet/puppet/modules/puphpet/manifests/php/pear.pp index 38ce09a..5bfa999 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/pear.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/pear.pp @@ -38,7 +38,7 @@ } if $package_name and $preferred_state - and ! defined(::Php::Pear::Module[$package_name]) + and ! defined(Php::Pear::Module[$package_name]) and $puphpet::php::settings::enable_pear { ::php::pear::module { $name: diff --git a/puphpet/puppet/modules/puphpet/manifests/php/pecl.pp b/puphpet/puppet/modules/puphpet/manifests/php/pecl.pp index 45bffe0..21508be 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/pecl.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/pecl.pp @@ -6,7 +6,8 @@ */ define puphpet::php::pecl ( - $service_autorestart + $service_autorestart, + $prefix = $puphpet::php::settings::pecl_prefix ){ $ignore = { @@ -16,13 +17,10 @@ $pecl = $::osfamily ? { 'Debian' => { - 'mongo' => $::lsbdistcodename ? { - 'precise' => 'mongo', - default => false, - }, + 'mongo' => 'mongodb', }, 'Redhat' => { - # + 'mongo' => 'mongodb', } } @@ -44,36 +42,40 @@ $package = $::osfamily ? { 'Debian' => { 'apc' => $::operatingsystem ? { - 'debian' => 'php5-apc', - 'ubuntu' => 'php5-apcu', + 'debian' => "${prefix}apc", + 'ubuntu' => "${prefix}apcu", }, - 'apcu' => 'php5-apcu', - 'imagick' => 'php5-imagick', - 'memcache' => 'php5-memcache', - 'memcached' => 'php5-memcached', - 'mongo' => $::lsbdistcodename ? { - 'precise' => false, - default => 'php5-mongo', + 'apcu' => "${prefix}apcu", + 'imagick' => "${prefix}imagick", + 'memcache' => "${prefix}memcache", + 'memcached' => "${prefix}memcached", + 'redis' => $puphpet::php::settings::version ? { + '54' => false, + '5.4' => false, + default => "${prefix}redis", }, - 'redis' => 'php5-redis', - 'sqlite' => 'php5-sqlite', - 'zendopcache' => 'php5-zendopcache', + 'sqlite' => "${prefix}sqlite", + 'zendopcache' => "${prefix}zendopcache", }, 'Redhat' => { - 'apc' => 'php-pecl-apcu', - 'apcu' => 'php-pecl-apcu', - 'imagick' => 'php-pecl-imagick', - 'memcache' => 'php-pecl-memcache', - 'memcached' => 'php-pecl-memcached', - 'mongo' => 'php-pecl-mongo', - 'redis' => 'php-pecl-redis', - 'sqlite' => 'php-pecl-sqlite', - 'zendopcache' => 'php-pecl-zendopcache', + 'amqp' => "${prefix}amqp", + 'apc' => $puphpet::php::settings::version ? { + '53' => "${prefix}apc", + '5.3' => "${prefix}apc", + default => "${prefix}apcu", + }, + 'apcu' => "${prefix}apcu", + 'imagick' => "${prefix}imagick", + 'memcache' => "${prefix}memcache", + 'memcached' => "${prefix}memcached", + 'redis' => "${prefix}redis", + 'sqlite' => "${prefix}sqlite", + 'zendopcache' => "${prefix}zendopcache", } } $auto_answer_hash = { - 'mongo' => 'no\n' + # } $downcase_name = downcase($name) @@ -108,7 +110,7 @@ $package_name = false } - if $pecl_name and ! defined(::Php::Pecl::Module[$pecl_name]) + if $pecl_name and ! defined(Php::Pecl::Module[$pecl_name]) and $puphpet::php::settings::enable_pecl { ::php::pecl::module { $pecl_name: @@ -117,6 +119,16 @@ auto_answer => $auto_answer, service_autorestart => $service_autorestart, } + + if ! defined(Puphpet::Php::Ini[$pecl_name]) { + puphpet::php::ini { $pecl_name: + entry => 'MODULE/extension', + value => "${pecl_name}.so", + php_version => $puphpet::php::settings::version, + webserver => $puphpet::php::settings::service, + ini_filename => "${pecl_name}.ini", + } + } } elsif $package_name and ! defined(Package[$package_name]) and $puphpet::php::settings::enable_pecl diff --git a/puphpet/puppet/modules/puphpet/manifests/php/repos.pp b/puphpet/puppet/modules/puphpet/manifests/php/repos.pp index 6a3a88d..79fc512 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/repos.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/repos.pp @@ -15,9 +15,11 @@ release => 'squeeze-php54', repos => 'all', required_packages => 'debian-keyring debian-archive-keyring', - key => '89DF5277', - key_server => 'keys.gnupg.net', - include_src => true + key => { + 'id' => '89DF5277', + 'server' => 'hkp://keyserver.ubuntu.com:80', + }, + include => { 'src' => true } } } # Wheezy : 5.4 (default) && 5.5 && 5.6 @@ -27,9 +29,11 @@ release => 'wheezy-php55', repos => 'all', required_packages => 'debian-keyring debian-archive-keyring', - key => '89DF5277', - key_server => 'keys.gnupg.net', - include_src => true + key => { + 'id' => '89DF5277', + 'server' => 'hkp://keyserver.ubuntu.com:80', + }, + include => { 'src' => true } } } elsif $::lsbdistcodename == 'wheezy' and $php_version == '56' { @@ -38,16 +42,18 @@ release => 'wheezy-php56', repos => 'all', required_packages => 'debian-keyring debian-archive-keyring', - key => '89DF5277', - key_server => 'keys.gnupg.net', - include_src => true + key => { + 'id' => '89DF5277', + 'server' => 'hkp://keyserver.ubuntu.com:80', + }, + include => { 'src' => true } } } } 'ubuntu': { - if ! defined(::Apt::Key['4F4EA0AAE5267A6C']) { - ::apt::key { '4F4EA0AAE5267A6C': - key_server => 'hkp://keyserver.ubuntu.com:80' + if ! defined(Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C']) { + ::apt::key { '14AA40EC0831756756D7F66C4F4EA0AAE5267A6C': + server => 'hkp://keyserver.ubuntu.com:80' } } @@ -62,7 +68,7 @@ } ::apt::ppa { 'ppa:ondrej/php5-oldstable': - require => ::Apt::Key['4F4EA0AAE5267A6C'], + require => ::Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C'], options => $options } } @@ -71,7 +77,7 @@ and $php_version == '55' { ::apt::ppa { 'ppa:ondrej/php5': - require => ::Apt::Key['4F4EA0AAE5267A6C'] + require => ::Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C'] } } elsif $::lsbdistcodename in ['lucid'] and $php_version == '55' { @@ -80,12 +86,40 @@ # Ubuntu 14.04 can do PHP 5.6 elsif $::lsbdistcodename == 'trusty' and $php_version == '56' { ::apt::ppa { 'ppa:ondrej/php5-5.6': - require => ::Apt::Key['4F4EA0AAE5267A6C'] + require => ::Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C'] + } + } + # Ubuntu 14.04 can do PHP 7 + elsif $::lsbdistcodename == 'trusty' and $php_version == '70' { + ::apt::ppa { 'ppa:ondrej/php-7.0': + require => ::Apt::Key['14AA40EC0831756756D7F66C4F4EA0AAE5267A6C'] } } } 'redhat', 'centos': { - include ::yum::repo::remi + if $php_version == '53' { + $ius_gpg_key_url = 'https://dl.iuscommunity.org/pub/ius/IUS-COMMUNITY-GPG-KEY' + $ius_gpg_key_dl = '/etc/pki/rpm-gpg/IUS-COMMUNITY-GPG-KEY' + + exec { 'ius gpg key': + command => "wget --quiet --tries=5 --connect-timeout=10 -O '${ius_gpg_key_dl}' ${ius_gpg_key_url}", + creates => $ius_gpg_key_dl, + path => '/usr/bin:/bin', + } + + ::yum::managed_yumrepo { 'ius6-archive': + descr => 'IUS Community Project Archive', + mirrorlist => 'http://dmirr.iuscommunity.org/mirrorlist/?repo=ius-el6-archive&arch=$basearch', + enabled => 1, + gpgcheck => 1, + gpgkey => "file://${ius_gpg_key_dl}", + priority => 1, + } + } + + if $php_version != '53' { + include ::yum::repo::remi + } # remi_php55 requires the remi repo as well if $php_version == '55' { @@ -103,6 +137,18 @@ priority => 1, } } + # remi_php70 requires the remi repo as well + elsif $php_version == '70' { + ::yum::managed_yumrepo { 'remi-php70': + descr => 'Les RPM de remi pour Enterpise Linux $releasever - $basearch - PHP 7.0', + mirrorlist => 'http://rpms.famillecollet.com/enterprise/$releasever/php70/mirror', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-remi', + priority => 1, + } + } } } diff --git a/puphpet/puppet/modules/puphpet/manifests/php/settings.pp b/puphpet/puppet/modules/puphpet/manifests/php/settings.pp index e2a3cc1..9fc0f92 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/settings.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/settings.pp @@ -3,29 +3,49 @@ ){ if $version_string == '7.0' or $version_string == '70' { - $version = '7.0' + $version = '70' } else { $version = $version_string } - if $version == '7.0' or $version == '70' { - $enable_modules = false - $enable_pear = false - $enable_pecl = false - $enable_xdebug = false + $enable_modules = true + $enable_pear = true + $enable_pecl = true + $enable_xdebug = true + if $version == '70' { $prefix = $::osfamily ? { - 'debian' => 'php7-', - 'redhat' => 'php-', + 'debian' => $::operatingsystem ? { + 'ubuntu' => 'php7.0-', + 'debian' => 'php7-' + }, + 'redhat' => 'php-' + } + + $pecl_prefix = $::osfamily ? { + 'debian' => $::operatingsystem ? { + 'ubuntu' => 'php-', + 'debian' => 'php7-' + }, + 'redhat' => 'php70-php-pecl-' + } + + $cli_package = "${prefix}cli" + $fpm_package = "${prefix}fpm" + $service = "${prefix}fpm" + + $package_devel = $::osfamily ? { + 'debian' => 'php7.0-dev', + 'redhat' => 'php-devel', } $base_ini = $::osfamily ? { - 'debian' => '/etc/php7/php.ini', + 'debian' => '/etc/php/7.0/php.ini', 'redhat' => '/etc/php.ini', } $fpm_ini = $::osfamily ? { - 'debian' => '/etc/php7/fpm/php.ini', + 'debian' => '/etc/php/7.0/fpm/php.ini', 'redhat' => '/etc/php.ini', } @@ -33,17 +53,51 @@ 'debian' => '/run/php-fpm.pid', 'redhat' => '/var/run/php-fpm.pid', } - } else { - $enable_modules = true - $enable_pear = true - $enable_pecl = true - $enable_xdebug = true + } elsif $version in ['53', '5.3'] { + $prefix = $::osfamily ? { + 'redhat' => 'php53u-', + } + + $pecl_prefix = $::osfamily ? { + 'redhat' => 'php53u-pecl-', + } + + $cli_package = "${prefix}cli" + $fpm_package = "${prefix}fpm" + $service = 'php-fpm' + + $package_devel = $::osfamily ? { + 'redhat' => 'php53u-devel', + } + + $base_ini = $::osfamily ? { + 'redhat' => '/etc/php.ini', + } + + $fpm_ini = $::osfamily ? { + 'redhat' => '/etc/php.ini', + } + $pid_file = $::osfamily ? { + 'redhat' => '/var/run/php-fpm/php-fpm.pid', + } + } else { $prefix = $::osfamily ? { 'debian' => 'php5-', 'redhat' => 'php-', } + $pecl_prefix = $::osfamily ? { + 'debian' => 'php5-', + 'redhat' => 'php-pecl-', + } + + $cli_package = "${prefix}cli" + $fpm_package = "${prefix}fpm" + $service = "${prefix}fpm" + + $package_devel = $php::params::package_devel + $base_ini = $::osfamily ? { 'debian' => '/etc/php5/php.ini', 'redhat' => '/etc/php.ini', @@ -60,10 +114,6 @@ } } - $cli_package = "${prefix}cli" - $fpm_package = "${prefix}fpm" - $service = "${prefix}fpm" - Package[$fpm_package] -> Puphpet::Php::Module <| |> diff --git a/puphpet/puppet/modules/puphpet/manifests/php/wordpress/wpcli.pp b/puphpet/puppet/modules/puphpet/manifests/php/wordpress/wpcli.pp index 40ba54d..9d3eadb 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/wordpress/wpcli.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/wordpress/wpcli.pp @@ -22,6 +22,7 @@ composer::exec { 'wp-cli': cmd => 'install', cwd => $location, + dev => false, require => Vcsrepo[$location], } -> file { "${location}/bin/wp": diff --git a/puphpet/puppet/modules/puphpet/manifests/php/xdebug.pp b/puphpet/puppet/modules/puphpet/manifests/php/xdebug.pp index 8e8c92f..5688e78 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/xdebug.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/xdebug.pp @@ -2,7 +2,8 @@ $install_cli = true, $webserver, $compile = false, - $ensure = present + $ensure = present, + $php_package = $puphpet::php::settings::fpm_package ) inherits puphpet::params { if $webserver != undef { @@ -11,50 +12,44 @@ $notify_service = [] } - if !$compile and ! defined(Package[$puphpet::params::xdebug_package]) + $xdebug_package = $::osfamily ? { + 'Debian' => "${puphpet::php::settings::prefix}xdebug", + 'Redhat' => "${puphpet::php::settings::pecl_prefix}xdebug" + } + + if !$compile and ! defined(Package[$xdebug_package]) and $puphpet::php::settings::enable_xdebug { package { 'xdebug': - name => $puphpet::params::xdebug_package, + name => $xdebug_package, ensure => installed, - require => Package['php'], + require => Package[$php_package], notify => $notify_service, } } elsif $puphpet::php::settings::enable_xdebug { # php 5.6 requires xdebug be compiled, for now - case $::operatingsystem { - # Debian and Ubuntu slightly differ - 'debian', 'ubuntu': { - if is_dir('/usr/lib/php5/20131226-zts') { - $mod_dir = '/usr/lib/php5/20131226-zts' - } else { - $mod_dir = '/usr/lib/php5/20131226' - } - } - 'redhat', 'centos': {$mod_dir = '/usr/lib64/php/modules'} - } - vcsrepo { '/.puphpet-stuff/xdebug': ensure => present, provider => git, source => 'https://github.com/xdebug/xdebug.git', - revision => 'XDEBUG_2_3_1', require => Class['Php::Devel'] } -> exec { 'phpize && ./configure --enable-xdebug && make': creates => '/.puphpet-stuff/xdebug/configure', cwd => '/.puphpet-stuff/xdebug', } - -> exec { "cp /.puphpet-stuff/xdebug/modules/xdebug.so ${mod_dir}/xdebug.so": - creates => "${mod_dir}/xdebug.so", + -> exec { 'copy xdebug.so to modules dir': + command => "cp /.puphpet-stuff/xdebug/modules/xdebug.so `php-config --extension-dir`/xdebug.so \ + && touch /.puphpet-stuff/xdebug-installed", + creates => '/.puphpet-stuff/xdebug-installed', } puphpet::php::ini { 'xdebug/zend_extension': entry => "XDEBUG/zend_extension", - value => "${mod_dir}/xdebug.so", - php_version => '5.6', + value => 'xdebug.so', + php_version => $puphpet::php::settings::version, webserver => $webserver, - require => Exec["cp /.puphpet-stuff/xdebug/modules/xdebug.so ${mod_dir}/xdebug.so"], + require => Exec['copy xdebug.so to modules dir'], } } @@ -66,7 +61,7 @@ ensure => present, mode => '+X', source => 'puppet:///modules/puphpet/xdebug_cli_alias.erb', - require => Package['php'] + require => Package[$php_package] } } diff --git a/puphpet/puppet/modules/puphpet/manifests/php/xhprof.pp b/puphpet/puppet/modules/puphpet/manifests/php/xhprof.pp index 56b68f8..3f2a571 100644 --- a/puphpet/puppet/modules/puphpet/manifests/php/xhprof.pp +++ b/puphpet/puppet/modules/puphpet/manifests/php/xhprof.pp @@ -15,7 +15,7 @@ } -> file { "${webroot_location}/xhprof/xhprof_html": ensure => directory, - mode => 0775, + mode => '0775', } -> exec { 'configure xhprof': cwd => "${webroot_location}/xhprof/extension", diff --git a/puphpet/puppet/modules/puphpet/manifests/phpmyadmin.pp b/puphpet/puppet/modules/puphpet/manifests/phpmyadmin.pp index e227aaa..ba0d580 100644 --- a/puphpet/puppet/modules/puphpet/manifests/phpmyadmin.pp +++ b/puphpet/puppet/modules/puphpet/manifests/phpmyadmin.pp @@ -8,8 +8,12 @@ if $::osfamily == 'debian' { if $::operatingsystem == 'ubuntu' { - apt::key { '80E7349A06ED541C': key_server => 'hkp://keyserver.ubuntu.com:80' } - apt::ppa { 'ppa:nijel/phpmyadmin': require => Apt::Key['80E7349A06ED541C'] } + apt::key { 'AD829E29A018BAF8C3842FB080E7349A06ED541C': + server => 'hkp://keyserver.ubuntu.com:80' + } + apt::ppa { 'ppa:nijel/phpmyadmin': + require => Apt::Key['AD829E29A018BAF8C3842FB080E7349A06ED541C'] + } } $phpMyAdmin_package = 'phpmyadmin' diff --git a/puphpet/puppet/modules/puphpet/manifests/server/centos_ius.pp b/puphpet/puppet/modules/puphpet/manifests/server/centos_ius.pp new file mode 100644 index 0000000..0d4e2ea --- /dev/null +++ b/puphpet/puppet/modules/puphpet/manifests/server/centos_ius.pp @@ -0,0 +1,23 @@ +class puphpet::server::centos_ius { + + $url = 'https://setup.ius.io/' + $path = '/.puphpet-stuff/ius.sh' + $cmd = "wget --quiet --tries=5 --connect-timeout=10 -O '${path}' ${url}" + + exec { "download ${url}": + creates => $path, + command => $cmd, + timeout => 3600, + path => '/bin:/sbin:/usr/bin:/usr/sbin', + } -> + file { $path: + ensure => present, + mode => '+x', + } -> + exec { "${path} && touch /.puphpet-stuff/ius.sh-ran": + creates => '/.puphpet-stuff/ius.sh-ran', + timeout => 3600, + path => '/bin:/sbin:/usr/bin:/usr/sbin', + } + +} diff --git a/puphpet/puppet/modules/puphpet/manifests/sqlite/db.pp b/puphpet/puppet/modules/puphpet/manifests/sqlite/db.pp index cf4d0ac..8a8126a 100644 --- a/puphpet/puppet/modules/puphpet/manifests/sqlite/db.pp +++ b/puphpet/puppet/modules/puphpet/manifests/sqlite/db.pp @@ -1,13 +1,12 @@ # Creates database, adds user # If requested, imports DB define puphpet::sqlite::db ( - $name, $owner, $group = 0, $sql_file = false ) { - if $name == '' or $owner == '' { + if $db_name == '' or $owner == '' { fail('SQLite requires that name and owner be set.') } @@ -16,7 +15,7 @@ default => 0 } - $location = "/var/lib/sqlite/${name}.db" + $location = "/var/lib/sqlite/${db_name}.db" file { $location: ensure => present, @@ -24,19 +23,19 @@ group => $group_real, mode => '0775', require => File['/var/lib/sqlite'], - notify => Exec["create_${name}_db"], + notify => Exec["create_${db_name}_db"], } - exec { "create_${name}_db": + exec { "create_${db_name}_db": command => "sqlite3 ${location}", path => '/usr/bin:/usr/local/bin', refreshonly => true, } if $sql_file { - $sqlite_db = "sqlite3 /var/lib/sqlite/${name}.db" + $sqlite_db = "sqlite3 /var/lib/sqlite/${db_name}.db" - exec{ "${name}-import": + exec{ "${db_name}-import": command => "cat ${sql_file} | sudo ${sqlite_db}", logoutput => true, refreshonly => true, diff --git a/puphpet/puppet/modules/puphpet/manifests/supervisord.pp b/puphpet/puppet/modules/puphpet/manifests/supervisord.pp index 92572bc..a1d0853 100644 --- a/puphpet/puppet/modules/puphpet/manifests/supervisord.pp +++ b/puphpet/puppet/modules/puphpet/manifests/supervisord.pp @@ -3,9 +3,21 @@ class puphpet::supervisord { - if ! defined(Class['::supervisord']) { - class{ 'puphpet::python::pip': } + include ::puphpet::python::pip + + if ! defined(Package['git']) { + package { 'git': + ensure => present, + } + } + if ! defined(Class['supervisord::pip']) { + class { '::supervisord::pip': + require => Package['git'] + } + } + + if ! defined(Class['::supervisord']) { class { '::supervisord': install_pip => false, require => [ diff --git a/puphpet/puppet/modules/puphpet/templates/apache/files_match.erb b/puphpet/puppet/modules/puphpet/templates/apache/files_match.erb index ee3cfd0..e62699c 100644 --- a/puphpet/puppet/modules/puphpet/templates/apache/files_match.erb +++ b/puphpet/puppet/modules/puphpet/templates/apache/files_match.erb @@ -1,3 +1,36 @@ +<% +class Puppet::Parser::Scope + def setvar(name, value, options = {}) + if name =~ /^[0-9]+$/ + raise Puppet::ParseError.new("Cannot assign to a numeric match result variable '$#{name}'") # unless options[:ephemeral] + end + unless name.is_a? String + raise Puppet::ParseError, "Scope variable name #{name.inspect} is a #{name.class}, not a string" + end + + # Check for reserved variable names + if !options[:privileged] && RESERVED_VARIABLE_NAMES.include?(name) + raise Puppet::ParseError, "Attempt to assign to a reserved variable name: '#{name}'" + end + + # Check for server_facts reserved variable name if the trusted_sever_facts setting is true + if Puppet[:trusted_server_facts] && name == 'server_facts' && !options[:privileged] + raise Puppet::ParseError, "Attempt to assign to a reserved variable name: '#{name}'" + end + + table = effective_symtable(options[:ephemeral]) + + if options[:append] + # produced result (value) is the resulting appended value, note: the table[]= does not return the value + table[name] = (value = append_value(undef_as('', self[name]), value)) + else + table[name] = value + end + value + end +end +-%> + <% if @directories_hash and ! @directories_hash.empty? -%> <% @directories_hash.each do |key, values| -%> <% if @directories_hash[key]['custom_fragment'].split.join.length > 0 -%> @@ -20,11 +53,10 @@ <% filesMatchArr.push(filesmatch) -%> <% end -%> <% table = scope.effective_symtable(true) -%> - <% table.delete('_directories') -%> <% scope['_directories'] = filesMatchArr -%> <% result = scope.function_template(['apache/vhost/_directories.erb']) -%> <% result = result.gsub("\n ## Directories, there should at least be a declaration for \n", "") -%> - <% @directories_hash[key]['custom_fragment'] << result.gsub("\n ", "\n ") -%> + <% @directories_hash[key]['custom_fragment'] += result.gsub("\n ", "\n ") -%> <% end -%> <% end -%> <% end -%> diff --git a/puphpet/puppet/modules/puphpet/templates/nodejs/install.erb b/puphpet/puppet/modules/puphpet/templates/nodejs/install.erb index e6bc31d..463f7fa 100644 --- a/puphpet/puppet/modules/puphpet/templates/nodejs/install.erb +++ b/puphpet/puppet/modules/puphpet/templates/nodejs/install.erb @@ -8,7 +8,7 @@ else FILENAME='linux-x64.tar.gz' fi -LATEST_NODE=$(curl 'http://nodejs.org/dist/latest/SHASUMS.txt' | grep "${FILENAME}" | awk '{ print $2 }') +LATEST_NODE=$(curl 'http://nodejs.org/dist/latest/SHASUMS256.txt' | grep "${FILENAME}" | awk '{ print $2 }') wget --quiet --tries=5 --connect-timeout=10 --no-check-certificate -O '/.puphpet-stuff/nodestable.tar.gz' "http://nodejs.org/dist/latest/${LATEST_NODE}" cd '/usr/local/' diff --git a/puphpet/puppet/modules/puppi/.gemfile b/puphpet/puppet/modules/puppi/.gemfile deleted file mode 100644 index 9309493..0000000 --- a/puphpet/puppet/modules/puppi/.gemfile +++ /dev/null @@ -1,7 +0,0 @@ -source 'https://rubygems.org' - -puppetversion = ENV['PUPPET_VERSION'] -gem 'puppet', puppetversion, :require => false -gem 'puppet-lint' -gem 'puppetlabs_spec_helper', '>= 0.1.0' -gem 'puppet-blacksmith', '>= 2.0.0' diff --git a/puphpet/puppet/modules/puppi/.gitignore b/puphpet/puppet/modules/puppi/.gitignore new file mode 100644 index 0000000..27a6f2f --- /dev/null +++ b/puphpet/puppet/modules/puppi/.gitignore @@ -0,0 +1,12 @@ +/.gradle +/metadata.json +/.rvmrc +build +pkg/ +Session.vim +spec/fixtures +.*.sw[a-z] +*.un~ +vendor +.bundle +Gemfile.lock diff --git a/puphpet/puppet/modules/puppi/.travis.yml b/puphpet/puppet/modules/puppi/.travis.yml index dffeca9..20afdf1 100644 --- a/puphpet/puppet/modules/puppi/.travis.yml +++ b/puphpet/puppet/modules/puppi/.travis.yml @@ -1,21 +1,26 @@ +--- language: ruby -rvm: - - 1.8.7 - - 1.9.3 script: - - "rake spec SPEC_OPTS='--format documentation'" -env: - - PUPPET_VERSION="~> 2.6.0" - - PUPPET_VERSION="~> 2.7.0" - - PUPPET_VERSION="~> 3.0.0" - - PUPPET_VERSION="~> 3.1.0" + - "bundle exec rake lint spec SPEC_OPTS='--format documentation'" +sudo: false matrix: - exclude: - - rvm: 1.9.3 - env: PUPPET_VERSION="~> 2.6.0" - gemfile: .gemfile + 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" -gemfile: .gemfile notifications: email: - al@lab42.it diff --git a/puphpet/puppet/modules/puppi/Gemfile b/puphpet/puppet/modules/puppi/Gemfile new file mode 100644 index 0000000..d65f008 --- /dev/null +++ b/puphpet/puppet/modules/puppi/Gemfile @@ -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 diff --git a/puphpet/puppet/modules/puppi/Modulefile b/puphpet/puppet/modules/puppi/Modulefile index d69331f..d90f1ac 100644 --- a/puphpet/puppet/modules/puppi/Modulefile +++ b/puphpet/puppet/modules/puppi/Modulefile @@ -1,9 +1,9 @@ name 'example42-puppi' -version '2.1.8' +version '2.1.12' author 'lab42' license 'Apache' -project_page 'http://www.example42.com' +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' diff --git a/puphpet/puppet/modules/puppi/README.md b/puphpet/puppet/modules/puppi/README.md index 1f6ed56..ce51e71 100644 --- a/puphpet/puppet/modules/puppi/README.md +++ b/puphpet/puppet/modules/puppi/README.md @@ -8,47 +8,55 @@ Source: http://www.example42.com Licence: Apache 2 -Puppi is a Puppet module and a CLI command. +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. -It can be used to standardize and automate the deployment of web applications -or to provides quick and standard commands to query and check your system's resources +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 actions required for virtually any kind of -application deployment and information gathering. +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 +* Old-Gen and Next-Gen Puppi implementation. -* A set of scripts that can be used in chain to automate any kind of deployment +* 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 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 +* Puppet defines to populate the output of the different actions. ## HOW TO INSTALL -Download Puppi from GitHub and place it in your modules directory: +Download Puppi from GitHub and place it in your modules directory: - git clone https://github.com/example42/puppi.git /etc/puppet/modules/puppi +```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 - class { 'puppi': } +```ruby +class { 'puppi': } +``` To test the Next-Gen version you can perform the following command. Please note that this module is not stable yet: - class { 'puppi': - version => '2', - } -If you have resources conflicts, do not install automatically the Puppi dependencies (commands and packages) +```ruby +class { 'puppi': + version => '2', +} +``` - class { 'puppi': - install_dependencies => false, - } +If you have resources conflicts, do not install automatically the Puppi dependencies (commands and packages) +```ruby +class { 'puppi': + install_dependencies => false, +} +``` ## HOW TO USE @@ -56,12 +64,14 @@ Once Puppi is installed you can use it to: * Easily define in Puppet manifests Web Applications deploy procedures. For example: - puppi::project::war { "myapp": - source => "http://repo.example42.com/deploy/prod/myapp.war", - deploy_root => "/opt/tomcat/myapp/webapps", - } + ```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 +* Integrate with your modules for puppi check, info and log * Enable Example42 modules integration @@ -71,26 +81,31 @@ Once Puppi is installed you can use it to: The Example42 modules provide (optional) Puppi integration. Once enabled for each module you have puppi check, info and log commands. -To eanble Puppi in OldGen Modules, set in the scope these variables: +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 +``` +$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: - class { 'openssh': - puppi => yes, - monitor => yes, - monitor_tool => 'puppi', - } - +```ruby +class { 'openssh': + puppi => yes, + monitor => yes, + monitor_tool => 'puppi', +} +``` ## USAGE OF THE PUPPI COMMAND (OLD GEN) - puppi [ -options ] +```bash +puppi [ -options ] +``` -The puppi command has these possibile actions: +The puppi command has these possible actions: First time initialization of the defined project (if available) puppi init @@ -130,12 +145,13 @@ You can also provide some options: Some common puppi commnds when you log for an application deployment: - puppi check - puppi log & # (More readable if done on another window) - puppi deploy myapp - puppi check - puppi info myapp - +```bash +puppi check +puppi log & # (More readable if done on another window) +puppi deploy myapp +puppi check +puppi info myapp +``` ## THE PUPPI MODULE @@ -209,7 +225,7 @@ A runtime configuration file, which is used by all all the the scripts invoked b ## HOW TO CUSTOMIZE -It should be clear that with puppi you have full flexibility in the definition of a deployment +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. @@ -217,10 +233,10 @@ 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. + 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 +* Reporting for each deploy/rollback is built-in and extensible * Automatic checks can be built in the deploy procedure @@ -234,7 +250,7 @@ There are different parts where you can customize the behaviour of puppi: 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 + 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 @@ -242,7 +258,7 @@ There are different parts where you can customize the behaviour of 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 + 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) diff --git a/puphpet/puppet/modules/puppi/README_deploy.md b/puphpet/puppet/modules/puppi/README_deploy.md index 683f48b..1f59dcd 100644 --- a/puphpet/puppet/modules/puppi/README_deploy.md +++ b/puphpet/puppet/modules/puppi/README_deploy.md @@ -3,50 +3,63 @@ Documentation and examples related to the puppi actions: deploy, rollback and in ## SYNOPSIS (COMMAND LINE) Shell command to launch a deploy: + puppi deploy puppi deploy [-f] [-i] [-t] [-d yes|full] [-r yes|no|fail] [-p "parameter=value parameter2=value2"] Shell command to launch a rollback: + puppi rollback Shell command to launch the first deploy: + puppi init ## 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', @@ -54,6 +67,7 @@ Get a war from $source and deploy it in $deploy_root: 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', @@ -63,6 +77,7 @@ to $report_mail (you can have a comma separated list of destination addresses): } 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', @@ -74,7 +89,8 @@ Get a tarfile with a .sql query file and apply to to you local Mysql with the cr } Get a list of files from $source, retrieve the actual files from $source_baseurl and place them -in $deploy_root +in $deploy_root: + puppi::project::files { 'gfxupdates': source => 'http://deploy.example42.com/prod/website2/list.txt', source_baseurl => 'http://design.example42.com/website2/gfx/', @@ -85,6 +101,7 @@ in $deploy_root 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', @@ -97,6 +114,7 @@ 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', @@ -114,6 +132,7 @@ The same deploy Nexus repository with some more options: - 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', @@ -140,6 +159,7 @@ An elaborated war deploy: - 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', @@ -155,6 +175,7 @@ An elaborated war deploy: } 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', @@ -176,20 +197,25 @@ The above puppi::projects defines manage more or less complex deployments proced 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 @@ -199,8 +225,11 @@ to have it rebuilt from scratch. Here is an example for a single deploy command: } 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}" diff --git a/puphpet/puppet/modules/puppi/Rakefile b/puphpet/puppet/modules/puppi/Rakefile index 8fcea70..f325677 100644 --- a/puphpet/puppet/modules/puppi/Rakefile +++ b/puphpet/puppet/modules/puppi/Rakefile @@ -1,6 +1,7 @@ -require 'rubygems' require 'puppetlabs_spec_helper/rake_tasks' -require 'puppet_blacksmith/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_parameter_defaults') +PuppetLint.configuration.send('disable_class_inherits_from_params_class') diff --git a/puphpet/puppet/modules/puppi/files/scripts/git.sh b/puphpet/puppet/modules/puppi/files/scripts/git.sh index 08b8c33..b422a20 100644 --- a/puphpet/puppet/modules/puppi/files/scripts/git.sh +++ b/puphpet/puppet/modules/puppi/files/scripts/git.sh @@ -158,7 +158,7 @@ do_install () { git checkout $verbosity $commit fi - if [ "x$gitdir" == "x$archivedir/$project-git" ] ; then + if [ "x$gitdir" == "x$archivedir/$project-git/gitrepo" ] ; then rsync -a --exclude=".git" $gitdir/$gitsubdir $deploy_root/ fi diff --git a/puphpet/puppet/modules/puppi/files/scripts/hg.sh b/puphpet/puppet/modules/puppi/files/scripts/hg.sh new file mode 100644 index 0000000..521a83f --- /dev/null +++ b/puphpet/puppet/modules/puppi/files/scripts/hg.sh @@ -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 (Optional) What action to perform. Available options: deploy (default), rollback" + echo "-s (Required) Git source repo to use" + echo "-d (Required) Directory where files are deployed" + echo "-u (Optional) User that performs the deploy operations. Default root" + echo "-t (Optional) Tag to deploy" + echo "-b (Optional) Branch to deploy" + echo "-c (Optional) Commit to deploy" + echo "-v (Optional) If verbose" + echo "-k (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 diff --git a/puphpet/puppet/modules/puppi/files/scripts/report_mongo.sh b/puphpet/puppet/modules/puppi/files/scripts/report_mongo.sh index c68ed7d..9969dd3 100644 --- a/puphpet/puppet/modules/puppi/files/scripts/report_mongo.sh +++ b/puphpet/puppet/modules/puppi/files/scripts/report_mongo.sh @@ -55,7 +55,7 @@ fqdn=$(facter fqdn) environment=$(facter ${env_key} -p) -if [ -z "${environment} ] +if [ -z "${environment}" ] then environment=$(facter ${fallback_key} -p) fi diff --git a/puphpet/puppet/modules/puppi/files/scripts/svn.sh b/puphpet/puppet/modules/puppi/files/scripts/svn.sh index a2dd4bc..651db93 100644 --- a/puphpet/puppet/modules/puppi/files/scripts/svn.sh +++ b/puphpet/puppet/modules/puppi/files/scripts/svn.sh @@ -188,7 +188,7 @@ do_install () { cd $svndir fi - if [ "x$svndir" == "x$archivedir/$project-svn" ] ; then + if [ "x$svndir" == "x$archivedir/$project-svn/svnrepo" ] ; then rsync -a --exclude=".svn" $svndir/$svnsubdir $deploy_root/ fi } diff --git a/puphpet/puppet/modules/puppi/lib/facter/last_run.rb b/puphpet/puppet/modules/puppi/lib/facter/last_run.rb index 1986984..f0eee04 100644 --- a/puphpet/puppet/modules/puppi/lib/facter/last_run.rb +++ b/puphpet/puppet/modules/puppi/lib/facter/last_run.rb @@ -2,6 +2,6 @@ Facter.add("last_run") do confine :kernel => [ 'Linux' , 'SunOS' , 'FreeBSD' , 'Darwin' ] setcode do - Facter::Util::Resolution.exec('date') + Facter::Util::Resolution.exec("date '+%a %b %d %T:%N %Z %Y'") end end diff --git a/puphpet/puppet/modules/puppi/lib/puppet/functions/params_lookup.rb b/puphpet/puppet/modules/puppi/lib/puppet/functions/params_lookup.rb new file mode 100644 index 0000000..4d7af2f --- /dev/null +++ b/puphpet/puppet/modules/puppi/lib/puppet/functions/params_lookup.rb @@ -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 diff --git a/puphpet/puppet/modules/puppi/lib/puppet/parser/functions/params_lookup.rb b/puphpet/puppet/modules/puppi/lib/puppet/parser/functions/params_lookup.rb index 53aad84..46ecdce 100644 --- a/puphpet/puppet/modules/puppi/lib/puppet/parser/functions/params_lookup.rb +++ b/puphpet/puppet/modules/puppi/lib/puppet/parser/functions/params_lookup.rb @@ -47,12 +47,24 @@ module Puppet::Parser::Functions end # Top Scope Variable Lookup (::modulename_varname) - value = lookupvar("::#{module_name}_#{var_name}") + 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' - value = lookupvar("::#{var_name}") + 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 diff --git a/puphpet/puppet/modules/puppi/manifests/init.pp b/puphpet/puppet/modules/puppi/manifests/init.pp index be2043f..cebceec 100644 --- a/puphpet/puppet/modules/puppi/manifests/init.pp +++ b/puphpet/puppet/modules/puppi/manifests/init.pp @@ -46,8 +46,8 @@ # Manage Version $puppi_ensure = $puppi::version ? { - 1 => '/usr/sbin/puppi.one', - 2 => '/usr/local/bin/puppi', + '1' => '/usr/sbin/puppi.one', + '2' => '/usr/local/bin/puppi', } file { 'puppi.link': diff --git a/puphpet/puppet/modules/puppi/manifests/mcollective/client.pp b/puphpet/puppet/modules/puppi/manifests/mcollective/client.pp index a15d0ca..24f2f63 100644 --- a/puphpet/puppet/modules/puppi/manifests/mcollective/client.pp +++ b/puphpet/puppet/modules/puppi/manifests/mcollective/client.pp @@ -42,19 +42,19 @@ # } file { '/usr/bin/puppicheck': - ensure => 'present', - mode => '0750', - owner => $puppi::params::mcollective_user, - group => $puppi::params::mcollective_group, - source => 'puppet:///modules/puppi/mcollective/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', + ensure => 'present', + mode => '0750', + owner => $puppi::params::mcollective_user, + group => $puppi::params::mcollective_group, + source => 'puppet:///modules/puppi/mcollective/puppideploy', } } diff --git a/puphpet/puppet/modules/puppi/manifests/netinstall.pp b/puphpet/puppet/modules/puppi/manifests/netinstall.pp index a7b7ed6..9f101fe 100644 --- a/puphpet/puppet/modules/puppi/manifests/netinstall.pp +++ b/puphpet/puppet/modules/puppi/manifests/netinstall.pp @@ -113,10 +113,10 @@ default => $postextract_cwd, } - if $preextract_command { - exec { "PreExtract ${source_filename} in ${destination_dir}": + if $preextract_command and $preextract_command != '' { + exec { "PreExtract ${source_filename} in ${destination_dir} - ${title}": command => $preextract_command, - subscribe => Exec["Retrieve ${url} in ${work_dir}"], + subscribe => Exec["Retrieve ${url} in ${work_dir} - ${title}"], refreshonly => true, path => $path, environment => $exec_env, @@ -124,7 +124,7 @@ } } - exec { "Retrieve ${url} in ${work_dir}": + exec { "Retrieve ${url} in ${work_dir} - ${title}": cwd => $work_dir, command => "${retrieve_command} ${retrieve_args} ${url}", creates => "${work_dir}/${source_filename}", @@ -133,34 +133,34 @@ environment => $exec_env, } - exec { "Extract ${source_filename} from ${work_dir}": + 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}"], + require => Exec["Retrieve ${url} in ${work_dir} - ${title}"], path => $path, environment => $exec_env, - notify => Exec["Chown ${source_filename} in ${destination_dir}"], + notify => Exec["Chown ${source_filename} in ${destination_dir} - ${title}"], } - exec { "Chown ${source_filename} in ${destination_dir}": + 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}"], + require => Exec["Extract ${source_filename} from ${work_dir} - ${title}"], path => $path, environment => $exec_env, } - if $postextract_command { - exec { "PostExtract ${source_filename} in ${destination_dir}": + if $postextract_command and $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}"], + subscribe => Exec["Extract ${source_filename} from ${work_dir} - ${title}"], refreshonly => true, timeout => $timeout, - require => [Exec["Retrieve ${url} in ${work_dir}"],Exec["Chown ${source_filename} in ${destination_dir}"]], + require => [Exec["Retrieve ${url} in ${work_dir} - ${title}"],Exec["Chown ${source_filename} in ${destination_dir} - ${title}"]], path => $path, environment => $exec_env, } diff --git a/puphpet/puppet/modules/puppi/manifests/params.pp b/puphpet/puppet/modules/puppi/manifests/params.pp index 721eae1..6829c48 100644 --- a/puphpet/puppet/modules/puppi/manifests/params.pp +++ b/puphpet/puppet/modules/puppi/manifests/params.pp @@ -29,11 +29,13 @@ $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, } diff --git a/puphpet/puppet/modules/puppi/manifests/project.pp b/puphpet/puppet/modules/puppi/manifests/project.pp index 4cf2331..74e6406 100644 --- a/puphpet/puppet/modules/puppi/manifests/project.pp +++ b/puphpet/puppet/modules/puppi/manifests/project.pp @@ -64,7 +64,7 @@ recurse => true, purge => true, require => File["${puppi::params::projectsdir}/${name}"]; - + "${puppi::params::projectsdir}/${name}/configure": ensure => $ensure, mode => '0755', diff --git a/puphpet/puppet/modules/puppi/manifests/project/archive.pp b/puphpet/puppet/modules/puppi/manifests/project/archive.pp index 34d25f0..70eea49 100644 --- a/puphpet/puppet/modules/puppi/manifests/project/archive.pp +++ b/puphpet/puppet/modules/puppi/manifests/project/archive.pp @@ -189,11 +189,11 @@ } puppi::deploy { "${name}-PreDeploy_Archive": - priority => '25' , - command => 'predeploy.sh' , - user => 'root' , - project => $name , - enable => $enable , + priority => '25' , + command => 'predeploy.sh' , + user => 'root' , + project => $name , + enable => $enable , } if ($firewall_src_ip != '') { diff --git a/puphpet/puppet/modules/puppi/manifests/project/hg.pp b/puphpet/puppet/modules/puppi/manifests/project/hg.pp new file mode 100644 index 0000000..61102ef --- /dev/null +++ b/puphpet/puppet/modules/puppi/manifests/project/hg.pp @@ -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: } + } + +} diff --git a/puphpet/puppet/modules/puppi/manifests/skel.pp b/puphpet/puppet/modules/puppi/manifests/skel.pp index 6be5cc9..48cdad8 100644 --- a/puphpet/puppet/modules/puppi/manifests/skel.pp +++ b/puphpet/puppet/modules/puppi/manifests/skel.pp @@ -8,11 +8,11 @@ require puppi::params file { 'puppi_basedir': - ensure => directory, - path => $puppi::params::basedir, - mode => '0755', - owner => $puppi::params::configfile_owner, - group => $puppi::params::configfile_group, + ensure => directory, + path => $puppi::params::basedir, + mode => '0755', + owner => $puppi::params::configfile_owner, + group => $puppi::params::configfile_group, } file { 'puppi_checksdir': @@ -143,11 +143,11 @@ # 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', + ensure => 'present', + mode => '0750', + owner => $puppi::params::configfile_owner, + group => $puppi::params::configfile_group, + source => 'puppet:///modules/puppi/mailpuppicheck', } # Puppi common scripts @@ -180,5 +180,5 @@ group => 'root', content => template('puppi/puppi_clean.erb'), } - } + } } diff --git a/puphpet/puppet/modules/puppi/spec/classes/puppi_spec.rb b/puphpet/puppet/modules/puppi/spec/classes/puppi_spec.rb index f6c072f..903f593 100644 --- a/puphpet/puppet/modules/puppi/spec/classes/puppi_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/classes/puppi_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_check_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_check_spec.rb index ba050bb..b825c23 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_check_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_check_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::check' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_deploy_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_deploy_spec.rb index a1969ba..2563b0c 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_deploy_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_deploy_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::deploy' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_helper_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_helper_spec.rb index 8e5ae9b..2fc08b9 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_helper_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_helper_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::helper' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_info_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_info_spec.rb index 7dcc99f..10ea20e 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_info_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_info_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::info' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_initialize_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_initialize_spec.rb index 158a600..f314880 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_initialize_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_initialize_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::initialize' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_log_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_log_spec.rb index 7fd8e91..e67188c 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_log_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_log_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::log' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_project_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_project_spec.rb index fbbf8ba..b37cb80 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_project_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_project_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::report' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_report_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_report_spec.rb index fbbf8ba..b37cb80 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_report_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_report_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::report' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_rollback_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_rollback_spec.rb index 2d4cbe5..c67e5c4 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_rollback_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_rollback_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::rollback' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_run_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_run_spec.rb index 692711c..40aa274 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_run_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_run_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::run' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_todo_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_todo_spec.rb index 4838522..249e151 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_todo_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_todo_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::todo' do diff --git a/puphpet/puppet/modules/puppi/spec/defines/puppi_ze_spec.rb b/puphpet/puppet/modules/puppi/spec/defines/puppi_ze_spec.rb index 1791368..e941b9a 100644 --- a/puphpet/puppet/modules/puppi/spec/defines/puppi_ze_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/defines/puppi_ze_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'puppi::ze' do diff --git a/puphpet/puppet/modules/puppi/spec/functions/any2bool_spec.rb b/puphpet/puppet/modules/puppi/spec/functions/any2bool_spec.rb index bc9a5ee..2f7a766 100644 --- a/puphpet/puppet/modules/puppi/spec/functions/any2bool_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/functions/any2bool_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'any2bool' do diff --git a/puphpet/puppet/modules/puppi/spec/functions/bool2ensure_spec.rb b/puphpet/puppet/modules/puppi/spec/functions/bool2ensure_spec.rb index 967d36c..e493eb5 100644 --- a/puphpet/puppet/modules/puppi/spec/functions/bool2ensure_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/functions/bool2ensure_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'bool2ensure' do diff --git a/puphpet/puppet/modules/puppi/spec/functions/url_parse_spec.rb b/puphpet/puppet/modules/puppi/spec/functions/url_parse_spec.rb index 3388e9a..bfc3133 100644 --- a/puphpet/puppet/modules/puppi/spec/functions/url_parse_spec.rb +++ b/puphpet/puppet/modules/puppi/spec/functions/url_parse_spec.rb @@ -1,4 +1,4 @@ -require "#{File.join(File.dirname(__FILE__),'..','spec_helper.rb')}" +require 'spec_helper' describe 'url_parse' do diff --git a/puphpet/puppet/modules/puppi/templates/puppi_clean.erb b/puphpet/puppet/modules/puppi/templates/puppi_clean.erb index f6a0eaa..5f006b0 100644 --- a/puphpet/puppet/modules/puppi/templates/puppi_clean.erb +++ b/puphpet/puppet/modules/puppi/templates/puppi_clean.erb @@ -1,10 +1,10 @@ #!/bin/bash -# This scripts cleans puppi log files older than <%= scope.lookupvar('puppi::logs_retention_days') %> +# 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') %> -type d -mtime +<%= scope.lookupvar('puppi::logs_retention_days') %> -exec rmdir '{}' '+' >/dev/null 2>&1 +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 diff --git a/puphpet/puppet/modules/puppi/templates/todo.erb b/puphpet/puppet/modules/puppi/templates/todo.erb index 3eaf03f..a7119e7 100644 --- a/puphpet/puppet/modules/puppi/templates/todo.erb +++ b/puphpet/puppet/modules/puppi/templates/todo.erb @@ -1,11 +1,11 @@ #!/bin/bash # Script generated by Puppet. It's executed when you run: -# puppi todo <%= name %> +# puppi todo <%= @name %> # # Sources common header for Puppi scripts . <%= scope.lookupvar('puppi::params::scriptsdir') %>/header || exit 10 -echo_title "$HOSTNAME - <%= name %>" +echo_title "$HOSTNAME - <%= @name %>" <% if @description != "" -%> cat < <% if @run != "" -%> -<% array_run.each do |cmd| %>show_command "<%= cmd -%>" +<% @array_run.each do |cmd| %>show_command "<%= cmd -%>" <% end -%> <% end -%> diff --git a/puphpet/puppet/modules/pyenv/.gitignore b/puphpet/puppet/modules/pyenv/.gitignore new file mode 100644 index 0000000..5f46921 --- /dev/null +++ b/puphpet/puppet/modules/pyenv/.gitignore @@ -0,0 +1,3 @@ +.python-version +Gemfile.lock +pkg diff --git a/puphpet/puppet/modules/rabbitmq/.fixtures.yml b/puphpet/puppet/modules/rabbitmq/.fixtures.yml index 90ea118..1d111f9 100644 --- a/puphpet/puppet/modules/rabbitmq/.fixtures.yml +++ b/puphpet/puppet/modules/rabbitmq/.fixtures.yml @@ -1,9 +1,7 @@ fixtures: repositories: "stdlib": "git://github.com/puppetlabs/puppetlabs-stdlib.git" - "apt": - repo: "git://github.com/puppetlabs/puppetlabs-apt.git" - branch: "1.8.x" + "apt": "git://github.com/puppetlabs/puppetlabs-apt.git" "staging": "git://github.com/nanliu/puppet-staging.git" erlang: repo: "https://github.com/garethr/garethr-erlang.git" diff --git a/puphpet/puppet/modules/rabbitmq/.gitignore b/puphpet/puppet/modules/rabbitmq/.gitignore new file mode 100644 index 0000000..b5db85e --- /dev/null +++ b/puphpet/puppet/modules/rabbitmq/.gitignore @@ -0,0 +1,9 @@ +pkg/ +Gemfile.lock +vendor/ +spec/fixtures/ +.vagrant/ +.bundle/ +coverage/ +.idea/ +*.iml diff --git a/puphpet/puppet/modules/rabbitmq/.travis.yml b/puphpet/puppet/modules/rabbitmq/.travis.yml index fef870d..c418ab5 100644 --- a/puphpet/puppet/modules/rabbitmq/.travis.yml +++ b/puphpet/puppet/modules/rabbitmq/.travis.yml @@ -7,18 +7,12 @@ matrix: fast_finish: true include: - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 3.4.0" - - rvm: 1.8.7 env: PUPPET_GEM_VERSION="~> 3.0" - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 3.0" - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes" - rvm: 2.1.5 env: PUPPET_GEM_VERSION="~> 3.0" - - rvm: 2.1.5 - env: PUPPET_GEM_VERSION="~> 3.4.0" - rvm: 2.1.5 env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes" + - rvm: 2.1.6 + env: PUPPET_GEM_VERSION="~> 4.0" STRICT_VARIABLES="yes" notifications: email: false diff --git a/puphpet/puppet/modules/rabbitmq/CHANGELOG.md b/puphpet/puppet/modules/rabbitmq/CHANGELOG.md index 85055dd..da05ca8 100644 --- a/puphpet/puppet/modules/rabbitmq/CHANGELOG.md +++ b/puphpet/puppet/modules/rabbitmq/CHANGELOG.md @@ -1,3 +1,46 @@ +## 2015-10-07 - Version 5.3.1 +### Summary +Adds a new resource type and a few ssl management parameters + +#### Features +- Add rabbitmq\_parameter type +- Add management\_ssl parameter to rabbitmq class +- Add stomp\_ssl\_only parameter to rabbitmq class + +#### Bugfixes +- file\_limit validation and el7 management +- Fix mnesia dir not getting wiped +- Fix message-ttl and max-length integer conversion in rabbitmq\_policy +- Allow managing erlang cookie without config\_cluster + +## 2015-05-26 - Version 5.3.0 [YANKED] +### Summary +This is a deleted release. It did not follow semver. + +## 2015-06-23 - Version 5.2.3 +### Summary +This is a patch release that updates the dependency requirements in the metadata. + +## 2015-06-09 - Version 5.2.2 +### Summary +This is a bugfix to allow the rabbitmq\_exchange type's internal/durable/auto\_delete attributes work when they are not explicitly passed. + +### Bugfixes +- Fix rabbitmq\_exchange create when internal/durable/auto\_delete are not specified +- Start unit testing on puppet 4 +- Add default value to tcp\_listen\_options + +## 2015-05-26 - Version 5.2.1 +###Summary +This release includes a fix for idempotency between puppet runs, as well as Readme updates + +####Features +- Readme updates +- Testing updates + +####Bugfixes +- Ensure idempotency between Puppet runs + ## 2015-04-28 - Version 5.2.0 ###Summary This release adds several new features for expanded configuration, support for SSL Ciphers, several bugfixes, and improved tests. diff --git a/puphpet/puppet/modules/rabbitmq/Gemfile b/puphpet/puppet/modules/rabbitmq/Gemfile index cc77f38..2b1b7cd 100644 --- a/puphpet/puppet/modules/rabbitmq/Gemfile +++ b/puphpet/puppet/modules/rabbitmq/Gemfile @@ -1,5 +1,15 @@ 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 @@ -9,10 +19,19 @@ group :development, :unit_tests do end group :system_tests do - gem 'beaker-rspec', :require => false + 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 end + + if facterversion = ENV['FACTER_GEM_VERSION'] gem 'facter', facterversion, :require => false else diff --git a/puphpet/puppet/modules/rabbitmq/README.md b/puphpet/puppet/modules/rabbitmq/README.md index ba56d0e..358f953 100644 --- a/puphpet/puppet/modules/rabbitmq/README.md +++ b/puphpet/puppet/modules/rabbitmq/README.md @@ -221,6 +221,8 @@ RabbitMQ Environment Variables in rabbitmq_env.config The erlang cookie to use for clustering - must be the same between all nodes. This value has no default and must be set explicitly if using clustering. +If you run Pacemaker and you don't want to use RabbitMQ buildin cluster, you can +set config_cluster to 'False' and set 'erlang_cookie'. ####`file_limit` @@ -272,6 +274,13 @@ Boolean, whether or not to manage package repositories. The port for the RabbitMQ management interface. +####`management_ssl` + +Enable/Disable SSL for the management port. +Has an effect only if ssl => true. +Default is true. +Valid values are true or false. + ####`node_ip_address` The value of NODE_IP_ADDRESS in rabbitmq_env.config @@ -381,6 +390,11 @@ Functionality can be tested with cipherscan or similar tool: https://github.com/ The port to use for Stomp. +####`stomp_ssl_only` + +Configures STOMP to only use SSL. No cleartext STOMP TCP listeners will be created. +Requires setting ssl_stomp_port also. + ####`stomp_ensure` Boolean to install the stomp plugin. @@ -442,7 +456,7 @@ rabbitmq_user { 'dan': query all current vhosts: `$ puppet resource rabbitmq_vhost` ```puppet -rabbitmq_vhost { 'myhost': +rabbitmq_vhost { 'myvhost': ensure => present, } ``` @@ -450,7 +464,7 @@ rabbitmq_vhost { 'myhost': ### rabbitmq\_exchange ```puppet -rabbitmq_exchange { 'myexchange@myhost': +rabbitmq_exchange { 'myexchange@myvhost': user => 'dan', password => 'bar', type => 'topic', @@ -467,7 +481,7 @@ rabbitmq_exchange { 'myexchange@myhost': ### rabbitmq\_queue ```puppet -rabbitmq_queue { 'myqueue@myhost': +rabbitmq_queue { 'myqueue@myvhost': user => 'dan', password => 'bar', durable => true, @@ -483,7 +497,7 @@ rabbitmq_queue { 'myqueue@myhost': ### rabbitmq\_binding ```puppet -rabbitmq_binding { 'myexchange@myqueue@myhost': +rabbitmq_binding { 'myexchange@myqueue@myvhost': user => 'dan', password => 'bar', destination_type => 'queue', @@ -496,7 +510,7 @@ rabbitmq_binding { 'myexchange@myqueue@myhost': ### rabbitmq\_user\_permissions ```puppet -rabbitmq_user_permissions { 'dan@myhost': +rabbitmq_user_permissions { 'dan@myvhost': configure_permission => '.*', read_permission => '.*', write_permission => '.*', @@ -506,7 +520,7 @@ rabbitmq_user_permissions { 'dan@myhost': ### rabbitmq\_policy ```puppet -rabbitmq_policy { 'ha-all@myhost': +rabbitmq_policy { 'ha-all@myvhost': pattern => '.*', priority => 0, applyto => 'all', @@ -527,6 +541,28 @@ rabbitmq_plugin {'rabbitmq_stomp': } ``` +### rabbitmq\_parameter + +```puppet + rabbitmq_parameter { 'documentumShovel@/': + component_name => '', + value => { + 'src-uri' => 'amqp://', + 'src-queue' => 'my-queue', + 'dest-uri' => 'amqp://remote-server', + 'dest-queue' => 'another-queue', + }, + } + + rabbitmq_parameter { 'documentumFed@/': + component_name => 'federation-upstream', + value => { + 'uri' => 'amqp://myserver', + 'expires' => '360000', + }, + } +``` + ### rabbitmq\_erlang\_cookie This is essentially a private type used by the rabbitmq::config class @@ -550,6 +586,10 @@ The module has been tested on: Testing on other platforms has been light and cannot be guaranteed. +### Apt module compatibility + +While this module supports both 1.x and 2.x versions of the puppetlabs-apt module, it does not support puppetlabs-apt 2.0.0 or 2.0.1. + ### Module dependencies If running CentOS/RHEL, and using the yum provider, ensure the epel repo is present. diff --git a/puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_erlang_cookie/ruby.rb b/puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_erlang_cookie/ruby.rb index 58c8b3c..74a9616 100644 --- a/puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_erlang_cookie/ruby.rb +++ b/puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_erlang_cookie/ruby.rb @@ -16,7 +16,7 @@ def exists? def content=(value) if resource[:force] == :true # Danger! puppet('resource', 'service', resource[:service_name], 'ensure=stopped') - FileUtils.rm_rf(resource[:rabbitmq_home] + File::PATH_SEPARATOR + 'mnesia') + FileUtils.rm_rf(resource[:rabbitmq_home] + File::SEPARATOR + 'mnesia') File.open(resource[:path], 'w') do |cookie| cookie.chmod(0400) cookie.write(value) diff --git a/puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_exchange/rabbitmqadmin.rb b/puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_exchange/rabbitmqadmin.rb index c1cff09..583b7bc 100644 --- a/puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_exchange/rabbitmqadmin.rb +++ b/puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_exchange/rabbitmqadmin.rb @@ -98,7 +98,12 @@ def create if arguments.nil? arguments = {} end - rabbitmqadmin('declare', 'exchange', vhost_opt, "--user=#{resource[:user]}", "--password=#{resource[:password]}", "name=#{name}", "type=#{resource[:type]}", "internal=#{resource[:internal]}", "durable=#{resource[:durable]}", "auto_delete=#{resource[:auto_delete]}", "arguments=#{arguments.to_json}", '-c', '/etc/rabbitmq/rabbitmqadmin.conf') + cmd = ['declare', 'exchange', vhost_opt, "--user=#{resource[:user]}", "--password=#{resource[:password]}", "name=#{name}", "type=#{resource[:type]}",] + cmd << "internal=#{resource[:internal]}" if resource[:internal] + cmd << "durable=#{resource[:durable]}" if resource[:durable] + cmd << "auto_delete=#{resource[:auto_delete]}" if resource[:auto_delete] + cmd += ["arguments=#{arguments.to_json}", '-c', '/etc/rabbitmq/rabbitmqadmin.conf'] + rabbitmqadmin(*cmd) @property_hash[:ensure] = :present end diff --git a/puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_parameter/rabbitmqctl.rb b/puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_parameter/rabbitmqctl.rb new file mode 100644 index 0000000..fe47688 --- /dev/null +++ b/puphpet/puppet/modules/rabbitmq/lib/puppet/provider/rabbitmq_parameter/rabbitmqctl.rb @@ -0,0 +1,84 @@ +require 'json' +require 'puppet/util/package' + +require File.expand_path(File.join(File.dirname(__FILE__), '..', 'rabbitmqctl')) +Puppet::Type.type(:rabbitmq_parameter).provide(:rabbitmqctl, :parent => Puppet::Provider::Rabbitmqctl) do + + defaultfor :feature => :posix + + # cache parameters + def self.parameters(name, vhost) + @parameters = {} unless @parameters + unless @parameters[vhost] + @parameters[vhost] = {} + self.run_with_retries { + rabbitmqctl('list_parameters', '-q', '-p', vhost) + }.split(/\n/).each do |line| + if line =~ /^(\S+)\s+(\S+)\s+(\S+)$/ + @parameters[vhost][$2] = { + :component_name => $1, + :value => JSON.parse($3), + } + else + raise Puppet::Error, "cannot parse line from list_parameter:#{line}" + end + end + end + @parameters[vhost][name] + end + + def parameters(name, vhost) + self.class.parameters(vhost, name) + end + + def should_parameter + @should_parameter ||= resource[:name].rpartition('@').first + end + + def should_vhost + @should_vhost ||= resource[:name].rpartition('@').last + end + + def create + set_parameter + end + + def destroy + rabbitmqctl('clear_parameter', '-p', should_vhost, 'shovel', should_parameter) + end + + def exists? + parameters(should_vhost, should_parameter) + end + + def component_name + parameters(should_vhost, should_parameter)[:component_name] + end + + def component_name=(component_name) + set_parameter + end + + def value + parameters(should_vhost, should_parameter)[:value] + end + + def value=(value) + set_parameter + end + + def set_parameter + unless @set_parameter + @set_parameter = true + resource[:value] ||= value + resource[:component_name] ||= component_name + rabbitmqctl('set_parameter', + '-p', should_vhost, + resource[:component_name], + should_parameter, + resource[:value].to_json + ) + end + end + +end diff --git a/puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_exchange.rb b/puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_exchange.rb index b2e88a8..7dd0a1f 100644 --- a/puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_exchange.rb +++ b/puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_exchange.rb @@ -24,16 +24,19 @@ newparam(:durable) do desc 'Exchange durability to be set *on creation*' newvalues(/^\S+$/) + defaultto 'false' end newparam(:auto_delete) do desc 'Exchange auto delete option to be set *on creation*' newvalues(/^\S+$/) + defaultto 'false' end newparam(:internal) do desc 'Exchange internal option to be set *on creation*' newvalues(/^\S+$/) + defaultto 'false' end newparam(:arguments) do diff --git a/puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_parameter.rb b/puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_parameter.rb new file mode 100644 index 0000000..5b1abea --- /dev/null +++ b/puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_parameter.rb @@ -0,0 +1,73 @@ +Puppet::Type.newtype(:rabbitmq_parameter) do + + desc 'Type for managing rabbitmq parameters' + + ensurable do + defaultto(:present) + newvalue(:present) do + provider.create + end + newvalue(:absent) do + provider.destroy + end + end + + autorequire(:service) { 'rabbitmq-server' } + + validate do + fail('component_name parameter is required.') if self[:ensure] == :present and self[:component_name].nil? + fail('value parameter is required.') if self[:ensure] == :present and self[:value].nil? + end + + newparam(:name, :namevar => true) do + desc 'combination of name@vhost to set parameter for' + newvalues(/^\S+@\S+$/) + end + + newproperty(:component_name) do + desc 'The component_name to use when setting parameter, eg: shovel or federation' + validate do |value| + resource.validate_component_name(value) + end + end + + newproperty(:value) do + desc 'A hash of values to use with the component name you are setting' + validate do |value| + resource.validate_value(value) + end + munge do |value| + resource.munge_value(value) + end + end + + autorequire(:rabbitmq_vhost) do + [self[:name].split('@')[1]] + end + + def validate_component_name(value) + if value.empty? + raise ArgumentError, "component_name must be defined" + end + end + + def validate_value(value) + unless [Hash].include?(value.class) + raise ArgumentError, "Invalid value" + end + value.each do |k,v| + unless [String].include?(v.class) + raise ArgumentError, "Invalid value" + end + end + end + + def munge_value(value) + value.each do |k,v| + if (v =~ /\A[-+]?[0-9]+\z/) + value[k] = v.to_i + end + end + value + end +end diff --git a/puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_policy.rb b/puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_policy.rb index 259a1d6..8b796d2 100644 --- a/puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_policy.rb +++ b/puphpet/puppet/modules/rabbitmq/lib/puppet/type/rabbitmq_policy.rb @@ -87,6 +87,18 @@ def validate_definition(definition) raise ArgumentError, "Invalid expires value '#{expires_val}'" end end + if definition.key? 'message-ttl' + message_ttl_val = definition['message-ttl'] + unless message_ttl_val.to_i.to_s == message_ttl_val + raise ArgumentError, "Invalid message-ttl value '#{message_ttl_val}'" + end + end + if definition.key? 'max-length' + max_length_val = definition['max-length'] + unless max_length_val.to_i.to_s == max_length_val + raise ArgumentError, "Invalid max-length value '#{max_length_val}'" + end + end end def munge_definition(definition) @@ -96,6 +108,12 @@ def munge_definition(definition) if definition.key? 'expires' definition['expires'] = definition['expires'].to_i end + if definition.key? 'message-ttl' + definition['message-ttl'] = definition['message-ttl'].to_i + end + if definition.key? 'max-length' + definition['max-length'] = definition['max-length'].to_i + end definition end end diff --git a/puphpet/puppet/modules/rabbitmq/manifests/config.pp b/puphpet/puppet/modules/rabbitmq/manifests/config.pp index 5e3f1ef..fce23ce 100644 --- a/puphpet/puppet/modules/rabbitmq/manifests/config.pp +++ b/puphpet/puppet/modules/rabbitmq/manifests/config.pp @@ -17,6 +17,7 @@ $erlang_cookie = $rabbitmq::erlang_cookie $interface = $rabbitmq::interface $management_port = $rabbitmq::management_port + $management_ssl = $rabbitmq::management_ssl $node_ip_address = $rabbitmq::node_ip_address $plugin_dir = $rabbitmq::plugin_dir $rabbitmq_user = $rabbitmq::rabbitmq_user @@ -39,6 +40,7 @@ $ssl_versions = $rabbitmq::ssl_versions $ssl_ciphers = $rabbitmq::ssl_ciphers $stomp_port = $rabbitmq::stomp_port + $stomp_ssl_only = $rabbitmq::stomp_ssl_only $ldap_auth = $rabbitmq::ldap_auth $ldap_server = $rabbitmq::ldap_server $ldap_user_dn_pattern = $rabbitmq::ldap_user_dn_pattern @@ -120,10 +122,11 @@ 'RedHat': { if versioncmp($::operatingsystemmajrelease, '7') >= 0 { file { '/etc/systemd/system/rabbitmq-server.service.d': - ensure => directory, - owner => '0', - group => '0', - mode => '0755', + ensure => directory, + owner => '0', + group => '0', + mode => '0755', + selinux_ignore_defaults => true, } -> file { '/etc/systemd/system/rabbitmq-server.service.d/limits.conf': content => template('rabbitmq/rabbitmq-server.service.d/limits.conf'), @@ -137,35 +140,31 @@ notify => Class['Rabbitmq::Service'], refreshonly => true, } - } else { - file { '/etc/security/limits.d/rabbitmq-server.conf': - content => template('rabbitmq/limits.conf'), - owner => '0', - group => '0', - mode => '0644', - notify => Class['Rabbitmq::Service'], - } + } + file { '/etc/security/limits.d/rabbitmq-server.conf': + content => template('rabbitmq/limits.conf'), + owner => '0', + group => '0', + mode => '0644', + notify => Class['Rabbitmq::Service'], } } default: { } } - if $config_cluster { - - if $erlang_cookie == undef { - fail('You must set the $erlang_cookie value in order to configure clustering.') - } else { - rabbitmq_erlang_cookie { "${rabbitmq_home}/.erlang.cookie": - content => $erlang_cookie, - force => $wipe_db_on_cookie_change, - rabbitmq_user => $rabbitmq_user, - rabbitmq_group => $rabbitmq_group, - rabbitmq_home => $rabbitmq_home, - service_name => $service_name, - before => File['rabbitmq.config'], - notify => Class['rabbitmq::service'], - } + if $erlang_cookie == undef and $config_cluster { + fail('You must set the $erlang_cookie value in order to configure clustering.') + } elsif $erlang_cookie != undef { + rabbitmq_erlang_cookie { "${rabbitmq_home}/.erlang.cookie": + content => $erlang_cookie, + force => $wipe_db_on_cookie_change, + rabbitmq_user => $rabbitmq_user, + rabbitmq_group => $rabbitmq_group, + rabbitmq_home => $rabbitmq_home, + service_name => $service_name, + before => File['rabbitmq.config'], + notify => Class['rabbitmq::service'], } } } diff --git a/puphpet/puppet/modules/rabbitmq/manifests/init.pp b/puphpet/puppet/modules/rabbitmq/manifests/init.pp index 4e115f9..f1346bb 100644 --- a/puphpet/puppet/modules/rabbitmq/manifests/init.pp +++ b/puphpet/puppet/modules/rabbitmq/manifests/init.pp @@ -15,6 +15,7 @@ $erlang_cookie = $rabbitmq::params::erlang_cookie, $interface = $rabbitmq::params::interface, $management_port = $rabbitmq::params::management_port, + $management_ssl = $rabbitmq::params::management_ssl, $node_ip_address = $rabbitmq::params::node_ip_address, $package_apt_pin = $rabbitmq::params::package_apt_pin, $package_ensure = $rabbitmq::params::package_ensure, @@ -56,6 +57,7 @@ $ldap_log = $rabbitmq::params::ldap_log, $ldap_config_variables = $rabbitmq::params::ldap_config_variables, $stomp_port = $rabbitmq::params::stomp_port, + $stomp_ssl_only = $rabbitmq::params::stomp_ssl_only, $version = $rabbitmq::params::version, $wipe_db_on_cookie_change = $rabbitmq::params::wipe_db_on_cookie_change, $cluster_partition_handling = $rabbitmq::params::cluster_partition_handling, @@ -101,9 +103,7 @@ } validate_bool($wipe_db_on_cookie_change) validate_bool($tcp_keepalive) - if ! is_integer($file_limit) { - validate_re($file_limit, '^(unlimited|infinity)$', '$file_limit must be an integer, \'unlimited\', or \'infinity\'.') - } + validate_re($file_limit, '^(\d+|-1|unlimited|infinity)$', '$file_limit must be a positive integer, \'-1\', \'unlimited\', or \'infinity\'.') # Validate service parameters. validate_re($service_ensure, '^(running|stopped)$') validate_bool($service_manage) @@ -124,6 +124,7 @@ validate_re($ssl_stomp_port, '\d+') } validate_bool($stomp_ensure) + validate_bool($stomp_ssl_only) validate_bool($ldap_auth) validate_string($ldap_server) validate_string($ldap_user_dn_pattern) @@ -144,6 +145,10 @@ warning('$ssl_stomp_port requires that $ssl => true and will be ignored') } + if $config_stomp and $stomp_ssl_only and ! $ssl_stomp_port { + fail('$stomp_ssl_only requires that $ssl_stomp_port be set') + } + if $ssl_versions { if $ssl { validate_array($ssl_versions) diff --git a/puphpet/puppet/modules/rabbitmq/manifests/install/rabbitmqadmin.pp b/puphpet/puppet/modules/rabbitmq/manifests/install/rabbitmqadmin.pp index bf545ee..cbb10e1 100644 --- a/puphpet/puppet/modules/rabbitmq/manifests/install/rabbitmqadmin.pp +++ b/puphpet/puppet/modules/rabbitmq/manifests/install/rabbitmqadmin.pp @@ -1,16 +1,17 @@ # class rabbitmq::install::rabbitmqadmin { - if($rabbitmq::ssl) { + if($rabbitmq::ssl and $rabbitmq::management_ssl) { $management_port = $rabbitmq::ssl_management_port + $protocol = 'https' } else { $management_port = $rabbitmq::management_port + $protocol = 'http' } $default_user = $rabbitmq::default_user $default_pass = $rabbitmq::default_pass - $protocol = $rabbitmq::ssl ? { false => 'http', default => 'https' } staging::file { 'rabbitmqadmin': target => "${rabbitmq::rabbitmq_home}/rabbitmqadmin", diff --git a/puphpet/puppet/modules/rabbitmq/manifests/params.pp b/puphpet/puppet/modules/rabbitmq/manifests/params.pp index 7366d95..74b2a7d 100644 --- a/puphpet/puppet/modules/rabbitmq/manifests/params.pp +++ b/puphpet/puppet/modules/rabbitmq/manifests/params.pp @@ -66,6 +66,7 @@ #install $admin_enable = true $management_port = '15672' + $management_ssl = true $package_apt_pin = '' $package_gpg_key = 'http://www.rabbitmq.com/rabbitmq-signing-key-public.asc' $repos_ensure = true @@ -112,10 +113,11 @@ $ldap_log = false $ldap_config_variables = {} $stomp_port = '6163' + $stomp_ssl_only = false $wipe_db_on_cookie_change = false $cluster_partition_handling = 'ignore' $environment_variables = {} $config_variables = {} $config_kernel_variables = {} - $file_limit = 16384 + $file_limit = '16384' } diff --git a/puphpet/puppet/modules/rabbitmq/metadata.json b/puphpet/puppet/modules/rabbitmq/metadata.json index d7d4133..bdc249e 100644 --- a/puphpet/puppet/modules/rabbitmq/metadata.json +++ b/puphpet/puppet/modules/rabbitmq/metadata.json @@ -1,6 +1,6 @@ { "name": "puppetlabs-rabbitmq", - "version": "5.2.0", + "version": "5.3.1", "author": "puppetlabs", "summary": "Installs, configures, and manages RabbitMQ.", "license": "Apache-2.0", @@ -49,7 +49,7 @@ ], "dependencies": [ {"name":"puppetlabs/stdlib","version_requirement":">=3.0.0 <5.0.0"}, - {"name":"puppetlabs/apt","version_requirement":">=1.8.0 <2.0.0"}, + {"name":"puppetlabs/apt","version_requirement":">=1.8.0 <3.0.0"}, {"name":"nanliu/staging","version_requirement":">=0.3.1 <2.0.0"} ] } diff --git a/puphpet/puppet/modules/rabbitmq/spec/acceptance/rabbitmqadmin_spec.rb b/puphpet/puppet/modules/rabbitmq/spec/acceptance/rabbitmqadmin_spec.rb index e9d619c..dcf6240 100644 --- a/puphpet/puppet/modules/rabbitmq/spec/acceptance/rabbitmqadmin_spec.rb +++ b/puphpet/puppet/modules/rabbitmq/spec/acceptance/rabbitmqadmin_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper_acceptance' describe 'rabbitmq::install::rabbitmqadmin class' do - context 'does nothing if service is unmanaged' do + context 'downloads the cli tools' do it 'should run successfully' do pp = <<-EOS class { 'rabbitmq': admin_enable => true, - service_manage => false, + service_manage => true, } if $::osfamily == 'RedHat' { class { 'erlang': epel_enable => true} @@ -14,21 +14,20 @@ class { 'erlang': epel_enable => true} } EOS - shell('rm -f /var/lib/rabbitmq/rabbitmqadmin') apply_manifest(pp, :catch_failures => true) end describe file('/var/lib/rabbitmq/rabbitmqadmin') do - it { should_not be_file } + it { should be_file } end end - context 'downloads the cli tools' do + context 'does nothing if service is unmanaged' do it 'should run successfully' do pp = <<-EOS class { 'rabbitmq': admin_enable => true, - service_manage => true, + service_manage => false, } if $::osfamily == 'RedHat' { class { 'erlang': epel_enable => true} @@ -36,11 +35,12 @@ class { 'erlang': epel_enable => true} } EOS + shell('rm -f /var/lib/rabbitmq/rabbitmqadmin') apply_manifest(pp, :catch_failures => true) end describe file('/var/lib/rabbitmq/rabbitmqadmin') do - it { should be_file } + it { should_not be_file } end end diff --git a/puphpet/puppet/modules/rabbitmq/spec/acceptance/zz281_spec.rb b/puphpet/puppet/modules/rabbitmq/spec/acceptance/zz281_spec.rb index 05e5ef4..7563748 100644 --- a/puphpet/puppet/modules/rabbitmq/spec/acceptance/zz281_spec.rb +++ b/puphpet/puppet/modules/rabbitmq/spec/acceptance/zz281_spec.rb @@ -3,209 +3,193 @@ # beacuse of some serious issues with upgrading and downgrading rabbitmq on RedHat, # we need to run all of the 2.8.1 tests last. # -# NOTE that this is only tested on RedHat and probably only works there. But I can't seem -# to get 'confine' to work... +# These tests only apply to RedHat because 2.8.1 is not available in either the +# distro or upstream repos for Debian/Ubuntu. # - describe 'rabbitmq class with 2.8.1:' do - case fact('osfamily') - when 'RedHat' - package_name = 'rabbitmq-server' - service_name = 'rabbitmq-server' - package_source = "http://www.rabbitmq.com/releases/rabbitmq-server/v2.8.1/rabbitmq-server-2.8.1-1.noarch.rpm" - package_ensure = '2.8.1-1' - when 'SUSE' - package_name = 'rabbitmq-server' - service_name = 'rabbitmq-server' - package_source = "http://www.rabbitmq.com/releases/rabbitmq-server/v2.8.1/rabbitmq-server-2.8.1-1.noarch.rpm" - package_ensure = '2.8.1-1' - when 'Debian' - package_name = 'rabbitmq-server' - service_name = 'rabbitmq-server' - package_source = '' - package_ensure = '2.8.1' - when 'Archlinux' - package_name = 'rabbitmq' - service_name = 'rabbitmq' - package_source = '' - package_ensure = '2.8.1' - end - - context "default class inclusion" do - it 'should run successfully' do - pp = <<-EOS - class { 'rabbitmq': - version => '2.8.1-1', - package_source => '#{package_source}', - package_ensure => '#{package_ensure}', - package_provider => 'rpm', - management_port => '55672', - } - if $::osfamily == 'RedHat' { - class { 'erlang': epel_enable => true} - Class['erlang'] -> Class['rabbitmq'] - } - EOS - - # clean up previous 3.x install - can't be ungraded cleanly via RPM - shell('service rabbitmq-server stop') - shell('yum -y erase rabbitmq-server') - shell('rm -Rf /var/lib/rabbitmq/mnesia /etc/rabbitmq /var/lib/rabbitmq/rabbitmqadmin') - # Apply twice to ensure no errors the second time. - apply_manifest(pp, :catch_failures => true) - expect(apply_manifest(pp, :catch_changes => true).exit_code).to be_zero - # DEBUG - shell('netstat -lntp') - end - - describe command('rabbitmqctl status') do - its(:stdout) { should match /{rabbit,"RabbitMQ","2.8.1"}/ } - end - - describe package(package_name) do - it { should be_installed } + if fact('osfamily') == 'RedHat' + package_name = 'rabbitmq-server' + service_name = 'rabbitmq-server' + package_source = "http://www.rabbitmq.com/releases/rabbitmq-server/v2.8.1/rabbitmq-server-2.8.1-1.noarch.rpm" + package_ensure = '2.8.1-1' + + context "default class inclusion" do + it 'should run successfully' do + pp = <<-EOS + class { 'rabbitmq': + version => '2.8.1-1', + package_source => '#{package_source}', + package_ensure => '#{package_ensure}', + package_provider => 'rpm', + management_port => '55672', + } + if $::osfamily == 'RedHat' { + class { 'erlang': epel_enable => true} + Class['erlang'] -> Class['rabbitmq'] + } + EOS + + # clean up previous 3.x install - can't be ungraded cleanly via RPM + shell('service rabbitmq-server stop') + shell('yum -y erase rabbitmq-server') + shell('rm -Rf /var/lib/rabbitmq/mnesia /etc/rabbitmq /var/lib/rabbitmq/rabbitmqadmin') + # Apply twice to ensure no errors the second time. + apply_manifest(pp, :catch_failures => true) + expect(apply_manifest(pp, :catch_changes => true).exit_code).to be_zero + # DEBUG + shell('netstat -lntp') + end + + describe command('rabbitmqctl status') do + its(:stdout) { should match /{rabbit,"RabbitMQ","2.8.1"}/ } + end + + describe package(package_name) do + it { should be_installed } + end + + describe service(service_name) do + it { should be_enabled } + it { should be_running } + end end - describe service(service_name) do - it { should be_enabled } - it { should be_running } + context "disable and stop service" do + it 'should run successfully' do + pp = <<-EOS + class { 'rabbitmq': + version => '2.8.1-1', + package_source => '#{package_source}', + package_ensure => '#{package_ensure}', + package_provider => 'rpm', + management_port => '55672', + service_ensure => 'stopped', + admin_enable => false, + } + if $::osfamily == 'RedHat' { + class { 'erlang': epel_enable => true} + Class['erlang'] -> Class['rabbitmq'] + } + EOS + + apply_manifest(pp, :catch_failures => true) + end + + describe service(service_name) do + it { should_not be_enabled } + it { should_not be_running } + end end - end - context "disable and stop service" do - it 'should run successfully' do - pp = <<-EOS - class { 'rabbitmq': - version => '2.8.1-1', - package_source => '#{package_source}', - package_ensure => '#{package_ensure}', - package_provider => 'rpm', - management_port => '55672', - service_ensure => 'stopped', - admin_enable => false, - } - if $::osfamily == 'RedHat' { - class { 'erlang': epel_enable => true} - Class['erlang'] -> Class['rabbitmq'] - } - EOS - - apply_manifest(pp, :catch_failures => true) + context "service is unmanaged" do + it 'should run successfully' do + pp_pre = <<-EOS + class { 'rabbitmq': + version => '2.8.1-1', + package_source => '#{package_source}', + package_ensure => '#{package_ensure}', + package_provider => 'rpm', + management_port => '55672', + } + if $::osfamily == 'RedHat' { + class { 'erlang': epel_enable => true} + Class['erlang'] -> Class['rabbitmq'] + } + EOS + + pp = <<-EOS + class { 'rabbitmq': + service_manage => false, + service_ensure => 'stopped', + } + if $::osfamily == 'RedHat' { + class { 'erlang': epel_enable => true} + Class['erlang'] -> Class['rabbitmq'] + } + EOS + + apply_manifest(pp_pre, :catch_failures => true) + apply_manifest(pp, :catch_failures => true) + end + + describe service(service_name) do + it { should be_enabled } + it { should be_running } + end end - describe service(service_name) do - it { should_not be_enabled } - it { should_not be_running } - end - end + context 'rabbitmqadmin' do + #confine :to, :platform => 'el-6-x86' + + it 'should run successfully' do + pp = <<-EOS + class { 'rabbitmq': + admin_enable => true, + service_manage => true, + version => '2.8.1-1', + package_source => '#{package_source}', + package_ensure => '#{package_ensure}', + package_provider => 'rpm', + management_port => '55672', + } + if $::osfamily == 'RedHat' { + class { 'erlang': epel_enable => true} + Class['erlang'] -> Class['rabbitmq'] + } + EOS + + shell('rm -f /var/lib/rabbitmq/rabbitmqadmin') + apply_manifest(pp, :catch_failures => true) + end + + # since serverspec (used by beaker-rspec) can only tell present/absent for packages + describe file('/var/lib/rabbitmq/rabbitmqadmin') do + it { should be_file } + end + + describe command('/usr/local/bin/rabbitmqadmin --help') do + its(:exit_status) { should eq 0 } + end - context "service is unmanaged" do - it 'should run successfully' do - pp_pre = <<-EOS - class { 'rabbitmq': - version => '2.8.1-1', - package_source => '#{package_source}', - package_ensure => '#{package_ensure}', - package_provider => 'rpm', - management_port => '55672', - } - if $::osfamily == 'RedHat' { - class { 'erlang': epel_enable => true} - Class['erlang'] -> Class['rabbitmq'] - } - EOS - - pp = <<-EOS - class { 'rabbitmq': - service_manage => false, - service_ensure => 'stopped', - } - if $::osfamily == 'RedHat' { - class { 'erlang': epel_enable => true} - Class['erlang'] -> Class['rabbitmq'] - } - EOS - - apply_manifest(pp_pre, :catch_failures => true) - apply_manifest(pp, :catch_failures => true) end - describe service(service_name) do - it { should be_enabled } - it { should be_running } - end - end - - context 'rabbitmqadmin' do - #confine :to, :platform => 'el-6-x86' - - it 'should run successfully' do - pp = <<-EOS - class { 'rabbitmq': - admin_enable => true, - service_manage => true, - version => '2.8.1-1', - package_source => '#{package_source}', - package_ensure => '#{package_ensure}', - package_provider => 'rpm', - management_port => '55672', - } - if $::osfamily == 'RedHat' { - class { 'erlang': epel_enable => true} - Class['erlang'] -> Class['rabbitmq'] - } - EOS - - shell('rm -f /var/lib/rabbitmq/rabbitmqadmin') - apply_manifest(pp, :catch_failures => true) - end - - # since serverspec (used by beaker-rspec) can only tell present/absent for packages - describe file('/var/lib/rabbitmq/rabbitmqadmin') do - it { should be_file } - end - - describe command('/usr/local/bin/rabbitmqadmin --help') do - its(:exit_status) { should eq 0 } - end - - end - - context 'rabbitmqadmin with specified default credentials' do - - it 'should run successfully' do - # make sure credential change takes effect before admin_enable - pp = <<-EOS - class { 'rabbitmq': - admin_enable => true, - service_manage => true, - version => '2.8.1-1', - package_source => '#{package_source}', - package_ensure => '#{package_ensure}', - package_provider => 'rpm', - management_port => '55672', - default_user => 'foobar', - default_pass => 'bazblam', - } - if $::osfamily == 'RedHat' { - class { 'erlang': epel_enable => true} - Class['erlang'] -> Class['rabbitmq'] - } - EOS - - # next 3 lines - see MODULES-1085 - shell('service rabbitmq-server stop') - shell('rm -Rf /var/lib/rabbitmq/mnesia /var/lib/rabbitmq/rabbitmqadmin') - apply_manifest(pp, :catch_failures => true) - end - - # since serverspec (used by beaker-rspec) can only tell present/absent for packages - describe file('/var/lib/rabbitmq/rabbitmqadmin') do - it { should be_file } - end + context 'rabbitmqadmin with specified default credentials' do + + it 'should run successfully' do + # make sure credential change takes effect before admin_enable + pp = <<-EOS + class { 'rabbitmq': + admin_enable => true, + service_manage => true, + version => '2.8.1-1', + package_source => '#{package_source}', + package_ensure => '#{package_ensure}', + package_provider => 'rpm', + management_port => '55672', + default_user => 'foobar', + default_pass => 'bazblam', + } + if $::osfamily == 'RedHat' { + class { 'erlang': epel_enable => true} + Class['erlang'] -> Class['rabbitmq'] + } + EOS + + # next 3 lines - see MODULES-1085 + shell('service rabbitmq-server stop') + shell('rm -Rf /var/lib/rabbitmq/mnesia /var/lib/rabbitmq/rabbitmqadmin') + apply_manifest(pp, :catch_failures => true) + end + + # since serverspec (used by beaker-rspec) can only tell present/absent for packages + describe file('/var/lib/rabbitmq/rabbitmqadmin') do + it { should be_file } + end + + describe command('/usr/local/bin/rabbitmqadmin --help') do + its(:exit_status) { should eq 0 } + end - describe command('/usr/local/bin/rabbitmqadmin --help') do - its(:exit_status) { should eq 0 } end end diff --git a/puphpet/puppet/modules/rabbitmq/spec/classes/rabbitmq_spec.rb b/puphpet/puppet/modules/rabbitmq/spec/classes/rabbitmq_spec.rb index 9ba29f7..45b4b7c 100644 --- a/puphpet/puppet/modules/rabbitmq/spec/classes/rabbitmq_spec.rb +++ b/puphpet/puppet/modules/rabbitmq/spec/classes/rabbitmq_spec.rb @@ -150,8 +150,8 @@ it { should contain_file('/etc/default/rabbitmq-server').with_content(/ulimit -n infinity/) } end - context 'with file_limit => -1' do - let(:params) {{ :file_limit => -1 }} + context 'with file_limit => \'-1\'' do + let(:params) {{ :file_limit => '-1' }} it { should contain_file('/etc/default/rabbitmq-server').with_content(/ulimit -n -1/) } end @@ -160,10 +160,17 @@ it { should contain_file('/etc/default/rabbitmq-server').with_content(/ulimit -n 1234/) } end - context 'with file_limit => foo' do + context 'with file_limit => \'-42\'' do + let(:params) {{ :file_limit => '-42' }} + it 'does not compile' do + expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be a positive integer, '-1', 'unlimited', or 'infinity'/) + end + end + + context 'with file_limit => \'foo\'' do let(:params) {{ :file_limit => 'foo' }} it 'does not compile' do - expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be an integer, 'unlimited', or 'infinity'/) + expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be a positive integer, '-1', 'unlimited', or 'infinity'/) end end end @@ -174,6 +181,72 @@ should contain_class('rabbitmq::repo::rhel') should contain_exec('rpm --import http://www.rabbitmq.com/rabbitmq-signing-key-public.asc') end + + context 'with file_limit => \'unlimited\'' do + let(:params) {{ :file_limit => 'unlimited' }} + it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( + 'owner' => '0', + 'group' => '0', + 'mode' => '0644', + 'notify' => 'Class[Rabbitmq::Service]', + 'content' => 'rabbitmq soft nofile unlimited +rabbitmq hard nofile unlimited +' + ) } + end + + context 'with file_limit => \'infinity\'' do + let(:params) {{ :file_limit => 'infinity' }} + it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( + 'owner' => '0', + 'group' => '0', + 'mode' => '0644', + 'notify' => 'Class[Rabbitmq::Service]', + 'content' => 'rabbitmq soft nofile infinity +rabbitmq hard nofile infinity +' + ) } + end + + context 'with file_limit => \'-1\'' do + let(:params) {{ :file_limit => '-1' }} + it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( + 'owner' => '0', + 'group' => '0', + 'mode' => '0644', + 'notify' => 'Class[Rabbitmq::Service]', + 'content' => 'rabbitmq soft nofile -1 +rabbitmq hard nofile -1 +' + ) } + end + + context 'with file_limit => \'1234\'' do + let(:params) {{ :file_limit => '1234' }} + it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( + 'owner' => '0', + 'group' => '0', + 'mode' => '0644', + 'notify' => 'Class[Rabbitmq::Service]', + 'content' => 'rabbitmq soft nofile 1234 +rabbitmq hard nofile 1234 +' + ) } + end + + context 'with file_limit => \'-42\'' do + let(:params) {{ :file_limit => '-42' }} + it 'does not compile' do + expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be a positive integer, '-1', 'unlimited', or 'infinity'/) + end + end + + context 'with file_limit => \'foo\'' do + let(:params) {{ :file_limit => 'foo' }} + it 'does not compile' do + expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be a positive integer, '-1', 'unlimited', or 'infinity'/) + end + end end context 'on Redhat' do @@ -252,10 +325,11 @@ let(:facts) {{ :osfamily => 'RedHat', :operatingsystemmajrelease => '7' }} it { should contain_file('/etc/systemd/system/rabbitmq-server.service.d').with( - 'ensure' => 'directory', - 'owner' => '0', - 'group' => '0', - 'mode' => '0755' + 'ensure' => 'directory', + 'owner' => '0', + 'group' => '0', + 'mode' => '0755', + 'selinux_ignore_defaults' => true ) } it { should contain_exec('rabbitmq-systemd-reload').with( @@ -263,7 +337,7 @@ 'notify' => 'Class[Rabbitmq::Service]', 'refreshonly' => true ) } - context 'with file_limit => unlimited' do + context 'with file_limit => \'unlimited\'' do let(:params) {{ :file_limit => 'unlimited' }} it { should contain_file('/etc/systemd/system/rabbitmq-server.service.d/limits.conf').with( 'owner' => '0', @@ -276,7 +350,7 @@ ) } end - context 'with file_limit => infinity' do + context 'with file_limit => \'infinity\'' do let(:params) {{ :file_limit => 'infinity' }} it { should contain_file('/etc/systemd/system/rabbitmq-server.service.d/limits.conf').with( 'owner' => '0', @@ -289,8 +363,8 @@ ) } end - context 'with file_limit => -1' do - let(:params) {{ :file_limit => -1 }} + context 'with file_limit => \'-1\'' do + let(:params) {{ :file_limit => '-1' }} it { should contain_file('/etc/systemd/system/rabbitmq-server.service.d/limits.conf').with( 'owner' => '0', 'group' => '0', @@ -314,76 +388,6 @@ ' ) } end - - context 'with file_limit => foo' do - let(:params) {{ :file_limit => 'foo' }} - it 'does not compile' do - expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be an integer, 'unlimited', or 'infinity'/) - end - end - end - - context 'on RedHat before 7.0' do - let(:facts) {{ :osfamily => 'RedHat', :operatingsystemmajrelease => '6' }} - - context 'with file_limit => unlimited' do - let(:params) {{ :file_limit => 'unlimited' }} - it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( - 'owner' => '0', - 'group' => '0', - 'mode' => '0644', - 'notify' => 'Class[Rabbitmq::Service]', - 'content' => 'rabbitmq soft nofile unlimited -rabbitmq hard nofile unlimited -' - ) } - end - - context 'with file_limit => infinity' do - let(:params) {{ :file_limit => 'infinity' }} - it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( - 'owner' => '0', - 'group' => '0', - 'mode' => '0644', - 'notify' => 'Class[Rabbitmq::Service]', - 'content' => 'rabbitmq soft nofile infinity -rabbitmq hard nofile infinity -' - ) } - end - - context 'with file_limit => -1' do - let(:params) {{ :file_limit => -1 }} - it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( - 'owner' => '0', - 'group' => '0', - 'mode' => '0644', - 'notify' => 'Class[Rabbitmq::Service]', - 'content' => 'rabbitmq soft nofile -1 -rabbitmq hard nofile -1 -' - ) } - end - - context 'with file_limit => \'1234\'' do - let(:params) {{ :file_limit => '1234' }} - it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( - 'owner' => '0', - 'group' => '0', - 'mode' => '0644', - 'notify' => 'Class[Rabbitmq::Service]', - 'content' => 'rabbitmq soft nofile 1234 -rabbitmq hard nofile 1234 -' - ) } - end - - context 'with file_limit => foo' do - let(:params) {{ :file_limit => 'foo' }} - it 'does not compile' do - expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be an integer, 'unlimited', or 'infinity'/) - end - end end ['Debian', 'RedHat', 'SUSE', 'Archlinux'].each do |distro| @@ -470,6 +474,25 @@ end end + describe 'with erlang_cookie set but without config_cluster' do + let(:params) {{ + :config_cluster => false, + :erlang_cookie => 'TESTCOOKIE', + }} + it 'contains the rabbitmq_erlang_cookie' do + should contain_rabbitmq_erlang_cookie('/var/lib/rabbitmq/.erlang.cookie') + end + end + + describe 'without erlang_cookie and without config_cluster' do + let(:params) {{ + :config_cluster => false, + }} + it 'contains the rabbitmq_erlang_cookie' do + should_not contain_rabbitmq_erlang_cookie('/var/lib/rabbitmq/.erlang.cookie') + end + end + describe 'and sets appropriate configuration' do let(:params) {{ :config_cluster => true, @@ -639,6 +662,79 @@ end end + describe 'ssl options and mangament_ssl false' do + let(:params) { + { :ssl => true, + :ssl_port => 3141, + :ssl_cacert => '/path/to/cacert', + :ssl_cert => '/path/to/cert', + :ssl_key => '/path/to/key', + :management_ssl => false, + :management_port => 13142 + } } + + it 'should set ssl options to specified values' do + should contain_file('rabbitmq.config').with_content( + %r{ssl_listeners, \[3141\]} + ) + should contain_file('rabbitmq.config').with_content( + %r{ssl_options, \[} + ) + should contain_file('rabbitmq.config').with_content( + %r{cacertfile,"/path/to/cacert"} + ) + should contain_file('rabbitmq.config').with_content( + %r{certfile,"/path/to/cert"} + ) + should contain_file('rabbitmq.config').with_content( + %r{keyfile,"/path/to/key"} + ) + end + it 'should set non ssl port for management port' do + should contain_file('rabbitmq.config').with_content( + %r{port, 13142} + ) + end + end + + describe 'ssl options and mangament_ssl true' do + let(:params) { + { :ssl => true, + :ssl_port => 3141, + :ssl_cacert => '/path/to/cacert', + :ssl_cert => '/path/to/cert', + :ssl_key => '/path/to/key', + :management_ssl => true, + :ssl_management_port => 13141 + } } + + it 'should set ssl options to specified values' do + should contain_file('rabbitmq.config').with_content( + %r{ssl_listeners, \[3141\]} + ) + should contain_file('rabbitmq.config').with_content( + %r{ssl_opts, } + ) + should contain_file('rabbitmq.config').with_content( + %r{ssl_options, \[} + ) + should contain_file('rabbitmq.config').with_content( + %r{cacertfile,"/path/to/cacert"} + ) + should contain_file('rabbitmq.config').with_content( + %r{certfile,"/path/to/cert"} + ) + should contain_file('rabbitmq.config').with_content( + %r{keyfile,"/path/to/key"} + ) + end + it 'should set ssl managment port to specified values' do + should contain_file('rabbitmq.config').with_content( + %r{port, 13141} + ) + end + end + describe 'ssl options' do let(:params) { { :ssl => true, @@ -810,10 +906,11 @@ should contain_file('rabbitmq.config').with_content(%r{listener, \[}) should contain_file('rabbitmq.config').with_content(%r{port, 5926\}}) should contain_file('rabbitmq.config').with_content(%r{ssl, true\}}) - should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[\{cacertfile, "/path/to/cacert"\},}) + should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[}) + should contain_file('rabbitmq.config').with_content(%r{cacertfile, "/path/to/cacert"\},}) should contain_file('rabbitmq.config').with_content(%r{certfile, "/path/to/cert"\},}) should contain_file('rabbitmq.config').with_content(%r{keyfile, "/path/to/key"\}}) - should contain_file('rabbitmq.config').with_content(%r{,\{versions, \['tlsv1.1', 'tlsv1.2'\]\}[\r\n ]*\]\}}) + should contain_file('rabbitmq.config').with_content(%r{,\{versions, \['tlsv1.1', 'tlsv1.2'\]\}}) end end @@ -832,9 +929,10 @@ should contain_file('rabbitmq.config').with_content(%r{listener, \[}) should contain_file('rabbitmq.config').with_content(%r{port, 3141\}}) should contain_file('rabbitmq.config').with_content(%r{ssl, true\}}) - should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[\{cacertfile, "/path/to/cacert"\},}) + should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[}) + should contain_file('rabbitmq.config').with_content(%r{cacertfile, "/path/to/cacert"\},}) should contain_file('rabbitmq.config').with_content(%r{certfile, "/path/to/cert"\},}) - should contain_file('rabbitmq.config').with_content(%r{keyfile, "/path/to/key"\}[\r\n ]*\]\}}) + should contain_file('rabbitmq.config').with_content(%r{keyfile, "/path/to/key"\}}) end end @@ -867,9 +965,10 @@ should contain_file('rabbitmq.config').with_content(%r{listener, \[}) should contain_file('rabbitmq.config').with_content(%r{port, 3141\},}) should contain_file('rabbitmq.config').with_content(%r{ssl, true\},}) - should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[\{cacertfile, "/path/to/cacert"\},}) + should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[}) + should contain_file('rabbitmq.config').with_content(%r{cacertfile, "/path/to/cacert"\},}) should contain_file('rabbitmq.config').with_content(%r{certfile, "/path/to/cert"\},}) - should contain_file('rabbitmq.config').with_content(%r{keyfile, "/path/to/key"\}[\r\n ]*\]\}}) + should contain_file('rabbitmq.config').with_content(%r{keyfile, "/path/to/key"\}}) end end @@ -922,14 +1021,14 @@ let(:params) {{ :tcp_keepalive => true }} it 'should set tcp_listen_options keepalive true' do should contain_file('rabbitmq.config') \ - .with_content(/\{tcp_listen_options, \[\{keepalive, true\}\]\},/) + .with_content(/\{keepalive, true\}/) end end describe 'tcp_keepalive disabled (default)' do it 'should not set tcp_listen_options' do should contain_file('rabbitmq.config') \ - .without_content(/\{tcp_listen_options, \[\{keepalive, true\}\]\},/) + .without_content(/\{keepalive, true\}/) end end diff --git a/puphpet/puppet/modules/rabbitmq/spec/spec_helper_acceptance.rb b/puphpet/puppet/modules/rabbitmq/spec/spec_helper_acceptance.rb index b82ba36..4c52dee 100644 --- a/puphpet/puppet/modules/rabbitmq/spec/spec_helper_acceptance.rb +++ b/puphpet/puppet/modules/rabbitmq/spec/spec_helper_acceptance.rb @@ -26,7 +26,7 @@ shell("/bin/touch #{default['puppetpath']}/hiera.yaml") shell('puppet module install puppetlabs-stdlib', { :acceptable_exit_codes => [0,1] }) if fact('osfamily') == 'Debian' - shell('puppet module install puppetlabs-apt --version 1.8.0 --force', { :acceptable_exit_codes => [0,1] }) + shell('puppet module install puppetlabs-apt', { :acceptable_exit_codes => [0,1] }) end shell('puppet module install nanliu-staging', { :acceptable_exit_codes => [0,1] }) if fact('osfamily') == 'RedHat' diff --git a/puphpet/puppet/modules/rabbitmq/spec/unit/puppet/provider/rabbitmq_parameter/rabbitmqctl_spec.rb b/puphpet/puppet/modules/rabbitmq/spec/unit/puppet/provider/rabbitmq_parameter/rabbitmqctl_spec.rb new file mode 100644 index 0000000..bfacda5 --- /dev/null +++ b/puphpet/puppet/modules/rabbitmq/spec/unit/puppet/provider/rabbitmq_parameter/rabbitmqctl_spec.rb @@ -0,0 +1,87 @@ +require 'puppet' +require 'mocha' + +RSpec.configure do |config| + config.mock_with :mocha +end + +describe Puppet::Type.type(:rabbitmq_parameter).provider(:rabbitmqctl) do + + let(:resource) do + Puppet::Type.type(:rabbitmq_parameter).new( + :name => 'documentumShovel@/', + :component_name => 'shovel', + :value => { + 'src-uri' => 'amqp://', + 'src-queue' => 'my-queue', + 'dest-uri' => 'amqp://remote-server', + 'dest-queue' => 'another-queue', + }, + :provider => described_class.name + ) + end + + let(:provider) { resource.provider } + + after(:each) do + described_class.instance_variable_set(:@parameters, nil) + end + + it 'should accept @ in parameter name' do + resource = Puppet::Type.type(:rabbitmq_parameter).new( + :name => 'documentumShovel@/', + :component_name => 'shovel', + :value => { + 'src-uri' => 'amqp://', + 'src-queue' => 'my-queue', + 'dest-uri' => 'amqp://remote-server', + 'dest-queue' => 'another-queue', + }, + :provider => described_class.name + ) + provider = described_class.new(resource) + provider.should_parameter.should == 'documentumShovel' + provider.should_vhost.should == '/' + end + + it 'should fail with invalid output from list' do + provider.class.expects(:rabbitmqctl).with('list_parameters', '-q', '-p', '/').returns 'foobar' + expect { provider.exists? }.to raise_error(Puppet::Error, /cannot parse line from list_parameter/) + end + + it 'should match parameters from list' do + provider.class.expects(:rabbitmqctl).with('list_parameters', '-q', '-p', '/').returns <<-EOT +shovel documentumShovel {"src-uri":"amqp://","src-queue":"my-queue","dest-uri":"amqp://remote-server","dest-queue":"another-queue"} +EOT + provider.exists?.should == { + :component_name => 'shovel', + :value => { + 'src-uri' => 'amqp://', + 'src-queue' => 'my-queue', + 'dest-uri' => 'amqp://remote-server', + 'dest-queue' => 'another-queue', + } + } + end + + it 'should not match an empty list' do + provider.class.expects(:rabbitmqctl).with('list_parameters', '-q', '-p', '/').returns '' + provider.exists?.should == nil + end + + it 'should destroy parameter' do + provider.expects(:rabbitmqctl).with('clear_parameter', '-p', '/', 'shovel', 'documentumShovel') + provider.destroy + end + + it 'should only call set_parameter once' do + provider.expects(:rabbitmqctl).with('set_parameter', + '-p', '/', + 'shovel', + 'documentumShovel', + '{"src-uri":"amqp://","src-queue":"my-queue","dest-uri":"amqp://remote-server","dest-queue":"another-queue"}' + ).once + provider.create + end + +end diff --git a/puphpet/puppet/modules/rabbitmq/spec/unit/puppet/type/rabbitmq_parameter_spec.rb b/puphpet/puppet/modules/rabbitmq/spec/unit/puppet/type/rabbitmq_parameter_spec.rb new file mode 100644 index 0000000..6afa31d --- /dev/null +++ b/puphpet/puppet/modules/rabbitmq/spec/unit/puppet/type/rabbitmq_parameter_spec.rb @@ -0,0 +1,81 @@ +require 'puppet' +require 'puppet/type/rabbitmq_parameter' + +describe Puppet::Type.type(:rabbitmq_parameter) do + + before do + @parameter = Puppet::Type.type(:rabbitmq_parameter).new( + :name => 'documentumShovel@/', + :component_name => 'shovel', + :value => { + 'src-uri' => 'amqp://myremote-server', + 'src-queue' => 'queue.docs.outgoing', + 'dest-uri' => 'amqp://', + 'dest-queue' => 'queue.docs.incoming', + }) + end + + it 'should accept a valid name' do + @parameter[:name] = 'documentumShovel@/' + @parameter[:name].should == 'documentumShovel@/' + end + + it 'should require a name' do + expect { + Puppet::Type.type(:rabbitmq_parameter).new({}) + }.to raise_error(Puppet::Error, 'Title or name must be provided') + end + + it 'should fail when name does not have a @' do + expect { + @parameter[:name] = 'documentumShovel' + }.to raise_error(Puppet::Error, /Valid values match/) + end + + it 'should accept a string' do + @parameter[:component_name] = 'mystring' + @parameter[:component_name].should == 'mystring' + end + + it 'should not be empty' do + expect { + @parameter[:component_name] = '' + }.to raise_error(Puppet::Error, /component_name must be defined/) + end + + it 'should accept a valid hash for value' do + value = {'message-ttl' => '1800000'} + @parameter[:value] = value + @parameter[:value].should == value + end + + it 'should not accept invalid hash for definition' do + expect { + @parameter[:value] = '' + }.to raise_error(Puppet::Error, /Invalid value/) + + expect { + @parameter[:value] = 'guest' + }.to raise_error(Puppet::Error, /Invalid value/) + + expect { + @parameter[:value] = {'message-ttl' => ['999', '100']} + }.to raise_error(Puppet::Error, /Invalid value/) + end + + it 'should accept string as myparameter' do + value = {'myparameter' => 'mystring'} + @parameter[:value] = value + @parameter[:value]['myparameter'].should be_a(String) + @parameter[:value]['myparameter'].should == 'mystring' + end + + + it 'should convert to integer when string only contains numbers' do + value = {'myparameter' => '1800000'} + @parameter[:value] = value + @parameter[:value]['myparameter'].should be_a(Fixnum) + @parameter[:value]['myparameter'].should == 1800000 + end + +end diff --git a/puphpet/puppet/modules/rabbitmq/spec/unit/puppet/type/rabbitmq_policy_spec.rb b/puphpet/puppet/modules/rabbitmq/spec/unit/puppet/type/rabbitmq_policy_spec.rb index 36bf2a7..ff96b1d 100644 --- a/puphpet/puppet/modules/rabbitmq/spec/unit/puppet/type/rabbitmq_policy_spec.rb +++ b/puphpet/puppet/modules/rabbitmq/spec/unit/puppet/type/rabbitmq_policy_spec.rb @@ -116,4 +116,32 @@ @policy[:definition] = definition }.to raise_error(Puppet::Error, /Invalid expires value.*future/) end + + it 'should accept and convert the message-ttl value' do + definition = {'message-ttl' => '1800000'} + @policy[:definition] = definition + @policy[:definition]['message-ttl'].should be_a(Fixnum) + @policy[:definition]['message-ttl'].should == 1800000 + end + + it 'should not accept non-numeric message-ttl value' do + definition = {'message-ttl' => 'future'} + expect { + @policy[:definition] = definition + }.to raise_error(Puppet::Error, /Invalid message-ttl value.*future/) + end + + it 'should accept and convert the max-length value' do + definition = {'max-length' => '1800000'} + @policy[:definition] = definition + @policy[:definition]['max-length'].should be_a(Fixnum) + @policy[:definition]['max-length'].should == 1800000 + end + + it 'should not accept non-numeric max-length value' do + definition = {'max-length' => 'future'} + expect { + @policy[:definition] = definition + }.to raise_error(Puppet::Error, /Invalid max-length value.*future/) + end end diff --git a/puphpet/puppet/modules/rabbitmq/templates/rabbitmq.config.erb b/puphpet/puppet/modules/rabbitmq/templates/rabbitmq.config.erb index 4e2154e..8a7502f 100644 --- a/puphpet/puppet/modules/rabbitmq/templates/rabbitmq.config.erb +++ b/puphpet/puppet/modules/rabbitmq/templates/rabbitmq.config.erb @@ -12,9 +12,17 @@ {cluster_nodes, {[<%= @cluster_nodes.map { |n| "\'rabbit@#{n}\'" }.join(', ') %>], <%= @cluster_node_type %>}}, {cluster_partition_handling, <%= @cluster_partition_handling %>}, <% end -%> -<%- if @tcp_keepalive -%> - {tcp_listen_options, [{keepalive, true}]}, -<%- end -%> + {tcp_listen_options, + [binary, + <%- if @tcp_keepalive -%> + {keepalive, true}, + <%- end -%> + {packet, raw}, + {reuseaddr, true}, + {backlog, 128}, + {nodelay, true}, + {exit_on_close, false}] + }, <%- if @ssl_only -%> {tcp_listeners, []}, <%- elsif @interface != 'UNSET' -%> @@ -59,10 +67,12 @@ <%- if @admin_enable -%>, {rabbitmq_management, [ {listener, [ -<%- if @ssl -%> +<%- if @ssl && @management_ssl -%> {port, <%= @ssl_management_port %>}, {ssl, true}, - {ssl_opts, [<%- if @ssl_cacert != 'UNSET' -%>{cacertfile, "<%= @ssl_cacert %>"},<%- end -%> + {ssl_opts, [<%- if @ssl_cacert != 'UNSET' %> + {cacertfile, "<%= @ssl_cacert %>"}, + <%- end -%> {certfile, "<%= @ssl_cert %>"}, {keyfile, "<%= @ssl_key %>"} @@ -84,8 +94,13 @@ <% if @config_stomp -%>, % Configure the Stomp Plugin listening port {rabbitmq_stomp, [ + <%- if @stomp_ssl_only -%> + {tcp_listeners, []} + <%- else -%> {tcp_listeners, [<%= @stomp_port %>]} - <%- if @ssl && @ssl_stomp_port -%>, + <%- end -%> + <%- if @ssl && @ssl_stomp_port -%> + , {ssl_listeners, [<%= @ssl_stomp_port %>]} <%- end -%> ]} diff --git a/puphpet/puppet/modules/rabbitmq/templates/rabbitmqadmin.conf.erb b/puphpet/puppet/modules/rabbitmq/templates/rabbitmqadmin.conf.erb index d76c811..5ea629c 100644 --- a/puphpet/puppet/modules/rabbitmq/templates/rabbitmqadmin.conf.erb +++ b/puphpet/puppet/modules/rabbitmq/templates/rabbitmqadmin.conf.erb @@ -1,5 +1,5 @@ [default] -<% if @ssl -%> +<% if @ssl && @management_ssl -%> ssl = True port = <%= @ssl_management_port %> <% else -%> diff --git a/puphpet/puppet/modules/redis/.fixtures.yml b/puphpet/puppet/modules/redis/.fixtures.yml new file mode 100644 index 0000000..d42da4b --- /dev/null +++ b/puphpet/puppet/modules/redis/.fixtures.yml @@ -0,0 +1,9 @@ +fixtures: + repositories: + apt: 'git://github.com/puppetlabs/puppetlabs-apt.git' + stdlib: 'git://github.com/puppetlabs/puppetlabs-stdlib.git' + epel: 'https://github.com/stahnma/puppet-module-epel.git' + + symlinks: + redis: "#{source_dir}" + diff --git a/puphpet/puppet/modules/redis/.gitignore b/puphpet/puppet/modules/redis/.gitignore new file mode 100644 index 0000000..7a03248 --- /dev/null +++ b/puphpet/puppet/modules/redis/.gitignore @@ -0,0 +1,9 @@ +*.swp +.DS_Store +.vagrant/ +.yardoc +Gemfile.lock +doc +log/ +pkg +spec/fixtures diff --git a/puphpet/puppet/modules/redis/.puppet-lint.rc b/puphpet/puppet/modules/redis/.puppet-lint.rc new file mode 100644 index 0000000..7ffd5ff --- /dev/null +++ b/puphpet/puppet/modules/redis/.puppet-lint.rc @@ -0,0 +1,2 @@ +--with-filename +#--no-80chars-check diff --git a/puphpet/puppet/modules/redis/.travis.yml b/puphpet/puppet/modules/redis/.travis.yml index 079eb44..98bff05 100644 --- a/puphpet/puppet/modules/redis/.travis.yml +++ b/puphpet/puppet/modules/redis/.travis.yml @@ -1,24 +1,37 @@ --- language: ruby +sudo: false + rvm: -- 1.8.7 -- 1.9.3 + - 1.9.3 + - 2.0.0 + - 2.1.3 + +matrix: + allow_failures: + - env: PUPPET_VERSION="3.7" FUTURE_PARSER="yes" + - env: PUPPET_VERSION="3.8" FUTURE_PARSER="yes" + +before_install: + - 'gem install bundler' + script: -- git clone -q git://github.com/puppetlabs/ghpublisher.git .forge-releng -- .forge-releng/publish -branches: - only: - - master + - bundle install + - bundle update + - bundle exec rake + env: - global: - - PUBLISHER_LOGIN=fsalum - - secure: "DENnYQVOgU9VOxYGjKsCdsoCNeZ42yf751SFhK9s7Fmu790KiQvnY7Vjs+Sj\nrQ3xYXProkMYtx+KVbtzQo02oSYRF+sVYyBza3066bir0GK1YPdgrpT9Q3vo\nuT4+kfaeJK8StiBRWvPlyY3QrDbVsnIuQ+NxBFxjnZdDg350G8Q=" - matrix: - - PUPPET_VERSION=2.7.25 - - PUPPET_VERSION=3.1.1 - - PUPPET_VERSION=3.2.4 - - PUPPET_VERSION=3.3.2 - - PUPPET_VERSION=3.4.2 -notifications: - email: false -gemfile: Gemfile + - PUPPET_VERSION="3.0" + - PUPPET_VERSION="3.1" + - PUPPET_VERSION="3.2" + - PUPPET_VERSION="3.3" + - PUPPET_VERSION="3.4" + - PUPPET_VERSION="3.5" + - PUPPET_VERSION="3.6" + - PUPPET_VERSION="3.7" + - PUPPET_VERSION="3.7" FUTURE_PARSER="yes" + - PUPPET_VERSION="3.8" + - PUPPET_VERSION="3.8" FUTURE_PARSER="yes" + - PUPPET_VERSION="4.0" + - PUPPET_VERSION="4.1" + - PUPPET_VERSION="4.2" diff --git a/puphpet/puppet/modules/redis/CHANGELOG b/puphpet/puppet/modules/redis/CHANGELOG deleted file mode 100644 index 02800f9..0000000 --- a/puphpet/puppet/modules/redis/CHANGELOG +++ /dev/null @@ -1,63 +0,0 @@ -## fsalum-redis changelog - -Release notes for the fsalum-redis module. - ------------------------------------------- - -#### 0.0.11 - 2014-02-19 - -* system_sysctl parameter for redis class (@tehmaspc) - -#### 0.0.10 - 2014-02-19 - -* Allow conf_bind to be unset (@stevelacey) -* Changing default of glueoutputbuf to UNSET (@tehmaspc) - -#### 0.0.9 - 2014-01-09 - -* Add quotes around all instances of UNSET (@charlesdunbar) - -#### 0.0.8 - 2013-12-20 - -* Setting mode permission for conf_dir (@KlavsKlavsen) - -#### 0.0.7 - 2013-12-11 - -* Add glueoutputbuf config option (@kryptx) -* Add support for Amazon Linux AMI (@mattboston) - -#### 0.0.6 - 2013-08-01 - -* Install package before poking config (@doismellburning) - -#### 0.0.5 - 2013-06-06 - -* Fix Puppet 3.2.1 deprecation warnings (@ripienaar) -* Fix duplicate entry for logrotate on Debian/RHEL using different paths (@arthurfurlan) -* Add $conf_nosave parameter (@fsalum) -* Minor changes to params variables (@fsalum) -* Update CHANGELOG format - ------------------------------------------- - -#### 0.0.4 - 2013-04-18 - -* Creates conf_dir directory if it doesn't exist - ------------------------------------------- - -#### 0.0.3 - 2013-02-25 - -* Fixing redis.conf less options on Debian - ------------------------------------------- - -#### 0.0.2 - 2013-02-25 - -* Fixing redis.conf location for Debian - ------------------------------------------- - -#### 0.0.1 - 2013-02-25 - -* Initial Forge release diff --git a/puphpet/puppet/modules/redis/Gemfile b/puphpet/puppet/modules/redis/Gemfile index 2df03ec..38f9229 100644 --- a/puphpet/puppet/modules/redis/Gemfile +++ b/puphpet/puppet/modules/redis/Gemfile @@ -1,7 +1,30 @@ -source :rubygems +source 'https://rubygems.org' -puppetversion = ENV.key?('PUPPET_VERSION') ? "= #{ENV['PUPPET_VERSION']}" : ['>= 2.7'] +# special dependencies for Ruby 1.8 +# since there are still several OSes with it +if RUBY_VERSION =~ /^1\.8\./ + gem 'rspec-core', '~> 3.1.7' + gem 'nokogiri', '~> 1.5.0' +end -gem 'rake' -gem 'puppet-lint' +puppetversion = ENV.key?('PUPPET_VERSION') ? "~> #{ENV['PUPPET_VERSION']}" : ['>= 3.2.1'] gem 'puppet', puppetversion + +if puppetversion =~ /^3/ + ## rspec-hiera-puppet is puppet 3 only + gem 'rspec-hiera-puppet', '>=1.0.0' +end + +facterversion = ENV.key?('FACTER_VERSION') ? "~> #{ENV['FACTER_VERSION']}" : ['>= 1.7.1'] + +gem 'facter', facterversion + +gem 'rake' +gem 'rspec' +gem 'puppet-lint', '>=0.3.2' +gem 'rspec-puppet', '>=0.1.6' +gem 'puppetlabs_spec_helper', '>=0.4.1' + +gem 'beaker-rspec' +gem 'bundler', '<= 1.10.5' +gem 'vagrant-wrapper' diff --git a/puphpet/puppet/modules/redis/LICENSE b/puphpet/puppet/modules/redis/LICENSE index f31e47d..b58f924 100644 --- a/puphpet/puppet/modules/redis/LICENSE +++ b/puphpet/puppet/modules/redis/LICENSE @@ -1,15 +1,14 @@ -Copyright (C) 2012 Felipe Salum + Copyright (C) 2012 Tom De Vylder -Felipe Salum can be contacted at: fsalum@gmail.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 -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 - 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. -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. diff --git a/puphpet/puppet/modules/redis/Modulefile b/puphpet/puppet/modules/redis/Modulefile deleted file mode 100644 index 3d9432e..0000000 --- a/puphpet/puppet/modules/redis/Modulefile +++ /dev/null @@ -1,13 +0,0 @@ -name 'fsalum-redis' -version '0.0.11' -source 'git://github.com/fsalum/puppet-redis.git' -author 'Felipe Salum' -license 'Apache License, Version 2.0' -summary 'Puppet module for Redis Server' -description 'Module to install and configure a Redis server' -project_page 'https://github.com/fsalum/puppet-redis' - -## Add dependencies, if any: - -# https://forge.puppetlabs.com/thias/sysctl -dependency 'thias/sysctl', '0.3.0' diff --git a/puphpet/puppet/modules/redis/README.md b/puphpet/puppet/modules/redis/README.md index 3fcd7d4..9c4e12e 100644 --- a/puphpet/puppet/modules/redis/README.md +++ b/puphpet/puppet/modules/redis/README.md @@ -1,57 +1,93 @@ -Redis Module for Puppet -======================= -[![Build Status](https://secure.travis-ci.org/fsalum/puppet-redis.png)](http://travis-ci.org/fsalum/puppet-redis) +# Puppet Redis -This module installs and manages a Redis server. All redis.conf options are -accepted in the parameterized class. +## Build status -Operating System ----------------- +[![Build Status](https://travis-ci.org/arioch/puppet-redis.png?branch=master)](https://travis-ci.org/arioch/puppet-redis) -Tested on CentOS 6.3 and Debian Squeeze. +## Example usage -Quick Start ------------ +### Standalone -Use the default parameters: + class { 'redis':; + } - class { 'redis': } +### Master node -To change the port and listening network interface: + class { 'redis': + bind => '10.0.1.1'; + #masterauth => 'secret'; + } + +### Slave node class { 'redis': - conf_port => '6379', - conf_bind => '0.0.0.0', + bind => '10.0.1.2', + slaveof => '10.0.1.1 6379'; + #masterauth => 'secret'; } -Parameters ----------- +### Redis 3.0 Clustering + + class { 'redis': + bind => '10.0.1.2', + appendonly => true, + cluster_enabled => true, + cluster_config_file => 'nodes.conf', + cluster_node_timeout => 5000, + } -Check the [init.pp](https://github.com/fsalum/puppet-redis/blob/master/manifests/init.pp) file for a complete list of parameters accepted. +### Manage repositories -To enable and set important Linux kernel sysctl parameters as described in the [Redis Admin Guide](http://redis.io/topics/admin) - use the following configuration option: +Disabled by default but if you really want the module to manage the required +repositories you can use this snippet: class { 'redis': - system_sysctl => true + manage_repo => true, } -By default, this sysctl parameter will not be enabled. Furthermore, you will need the sysctl module defined in the [Modulefile](https://github.com/fsalum/puppet-redis/blob/master/Modulefile) file. +On Ubuntu, "chris-lea/redis-server" ppa repo will be added. You can change it by using ppa_repo parameter: + + class { 'redis': + manage_repo => true, + ppa_repo => 'ppa:rwky/redis', + } +### Redis Sentinel + +Optionally install and configuration a redis-sentinel server. + +With default settings: + + class { 'redis::sentinel':} + +With adjustments: + + class { 'redis::sentinel': + master_name => 'cow', + redis_host => '192.168.1.5', + failover_timeout => 30000, + } + +## Unit testing + +Plain RSpec: + + $ rake spec -Copyright and License ---------------------- +Using bundle: -Copyright (C) 2012 Felipe Salum + $ bundle exec rake spec -Felipe Salum can be contacted at: fsalum@gmail.com +Test against a specific Puppet or Facter version: -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 + $ PUPPET_VERSION=3.2.1 bundle update && bundle exec rake spec + $ PUPPET_VERSION=2.7.19 bundle update && bundle exec rake spec + $ FACTER_VERSION=1.6.8 bundle update && bundle exec rake spec - http://www.apache.org/licenses/LICENSE-2.0 +## Contributing - 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. +* Fork it +* Create a feature branch (`git checkout -b my-new-feature`) +* Run rspec tests (`bundle exec rake spec`) +* Commit your changes (`git commit -am 'Added some feature'`) +* Push to the branch (`git push origin my-new-feature`) +* Create new Pull Request diff --git a/puphpet/puppet/modules/redis/Rakefile b/puphpet/puppet/modules/redis/Rakefile index d29667f..2fcf44c 100644 --- a/puphpet/puppet/modules/redis/Rakefile +++ b/puphpet/puppet/modules/redis/Rakefile @@ -1,6 +1,16 @@ -require 'puppet-lint/tasks/puppet-lint' +require 'rake' +require 'puppetlabs_spec_helper/rake_tasks' -PuppetLint.configuration.send("disable_80chars") -PuppetLint.configuration.send('disable_class_parameter_defaults') +RSpec::Core::RakeTask.new(:spec_verbose) do |t| + t.pattern = 'spec/*/*_spec.rb' + t.rspec_opts = File.read('spec/spec.opts').chomp || "" +end -task :default => :lint +task :test do + Rake::Task[:spec_prep].invoke + Rake::Task[:spec_verbose].invoke + Rake::Task[:spec_clean].invoke +end + + +task :default => [:spec, :lint] diff --git a/puphpet/puppet/modules/redis/Vagrantfile b/puphpet/puppet/modules/redis/Vagrantfile deleted file mode 100644 index 2c687ec..0000000 --- a/puphpet/puppet/modules/redis/Vagrantfile +++ /dev/null @@ -1,18 +0,0 @@ -VAGRANTFILE_API_VERSION = "2" -Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - config.vbguest.auto_update = false - config.hostmanager.enabled = false - - config.vm.define 'redis' do |node| - node.vm.box = "centos65" - node.vm.hostname = "redis.local" - node.vm.network :private_network, ip: "192.168.100.100" - node.vm.provision :shell, :inline => "yum install -y git && gem install librarian-puppet --no-ri --no-rdoc" - node.vm.provision :shell, :inline => "cd /vagrant ; librarian-puppet install --clean --path /etc/puppet/modules" - node.vm.provision :puppet do |puppet| - puppet.manifests_path = ["vm", "/etc/puppet/modules/redis/tests"] - puppet.manifest_file = "init.pp" - end - end - -end diff --git a/puphpet/puppet/modules/redis/manifests/config.pp b/puphpet/puppet/modules/redis/manifests/config.pp new file mode 100644 index 0000000..b0ff449 --- /dev/null +++ b/puphpet/puppet/modules/redis/manifests/config.pp @@ -0,0 +1,106 @@ +# = Class: redis::config +# +# This class provides configuration for Redis. +# +class redis::config { + $activerehashing = $::redis::activerehashing + $appendfsync = $::redis::appendfsync + $appendonly = $::redis::appendonly + $auto_aof_rewrite_min_size = $::redis::auto_aof_rewrite_min_size + $auto_aof_rewrite_percentage = $::redis::auto_aof_rewrite_percentage + $bind = $::redis::bind + $cluster_config_file = $::redis::cluster_config_file + $cluster_enabled = $::redis::cluster_enabled + $cluster_node_timeout = $::redis::cluster_node_timeout + $daemonize = $::redis::daemonize + $databases = $::redis::databases + $dbfilename = $::redis::dbfilename + $extra_config_file = $::redis::extra_config_file + $hash_max_ziplist_entries = $::redis::hash_max_ziplist_entries + $hash_max_ziplist_value = $::redis::hash_max_ziplist_value + $hz = $::redis::hz + $list_max_ziplist_entries = $::redis::list_max_ziplist_entries + $list_max_ziplist_value = $::redis::list_max_ziplist_value + $log_file = $::redis::log_file + $log_level = $::redis::log_level + $masterauth = $::redis::masterauth + $maxclients = $::redis::maxclients + $maxmemory = $::redis::maxmemory + $maxmemory_policy = $::redis::maxmemory_policy + $maxmemory_samples = $::redis::maxmemory_samples + $no_appendfsync_on_rewrite = $::redis::no_appendfsync_on_rewrite + $pid_file = $::redis::pid_file + $port = $::redis::port + $rdbcompression = $::redis::rdbcompression + $repl_timeout = $::redis::repl_timeout + $requirepass = $::redis::requirepass + $save_db_to_disk = $::redis::save_db_to_disk + $set_max_intset_entries = $::redis::set_max_intset_entries + $slave_read_only = $::redis::slave_read_only + $slave_serve_stale_data = $::redis::slave_serve_stale_data + $slaveof = $::redis::slaveof + $slowlog_log_slower_than = $::redis::slowlog_log_slower_than + $slowlog_max_len = $::redis::slowlog_max_len + $stop_writes_on_bgsave_error = $::redis::stop_writes_on_bgsave_error + $syslog_enabled = $::redis::syslog_enabled + $syslog_facility = $::redis::syslog_facility + $tcp_keepalive = $::redis::tcp_keepalive + $timeout = $::redis::timeout + $workdir = $::redis::workdir + $zset_max_ziplist_entries = $::redis::zset_max_ziplist_entries + $zset_max_ziplist_value = $::redis::zset_max_ziplist_value + + if $::redis::notify_service { + File { + owner => $::redis::config_owner, + group => $::redis::config_group, + mode => $::redis::config_file_mode, + notify => Service[$::redis::service_name] + } + } else { + File { + owner => $::redis::config_owner, + group => $::redis::config_group, + mode => $::redis::config_file_mode, + } + } + + file { + $::redis::config_dir: + ensure => directory, + mode => $::redis::config_dir_mode; + + $::redis::config_file: + ensure => present, + content => template($::redis::conf_template); + + $::redis::log_dir: + ensure => directory, + group => $::redis::service_group, + mode => $::redis::log_dir_mode, + owner => $::redis::service_user; + } + + # Adjust /etc/default/redis-server on Debian systems + case $::osfamily { + 'Debian': { + file { '/etc/default/redis-server': + ensure => present, + group => $::redis::config_group, + mode => $::redis::config_file_mode, + owner => $::redis::config_owner, + } + + if $::redis::ulimit { + augeas { 'redis ulimit' : + context => '/files/etc/default/redis-server', + changes => "set ULIMIT ${::redis::ulimit}", + } + } + } + + default: { + } + } +} + diff --git a/puphpet/puppet/modules/redis/manifests/init.pp b/puphpet/puppet/modules/redis/manifests/init.pp index 4185494..66dd6f5 100644 --- a/puphpet/puppet/modules/redis/manifests/init.pp +++ b/puphpet/puppet/modules/redis/manifests/init.pp @@ -1,160 +1,525 @@ -# == Class: redis +# = Class: redis # -# Install and configure a Redis server +# This class installs redis # -# === Parameters +# == Parameters: # -# All the redis.conf parameters can be passed to the class. -# See below for a complete list of parameters accepted. +# [*activerehashing*] +# Enable/disable active rehashing. # -# Check the README.md file for any further information about parameters for this class. +# Default: true # -# === Examples +# [*appendfsync*] +# Adjust fsync mode. +# Valid options: always, everysec, no. # -# class { redis: -# conf_port => '6380', -# conf_bind => '0.0.0.0', -# } +# Default: everysec # -# === Authors +# [*appendonly*] +# Enable/disable appendonly mode. # -# Felipe Salum +# Default: false # -# === Copyright +# [*auto_aof_rewrite_min_size*] +# Adjust minimum size for auto-aof-rewrite. # -# Copyright 2013 Felipe Salum, unless otherwise noted. +# Default: 64mb +# +# [*auto_aof_rewrite_percentage*] +# Adjust percentatge for auto-aof-rewrite. +# +# Default: 100 +# +# [*bind*] +# Configure which IP address to listen on. +# +# Default: 127.0.0.1 +# +# [*config_dir*] +# Directory containing the configuration files. +# +# Default: OS dependant +# +# [*config_dir_mode*] +# Adjust mode for directory containing configuration files. +# +# Default: 0755 +# +# [*config_file*] +# Adjust main configuration file. +# +# Default: OS dependant +# +# [*config_file_mode*] +# Adjust permissions for configuration files. +# +# Default: 0644 +# +# [*config_group*] +# Adjust filesystem group for config files. +# +# Default: OS dependant +# +# [*config_owner*] +# Adjust filesystem owner for config files. +# +# Default: OS dependant +# +# [*conf_template*] +# Define which template to use. +# +# Default: redis/redis.conf.erb +# +# [*daemonize*] +# Have Redis run as a daemon. +# +# Default: true +# +# [*databases*] +# Set the number of databases. +# +# Default: 16 +# +# [*dbfilename*] +# The filename where to dump the DB +# +# Default: dump.rdb +# +# [*extra_config_file*] +# Description +# +# Default: undef +# +# [*hash_max_ziplist_entries*] +# Set max ziplist entries for hashes. +# +# Default: 512 +# +# [*hash_max_ziplist_value*] +# Set max ziplist values for hashes. +# +# Default: 64 +# +# [*hz*] +# Set redis background tasks frequency +# +# Default: 10 +# +# [*list_max_ziplist_entries*] +# Set max ziplist entries for lists. +# +# Default: 512 +# +# [*list_max_ziplist_value*] +# Set max ziplist values for lists. +# +# Default: 64 +# +# [*log_dir*] +# Specify directory where to write log entries. +# +# Default: /var/log/redis +# +# [*log_dir_mode*] +# Adjust mode for directory containing log files. +# +# Default: 0755 +# +# [*log_file*] +# Specify file where to write log entries. +# +# Default: /var/log/redis/redis.log +# +# [*log_level*] +# Specify the server verbosity level. +# +# Default: notice +# +# [*manage_repo*] +# Enable/disable upstream repository configuration. +# +# Default: false +# +# [*masterauth*] +# If the master is password protected (using the "requirepass" configuration +# directive below) it is possible to tell the slave to authenticate before +# starting the replication synchronization process, otherwise the master will +# refuse the slave request. +# +# Default: undef +# +# [*maxclients*] +# Set the max number of connected clients at the same time. +# +# Default: 10000 +# +# [*maxmemory*] +# Don't use more memory than the specified amount of bytes. +# +# Default: undef +# +# [*maxmemory_policy*] +# How Redis will select what to remove when maxmemory is reached. +# You can select among five behaviors: +# +# volatile-lru -> remove the key with an expire set using an LRU algorithm +# allkeys-lru -> remove any key accordingly to the LRU algorithm +# volatile-random -> remove a random key with an expire set +# allkeys-random -> remove a random key, any key +# volatile-ttl -> remove the key with the nearest expire time (minor TTL) +# noeviction -> don't expire at all, just return an error on write operations +# +# Default: undef +# +# [*maxmemory_samples*] +# Select as well the sample size to check. +# +# Default: undef +# +# [*no_appendfsync_on_rewrite*] +# If you have latency problems turn this to 'true'. Otherwise leave it as +# 'false' that is the safest pick from the point of view of durability. +# +# Default: false +# +# [*notify_service*] +# You may disable service reloads when config files change if you +# have an external service (e.g. Monit) to manage it for you. +# +# Default: true +# +# [*package_ensure*] +# Default action for package. +# +# Default: present +# +# [*package_name*] +# Upstream package name. +# +# Default: OS dependant +# +# [*pid_file*] +# Where to store the pid. +# +# Default: /var/run/redis/redis-server.pid +# +# [*port*] +# Configure which port to listen on. +# +# Default: 6379 +# +# [*ppa_repo*] +# Specify upstream (Ubuntu) PPA entry. +# +# Default: ppa:chris-lea/redis-server +# +# [*rdbcompression*] +# Enable/disable compression of string objects using LZF when dumping. +# +# Default: true +# +# [*repl_ping_slave_period*] +# Slaves send PINGs to server in a predefined interval. It's possible +# to change this interval with the repl_ping_slave_period option. +# +# Default: 10 +# +# [*repl_timeout*] +# Set the replication timeout for: +# +# 1) Bulk transfer I/O during SYNC, from the point of view of slave. +# 2) Master timeout from the point of view of slaves (data, pings). +# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings). +# +# Default: 60 +# +# [*requirepass*] +# Require clients to issue AUTH before processing any +# other commands. +# +# Default: undef +# +#[*save_db_to_disk*] +# Set if save db to disk. +# +# Default: true +# +# [*service_manage*] +# Specify if the service should be part of the catalog. +# +# Default: true +# +# [*service_enable*] +# Enable/disable daemon at boot. +# +# Default: true +# +# [*service_ensure*] +# Specify if the server should be running. +# +# Default: running +# +# [*service_group*] +# Specify which group to run as. +# +# Default: OS dependant +# +# [*service_hasrestart*] +# Does the init script support restart? +# +# Default: OS dependant +# +# [*service_hasstatus*] +# Does the init script support status? +# +# Default: OS dependant +# +# [*service_name*] +# Specify the service name for Init or Systemd. +# +# Default: OS dependant +# +# [*service_provider*] +# Specify the service provider to use +# +# Default: undef +# +# [*service_user*] +# Specify which user to run as. +# +# Default: OS dependant +# +# [*set_max_intset_entries*] +# The following configuration setting sets the limit in the size of the +# set in order to use this special memory saving encoding. +# +# Default: 512 +# +# [*slave_read_only*] +# You can configure a slave instance to accept writes or not. +# +# Default: true +# +# [*slave_serve_stale_data*] +# When a slave loses its connection with the master, or when the replication +# is still in progress, the slave can act in two different ways: +# +# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will +# still reply to client requests, possibly with out of date data, or the +# data set may just be empty if this is the first synchronization. +# +# 2) if slave-serve-stale-data is set to 'no' the slave will reply with +# an error "SYNC with master in progress" to all the kind of commands +# but to INFO and SLAVEOF. +# +# Default: true +# +# [*slaveof*] +# Use slaveof to make a Redis instance a copy of another Redis server. +# +# Default: undef +# +# [*slowlog_log_slower_than*] +# Tells Redis what is the execution time, in microseconds, to exceed +# in order for the command to get logged. +# +# Default: 10000 +# +# [*slowlog_max_len*] +# Tells Redis what is the length to exceed in order for the command +# to get logged. +# +# Default: 1024 +# +# [*stop_writes_on_bgsave_error*] +# If false then Redis will continue to work as usual even if there +# are problems with disk, permissions, and so forth. +# +# Default: true +# +# [*syslog_enabled*] +# Enable/disable logging to the system logger. +# +# Default: undef +# +# [*syslog_facility*] +# Specify the syslog facility. +# Must be USER or between LOCAL0-LOCAL7. +# +# Default: undef +# +# [*tcp_keepalive*] +# TCP keepalive. +# +# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence +# of communication. This is useful for two reasons: +# +# 1) Detect dead peers. +# 2) Take the connection alive from the point of view of network +# equipment in the middle. +# +# On Linux, the specified value (in seconds) is the period used to send ACKs. +# Note that to close the connection the double of the time is needed. +# On other kernels the period depends on the kernel configuration. +# +# A reasonable value for this option is 60 seconds. +# +# [*timeout*] +# Close the connection after a client is idle for N seconds (0 to disable). +# +# Default: 0 +# +# [*ulimit*] +# Limit the use of system-wide resources. +# +# Default: 65536 +# +# [*workdir*] +# The DB will be written inside this directory, with the filename specified +# above using the 'dbfilename' configuration directive. +# +# Default: /var/lib/redis/ +# +# [*zset_max_ziplist_entries*] +# Set max entries for sorted sets. +# +# Default: 128 +# +# [*zset_max_ziplist_value*] +# Set max values for sorted sets. +# +# Default: 64 +# +# [*cluster_enabled*] +# Enables redis 3.0 cluster functionality +# +# Default: false +# +# [*cluster_config_file*] +# Config file for saving cluster nodes configuration. This file is never touched by humans. +# Only set if cluster_enabled is true +# +# Default: nodes.conf +# +# [*cluster_node_timeout*] +# Node timeout +# Only set if cluster_enabled is true +# +# Default: 5000 +# +# == Actions: +# - Install and configure Redis +# +# == Sample Usage: +# +# class { 'redis': } +# +# class { 'redis': +# manage_repo => true; +# } # class redis ( - $package_ensure = 'present', - $service_ensure = 'running', - $service_enable = true, - $system_sysctl = false, - $conf_daemonize = 'yes', - $conf_pidfile = 'UNSET', - $conf_port = '6379', - $conf_bind = '127.0.0.1', - $conf_timeout = '0', - $conf_loglevel = 'notice', - $conf_logfile = 'UNSET', - $conf_syslog_enabled = 'UNSET', - $conf_syslog_ident = 'UNSET', - $conf_syslog_facility = 'UNSET', - $conf_databases = '16', - $conf_save = 'UNSET', - $conf_nosave = 'UNSET', - $conf_rdbcompression = 'yes', - $conf_dbfilename = 'dump.rdb', - $conf_dir = '/var/lib/redis/', - $conf_slaveof = 'UNSET', - $conf_masterauth = 'UNSET', - $conf_slave_server_stale_data = 'yes', - $conf_repl_ping_slave_period = '10', - $conf_repl_timeout = '60', - $conf_requirepass = 'UNSET', - $conf_maxclients = 'UNSET', - $conf_maxmemory = 'UNSET', - $conf_maxmemory_policy = 'UNSET', - $conf_maxmemory_samples = 'UNSET', - $conf_appendonly = 'no', - $conf_appendfilename = 'UNSET', - $conf_appendfsync = 'everysec', - $conf_no_appendfsync_on_rewrite = 'no', - $conf_auto_aof_rewrite_percentage = '100', - $conf_auto_aof_rewrite_min_size = '64mb', - $conf_slowlog_log_slower_than = '10000', - $conf_slowlog_max_len = '1024', - $conf_vm_enabled = 'no', - $conf_vm_swap_file = '/tmp/redis.swap', - $conf_vm_max_memory = '0', - $conf_vm_page_size = '32', - $conf_vm_pages = '134217728', - $conf_vm_max_threads = '4', - $conf_hash_max_zipmap_entries = '512', - $conf_hash_max_zipmap_value = '64', - $conf_list_max_ziplist_entries = '512', - $conf_list_max_ziplist_value = '64', - $conf_set_max_intset_entries = '512', - $conf_zset_max_ziplist_entries = '128', - $conf_zset_max_ziplist_value = '64', - $conf_activerehashing = 'yes', - $conf_include = 'UNSET', - $conf_glueoutputbuf = 'UNSET', -) { - - include redis::params - - $conf_template = $redis::params::conf_template - $conf_redis = $redis::params::conf - $conf_logrotate = $redis::params::conf_logrotate - $package = $redis::params::package - $service = $redis::params::service - - $conf_pidfile_real = $conf_pidfile ? { - 'UNSET' => $::redis::params::pidfile, - default => $conf_pidfile, - } - - $conf_logfile_real = $conf_logfile ? { - 'UNSET' => $::redis::params::logfile, - default => $conf_logfile, - } - - package { 'redis': - ensure => $package_ensure, - name => $package, - } - - service { 'redis': - ensure => $service_ensure, - name => $service, - enable => $service_enable, - hasrestart => true, - hasstatus => true, - require => Package['redis'], - } - - file { $conf_redis: - path => $conf_redis, - content => template("redis/${conf_template}"), - owner => root, - group => root, - mode => '0644', - require => Package['redis'], - notify => Service['redis'], - } + $activerehashing = $::redis::params::activerehashing, + $appendfsync = $::redis::params::appendfsync, + $appendonly = $::redis::params::appendonly, + $auto_aof_rewrite_min_size = $::redis::params::auto_aof_rewrite_min_size, + $auto_aof_rewrite_percentage = $::redis::params::auto_aof_rewrite_percentage, + $bind = $::redis::params::bind, + $conf_template = $::redis::params::conf_template, + $config_dir = $::redis::params::config_dir, + $config_dir_mode = $::redis::params::config_dir_mode, + $config_file = $::redis::params::config_file, + $config_file_mode = $::redis::params::config_file_mode, + $config_group = $::redis::params::config_group, + $config_owner = $::redis::params::config_owner, + $daemonize = $::redis::params::daemonize, + $databases = $::redis::params::databases, + $dbfilename = $::redis::params::dbfilename, + $extra_config_file = $::redis::params::extra_config_file, + $hash_max_ziplist_entries = $::redis::params::hash_max_ziplist_entries, + $hash_max_ziplist_value = $::redis::params::hash_max_ziplist_value, + $hz = $::redis::params::hz, + $list_max_ziplist_entries = $::redis::params::list_max_ziplist_entries, + $list_max_ziplist_value = $::redis::params::list_max_ziplist_value, + $log_dir = $::redis::params::log_dir, + $log_dir_mode = $::redis::params::log_dir_mode, + $log_file = $::redis::params::log_file, + $log_level = $::redis::params::log_level, + $manage_repo = $::redis::params::manage_repo, + $masterauth = $::redis::params::masterauth, + $maxclients = $::redis::params::maxclients, + $maxmemory = $::redis::params::maxmemory, + $maxmemory_policy = $::redis::params::maxmemory_policy, + $maxmemory_samples = $::redis::params::maxmemory_samples, + $no_appendfsync_on_rewrite = $::redis::params::no_appendfsync_on_rewrite, + $notify_service = $::redis::params::notify_service, + $package_ensure = $::redis::params::package_ensure, + $package_name = $::redis::params::package_name, + $pid_file = $::redis::params::pid_file, + $port = $::redis::params::port, + $ppa_repo = $::redis::params::ppa_repo, + $rdbcompression = $::redis::params::rdbcompression, + $repl_ping_slave_period = $::redis::params::repl_ping_slave_period, + $repl_timeout = $::redis::params::repl_timeout, + $requirepass = $::redis::params::requirepass, + $save_db_to_disk = $::redis::params::save_db_to_disk, + $service_enable = $::redis::params::service_enable, + $service_ensure = $::redis::params::service_ensure, + $service_group = $::redis::params::service_group, + $service_hasrestart = $::redis::params::service_hasrestart, + $service_hasstatus = $::redis::params::service_hasstatus, + $service_manage = $::redis::params::service_manage, + $service_name = $::redis::params::service_name, + $service_provider = $::redis::params::service_provider, + $service_user = $::redis::params::service_user, + $set_max_intset_entries = $::redis::params::set_max_intset_entries, + $slave_read_only = $::redis::params::slave_read_only, + $slave_serve_stale_data = $::redis::params::slave_serve_stale_data, + $slaveof = $::redis::params::slaveof, + $slowlog_log_slower_than = $::redis::params::slowlog_log_slower_than, + $slowlog_max_len = $::redis::params::slowlog_max_len, + $stop_writes_on_bgsave_error = $::redis::params::stop_writes_on_bgsave_error, + $syslog_enabled = $::redis::params::syslog_enabled, + $syslog_facility = $::redis::params::syslog_facility, + $tcp_keepalive = $::redis::params::tcp_keepalive, + $timeout = $::redis::params::timeout, + $ulimit = $::redis::params::ulimit, + $workdir = $::redis::params::workdir, + $zset_max_ziplist_entries = $::redis::params::zset_max_ziplist_entries, + $zset_max_ziplist_value = $::redis::params::zset_max_ziplist_value, + $cluster_enabled = $::redis::params::cluster_enabled, + $cluster_config_file = $::redis::params::cluster_config_file, + $cluster_node_timeout = $::redis::params::cluster_node_timeout, +) inherits redis::params { + anchor { 'redis::begin': } + anchor { 'redis::end': } - file { $conf_logrotate: - path => $conf_logrotate, - content => template('redis/redis.logrotate.erb'), - owner => root, - group => root, - mode => '0644', - } - - exec { $conf_dir: - path => '/bin:/usr/bin:/sbin:/usr/sbin', - command => "mkdir -p ${conf_dir}", - user => root, - group => root, - creates => $conf_dir, - before => Service['redis'], - require => Package['redis'], - notify => Service['redis'], - } + include redis::preinstall + include redis::install + include redis::config + include redis::service - file { $conf_dir: - ensure => directory, - owner => redis, - group => redis, - mode => 0755, - before => Service['redis'], - require => Exec[$conf_dir], + if $::redis::notify_service { + Anchor['redis::begin'] -> + Class['redis::preinstall'] -> + Class['redis::install'] -> + Class['redis::config'] ~> + Class['redis::service'] -> + Anchor['redis::end'] + } else { + Anchor['redis::begin'] -> + Class['redis::preinstall'] -> + Class['redis::install'] -> + Class['redis::config'] -> + Class['redis::service'] -> + Anchor['redis::end'] } - if ( $system_sysctl == true ) { - # add necessary kernel parameters - # see the redis admin guide here: http://redis.io/topics/admin - sysctl { 'vm.overcommit_memory': value => '1' } + # Sanity check + if $::redis::slaveof { + if $::redis::bind =~ /^127.0.0./ { + fail "Replication is not possible when binding to ${::redis::bind}." + } } - } + diff --git a/puphpet/puppet/modules/redis/manifests/install.pp b/puphpet/puppet/modules/redis/manifests/install.pp new file mode 100644 index 0000000..a4c4315 --- /dev/null +++ b/puphpet/puppet/modules/redis/manifests/install.pp @@ -0,0 +1,12 @@ +# = Class: redis::install +# +# This class installs the application. +# +class redis::install { + unless defined(Package['$::redis::package_name']) { + ensure_resource('package', $::redis::package_name, { + 'ensure' => $::redis::package_ensure + }) + } +} + diff --git a/puphpet/puppet/modules/redis/manifests/params.pp b/puphpet/puppet/modules/redis/manifests/params.pp index 8983eea..d0697fc 100644 --- a/puphpet/puppet/modules/redis/manifests/params.pp +++ b/puphpet/puppet/modules/redis/manifests/params.pp @@ -1,39 +1,200 @@ -# Class: redis::params +# = Class: redis::params # -# This class configures parameters for the puppet-redis module. -# -# Parameters: -# -# Actions: -# -# Requires: -# -# Sample Usage: +# This class provides a number of parameters. # class redis::params { + # Generic + $manage_repo = false - case $::operatingsystem { - 'centos', 'redhat', 'fedora', 'amazon': { - $package = 'redis' - $service = 'redis' - $conf = '/etc/redis.conf' - $conf_template = 'redis.rhel.conf.erb' - $conf_logrotate = '/etc/logrotate.d/redis' - $pidfile = '/var/run/redis/redis.pid' - $logfile = '/var/log/redis/redis.log' + # redis.conf.erb + $activerehashing = true + $appendfsync = 'everysec' + $appendonly = false + $auto_aof_rewrite_min_size = '64mb' + $auto_aof_rewrite_percentage = 100 + $bind = '127.0.0.1' + $conf_template = 'redis/redis.conf.erb' + $databases = 16 + $dbfilename = 'dump.rdb' + $extra_config_file = undef + $hash_max_ziplist_entries = 512 + $hash_max_ziplist_value = 64 + $hz = 10 + $list_max_ziplist_entries = 512 + $list_max_ziplist_value = 64 + $log_dir = '/var/log/redis' + $log_file = '/var/log/redis/redis.log' + $log_level = 'notice' + $maxclients = 10000 + $maxmemory = undef + $maxmemory_policy = undef + $maxmemory_samples = undef + $no_appendfsync_on_rewrite = false + $notify_service = true + $pid_file = '/var/run/redis/redis-server.pid' + $port = 6379 + $rdbcompression = true + $requirepass = undef + $save_db_to_disk = true + $sentinel_auth_pass = undef + $sentinel_config_file_mode = '0644' + $sentinel_config_group = 'root' + $sentinel_config_owner = 'redis' + $sentinel_conf_template = 'redis/redis-sentinel.conf.erb' + $sentinel_down_after = 30000 + $sentinel_failover_timeout = 180000 + $sentinel_master_name = 'mymaster' + $sentinel_parallel_sync = 1 + $sentinel_port = 26379 + $sentinel_quorum = 2 + $sentinel_service_name = 'redis-sentinel' + $sentinel_working_dir = '/tmp' + $sentinel_init_template = 'redis/redis-sentinel.init.erb' + $sentinel_pid_file = '/var/run/redis/redis-sentinel.pid' + $sentinel_notification_script = undef + $service_provider = undef + $set_max_intset_entries = 512 + $slowlog_log_slower_than = 10000 + $slowlog_max_len = 1024 + $stop_writes_on_bgsave_error = true + $syslog_enabled = undef + $syslog_facility = undef + $tcp_keepalive = 0 + $timeout = 0 + $ulimit = 65536 + $workdir = '/var/lib/redis/' + $zset_max_ziplist_entries = 128 + $zset_max_ziplist_value = 64 + + # redis.conf.erb - replication + $masterauth = undef + $repl_ping_slave_period = 10 + $repl_timeout = 60 + $slave_read_only = true + $slave_serve_stale_data = true + $slaveof = undef + + # redis.conf.erb - redis 3.0 clustering + $cluster_enabled = false + $cluster_config_file = 'nodes.conf' + $cluster_node_timeout = 5000 + + case $::osfamily { + 'Debian': { + $config_dir = '/etc/redis' + $config_dir_mode = '0755' + $config_file = '/etc/redis/redis.conf' + $config_file_mode = '0644' + $config_group = 'root' + $config_owner = 'redis' + $daemonize = true + $log_dir_mode = '0755' + $package_ensure = 'present' + $package_name = 'redis-server' + $sentinel_config_file = '/etc/redis/redis-sentinel.conf' + $sentinel_config_file_orig = '/etc/redis/redis-sentinel.conf.puppet' + $sentinel_daemonize = true + $sentinel_init_script = '/etc/init.d/redis-sentinel' + $sentinel_package_name = 'redis-server' + $sentinel_package_ensure = 'present' + $service_manage = true + $service_enable = true + $service_ensure = 'running' + $service_group = 'redis' + $service_hasrestart = true + $service_hasstatus = false + $service_name = 'redis-server' + $service_user = 'redis' + $ppa_repo = 'ppa:chris-lea/redis-server' } - 'ubuntu', 'debian': { - $package = 'redis-server' - $service = 'redis-server' - $conf = '/etc/redis/redis.conf' - $conf_template = 'redis.debian.conf.erb' - $conf_logrotate = '/etc/logrotate.d/redis-server' - $pidfile = '/var/run/redis/redis-server.pid' - $logfile = '/var/log/redis/redis-server.log' + + 'RedHat': { + $config_dir = '/etc/redis' + $config_dir_mode = '0755' + $config_file = '/etc/redis.conf' + $config_file_mode = '0644' + $config_group = 'root' + $config_owner = 'redis' + $daemonize = true + $log_dir_mode = '0755' + $package_ensure = 'present' + $package_name = 'redis' + $sentinel_config_file = '/etc/redis-sentinel.conf' + $sentinel_config_file_orig = '/etc/redis-sentinel.conf.puppet' + $sentinel_daemonize = false + $sentinel_init_script = undef + $sentinel_package_name = 'redis' + $sentinel_package_ensure = 'present' + $service_manage = true + $service_enable = true + $service_ensure = 'running' + $service_group = 'redis' + $service_hasrestart = true + $service_hasstatus = true + $service_name = 'redis' + $service_user = 'redis' + $ppa_repo = undef } + + 'FreeBSD': { + $config_dir = '/usr/local/etc/redis' + $config_dir_mode = '0755' + $config_file = '/usr/local/etc/redis.conf' + $config_file_mode = '0644' + $config_group = 'wheel' + $config_owner = 'redis' + $daemonize = true + $log_dir_mode = '0755' + $package_ensure = 'present' + $package_name = 'redis' + $sentinel_config_file = '/usr/local/etc/redis-sentinel.conf' + $sentinel_config_file_orig = '/usr/local/etc/redis-sentinel.conf.puppet' + $sentinel_daemonize = true + $sentinel_init_script = undef + $sentinel_package_name = 'redis' + $sentinel_package_ensure = 'present' + $service_manage = true + $service_enable = true + $service_ensure = 'running' + $service_group = 'redis' + $service_hasrestart = true + $service_hasstatus = true + $service_name = 'redis' + $service_user = 'redis' + $ppa_repo = undef + } + + 'Suse': { + $config_dir = '/etc/redis' + $config_dir_mode = '0750' + $config_file = '/etc/redis/redis-server.conf' + $config_file_mode = '0644' + $config_group = 'redis' + $config_owner = 'redis' + $daemonize = true + $log_dir_mode = '0750' + $package_ensure = 'present' + $package_name = 'redis' + $sentinel_config_file = '/etc/redis/redis-sentinel.conf' + $sentinel_config_file_orig = '/etc/redis/redis-sentinel.conf.puppet' + $sentinel_daemonize = true + $sentinel_init_script = undef + $sentinel_package_name = 'redis' + $sentinel_package_ensure = 'present' + $service_manage = true + $service_enable = true + $service_ensure = 'running' + $service_group = 'redis' + $service_hasrestart = true + $service_hasstatus = true + $service_name = 'redis' + $service_user = 'redis' + $ppa_repo = undef + } + default: { - fail("Unsupported osfamily: ${::osfamily} operatingsystem: ${::operatingsystem}, module ${module_name} only support osfamily RedHat and Debian") + fail "Operating system ${::operatingsystem} is not supported yet." } } - } + diff --git a/puphpet/puppet/modules/redis/manifests/preinstall.pp b/puphpet/puppet/modules/redis/manifests/preinstall.pp new file mode 100644 index 0000000..5f3ce6a --- /dev/null +++ b/puphpet/puppet/modules/redis/manifests/preinstall.pp @@ -0,0 +1,82 @@ +# = Class: redis::preinstall +# +# This class provides anything required by the install class. +# Such as package repositories. +# +class redis::preinstall { + if $::redis::manage_repo { + case $::operatingsystem { + 'RedHat', 'CentOS', 'Scientific', 'OEL': { + if (versioncmp($::operatingsystemrelease, '7.0') == -1) { + $rpm_url = $::operatingsystemrelease ? { + /^5/ => "http://download.powerstack.org/5/${::architecture}/", + /^6/ => "http://download.powerstack.org/6/${::architecture}/", + default => Fail['Operating system or release not supported.'], + } + + $rpm_gpgkey = $::operatingsystemmajrelease ? { + '5' => 'https://raw.githubusercontent.com/santisaez/powerstack/master/RPM-GPG-KEY-powerstack', + '6' => 'https://raw.githubusercontent.com/santisaez/powerstack/master/RPM-GPG-KEY-powerstack', + default => Fail['Operating system or release not supported.'], + } + + yumrepo { 'powerstack': + descr => 'PowerStack for CentOS', + baseurl => $rpm_url, + gpgkey => $rpm_gpgkey, + enabled => 1, + gpgcheck => 1; + } + } + + if (versioncmp($::operatingsystemmajrelease, '7') >= 0) { + require ::epel + } + } + + 'Amazon': { + $rpm_url = $::operatingsystemmajrelease ? { + '3' => "http://download.powerstack.org/6/${::architecture}/", + default => Fail['Operating system or release version not supported.'], + } + + $rpm_gpgkey = $::operatingsystemmajrelease ? { + '3' => 'https://raw.githubusercontent.com/santisaez/powerstack/master/RPM-GPG-KEY-powerstack', + default => Fail['Operating system or release version not supported.'], + } + + yumrepo { 'powerstack': + descr => 'PowerStack for CentOS', + baseurl => $rpm_url, + gpgkey => $rpm_gpgkey, + enabled => 1, + gpgcheck => 1; + } + } + + 'Debian': { + include apt + apt::key { 'dotdeb': + id => '89DF5277', + content => 'http://www.dotdeb.org/dotdeb.gpg', + } + + apt::source { 'dotdeb': + location => 'http://packages.dotdeb.org', + release => $::lsbdistcodename, + repos => 'all', + require => Apt::Key['dotdeb'], + } + } + + 'Ubuntu': { + include apt + apt::ppa { $::redis::ppa_repo: } + } + + default: { + } + } + } +} + diff --git a/puphpet/puppet/modules/redis/manifests/sentinel.pp b/puphpet/puppet/modules/redis/manifests/sentinel.pp new file mode 100644 index 0000000..4f36638 --- /dev/null +++ b/puphpet/puppet/modules/redis/manifests/sentinel.pp @@ -0,0 +1,230 @@ +# = Class: redis::sentinel +# +# This class installs redis-sentinel +# +# == Parameters: +# +# +# [*auth_pass*] +# The password to use to authenticate with the master and slaves. +# +# Default: undef +# +# [*config_file*] +# The location and name of the sentinel config file. +# +# Default for deb: /etc/redis/redis-sentinel.conf +# Default for rpm: /etc/redis-sentinel.conf +# +# [*config_file_orig*] +# The location and name of a config file that provides the source +# of the sentinel config file. Two different files are needed +# because sentinel itself writes to its own config file and we do +# not want override that when puppet is run unless there are +# changes from the manifests. +# +# Default for deb: /etc/redis/redis-sentinel.conf.puppet +# Default for rpm: /etc/redis-sentinel.conf.puppet +# +# [*config_file_mode*] +# Permissions of config file. +# +# Default: 0644 +# +# [*conf_template*] +# Define which template to use. +# +# Default: redis/redis-sentinel.conf.erb +# +# [*daemonize*] +# Have Redis sentinel run as a daemon. +# +# Default: true +# +# [*down_after*] +# Number of milliseconds the master (or any attached slave or sentinel) +# should be unreachable (as in, not acceptable reply to PING, continuously, +# for the specified period) in order to consider it in S_DOWN state. +# +# Default: 30000 +# +# [*failover_timeout*] +# Specify the failover timeout in milliseconds. +# +# Default: 180000 +# +# [*init_script*] +# Specifiy the init script that will be created for sentinel. +# +# Default: undef on rpm, /etc/init.d/redis-sentinel on apt. +# +# [*log_file*] +# Specify where to write log entries. +# +# Default: /var/log/redis/redis.log +# +# [*master_name*] +# Specify the name of the master redis server. +# The valid charset is A-z 0-9 and the three characters ".-_". +# +# Default: mymaster +# +# [*redis_host*] +# Specify the bound host of the master redis server. +# +# Default: 127.0.0.1 +# +# [*redis_port*] +# Specify the port of the master redis server. +# +# Default: 6379 +# +# [*package_name*] +# The name of the package that installs sentinel. +# +# Default: 'redis-server' on apt, 'redis' on rpm +# +# [*package_ensure*] +# Do we ensure this package. +# +# Default: 'present' +# +# [*parallel_sync*] +# How many slaves can be reconfigured at the same time to use a +# new master after a failover. +# +# Default: 1 +# +# [*pid_file*] +# If sentinel is daemonized it will write its pid at this location. +# +# Default: /var/run/redis/redis-sentinel.pid +# +# [*quorum*] +# Number of sentinels that must agree that a master is down to +# signal sdown state. +# +# Default: 2 +# +# [*sentinel_port*] +# The port of sentinel server. +# +# Default: 26379 +# +# [*service_group*] +# The group of the config file. +# +# Default: redis +# +# [*service_name*] +# The name of the service (for puppet to manage). +# +# Default: redis-sentinel +# +# [*service_owner*] +# The owner of the config file. +# +# Default: redis +# +# [*working_dir*] +# The directory into which sentinel will change to avoid mount +# conflicts. +# +# Default: /tmp +# +# [*notification_script*] +# Path to the notification script +# +# Default: undef +# == Actions: +# - Install and configure Redis Sentinel +# +# == Sample Usage: +# +# class { 'redis::sentinel': } +# +# class {'redis::sentinel': +# down_after => 80000, +# log_file => '/var/log/redis/sentinel.log', +# } +# +class redis::sentinel ( + $auth_pass = $::redis::params::sentinel_auth_pass, + $config_file = $::redis::params::sentinel_config_file, + $config_file_orig = $::redis::params::sentinel_config_file_orig, + $config_file_mode = $::redis::params::sentinel_config_file_mode, + $conf_template = $::redis::params::sentinel_conf_template, + $daemonize = $::redis::params::sentinel_daemonize, + $down_after = $::redis::params::sentinel_down_after, + $failover_timeout = $::redis::params::sentinel_failover_timeout, + $init_script = $::redis::params::sentinel_init_script, + $init_template = $::redis::params::sentinel_init_template, + $log_file = $::redis::params::log_file, + $master_name = $::redis::params::sentinel_master_name, + $redis_host = $::redis::params::bind, + $redis_port = $::redis::params::port, + $package_name = $::redis::params::sentinel_package_name, + $package_ensure = $::redis::params::sentinel_package_ensure, + $parallel_sync = $::redis::params::sentinel_parallel_sync, + $pid_file = $::redis::params::sentinel_pid_file, + $quorum = $::redis::params::sentinel_quorum, + $sentinel_port = $::redis::params::sentinel_port, + $service_group = $::redis::params::service_group, + $service_name = $::redis::params::sentinel_service_name, + $service_user = $::redis::params::service_user, + $working_dir = $::redis::params::sentinel_working_dir, + $notification_script = $::redis::params::sentinel_notification_script, +) inherits redis::params { + + unless defined(Package[$package_name]) { + ensure_resource('package', $package_name, { + 'ensure' => $package_ensure + }) + } + + file { + $config_file_orig: + ensure => present, + owner => $service_user, + group => $service_group, + mode => $config_file_mode, + content => template($conf_template), + require => Package[$package_name]; + } + + exec { + "cp -p ${config_file_orig} ${config_file}": + path => '/usr/bin:/bin', + subscribe => File[$config_file_orig], + notify => Service[$service_name], + refreshonly => true; + } + + if $init_script { + + file { + $init_script: + ensure => present, + owner => 'root', + group => 'root', + mode => '0755', + content => template($init_template), + require => Package[$package_name]; + } + + exec { + '/usr/sbin/update-rc.d redis-sentinel defaults': + subscribe => File[$init_script], + refreshonly => true; + } + + } + + service { $service_name: + ensure => $::redis::params::service_ensure, + enable => $::redis::params::service_enable, + hasrestart => $::redis::params::service_hasrestart, + hasstatus => $::redis::params::service_hasstatus, + } + +} diff --git a/puphpet/puppet/modules/redis/manifests/service.pp b/puphpet/puppet/modules/redis/manifests/service.pp new file mode 100644 index 0000000..9d86f02 --- /dev/null +++ b/puphpet/puppet/modules/redis/manifests/service.pp @@ -0,0 +1,16 @@ +# = Class: redis::service +# +# This class manages the Redis daemon. +# +class redis::service { + if $::redis::service_manage { + service { $::redis::service_name: + ensure => $::redis::service_ensure, + enable => $::redis::service_enable, + hasrestart => $::redis::service_hasrestart, + hasstatus => $::redis::service_hasstatus, + provider => $::redis::service_provider, + } + } +} + diff --git a/puphpet/puppet/modules/redis/metadata.json b/puphpet/puppet/modules/redis/metadata.json new file mode 100644 index 0000000..f93c305 --- /dev/null +++ b/puphpet/puppet/modules/redis/metadata.json @@ -0,0 +1,80 @@ +{ + "name": "arioch-redis", + "version": "1.2.1", + "author": "Tom De Vylder", + "summary": "Redis module", + "license": "Apache-2.0", + "source": "https://github.com/arioch/puppet-redis", + "project_page": "http://arioch.github.io/puppet-redis/", + "issues_url": "https://github.com/arioch/puppet-redis/issues", + "dependencies": [ + {"name":"puppetlabs/apt","version_requirement":">= 2.0.1 <3.0.0"}, + {"name":"puppetlabs/stdlib","version_requirement":">= 1.0.2 <5.0.0"}, + {"name":"stahnma/epel","version_requirement":">= 1.0.2 <2.0.0"} + ], + "data_provider": null, + "description": "Redis module with cluster support", + "tags": [ + "cluster", + "failover", + "loadbalancing", + "redis", + "sentinel" + ], + "operatingsystem_support": [ + { + "operatingsystem": "Debian", + "operatingsystemrelease": [ + "6.0", + "6.1", + "6.2", + "6.3", + "6.4", + "6.5", + "6.6", + "6.6", + "6.7", + "6.9", + "7.0", + "7.1", + "7.2", + "7.3", + "7.4", + "7.5" + ] + }, + { + "operatingsystem": "Ubuntu", + "operatingsystemrelease": [ + "14.04", + "14.10" + ] + }, + { + "operatingsystem": "RedHat", + "operatingsystemrelease": [ + "6.0", + "6.1", + "6.2", + "6.3", + "6.4", + "6.5", + "7.0", + "7.1" + ] + }, + { + "operatingsystem": "CentOS", + "operatingsystemrelease": [ + "6.0", + "6.1", + "6.2", + "6.3", + "6.4", + "6.5", + "7.0", + "7.1" + ] + } + ] +} diff --git a/puphpet/puppet/modules/redis/spec/acceptance/nodesets/default.yml b/puphpet/puppet/modules/redis/spec/acceptance/nodesets/default.yml new file mode 100644 index 0000000..780db9e --- /dev/null +++ b/puphpet/puppet/modules/redis/spec/acceptance/nodesets/default.yml @@ -0,0 +1,11 @@ +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 diff --git a/puphpet/puppet/modules/redis/spec/acceptance/redis_spec.rb b/puphpet/puppet/modules/redis/spec/acceptance/redis_spec.rb new file mode 100644 index 0000000..1e1998a --- /dev/null +++ b/puphpet/puppet/modules/redis/spec/acceptance/redis_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper_acceptance' + +describe 'redis' do + it 'should run successfully' do + pp = <<-EOS + Exec { + path => [ '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', ] + } + + class { '::redis': + manage_repo => true, + } + EOS + + # Apply twice to ensure no errors the second time. + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe package('redis') do + it { should be_installed } + end +end diff --git a/puphpet/puppet/modules/redis/spec/classes/redis_sentinel_spec.rb b/puphpet/puppet/modules/redis/spec/classes/redis_sentinel_spec.rb new file mode 100644 index 0000000..d21e221 --- /dev/null +++ b/puphpet/puppet/modules/redis/spec/classes/redis_sentinel_spec.rb @@ -0,0 +1,84 @@ +require 'spec_helper' + +$expected_noparams_content = < :class do + let (:facts) { debian_facts } + + let :pre_condition do + [ + 'class { redis: }' + ] + end + + describe 'without parameters' do + + it { should create_class('redis::sentinel') } + + it { should contain_file('/etc/redis/redis-sentinel.conf.puppet').with( + 'ensure' => 'present', + 'mode' => '0644', + 'owner' => 'redis', + 'content' => $expected_noparams_content + ) + } + + it { should contain_service('redis-sentinel').with( + 'ensure' => 'running', + 'enable' => 'true', + 'hasrestart' => 'true', + 'hasstatus' => 'false' + ) + } + + end + + describe 'with custom parameters' do + let (:params) { + { + :auth_pass => 'password', + :master_name => 'cow', + :down_after => 6000, + :log_file => '/tmp/barn-sentinel.log', + :failover_timeout => 28000, + :notification_script => 'bar.sh' + } + } + + it { should create_class('redis::sentinel') } + + it { should contain_file('/etc/redis/redis-sentinel.conf.puppet').with( + 'content' => $expected_params_content + ) + } + end + +end diff --git a/puphpet/puppet/modules/redis/spec/classes/redis_spec.rb b/puphpet/puppet/modules/redis/spec/classes/redis_spec.rb new file mode 100644 index 0000000..193d999 --- /dev/null +++ b/puphpet/puppet/modules/redis/spec/classes/redis_spec.rb @@ -0,0 +1,862 @@ +require 'spec_helper' + +describe 'redis', :type => :class do + let (:facts) { debian_facts } + + describe 'without parameters' do + it { should create_class('redis') } + it { should contain_class('redis::preinstall') } + it { should contain_class('redis::install') } + it { should contain_class('redis::config') } + it { should contain_class('redis::service') } + + it { should contain_package('redis-server').with_ensure('present') } + + it { should contain_file('/etc/redis/redis.conf').with( + 'ensure' => 'present' + ) + } + + it { should contain_service('redis-server').with( + 'ensure' => 'running', + 'enable' => 'true', + 'hasrestart' => 'true', + 'hasstatus' => 'false' + ) + } + end + + describe 'with parameter activerehashing' do + let (:params) { + { + :activerehashing => true + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /activerehashing.*yes/ + ) + } + end + + describe 'with parameter appendfsync' do + let (:params) { + { + :appendfsync => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /appendfsync.*_VALUE_/ + ) + } + end + + describe 'with parameter appendonly' do + let (:params) { + { + :appendonly => true + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /appendonly.*yes/ + ) + } + end + + describe 'with parameter auto_aof_rewrite_min_size' do + let (:params) { + { + :auto_aof_rewrite_min_size => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /auto-aof-rewrite-min-size.*_VALUE_/ + ) + } + end + + describe 'with parameter auto_aof_rewrite_percentage' do + let (:params) { + { + :auto_aof_rewrite_percentage => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /auto-aof-rewrite-percentage.*_VALUE_/ + ) + } + end + + describe 'with parameter bind' do + let (:params) { + { + :bind => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /bind.*_VALUE_/ + ) + } + end + + describe 'with parameter: config_dir' do + let (:params) { { :config_dir => '_VALUE_' } } + + it { should contain_file('_VALUE_').with_ensure('directory') } + end + + describe 'with parameter: config_dir_mode' do + let (:params) { { :config_dir_mode => '_VALUE_' } } + + it { should contain_file('/etc/redis').with_mode('_VALUE_') } + end + + describe 'with parameter: log_dir_mode' do + let (:params) { { :log_dir_mode => '_VALUE_' } } + + it { should contain_file('/var/log/redis').with_mode('_VALUE_') } + end + + describe 'with parameter: config_file' do + let (:params) { { :config_file => '_VALUE_' } } + + it { should contain_file('_VALUE_') } + end + + describe 'with parameter: config_file_mode' do + let (:params) { { :config_file_mode => '_VALUE_' } } + + it { should contain_file('/etc/redis/redis.conf').with_mode('_VALUE_') } + end + + describe 'with parameter: config_group' do + let (:params) { { :config_group => '_VALUE_' } } + + it { should contain_file('/etc/redis').with_group('_VALUE_') } + end + + describe 'with parameter: config_owner' do + let (:params) { { :config_owner => '_VALUE_' } } + + it { should contain_file('/etc/redis').with_owner('_VALUE_') } + end + + describe 'with parameter daemonize' do + let (:params) { + { + :daemonize => true + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /daemonize.*yes/ + ) + } + end + + describe 'with parameter databases' do + let (:params) { + { + :databases => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /databases.*_VALUE_/ + ) + } + end + + describe 'with parameter dbfilename' do + let (:params) { + { + :dbfilename => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /dbfilename.*_VALUE_/ + ) + } + end + + describe 'with parameter hash_max_ziplist_entries' do + let (:params) { + { + :hash_max_ziplist_entries => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /hash-max-ziplist-entries.*_VALUE_/ + ) + } + end + + describe 'with parameter hash_max_ziplist_value' do + let (:params) { + { + :hash_max_ziplist_value => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /hash-max-ziplist-value.*_VALUE_/ + ) + } + end + + describe 'with parameter list_max_ziplist_entries' do + let (:params) { + { + :list_max_ziplist_entries => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /list-max-ziplist-entries.*_VALUE_/ + ) + } + end + + describe 'with parameter list_max_ziplist_value' do + let (:params) { + { + :list_max_ziplist_value => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /list-max-ziplist-value.*_VALUE_/ + ) + } + end + + describe 'with parameter log_dir' do + let (:params) { + { + :log_dir => '_VALUE_' + } + } + + it { should contain_file('_VALUE_').with( + 'ensure' => 'directory' + ) + } + end + + describe 'with parameter log_file' do + let (:params) { + { + :log_file => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /logfile.*_VALUE_/ + ) + } + end + + describe 'with parameter log_level' do + let (:params) { + { + :log_level => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /loglevel.*_VALUE_/ + ) + } + end + + describe 'with parameter: manage_repo' do + let (:params) { { :manage_repo => true } } + + context 'on Debian' do + let (:facts) { + { + :lsbdistcodename => 'wheezy', + :lsbdistid => 'Debian', + :operatingsystem => 'Debian', + :osfamily => 'Debian' + } + } + + it { should create_apt__key('dotdeb') } + it { should create_apt__source('dotdeb') } + end + + context 'on Ubuntu' do + let (:facts) { + { + :lsbdistcodename => 'raring', + :lsbdistid => 'Ubuntu', + :operatingsystem => 'Ubuntu', + :osfamily => 'Debian' + } + } + + it { should create_apt__ppa('ppa:chris-lea/redis-server') } + end + + context 'on RHEL 6' do + let (:facts) { + { + :osfamily => 'RedHat', + :operatingsystem => 'RedHat', + :operatingsystemmajrelease => '6' + } + } + + it { should create_yumrepo('powerstack').with_enabled(1) } + end + + context 'on RHEL 7' do + let (:facts) { + { + :osfamily => 'RedHat', + :operatingsystem => 'RedHat', + :operatingsystemmajrelease => '7' + } + } + + it { should contain_class('epel') } + end + end + + describe 'with parameter masterauth' do + let (:params) { + { + :masterauth => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /masterauth.*_VALUE_/ + ) + } + end + + describe 'with parameter maxclients' do + let (:params) { + { + :maxclients => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /maxclients.*_VALUE_/ + ) + } + end + + describe 'with parameter maxmemory' do + let (:params) { + { + :maxmemory => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /maxmemory.*_VALUE_/ + ) + } + end + + describe 'with parameter maxmemory_policy' do + let (:params) { + { + :maxmemory_policy => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /maxmemory-policy.*_VALUE_/ + ) + } + end + + describe 'with parameter maxmemory_samples' do + let (:params) { + { + :maxmemory_samples => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /maxmemory-samples.*_VALUE_/ + ) + } + end + + describe 'with parameter notify_service' do + let (:params) { + { + :notify_service => true + } + } + + it { should contain_file('/etc/redis/redis.conf').that_notifies('Service[redis-server]' + ) + } + end + + describe 'with parameter no_appendfsync_on_rewrite' do + let (:params) { + { + :no_appendfsync_on_rewrite => true + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /no-appendfsync-on-rewrite.*yes/ + ) + } + end + + describe 'with parameter: package_ensure' do + let (:params) { { :package_ensure => '_VALUE_' } } + + it { should contain_package('redis-server').with( + 'ensure' => '_VALUE_' + ) + } + end + + describe 'with parameter: package_name' do + let (:params) { { :package_name => '_VALUE_' } } + + it { should contain_package('_VALUE_') } + end + + describe 'with parameter pid_file' do + let (:params) { + { + :pid_file => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /pidfile.*_VALUE_/ + ) + } + end + + describe 'with parameter port' do + let (:params) { + { + :port => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /port.*_VALUE_/ + ) + } + end + + describe 'with parameter hz' do + let (:params) { + { + :hz=> '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /hz.*_VALUE_/ + ) + } + end + + describe 'with parameter rdbcompression' do + let (:params) { + { + :rdbcompression => true + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /rdbcompression.*yes/ + ) + } + end + + describe 'with parameter repl_ping_slave_period' do + let (:params) { + { + :repl_ping_slave_period => 1 + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /repl-ping-slave-period.*1/ + ) + } + end + + describe 'with parameter repl_timeout' do + let (:params) { + { + :repl_timeout => 1 + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /repl-timeout.*1/ + ) + } + end + + describe 'with parameter requirepass' do + let (:params) { + { + :requirepass => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /requirepass.*_VALUE_/ + ) + } + end + + describe 'with parameter save_db_to_disk' do + context 'true' do + let (:params) { + { + :save_db_to_disk => true + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /^save/ + ) + } + end + + context 'false' do + let (:params) { + { + :save_db_to_disk => false + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /^(?!save)/ + ) + } + end + end + + describe 'with parameter: service_manage (set to false)' do + let (:params) { { :service_manage => false } } + + it { should_not contain_service('redis-server') } + end + + describe 'with parameter: service_enable' do + let (:params) { { :service_enable => true } } + + it { should contain_service('redis-server').with_enable(true) } + end + + describe 'with parameter: service_ensure' do + let (:params) { { :service_ensure => '_VALUE_' } } + + it { should contain_service('redis-server').with_ensure('_VALUE_') } + end + + describe 'with parameter: service_group' do + let (:params) { { :service_group => '_VALUE_' } } + + it { should contain_file('/var/log/redis').with_group('_VALUE_') } + end + + describe 'with parameter: service_hasrestart' do + let (:params) { { :service_hasrestart => true } } + + it { should contain_service('redis-server').with_hasrestart(true) } + end + + describe 'with parameter: service_hasstatus' do + let (:params) { { :service_hasstatus => true } } + + it { should contain_service('redis-server').with_hasstatus(true) } + end + + describe 'with parameter: service_name' do + let (:params) { { :service_name => '_VALUE_' } } + + it { should contain_service('_VALUE_').with_name('_VALUE_') } + end + + describe 'with parameter: service_user' do + let (:params) { { :service_user => '_VALUE_' } } + + it { should contain_file('/var/log/redis').with_owner('_VALUE_') } + end + + describe 'with parameter set_max_intset_entries' do + let (:params) { + { + :set_max_intset_entries => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /set-max-intset-entries.*_VALUE_/ + ) + } + end + + describe 'with parameter slave_read_only' do + let (:params) { + { + :slave_read_only => true + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /slave-read-only.*yes/ + ) + } + end + + describe 'with parameter slave_serve_stale_data' do + let (:params) { + { + :slave_serve_stale_data => true + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /slave-serve-stale-data.*yes/ + ) + } + end + + describe 'with parameter: slaveof' do + context 'binding to localhost' do + let (:params) { + { + :bind => '127.0.0.1', + :slaveof => '_VALUE_' + } + } + + it do + expect { + should create_class('redis') + }.to raise_error(Puppet::Error, /Replication is not possible/) + end + end + + context 'binding to external ip' do + let (:params) { + { + :bind => '10.0.0.1', + :slaveof => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /^slaveof _VALUE_/ + ) + } + end + end + + describe 'with parameter slowlog_log_slower_than' do + let (:params) { + { + :slowlog_log_slower_than => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /slowlog-log-slower-than.*_VALUE_/ + ) + } + end + + describe 'with parameter slowlog_max_len' do + let (:params) { + { + :slowlog_max_len => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /slowlog-max-len.*_VALUE_/ + ) + } + end + + describe 'with parameter stop_writes_on_bgsave_error' do + let (:params) { + { + :stop_writes_on_bgsave_error => true + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /stop-writes-on-bgsave-error.*yes/ + ) + } + end + + describe 'with parameter syslog_enabled' do + let (:params) { + { + :syslog_enabled => true + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /syslog-enabled yes/ + ) + } + end + + describe 'with parameter syslog_facility' do + let (:params) { + { + :syslog_enabled => true, + :syslog_facility => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /syslog-facility.*_VALUE_/ + ) + } + end + + describe 'with parameter tcp_keepalive' do + let (:params) { + { + :tcp_keepalive => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /tcp-keepalive.*_VALUE_/ + ) + } + end + + describe 'with parameter timeout' do + let (:params) { + { + :timeout => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /timeout.*_VALUE_/ + ) + } + end + + describe 'with parameter workdir' do + let (:params) { + { + :workdir => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /dir.*_VALUE_/ + ) + } + end + + describe 'with parameter zset_max_ziplist_entries' do + let (:params) { + { + :zset_max_ziplist_entries => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /zset-max-ziplist-entries.*_VALUE_/ + ) + } + end + + describe 'with parameter zset_max_ziplist_value' do + let (:params) { + { + :zset_max_ziplist_value => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /zset-max-ziplist-value.*_VALUE_/ + ) + } + end + + describe 'with parameter cluster_enabled-false' do + let (:params) { + { + :cluster_enabled => false + } + } + + it { should_not contain_file('/etc/redis/redis.conf').with( + 'content' => /cluster-enabled/ + ) + } + end + + describe 'with parameter cluster_enabled-true' do + let (:params) { + { + :cluster_enabled => true + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /cluster-enabled.*yes/ + ) + } + end + + describe 'with parameter cluster_config_file' do + let (:params) { + { + :cluster_enabled => true, + :cluster_config_file => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /cluster-config-file.*_VALUE_/ + ) + } + end + + describe 'with parameter cluster_config_file' do + let (:params) { + { + :cluster_enabled => true, + :cluster_node_timeout => '_VALUE_' + } + } + + it { should contain_file('/etc/redis/redis.conf').with( + 'content' => /cluster-node-timeout.*_VALUE_/ + ) + } + end + +end + diff --git a/puphpet/puppet/modules/redis/spec/spec.opts b/puphpet/puppet/modules/redis/spec/spec.opts new file mode 100644 index 0000000..7a0e5e3 --- /dev/null +++ b/puphpet/puppet/modules/redis/spec/spec.opts @@ -0,0 +1 @@ +--format documentation --color --backtrace diff --git a/puphpet/puppet/modules/redis/spec/spec_helper.rb b/puphpet/puppet/modules/redis/spec/spec_helper.rb index 5fda588..50795cd 100644 --- a/puphpet/puppet/modules/redis/spec/spec_helper.rb +++ b/puphpet/puppet/modules/redis/spec/spec_helper.rb @@ -1,17 +1,16 @@ -dir = File.expand_path(File.dirname(__FILE__)) -$LOAD_PATH.unshift File.join(dir, 'lib') +require 'rubygems' +require 'puppetlabs_spec_helper/module_spec_helper' -require 'mocha' -require 'puppet' -require 'rspec' -require 'spec/autorun' - -Spec::Runner.configure do |config| - config.mock_with :mocha +def centos_facts + { + :operatingsystem => 'CentOS', + :osfamily => 'RedHat', + } end -# We need this because the RAL uses 'should' as a method. This -# allows us the same behaviour but with a different method name. -class Object - alias :must :should +def debian_facts + { + :operatingsystem => 'Debian', + :osfamily => 'Debian', + } end diff --git a/puphpet/puppet/modules/redis/spec/spec_helper_acceptance.rb b/puphpet/puppet/modules/redis/spec/spec_helper_acceptance.rb new file mode 100644 index 0000000..ac4f001 --- /dev/null +++ b/puphpet/puppet/modules/redis/spec/spec_helper_acceptance.rb @@ -0,0 +1,31 @@ +require 'beaker-rspec' + +unless ENV['RS_PROVISION'] == 'no' + hosts.each do |host| + # Install Puppet + if host.is_pe? + install_pe + else + install_puppet + 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 + + c.before :suite do + # Install module and dependencies + puppet_module_install(:source => proj_root, :module_name => 'redis') + + hosts.each do |host| + shell("/bin/touch #{default['puppetpath']}/hiera.yaml") + + shell('puppet module install puppetlabs-stdlib', { :acceptable_exit_codes => [0,1] }) + end + end +end diff --git a/puphpet/puppet/modules/redis/templates/redis-sentinel.conf.erb b/puphpet/puppet/modules/redis/templates/redis-sentinel.conf.erb new file mode 100644 index 0000000..a3e6f2d --- /dev/null +++ b/puphpet/puppet/modules/redis/templates/redis-sentinel.conf.erb @@ -0,0 +1,17 @@ +port <%= @sentinel_port %> +dir <%= @working_dir %> +<% if @daemonize -%>daemonize yes<% else -%>daemonize no<% end %> +pidfile <%= @pid_file %> + +sentinel monitor <%= @master_name %> <%= @redis_host %> <%= @redis_port %> <%= @quorum %> +sentinel down-after-milliseconds <%= @master_name %> <%= @down_after %> +sentinel parallel-syncs <%= @master_name %> <%= @parallel_sync %> +sentinel failover-timeout <%= @master_name %> <%= @failover_timeout %> +<% if @auth_pass -%> +sentinel auth-pass <%= @master_name %> <%= @auth_pass %> +<% end -%> +<% if @notification_script -%> +sentinel notification-script <%= @master_name %> <%= @notification_script %> +<% end -%> + +logfile <%= @log_file %> diff --git a/puphpet/puppet/modules/redis/templates/redis-sentinel.init.erb b/puphpet/puppet/modules/redis/templates/redis-sentinel.init.erb new file mode 100644 index 0000000..a4e1b39 --- /dev/null +++ b/puphpet/puppet/modules/redis/templates/redis-sentinel.init.erb @@ -0,0 +1,89 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: redis-sentinel +# Required-Start: $syslog $remote_fs +# Required-Stop: $syslog $remote_fs +# Should-Start: $local_fs +# Should-Stop: $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: redis-sentinel - Monitor redis-server +# Description: redis-sentinel - Monitor redis-server +### END INIT INFO + + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/bin/redis-sentinel +DAEMON_ARGS=<%= @config_file %> +NAME=redis-sentinel +DESC=redis-senitnel + +RUNDIR=/var/run/redis +PIDFILE=$RUNDIR/redis-sentinel.pid + +test -x $DAEMON || exit 0 + +if [ -r /etc/default/$NAME ] +then + . /etc/default/$NAME +fi + +. /lib/lsb/init-functions + +set -e + +case "$1" in + start) + echo -n "Starting $DESC: " + mkdir -p $RUNDIR + touch $PIDFILE + chown <%= @service_user %>:<%= @service_group %> $RUNDIR $PIDFILE + chmod 755 $RUNDIR + + if [ -n "$ULIMIT" ] + then + ulimit -n $ULIMIT + fi + + if start-stop-daemon --start --quiet --umask 007 --pidfile $PIDFILE --chuid <%= @service_user %>:<%= @service_group %> --exec $DAEMON -- $DAEMON_ARGS + then + echo "$NAME." + else + echo "failed" + fi + ;; + stop) + echo -n "Stopping $DESC: " + if start-stop-daemon --stop --retry forever/TERM/1 --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON + then + echo "$NAME." + else + echo "failed" + fi + rm -f $PIDFILE + sleep 1 + ;; + + restart|force-reload) + ${0} stop + ${0} start + ;; + + status) + echo -n "$DESC is " + if start-stop-daemon --stop --quiet --signal 0 --name ${NAME} --pidfile ${PIDFILE} + then + echo "running" + else + echo "not running" + exit 1 + fi + ;; + + *) + echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|status}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/puphpet/puppet/modules/redis/templates/redis.rhel.conf.erb b/puphpet/puppet/modules/redis/templates/redis.conf.erb similarity index 56% rename from puphpet/puppet/modules/redis/templates/redis.rhel.conf.erb rename to puphpet/puppet/modules/redis/templates/redis.conf.erb index 51d1e07..e445427 100644 --- a/puphpet/puppet/modules/redis/templates/redis.rhel.conf.erb +++ b/puphpet/puppet/modules/redis/templates/redis.conf.erb @@ -1,6 +1,6 @@ # Redis configuration file example -# Note on units: when memory size is needed, it is possible to specifiy +# Note on units: when memory size is needed, it is possible to specify # it in the usual form of 1k 5GB 4M and so forth: # # 1k => 1000 bytes @@ -14,32 +14,46 @@ # By default Redis does not run as a daemon. Use 'yes' if you need it. # Note that Redis will write a pid file in /var/run/redis.pid when daemonized. -daemonize <%= @conf_daemonize %> +<% if @daemonize -%>daemonize yes<% else -%>daemonize no<% end -%> # When running daemonized, Redis writes a pid file in /var/run/redis.pid by # default. You can specify a custom pid file location here. -pidfile <%= @conf_pidfile_real %> +pidfile <%= @pid_file %> # Accept connections on the specified port, default is 6379. # If port 0 is specified Redis will not listen on a TCP socket. -port <%= @conf_port %> +port <%= @port %> # If you want you can bind a single interface, if the bind option is not # specified all the interfaces will listen for incoming connections. # -<% if @conf_bind != 'UNSET' %> -bind <%= @conf_bind %> -<% end %> +bind <%= @bind %> # Specify the path for the unix socket that will be used to listen for # incoming connections. There is no default, so Redis will not listen # on a unix socket when not specified. # -# unixsocket /tmp/redis.sock +# unixsocket /var/run/redis/redis.sock # unixsocketperm 755 # Close the connection after a client is idle for N seconds (0 to disable) -timeout <%= @conf_timeout %> +timeout <%= @timeout %> + +# TCP keepalive. +# +# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence +# of communication. This is useful for two reasons: +# +# 1) Detect dead peers. +# 2) Take the connection alive from the point of view of network +# equipment in the middle. +# +# On Linux, the specified value (in seconds) is the period used to send ACKs. +# Note that to close the connection the double of the time is needed. +# On other kernels the period depends on the kernel configuration. +# +# A reasonable value for this option is 60 seconds. +tcp-keepalive <%= @tcp_keepalive %> # Set server verbosity to 'debug' # it can be one of: @@ -47,39 +61,27 @@ timeout <%= @conf_timeout %> # verbose (many rarely useful info, but not a mess like the debug level) # notice (moderately verbose, what you want in production probably) # warning (only very important / critical messages are logged) -loglevel <%= @conf_loglevel %> +loglevel <%= @log_level %> # Specify the log file name. Also 'stdout' can be used to force # Redis to log on the standard output. Note that if you use standard # output for logging but daemonize, logs will be sent to /dev/null -logfile <%= @conf_logfile_real %> +logfile <%= @log_file %> # To enable logging to the system logger, just set 'syslog-enabled' to yes, # and optionally update the other syslog parameters to suit your needs. -<% if @conf_syslog_enabled != 'UNSET' %> -syslog-enabled <%= @conf_syslog_enabled %> -<% else %> -# syslog-enabled no -<% end %> +<% if @syslog_enabled %>syslog-enabled yes<% else %>syslog-enabled no<% end %> # Specify the syslog identity. -<% if @conf_syslog_ident != 'UNSET' %> -syslog-ident <%= @conf_syslog_ident %> -<% else %> # syslog-ident redis -<% end %> # Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. -<% if @conf_syslog_facility != 'UNSET' %> -syslog-facility <%= @conf_syslog_facility %> -<% else %> -# syslog-facility local0 -<% end %> +<% if @syslog_facility %>syslog-facility <%= @syslog_facility %><% else %># syslog-facility local0<% end %> # Set the number of databases. The default database is DB 0, you can select # a different one on a per-connection basis using SELECT where # dbid is a number between 0 and 'databases'-1 -databases <%= @conf_databases %> +databases <%= @databases %> ################################ SNAPSHOTTING ################################# # @@ -96,30 +98,51 @@ databases <%= @conf_databases %> # after 60 sec if at least 10000 keys changed # # Note: you can disable saving at all commenting all the "save" lines. +# +# It is also possible to remove all the previously configured save +# points by adding a save directive with a single empty string argument +# like in the following example: +# +# save "" -<% if @conf_nosave != 'UNSET' %> -#do not persist to disk: -#save 900 1 -#save 300 10 -#save 60 10000 -<% else %> - <% if @conf_save != 'UNSET' %> - save <%= @conf_save %> - <% else %> - save 900 1 - save 300 10 - save 60 10000 - <% end %> +<% if @save_db_to_disk %> +save 900 1 +save 300 10 +save 60 10000 <% end %> +# By default Redis will stop accepting writes if RDB snapshots are enabled +# (at least one save point) and the latest background save failed. +# This will make the user aware (in an hard way) that data is not persisting +# on disk properly, otherwise chances are that no one will notice and some +# distater will happen. +# +# If the background saving process will start working again Redis will +# automatically allow writes again. +# +# However if you have setup your proper monitoring of the Redis server +# and persistence, you may want to disable this feature so that Redis will +# continue to work as usually even if there are problems with disk, +# permissions, and so forth. +<% if @stop_writes_on_bgsave_error -%>stop-writes-on-bgsave-error yes<% else -%>stop-writes-on-bgsave-error no<% end -%> + # Compress string objects using LZF when dump .rdb databases? # For default that's set to 'yes' as it's almost always a win. # If you want to save some CPU in the saving child set it to 'no' but # the dataset will likely be bigger if you have compressible values or keys. -rdbcompression <%= @conf_rdbcompression %> +<% if @rdbcompression -%>rdbcompression yes<% else -%>rdbcompression no<% end -%> + +# Since verison 5 of RDB a CRC64 checksum is placed at the end of the file. +# This makes the format more resistant to corruption but there is a performance +# hit to pay (around 10%) when saving and loading RDB files, so you can disable it +# for maximum performances. +# +# RDB files created with checksum disabled have a checksum of zero that will +# tell the loading code to skip the check. +rdbchecksum yes # The filename where to dump the DB -dbfilename <%= @conf_dbfilename %> +dbfilename <%= @dbfilename %> # The working directory. # @@ -129,7 +152,7 @@ dbfilename <%= @conf_dbfilename %> # Also the Append Only File will be created inside this directory. # # Note that you must specify a directory here, not a file name. -dir <%= @conf_dir %> +dir <%= @workdir %> ################################# REPLICATION ################################# @@ -138,42 +161,51 @@ dir <%= @conf_dir %> # so for example it is possible to configure the slave to save the DB with a # different interval, or to listen to another port, and so on. # -<% if @conf_slaveof != 'UNSET' %> -slaveof <%= @conf_slaveof %> -<% else %> # slaveof -<% end %> +<% if @slaveof -%>slaveof <%= @slaveof %><% end -%> # If the master is password protected (using the "requirepass" configuration # directive below) it is possible to tell the slave to authenticate before # starting the replication synchronization process, otherwise the master will # refuse the slave request. # -<% if @conf_masterauth != 'UNSET' %> -masterauth <%= @conf_masterauth %> -<% else %> # masterauth -<% end %> +<% if @masterauth -%>masterauth <%= @masterauth %><% end -%> # When a slave lost the connection with the master, or when the replication # is still in progress, the slave can act in two different ways: # # 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will -# still reply to client requests, possibly with out of data data, or the +# still reply to client requests, possibly with out of date data, or the # data set may just be empty if this is the first synchronization. # # 2) if slave-serve-stale data is set to 'no' the slave will reply with # an error "SYNC with master in progress" to all the kind of commands # but to INFO and SLAVEOF. # -slave-serve-stale-data <%= @conf_slave_server_stale_data %> +slave-serve-stale-data <% if @slave_serve_stale_data -%>yes<% else -%>no<% end -%> + +# You can configure a slave instance to accept writes or not. Writing against +# a slave instance may be useful to store some ephemeral data (because data +# written on a slave will be easily deleted after resync with the master) but +# may also cause problems if clients are writing to it because of a +# misconfiguration. +# +# Since Redis 2.6 by default slaves are read-only. +# +# Note: read only slaves are not designed to be exposed to untrusted clients +# on the internet. It's just a protection layer against misuse of the instance. +# Still a read only slave exports by default all the administrative commands +# such as CONFIG, DEBUG, and so forth. To a limited extend you can improve +# security of read only slaves using 'rename-command' to shadow all the +# administrative / dangerous commands. +slave-read-only <% if @slave_read_only -%>yes<% else -%>no<% end -%> # Slaves send PINGs to server in a predefined interval. It's possible to change # this interval with the repl_ping_slave_period option. The default value is 10 # seconds. # # repl-ping-slave-period 10 -repl-ping-slave-period <%= @conf_repl_ping_slave_period %> # The following option sets a timeout for both Bulk transfer I/O timeout and # master data or ping response timeout. The default value is 60 seconds. @@ -182,8 +214,22 @@ repl-ping-slave-period <%= @conf_repl_ping_slave_period %> # specified for repl-ping-slave-period otherwise a timeout will be detected # every time there is low traffic between the master and the slave. # -# repl-timeout 60 -repl-timeout <%= @conf_repl_timeout %> +repl-timeout <%= @repl_timeout %> + +# The slave priority is an integer number published by Redis in the INFO output. +# It is used by Redis Sentinel in order to select a slave to promote into a +# master if the master is no longer working correctly. +# +# A slave with a low priority number is considered better for promotion, so +# for instance if there are three slaves with priority 10, 100, 25 Sentinel will +# pick the one wtih priority 10, that is the lowest. +# +# However a special priority of 0 marks the slave as not able to perform the +# role of master, so a slave with priority of 0 will never be selected by +# Redis Sentinel for promotion. +# +# By default the priority is 100. +slave-priority 100 ################################## SECURITY ################################### @@ -198,15 +244,11 @@ repl-timeout <%= @conf_repl_timeout %> # 150k passwords per second against a good box. This means that you should # use a very strong password otherwise it will be very easy to break. # -<% if @conf_requirepass != 'UNSET' %> -requirepass <%= @conf_requirepass %> -<% else %> -# requirepass foobared -<% end %> +<% if @requirepass -%>requirepass <%= @requirepass %><% end -%> # Command renaming. # -# It is possilbe to change the name of dangerous commands in a shared +# It is possible to change the name of dangerous commands in a shared # environment. For instance the CONFIG command may be renamed into something # of hard to guess so that it will be still available for internal-use # tools but not available for general clients. @@ -215,23 +257,23 @@ requirepass <%= @conf_requirepass %> # # rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 # -# It is also possilbe to completely kill a command renaming it into +# It is also possible to completely kill a command renaming it into # an empty string: # # rename-command CONFIG "" ################################### LIMITS #################################### -# Set the max number of connected clients at the same time. By default there -# is no limit, and it's up to the number of file descriptors the Redis process -# is able to open. The special value '0' means no limits. +# Set the max number of connected clients at the same time. By default +# this limit is set to 10000 clients, however if the Redis server is not +# able ot configure the process file limit to allow for the specified limit +# the max number of allowed clients is set to the current file limit +# minus 32 (as Redis reserves a few file descriptors for internal uses). +# # Once the limit is reached Redis will close all the new connections sending # an error 'max number of clients reached'. # -# maxclients 128 -<% if @conf_maxclients != 'UNSET' %> -maxclients <%= @conf_maxclients %> -<% end %> +maxclients <%= @maxclients %> # Don't use more memory than the specified amount of bytes. # When the memory limit is reached Redis will try to remove keys @@ -257,9 +299,7 @@ maxclients <%= @conf_maxclients %> # output buffers (but this is not needed if the policy is 'noeviction'). # # maxmemory -<% if @conf_maxmemory != 'UNSET' %> -maxmemory <%= @conf_maxmemory %> -<% end %> +<% if @maxmemory -%>maxmemory <%= @maxmemory %><% end -%> # MAXMEMORY POLICY: how Redis will select what to remove when maxmemory # is reached? You can select among five behavior: @@ -267,7 +307,7 @@ maxmemory <%= @conf_maxmemory %> # volatile-lru -> remove the key with an expire set using an LRU algorithm # allkeys-lru -> remove any key accordingly to the LRU algorithm # volatile-random -> remove a random key with an expire set -# allkeys->random -> remove a random key, any key +# allkeys-random -> remove a random key, any key # volatile-ttl -> remove the key with the nearest expire time (minor TTL) # noeviction -> don't expire at all, just return an error on write operations # @@ -283,9 +323,7 @@ maxmemory <%= @conf_maxmemory %> # The default is: # # maxmemory-policy volatile-lru -<% if @conf_maxmemory_policy != 'UNSET' %> -maxmemory-policy <%= @conf_maxmemory_policy %> -<% end %> +<% if @maxmemory_policy -%>maxmemory-policy <%= @maxmemory_policy %><% end -%> # LRU and minimal TTL algorithms are not precise algorithms but approximated # algorithms (in order to save memory), so you can select as well the sample @@ -294,35 +332,32 @@ maxmemory-policy <%= @conf_maxmemory_policy %> # using the following configuration directive. # # maxmemory-samples 3 -<% if @conf_maxmemory_samples != 'UNSET' %> -maxmemory-samples <%= @conf_maxmemory_samples %> -<% end %> +<% if @maxmemory_samples -%>maxmemory-samples <%= @maxmemory_samples %><% end -%> ############################## APPEND ONLY MODE ############################### -# By default Redis asynchronously dumps the dataset on disk. If you can live -# with the idea that the latest records will be lost if something like a crash -# happens this is the preferred way to run Redis. If instead you care a lot -# about your data and don't want to that a single record can get lost you should -# enable the append only mode: when this mode is enabled Redis will append -# every write operation received in the file appendonly.aof. This file will -# be read on startup in order to rebuild the full dataset in memory. +# By default Redis asynchronously dumps the dataset on disk. This mode is +# good enough in many applications, but an issue with the Redis process or +# a power outage may result into a few minutes of writes lost (depending on +# the configured save points). # -# Note that you can have both the async dumps and the append only file if you -# like (you have to comment the "save" statements above to disable the dumps). -# Still if append only mode is enabled Redis will load the data from the -# log file at startup ignoring the dump.rdb file. +# The Append Only File is an alternative persistence mode that provides +# much better durability. For instance using the default data fsync policy +# (see later in the config file) Redis can lose just one second of writes in a +# dramatic event like a server power outage, or a single write if something +# wrong with the Redis process itself happens, but the operating system is +# still running correctly. # -# IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append -# log file in background when it gets too big. +# AOF and RDB persistence can be enabled at the same time without problems. +# If the AOF is enabled on startup Redis will load the AOF, that is the file +# with the better durability guarantees. +# +# Please check http://redis.io/topics/persistence for more information. -appendonly <%= @conf_appendonly %> +<% if @appendonly -%>appendonly yes<% else -%>appendonly no<% end -%> # The name of the append only file (default: "appendonly.aof") # appendfilename appendonly.aof -<% if @conf_appendfilename != 'UNSET' %> -appendfilename <%= @conf_appendfilename %> -<% end %> # The fsync() call tells the Operating System to actually write data on disk # instead to wait for more data in the output buffer. Some OS will really flush @@ -332,21 +367,22 @@ appendfilename <%= @conf_appendfilename %> # # no: don't fsync, just let the OS flush the data when it wants. Faster. # always: fsync after every write to the append only log . Slow, Safest. -# everysec: fsync only if one second passed since the last fsync. Compromise. +# everysec: fsync only one time every second. Compromise. # # The default is "everysec" that's usually the right compromise between # speed and data safety. It's up to you to understand if you can relax this to -# "no" that will will let the operating system flush the output buffer when +# "no" that will let the operating system flush the output buffer when # it wants, for better performances (but if you can live with the idea of # some data loss consider the default persistence mode that's snapshotting), # or on the contrary, use "always" that's very slow but a bit safer than # everysec. # +# More details please check the following article: +# http://antirez.com/post/redis-persistence-demystified.html +# # If unsure, use "everysec". -# appendfsync always -appendfsync <%= @conf_appendfsync %> -# appendfsync no +appendfsync <%= @appendfsync %> # When the AOF fsync policy is set to always or everysec, and a background # saving process (a background save or AOF log background rewriting) is @@ -360,13 +396,13 @@ appendfsync <%= @conf_appendfsync %> # BGSAVE or BGREWRITEAOF is in progress. # # This means that while another child is saving the durability of Redis is -# the same as "appendfsync none", that in pratical terms means that it is +# the same as "appendfsync none", that in practical terms means that it is # possible to lost up to 30 seconds of log in the worst scenario (with the # default Linux settings). # # If you have latency problems turn this to "yes". Otherwise leave it as # "no" that is the safest pick from the point of view of durability. -no-appendfsync-on-rewrite <%= @conf_no_appendfsync_on_rewrite %> +<% if @no_appendfsync_on_rewrite -%>no-appendfsync-on-rewrite yes<% else -%>no-appendfsync-on-rewrite no<% end -%> # Automatic rewrite of the append only file. # Redis is able to automatically rewrite the log file implicitly calling @@ -382,11 +418,29 @@ no-appendfsync-on-rewrite <%= @conf_no_appendfsync_on_rewrite %> # is useful to avoid rewriting the AOF file even if the percentage increase # is reached but it is still pretty small. # -# Specify a precentage of zero in order to disable the automatic AOF +# Specify a percentage of zero in order to disable the automatic AOF # rewrite feature. -auto-aof-rewrite-percentage <%= @conf_auto_aof_rewrite_percentage %> -auto-aof-rewrite-min-size <%= @conf_auto_aof_rewrite_min_size %> +auto-aof-rewrite-percentage <%= @auto_aof_rewrite_percentage %> +auto-aof-rewrite-min-size <%= @auto_aof_rewrite_min_size %> + +################################ LUA SCRIPTING ############################### + +# Max execution time of a Lua script in milliseconds. +# +# If the maximum execution time is reached Redis will log that a script is +# still in execution after the maximum allowed time and will start to +# reply to queries with an error. +# +# When a long running script exceed the maximum execution time only the +# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be +# used to stop a script that did not yet called write commands. The second +# is the only way to shut down the server in the case a write commands was +# already issue by the script but the user don't want to wait for the natural +# termination of the script. +# +# Set it to 0 or a negative value for unlimited execution without warnings. +lua-time-limit 5000 ################################## SLOW LOG ################################### @@ -406,120 +460,44 @@ auto-aof-rewrite-min-size <%= @conf_auto_aof_rewrite_min_size %> # The following time is expressed in microseconds, so 1000000 is equivalent # to one second. Note that a negative number disables the slow log, while # a value of zero forces the logging of every command. -slowlog-log-slower-than <%= @conf_slowlog_log_slower_than %> +slowlog-log-slower-than <%= @slowlog_log_slower_than %> # There is no limit to this length. Just be aware that it will consume memory. # You can reclaim memory used by the slow log with SLOWLOG RESET. -slowlog-max-len <%= @conf_slowlog_max_len %> - -################################ VIRTUAL MEMORY ############################### - -### WARNING! Virtual Memory is deprecated in Redis 2.4 -### The use of Virtual Memory is strongly discouraged. - -# Virtual Memory allows Redis to work with datasets bigger than the actual -# amount of RAM needed to hold the whole dataset in memory. -# In order to do so very used keys are taken in memory while the other keys -# are swapped into a swap file, similarly to what operating systems do -# with memory pages. -# -# To enable VM just set 'vm-enabled' to yes, and set the following three -# VM parameters accordingly to your needs. - -#vm-enabled <%= @conf_vm_enabled %> -# vm-enabled yes - -# This is the path of the Redis swap file. As you can guess, swap files -# can't be shared by different Redis instances, so make sure to use a swap -# file for every redis process you are running. Redis will complain if the -# swap file is already in use. -# -# The best kind of storage for the Redis swap file (that's accessed at random) -# is a Solid State Disk (SSD). -# -# *** WARNING *** if you are using a shared hosting the default of putting -# the swap file under /tmp is not secure. Create a dir with access granted -# only to Redis user and configure Redis to create the swap file there. -#vm-swap-file <%= @conf_vm_swap_file %> - -# vm-max-memory configures the VM to use at max the specified amount of -# RAM. Everything that deos not fit will be swapped on disk *if* possible, that -# is, if there is still enough contiguous space in the swap file. -# -# With vm-max-memory 0 the system will swap everything it can. Not a good -# default, just specify the max amount of RAM you can in bytes, but it's -# better to leave some margin. For instance specify an amount of RAM -# that's more or less between 60 and 80% of your free RAM. -#vm-max-memory <%= @conf_vm_max_memory %> - -# Redis swap files is split into pages. An object can be saved using multiple -# contiguous pages, but pages can't be shared between different objects. -# So if your page is too big, small objects swapped out on disk will waste -# a lot of space. If you page is too small, there is less space in the swap -# file (assuming you configured the same number of total swap file pages). -# -# If you use a lot of small objects, use a page size of 64 or 32 bytes. -# If you use a lot of big objects, use a bigger page size. -# If unsure, use the default :) -#vm-page-size <%= @conf_vm_page_size %> - -# Number of total memory pages in the swap file. -# Given that the page table (a bitmap of free/used pages) is taken in memory, -# every 8 pages on disk will consume 1 byte of RAM. -# -# The total swap size is vm-page-size * vm-pages -# -# With the default of 32-bytes memory pages and 134217728 pages Redis will -# use a 4 GB swap file, that will use 16 MB of RAM for the page table. -# -# It's better to use the smallest acceptable value for your application, -# but the default is large in order to work in most conditions. -#vm-pages <%= @conf_vm_pages %> - -# Max number of VM I/O threads running at the same time. -# This threads are used to read/write data from/to swap file, since they -# also encode and decode objects from disk to memory or the reverse, a bigger -# number of threads can help with big objects even if they can't help with -# I/O itself as the physical device may not be able to couple with many -# reads/writes operations at the same time. -# -# The special value of 0 turn off threaded I/O and enables the blocking -# Virtual Memory implementation. -#vm-max-threads <%= @conf_vm_max_threads %> +slowlog-max-len <%= @slowlog_max_len %> ############################### ADVANCED CONFIG ############################### -# Hashes are encoded in a special way (much more memory efficient) when they -# have at max a given numer of elements, and the biggest element does not -# exceed a given threshold. You can configure this limits with the following -# configuration directives. -#hash-max-zipmap-entries <%= @conf_hash_max_zipmap_entries %> -#hash-max-zipmap-value <%= @conf_hash_max_zipmap_value %> +# Hashes are encoded using a memory efficient data structure when they have a +# small number of entries, and the biggest entry does not exceed a given +# threshold. These thresholds can be configured using the following directives. +hash-max-ziplist-entries <%= @hash_max_ziplist_entries %> +hash-max-ziplist-value <%= @hash_max_ziplist_value %> # Similarly to hashes, small lists are also encoded in a special way in order # to save a lot of space. The special representation is only used when # you are under the following limits: -list-max-ziplist-entries <%= @conf_list_max_ziplist_entries %> -list-max-ziplist-value <%= @conf_list_max_ziplist_value %> +list-max-ziplist-entries <%= @list_max_ziplist_entries %> +list-max-ziplist-value <%= @list_max_ziplist_value %> # Sets have a special encoding in just one case: when a set is composed # of just strings that happens to be integers in radix 10 in the range # of 64 bit signed integers. # The following configuration setting sets the limit in the size of the # set in order to use this special memory saving encoding. -set-max-intset-entries <%= @conf_set_max_intset_entries %> +set-max-intset-entries <%= @set_max_intset_entries %> # Similarly to hashes and lists, sorted sets are also specially encoded in # order to save a lot of space. This encoding is only used when the length and # elements of a sorted set are below the following limits: -zset-max-ziplist-entries <%= @conf_zset_max_ziplist_entries %> -zset-max-ziplist-value <%= @conf_zset_max_ziplist_value %> +zset-max-ziplist-entries <%= @zset_max_ziplist_entries %> +zset-max-ziplist-value <%= @zset_max_ziplist_value %> # Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in # order to help rehashing the main Redis hash table (the one mapping top-level -# keys to values). The hash table implementation redis uses (see dict.c) +# keys to values). The hash table implementation Redis uses (see dict.c) # performs a lazy rehashing: the more operation you run into an hash table -# that is rhashing, the more rehashing "steps" are performed, so if the +# that is rehashing, the more rehashing "steps" are performed, so if the # server is idle the rehashing is never complete and some more memory is used # by the hash table. # @@ -533,17 +511,79 @@ zset-max-ziplist-value <%= @conf_zset_max_ziplist_value %> # # use "activerehashing yes" if you don't have such hard requirements but # want to free memory asap when possible. -activerehashing <%= @conf_activerehashing %> +<% if @activerehashing -%>activerehashing yes<% else -%>activerehashing no<% end -%> + +# The client output buffer limits can be used to force disconnection of clients +# that are not reading data from the server fast enough for some reason (a +# common reason is that a Pub/Sub client can't consume messages as fast as the +# publisher can produce them). +# +# The limit can be set differently for the three different classes of clients: +# +# normal -> normal clients +# slave -> slave clients and MONITOR clients +# pubsub -> clients subcribed to at least one pubsub channel or pattern +# +# The syntax of every client-output-buffer-limit directive is the following: +# +# client-output-buffer-limit +# +# A client is immediately disconnected once the hard limit is reached, or if +# the soft limit is reached and remains reached for the specified number of +# seconds (continuously). +# So for instance if the hard limit is 32 megabytes and the soft limit is +# 16 megabytes / 10 seconds, the client will get disconnected immediately +# if the size of the output buffers reach 32 megabytes, but will also get +# disconnected if the client reaches 16 megabytes and continuously overcomes +# the limit for 10 seconds. +# +# By default normal clients are not limited because they don't receive data +# without asking (in a push way), but just after a request, so only +# asynchronous clients may create a scenario where data is requested faster +# than it can read. +# +# Instead there is a default limit for pubsub and slave clients, since +# subscribers and slaves receive data in a push fashion. +# +# Both the hard or the soft limit can be disabled just setting it to zero. +client-output-buffer-limit normal 0 0 0 +client-output-buffer-limit slave 256mb 64mb 60 +client-output-buffer-limit pubsub 32mb 8mb 60 + +# Redis calls an internal function to perform many background tasks, like +# closing connections of clients in timeout, purging expired keys that are +# never requested, and so forth. +# +# Not all tasks are performed with the same frequency, but Redis checks for +# tasks to perform accordingly to the specified "hz" value. +# +# By default "hz" is set to 10. Raising the value will use more CPU when +# Redis is idle, but at the same time will make Redis more responsive when +# there are many keys expiring at the same time, and timeouts may be +# handled with more precision. +# +# The range is between 1 and 500, however a value over 100 is usually not +# a good idea. Most users should use the default of 10 and raise this up to +# 100 only in environments where very low latency is required. +hz <%= @hz %> + +# Redis Cluster Settings +<% if @cluster_enabled -%> +cluster-enabled yes +cluster-config-file <%= @cluster_config_file %> +cluster-node-timeout <%= @cluster_node_timeout %> +<% end -%> + ################################## INCLUDES ################################### # Include one or more other config files here. This is useful if you -# have a standard template that goes to all redis server but also need +# have a standard template that goes to all Redis server but also need # to customize a few per-server settings. Include files can include # other files, so use this wisely. # # include /path/to/local.conf # include /path/to/other.conf -<% if @conf_include != 'UNSET' %> -include <%= @conf_include %> -<% end %> +<% if @extra_config_file -%> +include <%= @extra_config_file %> +<% end -%> diff --git a/puphpet/puppet/modules/redis/templates/redis.debian.conf.erb b/puphpet/puppet/modules/redis/templates/redis.debian.conf.erb deleted file mode 100644 index e6706d0..0000000 --- a/puphpet/puppet/modules/redis/templates/redis.debian.conf.erb +++ /dev/null @@ -1,221 +0,0 @@ -# Redis configuration file example - -# By default Redis does not run as a daemon. Use 'yes' if you need it. -# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. -daemonize <%= @conf_daemonize %> - -# When run as a daemon, Redis write a pid file in /var/run/redis.pid by default. -# You can specify a custom pid file location here. -pidfile <%= @conf_pidfile_real %> - -# Accept connections on the specified port, default is 6379 -port <%= @conf_port %> - -# If you want you can bind a single interface, if the bind option is not -# specified all the interfaces will listen for connections. -# -<% if @conf_bind != 'UNSET' %> -bind <%= @conf_bind %> -<% end %> - -# Close the connection after a client is idle for N seconds (0 to disable) -timeout <%= @conf_timeout %> - -# Set server verbosity to 'debug' -# it can be one of: -# debug (a lot of information, useful for development/testing) -# notice (moderately verbose, what you want in production probably) -# warning (only very important / critical messages are logged) -loglevel <%= @conf_loglevel %> - -# Specify the log file name. Also 'stdout' can be used to force -# the demon to log on the standard output. Note that if you use standard -# output for logging but daemonize, logs will be sent to /dev/null -logfile <%= @conf_logfile_real %> - -# Set the number of databases. The default database is DB 0, you can select -# a different one on a per-connection basis using SELECT where -# dbid is a number between 0 and 'databases'-1 -databases <%= @conf_databases %> - -################################ SNAPSHOTTING ################################# -# -# Save the DB on disk: -# -# save -# -# Will save the DB if both the given number of seconds and the given -# number of write operations against the DB occurred. -# -# In the example below the behaviour will be to save: -# after 900 sec (15 min) if at least 1 key changed -# after 300 sec (5 min) if at least 10 keys changed -# after 60 sec if at least 10000 keys changed -<% if @conf_nosave != 'UNSET' %> -#do not persist to disk: -#save 900 1 -#save 300 10 -#save 60 10000 -<% else %> - <% if @conf_save != 'UNSET' %> - save <%= @conf_save %> - <% else %> - save 900 1 - save 300 10 - save 60 10000 - <% end %> -<% end %> - -# Compress string objects using LZF when dump .rdb databases? -# For default that's set to 'yes' as it's almost always a win. -# If you want to save some CPU in the saving child set it to 'no' but -# the dataset will likely be bigger if you have compressible values or keys. -rdbcompression <%= @conf_rdbcompression %> - -# The filename where to dump the DB -dbfilename <%= @conf_dbfilename %> - -# For default save/load DB in/from the working directory -# Note that you must specify a directory not a file name. -dir <%= @conf_dir %> - -################################# REPLICATION ################################# - -# Master-Slave replication. Use slaveof to make a Redis instance a copy of -# another Redis server. Note that the configuration is local to the slave -# so for example it is possible to configure the slave to save the DB with a -# different interval, or to listen to another port, and so on. -# -# slaveof -<% if @conf_slaveof != 'UNSET' %> -slaveof <%= @conf_slaveof %> -<% end %> - -# If the master is password protected (using the "requirepass" configuration -# directive below) it is possible to tell the slave to authenticate before -# starting the replication synchronization process, otherwise the master will -# refuse the slave request. -# -# masterauth -<% if @conf_masterauth != 'UNSET' %> -masterauth <%= @conf_masterauth %> -<% end %> - - -################################## SECURITY ################################### - -# Require clients to issue AUTH before processing any other -# commands. This might be useful in environments in which you do not trust -# others with access to the host running redis-server. -# -# This should stay commented out for backward compatibility and because most -# people do not need auth (e.g. they run their own servers). -# -# requirepass foobared -<% if @conf_requirepass != 'UNSET' %> -requirepass <%= @conf_requirepass %> -<% end %> - - -################################### LIMITS #################################### - -# Set the max number of connected clients at the same time. By default there -# is no limit, and it's up to the number of file descriptors the Redis process -# is able to open. The special value '0' means no limts. -# Once the limit is reached Redis will close all the new connections sending -# an error 'max number of clients reached'. -# -# maxclients 128 -<% if @conf_maxclients != 'UNSET' %> -maxclients <%= @conf_maxclients %> -<% end %> - -# Don't use more memory than the specified amount of bytes. -# When the memory limit is reached Redis will try to remove keys with an -# EXPIRE set. It will try to start freeing keys that are going to expire -# in little time and preserve keys with a longer time to live. -# Redis will also try to remove objects from free lists if possible. -# -# If all this fails, Redis will start to reply with errors to commands -# that will use more memory, like SET, LPUSH, and so on, and will continue -# to reply to most read-only commands like GET. -# -# WARNING: maxmemory can be a good idea mainly if you want to use Redis as a -# 'state' server or cache, not as a real DB. When Redis is used as a real -# database the memory usage will grow over the weeks, it will be obvious if -# it is going to use too much memory in the long run, and you'll have the time -# to upgrade. With maxmemory after the limit is reached you'll start to get -# errors for write operations, and this may even lead to DB inconsistency. -# -# maxmemory -<% if @conf_maxmemory != 'UNSET' %> -maxmemory <%= @conf_maxmemory %> -<% end %> - -############################## APPEND ONLY MODE ############################### - -# By default Redis asynchronously dumps the dataset on disk. If you can live -# with the idea that the latest records will be lost if something like a crash -# happens this is the preferred way to run Redis. If instead you care a lot -# about your data and don't want to that a single record can get lost you should -# enable the append only mode: when this mode is enabled Redis will append -# every write operation received in the file appendonly.log. This file will -# be read on startup in order to rebuild the full dataset in memory. -# -# Note that you can have both the async dumps and the append only file if you -# like (you have to comment the "save" statements above to disable the dumps). -# Still if append only mode is enabled Redis will load the data from the -# log file at startup ignoring the dump.rdb file. -# -# The name of the append only file is "appendonly.log" -# -# IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append -# log file in background when it gets too big. - -appendonly <%= @conf_appendonly %> - -# The fsync() call tells the Operating System to actually write data on disk -# instead to wait for more data in the output buffer. Some OS will really flush -# data on disk, some other OS will just try to do it ASAP. -# -# Redis supports three different modes: -# -# no: don't fsync, just let the OS flush the data when it wants. Faster. -# always: fsync after every write to the append only log . Slow, Safest. -# everysec: fsync only if one second passed since the last fsync. Compromise. -# -# The default is "always" that's the safer of the options. It's up to you to -# understand if you can relax this to "everysec" that will fsync every second -# or to "no" that will let the operating system flush the output buffer when -# it want, for better performances (but if you can live with the idea of -# some data loss consider the default persistence mode that's snapshotting). - -appendfsync <%= @conf_appendfsync %> -# appendfsync everysec -# appendfsync no - -############################### ADVANCED CONFIG ############################### - -# Glue small output buffers together in order to send small replies in a -# single TCP packet. Uses a bit more CPU but most of the times it is a win -# in terms of number of queries per second. Use 'yes' if unsure. -<% if @conf_glueoutputbuf != 'UNSET' %> -glueoutputbuf <%= @conf_glueoutputbuf %> -<% end %> - -# Use object sharing. Can save a lot of memory if you have many common -# string in your dataset, but performs lookups against the shared objects -# pool so it uses more CPU and can be a bit slower. Usually it's a good -# idea. -# -# When object sharing is enabled (shareobjects yes) you can use -# shareobjectspoolsize to control the size of the pool used in order to try -# object sharing. A bigger pool size will lead to better sharing capabilities. -# In general you want this value to be at least the double of the number of -# very common strings you have in your dataset. -# -# WARNING: object sharing is experimental, don't enable this feature -# in production before of Redis 1.0-stable. Still please try this feature in -# your development environment so that we can test it better. -# shareobjects no -# shareobjectspoolsize 1024 diff --git a/puphpet/puppet/modules/redis/templates/redis.logrotate.erb b/puphpet/puppet/modules/redis/templates/redis.logrotate.erb deleted file mode 100644 index b9ba724..0000000 --- a/puphpet/puppet/modules/redis/templates/redis.logrotate.erb +++ /dev/null @@ -1,9 +0,0 @@ -<%= @conf_logfile_real %> { - weekly - rotate 10 - copytruncate - delaycompress - compress - notifempty - missingok -} diff --git a/puphpet/puppet/modules/redis/tests/init.pp b/puphpet/puppet/modules/redis/tests/init.pp deleted file mode 100644 index b985981..0000000 --- a/puphpet/puppet/modules/redis/tests/init.pp +++ /dev/null @@ -1,15 +0,0 @@ -node default { - - package { 'epel-release': - ensure => present, - source => 'http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm', - provider => rpm, - } - - class { 'redis': - conf_port => '6379', - conf_bind => '0.0.0.0', - system_sysctl => true, - } - -} diff --git a/puphpet/puppet/modules/rvm/Gemfile b/puphpet/puppet/modules/rvm/Gemfile index c3b9b96..e65e84b 100644 --- a/puphpet/puppet/modules/rvm/Gemfile +++ b/puphpet/puppet/modules/rvm/Gemfile @@ -6,11 +6,11 @@ source 'https://rubygems.org' gem 'puppet', ENV['PUPPET_VERSION'] || '>= 3.0', :require => false gem 'rake', :require => false -gem 'rspec-puppet', '>= 1.0.0', :require => false +gem 'rspec-puppet', '>= 2.1.0', :require => false gem 'puppetlabs_spec_helper', '>= 0.8.0', :require => false gem 'puppet-lint', '>= 1.1.0', :require => false gem 'simplecov', :require => false -gem 'puppet-blacksmith', '>= 3.3.0', :require => false +gem 'puppet-blacksmith', '>= 3.3.1', :require => false gem 'librarian-puppet', '>= 2.0.0', :require => false gem 'beaker-rspec', '>= 3.0.0', :require => false diff --git a/puphpet/puppet/modules/rvm/Gemfile.lock b/puphpet/puppet/modules/rvm/Gemfile.lock index b306825..ca37d9d 100644 --- a/puphpet/puppet/modules/rvm/Gemfile.lock +++ b/puphpet/puppet/modules/rvm/Gemfile.lock @@ -2,64 +2,71 @@ GEM remote: https://rubygems.org/ specs: CFPropertyList (2.3.1) - activemodel (3.2.21) - activesupport (= 3.2.21) - builder (~> 3.0.0) - activesupport (3.2.21) - i18n (~> 0.6, >= 0.6.4) - multi_json (~> 1.0) - addressable (2.3.7) + activemodel (4.2.3) + activesupport (= 4.2.3) + builder (~> 3.1) + activesupport (4.2.3) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.3.8) autoparse (0.3.3) addressable (>= 2.3.1) extlib (>= 0.9.15) multi_json (>= 1.0.0) - aws-sdk (1.63.0) - aws-sdk-v1 (= 1.63.0) - aws-sdk-v1 (1.63.0) + aws-sdk (1.64.0) + aws-sdk-v1 (= 1.64.0) + aws-sdk-v1 (1.64.0) json (~> 1.4) nokogiri (>= 1.4.4) - beaker (2.8.0) + beaker (2.16.0) aws-sdk (~> 1.57) docker-api fission (~> 0.4) fog (~> 1.25) google-api-client (~> 0.8) - hocon (~> 0.0.4) + hocon (~> 0.1) inifile (~> 2.0) json (~> 1.8) minitest (~> 5.4) net-scp (~> 1.2) net-ssh (~> 2.9) + open_uri_redirections (~> 0.2.1) rbvmomi (~> 1.8) rsync (~> 1.0.9) unf (~> 0.1) - beaker-rspec (5.0.1) + beaker-rspec (5.1.0) beaker (~> 2.0) rspec serverspec (~> 2) specinfra (~> 2) - builder (3.0.4) + builder (3.2.2) diff-lcs (1.2.5) docile (1.1.5) - docker-api (1.20.0) + docker-api (1.21.4) excon (>= 0.38.0) json - domain_name (0.5.23) + domain_name (0.5.24) unf (>= 0.0.5, < 1.0.0) - excon (0.45.0) + excon (0.45.3) extlib (0.9.16) facter (1.7.6) faraday (0.9.1) multipart-post (>= 1.2, < 3) fission (0.5.0) CFPropertyList (~> 2.2) - fog (1.28.0) + fog (1.32.0) fog-atmos - fog-aws (~> 0.0) + fog-aws (>= 0.6.0) fog-brightbox (~> 0.4) - fog-core (~> 1.27, >= 1.27.3) - fog-ecloud + fog-core (~> 1.32) + fog-ecloud (= 0.1.1) + fog-google (>= 0.0.2) fog-json + fog-local + fog-powerdns (>= 0.1.1) fog-profitbricks fog-radosgw (>= 0.0.2) fog-riakcs @@ -76,32 +83,43 @@ GEM fog-atmos (0.1.0) fog-core fog-xml - fog-aws (0.1.1) + fog-aws (0.7.1) fog-core (~> 1.27) fog-json (~> 1.0) fog-xml (~> 0.1) ipaddress (~> 0.8) - fog-brightbox (0.7.1) + fog-brightbox (0.7.2) fog-core (~> 1.22) fog-json inflecto (~> 0.0.2) - fog-core (1.29.0) + fog-core (1.32.0) builder - excon (~> 0.38) + excon (~> 0.45) formatador (~> 0.2) mime-types net-scp (~> 1.1) net-ssh (>= 2.1.3) - fog-ecloud (0.0.2) + fog-ecloud (0.1.1) fog-core fog-xml - fog-json (1.0.0) - multi_json (~> 1.0) - fog-profitbricks (0.0.2) + fog-google (0.0.7) + fog-core + fog-json + fog-xml + fog-json (1.0.2) + fog-core (~> 1.0) + multi_json (~> 1.10) + fog-local (0.2.1) + fog-core (~> 1.27) + fog-powerdns (0.1.1) + fog-core (~> 1.27) + fog-json (~> 1.0) + fog-xml (~> 0.1) + fog-profitbricks (0.0.3) fog-core fog-xml nokogiri - fog-radosgw (0.0.3) + fog-radosgw (0.0.4) fog-core (>= 1.21.0) fog-json fog-xml (>= 0.0.1) @@ -109,33 +127,33 @@ GEM fog-core fog-json fog-xml - fog-sakuracloud (1.0.0) + fog-sakuracloud (1.0.1) fog-core fog-json - fog-serverlove (0.1.1) + fog-serverlove (0.1.2) fog-core fog-json - fog-softlayer (0.4.1) + fog-softlayer (0.4.7) fog-core fog-json - fog-storm_on_demand (0.1.0) + fog-storm_on_demand (0.1.1) fog-core fog-json - fog-terremark (0.0.4) + fog-terremark (0.1.0) fog-core fog-xml - fog-vmfusion (0.0.1) + fog-vmfusion (0.1.0) fission fog-core - fog-voxel (0.0.2) + fog-voxel (0.1.0) fog-core fog-xml - fog-xml (0.1.1) + fog-xml (0.1.2) fog-core nokogiri (~> 1.5, >= 1.5.11) formatador (0.2.5) - google-api-client (0.8.4) - activesupport (~> 3.2) + google-api-client (0.8.6) + activesupport (>= 3.2) addressable (~> 2.3) autoparse (~> 0.3) extlib (~> 0.9) @@ -145,47 +163,47 @@ GEM multi_json (~> 1.10) retriable (~> 1.4) signet (~> 0.6) - googleauth (0.4.0) + googleauth (0.4.1) faraday (~> 0.9) jwt (~> 1.4) - logging (~> 1.8) - memoist (~> 0.11) + logging (~> 2.0) + memoist (~> 0.12) multi_json (= 1.11) signet (~> 0.6) - her (0.7.4) - activemodel (>= 3.0.0, <= 4.2.1) - activesupport (>= 3.0.0, <= 4.2.1) + her (0.7.6) + activemodel (>= 3.0.0, <= 4.3.0) + activesupport (>= 3.0.0, <= 4.3.0) faraday (>= 0.8, < 1.0) multi_json (~> 1.7) hiera (1.3.4) json_pure - hocon (0.0.7) + hocon (0.9.2) http-cookie (1.0.2) domain_name (~> 0.5) i18n (0.7.0) inflecto (0.0.2) inifile (2.0.2) ipaddress (0.8.0) - json (1.8.2) + json (1.8.3) json_pure (1.8.2) - jwt (1.4.1) + jwt (1.5.1) launchy (2.4.3) addressable (~> 2.3) - librarian-puppet (2.1.0) - librarianp (>= 0.5.1) - puppet_forge + librarian-puppet (2.2.1) + librarianp (>= 0.6.3) + puppet_forge (~> 1.0) rsync - librarianp (0.6.2) + librarianp (0.6.3) thor (~> 0.15) little-plugger (1.1.3) - logging (1.8.2) - little-plugger (>= 1.1.3) - multi_json (>= 1.8.4) - memoist (0.11.0) + logging (2.0.0) + little-plugger (~> 1.1) + multi_json (~> 1.10) + memoist (0.12.0) metaclass (0.0.4) - mime-types (2.4.3) + mime-types (2.6.1) mini_portile (0.6.2) - minitest (5.5.1) + minitest (5.7.0) mocha (1.1.0) metaclass (~> 0.0.1) multi_json (1.11.0) @@ -193,9 +211,11 @@ GEM net-scp (1.2.1) net-ssh (>= 2.6.5) net-ssh (2.9.2) + net-telnet (0.1.1) netrc (0.10.3) nokogiri (1.6.6.2) mini_portile (~> 0.6.0) + open_uri_redirections (0.2.1) puppet (3.6.2) facter (> 1.6, < 3) hiera (~> 1.0) @@ -209,7 +229,7 @@ GEM rake puppet_forge (1.0.4) her (~> 0.6) - puppetlabs_spec_helper (0.10.1) + puppetlabs_spec_helper (0.10.3) mocha puppet-lint puppet-syntax @@ -226,49 +246,55 @@ GEM netrc (~> 0.7) retriable (1.4.1) rgen (0.6.6) - rspec (3.2.0) - rspec-core (~> 3.2.0) - rspec-expectations (~> 3.2.0) - rspec-mocks (~> 3.2.0) - rspec-core (3.2.2) - rspec-support (~> 3.2.0) - rspec-expectations (3.2.0) + rspec (3.3.0) + rspec-core (~> 3.3.0) + rspec-expectations (~> 3.3.0) + rspec-mocks (~> 3.3.0) + rspec-core (3.3.1) + rspec-support (~> 3.3.0) + rspec-expectations (3.3.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.2.0) + rspec-support (~> 3.3.0) rspec-its (1.2.0) rspec-core (>= 3.0.0) rspec-expectations (>= 3.0.0) - rspec-mocks (3.2.1) + rspec-mocks (3.3.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.2.0) - rspec-puppet (2.0.1) + rspec-support (~> 3.3.0) + rspec-puppet (2.2.0) rspec - rspec-support (3.2.2) + rspec-support (3.3.0) rsync (1.0.9) - serverspec (2.13.0) + serverspec (2.19.0) multi_json rspec (~> 3.0) rspec-its - specinfra (~> 2.25) - signet (0.6.0) + specinfra (~> 2.35) + sfl (2.2) + signet (0.6.1) addressable (~> 2.3) extlib (~> 0.9) faraday (~> 0.9) - jwt (~> 1.0) + jwt (~> 1.5) multi_json (~> 1.10) - simplecov (0.9.2) + simplecov (0.10.0) docile (~> 1.1.0) - multi_json (~> 1.0) - simplecov-html (~> 0.9.0) - simplecov-html (0.9.0) - specinfra (2.27.0) + json (~> 1.8) + simplecov-html (~> 0.10.0) + simplecov-html (0.10.0) + specinfra (2.37.0) net-scp net-ssh + net-telnet + sfl thor (0.19.1) + thread_safe (0.3.5) trollop (2.1.2) + tzinfo (1.2.2) + thread_safe (~> 0.1) unf (0.1.4) unf_ext - unf_ext (0.0.6) + unf_ext (0.0.7.1) PLATFORMS ruby @@ -277,9 +303,9 @@ DEPENDENCIES beaker-rspec (>= 3.0.0) librarian-puppet (>= 2.0.0) puppet (~> 3.6.0) - puppet-blacksmith (>= 3.3.0) + puppet-blacksmith (>= 3.3.1) puppet-lint (>= 1.1.0) puppetlabs_spec_helper (>= 0.8.0) rake - rspec-puppet (>= 1.0.0) + rspec-puppet (>= 2.1.0) simplecov diff --git a/puphpet/puppet/modules/rvm/Puppetfile.lock b/puphpet/puppet/modules/rvm/Puppetfile.lock index 0d443b5..4667ec3 100644 --- a/puphpet/puppet/modules/rvm/Puppetfile.lock +++ b/puphpet/puppet/modules/rvm/Puppetfile.lock @@ -1,6 +1,7 @@ FORGE remote: https://forgeapi.puppetlabs.com specs: + golja-gnupg (1.2.0) puppetlabs-apache (1.1.0) puppetlabs-concat (>= 1.0.0) puppetlabs-stdlib (>= 2.4.0) @@ -9,6 +10,7 @@ FORGE puppetlabs-stdlib (4.5.1) DEPENDENCIES + golja-gnupg (>= 1.2.0) puppetlabs-apache (>= 1.1.0) puppetlabs-stdlib (>= 4.2.0) diff --git a/puphpet/puppet/modules/rvm/README.markdown b/puphpet/puppet/modules/rvm/README.markdown index ae0115f..77da7eb 100644 --- a/puphpet/puppet/modules/rvm/README.markdown +++ b/puphpet/puppet/modules/rvm/README.markdown @@ -26,7 +26,9 @@ Puppet 3.0.0 or higher. ## Upgrading -Version 1.5 no longer includes a dependency on puppetlabs/apache, you must install it yourself +* 1.12: uses [golja-gnupg](https://forge.puppetlabs.com/golja/gnupg) module +to manage the installation of the gpg key. +* 1.5: no longer includes a dependency on puppetlabs/apache, you must install it yourself if you want to use the passenger module. ## Add Puppet Module @@ -40,13 +42,7 @@ You may now continue configuring RVM resources. ## Install RVM with Puppet -Install RVM with: - - include rvm - -or - - class { 'rvm': version => '1.20.12' } + class { '::rvm': } This will install RVM into `/usr/local/rvm`. @@ -54,6 +50,13 @@ To use RVM without sudo, users need to be added to the `rvm` group. This can be rvm::system_user { bturner: ; jdoe: ; jsmith: ; } +If GPG is installed, installing RVM requires the RVM GPG key. +This module will install the key if `gpg` is already installed or being installed with the +[`golja-gnupg`](https://forge.puppetlabs.com/golja/gnupg) module. + +If you don't want this module to install the gpg key just set to false the `gpg_key_id` parameter + + class { '::rvm': gnupg_key_id => false } ## Installing Ruby diff --git a/puphpet/puppet/modules/rvm/Rakefile b/puphpet/puppet/modules/rvm/Rakefile index 6e452c1..466d7a1 100644 --- a/puphpet/puppet/modules/rvm/Rakefile +++ b/puphpet/puppet/modules/rvm/Rakefile @@ -9,7 +9,6 @@ require 'puppet_blacksmith/rake_tasks' CLEAN.include('spec/fixtures/manifests/', 'spec/fixtures/modules/', 'doc', 'pkg') CLOBBER.include('.tmp', '.librarian') -ENV['STRICT_VARIABLES']='yes' unless Gem::Version.new(Puppet.version) < Gem::Version.new("3.5.0") task :librarian_spec_prep do sh "librarian-puppet install --path=spec/fixtures/modules/" diff --git a/puphpet/puppet/modules/rvm/checksums.json b/puphpet/puppet/modules/rvm/checksums.json index 07f103b..8bea519 100644 --- a/puphpet/puppet/modules/rvm/checksums.json +++ b/puphpet/puppet/modules/rvm/checksums.json @@ -1,11 +1,11 @@ { - "Gemfile": "e22f8c7a1a9e08169f644db6623a6ceb", - "Gemfile.lock": "57623b258376075027550a2e5147cc87", + "Gemfile": "a8b077ddeb33c19277f272d9bf9d3151", + "Gemfile.lock": "cc4cdb889ae3574b45b15ac4d37bfe06", "LICENSE": "c09f1ff12ffc19bb5aa3ca918d6496c7", "Puppetfile": "3e0e8b7a7a4cbc0d7d9dc17318042ba1", - "Puppetfile.lock": "0af98f627c930c019b8cf27275755fee", - "README.markdown": "31385112eed259817af430441fedae5a", - "Rakefile": "6b17151aa2542da1e1762a712b53fb30", + "Puppetfile.lock": "d7147b2e03aa71006200f11b56c8fdec", + "README.markdown": "28926de01a8014558e52f308612a0b0f", + "Rakefile": "78ea614b4262234dc92489017f039d27", "lib/facter/rvm_installed.rb": "17880333546300f31ee0b924dc0e7135", "lib/facter/rvm_version.rb": "83ce2d25f399adbcbc04c9f441066c8b", "lib/puppet/provider/rvm_alias/alias.rb": "7f422f68856ffa399a7d564fc7cdc62e", @@ -22,34 +22,36 @@ "manifests/dependencies/oraclelinux.pp": "3f60f61da00a2e41109058fe70ed7536", "manifests/dependencies/ubuntu.pp": "c18938a26d927f3c4f3a64bddd3b1948", "manifests/dependencies.pp": "421d1b11cb1395ee0d2f3763e75d8c72", - "manifests/gpg.pp": "f08fe68d273591aa86de372a6dc2af25", + "manifests/gnupg_key.pp": "62b190beebda0b14e78d031c6622e4fc", + "manifests/gpg.pp": "eb3ed96b79c9b95a3f56a3f59ed106da", "manifests/group.pp": "ac396e22475220c972a6777ea03f26b8", - "manifests/init.pp": "fca3cc39a66b8e2f3e8250d12c373469", - "manifests/params.pp": "a3c69aa0c4b1e151cfc52078f3ddb3f1", + "manifests/init.pp": "bb57c68415fe4abfa73a6bd4fa2edc14", + "manifests/params.pp": "c40acedd00b9fc2802a68abfa6a9104f", "manifests/passenger/apache.pp": "2df4eb774a759493c54cd15ad54a21fd", "manifests/passenger/dependencies/centos.pp": "11c1f59ccdc4cead38a9fa550bb03812", "manifests/passenger/dependencies/oraclelinux.pp": "388ca20676c972d2a85790374adae45f", "manifests/passenger/dependencies/ubuntu.pp": "1a61e3cb072c82f68d8ff604f1e59e47", "manifests/passenger/dependencies.pp": "e819338156ed5965ebdbc76f6b698a75", "manifests/passenger/gem.pp": "80587f1bc2beab8b91f3b54932e60e7c", - "manifests/rvmrc.pp": "14a480ba714374f89b32cb34a0a153f9", - "manifests/system.pp": "eeb89b83ab2e1863013b5f2927974aeb", + "manifests/rvmrc.pp": "96bc8d0edd1cfdb69a5a7e154ae66573", + "manifests/system.pp": "ed97f5bf073dd0d01b64ded4d5587ef0", "manifests/system_user.pp": "0f672b3b0ff4e08487af384ccd527bc0", - "metadata.json": "3da00872f712f3f69dc98ce03d85c974", + "metadata.json": "7978c22b173df3e9552f55afceaa6bd7", "spec/acceptance/nodesets/centos-65-x64-docker.yml": "9674bdbae4ed3135a8567b5f7a3105ff", "spec/acceptance/nodesets/centos-65-x64.yml": "93493768080a4d0f2d04ef7d75b717a5", "spec/acceptance/nodesets/debian-7-x64-docker.yml": "3b89e3555ba378b350ff898de2bed74a", "spec/acceptance/nodesets/debian-7-x64.yml": "49a054626b92ba240aa09c2fac824a73", "spec/acceptance/nodesets/debian-73-x64.yml": "d93ed0079254ebb6a603d829acea77ef", - "spec/acceptance/nodesets/default.yml": "9674bdbae4ed3135a8567b5f7a3105ff", + "spec/acceptance/nodesets/default.yml": "6b0981c1efbef8993c9bd49163ca403d", "spec/acceptance/nodesets/ubuntu-server-1404-x64-docker.yml": "452fa39e36c94494eee5a4a602a918f5", "spec/acceptance/nodesets/ubuntu-server-1404-x64.yml": "ec5f2ace9479ea9c625ef8764b6c2557", "spec/acceptance/rvm_system_spec.rb": "2aee82eb49bd0117b9ace79ce0de4a17", "spec/classes/dependencies_spec.rb": "d40ac9bd6ce9b4bf96d8fc2ce5740b6c", - "spec/classes/gpg_spec.rb": "3d3e08524633d06503bf389520142509", - "spec/classes/init_spec.rb": "5d9e586ced348a534ddce6d900360849", + "spec/classes/gnupg_key_spec.rb": "f8ac907a4829208a07dffb17082724d5", + "spec/classes/gpg_spec.rb": "d8ed63bf7c3d833dc299e8137a25a5b2", + "spec/classes/init_spec.rb": "60a932fc8bd097227f03a591bb933157", "spec/classes/rvmrc_spec.rb": "8a89f89ca9b7b9ec1d5c9bc2868be646", - "spec/classes/system_spec.rb": "b600c9c32b01128fa8ae961d3d137c9d", + "spec/classes/system_spec.rb": "e2b57b98a48bbaa36d5e44a12bcc04e1", "spec/defines/rvm_alias_spec.rb": "83c263ca60fd32aec9fbccc8f3679e83", "spec/defines/rvm_gem_spec.rb": "c26c78f19676b8a03e96bd30625ab2fb", "spec/defines/rvm_gemset_spec.rb": "ae6518149a7100a1f35a80a919b1f55f", @@ -57,8 +59,8 @@ "spec/defines/rvm_wrapper_spec.rb": "a37c75e48716ce92e2ad5381c821397f", "spec/defines/system_user_spec.rb": "7899c7147abbc4c3a9f7f0c5e3f0e81a", "spec/fixtures/hiera.yaml": "37ca9bf76ec6d6a251fdcc6c559a3619", - "spec/spec_helper.rb": "030960a9be1f4a9e6b28de3d781519b9", + "spec/spec_helper.rb": "3ce7855a3a830837a3c338b33cf38baa", "spec/spec_helper_acceptance.rb": "2899ac6512eea19a0b09fe68c123ac1f", - "templates/rvmrc.erb": "a3e3e312817a572a6f148891d27d7d86", + "templates/rvmrc.erb": "3e6e47c115ed6136278c476b090bcada", "tests/init.pp": "7096c96ab9b56ee1dab6e2b5754e770a" } \ No newline at end of file diff --git a/puphpet/puppet/modules/rvm/manifests/gnupg_key.pp b/puphpet/puppet/modules/rvm/manifests/gnupg_key.pp new file mode 100644 index 0000000..1c0c6c2 --- /dev/null +++ b/puphpet/puppet/modules/rvm/manifests/gnupg_key.pp @@ -0,0 +1,15 @@ +# RVM's GPG key import + +class rvm::gnupg_key( + $key_id = $rvm::params::gnupg_key_id, + $key_server = $rvm::params::key_server) inherits rvm::params { + + gnupg_key { "rvm_${key_id}": + ensure => present, + key_id => $key_id, + user => 'root', + key_server => $key_server, + key_type => public, + } + +} diff --git a/puphpet/puppet/modules/rvm/manifests/gpg.pp b/puphpet/puppet/modules/rvm/manifests/gpg.pp index a2cdefa..edd8b21 100644 --- a/puphpet/puppet/modules/rvm/manifests/gpg.pp +++ b/puphpet/puppet/modules/rvm/manifests/gpg.pp @@ -1,5 +1,7 @@ # RVM's GPG key security signing mechanism requires gpg2 for key import / validation class rvm::gpg($package = $rvm::params::gpg_package) inherits rvm::params { - ensure_packages([$package]) + + class { '::gnupg': } + } diff --git a/puphpet/puppet/modules/rvm/manifests/init.pp b/puphpet/puppet/modules/rvm/manifests/init.pp index 342f80c..69a47eb 100644 --- a/puphpet/puppet/modules/rvm/manifests/init.pp +++ b/puphpet/puppet/modules/rvm/manifests/init.pp @@ -9,7 +9,8 @@ $rvm_gems={}, $proxy_url=$rvm::params::proxy_url, $no_proxy=$rvm::params::no_proxy, - $key_server=$rvm::params::key_server) inherits rvm::params { + $key_server=$rvm::params::key_server, + $gnupg_key_id=$rvm::params::gnupg_key_id) inherits rvm::params { if $install_rvm { @@ -25,10 +26,11 @@ } class { 'rvm::system': - version => $version, - proxy_url => $proxy_url, - no_proxy => $no_proxy, - key_server => $key_server + version => $version, + proxy_url => $proxy_url, + no_proxy => $no_proxy, + key_server => $key_server, + gnupg_key_id => $gnupg_key_id, } } diff --git a/puphpet/puppet/modules/rvm/manifests/params.pp b/puphpet/puppet/modules/rvm/manifests/params.pp index 03686bb..838793a 100644 --- a/puphpet/puppet/modules/rvm/manifests/params.pp +++ b/puphpet/puppet/modules/rvm/manifests/params.pp @@ -7,8 +7,16 @@ $proxy_url = undef $no_proxy = undef - $key_server = 'keys.gnupg.net' + $key_server = 'hkp://keys.gnupg.net' + # install the gpg key if gpg is installed or being installed in this puppet run + if defined(Class['::gnupg']) or $::gnupg_installed { + $gnupg_key_id = 'D39DC0E3' + } else { + $gnupg_key_id = false + } + + # ignored param, using gnupg module $gpg_package = $::kernel ? { /(Linux|Darwin)/ => 'gnupg2', default => undef, diff --git a/puphpet/puppet/modules/rvm/manifests/rvmrc.pp b/puphpet/puppet/modules/rvm/manifests/rvmrc.pp index ab5aeda..6870304 100644 --- a/puphpet/puppet/modules/rvm/manifests/rvmrc.pp +++ b/puphpet/puppet/modules/rvm/manifests/rvmrc.pp @@ -4,7 +4,7 @@ $template = 'rvm/rvmrc.erb', $umask = 'u=rwx,g=rwx,o=rx', $max_time_flag = undef, - $autoupdate_flag = '0', + $autoupdate_flag = 0, $silence_path_mismatch_check_flag = undef) inherits rvm::params { if $manage_group { include rvm::group } diff --git a/puphpet/puppet/modules/rvm/manifests/system.pp b/puphpet/puppet/modules/rvm/manifests/system.pp index eab79c9..e0d98d1 100644 --- a/puphpet/puppet/modules/rvm/manifests/system.pp +++ b/puphpet/puppet/modules/rvm/manifests/system.pp @@ -4,7 +4,8 @@ $proxy_url=undef, $no_proxy=undef, $key_server=undef, - $home=$::root_home) { + $home=$::root_home, + $gnupg_key_id=$rvm::params::gnupg_key_id) inherits rvm::params { $actual_version = $version ? { undef => 'latest', @@ -22,7 +23,7 @@ default: {} } } - + $http_proxy_environment = $proxy_url ? { undef => [], default => ["http_proxy=${proxy_url}", "https_proxy=${proxy_url}"] @@ -34,14 +35,14 @@ $proxy_environment = concat($http_proxy_environment, $no_proxy_environment) $environment = concat($proxy_environment, ["HOME=${home}"]) - # ignore gpg check if it is not installed, same as rvm does - exec { 'system-rvm-gpg-key': - command => "which gpg && gpg --keyserver hkp://${key_server} --recv-keys D39DC0E3", - path => '/usr/bin:/usr/sbin:/bin', - environment => $environment, - unless => 'which gpg && gpg --list-keys D39DC0E3', - onlyif => 'which gpg', - } -> + # install the gpg key + if $gnupg_key_id { + class { 'rvm::gnupg_key': + key_server => $key_server, + key_id => $gnupg_key_id, + before => Exec['system-rvm'], + } + } exec { 'system-rvm': path => '/usr/bin:/usr/sbin:/bin', @@ -53,6 +54,11 @@ # the fact won't work until rvm is installed before puppet starts if !empty($::rvm_version) { if ($version != undef) and ($version != present) and ($version != $::rvm_version) { + + if defined(Class['rvm::gnupg_key']) { + Class['rvm::gnupg_key'] -> Exec['system-rvm-get'] + } + # Update the rvm installation to the version specified notify { 'rvm-get_version': message => "RVM updating from version ${::rvm_version} to ${version}", @@ -62,7 +68,6 @@ command => "rvm get ${version}", before => Exec['system-rvm'], # so it doesn't run after being installed the first time environment => $environment, - require => Exec['system-rvm-gpg-key'], } } } diff --git a/puphpet/puppet/modules/rvm/metadata.json b/puphpet/puppet/modules/rvm/metadata.json index e8c1784..4a3bcb1 100644 --- a/puphpet/puppet/modules/rvm/metadata.json +++ b/puphpet/puppet/modules/rvm/metadata.json @@ -1,12 +1,16 @@ { "name": "maestrodev-rvm", - "version": "1.11.0", + "version": "1.12.1", "author": "maestrodev & Brandon Turner ", "summary": "A puppet module for installing and using RVM (Ruby Version Manager)", "license": "Modified BSD License", "source": "http://github.com/maestrodev/puppet-rvm", "project_page": "http://github.com/maestrodev/puppet-rvm", "issues_url": "https://github.com/maestrodev/puppet-rvm/issues", + "dependencies": [ + {"name":"puppetlabs/stdlib","version_requirement":">=4.2.0"}, + {"name":"golja/gnupg","version_requirement":">=1.2.0"} + ], "description": "Installing and using RVM (Ruby Version Manager)", "operatingsystem_support": [ { @@ -112,8 +116,5 @@ "name": "puppet", "version_requirement": ">=3.0.0" } - ], - "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":">=4.2.0"} ] } diff --git a/puphpet/puppet/modules/rvm/spec/acceptance/nodesets/default.yml b/puphpet/puppet/modules/rvm/spec/acceptance/nodesets/default.yml index 7ec622e..f01a395 100644 --- a/puphpet/puppet/modules/rvm/spec/acceptance/nodesets/default.yml +++ b/puphpet/puppet/modules/rvm/spec/acceptance/nodesets/default.yml @@ -12,12 +12,6 @@ HOSTS: docker_image_commands: - yum -y install tar - useradd vagrant - - "sed -ri 's/^#?PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config" - - "sed -ri 's/^#?PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config" - docker_cmd: - - 'sh' - - '-c' - - 'service sshd start; tail -f /dev/null' CONFIG: log_level: debug type: git diff --git a/puphpet/puppet/modules/rvm/spec/classes/gnupg_key_spec.rb b/puphpet/puppet/modules/rvm/spec/classes/gnupg_key_spec.rb new file mode 100644 index 0000000..dc2b1a2 --- /dev/null +++ b/puphpet/puppet/modules/rvm/spec/classes/gnupg_key_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +describe 'rvm::gnupg_key', :compile do + + let(:facts) {{ :gnupg_installed => true }} + + it { should contain_gnupg_key('rvm_D39DC0E3') } + +end diff --git a/puphpet/puppet/modules/rvm/spec/classes/gpg_spec.rb b/puphpet/puppet/modules/rvm/spec/classes/gpg_spec.rb index 5ae9d55..06b3f96 100644 --- a/puphpet/puppet/modules/rvm/spec/classes/gpg_spec.rb +++ b/puphpet/puppet/modules/rvm/spec/classes/gpg_spec.rb @@ -7,7 +7,7 @@ :kernel => 'Linux', :osfamily => 'RedHat' }} - it { should contain_package('gnupg2') } + it { should contain_package('gnupg') } end context "Debian", :compile do @@ -15,14 +15,15 @@ :kernel => 'Linux', :osfamily => 'Debian' }} - it { should contain_package('gnupg2') } + it { should contain_package('gnupg') } end - context "OS X", :compile do - let(:facts) {{ - :kernel => 'Darwin', - :osfamily => 'Darwin' - }} - it { should contain_package('gnupg2') } - end + # Not supported by gnupg module + # context "OS X", :compile do + # let(:facts) {{ + # :kernel => 'Darwin', + # :osfamily => 'Darwin' + # }} + # it { should contain_package('gnupg') } + # end end diff --git a/puphpet/puppet/modules/rvm/spec/classes/init_spec.rb b/puphpet/puppet/modules/rvm/spec/classes/init_spec.rb index fcc8b64..c70188c 100644 --- a/puphpet/puppet/modules/rvm/spec/classes/init_spec.rb +++ b/puphpet/puppet/modules/rvm/spec/classes/init_spec.rb @@ -44,4 +44,11 @@ it { should contain_rvm__system_user('john') } it { should contain_rvm__system_user('doe') } end + + context "with no gnupg key id", :compile do + let(:params) {{ :gnupg_key_id => false }} + it { should_not contain_gnupg_key('rvm_D39DC0E3') } + it { should_not contain_gnupg_key('rvm_') } + end + end diff --git a/puphpet/puppet/modules/rvm/spec/classes/system_spec.rb b/puphpet/puppet/modules/rvm/spec/classes/system_spec.rb index 1d1b2f5..886ca98 100644 --- a/puphpet/puppet/modules/rvm/spec/classes/system_spec.rb +++ b/puphpet/puppet/modules/rvm/spec/classes/system_spec.rb @@ -37,4 +37,14 @@ it { should contain_exec('system-rvm-get').with_environment("[\"http_proxy=#{params[:proxy_url]}\", \"https_proxy=#{params[:proxy_url]}\", \"no_proxy=#{params[:no_proxy]}\", \"HOME=/root\"]") } end + context "with gnupg", :compile do + let(:pre_condition) { "class { '::gnupg': }" } + it { should contain_gnupg_key('rvm_D39DC0E3').with_key_id('D39DC0E3').with_key_server('hkp://keys.gnupg.net') } + end + + context "with gnupg customized", :compile do + let(:params) {{ :key_server => 'hkp://example.com', :gnupg_key_id => 'AAAAAAAA' }} + let(:pre_condition) { "class { '::gnupg': }" } + it { should contain_gnupg_key('rvm_AAAAAAAA').with_key_id('AAAAAAAA').with_key_server('hkp://example.com') } + end end diff --git a/puphpet/puppet/modules/rvm/spec/spec_helper.rb b/puphpet/puppet/modules/rvm/spec/spec_helper.rb index d26b672..d6f2d80 100644 --- a/puphpet/puppet/modules/rvm/spec/spec_helper.rb +++ b/puphpet/puppet/modules/rvm/spec/spec_helper.rb @@ -4,7 +4,6 @@ require 'puppetlabs_spec_helper/module_spec_helper' RSpec.configure do |c| - c.treat_symbols_as_metadata_keys_with_true_values = true c.mock_with :rspec c.hiera_config = File.expand_path(File.join(__FILE__, '../fixtures/hiera.yaml')) diff --git a/puphpet/puppet/modules/rvm/templates/rvmrc.erb b/puphpet/puppet/modules/rvm/templates/rvmrc.erb index ab802f7..8ebac6d 100644 --- a/puphpet/puppet/modules/rvm/templates/rvmrc.erb +++ b/puphpet/puppet/modules/rvm/templates/rvmrc.erb @@ -1,12 +1,12 @@ <% if @umask and !@umask.empty? -%> umask <%= @umask %> <% end -%> -<% if @max_time_flag and !@max_time_flag.empty? -%> +<% if @max_time_flag and !@max_time_flag.to_s.empty? -%> export rvm_max_time_flag=<%= @max_time_flag %> <% end -%> -<% if @autoupdate_flag and !@autoupdate_flag.empty? -%> +<% if @autoupdate_flag and !@autoupdate_flag.to_s.empty?-%> rvm_autoupdate_flag=<%= @autoupdate_flag %> <% end -%> -<% if @silence_path_mismatch_check_flag and !@silence_path_mismatch_check_flag.empty? -%> +<% if @silence_path_mismatch_check_flag and !@silence_path_mismatch_check_flag.to_s.empty? -%> rvm_silence_path_mismatch_check_flag=<%= @silence_path_mismatch_check_flag %> <%end -%> diff --git a/puphpet/puppet/modules/solr/.gitignore b/puphpet/puppet/modules/solr/.gitignore new file mode 100644 index 0000000..3d116dc --- /dev/null +++ b/puphpet/puppet/modules/solr/.gitignore @@ -0,0 +1,9 @@ +/.gradle +/metadata.json +/.rvmrc +build +pkg/ +Session.vim +spec/fixtures +.*.sw[a-z] +*.un~ diff --git a/puphpet/puppet/modules/solr/Modulefile b/puphpet/puppet/modules/solr/Modulefile index f9735b3..555953b 100644 --- a/puphpet/puppet/modules/solr/Modulefile +++ b/puphpet/puppet/modules/solr/Modulefile @@ -1,5 +1,5 @@ name 'example42-solr' -version '2.0.6' +version '2.0.7' author 'Alessandro Franceschi' license 'Apache2' diff --git a/puphpet/puppet/modules/solr/README.markdown b/puphpet/puppet/modules/solr/README.markdown index d6dbc6f..a21a2ef 100644 --- a/puphpet/puppet/modules/solr/README.markdown +++ b/puphpet/puppet/modules/solr/README.markdown @@ -1,5 +1,13 @@ # Puppet module: solr +## DEPRECATION NOTICE +This module is no more actively maintained and will hardly be updated. + +Please find an alternative module from other authors or consider [Tiny Puppet](https://github.com/example42/puppet-tp) as replacement. + +If you want to maintain this module, contact [Alessandro Franceschi](https://github.com/alvagante) + + This is a Puppet solr module from the second generation of Example42 Puppet Modules. Made by Alessandro Franceschi / Lab42 - http://www.example42.com diff --git a/puphpet/puppet/modules/solr/README.md b/puphpet/puppet/modules/solr/README.md index 7de932c..6991cf1 100644 --- a/puphpet/puppet/modules/solr/README.md +++ b/puphpet/puppet/modules/solr/README.md @@ -1,2 +1,6 @@ +## DEPRECATION NOTICE +This module is no more actively maintained and will hardly be updated. -[![Build Status](https://travis-ci.org/example42/puppet-solr.png?branch=master)](https://travis-ci.org/example42/puppet-solr) +Please find an alternative module from other authors or consider [Tiny Puppet](https://github.com/example42/puppet-tp) as replacement. + +If you want to maintain this module, contact [Alessandro Franceschi](https://github.com/alvagante) diff --git a/puphpet/puppet/modules/solr/manifests/init.pp b/puphpet/puppet/modules/solr/manifests/init.pp index aa1cefd..86d8001 100644 --- a/puphpet/puppet/modules/solr/manifests/init.pp +++ b/puphpet/puppet/modules/solr/manifests/init.pp @@ -193,7 +193,7 @@ } # Whole solr configuration directory can be recursively overriden - if $solr::source_dir { + if $solr::source_dir and $solr::source_dir != '' { file { 'solr.dir': ensure => directory, path => $solr::config_dir, diff --git a/puphpet/puppet/modules/stdlib/.gitignore b/puphpet/puppet/modules/stdlib/.gitignore new file mode 100644 index 0000000..37c4f59 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/.gitignore @@ -0,0 +1,12 @@ +/pkg/ +/Gemfile.lock +/vendor/ +/spec/fixtures/manifests/* +/spec/fixtures/modules/* +!/spec/fixtures/modules/stdlib +!/spec/fixtures/modules/stdlib/* +/.vagrant/ +/.bundle/ +/coverage/ +/.idea/ +*.iml diff --git a/puphpet/puppet/modules/stdlib/.travis.yml b/puphpet/puppet/modules/stdlib/.travis.yml index 503e184..6fad7a4 100644 --- a/puphpet/puppet/modules/stdlib/.travis.yml +++ b/puphpet/puppet/modules/stdlib/.travis.yml @@ -1,18 +1,21 @@ --- sudo: false language: ruby +cache: bundler bundler_args: --without system_tests script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake spec SPEC_OPTS='--color --format documentation'" matrix: fast_finish: true include: - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.6.0" - - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 2.7.0" FACTER_GEM_VERSION="~> 1.7.0" + env: PUPPET_GEM_VERSION="~> 3.0" - rvm: 1.9.3 env: PUPPET_GEM_VERSION="~> 3.0" - - rvm: 2.0.0 + - rvm: 2.1.5 env: PUPPET_GEM_VERSION="~> 3.0" + - rvm: 2.1.5 + env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes" + - rvm: 2.1.6 + env: PUPPET_GEM_VERSION="~> 4.0" STRICT_VARIABLES="yes" notifications: email: false diff --git a/puphpet/puppet/modules/stdlib/CHANGELOG.md b/puphpet/puppet/modules/stdlib/CHANGELOG.md index 1385695..2698dde 100644 --- a/puphpet/puppet/modules/stdlib/CHANGELOG.md +++ b/puphpet/puppet/modules/stdlib/CHANGELOG.md @@ -1,17 +1,147 @@ -##2015-01-14 - Supported Release 4.6.0 +## Supported Release 4.11.0 ###Summary -Improved functionality and preparing for Puppet Next with new parser +Provides a validate_absolute_paths and Debian 8 support. There is a fix to the is_package_provider fact and a test improvement. ####Features -- MODULES-444: concat can now take more than two arrays -- basename function added to have Ruby File.basename functionality -- delete function can now take an array of items to remove -- MODULES-1473: deprecate type function in favor of type_of +- Adds new parser called is_absolute_path +- Supports Debian 8 ####Bugfixes -- Several test case fixes -- Ensure_resource is more verbose on debug mode +- Allow package_provider fact to resolve on PE 3.x + +####Improvements +- ensures that the test passes independently of changes to rubygems for ensure_resource + +##2015-12-15 - Supported Release 4.10.0 +###Summary + +Includes the addition of several new functions and considerable improvements to the existing functions, tests and documentation. Includes some bug fixes which includes compatibility, test and fact issues. + +####Features +- Adds service_provider fact +- Adds is_a() function +- Adds package_provider fact +- Adds validate_ip_address function +- Adds seeded_rand function + +####Bugfixes +- Fix backwards compatibility from an improvement to the parseyaml function +- Renaming of load_module_metadata test to include _spec.rb +- Fix root_home fact on AIX 5.x, now '-c' rather than '-C' +- Fixed Gemfile to work with ruby 1.8.7 + +####Improvements +- (MODULES-2462) Improvement of parseyaml function +- Improvement of str2bool function +- Improvement to readme +- Improvement of intersection function +- Improvement of validate_re function +- Improved speed on Facter resolution of service_provider +- empty function now handles numeric values +- Package_provider now prevents deprecation warning about the allow_virtual parameter +- load_module_metadata now succeeds on empty file +- Check added to ensure puppetversion value is not nil +- Improvement to bool2str to return a string of choice using boolean +- Improvement to naming convention in validate_ipv4_address function + +## 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 @@ -75,7 +205,7 @@ backwards-compatible with the stdlib 3 series. It adds two new functions, one bu #### Features - New `bool2str()` function -- New `camalcase()` function +- New `camelcase()` function #### Bugfixes - Fix `has_interface_with()` when interfaces fact is nil @@ -278,7 +408,7 @@ This is a supported release * Add an ensure\_packages function. (8a8c09e) -##### 2012-11-23 - Erik Dalén - 3.2.0 +##### 2012-11-23 - Erik Dalén - 3.2.0 * (#17797) min() and max() functions (9954133) @@ -375,7 +505,7 @@ This is a supported release * Add support for a 'match' parameter to file\_line (a06c0d8) -##### 2012-08-07 - Erik Dalén - 2.4.0 +##### 2012-08-07 - Erik Dalén - 2.4.0 * (#15872) Add to\_bytes function (247b69c) diff --git a/puphpet/puppet/modules/stdlib/Gemfile b/puphpet/puppet/modules/stdlib/Gemfile index e1a59fa..8221514 100644 --- a/puphpet/puppet/modules/stdlib/Gemfile +++ b/puphpet/puppet/modules/stdlib/Gemfile @@ -11,22 +11,37 @@ def location_for(place, fake_version = nil) end group :development, :unit_tests do + # rspec must be v2 for ruby 1.8.7 + if RUBY_VERSION >= '1.8.7' and RUBY_VERSION < '1.9' + gem 'rspec', '~> 2.0' + else + gem 'rspec', '~> 3.1.0', :require => false + end + gem 'rake', '~> 10.1.0', :require => false - gem 'rspec', '~> 3.1.0', :require => false - gem 'rspec-puppet', :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) + 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 'beaker-rspec', :require => false - gem 'serverspec', :require => false + gem 'serverspec', :require => false + gem 'beaker-puppet_install_helper', :require => false end facterversion = ENV['GEM_FACTER_VERSION'] || ENV['FACTER_GEM_VERSION'] diff --git a/puphpet/puppet/modules/stdlib/README.markdown b/puphpet/puppet/modules/stdlib/README.markdown index 9c6a54b..a6ed1fb 100644 --- a/puphpet/puppet/modules/stdlib/README.markdown +++ b/puphpet/puppet/modules/stdlib/README.markdown @@ -16,8 +16,7 @@ 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: +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 @@ -38,23 +37,11 @@ After you've installed stdlib, all of its functions, facts, and resources are av If you want to use a standardized set of run stages for Puppet, `include stdlib` in your manifest. -## Reference - -### Classes - -#### Public Classes - * `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 class has no parameters. - -#### Private Classes - -* `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 `stdlib::stages` class declares various run stages for deploying infrastructure, language runtimes, and application layers. The high level stages are (in order): +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 @@ -67,78 +54,167 @@ If you want to use a standardized set of run stages for Puppet, `include stdlib` Sample usage: - ``` + ~~~ node default { include stdlib class { java: stage => 'runtime' } } - ``` + ~~~ -### Resources +## Reference -* `file_line`: This resource 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. +### Classes - ``` - 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', - } - ``` +#### 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 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 appends the line to the end of the file to ensure the desired state. Multiple resources can 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 ensures that both of the specified lines are contained in the file `/etc/sudoers`. + +Match Example: - * `after`: Specify the line after which Puppet will add any new lines. (Existing lines are added in place.) Optional. - * `ensure`: Ensures whether the resource is present. Valid values are 'present', 'absent'. - * `line`: The line to be added to the file located by the `path` parameter. - * `match`: A 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. Optional. - * `multiple`: Determine if match can change multiple lines. Valid values are 'true', 'false'. Optional. - * `name`: An arbitrary name used as the identity of the resource. - * `path`: The file in which Puppet will ensure the line specified by the line parameter. + 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` looks for a line beginning with export followed by HTTP_PROXY and replaces 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` looks 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 contains the line being managed, the `file_line` resource autorequires that file. + +##### Parameters + +All parameters are optional, unless otherwise noted. + +* `after`: Specifies the line after which Puppet adds 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. A regex comparison is performed against the line value, and if it does not match, an exception is raised. Valid options: String containing a regex. Default: Undefined. +* `match_for_absence`: 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` and the value of `line` is used instead. Default: false. +* `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 +#### `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. -* `any2array`: 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. *Type*: rvalue +#### `base64` -* `base64`: Converts a string to and from base64 encoding. -Requires an action ('encode', 'decode') and either a plain or base64-encoded -string. *Type*: rvalue +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: +#### `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 +*Type*: rvalue. + +#### `bool2num` -* `bool2num`: Converts a boolean to a number. Converts values: +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 + Requires a single boolean or string as an input. *Type*: rvalue. + +#### `bool2str` -* `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 +Converts a boolean to a string using optionally supplied arguments. The optional second and third arguments represent what true and false are converted to respectively. If only one argument is given, it is converted from a boolean to a string containing 'true' or 'false'. -* `ceiling`: Returns the smallest integer greater than or equal to the argument. -Takes a single numeric value as an argument. *Type*: rvalue +*Examples:* +~~~ +bool2str(true) => 'true' +bool2str(true, 'yes', 'no') => 'yes' +bool2str(false, 't', 'f') => 'f' +~~~ -* `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 +Requires a single boolean as 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 +#### `capitalize` -* `concat`: Appends the contents of multiple arrays onto array 1. For example: - * `concat(['1','2','3'],'4')` results in: ['1','2','3','4']. - * `concat(['1','2','3'],'4',['5','6','7'])` results in: ['1','2','3','4','5','6','7']. +Capitalizes the first character of a string or array of strings and lowercases the remaining characters of each string. Requires either a single string or an array as an input. *Type*: rvalue. -* `count`: 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. *Type*: rvalue +#### `ceiling` -* `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. +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, } @@ -146,70 +222,141 @@ strings; for example, 'hello\n' becomes 'hello'. Requires a single string or arr if ! defined_with_params(User[dan], {'ensure' => 'present' }) { user { 'dan': ensure => present, } } - ``` + ~~~ - *Type*: rvalue +*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` -* `delete_at`: Deletes a determined indexed value from an array. For example, `delete_at(['a','b','c'], 1)` returns ['a','c']. *Type*: rvalue +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_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_at` -* `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 +Deletes a determined indexed value from an array. For example, `delete_at(['a','b','c'], 1)` returns ['a','c']. *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"]. +#### `delete_values` -* `dirname`: Returns the `dirname` of a path. For example, `dirname('/path/to/a/file.ext')` returns '/path/to/a'. +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. -* `downcase`: Converts the case of a string or of all strings in an array to lowercase. *Type*: rvalue +#### `delete_undef_values` -* `empty`: Returns 'true' if the variable is empty. *Type*: rvalue +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. -* `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 +#### `difference` -* `ensure_resource`: Takes a resource type, title, and a list of attributes that describe a resource. +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. - ``` - user { 'dan': - ensure => present, - } - ``` +#### `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 argument is an array or hash that contains no elements, or an empty string. Returns false when the argument is a numerical value. *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). - This example only creates the resource if it does not already exist: +~~~ +user { 'dan': + ensure => present, +} +~~~ - `ensure_resource('user', 'dan', {'ensure' => 'present' })` +This example only creates the resource if it does not already exist: - 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. + `ensure_resource('user', 'dan', {'ensure' => 'present' })` - 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. +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 +*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:* -* `flatten`: This function flattens any deeply nested arrays and returns a single flat array as a result. For example, `flatten(['a', ['b', ['c']]])` returns ['a','b','c']. *Type*: rvalue +~~~ +fqdn_rotate(['a', 'b', 'c', 'd']) +fqdn_rotate('abcd') +fqdn_rotate([1, 2, 3], 'custom seed') +~~~ -* `floor`: Returns the largest integer less than or equal to the argument. -Takes a single numeric value as an argument. *Type*: rvalue +*Type*: rvalue. -* `fqdn_rotate`: Rotates an array a random number of times based on a node's fqdn. *Type*: rvalue +#### `get_module_path` -* `get_module_path`: Returns the absolute path of the specified module for the current environment. +Returns the absolute path of the specified module for the current environment. `$module_path = get_module_path('stdlib')` - *Type*: rvalue +*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 code returns 'param_value'. +#### `getparam` - *Example:* +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) { } @@ -218,61 +365,73 @@ returns the value of the resource's parameter. For example, the following code r } getparam(Example_resource["example_resource_instance"], "param") - ``` + ~~~ + +*Type*: rvalue. - *Type*: rvalue +#### `getvar` -* `getvar`: Lookup a variable in a remote namespace. +Looks up a variable in a remote namespace. - For example: +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: +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` - *Type*: rvalue +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. -* `grep`: This function 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` -* `has_interface_with`: Returns boolean based on kind and value: +Returns a boolean based on kind and value: * macaddress * netmask * ipaddress * network - *Examples:* +*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: +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. - *Type*: rvalue +#### `has_ip_network` -* `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 +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_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` -* `has_key`: Determine if a hash has a certain key value. +Determines if a hash has a certain key value. - *Example*: +*Example*: - ``` + ~~~ $my_hash = {'key_one' => 'value_one'} if has_key($my_hash, 'key_two') { notice('we will not reach here') @@ -280,139 +439,299 @@ returns the value of the resource's parameter. For example, the following code r 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_a` + +Boolean check to determine whether a variable is of a given data type. This is equivalent to the `=~` type checks. This function is available only in Puppet 4 or in Puppet 3 with the "future" parser. + + ~~~ + foo = 3 + $bar = [1,2,3] + $baz = 'A string!' + + if $foo.is_a(Integer) { + notify { 'foo!': } + } + if $bar.is_a(Array) { + notify { 'bar!': } + } + if $baz.is_a(String) { + notify { 'baz!': } + } + ~~~ + +See the [the Puppet type system](https://docs.puppetlabs.com/references/latest/type.html#about-resource-types) for more information about types. +See the [`assert_type()`](https://docs.puppetlabs.com/references/latest/function.html#asserttype) function for flexible ways to assert the type of a value. + +#### `is_absolute_path` + +Returns 'true' if the given path is absolute. *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. - *Type*: rvalue +#### `is_float` -* `hash`: This function converts an array into a hash. For example, `hash(['a',1,'b',2,'c',3])` returns {'a'=>1,'b'=>2,'c'=>3}. *Type*: rvalue +Returns 'true' if the variable passed to this function is a float. *Type*: rvalue. -* `intersection`: This function returns an array an intersection of two. For example, `intersection(["a","b","c"],["b","c","d"])` returns ["b","c"]. +#### `is_function_available` -* `is_array`: Returns 'true' if the variable passed to this function is an array. *Type*: rvalue +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_bool`: Returns 'true' if the variable passed to this function is a boolean. *Type*: rvalue +#### `is_hash` -* `is_domain_name`: Returns 'true' if the string passed to this function is a syntactically correct domain name. *Type*: rvalue +Returns 'true' if the variable passed to this function is a hash. *Type*: rvalue. -* `is_float`: Returns 'true' if the variable passed to this function is a float. *Type*: rvalue +#### `is_integer` -* `is_function_available`: This function 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 +Returns 'true' if the variable returned to this string is an integer. *Type*: rvalue. -* `is_hash`: Returns 'true' if the variable passed to this function is a hash. *Type*: rvalue +#### `is_ip_address` -* `is_integer`: Returns 'true' if the variable returned to this string is an integer. *Type*: rvalue +Returns 'true' if the string passed to this function is a valid IP address. *Type*: rvalue. -* `is_ip_address`: Returns 'true' if the string passed to this function is a valid IP address. *Type*: rvalue +#### `is_mac_address` -* `is_mac_address`: Returns 'true' if the string passed to this function is a valid MAC address. *Type*: rvalue +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_numeric` -* `is_string`: Returns 'true' if the variable passed to this function is a string. *Type*: rvalue +Returns 'true' if the variable passed to this function is a number. *Type*: rvalue. -* `join`: This function joins an array into a string using a separator. For example, `join(['a','b','c'], ",")` results in: "a,b,c". *Type*: rvalue +#### `is_string` -* `join_keys_to_values`: 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. For example, `join_keys_to_values({'a'=>1,'b'=>2}, " is ")` results in ["a is 1","b is 2"]. *Type*: rvalue +Returns 'true' if the variable passed to this function is a string. *Type*: rvalue. -* `keys`: Returns the keys of a hash as an array. *Type*: rvalue +#### `join` -* `loadyaml`: Load a YAML file containing an array, string, or hash, and return the data in the corresponding native data type. For example: +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']: } + ~~~ + +If you do not want to fail the catalog compilation when a module's metadata file is absent: + + ~~~ + $metadata = load_module_metadata('mysql', true) + if empty($metadata) { + notify { "This module does not have a metadata.json file.": } + } + ~~~ + +*Type*: rvalue. + +#### `lstrip` - *Type*: rvalue +Strips spaces to the left of a string. *Type*: rvalue. -* `lstrip`: Strips leading spaces to the left of a string. *Type*: rvalue +#### `max` -* `max`: Returns the highest value of all arguments. Requires at least one argument. *Type*: rvalue +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'. *Type*: rvalue +#### `member` -* `merge`: Merges two or more hashes together and returns the resulting hash. +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. - *Example*: +*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` - When there is a duplicate key, the key in the rightmost hash "wins." *Type*: rvalue +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. -* `min`: Returns the lowest value of all arguments. Requires at least one argument. *Type*: rvalue +#### `parsejson` -* `num2bool`: This function 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 +Converts a string of JSON into the correct Puppet structure. *Type*: rvalue. The optional second argument is returned if the data was not correct. -* `parsejson`: This function accepts JSON as a string and converts into the correct Puppet structure. *Type*: rvalue +#### `parseyaml` -* `parseyaml`: This function accepts YAML as a string and converts it into the correct Puppet structure. *Type*: rvalue +Converts a string of YAML into the correct Puppet structure. *Type*: rvalue. The optional second argument is returned if the data was not correct. -* `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. +#### `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. + +#### `pick_default` + +Returns the first value in a list of values. Contrary to the `pick()` function, the `pick_default()` does not fail if all arguments are empty. This allows it to use an empty value as default. *Type*: rvalue. - *Type*: rvalue +#### `prefix` -* `prefix`: This function 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'], and `prefix({'a'=>'b','b'=>'c','c'=>'d'}, 'p')` returns {'pa'=>'b','pb'=>'c','pc'=>'d'}. *Type*: rvalue +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`: This function 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`: +#### `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 - ``` + ~~~ - You can specify the error message you want to use: + To specify the error message you want to use: - ``` + ~~~ assert_private("You're not supposed to do that!") - ``` + ~~~ + +*Type*: statement. - *Type*: statement +#### `pw_hash` -* `range`: When given range in the form of '(start, stop)', `range` extrapolates a range as an array. 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]. +Hashes a password using the crypt function. Provides a hash usable on most POSIX systems. - Non-integer strings are accepted; `range("a", "c")` returns ["a","b","c"], and `range("host01", "host10")` returns ["host01", "host02", ..., "host09", "host10"]. +The first argument to this function is the password to hash. If it is undef or an empty string, this function returns undef. - 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"] +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: - *Type*: rvalue +|Hash type |Specifier| +|---------------------|---------| +|MD5 |1 | +|SHA-256 |5 | +|SHA-512 (recommended)|6 | -* `reject`: This function 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 +The third argument to this function is the salt to use. -* `reverse`: Reverses the order of a string or array. *Type*: rvalue +*Type*: rvalue. -* `rstrip`: Strips leading spaces to the right of the string.*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. -* `shuffle`: Randomizes the order of a string or array elements. *Type*: rvalue +#### `range` -* `size`: Returns the number of elements in a string or array. *Type*: rvalue +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]. -* `sort`: Sorts strings and arrays lexically. *Type*: rvalue +Non-integer strings are accepted; `range("a", "c")` returns ["a","b","c"], and `range("host01", "host10")` returns ["host01", "host02", ..., "host09", "host10"]. -* `squeeze`: Returns a new string where runs of the same character that occur in this set are replaced by a single character. *Type*: rvalue +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"]. -* `str2bool`: This 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 +*Type*: rvalue. -* `str2saltedsha512`: This 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 +#### `reject` -* `strftime`: This function returns formatted time. For example, `strftime("%s")` returns the time since epoch, and `strftime("%Y=%m-%d")` returns the date. *Type*: rvalue +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. + +#### `seeded_rand` + +Takes an integer max value and a string seed value and returns a repeatable random integer smaller than max. Like `fqdn_rand`, but does not add node specific data to the seed. *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 certain strings to a boolean. This attempts to convert strings that contain the values '1', 't', 'y', or 'yes' to true. Strings that contain values '0', 'f', 'n', or 'no', or that are an empty string or undefined are converted to false. Any other value causes an error. *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') + * `%A`: The full weekday name ('Sunday') * `%b`: The abbreviated month name ('Jan') - * `%B`: The full month name ('January') + * `%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) @@ -433,191 +752,275 @@ manifests as a valid password attribute. *Type*: rvalue * `%3N`: Millisecond (3 digits) * `%6N`: Microsecond (6 digits) * `%9N`: Nanosecond (9 digits) - * `%p`: Meridian indicator ('AM' or 'PM') - * `%P`: Meridian indicator ('am' or 'pm') + * `%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`: 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) + * `%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`: 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 as hour offset from UTC (e.g. +0900) * `%Z`: Time zone name * `%%`: Literal '%' character -* `strip`: This function removes leading and trailing whitespace from a string or from every string inside an array. For example, `strip(" aaa ")` results in "aaa". *Type*: rvalue +#### `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`: This function applies a suffix to all elements in an array. For example, `suffix(['a','b','c'], 'p')` returns ['ap','bp','cp']. *Type*: rvalue +#### `suffix` -* `swapcase`: This function swaps the existing case of a string. For example, `swapcase("aBcD")` results in "AbCd". *Type*: rvalue +Applies a suffix to all elements in an array. For example, `suffix(['a','b','c'], 'p')` returns ['ap','bp','cp']. *Type*: rvalue. -* `time`: This function returns the current time since epoch as an integer. For example, `time()` returns something like '1311972653'. *Type*: rvalue +#### `swapcase` -* `to_bytes`: Converts the argument into bytes, for example 4 kB becomes 4096. -Takes a single string value as an argument. *Type*: rvalue +Swaps the existing case of a string. For example, `swapcase("aBcD")` results in "AbCd". *Type*: rvalue. -* `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 may be used. *Type*: rvalue +#### `time` -* `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 +Returns the current Unix epoch time as an integer. For example, `time()` returns something like '1311972653'. *Type*: rvalue. -* `union`: This function returns a union of two arrays. For example, `union(["a","b","c"],["b","c","d"])` returns ["a","b","c","d"]. +#### `to_bytes` -* `unique`: This function removes duplicates from strings and arrays. For example, `unique("aabbcc")` returns 'abc'. +Converts the argument into bytes, for example "4 kB" becomes "4096". Takes a single string value as an argument. *Type*: rvalue. -You can also use this with arrays. For example, `unique(["a","a","b","b","c","c"])` returns ["a","b","c"]. *Type*: rvalue +#### `try_get_value` -* `upcase`: Converts an object, array or hash of objects that respond to upcase to uppercase. For example, `upcase("abcd")` returns 'ABCD'. *Type*: rvalue +*Type*: rvalue. -* `uriescape`: Urlencodes a string or array of strings. Requires either a single string or an array as an input. *Type*: rvalue +Retrieves a value within multiple layers of hashes and arrays via a string containing a path. The path is a string of hash keys or array indexes starting with zero, separated by the path separator character (default "/"). The function goes through the structure by each path component and tries to return the value at the end of the path. -* `validate_absolute_path`: Validate the string represents an absolute path in the filesystem. This function works for Windows and Unix style paths. +In addition to the required path argument, the function accepts the default argument. It is returned if the path is not correct, if no value was found, or if any other error has occurred. The last argument can set the path separator character. - The following values will pass: +~~~ruby +$data = { + 'a' => { + 'b' => [ + 'b1', + 'b2', + 'b3', + ] + } +} - ``` - $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) - ``` +$value = try_get_value($data, 'a/b/2') +# $value = 'b3' - The following values will fail, causing compilation to abort: +# with all possible options +$value = try_get_value($data, 'a/b/2', 'not_found', '/') +# $value = 'b3' - ``` - 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) - ``` +# using the default value +$value = try_get_value($data, 'a/b/c/d', 'not_found') +# $value = 'not_found' - *Type*: statement +# using custom separator +$value = try_get_value($data, 'a|b', [], '|') +# $value = ['b1','b2','b3'] +~~~ -* `validate_array`: Validate that all passed values are array data structures. Abort catalog compilation if any value fails this check. +1. **$data** The data structure we are working with. +2. **'a/b/2'** The path string. +3. **'not_found'** The default value. It will be returned if nothing is found. + (optional, defaults to *undef*) +4. **'/'** The path separator character. + (optional, defaults to *'/'*) - The following values will pass: +#### `type3x` - ``` - $my_array = [ 'one', 'two' ] - validate_array($my_array) - ``` +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. - The following values will fail, causing compilation to abort: +#### `type_of` - ``` - validate_array(true) - validate_array('some_string') - $undefined = undef - validate_array($undefined) - ``` +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. - *Type*: statement +#### `union` -* `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. +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. - 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. +#### `unique` - For example, to make sure your passwd content never contains user `foo`: +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. - ``` - validate_augeas($passwdcontent, 'Passwd.lns', ['$file/foo']) - ``` +#### `unix2dos` - To ensure that no users use the '/bin/barsh' shell: +Returns the DOS version of the given string. Very useful when using a File resource with a cross-platform template. *Type*: rvalue. - ``` - validate_augeas($passwdcontent, 'Passwd.lns', ['$file/*[shell="/bin/barsh"]'] - ``` +~~~ +file{$config_file: + ensure => file, + content => unix2dos(template('my_module/settings.conf.erb')), +} +~~~ - You can pass a fourth argument as the error message raised and shown to the user: +See also [dos2unix](#dos2unix). - ``` - validate_augeas($sudoerscontent, 'Sudoers.lns', [], 'Failed to validate sudoers content with Augeas') - ``` +#### `upcase` - *Type*: statement +Converts an object, array or hash of objects that respond to upcase to uppercase. For example, `upcase('abcd')` returns 'ABCD'. *Type*: rvalue. -* `validate_bool`: Validate that all passed values are either true or false. Abort catalog compilation if any value fails this check. +#### `uriescape` - The following values will pass: +URLEncodes a string or array of strings. Requires either a single string or an array as an input. *Type*: rvalue. - ``` - $iamtrue = true - validate_bool(true) - validate_bool(true, true, false, $iamtrue) - ``` +#### `validate_absolute_path` - The following values will fail, causing compilation to abort: +Validates that a given string represents an absolute path in the filesystem. Works for Windows and Unix style paths. + +The following values pass: - ``` - $some_array = [ true ] - validate_bool("false") - validate_bool("true") - validate_bool($some_array) - ``` +~~~ +$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) +~~~ - *Type*: statement +The following values fail, causing compilation to abort: -* `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, launched against a tempfile containing the passed string, returns a non-null value, compilation will abort with a parse error. +~~~ +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') - ``` +~~~ +# 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. - *Type*: statement +#### `validate_hash` -* `validate_hash`: Validates that all passed values are hash data structures. Abort catalog compilation if any value fails this check. +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 +*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. -* `validate_integer`: 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. + 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. @@ -625,7 +1028,7 @@ If a third argument is specified, this will be the error message raised and seen The following values will pass: - ``` + ~~~ validate_integer(1) validate_integer(1, 2) validate_integer(1, 1) @@ -637,14 +1040,14 @@ If a third argument is specified, this will be the error message raised and seen 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) @@ -661,19 +1064,53 @@ If a third argument is specified, this will be the error message raised and seen 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 crap in arrays or maximum / minimum argument. + * Plus all of the above, but with non-integer items in arrays or maximum / minimum argument. + + *Type*: statement. + +#### `validate_ip_address` + +Validates that the argument is an IP address, regardless of it is an IPv4 or an IPv6 +address. It also validates IP address with netmask. The argument must be given as a string. + +The following values will pass: + + ~~~ + validate_ip_address('0.0.0.0') + validate_ip_address('8.8.8.8') + validate_ip_address('127.0.0.1') + validate_ip_address('194.232.104.150') + validate_ip_address('3ffe:0505:0002::') + validate_ip_address('::1/64') + validate_ip_address('fe80::a00:27ff:fe94:44d6/64') + validate_ip_address('8.8.8.8/32') + ~~~ - *Type*: statement +The following values will fail, causing compilation to abort: -* `validate_numeric`: Validate that the first argument is a numeric value (or an array of numeric values). Abort catalog compilation if any of the checks fail. + ~~~ + validate_ip_address(1) + validate_ip_address(true) + validate_ip_address(0.0.0.256) + validate_ip_address('::1', {}) + validate_ip_address('0.0.0.0.0') + validate_ip_address('3.3.3') + validate_ip_address('23.43.9.22/64') + validate_ip_address('260.2.32.43') + ~~~ + + +#### `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. + 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. @@ -681,92 +1118,103 @@ If a third argument is specified, this will be the error message raised and seen 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 +*Type*: statement. + +#### `validate_re` -* `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. +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') - ``` + ~~~ + + Note: Compilation terminates if the first argument is not a string. Always use quotes to force stringification: + + ~~~ + validate_re("${::operatingsystemmajrelease}", '^[57]$') + ~~~ + +*Type*: statement. - *Type*: statement +#### `validate_slength` -* `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. +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 the second argument 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 +*Type*: statement. -* `validate_string`: Validates that all passed values are string data structures. Aborts catalog compilation if any value fails this check. +#### `validate_string` - The following values pass: +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' ]) - $undefined = undef - validate_string($undefined) - ``` - - *Type*: statement + ~~~ -* `values`: When given a hash, this function returns the values of that hash. +*Note:* validate_string(undef) will not fail in this version of the functions API (incl. current and future parser). - *Examples:* +Instead, use: - ``` - $hash = { - 'a' => 1, - 'b' => 2, - 'c' => 3, + ~~~ + if $var == undef { + fail('...') } - values($hash) - ``` + ~~~ + +*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]. - The example above returns [1,2,3]. +*Type*: rvalue. - *Type*: rvalue +#### `values_at` -* `values_at`: 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: +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) @@ -774,13 +1222,15 @@ of the regular expressions match the string passed in, compilation aborts with a 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 +*Type*: rvalue. -* `zip`: 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. For example, `zip(['1','2','3'],['4','5','6'])` results in ["1", "4"], ["2", "5"], ["3", "6"]. *Type*: rvalue +#### `zip` -##Limitations +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. -As of Puppet Enterprise version 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. +## 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 @@ -789,25 +1239,18 @@ 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 of hardware, software, and deployment configurations that Puppet is intended to serve. +## Development -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. - -You can read the complete module contribution guide on the [Puppet Labs wiki](http://projects.puppetlabs.com/projects/module-site/wiki/Module_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 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 - - - +## Contributors +The list of contributors can be found at: [https://github.com/puppetlabs/puppetlabs-stdlib/graphs/contributors](https://github.com/puppetlabs/puppetlabs-stdlib/graphs/contributors). diff --git a/puphpet/puppet/modules/stdlib/Rakefile b/puphpet/puppet/modules/stdlib/Rakefile index 4ed1327..e136b8e 100644 --- a/puphpet/puppet/modules/stdlib/Rakefile +++ b/puphpet/puppet/modules/stdlib/Rakefile @@ -1,18 +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"] -desc "Validate manifests, templates, and ruby files in lib." -task :validate do - Dir['manifests/**/*.pp'].each do |manifest| - sh "puppet parser validate --noop #{manifest}" - end - Dir['lib/**/*.rb'].each do |lib_file| - sh "ruby -c #{lib_file}" - end - Dir['templates/**/*.erb'].each do |template| - sh "erb -P -x -T '-' #{template} | ruby -c" - end -end diff --git a/puphpet/puppet/modules/stdlib/tests/file_line.pp b/puphpet/puppet/modules/stdlib/examples/file_line.pp similarity index 87% rename from puphpet/puppet/modules/stdlib/tests/file_line.pp rename to puphpet/puppet/modules/stdlib/examples/file_line.pp index eea693e..85b1325 100644 --- a/puphpet/puppet/modules/stdlib/tests/file_line.pp +++ b/puphpet/puppet/modules/stdlib/examples/file_line.pp @@ -1,8 +1,8 @@ # This is a simple smoke test # of the file_line resource type. file { '/tmp/dansfile': - ensure => present -}-> + ensure => file, +} -> file_line { 'dans_line': line => 'dan is awesome', path => '/tmp/dansfile', diff --git a/puphpet/puppet/modules/stdlib/tests/has_interface_with.pp b/puphpet/puppet/modules/stdlib/examples/has_interface_with.pp similarity index 97% rename from puphpet/puppet/modules/stdlib/tests/has_interface_with.pp rename to puphpet/puppet/modules/stdlib/examples/has_interface_with.pp index e1f1353..a578dd2 100644 --- a/puphpet/puppet/modules/stdlib/tests/has_interface_with.pp +++ b/puphpet/puppet/modules/stdlib/examples/has_interface_with.pp @@ -1,4 +1,4 @@ -include stdlib +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')) @@ -7,4 +7,3 @@ 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')) - diff --git a/puphpet/puppet/modules/stdlib/tests/has_ip_address.pp b/puphpet/puppet/modules/stdlib/examples/has_ip_address.pp similarity index 89% rename from puphpet/puppet/modules/stdlib/tests/has_ip_address.pp rename to puphpet/puppet/modules/stdlib/examples/has_ip_address.pp index 8429a88..594143d 100644 --- a/puphpet/puppet/modules/stdlib/tests/has_ip_address.pp +++ b/puphpet/puppet/modules/stdlib/examples/has_ip_address.pp @@ -1,3 +1,3 @@ -include stdlib +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')) diff --git a/puphpet/puppet/modules/stdlib/tests/has_ip_network.pp b/puphpet/puppet/modules/stdlib/examples/has_ip_network.pp similarity index 88% rename from puphpet/puppet/modules/stdlib/tests/has_ip_network.pp rename to puphpet/puppet/modules/stdlib/examples/has_ip_network.pp index a15d8c0..1f1130d 100644 --- a/puphpet/puppet/modules/stdlib/tests/has_ip_network.pp +++ b/puphpet/puppet/modules/stdlib/examples/has_ip_network.pp @@ -1,4 +1,3 @@ -include stdlib +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')) - diff --git a/puphpet/puppet/modules/stdlib/examples/init.pp b/puphpet/puppet/modules/stdlib/examples/init.pp new file mode 100644 index 0000000..ad27972 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/examples/init.pp @@ -0,0 +1 @@ +include ::stdlib diff --git a/puphpet/puppet/modules/stdlib/lib/facter/facter_dot_d.rb b/puphpet/puppet/modules/stdlib/lib/facter/facter_dot_d.rb index b058437..d85940d 100644 --- a/puphpet/puppet/modules/stdlib/lib/facter/facter_dot_d.rb +++ b/puphpet/puppet/modules/stdlib/lib/facter/facter_dot_d.rb @@ -8,7 +8,7 @@ # contains a cache TTL. For foo.sh store the ttl as just # a number in foo.sh.ttl # -# The cache is stored in /tmp/facts_cache.yaml as a mode +# 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 diff --git a/puphpet/puppet/modules/stdlib/lib/facter/package_provider.rb b/puphpet/puppet/modules/stdlib/lib/facter/package_provider.rb new file mode 100644 index 0000000..1a0bac9 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/facter/package_provider.rb @@ -0,0 +1,21 @@ +# Fact: package_provider +# +# Purpose: Returns the default provider Puppet will choose to manage packages +# on this system +# +# Resolution: Instantiates a dummy package resource and return the provider +# +# Caveats: +# +require 'puppet/type' +require 'puppet/type/package' + +Facter.add(:package_provider) do + setcode do + if Gem::Version.new(Facter.value(:puppetversion).split(' ')[0]) >= Gem::Version.new('3.6') + Puppet::Type.type(:package).newpackage(:name => 'dummy', :allow_virtual => 'true')[:provider].to_s + else + Puppet::Type.type(:package).newpackage(:name => 'dummy')[:provider].to_s + end + end +end diff --git a/puphpet/puppet/modules/stdlib/lib/facter/pe_version.rb b/puphpet/puppet/modules/stdlib/lib/facter/pe_version.rb index 0cc0f64..c9f2181 100644 --- a/puphpet/puppet/modules/stdlib/lib/facter/pe_version.rb +++ b/puphpet/puppet/modules/stdlib/lib/facter/pe_version.rb @@ -10,8 +10,13 @@ # Facter.add("pe_version") do setcode do - pe_ver = Facter.value("puppetversion").match(/Puppet Enterprise (\d+\.\d+\.\d+)/) - pe_ver[1] if pe_ver + puppet_ver = Facter.value("puppetversion") + if puppet_ver != nil + pe_ver = puppet_ver.match(/Puppet Enterprise (\d+\.\d+\.\d+)/) + pe_ver[1] if pe_ver + else + nil + end end end diff --git a/puphpet/puppet/modules/stdlib/lib/facter/root_home.rb b/puphpet/puppet/modules/stdlib/lib/facter/root_home.rb index b4f87ff..87c7657 100644 --- a/puphpet/puppet/modules/stdlib/lib/facter/root_home.rb +++ b/puphpet/puppet/modules/stdlib/lib/facter/root_home.rb @@ -30,3 +30,16 @@ def get_root_home 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 diff --git a/puphpet/puppet/modules/stdlib/lib/facter/service_provider.rb b/puphpet/puppet/modules/stdlib/lib/facter/service_provider.rb new file mode 100644 index 0000000..a117921 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/facter/service_provider.rb @@ -0,0 +1,17 @@ +# Fact: service_provider +# +# Purpose: Returns the default provider Puppet will choose to manage services +# on this system +# +# Resolution: Instantiates a dummy service resource and return the provider +# +# Caveats: +# +require 'puppet/type' +require 'puppet/type/service' + +Facter.add(:service_provider) do + setcode do + Puppet::Type.type(:service).newservice(:name => 'dummy')[:provider].to_s + end +end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/functions/is_a.rb b/puphpet/puppet/modules/stdlib/lib/puppet/functions/is_a.rb new file mode 100644 index 0000000..da98b03 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/puppet/functions/is_a.rb @@ -0,0 +1,32 @@ +# Boolean check to determine whether a variable is of a given data type. This is equivalent to the `=~` type checks. +# +# @example how to check a data type +# # check a data type +# foo = 3 +# $bar = [1,2,3] +# $baz = 'A string!' +# +# if $foo.is_a(Integer) { +# notify { 'foo!': } +# } +# if $bar.is_a(Array) { +# notify { 'bar!': } +# } +# if $baz.is_a(String) { +# notify { 'baz!': } +# } +# +# 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(:is_a) do + dispatch :is_a do + param 'Any', :value + param 'Type', :type + end + + def is_a(value, type) + # See puppet's lib/puppet/pops/evaluator/evaluator_impl.rb eval_MatchExpression + Puppet::Pops::Types::TypeCalculator.instance?(type, value) + end +end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/bool2str.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/bool2str.rb index fcd3791..7e36474 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/bool2str.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/bool2str.rb @@ -4,15 +4,29 @@ module Puppet::Parser::Functions newfunction(:bool2str, :type => :rvalue, :doc => <<-EOS - Converts a boolean to a string. + Converts a boolean to a string using optionally supplied arguments. The + optional second and third arguments represent what true and false will be + converted to respectively. If only one argument is given, it will be + converted from a boolean to a string containing 'true' or 'false'. + + *Examples:* + + bool2str(true) => 'true' + bool2str(true, 'yes', 'no') => 'yes' + bool2str(false, 't', 'f') => 'f' + 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 + unless arguments.size == 1 or arguments.size == 3 + raise(Puppet::ParseError, "bool2str(): Wrong number of arguments " + + "given (#{arguments.size} for 3)") + end value = arguments[0] + true_string = arguments[1] || 'true' + false_string = arguments[2] || 'false' klass = value.class # We can have either true or false, and nothing else @@ -20,7 +34,11 @@ module Puppet::Parser::Functions raise(Puppet::ParseError, 'bool2str(): Requires a boolean to work with') end - return value.to_s + unless [true_string, false_string].all?{|x| x.kind_of?(String)} + raise(Puppet::ParseError, "bool2str(): Requires strings to convert to" ) + end + + return value ? true_string : false_string end end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/convert_base.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/convert_base.rb new file mode 100644 index 0000000..0fcbafe --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/convert_base.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/dos2unix.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/dos2unix.rb new file mode 100644 index 0000000..ccac899 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/dos2unix.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/empty.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/empty.rb index cca620f..b5a3cde 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/empty.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/empty.rb @@ -13,14 +13,18 @@ module Puppet::Parser::Functions value = arguments[0] - unless value.is_a?(Array) || value.is_a?(Hash) || value.is_a?(String) + unless value.is_a?(Array) || value.is_a?(Hash) || value.is_a?(String) || value.is_a?(Numeric) raise(Puppet::ParseError, 'empty(): Requires either ' + - 'array, hash or string to work with') + 'array, hash, string or integer to work with') end - result = value.empty? + if value.is_a?(Numeric) + return false + else + result = value.empty? - return result + return result + end end end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb new file mode 100644 index 0000000..2bb1287 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/fqdn_rotate.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/fqdn_rotate.rb index cf22d36..b66431d 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/fqdn_rotate.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/fqdn_rotate.rb @@ -2,16 +2,23 @@ # fqdn_rotate.rb # -module Puppet::Parser::Functions - newfunction(:fqdn_rotate, :type => :rvalue, :doc => <<-EOS -Rotates an array a random number of times based on a nodes fqdn. - EOS - ) do |arguments| +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 (#{arguments.size} for 1)") if arguments.size < 1 + "given (#{args.size} for 1)") if args.size < 1 - value = arguments[0] + value = args.shift require 'digest/md5' unless value.is_a?(Array) || value.is_a?(String) @@ -31,7 +38,7 @@ module Puppet::Parser::Functions elements = result.size - seed = Digest::MD5.hexdigest([lookupvar('::fqdn'),arguments].join(':')).hex + 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 @@ -39,9 +46,9 @@ module Puppet::Parser::Functions if defined?(Random) == 'constant' && Random.class == Class offset = Random.new(seed).rand(elements) else - srand(seed) + old_seed = srand(seed) offset = rand(elements) - srand() + srand(old_seed) end end offset.times { @@ -51,7 +58,6 @@ module Puppet::Parser::Functions result = string ? result.join : result return result - end end # vim: set ts=2 sw=2 et : diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/getvar.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/getvar.rb index fb336b6..ae9c869 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/getvar.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/getvar.rb @@ -20,7 +20,9 @@ module Puppet::Parser::Functions end begin - self.lookupvar("#{args[0]}") + catch(:undefined_variable) do + self.lookupvar("#{args[0]}") + end rescue Puppet::ParseError # Eat the exception if strict_variables = true is set end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/has_interface_with.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/has_interface_with.rb index 3691524..e762798 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/has_interface_with.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/has_interface_with.rb @@ -38,8 +38,11 @@ module Puppet::Parser::Functions # Bug with 3.7.1 - 3.7.3 when using future parser throws :undefined_variable # https://tickets.puppetlabs.com/browse/PUP-3597 factval = nil - catch :undefined_variable do - factval = lookupvar(kind) + 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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/intersection.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/intersection.rb index 48f02e9..bfbb4ba 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/intersection.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/intersection.rb @@ -4,13 +4,13 @@ module Puppet::Parser::Functions newfunction(:intersection, :type => :rvalue, :doc => <<-EOS -This function returns an array an intersection of two. +This function returns an array of the intersection of two. *Examples:* - intersection(["a","b","c"],["b","c","d"]) + intersection(["a","b","c"],["b","c","d"]) # returns ["b","c"] + intersection(["a","b","c"],[1,2,3,4]) # returns [] (true, when evaluated as a Boolean) -Would return: ["b","c"] EOS ) do |arguments| diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/is_absolute_path.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/is_absolute_path.rb new file mode 100644 index 0000000..53a5445 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/is_absolute_path.rb @@ -0,0 +1,50 @@ +module Puppet::Parser::Functions + newfunction(:is_absolute_path, :type => :rvalue, :arity => 1, :doc => <<-'ENDHEREDOC') do |args| + Returns boolean true if the string represents an absolute path in the filesystem. This function works + for windows and unix style paths. + + The following values will return true: + + $my_path = 'C:/Program Files (x86)/Puppet Labs/Puppet' + is_absolute_path($my_path) + $my_path2 = '/var/lib/puppet' + is_absolute_path($my_path2) + $my_path3 = ['C:/Program Files (x86)/Puppet Labs/Puppet'] + is_absolute_path($my_path3) + $my_path4 = ['/var/lib/puppet'] + is_absolute_path($my_path4) + + The following values will return false: + + is_absolute_path(true) + is_absolute_path('../var/lib/puppet') + is_absolute_path('var/lib/puppet') + $undefined = undef + is_absolute_path($undefined) + + ENDHEREDOC + + require 'puppet/util' + + path = args[0] + # 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 + value = (Puppet::Util.absolute_path?(path, :posix) or Puppet::Util.absolute_path?(path, :windows)) + 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!^/! + } + value = (!!(path =~ regexes[:posix])) || (!!(path =~ regexes[:windows])) + end + value + end +end \ No newline at end of file diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/is_mac_address.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/is_mac_address.rb index 1b3088a..2619d44 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/is_mac_address.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/is_mac_address.rb @@ -15,7 +15,7 @@ module Puppet::Parser::Functions mac = arguments[0] - if /^[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}$/.match(mac) then + if /^[a-f0-9]{1,2}(:[a-f0-9]{1,2}){5}$/i.match(mac) then return true else return false diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/load_module_metadata.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/load_module_metadata.rb new file mode 100644 index 0000000..c9b8488 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/load_module_metadata.rb @@ -0,0 +1,24 @@ +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 or two") unless [1,2].include?(args.size) + mod = args[0] + allow_empty_metadata = args[1] + module_path = function_get_module_path([mod]) + metadata_json = File.join(module_path, 'metadata.json') + + metadata_exists = File.exists?(metadata_json) + if metadata_exists + metadata = PSON.load(File.read(metadata_json)) + else + if allow_empty_metadata + metadata = {} + else + raise(Puppet::ParseError, "load_module_metadata(): No metadata.json file for module #{mod}") + end + end + + return metadata + end +end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/loadyaml.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/loadyaml.rb index 10c4005..ca655f6 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/loadyaml.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/loadyaml.rb @@ -13,7 +13,12 @@ module Puppet::Parser::Functions raise Puppet::ParseError, ("loadyaml(): wrong number of arguments (#{args.length}; must be 1)") end - YAML.load_file(args[0]) + 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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/member.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/member.rb index 88609ce..1e5b3de 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/member.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/member.rb @@ -44,7 +44,7 @@ module Puppet::Parser::Functions end if arguments[1].is_a? String or arguments[1].is_a? Fixnum - item = Array(arguments[1]) + item = [arguments[1]] else item = arguments[1] end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/parsejson.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/parsejson.rb index a9a16a4..b4af40e 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/parsejson.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/parsejson.rb @@ -4,20 +4,25 @@ 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 +This function accepts JSON as a string and converts it into the correct +Puppet structure. + +The optional second argument can be used to pass a default value that will +be returned if the parsing of YAML string have failed. + EOS ) do |arguments| + raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless arguments.length >= 1 - if (arguments.size != 1) then - raise(Puppet::ParseError, "parsejson(): Wrong number of arguments "+ - "given #{arguments.size} for 1") + begin + PSON::load(arguments[0]) || arguments[1] + rescue Exception => e + if arguments[1] + arguments[1] + else + raise e + end end - json = arguments[0] - - # PSON is natively available in puppet - PSON.load(json) end end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/parseyaml.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/parseyaml.rb index 53d54fa..66d0413 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/parseyaml.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/parseyaml.rb @@ -6,17 +6,23 @@ 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 +The optional second argument can be used to pass a default value that will +be returned if the parsing of YAML string have failed. + EOS + ) do |arguments| + raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless arguments.length >= 1 require 'yaml' - YAML::load(arguments[0]) + begin + YAML::load(arguments[0]) || arguments[1] + rescue Exception => e + if arguments[1] + arguments[1] + else + raise e + end + end end end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/pw_hash.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/pw_hash.rb new file mode 100644 index 0000000..41d4223 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/pw_hash.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/range.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/range.rb index 49fba21..2fc2113 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/range.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/range.rb @@ -37,18 +37,17 @@ module Puppet::Parser::Functions EOS ) do |arguments| - # We support more than one argument but at least one is mandatory ... - raise(Puppet::ParseError, "range(): Wrong number of " + - "arguments given (#{arguments.size} for 1)") if arguments.size < 1 + 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 = '..' # We select simplest type for Range available in Ruby ... + type = '..' # Use the simplest type of Range available in Ruby - elsif arguments.size > 0 + else # arguments.size == 1 value = arguments[0] if m = value.match(/^(\w+)(\.\.\.?|\-)(\w+)$/) @@ -56,16 +55,16 @@ module Puppet::Parser::Functions stop = m[3] type = m[2] - + step = 1 elsif value.match(/^.+$/) - raise(Puppet::ParseError, 'range(): Unable to compute range ' + - 'from the value given') + raise(Puppet::ParseError, "range(): Unable to compute range " + + "from the value: #{value}") else - raise(Puppet::ParseError, 'range(): Unknown format of range given') + raise(Puppet::ParseError, "range(): Unknown range format: #{value}") end end - # Check whether we have integer value if so then make it so ... + # 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 @@ -76,10 +75,10 @@ module Puppet::Parser::Functions range = case type when /^(\.\.|\-)$/ then (start .. stop) - when /^(\.\.\.)$/ then (start ... stop) # Exclusive of last element ... + when '...' then (start ... stop) # Exclusive of last element end - result = range.step(step).collect { |i| i } # Get them all ... Pokemon ... + result = range.step(step).to_a return result end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/seeded_rand.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/seeded_rand.rb new file mode 100644 index 0000000..44e27b8 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/seeded_rand.rb @@ -0,0 +1,22 @@ +Puppet::Parser::Functions::newfunction( + :seeded_rand, + :arity => 2, + :type => :rvalue, + :doc => <<-EOS +Usage: `seeded_rand(MAX, SEED)`. MAX must be a positive integer; SEED is any string. + +Generates a random whole number greater than or equal to 0 and less +than MAX, using the value of SEED for repeatable randomness. If SEED +starts with "$fqdn:", this is behaves the same as `fqdn_rand`. + +EOS +) do |args| + require 'digest/md5' + + raise(ArgumentError, "seeded_rand(): first argument must be a positive integer") unless function_is_integer([args[0]]) and args[0].to_i > 0 + raise(ArgumentError, "seeded_rand(): second argument must be a string") unless args[1].is_a? String + + max = args[0].to_i + seed = Digest::MD5.hexdigest(args[1]).hex + Puppet::Util.deterministic_rand(seed,max) +end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/size.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/size.rb index cc207e3..0d6cc96 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/size.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/size.rb @@ -2,11 +2,9 @@ # size.rb # -# TODO(Krzysztof Wilczynski): Support for hashes would be nice too ... - module Puppet::Parser::Functions newfunction(:size, :type => :rvalue, :doc => <<-EOS -Returns the number of elements in a string or array. +Returns the number of elements in a string, an array or a hash EOS ) do |arguments| @@ -29,13 +27,13 @@ module Puppet::Parser::Functions Float(item) raise(Puppet::ParseError, 'size(): Requires either ' + - 'string or array to work with') + 'string, array or hash to work with') rescue ArgumentError result = item.size end - elsif item.is_a?(Array) + elsif item.is_a?(Array) || item.is_a?(Hash) result = item.size else raise(Puppet::ParseError, 'size(): Unknown type given') diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/str2bool.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/str2bool.rb index 446732e..8def131 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/str2bool.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/str2bool.rb @@ -5,8 +5,8 @@ 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'. +contain things like: Y,y, 1, T,t, TRUE,true to 'true' and strings that contain things +like: 0, F,f, N,n, false, FALSE, no to 'false'. EOS ) do |arguments| @@ -32,8 +32,8 @@ module Puppet::Parser::Functions # 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 /^(1|t|y|true|yes)$/i then true + when /^(0|f|n|false|no)$/i then false when /^(undef|undefined)$/ then false # This is not likely to happen ... else raise(Puppet::ParseError, 'str2bool(): Unknown type of boolean given') diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/time.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/time.rb index 0cddaf8..c574747 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/time.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/time.rb @@ -33,13 +33,14 @@ module Puppet::Parser::Functions ENV['TZ'] = time_zone - time = local_time.localtime + 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 = time.strftime('%s') result = result.to_i return result diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/try_get_value.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/try_get_value.rb new file mode 100644 index 0000000..0c19fd9 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/try_get_value.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/union.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/union.rb index c91bb80..6c5bb83 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/union.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/union.rb @@ -4,7 +4,7 @@ module Puppet::Parser::Functions newfunction(:union, :type => :rvalue, :doc => <<-EOS -This function returns a union of two arrays. +This function returns a union of two or more arrays. *Examples:* @@ -14,20 +14,15 @@ module Puppet::Parser::Functions EOS ) do |arguments| - # Two arguments are required + # 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 + "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, 'union(): Requires 2 arrays') + arguments.each do |argument| + raise(Puppet::ParseError, 'union(): Every parameter must be an array') unless argument.is_a?(Array) end - result = first | second - - return result + arguments.reduce(:|) end end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/unix2dos.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/unix2dos.rb new file mode 100644 index 0000000..0bd9cd1 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/unix2dos.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/upcase.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/upcase.rb index 0226a88..44b3bcd 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/upcase.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/upcase.rb @@ -12,7 +12,7 @@ module Puppet::Parser::Functions Will return: - ASDF + ABCD EOS ) do |arguments| diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_absolute_path.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_absolute_path.rb index b696680..5f85f72 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_absolute_path.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_absolute_path.rb @@ -40,28 +40,10 @@ module Puppet::Parser::Functions unless arg.is_a?(Array) then candidates = Array.new(1,arg) end - # iterate over all pathes within the candidates array + # iterate over all paths 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.") + unless function_is_absolute_path([path]) + raise Puppet::ParseError, ("#{path.inspect} is not an absolute path.") end end end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_augeas.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_augeas.rb index 4ea4fe0..2196c3e 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_augeas.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_augeas.rb @@ -31,7 +31,7 @@ module Puppet::Parser::Functions ENDHEREDOC unless Puppet.features.augeas? - raise Puppet::ParseError, ("validate_augeas(): this function requires the augeas feature. See http://projects.puppetlabs.com/projects/puppet/wiki/Puppet_Augeas#Pre-requisites for how to activate it.") + 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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_integer.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_integer.rb index 995f8db..a950916 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_integer.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_integer.rb @@ -49,7 +49,7 @@ module Puppet::Parser::Functions 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 crap in arrays or maximum / minimum argument. + Plus all of the above, but with non-integer items in arrays or maximum / minimum argument. ENDHEREDOC @@ -109,6 +109,7 @@ module Puppet::Parser::Functions # 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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_ip_address.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_ip_address.rb new file mode 100644 index 0000000..c0baf82 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_ip_address.rb @@ -0,0 +1,50 @@ +module Puppet::Parser::Functions + + newfunction(:validate_ip_address, :doc => <<-ENDHEREDOC + Validate that all values passed are valid IP addresses, + regardless they are IPv4 or IPv6 + Fail compilation if any value fails this check. + The following values will pass: + $my_ip = "1.2.3.4" + validate_ip_address($my_ip) + validate_bool("8.8.8.8", "172.16.0.1", $my_ip) + + $my_ip = "3ffe:505:2" + validate_ip_address(1) + validate_ip_address($my_ip) + validate_bool("fe80::baf6:b1ff:fe19:7507", $my_ip) + + The following values will fail, causing compilation to abort: + $some_array = [ 1, true, false, "garbage string", "3ffe:505:2" ] + validate_ip_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_ip_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? or IPAddr.new(arg).ipv6? + raise Puppet::ParseError, "#{arg.inspect} is not a valid IP address." + end + rescue *rescuable_exceptions + raise Puppet::ParseError, "#{arg.inspect} is not a valid IP address." + end + end + + end + +end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_ipv4_address.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_ipv4_address.rb index fc02748..97faa57 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_ipv4_address.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_ipv4_address.rb @@ -8,7 +8,7 @@ module Puppet::Parser::Functions $my_ip = "1.2.3.4" validate_ipv4_address($my_ip) - validate_bool("8.8.8.8", "172.16.0.1", $my_ip) + validate_ipv4_address("8.8.8.8", "172.16.0.1", $my_ip) The following values will fail, causing compilation to abort: diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_numeric.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_numeric.rb index d2e4d16..3a14443 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_numeric.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_numeric.rb @@ -71,6 +71,7 @@ module Puppet::Parser::Functions # 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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_re.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_re.rb index ca25a70..efee7f8 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_re.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_re.rb @@ -23,16 +23,23 @@ module Puppet::Parser::Functions validate_re($::puppetversion, '^2.7', 'The $puppetversion fact value does not match 2.7') + Note: Compilation will also abort, if the first argument is not a String. Always use + quotes to force stringification: + + validate_re("${::operatingsystemmajrelease}", '^[57]$') + 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)") + raise Puppet::ParseError, "validate_re(): wrong number of arguments (#{args.length}; must be 2 or 3)" end + raise Puppet::ParseError, "validate_re(): input needs to be a String, not a #{args[0].class}" unless args[0].is_a? String + 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| + raise Puppet::ParseError, msg unless [args[1]].flatten.any? do |re_str| args[0] =~ Regexp.compile(re_str) end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_slength.rb b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_slength.rb index 7d534f3..47c7d4a 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_slength.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/parser/functions/validate_slength.rb @@ -3,7 +3,7 @@ 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 a the minimum length. It fails if the first + 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. @@ -43,9 +43,7 @@ module Puppet::Parser::Functions min_length = 0 end - if min_length > max_length - raise Puppet::ParseError, "validate_slength(): Expected second argument to be larger than third argument" - 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 diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/provider/file_line/ruby.rb b/puphpet/puppet/modules/stdlib/lib/puppet/provider/file_line/ruby.rb index ae1a8b3..aab6fe2 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/provider/file_line/ruby.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/provider/file_line/ruby.rb @@ -1,24 +1,31 @@ Puppet::Type.type(:file_line).provide(:ruby) do def exists? - lines.find do |line| - line.chomp == resource[:line].chomp + 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 - if resource[:match] - handle_create_with_match - elsif resource[:after] - handle_create_with_after - else - append_line + 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 - local_lines = lines - File.open(resource[:path],'w') do |fh| - fh.write(local_lines.reject{|l| l.chomp == resource[:line] }.join('')) + if resource[:match_for_absence].to_s == 'true' and resource[:match] + handle_destroy_with_match + else + handle_destroy_line end end @@ -32,15 +39,27 @@ def lines @lines ||= File.readlines(resource[:path]) end + def match_regex + resource[:match] ? Regexp.new(resource[:match]) : nil + end + def handle_create_with_match() - regex = resource[:match] ? Regexp.new(resource[:match]) : nil - match_count = count_matches(regex) + 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(regex.match(l) ? resource[:line] : 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) @@ -52,20 +71,22 @@ def handle_create_with_match() def handle_create_with_after regex = Regexp.new(resource[:after]) count = count_matches(regex) - case count - when 1 # find the line to put our line after - File.open(resource[:path], 'w') do |fh| - lines.each do |l| - fh.puts(l) - if regex.match(l) then - fh.puts(resource[:line]) - end + + 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 - when 0 # append the line to the end of the file + end + + if (count == 0) # append the line to the end of the file append_line - else - raise Puppet::Error, "#{count} lines match pattern '#{resource[:after]}' in file '#{resource[:path]}'. One or no line must match the pattern." end end @@ -73,12 +94,34 @@ 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], 'a') do |fh| + File.open(resource[:path], 'w') do |fh| + lines.each do |l| + fh.puts(l) + end fh.puts resource[:line] end end diff --git a/puphpet/puppet/modules/stdlib/lib/puppet/type/file_line.rb b/puphpet/puppet/modules/stdlib/lib/puppet/type/file_line.rb index df263e6..77d3be2 100644 --- a/puphpet/puppet/modules/stdlib/lib/puppet/type/file_line.rb +++ b/puphpet/puppet/modules/stdlib/lib/puppet/type/file_line.rb @@ -3,9 +3,9 @@ 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 add the line to - ensure the desired state. Multiple resources may be declared to manage - multiple lines in the same file. + 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: @@ -13,6 +13,7 @@ path => '/etc/sudoers', line => '%sudo ALL=(ALL) ALL', } + file_line { 'sudo_rule_nopw': path => '/etc/sudoers', line => '%sudonopw ALL=(ALL) NOPASSWD: ALL', @@ -21,9 +22,34 @@ 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 @@ -36,12 +62,23 @@ end newparam(:match) do - desc 'An optional regular expression to run against existing lines in the file;\n' + - 'if a match is found, we replace that line rather than adding a new line.' + 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 comparison 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.' + 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 @@ -50,7 +87,7 @@ end newparam(:line) do - desc 'The line to be appended to the file located by the path parameter.' + desc 'The line to be appended to the file or used to replace matches found by the match attribute.' end newparam(:path) do @@ -62,6 +99,12 @@ 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] diff --git a/puphpet/puppet/modules/stdlib/manifests/init.pp b/puphpet/puppet/modules/stdlib/manifests/init.pp index 500ad77..9ea22a7 100644 --- a/puphpet/puppet/modules/stdlib/manifests/init.pp +++ b/puphpet/puppet/modules/stdlib/manifests/init.pp @@ -14,7 +14,5 @@ # Requires: nothing # class stdlib { - - class { 'stdlib::stages': } - + include ::stdlib::stages } diff --git a/puphpet/puppet/modules/stdlib/manifests/stages.pp b/puphpet/puppet/modules/stdlib/manifests/stages.pp index eb15fd6..7de254c 100644 --- a/puphpet/puppet/modules/stdlib/manifests/stages.pp +++ b/puphpet/puppet/modules/stdlib/manifests/stages.pp @@ -26,7 +26,7 @@ # Sample Usage: # # node default { -# include stdlib +# include ::stdlib # class { java: stage => 'runtime' } # } # diff --git a/puphpet/puppet/modules/stdlib/metadata.json b/puphpet/puppet/modules/stdlib/metadata.json index 27def9c..a7ea0af 100644 --- a/puphpet/puppet/modules/stdlib/metadata.json +++ b/puphpet/puppet/modules/stdlib/metadata.json @@ -1,6 +1,6 @@ { "name": "puppetlabs-stdlib", - "version": "4.5.1", + "version": "4.11.0", "author": "puppetlabs", "summary": "Standard library of resources for Puppet modules.", "license": "Apache-2.0", @@ -56,7 +56,8 @@ "operatingsystem": "Debian", "operatingsystemrelease": [ "6", - "7" + "7", + "8" ] }, { @@ -71,7 +72,8 @@ "operatingsystem": "Solaris", "operatingsystemrelease": [ "10", - "11" + "11", + "12" ] }, { @@ -99,11 +101,11 @@ "requirements": [ { "name": "pe", - "version_requirement": "3.x" + "version_requirement": ">= 3.0.0 < 2015.4.0" }, { "name": "puppet", - "version_requirement": ">=2.7.20 <4.0.0" + "version_requirement": ">=2.7.20 <5.0.0" } ], "description": "Standard Library for Puppet Modules", diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/anchor_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/anchor_spec.rb new file mode 100755 index 0000000..5bc2bbb --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/acceptance/anchor_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/empty_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/empty_spec.rb index 8b46aac..2d4df90 100755 --- a/puphpet/puppet/modules/stdlib/spec/acceptance/empty_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/acceptance/empty_spec.rb @@ -27,6 +27,20 @@ } EOS + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).to match(/Notice: output correct/) + end + end + it 'handles numerical values' do + pp = <<-EOS + $a = 7 + $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 diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/ensure_packages_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/ensure_packages_spec.rb deleted file mode 100755 index aedcfb5..0000000 --- a/puphpet/puppet/modules/stdlib/spec/acceptance/ensure_packages_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -#! /usr/bin/env ruby -S rspec -require 'spec_helper_acceptance' - -describe 'ensure_packages function', :unless => fact('osfamily') =~ /windows/i do - describe 'success' do - it 'ensure_packages a package' do - apply_manifest('package { "rake": ensure => absent, provider => "gem", }') - pp = <<-EOS - $a = "rake" - ensure_packages($a,{'provider' => 'gem'}) - EOS - - apply_manifest(pp, :expect_changes => true) - end - it 'ensures a package already declared' - it 'takes defaults arguments' - end - describe 'failure' do - it 'handles no arguments' - it 'handles non strings' - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/ensure_resource_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/ensure_resource_spec.rb index 1cee53d..93f25dd 100755 --- a/puphpet/puppet/modules/stdlib/spec/acceptance/ensure_resource_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/acceptance/ensure_resource_spec.rb @@ -1,18 +1,26 @@ #! /usr/bin/env ruby -S rspec require 'spec_helper_acceptance' -describe 'ensure_resource function', :unless => fact('osfamily') =~ /windows/i do +describe 'ensure_resource function' do describe 'success' do - it 'ensure_resource a package' do - apply_manifest('package { "rake": ensure => absent, provider => "gem", }') + it 'ensures a resource already declared' do + apply_manifest('') pp = <<-EOS - $a = "rake" - ensure_resource('package', $a, {'provider' => 'gem'}) + notify { "test": loglevel => 'err' } + ensure_resource('notify', 'test', { 'loglevel' => 'err' }) + EOS + + apply_manifest(pp, :expect_changes => true) + end + + it 'ensures a undeclared resource' do + apply_manifest('') + pp = <<-EOS + ensure_resource('notify', 'test', { 'loglevel' => 'err' }) EOS apply_manifest(pp, :expect_changes => true) end - it 'ensures a resource already declared' it 'takes defaults arguments' end describe 'failure' do diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/fqdn_rand_string_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/fqdn_rand_string_spec.rb new file mode 100644 index 0000000..9c6d701 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/acceptance/fqdn_rand_string_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/fqdn_rotate_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/fqdn_rotate_spec.rb index 753068b..404351f 100755 --- a/puphpet/puppet/modules/stdlib/spec/acceptance/fqdn_rotate_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/acceptance/fqdn_rotate_spec.rb @@ -3,45 +3,62 @@ describe 'fqdn_rotate function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do describe 'success' do - let(:facts_d) do - if fact('is_pe', '--puppet') == "true" - 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 - else - '/etc/puppetlabs/facter/facts.d' + 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 - else - '/etc/facter/facts.d' end - end - after :each do - shell("if [ -f '#{facts_d}/fqdn.txt' ] ; then rm '#{facts_d}/fqdn.txt' ; fi") - end - before :each do - #No need to create on windows, PE creates by default - if fact('osfamily') !~ /windows/i - shell("mkdir -p '#{facts_d}'") + 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 - end - it 'fqdn_rotates floats' do - shell("echo fqdn=fakehost.localdomain > '#{facts_d}/fqdn.txt'") - pp = <<-EOS - $a = ['a','b','c','d'] - $o = fqdn_rotate($a) - notice(inline_template('fqdn_rotate is <%= @o.inspect %>')) - EOS + 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 \["c", "d", "a", "b"\]/) + 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 non-numbers' + it 'handles invalid arguments' end end diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/is_a_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/is_a_spec.rb new file mode 100644 index 0000000..355fd83 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/acceptance/is_a_spec.rb @@ -0,0 +1,30 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper_acceptance' + +if get_puppet_version =~ /^4/ + describe 'is_a function', :unless => UNSUPPORTED_PLATFORMS.include?(fact('operatingsystem')) do + it 'should match a string' do + pp = <<-EOS + if 'hello world'.is_a(String) { + notify { 'output correct': } + } + EOS + + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).to match(/Notice: output correct/) + end + end + + it 'should not match a integer as string' do + pp = <<-EOS + if 5.is_a(String) { + notify { 'output wrong': } + } + EOS + + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).not_to match(/Notice: output wrong/) + end + end + end +end diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/parsejson_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/parsejson_spec.rb index 5097810..d0e3de8 100755 --- a/puphpet/puppet/modules/stdlib/spec/acceptance/parsejson_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/acceptance/parsejson_spec.rb @@ -16,7 +16,20 @@ end end end + describe 'failure' do + it 'raises error on incorrect json' do + pp = <<-EOS + $a = '{"hunter": "washere", "tests": "passing",}' + $ao = parsejson($a, 'tests are using the default value') + notice(inline_template('a is <%= @ao.inspect %>')) + EOS + + apply_manifest(pp, :catch_failures => true) do |r| + expect(r.stdout).to match(/tests are using the default value/) + end + end + it 'raises error on incorrect json' do pp = <<-EOS $a = '{"hunter": "washere", "tests": "passing",}' @@ -29,6 +42,14 @@ end end - it 'raises error on incorrect number of arguments' + it 'raises error on incorrect number of arguments' do + pp = <<-EOS + $o = parsejson() + EOS + + apply_manifest(pp, :expect_failures => true) do |r| + expect(r.stderr).to match(/wrong number of arguments/i) + end + end end end diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/parseyaml_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/parseyaml_spec.rb index 5819837..64511f1 100755 --- a/puphpet/puppet/modules/stdlib/spec/acceptance/parseyaml_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/acceptance/parseyaml_spec.rb @@ -16,7 +16,21 @@ end end end + describe 'failure' do + it 'returns the default value on incorrect yaml' do + pp = <<-EOS + $a = "---\nhunter: washere\ntests: passing\n:" + $o = parseyaml($a, {'tests' => 'using the default value'}) + $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 "using the default value"/) + end + end + it 'raises error on incorrect yaml' do pp = <<-EOS $a = "---\nhunter: washere\ntests: passing\n:" @@ -30,6 +44,15 @@ end end - it 'raises error on incorrect number of arguments' + + it 'raises error on incorrect number of arguments' do + pp = <<-EOS + $o = parseyaml() + EOS + + apply_manifest(pp, :expect_failures => true) do |r| + expect(r.stderr).to match(/wrong number of arguments/i) + end + end end end diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/pw_hash_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/pw_hash_spec.rb new file mode 100644 index 0000000..cd4cb87 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/acceptance/pw_hash_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/try_get_value_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/try_get_value_spec.rb new file mode 100755 index 0000000..c0bf38a --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/acceptance/try_get_value_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/acceptance/union_spec.rb b/puphpet/puppet/modules/stdlib/spec/acceptance/union_spec.rb index 6db8d0c..160fd7b 100755 --- a/puphpet/puppet/modules/stdlib/spec/acceptance/union_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/acceptance/union_spec.rb @@ -6,9 +6,10 @@ it 'unions arrays' do pp = <<-EOS $a = ["the","public"] - $b = ["art","galleries"] + $b = ["art"] + $c = ["galleries"] # Anagram: Large picture halls, I bet - $o = union($a,$b) + $o = union($a,$b,$c) notice(inline_template('union is <%= @o.inspect %>')) EOS diff --git a/puphpet/puppet/modules/stdlib/spec/classes/anchor_spec.rb b/puphpet/puppet/modules/stdlib/spec/classes/anchor_spec.rb deleted file mode 100755 index 2d4455e..0000000 --- a/puphpet/puppet/modules/stdlib/spec/classes/anchor_spec.rb +++ /dev/null @@ -1,30 +0,0 @@ -#! /usr/bin/env ruby -S rspec -require 'spec_helper' -require 'puppet_spec/compiler' - -describe "anchorrefresh" do - include PuppetSpec::Compiler - - let :transaction do - apply_compiled_manifest(<<-ANCHORCLASS) - class anchored { - anchor { 'anchored::begin': } - ~> anchor { 'anchored::end': } - } - - class anchorrefresh { - notify { 'first': } - ~> class { 'anchored': } - ~> anchor { 'final': } - } - - include anchorrefresh - ANCHORCLASS - end - - it 'propagates events through the anchored class' do - resource = transaction.resource_status('Anchor[final]') - - expect(resource.restarted).to eq(true) - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/lsuser/root b/puphpet/puppet/modules/stdlib/spec/fixtures/lsuser/root new file mode 100644 index 0000000..afd59ca --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/lsuser/root @@ -0,0 +1,2 @@ +#name:home +root:/root diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/facter_dot_d.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/facter_dot_d.rb new file mode 100644 index 0000000..d85940d --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/facter_dot_d.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/package_provider.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/package_provider.rb new file mode 100644 index 0000000..1a0bac9 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/package_provider.rb @@ -0,0 +1,21 @@ +# Fact: package_provider +# +# Purpose: Returns the default provider Puppet will choose to manage packages +# on this system +# +# Resolution: Instantiates a dummy package resource and return the provider +# +# Caveats: +# +require 'puppet/type' +require 'puppet/type/package' + +Facter.add(:package_provider) do + setcode do + if Gem::Version.new(Facter.value(:puppetversion).split(' ')[0]) >= Gem::Version.new('3.6') + Puppet::Type.type(:package).newpackage(:name => 'dummy', :allow_virtual => 'true')[:provider].to_s + else + Puppet::Type.type(:package).newpackage(:name => 'dummy')[:provider].to_s + end + end +end diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/pe_version.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/pe_version.rb new file mode 100644 index 0000000..c9f2181 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/pe_version.rb @@ -0,0 +1,58 @@ +# 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 + puppet_ver = Facter.value("puppetversion") + if puppet_ver != nil + pe_ver = puppet_ver.match(/Puppet Enterprise (\d+\.\d+\.\d+)/) + pe_ver[1] if pe_ver + else + nil + end + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/puppet_vardir.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/puppet_vardir.rb new file mode 100644 index 0000000..0e6af40 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/puppet_vardir.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/root_home.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/root_home.rb new file mode 100644 index 0000000..87c7657 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/root_home.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/service_provider.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/service_provider.rb new file mode 100644 index 0000000..a117921 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/service_provider.rb @@ -0,0 +1,17 @@ +# Fact: service_provider +# +# Purpose: Returns the default provider Puppet will choose to manage services +# on this system +# +# Resolution: Instantiates a dummy service resource and return the provider +# +# Caveats: +# +require 'puppet/type' +require 'puppet/type/service' + +Facter.add(:service_provider) do + setcode do + Puppet::Type.type(:service).newservice(:name => 'dummy')[:provider].to_s + end +end diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/util/puppet_settings.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/util/puppet_settings.rb new file mode 100644 index 0000000..1ad9452 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/facter/util/puppet_settings.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/functions/is_a.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/functions/is_a.rb new file mode 100644 index 0000000..da98b03 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/functions/is_a.rb @@ -0,0 +1,32 @@ +# Boolean check to determine whether a variable is of a given data type. This is equivalent to the `=~` type checks. +# +# @example how to check a data type +# # check a data type +# foo = 3 +# $bar = [1,2,3] +# $baz = 'A string!' +# +# if $foo.is_a(Integer) { +# notify { 'foo!': } +# } +# if $bar.is_a(Array) { +# notify { 'bar!': } +# } +# if $baz.is_a(String) { +# notify { 'baz!': } +# } +# +# 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(:is_a) do + dispatch :is_a do + param 'Any', :value + param 'Type', :type + end + + def is_a(value, type) + # See puppet's lib/puppet/pops/evaluator/evaluator_impl.rb eval_MatchExpression + Puppet::Pops::Types::TypeCalculator.instance?(type, value) + end +end diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/functions/type_of.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/functions/type_of.rb new file mode 100644 index 0000000..02cdd4d --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/functions/type_of.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/abs.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/abs.rb new file mode 100644 index 0000000..11d2d7f --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/abs.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/any2array.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/any2array.rb new file mode 100644 index 0000000..e71407e --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/any2array.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/assert_private.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/assert_private.rb new file mode 100644 index 0000000..66c79cc --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/assert_private.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/base64.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/base64.rb new file mode 100644 index 0000000..617ba31 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/base64.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/basename.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/basename.rb new file mode 100644 index 0000000..f7e4438 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/basename.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/bool2num.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/bool2num.rb new file mode 100644 index 0000000..6ad6cf4 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/bool2num.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/bool2str.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/bool2str.rb new file mode 100644 index 0000000..7e36474 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/bool2str.rb @@ -0,0 +1,45 @@ +# +# bool2str.rb +# + +module Puppet::Parser::Functions + newfunction(:bool2str, :type => :rvalue, :doc => <<-EOS + Converts a boolean to a string using optionally supplied arguments. The + optional second and third arguments represent what true and false will be + converted to respectively. If only one argument is given, it will be + converted from a boolean to a string containing 'true' or 'false'. + + *Examples:* + + bool2str(true) => 'true' + bool2str(true, 'yes', 'no') => 'yes' + bool2str(false, 't', 'f') => 'f' + + Requires a single boolean as an input. + EOS + ) do |arguments| + + unless arguments.size == 1 or arguments.size == 3 + raise(Puppet::ParseError, "bool2str(): Wrong number of arguments " + + "given (#{arguments.size} for 3)") + end + + value = arguments[0] + true_string = arguments[1] || 'true' + false_string = arguments[2] || 'false' + 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 + + unless [true_string, false_string].all?{|x| x.kind_of?(String)} + raise(Puppet::ParseError, "bool2str(): Requires strings to convert to" ) + end + + return value ? true_string : false_string + end +end + +# vim: set ts=2 sw=2 et : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/camelcase.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/camelcase.rb new file mode 100644 index 0000000..d7f43f7 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/camelcase.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/capitalize.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/capitalize.rb new file mode 100644 index 0000000..98b2d16 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/capitalize.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ceiling.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ceiling.rb new file mode 100644 index 0000000..5f3b10b --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ceiling.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/chomp.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/chomp.rb new file mode 100644 index 0000000..c55841e --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/chomp.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/chop.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/chop.rb new file mode 100644 index 0000000..b24ab78 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/chop.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/concat.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/concat.rb new file mode 100644 index 0000000..618e62d --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/concat.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/convert_base.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/convert_base.rb new file mode 100644 index 0000000..0fcbafe --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/convert_base.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/count.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/count.rb new file mode 100644 index 0000000..52de1b8 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/count.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/deep_merge.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/deep_merge.rb new file mode 100644 index 0000000..6df32e9 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/deep_merge.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/defined_with_params.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/defined_with_params.rb new file mode 100644 index 0000000..d7df306 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/defined_with_params.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete.rb new file mode 100644 index 0000000..f548b44 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_at.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_at.rb new file mode 100644 index 0000000..3eb4b53 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_at.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_undef_values.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_undef_values.rb new file mode 100644 index 0000000..f94d4da --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_undef_values.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_values.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_values.rb new file mode 100644 index 0000000..f6c8c0e --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/delete_values.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/difference.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/difference.rb new file mode 100644 index 0000000..cd258f7 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/difference.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/dirname.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/dirname.rb new file mode 100644 index 0000000..40b300d --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/dirname.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/dos2unix.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/dos2unix.rb new file mode 100644 index 0000000..ccac899 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/dos2unix.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/downcase.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/downcase.rb new file mode 100644 index 0000000..040b84f --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/downcase.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/empty.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/empty.rb new file mode 100644 index 0000000..b5a3cde --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/empty.rb @@ -0,0 +1,31 @@ +# +# 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) || value.is_a?(Numeric) + raise(Puppet::ParseError, 'empty(): Requires either ' + + 'array, hash, string or integer to work with') + end + + if value.is_a?(Numeric) + return false + else + result = value.empty? + + return result + end + end +end + +# vim: set ts=2 sw=2 et : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ensure_packages.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ensure_packages.rb new file mode 100644 index 0000000..f1da4aa --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ensure_packages.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ensure_resource.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ensure_resource.rb new file mode 100644 index 0000000..1ba6a44 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/ensure_resource.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/flatten.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/flatten.rb new file mode 100644 index 0000000..a1ed183 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/flatten.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/floor.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/floor.rb new file mode 100644 index 0000000..9a6f014 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/floor.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb new file mode 100644 index 0000000..2bb1287 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/fqdn_rotate.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/fqdn_rotate.rb new file mode 100644 index 0000000..b66431d --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/fqdn_rotate.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/get_module_path.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/get_module_path.rb new file mode 100644 index 0000000..1421b91 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/get_module_path.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/getparam.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/getparam.rb new file mode 100644 index 0000000..6d51006 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/getparam.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/getvar.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/getvar.rb new file mode 100644 index 0000000..ae9c869 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/getvar.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/grep.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/grep.rb new file mode 100644 index 0000000..ceba9ec --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/grep.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_interface_with.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_interface_with.rb new file mode 100644 index 0000000..e762798 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_interface_with.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_ip_address.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_ip_address.rb new file mode 100644 index 0000000..842c8ec --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_ip_address.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_ip_network.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_ip_network.rb new file mode 100644 index 0000000..9ccf902 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_ip_network.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_key.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_key.rb new file mode 100644 index 0000000..4657cc2 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/has_key.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/hash.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/hash.rb new file mode 100644 index 0000000..8cc4823 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/hash.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/intersection.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/intersection.rb new file mode 100644 index 0000000..bfbb4ba --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/intersection.rb @@ -0,0 +1,34 @@ +# +# intersection.rb +# + +module Puppet::Parser::Functions + newfunction(:intersection, :type => :rvalue, :doc => <<-EOS +This function returns an array of the intersection of two. + +*Examples:* + + intersection(["a","b","c"],["b","c","d"]) # returns ["b","c"] + intersection(["a","b","c"],[1,2,3,4]) # returns [] (true, when evaluated as a Boolean) + + 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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_absolute_path.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_absolute_path.rb new file mode 100644 index 0000000..53a5445 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_absolute_path.rb @@ -0,0 +1,50 @@ +module Puppet::Parser::Functions + newfunction(:is_absolute_path, :type => :rvalue, :arity => 1, :doc => <<-'ENDHEREDOC') do |args| + Returns boolean true if the string represents an absolute path in the filesystem. This function works + for windows and unix style paths. + + The following values will return true: + + $my_path = 'C:/Program Files (x86)/Puppet Labs/Puppet' + is_absolute_path($my_path) + $my_path2 = '/var/lib/puppet' + is_absolute_path($my_path2) + $my_path3 = ['C:/Program Files (x86)/Puppet Labs/Puppet'] + is_absolute_path($my_path3) + $my_path4 = ['/var/lib/puppet'] + is_absolute_path($my_path4) + + The following values will return false: + + is_absolute_path(true) + is_absolute_path('../var/lib/puppet') + is_absolute_path('var/lib/puppet') + $undefined = undef + is_absolute_path($undefined) + + ENDHEREDOC + + require 'puppet/util' + + path = args[0] + # 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 + value = (Puppet::Util.absolute_path?(path, :posix) or Puppet::Util.absolute_path?(path, :windows)) + 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!^/! + } + value = (!!(path =~ regexes[:posix])) || (!!(path =~ regexes[:windows])) + end + value + end +end \ No newline at end of file diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_array.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_array.rb new file mode 100644 index 0000000..b39e184 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_array.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_bool.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_bool.rb new file mode 100644 index 0000000..8bbdbc8 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_bool.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_domain_name.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_domain_name.rb new file mode 100644 index 0000000..90ede32 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_domain_name.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_float.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_float.rb new file mode 100644 index 0000000..a2da943 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_float.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_function_available.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_function_available.rb new file mode 100644 index 0000000..6da82c8 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_function_available.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_hash.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_hash.rb new file mode 100644 index 0000000..ad907f0 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_hash.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_integer.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_integer.rb new file mode 100644 index 0000000..c03d28d --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_integer.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_ip_address.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_ip_address.rb new file mode 100644 index 0000000..a90adab --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_ip_address.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_mac_address.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_mac_address.rb new file mode 100644 index 0000000..2619d44 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_mac_address.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_numeric.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_numeric.rb new file mode 100644 index 0000000..e7e1d2a --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_numeric.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_string.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_string.rb new file mode 100644 index 0000000..f5bef04 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/is_string.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/join.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/join.rb new file mode 100644 index 0000000..6c0a6ba --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/join.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/join_keys_to_values.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/join_keys_to_values.rb new file mode 100644 index 0000000..e9924fe --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/join_keys_to_values.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/keys.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/keys.rb new file mode 100644 index 0000000..f0d13b6 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/keys.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/load_module_metadata.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/load_module_metadata.rb new file mode 100644 index 0000000..c9b8488 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/load_module_metadata.rb @@ -0,0 +1,24 @@ +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 or two") unless [1,2].include?(args.size) + mod = args[0] + allow_empty_metadata = args[1] + module_path = function_get_module_path([mod]) + metadata_json = File.join(module_path, 'metadata.json') + + metadata_exists = File.exists?(metadata_json) + if metadata_exists + metadata = PSON.load(File.read(metadata_json)) + else + if allow_empty_metadata + metadata = {} + else + raise(Puppet::ParseError, "load_module_metadata(): No metadata.json file for module #{mod}") + end + end + + return metadata + end +end diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/loadyaml.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/loadyaml.rb new file mode 100644 index 0000000..ca655f6 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/loadyaml.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/lstrip.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/lstrip.rb new file mode 100644 index 0000000..624e4c8 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/lstrip.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/max.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/max.rb new file mode 100644 index 0000000..60fb94a --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/max.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/member.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/member.rb new file mode 100644 index 0000000..1e5b3de --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/member.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/merge.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/merge.rb new file mode 100644 index 0000000..1b39f20 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/merge.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/min.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/min.rb new file mode 100644 index 0000000..6bd6ebf --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/min.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/num2bool.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/num2bool.rb new file mode 100644 index 0000000..af0e6ed --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/num2bool.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/parsejson.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/parsejson.rb new file mode 100644 index 0000000..b4af40e --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/parsejson.rb @@ -0,0 +1,29 @@ +# +# parsejson.rb +# + +module Puppet::Parser::Functions + newfunction(:parsejson, :type => :rvalue, :doc => <<-EOS +This function accepts JSON as a string and converts it into the correct +Puppet structure. + +The optional second argument can be used to pass a default value that will +be returned if the parsing of YAML string have failed. + EOS + ) do |arguments| + raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless arguments.length >= 1 + + begin + PSON::load(arguments[0]) || arguments[1] + rescue Exception => e + if arguments[1] + arguments[1] + else + raise e + end + end + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/parseyaml.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/parseyaml.rb new file mode 100644 index 0000000..66d0413 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/parseyaml.rb @@ -0,0 +1,30 @@ +# +# 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. + +The optional second argument can be used to pass a default value that will +be returned if the parsing of YAML string have failed. + EOS + ) do |arguments| + raise ArgumentError, 'Wrong number of arguments. 1 or 2 arguments should be provided.' unless arguments.length >= 1 + require 'yaml' + + begin + YAML::load(arguments[0]) || arguments[1] + rescue Exception => e + if arguments[1] + arguments[1] + else + raise e + end + end + + end +end + +# vim: set ts=2 sw=2 et : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pick.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pick.rb new file mode 100644 index 0000000..fdd0aef --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pick.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pick_default.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pick_default.rb new file mode 100644 index 0000000..36e33ab --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pick_default.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/prefix.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/prefix.rb new file mode 100644 index 0000000..ac1c58a --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/prefix.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/private.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/private.rb new file mode 100644 index 0000000..3b00ba1 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/private.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pw_hash.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pw_hash.rb new file mode 100644 index 0000000..41d4223 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/pw_hash.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/range.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/range.rb new file mode 100644 index 0000000..2fc2113 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/range.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/reject.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/reject.rb new file mode 100644 index 0000000..1953ffc --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/reject.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/reverse.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/reverse.rb new file mode 100644 index 0000000..7f1018f --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/reverse.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/rstrip.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/rstrip.rb new file mode 100644 index 0000000..0cf8d22 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/rstrip.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/seeded_rand.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/seeded_rand.rb new file mode 100644 index 0000000..44e27b8 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/seeded_rand.rb @@ -0,0 +1,22 @@ +Puppet::Parser::Functions::newfunction( + :seeded_rand, + :arity => 2, + :type => :rvalue, + :doc => <<-EOS +Usage: `seeded_rand(MAX, SEED)`. MAX must be a positive integer; SEED is any string. + +Generates a random whole number greater than or equal to 0 and less +than MAX, using the value of SEED for repeatable randomness. If SEED +starts with "$fqdn:", this is behaves the same as `fqdn_rand`. + +EOS +) do |args| + require 'digest/md5' + + raise(ArgumentError, "seeded_rand(): first argument must be a positive integer") unless function_is_integer([args[0]]) and args[0].to_i > 0 + raise(ArgumentError, "seeded_rand(): second argument must be a string") unless args[1].is_a? String + + max = args[0].to_i + seed = Digest::MD5.hexdigest(args[1]).hex + Puppet::Util.deterministic_rand(seed,max) +end diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/shuffle.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/shuffle.rb new file mode 100644 index 0000000..30c663d --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/shuffle.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/size.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/size.rb new file mode 100644 index 0000000..0d6cc96 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/size.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/sort.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/sort.rb new file mode 100644 index 0000000..cefbe54 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/sort.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/squeeze.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/squeeze.rb new file mode 100644 index 0000000..81fadfd --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/squeeze.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/str2bool.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/str2bool.rb new file mode 100644 index 0000000..8def131 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/str2bool.rb @@ -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,y, 1, T,t, TRUE,true to 'true' and strings that contain things +like: 0, F,f, N,n, false, 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)$/i then true + when /^(0|f|n|false|no)$/i 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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/str2saltedsha512.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/str2saltedsha512.rb new file mode 100644 index 0000000..7fe7b01 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/str2saltedsha512.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/strftime.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/strftime.rb new file mode 100644 index 0000000..0b52ade --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/strftime.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/strip.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/strip.rb new file mode 100644 index 0000000..3fac47d --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/strip.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/suffix.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/suffix.rb new file mode 100644 index 0000000..f7792d6 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/suffix.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/swapcase.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/swapcase.rb new file mode 100644 index 0000000..eb7fe13 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/swapcase.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/time.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/time.rb new file mode 100644 index 0000000..c574747 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/time.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/to_bytes.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/to_bytes.rb new file mode 100644 index 0000000..df490ea --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/to_bytes.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/try_get_value.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/try_get_value.rb new file mode 100644 index 0000000..0c19fd9 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/try_get_value.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/type.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/type.rb new file mode 100644 index 0000000..016529b --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/type.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/type3x.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/type3x.rb new file mode 100644 index 0000000..0800b4a --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/type3x.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/union.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/union.rb new file mode 100644 index 0000000..6c5bb83 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/union.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/unique.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/unique.rb new file mode 100644 index 0000000..cf770f3 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/unique.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/unix2dos.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/unix2dos.rb new file mode 100644 index 0000000..0bd9cd1 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/unix2dos.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/upcase.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/upcase.rb new file mode 100644 index 0000000..44b3bcd --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/upcase.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/uriescape.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/uriescape.rb new file mode 100644 index 0000000..45bbed2 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/uriescape.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_absolute_path.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_absolute_path.rb new file mode 100644 index 0000000..5f85f72 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_absolute_path.rb @@ -0,0 +1,51 @@ +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 paths within the candidates array + candidates.each do |path| + unless function_is_absolute_path([path]) + raise Puppet::ParseError, ("#{path.inspect} is not an absolute path.") + end + end + end + end +end diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_array.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_array.rb new file mode 100644 index 0000000..34b5118 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_array.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_augeas.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_augeas.rb new file mode 100644 index 0000000..2196c3e --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_augeas.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_bool.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_bool.rb new file mode 100644 index 0000000..59a0805 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_bool.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_cmd.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_cmd.rb new file mode 100644 index 0000000..5df3c60 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_cmd.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_hash.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_hash.rb new file mode 100644 index 0000000..9bdd543 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_hash.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_integer.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_integer.rb new file mode 100644 index 0000000..a950916 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_integer.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ip_address.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ip_address.rb new file mode 100644 index 0000000..c0baf82 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ip_address.rb @@ -0,0 +1,50 @@ +module Puppet::Parser::Functions + + newfunction(:validate_ip_address, :doc => <<-ENDHEREDOC + Validate that all values passed are valid IP addresses, + regardless they are IPv4 or IPv6 + Fail compilation if any value fails this check. + The following values will pass: + $my_ip = "1.2.3.4" + validate_ip_address($my_ip) + validate_bool("8.8.8.8", "172.16.0.1", $my_ip) + + $my_ip = "3ffe:505:2" + validate_ip_address(1) + validate_ip_address($my_ip) + validate_bool("fe80::baf6:b1ff:fe19:7507", $my_ip) + + The following values will fail, causing compilation to abort: + $some_array = [ 1, true, false, "garbage string", "3ffe:505:2" ] + validate_ip_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_ip_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? or IPAddr.new(arg).ipv6? + raise Puppet::ParseError, "#{arg.inspect} is not a valid IP address." + end + rescue *rescuable_exceptions + raise Puppet::ParseError, "#{arg.inspect} is not a valid IP address." + end + end + + end + +end diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ipv4_address.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ipv4_address.rb new file mode 100644 index 0000000..97faa57 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ipv4_address.rb @@ -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_ipv4_address("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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ipv6_address.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ipv6_address.rb new file mode 100644 index 0000000..b0f2558 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_ipv6_address.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_numeric.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_numeric.rb new file mode 100644 index 0000000..3a14443 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_numeric.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_re.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_re.rb new file mode 100644 index 0000000..efee7f8 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_re.rb @@ -0,0 +1,47 @@ +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') + + Note: Compilation will also abort, if the first argument is not a String. Always use + quotes to force stringification: + + validate_re("${::operatingsystemmajrelease}", '^[57]$') + + 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 + + raise Puppet::ParseError, "validate_re(): input needs to be a String, not a #{args[0].class}" unless args[0].is_a? String + + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_slength.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_slength.rb new file mode 100644 index 0000000..47c7d4a --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_slength.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_string.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_string.rb new file mode 100644 index 0000000..c841f6a --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/validate_string.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/values.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/values.rb new file mode 100644 index 0000000..1606756 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/values.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/values_at.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/values_at.rb new file mode 100644 index 0000000..f350f53 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/values_at.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/zip.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/zip.rb new file mode 100644 index 0000000..3074f28 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/parser/functions/zip.rb @@ -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 : diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/provider/file_line/ruby.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/provider/file_line/ruby.rb new file mode 100644 index 0000000..aab6fe2 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/provider/file_line/ruby.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/type/anchor.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/type/anchor.rb new file mode 100644 index 0000000..fe1e5aa --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/type/anchor.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/type/file_line.rb b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/type/file_line.rb new file mode 100644 index 0000000..77d3be2 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/lib/puppet/type/file_line.rb @@ -0,0 +1,118 @@ +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 comparison 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 diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/manifests/init.pp b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/manifests/init.pp new file mode 100644 index 0000000..9ea22a7 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/manifests/init.pp @@ -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 +} diff --git a/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/manifests/stages.pp b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/manifests/stages.pp new file mode 100644 index 0000000..7de254c --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/fixtures/modules/stdlib/manifests/stages.pp @@ -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': } + +} diff --git a/puphpet/puppet/modules/stdlib/spec/functions/abs_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/abs_spec.rb index 3c25ce2..7d2257b 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/abs_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/abs_spec.rb @@ -1,25 +1,30 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe "the abs function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("abs")).to eq("function_abs") - end +describe 'abs' do + it { is_expected.not_to eq(nil) } - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_abs([]) }.to( raise_error(Puppet::ParseError)) + 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 - it "should convert a negative number into a positive" do - result = scope.function_abs(["-34"]) - expect(result).to(eq(34)) + 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 "should do nothing with a positive number" do - result = scope.function_abs(["5678"]) - expect(result).to(eq(5678)) - 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/any2array_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/any2array_spec.rb index 87cd04b..70121f1 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/any2array_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/any2array_spec.rb @@ -1,55 +1,15 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the any2array function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("any2array")).to eq("function_any2array") - end - - it "should return an empty array if there is less than 1 argument" do - result = scope.function_any2array([]) - expect(result).to(eq([])) - end - - it "should convert boolean true to [ true ] " do - result = scope.function_any2array([true]) - expect(result).to(eq([true])) - end - - it "should convert one object to [object]" do - result = scope.function_any2array(['one']) - expect(result).to(eq(['one'])) - end - - it "should convert multiple objects to [objects]" do - result = scope.function_any2array(['one', 'two']) - expect(result).to(eq(['one', 'two'])) - end - - it "should return empty array it was called with" do - result = scope.function_any2array([[]]) - expect(result).to(eq([])) - end - - it "should return one-member array it was called with" do - result = scope.function_any2array([['string']]) - expect(result).to(eq(['string'])) - end - - it "should return multi-member array it was called with" do - result = scope.function_any2array([['one', 'two']]) - expect(result).to(eq(['one', 'two'])) - end - - it "should return members of a hash it was called with" do - result = scope.function_any2array([{ 'key' => 'value' }]) - expect(result).to(eq(['key', 'value'])) - end - - it "should return an empty array if it was called with an empty hash" do - result = scope.function_any2array([{ }]) - expect(result).to(eq([])) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/assert_private_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/assert_private_spec.rb index a009d28..98f2598 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/assert_private_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/assert_private_spec.rb @@ -1,15 +1,7 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe Puppet::Parser::Functions.function(:assert_private) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - subject do - function_name = Puppet::Parser::Functions.function(:assert_private) - scope.method(function_name) - end - - context "when called from inside module" do +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') diff --git a/puphpet/puppet/modules/stdlib/spec/functions/base64_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/base64_spec.rb index e93fafc..c529e9e 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/base64_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/base64_spec.rb @@ -1,34 +1,16 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe "the base64 function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("base64")).to eq("function_base64") - end - - it "should raise a ParseError if there are other than 2 arguments" do - expect { scope.function_base64([]) }.to(raise_error(Puppet::ParseError)) - expect { scope.function_base64(["asdf"]) }.to(raise_error(Puppet::ParseError)) - expect { scope.function_base64(["asdf","moo","cow"]) }.to(raise_error(Puppet::ParseError)) - end - - it "should raise a ParseError if argument 1 isn't 'encode' or 'decode'" do - expect { scope.function_base64(["bees","astring"]) }.to(raise_error(Puppet::ParseError, /first argument must be one of/)) - end - - it "should raise a ParseError if argument 2 isn't a string" do - expect { scope.function_base64(["encode",["2"]]) }.to(raise_error(Puppet::ParseError, /second argument must be a string/)) - end +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 "should encode a encoded string" do - result = scope.function_base64(["encode",'thestring']) - expect(result).to match(/\AdGhlc3RyaW5n\n\Z/) - end - it "should decode a base64 encoded string" do - result = scope.function_base64(["decode",'dGhlc3RyaW5n']) - expect(result).to eq('thestring') - end + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/basename_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/basename_spec.rb new file mode 100755 index 0000000..0ea30e7 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/basename_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/bool2num_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/bool2num_spec.rb index 3904d7e..e506859 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/bool2num_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/bool2num_spec.rb @@ -1,38 +1,14 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the bool2num function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +describe 'bool2num' do + it { is_expected.not_to eq(nil) } + it { is_expected.to run.with_params().and_raise_error(Puppet::ParseError) } - it "should exist" do - expect(Puppet::Parser::Functions.function("bool2num")).to eq("function_bool2num") + [ true, 'true', AlsoString.new('true') ].each do |truthy| + it { is_expected.to run.with_params(truthy).and_return(1) } end - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_bool2num([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should convert true to 1" do - result = scope.function_bool2num([true]) - expect(result).to(eq(1)) - end - - it "should convert 'true' to 1" do - result = scope.function_bool2num(['true']) - result.should(eq(1)) - end - - it "should convert 'false' to 0" do - result = scope.function_bool2num(['false']) - expect(result).to(eq(0)) - end - - it "should accept objects which extend String" do - class AlsoString < String - end - - value = AlsoString.new('true') - result = scope.function_bool2num([value]) - result.should(eq(1)) + [ false, 'false', AlsoString.new('false') ].each do |falsey| + it { is_expected.to run.with_params(falsey).and_return(0) } end end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/bool2str_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/bool2str_spec.rb new file mode 100755 index 0000000..23a754b --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/bool2str_spec.rb @@ -0,0 +1,17 @@ +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, 'yes', 'no', 'maybe').and_raise_error(Puppet::ParseError) } + it { is_expected.to run.with_params(true, 'maybe').and_raise_error(Puppet::ParseError) } + it { is_expected.to run.with_params(true, 0, 1).and_raise_error(Puppet::ParseError) } + it { is_expected.to run.with_params(true).and_return("true") } + it { is_expected.to run.with_params(false).and_return("false") } + it { is_expected.to run.with_params(true, 'yes', 'no').and_return("yes") } + it { is_expected.to run.with_params(false, 'yes', 'no').and_return("no") } + +end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/camelcase_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/camelcase_spec.rb new file mode 100755 index 0000000..c78aa62 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/camelcase_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/capitalize_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/capitalize_spec.rb index fd0e92b..7ce2e16 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/capitalize_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/capitalize_spec.rb @@ -1,28 +1,15 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the capitalize function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("capitalize")).to eq("function_capitalize") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_capitalize([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should capitalize the beginning of a string" do - result = scope.function_capitalize(["abc"]) - expect(result).to(eq("Abc")) - end - - it "should accept objects which extend String" do - class AlsoString < String - end - - value = AlsoString.new('abc') - result = scope.function_capitalize([value]) - result.should(eq('Abc')) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/ceiling_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/ceiling_spec.rb index 814aa7c..567426f 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/ceiling_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/ceiling_spec.rb @@ -1,39 +1,13 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe "the ceiling function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("ceiling")).to eq("function_ceiling") - end - - it "should raise a ParseError if there is less than 1 argument" do - expect { scope.function_ceiling([]) }.to( raise_error(Puppet::ParseError, /Wrong number of arguments/)) - end - - it "should should raise a ParseError if input isn't numeric (eg. String)" do - expect { scope.function_ceiling(["foo"]) }.to( raise_error(Puppet::ParseError, /Wrong argument type/)) - end - - it "should should raise a ParseError if input isn't numeric (eg. Boolean)" do - expect { scope.function_ceiling([true]) }.to( raise_error(Puppet::ParseError, /Wrong argument type/)) - end - - it "should return an integer when a numeric type is passed" do - result = scope.function_ceiling([12.4]) - expect(result.is_a?(Integer)).to(eq(true)) - end - - it "should return the input when an integer is passed" do - result = scope.function_ceiling([7]) - expect(result).to(eq(7)) - end - - it "should return the smallest integer greater than or equal to the input" do - result = scope.function_ceiling([3.8]) - expect(result).to(eq(4)) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/chomp_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/chomp_spec.rb index b1e1e60..6878742 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/chomp_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/chomp_spec.rb @@ -1,28 +1,20 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the chomp function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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 "should exist" do - expect(Puppet::Parser::Functions.function("chomp")).to eq("function_chomp") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_chomp([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should chomp the end of a string" do - result = scope.function_chomp(["abc\n"]) - expect(result).to(eq("abc")) - end - - it "should accept objects which extend String" do - class AlsoString < String - end - - value = AlsoString.new("abc\n") - result = scope.function_chomp([value]) - result.should(eq("abc")) - end + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/chop_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/chop_spec.rb index c8a1951..db7d18b 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/chop_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/chop_spec.rb @@ -1,28 +1,20 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the chop function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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 "should exist" do - expect(Puppet::Parser::Functions.function("chop")).to eq("function_chop") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_chop([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should chop the end of a string" do - result = scope.function_chop(["asdf\n"]) - expect(result).to(eq("asdf")) - end - - it "should accept objects which extend String" do - class AlsoString < String - end - - value = AlsoString.new("abc\n") - result = scope.function_chop([value]) - result.should(eq('abc')) - end + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/concat_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/concat_spec.rb index 49fa6bb..1694d5e 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/concat_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/concat_spec.rb @@ -1,50 +1,24 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the concat function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should raise a ParseError if the client does not provide at least two arguments" do - expect { scope.function_concat([]) }.to(raise_error(Puppet::ParseError)) - expect { scope.function_concat([[1]]) }.to(raise_error(Puppet::ParseError)) - end - - it "should raise a ParseError if the first parameter is not an array" do - expect { scope.function_concat([1, []])}.to(raise_error(Puppet::ParseError)) - end - - it "should not raise a ParseError if the client provides more than two arguments" do - expect { scope.function_concat([[1],[2],[3]]) }.not_to raise_error - end - - it "should be able to concat an array" do - result = scope.function_concat([['1','2','3'],['4','5','6']]) - expect(result).to(eq(['1','2','3','4','5','6'])) - end - - it "should be able to concat a primitive to an array" do - result = scope.function_concat([['1','2','3'],'4']) - expect(result).to(eq(['1','2','3','4'])) - end - - it "should not accidentally flatten nested arrays" do - result = scope.function_concat([['1','2','3'],[['4','5'],'6']]) - expect(result).to(eq(['1','2','3',['4','5'],'6'])) - end +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 - array_original = ['1','2','3'] - result = scope.function_concat([array_original,['4','5','6']]) - array_original.should(eq(['1','2','3'])) - end - - it "should be able to concat multiple arrays" do - result = scope.function_concat([['1','2','3'],['4','5','6'],['7','8','9']]) - expect(result).to(eq(['1','2','3','4','5','6','7','8','9'])) - end - - it "should be able to concat mix of primitives and arrays to a final array" do - result = scope.function_concat([['1','2','3'],'4',['5','6','7']]) - expect(result).to(eq(['1','2','3','4','5','6','7'])) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/convert_base_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/convert_base_spec.rb new file mode 100644 index 0000000..8ab2284 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/convert_base_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/count_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/count_spec.rb index f8f1d48..c8d1960 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/count_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/count_spec.rb @@ -1,31 +1,18 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe "the count function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("count")).to eq("function_count") - end - - it "should raise a ArgumentError if there is more than 2 arguments" do - expect { scope.function_count(['foo', 'bar', 'baz']) }.to( raise_error(ArgumentError)) - end - - it "should be able to count arrays" do - expect(scope.function_count([["1","2","3"]])).to(eq(3)) - end - - it "should be able to count matching elements in arrays" do - expect(scope.function_count([["1", "2", "2"], "2"])).to(eq(2)) - end - - it "should not count nil or empty strings" do - expect(scope.function_count([["foo","bar",nil,""]])).to(eq(2)) - end - - it 'does not count an undefined hash key or an out of bound array index (which are both :undef)' do - expect(scope.function_count([["foo",:undef,:undef]])).to eq(1) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/deep_merge_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/deep_merge_spec.rb index 7087904..397e048 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/deep_merge_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/deep_merge_spec.rb @@ -1,105 +1,55 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe Puppet::Parser::Functions.function(:deep_merge) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - describe 'when calling deep_merge 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 = deep_merge()' - 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 = deep_merge($my_hash)" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /wrong number of arguments/) - end +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 calling deep_merge on the scope instance' do - it 'should require all parameters are hashes' do - expect { new_hash = scope.function_deep_merge([{}, '2'])}.to raise_error(Puppet::ParseError, /unexpected argument type String/) - expect { new_hash = scope.function_deep_merge([{}, 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_deep_merge([{}, ''])}.not_to raise_error - end - - it 'should be able to deep_merge two hashes' do - new_hash = scope.function_deep_merge([{'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 deep_merge multiple hashes' do - hash = scope.function_deep_merge([{'one' => 1}, {'one' => '2'}, {'one' => '3'}]) - expect(hash['one']).to eq('3') - end - - it 'should accept empty hashes' do - expect(scope.function_deep_merge([{},{},{}])).to eq({}) - end - - it 'should deep_merge subhashes' do - hash = scope.function_deep_merge([{'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_deep_merge([{'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_deep_merge([{'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_deep_merge([{ '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 not change the original hashes' do - hash1 = {'one' => { 'two' => 2 } } - hash2 = { 'one' => { 'three' => 3 } } - hash = scope.function_deep_merge([hash1, hash2]) - expect(hash1).to eq({'one' => { 'two' => 2 } }) - expect(hash2).to eq({ 'one' => { 'three' => 3 } }) - expect(hash['one']).to eq({ 'two' => 2, 'three' => 3 }) - 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 2' do - hash1 = {'one' => { 'two' => [1,2] } } - hash2 = { 'one' => { 'three' => 3 } } - hash = scope.function_deep_merge([hash1, hash2]) - expect(hash1).to eq({'one' => { 'two' => [1,2] } }) - expect(hash2).to eq({ 'one' => { 'three' => 3 } }) - expect(hash['one']).to eq({ 'two' => [1,2], 'three' => 3 }) - end + it 'should not change the original hashes' do + argument1 = { 'key1' => 'value1' } + original1 = argument1.dup + argument2 = { 'key2' => 'value2' } + original2 = argument2.dup - it 'should not change the original hashes 3' do - hash1 = {'one' => { 'two' => [1,2, {'two' => 2} ] } } - hash2 = { 'one' => { 'three' => 3 } } - hash = scope.function_deep_merge([hash1, hash2]) - expect(hash1).to eq({'one' => { 'two' => [1,2, {'two' => 2}] } }) - expect(hash2).to eq({ 'one' => { 'three' => 3 } }) - expect(hash['one']).to eq({ 'two' => [1,2, {'two' => 2} ], 'three' => 3 }) - expect(hash['one']['two']).to eq([1,2, {'two' => 2}]) - end + subject.call([argument1, argument2]) + expect(argument1).to eq(original1) + expect(argument2).to eq(original2) end end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/defined_with_params_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/defined_with_params_spec.rb index 3590304..516d986 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/defined_with_params_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/defined_with_params_spec.rb @@ -1,37 +1,26 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -require 'rspec-puppet' describe 'defined_with_params' do - describe 'when a resource is not specified' 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 do - is_expected.to run.with_params('User[dan]', {}).and_return(true) - is_expected.to run.with_params('User[bob]', {}).and_return(false) - is_expected.to run.with_params('User[dan]', {'foo' => 'bar'}).and_return(false) - 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 do - is_expected.to run.with_params('User[dan]', {}).and_return(true) - is_expected.to run.with_params('User[dan]', '').and_return(true) - is_expected.to run.with_params('User[dan]', {'ensure' => 'present'} - ).and_return(true) - is_expected.to run.with_params('User[dan]', - {'ensure' => 'present', 'managehome' => false} - ).and_return(true) - is_expected.to run.with_params('User[dan]', - {'ensure' => 'absent', 'managehome' => false} - ).and_return(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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/delete_at_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/delete_at_spec.rb index 7c20aec..0e19472 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/delete_at_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/delete_at_spec.rb @@ -1,25 +1,28 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the delete_at function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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) + } - it "should exist" do - expect(Puppet::Parser::Functions.function("delete_at")).to eq("function_delete_at") + describe 'argument validation' do + it { is_expected.to run.with_params([0, 1, 2], 3).and_raise_error(Puppet::ParseError) } end - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_delete_at([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should delete an item at specified location from an array" do - result = scope.function_delete_at([['a','b','c'],1]) - expect(result).to(eq(['a','c'])) - 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 not change origin array passed as argument" do - origin_array = ['a','b','c','d'] - result = scope.function_delete_at([origin_array, 1]) - expect(origin_array).to(eq(['a','b','c','d'])) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/delete_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/delete_spec.rb index c8edd78..6c4747b 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/delete_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/delete_spec.rb @@ -1,61 +1,67 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the delete function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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) } - it "should exist" do - expect(Puppet::Parser::Functions.function("delete")).to eq("function_delete") + 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 - it "should raise a ParseError if there are fewer than 2 arguments" do - expect { scope.function_delete([]) }.to(raise_error(Puppet::ParseError)) + 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 - it "should raise a ParseError if there are greater than 2 arguments" do - expect { scope.function_delete([[], 'foo', 'bar']) }.to(raise_error(Puppet::ParseError)) + 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 raise a TypeError if a number is passed as the first argument" do - expect { scope.function_delete([1, 'bar']) }.to(raise_error(TypeError)) + 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 delete all instances of an element from an array" do - result = scope.function_delete([['a', 'b', 'c', 'b'], 'b']) - expect(result).to(eq(['a', 'c'])) - end - - it "should delete all instances of a substring from a string" do - result = scope.function_delete(['foobarbabarz', 'bar']) - expect(result).to(eq('foobaz')) + 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 delete a key from a hash" do - result = scope.function_delete([{'a' => 1, 'b' => 2, 'c' => 3}, 'b']) - expect(result).to(eq({'a' => 1, 'c' => 3})) + 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 - - it 'should accept an array of items to delete' do - result = scope.function_delete([{'a' => 1, 'b' => 2, 'c' => 3}, ['b', 'c']]) - expect(result).to(eq({'a' => 1})) - end - - it "should not change origin array passed as argument" do - origin_array = ['a', 'b', 'c', 'd'] - result = scope.function_delete([origin_array, 'b']) - expect(origin_array).to(eq(['a', 'b', 'c', 'd'])) - end - - it "should not change the origin string passed as argument" do - origin_string = 'foobarbabarz' - result = scope.function_delete([origin_string, 'bar']) - expect(origin_string).to(eq('foobarbabarz')) - end - - it "should not change origin hash passed as argument" do - origin_hash = {'a' => 1, 'b' => 2, 'c' => 3} - result = scope.function_delete([origin_hash, 'b']) - expect(origin_hash).to(eq({'a' => 1, 'b' => 2, 'c' => 3})) - end - end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/delete_undef_values_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/delete_undef_values_spec.rb index dc67953..ec9fb9c 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/delete_undef_values_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/delete_undef_values_spec.rb @@ -1,41 +1,56 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the delete_undef_values function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("delete_undef_values")).to eq("function_delete_undef_values") - end - - it "should raise a ParseError if there is less than 1 argument" do - expect { scope.function_delete_undef_values([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should raise a ParseError if the argument is not Array nor Hash" do - expect { scope.function_delete_undef_values(['']) }.to( raise_error(Puppet::ParseError)) - expect { scope.function_delete_undef_values([nil]) }.to( raise_error(Puppet::ParseError)) - end - - it "should delete all undef items from Array and only these" do - result = scope.function_delete_undef_values([['a',:undef,'c','undef']]) - expect(result).to(eq(['a','c','undef'])) - end - - it "should delete all undef items from Hash and only these" do - result = scope.function_delete_undef_values([{'a'=>'A','b'=>:undef,'c'=>'C','d'=>'undef'}]) - expect(result).to(eq({'a'=>'A','c'=>'C','d'=>'undef'})) - end - - it "should not change origin array passed as argument" do - origin_array = ['a',:undef,'c','undef'] - result = scope.function_delete_undef_values([origin_array]) - expect(origin_array).to(eq(['a',:undef,'c','undef'])) +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 - it "should not change origin hash passed as argument" do - origin_hash = { 'a' => 1, 'b' => :undef, 'c' => 'undef' } - result = scope.function_delete_undef_values([origin_hash]) - expect(origin_hash).to(eq({ 'a' => 1, 'b' => :undef, 'c' => 'undef' })) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/delete_values_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/delete_values_spec.rb index 4f4d411..12907d4 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/delete_values_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/delete_values_spec.rb @@ -1,36 +1,37 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the delete_values function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("delete_values")).to eq("function_delete_values") - end - - it "should raise a ParseError if there are fewer than 2 arguments" do - expect { scope.function_delete_values([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should raise a ParseError if there are greater than 2 arguments" do - expect { scope.function_delete_values([[], 'foo', 'bar']) }.to( raise_error(Puppet::ParseError)) - end - - it "should raise a TypeError if the argument is not a hash" do - expect { scope.function_delete_values([1,'bar']) }.to( raise_error(TypeError)) - expect { scope.function_delete_values(['foo','bar']) }.to( raise_error(TypeError)) - expect { scope.function_delete_values([[],'bar']) }.to( raise_error(TypeError)) +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 - it "should delete all instances of a value from a hash" do - result = scope.function_delete_values([{ 'a'=>'A', 'b'=>'B', 'B'=>'C', 'd'=>'B' },'B']) - expect(result).to(eq({ 'a'=>'A', 'B'=>'C' })) + 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 not change origin hash passed as argument" do - origin_hash = { 'a' => 1, 'b' => 2, 'c' => 3 } - result = scope.function_delete_values([origin_hash, 2]) - expect(origin_hash).to(eq({ 'a' => 1, 'b' => 2, 'c' => 3 })) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/difference_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/difference_spec.rb index 24b2b1b..d5e983d 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/difference_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/difference_spec.rb @@ -1,19 +1,21 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the difference function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("difference")).to eq("function_difference") - end - - it "should raise a ParseError if there are fewer than 2 arguments" do - expect { scope.function_difference([]) }.to( raise_error(Puppet::ParseError) ) - end - - it "should return the difference between two arrays" do - result = scope.function_difference([["a","b","c"],["b","c","d"]]) - expect(result).to(eq(["a"])) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/dirname_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/dirname_spec.rb index 4261144..46c4c35 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/dirname_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/dirname_spec.rb @@ -1,38 +1,13 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the dirname function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("dirname")).to eq("function_dirname") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_dirname([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should raise a ParseError if there is more than 1 argument" do - expect { scope.function_dirname(['a', 'b']) }.to( raise_error(Puppet::ParseError)) - end - - it "should return dirname for an absolute path" do - result = scope.function_dirname(['/path/to/a/file.ext']) - expect(result).to(eq('/path/to/a')) - end - - it "should return dirname for a relative path" do - result = scope.function_dirname(['path/to/a/file.ext']) - expect(result).to(eq('path/to/a')) - end - - it "should complain about hash argument" do - expect { scope.function_dirname([{}]) }.to( raise_error(Puppet::ParseError)) - end - it "should complain about list argument" do - expect { scope.function_dirname([[]]) }.to( raise_error(Puppet::ParseError)) - end - it "should complain about numeric argument" do - expect { scope.function_dirname([2112]) }.to( raise_error(Puppet::ParseError)) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/dos2unix_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/dos2unix_spec.rb new file mode 100644 index 0000000..9c84703 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/dos2unix_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/downcase_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/downcase_spec.rb index edebc44..c594560 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/downcase_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/downcase_spec.rb @@ -1,33 +1,15 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the downcase function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("downcase")).to eq("function_downcase") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_downcase([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should downcase a string" do - result = scope.function_downcase(["ASFD"]) - expect(result).to(eq("asfd")) - end - - it "should do nothing to a string that is already downcase" do - result = scope.function_downcase(["asdf asdf"]) - expect(result).to(eq("asdf asdf")) - end - - it "should accept objects which extend String" do - class AlsoString < String - end - - value = AlsoString.new("ASFD") - result = scope.function_downcase([value]) - result.should(eq('asfd')) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/empty_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/empty_spec.rb index 6a97c4c..a3a25d6 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/empty_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/empty_spec.rb @@ -1,32 +1,22 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the empty function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - it "should exist" do - expect(Puppet::Parser::Functions.function("empty")).to eq("function_empty") - end +describe 'empty' do + it { is_expected.not_to eq(nil) } + it { is_expected.to run.with_params().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(0).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 "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_empty([]) }.to( raise_error(Puppet::ParseError)) - end + 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 "should return a true for an empty string" do - result = scope.function_empty(['']) - expect(result).to(eq(true)) - end + it { is_expected.to run.with_params([]).and_return(true) } + it { is_expected.to run.with_params(['one']).and_return(false) } - it "should return a false for a non-empty string" do - result = scope.function_empty(['asdf']) - expect(result).to(eq(false)) - end - - it "should accept objects which extend String" do - class AlsoString < String - end - - value = AlsoString.new() - result = scope.function_empty([value]) - result.should(eq(true)) - end + it { is_expected.to run.with_params({}).and_return(true) } + it { is_expected.to run.with_params({'key' => 'value'}).and_return(false) } end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/ensure_packages_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/ensure_packages_spec.rb index 436be10..c824732 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/ensure_packages_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/ensure_packages_spec.rb @@ -1,81 +1,36 @@ -#! /usr/bin/env ruby - require 'spec_helper' -require 'rspec-puppet' -require 'puppet_spec/compiler' describe 'ensure_packages' do - include PuppetSpec::Compiler - - before :each do - Puppet::Parser::Functions.autoloader.loadall - Puppet::Parser::Functions.function(:ensure_packages) - Puppet::Parser::Functions.function(:ensure_resource) - Puppet::Parser::Functions.function(:defined_with_params) - Puppet::Parser::Functions.function(:create_resources) - end - - let :node do Puppet::Node.new('localhost') end - let :compiler do Puppet::Parser::Compiler.new(node) end - let :scope do - if Puppet.version.to_f >= 3.0 - Puppet::Parser::Scope.new(compiler) - else - newscope = Puppet::Parser::Scope.new - newscope.compiler = compiler - newscope.source = Puppet::Resource::Type.new(:node, :localhost) - newscope - end - end - - describe 'argument handling' do - it 'fails with no arguments' do - expect { - scope.function_ensure_packages([]) - }.to raise_error(Puppet::ParseError, /0 for 1 or 2/) - end - - it 'accepts an array of values' do - scope.function_ensure_packages([['foo']]) - end - - it 'accepts a single package name as a string' do - scope.function_ensure_packages(['foo']) - end - end - - context 'given a catalog with puppet package => absent' do - let :catalog do - compile_to_catalog(<<-EOS - ensure_packages(['facter']) - package { puppet: ensure => absent } - EOS - ) - end - - it 'has no effect on Package[puppet]' do - expect(catalog.resource(:package, 'puppet')['ensure']).to eq('absent') - end - end - - context 'given a clean catalog' do - let :catalog do - compile_to_catalog('ensure_packages(["facter"])') - end - - it 'declares package resources with ensure => present' do - expect(catalog.resource(:package, 'facter')['ensure']).to eq('present') - end - end - - context 'given a clean catalog and specified defaults' do - let :catalog do - compile_to_catalog('ensure_packages(["facter"], {"provider" => "gem"})') - end - - it 'declares package resources with ensure => present' do - expect(catalog.resource(:package, 'facter')['ensure']).to eq('present') - expect(catalog.resource(:package, 'facter')['provider']).to eq('gem') + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/ensure_resource_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/ensure_resource_spec.rb index 33bcac0..c4f2cbd 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/ensure_resource_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/ensure_resource_spec.rb @@ -1,113 +1,55 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -require 'rspec-puppet' -require 'puppet_spec/compiler' describe 'ensure_resource' do - include PuppetSpec::Compiler + 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) + } - before :all do - Puppet::Parser::Functions.autoloader.loadall - Puppet::Parser::Functions.function(:ensure_packages) - end - - let :node do Puppet::Node.new('localhost') end - let :compiler do Puppet::Parser::Compiler.new(node) end - let :scope do Puppet::Parser::Scope.new(compiler) end + context 'given a catalog with "user { username1: ensure => present }"' do + let(:pre_condition) { 'user { username1: ensure => present }' } - describe 'when a type or title is not specified' do - it { expect { scope.function_ensure_resource([]) }.to raise_error } - it { expect { scope.function_ensure_resource(['type']) }.to raise_error } - end - - describe 'when compared against a resource with no attributes' do - let :catalog do - compile_to_catalog(<<-EOS - user { "dan": } - ensure_resource('user', 'dan', {}) - EOS - ) - end + describe 'after running ensure_resource("user", "username1", {})' do + before { subject.call(['User', 'username1', {}]) } - it 'should contain the the ensured resources' do - expect(catalog.resource(:user, 'dan').to_s).to eq('User[dan]') + # 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 - end - describe 'works when compared against a resource with non-conflicting attributes' do - [ - "ensure_resource('User', 'dan', {})", - "ensure_resource('User', 'dan', '')", - "ensure_resource('User', 'dan', {'ensure' => 'present'})", - "ensure_resource('User', 'dan', {'ensure' => 'present', 'managehome' => false})" - ].each do |ensure_resource| - pp = <<-EOS - user { "dan": ensure => present, shell => "/bin/csh", managehome => false} - #{ensure_resource} - EOS + describe 'after running ensure_resource("user", "username2", {})' do + before { subject.call(['User', 'username2', {}]) } - it { expect { compile_to_catalog(pp) }.to_not raise_error } + # 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 - end - - describe 'fails when compared against a resource with conflicting attributes' do - pp = <<-EOS - user { "dan": ensure => present, shell => "/bin/csh", managehome => false} - ensure_resource('User', 'dan', {'ensure' => 'absent', 'managehome' => false}) - EOS - - it { expect { compile_to_catalog(pp) }.to raise_error } - end - describe 'when an array of new resources are passed in' do - let :catalog do - compile_to_catalog("ensure_resource('User', ['dan', 'alex'], {})") - end + describe 'after running ensure_resource("user", ["username1", "username2"], {})' do + before { subject.call(['User', ['username1', 'username2'], {}]) } - it 'should contain the ensured resources' do - expect(catalog.resource('User[dan]').to_s).to eq('User[dan]') - expect(catalog.resource('User[alex]').to_s).to eq('User[alex]') + # 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 - end - describe 'when an array of existing resources is compared against existing resources' do - pp = <<-EOS - user { 'dan': ensure => present; 'alex': ensure => present } - ensure_resource('User', ['dan', 'alex'], {}) - EOS + describe 'when providing already set params' do + let(:params) { { 'ensure' => 'present' } } + before { subject.call(['User', ['username2', 'username3'], params]) } - let :catalog do - compile_to_catalog(pp) + # 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 - it 'should return the existing resources' do - expect(catalog.resource('User[dan]').to_s).to eq('User[dan]') - expect(catalog.resource('User[alex]').to_s).to eq('User[alex]') - end - end - - describe 'works when compared against existing resources with attributes' do - [ - "ensure_resource('User', ['dan', 'alex'], {})", - "ensure_resource('User', ['dan', 'alex'], '')", - "ensure_resource('User', ['dan', 'alex'], {'ensure' => 'present'})", - ].each do |ensure_resource| - pp = <<-EOS - user { 'dan': ensure => present; 'alex': ensure => present } - #{ensure_resource} - EOS - - it { expect { compile_to_catalog(pp) }.to_not raise_error } + 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 - - describe 'fails when compared against existing resources with conflicting attributes' do - pp = <<-EOS - user { 'dan': ensure => present; 'alex': ensure => present } - ensure_resource('User', ['dan', 'alex'], {'ensure' => 'absent'}) - EOS - - it { expect { compile_to_catalog(pp) }.to raise_error } - end - end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/flatten_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/flatten_spec.rb index de8c66d..a4338be 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/flatten_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/flatten_spec.rb @@ -1,27 +1,14 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the flatten function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - it "should exist" do - expect(Puppet::Parser::Functions.function("flatten")).to eq("function_flatten") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_flatten([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should raise a ParseError if there is more than 1 argument" do - expect { scope.function_flatten([[], []]) }.to( raise_error(Puppet::ParseError)) - end - - it "should flatten a complex data structure" do - result = scope.function_flatten([["a","b",["c",["d","e"],"f","g"]]]) - expect(result).to(eq(["a","b","c","d","e","f","g"])) - end - - it "should do nothing to a structure that is already flat" do - result = scope.function_flatten([["a","b","c","d"]]) - expect(result).to(eq(["a","b","c","d"])) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/floor_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/floor_spec.rb index 12a6917..608c602 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/floor_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/floor_spec.rb @@ -1,39 +1,12 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe "the floor function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("floor")).to eq("function_floor") - end - - it "should raise a ParseError if there is less than 1 argument" do - expect { scope.function_floor([]) }.to( raise_error(Puppet::ParseError, /Wrong number of arguments/)) - end - - it "should should raise a ParseError if input isn't numeric (eg. String)" do - expect { scope.function_floor(["foo"]) }.to( raise_error(Puppet::ParseError, /Wrong argument type/)) - end - - it "should should raise a ParseError if input isn't numeric (eg. Boolean)" do - expect { scope.function_floor([true]) }.to( raise_error(Puppet::ParseError, /Wrong argument type/)) - end - - it "should return an integer when a numeric type is passed" do - result = scope.function_floor([12.4]) - expect(result.is_a?(Integer)).to(eq(true)) - end - - it "should return the input when an integer is passed" do - result = scope.function_floor([7]) - expect(result).to(eq(7)) - end - - it "should return the largest integer less than or equal to the input" do - result = scope.function_floor([3.8]) - expect(result).to(eq(3)) - end +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 - diff --git a/puphpet/puppet/modules/stdlib/spec/functions/fqdn_rand_string_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/fqdn_rand_string_spec.rb new file mode 100644 index 0000000..e407084 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/fqdn_rand_string_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/fqdn_rotate_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/fqdn_rotate_spec.rb index 673a8a3..db7a717 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/fqdn_rotate_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/fqdn_rotate_spec.rb @@ -1,60 +1,75 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the fqdn_rotate function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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 "should exist" do - expect(Puppet::Parser::Functions.function("fqdn_rotate")).to eq("function_fqdn_rotate") + 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 raise a ParseError if there is less than 1 arguments" do - expect { scope.function_fqdn_rotate([]) }.to( raise_error(Puppet::ParseError)) + 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 "should rotate a string and the result should be the same size" do - scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") - result = scope.function_fqdn_rotate(["asdf"]) - expect(result.size).to(eq(4)) + 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 "should rotate a string to give the same results for one host" do - scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1").twice - expect(scope.function_fqdn_rotate(["abcdefg"])).to eql(scope.function_fqdn_rotate(["abcdefg"])) + 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 - scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") - val1 = scope.function_fqdn_rotate(["abcdefghijklmnopqrstuvwxyz01234567890987654321"]) - scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.2") - val2 = scope.function_fqdn_rotate(["abcdefghijklmnopqrstuvwxyz01234567890987654321"]) - expect(val1).not_to eql(val2) + 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 - class AlsoString < String - end - - scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") - value = AlsoString.new("asdf") - result = scope.function_fqdn_rotate([value]) - result.size.should(eq(4)) + result = fqdn_rotate(AlsoString.new('asdf')) + expect(result).to eq('dfas') end - it "should use the Puppet::Util.deterministic_rand function if available" do - scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1") + it "should use the Puppet::Util.deterministic_rand function" do if Puppet::Util.respond_to?(:deterministic_rand) - Puppet::Util.expects(:deterministic_rand).with(113646079810780526294648115052177588845,4) + Puppet::Util.expects(:deterministic_rand).with(44489829212339698569024999901561968770,4) + fqdn_rotate("asdf") + else + skip 'Puppet::Util#deterministic_rand not available' end - scope.function_fqdn_rotate(["asdf"]) end it "should not leave the global seed in a deterministic state" do - scope.expects(:lookupvar).with("::fqdn").returns("127.0.0.1").twice - scope.function_fqdn_rotate(["asdf"]) + fqdn_rotate("asdf") rand1 = rand() - scope.function_fqdn_rotate(["asdf"]) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/get_module_path_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/get_module_path_spec.rb index 38ce645..b1f682f 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/get_module_path_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/get_module_path_spec.rb @@ -1,8 +1,16 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe Puppet::Parser::Functions.function(:get_module_path) do - Internals = PuppetlabsSpec::PuppetInternals +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) @@ -10,37 +18,35 @@ def initialize(path) end end - def scope(environment = "production") - Internals.scope(:compiler => Internals.compiler(:node => Internals.node(:environment => environment))) - end - - it 'should only allow one argument' do - expect { scope.function_get_module_path([]) }.to raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) - expect { scope.function_get_module_path(['1','2','3']) }.to raise_error(Puppet::ParseError, /Wrong number of arguments, expects one/) - end - it 'should raise an exception when the module cannot be found' do - expect { scope.function_get_module_path(['foo']) }.to raise_error(Puppet::ParseError, /Could not find module/) - 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 } - it 'should be able to find module paths from the modulepath setting' do - Puppet::Module.expects(:find).with('foo', 'production').returns(path_of_module_foo) - expect(scope.function_get_module_path(['foo'])).to eq(path_of_module_foo.path) - end - it 'should be able to find module paths when the modulepath is a list' do - Puppet[:modulepath] = modulepath + ":/tmp" - Puppet::Module.expects(:find).with('foo', 'production').returns(path_of_module_foo) - expect(scope.function_get_module_path(['foo'])).to eq(path_of_module_foo.path) + 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 - it 'should respect the environment' do - skip("Disabled on Puppet 2.6.x") if Puppet.version =~ /^2\.6\b/ - Puppet.settings[:environment] = 'danstestenv' - Puppet::Module.expects(:find).with('foo', 'danstestenv').returns(path_of_module_foo) - expect(scope('danstestenv').function_get_module_path(['foo'])).to eq(path_of_module_foo.path) + + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/getparam_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/getparam_spec.rb index 833c4d4..9e3d9e4 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/getparam_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/getparam_spec.rb @@ -1,76 +1,30 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -require 'rspec-puppet' -require 'puppet_spec/compiler' describe 'getparam' do - include PuppetSpec::Compiler - - before :each do - Puppet::Parser::Functions.autoloader.loadall - Puppet::Parser::Functions.function(:getparam) - end - - let :node do Puppet::Node.new('localhost') end - let :compiler do Puppet::Parser::Compiler.new(node) end - if Puppet.version.to_f >= 3.0 - let :scope do Puppet::Parser::Scope.new(compiler) end - else - let :scope do - newscope = Puppet::Parser::Scope.new - newscope.compiler = compiler - newscope.source = Puppet::Resource::Type.new(:node, :localhost) - newscope - end + 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 - it "should exist" do - expect(Puppet::Parser::Functions.function("getparam")).to eq("function_getparam") - end - - describe 'when a resource is not specified' do - it { expect { scope.function_getparam([]) }.to raise_error } - it { expect { scope.function_getparam(['User[dan]']) }.to raise_error } - it { expect { scope.function_getparam(['User[dan]']) }.to raise_error } - it { expect { scope.function_getparam(['User[dan]', {}]) }.to raise_error } - # This seems to be OK because we just check for a string. - it { expect { scope.function_getparam(['User[dan]', '']) }.to_not raise_error } - end - - describe 'when compared against a resource with no params' do - let :catalog do - compile_to_catalog(<<-EOS - user { "dan": } - EOS - ) - end - - it do - expect(scope.function_getparam(['User[dan]', 'shell'])).to eq('') - end - end - - describe 'when compared against a resource with params' do - let :catalog do - compile_to_catalog(<<-EOS - user { 'dan': ensure => present, shell => '/bin/sh', managehome => false} - $test = getparam(User[dan], 'shell') - EOS - ) - end - - it do - resource = Puppet::Parser::Resource.new(:user, 'dan', {:scope => scope}) - resource.set_parameter('ensure', 'present') - resource.set_parameter('shell', '/bin/sh') - resource.set_parameter('managehome', false) - compiler.add_resource(scope, resource) + describe 'when compared against a user resource with params' do + let(:pre_condition) { 'user { "one": ensure => present, shell => "/bin/sh", managehome => false, }' } - expect(scope.function_getparam(['User[dan]', 'shell'])).to eq('/bin/sh') - expect(scope.function_getparam(['User[dan]', ''])).to eq('') - expect(scope.function_getparam(['User[dan]', 'ensure'])).to eq('present') - # TODO: Expected this to be false, figure out why we're getting '' back. - expect(scope.function_getparam(['User[dan]', 'managehome'])).to eq('') - end + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/getvar_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/getvar_spec.rb index 87ab9b5..6ab137e 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/getvar_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/getvar_spec.rb @@ -1,37 +1,21 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe Puppet::Parser::Functions.function(:getvar) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - describe 'when calling getvar from puppet' do +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) } - 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] = '$foo = getvar()' - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /wrong number of arguments/) - end - - it "should not compile when too many arguments are passed" do - skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./ - Puppet[:code] = '$foo = getvar("foo::bar", "baz")' - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /wrong number of arguments/) - end - - it "should lookup variables in other namespaces" do - skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./ - Puppet[:code] = <<-'ENDofPUPPETcode' - class site::data { $foo = 'baz' } - include site::data - $foo = getvar("site::data::foo") - if $foo != 'baz' { - fail('getvar did not return what we expect') - } + context 'given variables in namespaces' do + let(:pre_condition) { + <<-'ENDofPUPPETcode' + class site::data { $foo = 'baz' } + include site::data ENDofPUPPETcode - scope.compiler.compile - end + } + + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/grep_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/grep_spec.rb index 9c671dd..6e0bd6e 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/grep_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/grep_spec.rb @@ -1,19 +1,19 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the grep function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("grep")).to eq("function_grep") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_grep([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should grep contents from an array" do - result = scope.function_grep([["aaabbb","bbbccc","dddeee"], "bbb"]) - expect(result).to(eq(["aaabbb","bbbccc"])) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/has_interface_with_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/has_interface_with_spec.rb index 23e09a9..7334d38 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/has_interface_with_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/has_interface_with_spec.rb @@ -1,64 +1,38 @@ -#!/usr/bin/env ruby -S rspec require 'spec_helper' -describe Puppet::Parser::Functions.function(:has_interface_with) do - - let(:scope) do - PuppetlabsSpec::PuppetInternals.scope - end - - # The subject of these examples is the method itself. - subject do - function_name = Puppet::Parser::Functions.function(:has_interface_with) - scope.method(function_name) - end +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 - before :each do - scope.stubs(:lookupvar).with("interfaces").returns('lo0,gif0,stf0,en1,p2p0,fw0,en0,vmnet1,vmnet8,utun0') - end - it 'should have loopback (lo0)' do - expect(subject.call(['lo0'])).to be_truthy - end - it 'should not have loopback (lo)' do - expect(subject.call(['lo'])).to be_falsey - end + 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 - before :each do - scope.stubs(:lookupvar).with("interfaces").returns('eth0,lo') - scope.stubs(:lookupvar).with("ipaddress").returns('10.0.0.1') - scope.stubs(:lookupvar).with("ipaddress_lo").returns('127.0.0.1') - scope.stubs(:lookupvar).with("ipaddress_eth0").returns('10.0.0.1') - scope.stubs(:lookupvar).with('muppet').returns('kermit') - scope.stubs(:lookupvar).with('muppet_lo').returns('mspiggy') - scope.stubs(:lookupvar).with('muppet_eth0').returns('kermit') - end - it 'should have loopback (lo)' do - expect(subject.call(['lo'])).to be_truthy - end - it 'should not have loopback (lo0)' do - expect(subject.call(['lo0'])).to be_falsey - end - it 'should have ipaddress with 127.0.0.1' do - expect(subject.call(['ipaddress', '127.0.0.1'])).to be_truthy - end - it 'should have ipaddress with 10.0.0.1' do - expect(subject.call(['ipaddress', '10.0.0.1'])).to be_truthy - end - it 'should not have ipaddress with 10.0.0.2' do - expect(subject.call(['ipaddress', '10.0.0.2'])).to be_falsey - end - it 'should have muppet named kermit' do - expect(subject.call(['muppet', 'kermit'])).to be_truthy - end - it 'should have muppet named mspiggy' do - expect(subject.call(['muppet', 'mspiggy'])).to be_truthy - end - it 'should not have muppet named bigbird' do - expect(subject.call(['muppet', 'bigbird'])).to be_falsey + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/has_ip_address_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/has_ip_address_spec.rb index 0df12a7..42a5a79 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/has_ip_address_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/has_ip_address_spec.rb @@ -1,39 +1,22 @@ -#!/usr/bin/env ruby -S rspec require 'spec_helper' -describe Puppet::Parser::Functions.function(:has_ip_address) do - - let(:scope) do - PuppetlabsSpec::PuppetInternals.scope - end - - subject do - function_name = Puppet::Parser::Functions.function(:has_ip_address) - scope.method(function_name) - end +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 - before :each do - scope.stubs(:lookupvar).with('interfaces').returns('eth0,lo') - scope.stubs(:lookupvar).with('ipaddress').returns('10.0.2.15') - scope.stubs(:lookupvar).with('ipaddress_eth0').returns('10.0.2.15') - scope.stubs(:lookupvar).with('ipaddress_lo').returns('127.0.0.1') - end - - it 'should have primary address (10.0.2.15)' do - expect(subject.call(['10.0.2.15'])).to be_truthy + 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 'should have lookupback address (127.0.0.1)' do - expect(subject.call(['127.0.0.1'])).to be_truthy - end - - it 'should not have other address' do - expect(subject.call(['192.1681.1.1'])).to be_falsey - end - - it 'should not have "mspiggy" on an interface' do - expect(subject.call(['mspiggy'])).to be_falsey - 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/has_ip_network_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/has_ip_network_spec.rb index 2a2578e..7b5fe66 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/has_ip_network_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/has_ip_network_spec.rb @@ -1,36 +1,22 @@ -#!/usr/bin/env ruby -S rspec require 'spec_helper' -describe Puppet::Parser::Functions.function(:has_ip_network) do - - let(:scope) do - PuppetlabsSpec::PuppetInternals.scope - end - - subject do - function_name = Puppet::Parser::Functions.function(:has_ip_network) - scope.method(function_name) - end +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 - before :each do - scope.stubs(:lookupvar).with('interfaces').returns('eth0,lo') - scope.stubs(:lookupvar).with('network').returns(:undefined) - scope.stubs(:lookupvar).with('network_eth0').returns('10.0.2.0') - scope.stubs(:lookupvar).with('network_lo').returns('127.0.0.1') - end - - it 'should have primary network (10.0.2.0)' do - expect(subject.call(['10.0.2.0'])).to be_truthy - end - - it 'should have loopback network (127.0.0.0)' do - expect(subject.call(['127.0.0.1'])).to be_truthy + let(:facts) do + { + :interfaces => 'eth0,lo', + :network => :undefined, + :network_lo => '127.0.0.0', + :network_eth0 => '10.0.0.0', + } end - it 'should not have other network' do - expect(subject.call(['192.168.1.0'])).to be_falsey - 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 - diff --git a/puphpet/puppet/modules/stdlib/spec/functions/has_key_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/has_key_spec.rb index 6b71800..965d5a6 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/has_key_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/has_key_spec.rb @@ -1,42 +1,15 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe Puppet::Parser::Functions.function(:has_key) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - describe 'when calling has_key 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 = has_key()' - 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] = "$x = has_key('foo')" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /wrong number of arguments/) - end - - it "should require the first value to be a Hash" do - skip("Fails on 2.6.x, see bug #15912") if Puppet.version =~ /^2\.6\./ - Puppet[:code] = "$x = has_key('foo', 'bar')" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /expects the first argument to be a hash/) - end - end - - describe 'when calling the function has_key from a scope instance' do - it 'should detect existing keys' do - expect(scope.function_has_key([{'one' => 1}, 'one'])).to be_truthy - end - - it 'should detect existing keys' do - expect(scope.function_has_key([{'one' => 1}, 'two'])).to be_falsey - end - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/hash_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/hash_spec.rb index ec2988b..4fe99ce 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/hash_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/hash_spec.rb @@ -1,19 +1,14 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the hash function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("hash")).to eq("function_hash") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_hash([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should convert an array to a hash" do - result = scope.function_hash([['a',1,'b',2,'c',3]]) - expect(result).to(eq({'a'=>1,'b'=>2,'c'=>3})) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/intersection_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/intersection_spec.rb index 6361304..c0f6086 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/intersection_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/intersection_spec.rb @@ -1,19 +1,21 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the intersection function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("intersection")).to eq("function_intersection") - end - - it "should raise a ParseError if there are fewer than 2 arguments" do - expect { scope.function_intersection([]) }.to( raise_error(Puppet::ParseError) ) - end - - it "should return the intersection of two arrays" do - result = scope.function_intersection([["a","b","c"],["b","c","d"]]) - expect(result).to(eq(["b","c"])) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_a_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_a_spec.rb new file mode 100644 index 0000000..8dec13f --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_a_spec.rb @@ -0,0 +1,25 @@ +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' do + it { is_expected.not_to eq(nil) } + end + end +end + +if Puppet.version.to_f >= 4.0 + describe 'is_a' 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 'succeeds when comparing a string and a string' do + is_expected.to run.with_params('hello world', String).and_return(true) + end + + it 'fails when comparing an integer and a string' do + is_expected.to run.with_params(5, String).and_return(false) + end + end +end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_array_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_array_spec.rb index 94920a4..7dd21c2 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/is_array_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_array_spec.rb @@ -1,29 +1,19 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the is_array function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("is_array")).to eq("function_is_array") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_is_array([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return true if passed an array" do - result = scope.function_is_array([[1,2,3]]) - expect(result).to(eq(true)) - end - - it "should return false if passed a hash" do - result = scope.function_is_array([{'a'=>1}]) - expect(result).to(eq(false)) - end - - it "should return false if passed a string" do - result = scope.function_is_array(["asdf"]) - expect(result).to(eq(false)) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_bool_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_bool_spec.rb index 4a342ba..76d619b 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/is_bool_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_bool_spec.rb @@ -1,44 +1,15 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the is_bool function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("is_bool")).to eq("function_is_bool") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_is_bool([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return true if passed a TrueClass" do - result = scope.function_is_bool([true]) - expect(result).to(eq(true)) - end - - it "should return true if passed a FalseClass" do - result = scope.function_is_bool([false]) - expect(result).to(eq(true)) - end - - it "should return false if passed the string 'true'" do - result = scope.function_is_bool(['true']) - expect(result).to(eq(false)) - end - - it "should return false if passed the string 'false'" do - result = scope.function_is_bool(['false']) - expect(result).to(eq(false)) - end - - it "should return false if passed an array" do - result = scope.function_is_bool([["a","b"]]) - expect(result).to(eq(false)) - end - - it "should return false if passed a hash" do - result = scope.function_is_bool([{"a" => "b"}]) - expect(result).to(eq(false)) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_domain_name_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_domain_name_spec.rb index ef88061..c1bf0e3 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/is_domain_name_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_domain_name_spec.rb @@ -1,81 +1,43 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the is_domain_name function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("is_domain_name")).to eq("function_is_domain_name") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_is_domain_name([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return true if a valid short domain name" do - result = scope.function_is_domain_name(["x.com"]) - expect(result).to(be_truthy) - end - - it "should return true if the domain is ." do - result = scope.function_is_domain_name(["."]) - expect(result).to(be_truthy) +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 - - it "should return true if the domain is x.com." do - result = scope.function_is_domain_name(["x.com."]) - expect(result).to(be_truthy) - end - - it "should return true if a valid domain name" do - result = scope.function_is_domain_name(["foo.bar.com"]) - expect(result).to(be_truthy) - end - - it "should allow domain parts to start with numbers" do - result = scope.function_is_domain_name(["3foo.2bar.com"]) - expect(result).to(be_truthy) - end - - it "should allow domain to end with a dot" do - result = scope.function_is_domain_name(["3foo.2bar.com."]) - expect(result).to(be_truthy) - end - - it "should allow a single part domain" do - result = scope.function_is_domain_name(["orange"]) - expect(result).to(be_truthy) - end - - it "should return false if domain parts start with hyphens" do - result = scope.function_is_domain_name(["-3foo.2bar.com"]) - expect(result).to(be_falsey) - end - - it "should return true if domain contains hyphens" do - result = scope.function_is_domain_name(["3foo-bar.2bar-fuzz.com"]) - expect(result).to(be_truthy) - end - - it "should return false if domain name contains spaces" do - result = scope.function_is_domain_name(["not valid"]) - expect(result).to(be_falsey) - end - # Values obtained from Facter values will be frozen strings # in newer versions of Facter: - it "should not throw an exception if passed a frozen string" do - result = scope.function_is_domain_name(["my.domain.name".freeze]) - expect(result).to(be_truthy) + 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 - - it "should return false if top-level domain is not entirely alphabetic" do - result = scope.function_is_domain_name(["kiwi.2bar"]) - expect(result).to(be_falsey) - end - - it "should return false if domain name has the dotted-decimal form, e.g. an IPv4 address" do - result = scope.function_is_domain_name(["192.168.1.1"]) - expect(result).to(be_falsey) + describe 'IP addresses are not domain names' do + it { is_expected.to run.with_params('192.168.1.1').and_return(false) } end end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_float_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_float_spec.rb index d926634..ffff971 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/is_float_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_float_spec.rb @@ -1,33 +1,22 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the is_float function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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) } - it "should exist" do - expect(Puppet::Parser::Functions.function("is_float")).to eq("function_is_float") + 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 - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_is_float([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return true if a float" do - result = scope.function_is_float(["0.12"]) - expect(result).to(eq(true)) - end - - it "should return false if a string" do - result = scope.function_is_float(["asdf"]) - expect(result).to(eq(false)) - end - - it "should return false if an integer" do - result = scope.function_is_float(["3"]) - expect(result).to(eq(false)) - end - it "should return true if a float is created from an arithmetical operation" do - result = scope.function_is_float([3.2*2]) - expect(result).to(eq(true)) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_function_available.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_function_available.rb index 3a9aa1b..44f08c0 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/is_function_available.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_function_available.rb @@ -1,31 +1,9 @@ -#!/usr/bin/env ruby -S rspec require 'spec_helper' -describe "the is_function_available function" do - before :all do - Puppet::Parser::Functions.autoloader.loadall - end - - before :each do - @scope = Puppet::Parser::Scope.new - end - - it "should exist" do - expect(Puppet::Parser::Functions.function("is_function_available")).to eq("function_is_function_available") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { @scope.function_is_function_available([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return false if a nonexistent function is passed" do - result = @scope.function_is_function_available(['jeff_mccunes_left_sock']) - expect(result).to(eq(false)) - end - - it "should return true if an available function is passed" do - result = @scope.function_is_function_available(['require']) - expect(result).to(eq(true)) - end - +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_hash_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_hash_spec.rb index a849411..c2599a0 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/is_hash_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_hash_spec.rb @@ -1,29 +1,11 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the is_hash function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("is_hash")).to eq("function_is_hash") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_is_hash([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return true if passed a hash" do - result = scope.function_is_hash([{"a"=>1,"b"=>2}]) - expect(result).to(eq(true)) - end - - it "should return false if passed an array" do - result = scope.function_is_hash([["a","b"]]) - expect(result).to(eq(false)) - end - - it "should return false if passed a string" do - result = scope.function_is_hash(["asdf"]) - expect(result).to(eq(false)) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_integer_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_integer_spec.rb index f0cbca8..67263c1 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/is_integer_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_integer_spec.rb @@ -1,69 +1,25 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the is_integer function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("is_integer")).to eq("function_is_integer") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_is_integer([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return true if an integer" do - result = scope.function_is_integer(["3"]) - expect(result).to(eq(true)) - end - - it "should return true if a negative integer" do - result = scope.function_is_integer(["-7"]) - expect(result).to(eq(true)) - end - - it "should return false if a float" do - result = scope.function_is_integer(["3.2"]) - expect(result).to(eq(false)) - end - - it "should return false if a string" do - result = scope.function_is_integer(["asdf"]) - expect(result).to(eq(false)) - end - - it "should return true if an integer is created from an arithmetical operation" do - result = scope.function_is_integer([3*2]) - expect(result).to(eq(true)) - end - - it "should return false if an array" do - result = scope.function_is_numeric([["asdf"]]) - expect(result).to(eq(false)) - end - - it "should return false if a hash" do - result = scope.function_is_numeric([{"asdf" => false}]) - expect(result).to(eq(false)) - end - - it "should return false if a boolean" do - result = scope.function_is_numeric([true]) - expect(result).to(eq(false)) - end - - it "should return false if a whitespace is in the string" do - result = scope.function_is_numeric([" -1324"]) - expect(result).to(eq(false)) - end - - it "should return false if it is zero prefixed" do - result = scope.function_is_numeric(["0001234"]) - expect(result).to(eq(false)) - end - - it "should return false if it is wrapped inside an array" do - result = scope.function_is_numeric([[1234]]) - expect(result).to(eq(false)) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_ip_address_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_ip_address_spec.rb index c16d12b..a7a383a 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/is_ip_address_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_ip_address_spec.rb @@ -1,39 +1,23 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the is_ip_address function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("is_ip_address")).to eq("function_is_ip_address") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_is_ip_address([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return true if an IPv4 address" do - result = scope.function_is_ip_address(["1.2.3.4"]) - expect(result).to(eq(true)) - end - - it "should return true if a full IPv6 address" do - result = scope.function_is_ip_address(["fe80:0000:cd12:d123:e2f8:47ff:fe09:dd74"]) - expect(result).to(eq(true)) - end - - it "should return true if a compressed IPv6 address" do - result = scope.function_is_ip_address(["fe00::1"]) - expect(result).to(eq(true)) - end - - it "should return false if not valid" do - result = scope.function_is_ip_address(["asdf"]) - expect(result).to(eq(false)) - end - - it "should return false if IP octets out of range" do - result = scope.function_is_ip_address(["1.1.1.300"]) - expect(result).to(eq(false)) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_mac_address_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_mac_address_spec.rb index 66edd19..5f76a91 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/is_mac_address_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_mac_address_spec.rb @@ -1,29 +1,24 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the is_mac_address function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("is_mac_address")).to eq("function_is_mac_address") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_is_mac_address([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return true if a valid mac address" do - result = scope.function_is_mac_address(["00:a0:1f:12:7f:a0"]) - expect(result).to(eq(true)) - end - - it "should return false if octets are out of range" do - result = scope.function_is_mac_address(["00:a0:1f:12:7f:g0"]) - expect(result).to(eq(false)) - end - - it "should return false if not valid" do - result = scope.function_is_mac_address(["not valid"]) - expect(result).to(eq(false)) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_numeric_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_numeric_spec.rb index 4176961..d0f5a6e 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/is_numeric_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_numeric_spec.rb @@ -1,119 +1,28 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the is_numeric function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("is_numeric")).to eq("function_is_numeric") - end - - it "should raise a ParseError if there is less than 1 argument" do - expect { scope.function_is_numeric([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return true if an integer" do - result = scope.function_is_numeric(["3"]) - expect(result).to(eq(true)) - end - - it "should return true if a float" do - result = scope.function_is_numeric(["3.2"]) - expect(result).to(eq(true)) - end - - it "should return true if an integer is created from an arithmetical operation" do - result = scope.function_is_numeric([3*2]) - expect(result).to(eq(true)) - end - - it "should return true if a float is created from an arithmetical operation" do - result = scope.function_is_numeric([3.2*2]) - expect(result).to(eq(true)) - end - - it "should return false if a string" do - result = scope.function_is_numeric(["asdf"]) - expect(result).to(eq(false)) - end - - it "should return false if an array" do - result = scope.function_is_numeric([["asdf"]]) - expect(result).to(eq(false)) - end - - it "should return false if an array of integers" do - result = scope.function_is_numeric([[1,2,3,4]]) - expect(result).to(eq(false)) - end - - it "should return false if a hash" do - result = scope.function_is_numeric([{"asdf" => false}]) - expect(result).to(eq(false)) - end - - it "should return false if a hash with numbers in it" do - result = scope.function_is_numeric([{1 => 2}]) - expect(result).to(eq(false)) - end - - it "should return false if a boolean" do - result = scope.function_is_numeric([true]) - expect(result).to(eq(false)) - end - - it "should return true if a negative float with exponent" do - result = scope.function_is_numeric(["-342.2315e-12"]) - expect(result).to(eq(true)) - end - - it "should return false if a negative integer with whitespaces before/after the dash" do - result = scope.function_is_numeric([" - 751"]) - expect(result).to(eq(false)) - end - -# it "should return true if a hexadecimal" do -# result = scope.function_is_numeric(["0x52F8c"]) -# result.should(eq(true)) -# end -# -# it "should return true if a hexadecimal with uppercase 0X prefix" do -# result = scope.function_is_numeric(["0X52F8c"]) -# result.should(eq(true)) -# end -# -# it "should return false if a hexadecimal without a prefix" do -# result = scope.function_is_numeric(["52F8c"]) -# result.should(eq(false)) -# end -# -# it "should return true if a octal" do -# result = scope.function_is_numeric(["0751"]) -# result.should(eq(true)) -# end -# -# it "should return true if a negative hexadecimal" do -# result = scope.function_is_numeric(["-0x52F8c"]) -# result.should(eq(true)) -# end -# -# it "should return true if a negative octal" do -# result = scope.function_is_numeric(["-0751"]) -# result.should(eq(true)) -# end -# -# it "should return false if a negative octal with whitespaces before/after the dash" do -# result = scope.function_is_numeric([" - 0751"]) -# result.should(eq(false)) -# end -# -# it "should return false if a bad hexadecimal" do -# result = scope.function_is_numeric(["0x23d7g"]) -# result.should(eq(false)) -# end -# -# it "should return false if a bad octal" do -# result = scope.function_is_numeric(["0287"]) -# result.should(eq(false)) -# end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/is_string_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/is_string_spec.rb index 6a0801a..8e459cc 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/is_string_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/is_string_spec.rb @@ -1,34 +1,28 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the is_string function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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 "should exist" do - expect(Puppet::Parser::Functions.function("is_string")).to eq("function_is_string") - end + 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 "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_is_string([]) }.to( raise_error(Puppet::ParseError)) - end + 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 "should return true if a string" do - result = scope.function_is_string(["asdf"]) - expect(result).to(eq(true)) - end - - it "should return false if an integer" do - result = scope.function_is_string(["3"]) - expect(result).to(eq(false)) - end - - it "should return false if a float" do - result = scope.function_is_string(["3.23"]) - expect(result).to(eq(false)) - end - - it "should return false if an array" do - result = scope.function_is_string([["a","b","c"]]) - expect(result).to(eq(false)) - end + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/join_keys_to_values_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/join_keys_to_values_spec.rb index 4a9ae87..6c109d1 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/join_keys_to_values_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/join_keys_to_values_spec.rb @@ -1,40 +1,19 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the join_keys_to_values function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("join_keys_to_values")).to eq("function_join_keys_to_values") - end - - it "should raise a ParseError if there are fewer than two arguments" do - expect { scope.function_join_keys_to_values([{}]) }.to raise_error Puppet::ParseError - end - - it "should raise a ParseError if there are greater than two arguments" do - expect { scope.function_join_keys_to_values([{}, 'foo', 'bar']) }.to raise_error Puppet::ParseError - end - - it "should raise a TypeError if the first argument is an array" do - expect { scope.function_join_keys_to_values([[1,2], ',']) }.to raise_error TypeError - end - - it "should raise a TypeError if the second argument is an array" do - expect { scope.function_join_keys_to_values([{}, [1,2]]) }.to raise_error TypeError - end - - it "should raise a TypeError if the second argument is a number" do - expect { scope.function_join_keys_to_values([{}, 1]) }.to raise_error TypeError - end - - it "should return an empty array given an empty hash" do - result = scope.function_join_keys_to_values([{}, ":"]) - expect(result).to eq([]) - end - - it "should join hash's keys to its values" do - result = scope.function_join_keys_to_values([{'a'=>1,2=>'foo',:b=>nil}, ":"]) - expect(result).to match_array(['a:1','2:foo','b:']) +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(, ":") 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/join_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/join_spec.rb index 793c36f..a300571 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/join_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/join_spec.rb @@ -1,19 +1,19 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the join function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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 "should exist" do - expect(Puppet::Parser::Functions.function("join")).to eq("function_join") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_join([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should join an array into a string" do - result = scope.function_join([["a","b","c"], ":"]) - expect(result).to(eq("a:b:c")) - end + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/keys_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/keys_spec.rb index f2e7d42..2e009dc 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/keys_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/keys_spec.rb @@ -1,21 +1,19 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the keys function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("keys")).to eq("function_keys") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_keys([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return an array of keys when given a hash" do - result = scope.function_keys([{'a'=>1, 'b'=>2}]) - # =~ performs 'array with same elements' (set) matching - # For more info see RSpec::Matchers::MatchArray - expect(result).to match_array(['a','b']) +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/load_module_metadata_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/load_module_metadata_spec.rb new file mode 100755 index 0000000..fe665fb --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/load_module_metadata_spec.rb @@ -0,0 +1,29 @@ +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", "three").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 + + it "should fail by default if there is no metadata.json" 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(false) + expect {subject.call(['science'])}.to raise_error(Puppet::ParseError) + end + + it "should return nil if user allows empty metadata.json" 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(false) + result = subject.call(['science', true]) + expect(result).to eq({}) + end +end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/loadyaml_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/loadyaml_spec.rb index cdc3d6f..ffc714d 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/loadyaml_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/loadyaml_spec.rb @@ -1,25 +1,24 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the loadyaml function" do - include PuppetlabsSpec::Files - - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("loadyaml")).to eq("function_loadyaml") +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 - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_loadyaml([]) }.to raise_error(Puppet::ParseError) - end - - it "should convert YAML file to a data structure" do - yaml_file = tmpfilename ('yamlfile') - File.open(yaml_file, 'w') do |fh| - fh.write("---\n aaa: 1\n bbb: 2\n ccc: 3\n ddd: 4\n") - end - result = scope.function_loadyaml([yaml_file]) - expect(result).to eq({"aaa" => 1, "bbb" => 2, "ccc" => 3, "ddd" => 4 }) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/lstrip_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/lstrip_spec.rb index 68cca1c..981794e 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/lstrip_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/lstrip_spec.rb @@ -1,28 +1,34 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the lstrip function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("lstrip")).to eq("function_lstrip") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_lstrip([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should lstrip a string" do - result = scope.function_lstrip([" asdf"]) - expect(result).to(eq('asdf')) - end - - it "should accept objects which extend String" do - class AlsoString < String - end - - value = AlsoString.new(" asdf") - result = scope.function_lstrip([value]) - result.should(eq("asdf")) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/max_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/max_spec.rb index c3d8a13..66fb0c8 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/max_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/max_spec.rb @@ -1,27 +1,21 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe "the max function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("max")).to eq("function_max") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_max([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should be able to compare strings" do - expect(scope.function_max(["albatross","dog","horse"])).to(eq("horse")) - end - - it "should be able to compare numbers" do - expect(scope.function_max([6,8,4])).to(eq(8)) - end +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') } - it "should be able to compare a number with a stringified number" do - expect(scope.function_max([1,"2"])).to(eq("2")) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/member_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/member_spec.rb index 1a1d7c6..527f887 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/member_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/member_spec.rb @@ -1,34 +1,21 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the member function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("member")).to eq("function_member") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_member([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return true if a member is in an array" do - result = scope.function_member([["a","b","c"], "a"]) - expect(result).to(eq(true)) - end - - it "should return false if a member is not in an array" do - result = scope.function_member([["a","b","c"], "d"]) - expect(result).to(eq(false)) - end - - it "should return true if a member array is in an array" do - result = scope.function_member([["a","b","c"], ["a", "b"]]) - expect(result).to(eq(true)) - end - - it "should return false if a member array is not in an array" do - result = scope.function_member([["a","b","c"], ["d", "e"]]) - expect(result).to(eq(false)) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/merge_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/merge_spec.rb index 2abf976..7b53363 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/merge_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/merge_spec.rb @@ -1,52 +1,25 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe Puppet::Parser::Functions.function(:merge) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - describe 'when calling merge 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 = merge()' - 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 = merge($my_hash)" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /wrong number of arguments/) - end - end - - describe 'when calling merge on the scope instance' do - it 'should require all parameters are hashes' do - expect { new_hash = scope.function_merge([{}, '2'])}.to raise_error(Puppet::ParseError, /unexpected argument type String/) - expect { new_hash = scope.function_merge([{}, 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_merge([{}, ''])}.not_to raise_error - end - - it 'should be able to merge two hashes' do - new_hash = scope.function_merge([{'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 merge multiple hashes' do - hash = scope.function_merge([{'one' => 1}, {'one' => '2'}, {'one' => '3'}]) - expect(hash['one']).to eq('3') - end - - it 'should accept empty hashes' do - expect(scope.function_merge([{},{},{}])).to eq({}) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/min_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/min_spec.rb index 35a0890..c840a72 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/min_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/min_spec.rb @@ -1,27 +1,21 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe "the min function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("min")).to eq("function_min") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_min([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should be able to compare strings" do - expect(scope.function_min(["albatross","dog","horse"])).to(eq("albatross")) - end - - it "should be able to compare numbers" do - expect(scope.function_min([6,8,4])).to(eq(4)) - end +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') } - it "should be able to compare a number with a stringified number" do - expect(scope.function_min([1,"2"])).to(eq(1)) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/num2bool_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/num2bool_spec.rb index d0ba935..494afff 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/num2bool_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/num2bool_spec.rb @@ -1,67 +1,22 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the num2bool function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("num2bool")).to eq("function_num2bool") - end - - it "should raise a ParseError if there are no arguments" do - expect { scope.function_num2bool([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should raise a ParseError if there are more than 1 arguments" do - expect { scope.function_num2bool(["foo","bar"]) }.to( raise_error(Puppet::ParseError)) - end - - it "should raise a ParseError if passed something non-numeric" do - expect { scope.function_num2bool(["xyzzy"]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return true if passed string 1" do - result = scope.function_num2bool(["1"]) - expect(result).to(be_truthy) - end - - it "should return true if passed string 1.5" do - result = scope.function_num2bool(["1.5"]) - expect(result).to(be_truthy) - end - - it "should return true if passed number 1" do - result = scope.function_num2bool([1]) - expect(result).to(be_truthy) - end - - it "should return false if passed string 0" do - result = scope.function_num2bool(["0"]) - expect(result).to(be_falsey) - end - - it "should return false if passed number 0" do - result = scope.function_num2bool([0]) - expect(result).to(be_falsey) - end - - it "should return false if passed string -1" do - result = scope.function_num2bool(["-1"]) - expect(result).to(be_falsey) - end - - it "should return false if passed string -1.5" do - result = scope.function_num2bool(["-1.5"]) - expect(result).to(be_falsey) - end - - it "should return false if passed number -1" do - result = scope.function_num2bool([-1]) - expect(result).to(be_falsey) - end - - it "should return false if passed float -1.5" do - result = scope.function_num2bool([-1.5]) - expect(result).to(be_falsey) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/parsejson_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/parsejson_spec.rb index 1dd41b9..a01f1f6 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/parsejson_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/parsejson_spec.rb @@ -1,22 +1,64 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the parsejson function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +describe 'parsejson' do + it 'should exist' do + is_expected.not_to eq(nil) + end - it "should exist" do - expect(Puppet::Parser::Functions.function("parsejson")).to eq("function_parsejson") + it 'should raise an error if called without any arguments' do + is_expected.to run.with_params(). + and_raise_error(/wrong number of arguments/i) end - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_parsejson([]) }.to( raise_error(Puppet::ParseError)) + context 'with correct JSON data' do + + it 'should be able to parse a JSON data with a Hash' do + is_expected.to run.with_params('{"a":"1","b":"2"}'). + and_return({'a'=>'1', 'b'=>'2'}) + end + + it 'should be able to parse a JSON data with an Array' do + is_expected.to run.with_params('["a","b","c"]'). + and_return(['a', 'b', 'c']) + end + + it 'should be able to parse empty JSON values' do + is_expected.to run.with_params('[]'). + and_return([]) + is_expected.to run.with_params('{}'). + and_return({}) + end + + it 'should be able to parse a JSON data with a mixed structure' do + is_expected.to run.with_params('{"a":"1","b":2,"c":{"d":[true,false]}}'). + and_return({'a' =>'1', 'b' => 2, 'c' => { 'd' => [true, false] } }) + end + + it 'should not return the default value if the data was parsed correctly' do + is_expected.to run.with_params('{"a":"1"}', 'default_value'). + and_return({'a' => '1'}) + end + end - it "should convert JSON to a data structure" do - json = <<-EOS -["aaa","bbb","ccc"] -EOS - result = scope.function_parsejson([json]) - expect(result).to(eq(['aaa','bbb','ccc'])) + context 'with incorrect JSON data' do + it 'should raise an error with invalid JSON and no default' do + is_expected.to run.with_params(''). + and_raise_error(PSON::ParserError) + end + + it 'should support a structure for a default value' do + is_expected.to run.with_params('', {'a' => '1'}). + and_return({'a' => '1'}) + end + + ['', 1, 1.2, nil, true, false, [], {}, :yaml].each do |value| + it "should return the default value for an incorrect #{value.inspect} (#{value.class}) parameter" do + is_expected.to run.with_params(value, 'default_value'). + and_return('default_value') + end + end + end + end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/parseyaml_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/parseyaml_spec.rb index e5f145b..fa947ca 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/parseyaml_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/parseyaml_spec.rb @@ -1,24 +1,81 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the parseyaml function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +describe 'parseyaml' do + it 'should exist' do + is_expected.not_to eq(nil) + end - it "should exist" do - expect(Puppet::Parser::Functions.function("parseyaml")).to eq("function_parseyaml") + it 'should raise an error if called without any arguments' do + is_expected.to run.with_params(). + and_raise_error(/wrong number of arguments/i) end - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_parseyaml([]) }.to( raise_error(Puppet::ParseError)) + context 'with correct YAML data' do + it 'should be able to parse a YAML data with a String' do + is_expected.to run.with_params('--- just a string'). + and_return('just a string') + is_expected.to run.with_params('just a string'). + and_return('just a string') + end + + it 'should be able to parse a YAML data with a Hash' do + is_expected.to run.with_params("---\na: '1'\nb: '2'\n"). + and_return({'a' => '1', 'b' => '2'}) + end + + it 'should be able to parse a YAML data with an Array' do + is_expected.to run.with_params("---\n- a\n- b\n- c\n"). + and_return(['a', 'b', 'c']) + end + + it 'should be able to parse a YAML data with a mixed structure' do + is_expected.to run.with_params("---\na: '1'\nb: 2\nc:\n d:\n - :a\n - true\n - false\n"). + and_return({'a' => '1', 'b' => 2, 'c' => {'d' => [:a, true, false]}}) + end + + it 'should not return the default value if the data was parsed correctly' do + is_expected.to run.with_params("---\na: '1'\n", 'default_value'). + and_return({'a' => '1'}) + end + end - it "should convert YAML to a data structure" do - yaml = <<-EOS -- aaa -- bbb -- ccc -EOS - result = scope.function_parseyaml([yaml]) - expect(result).to(eq(['aaa','bbb','ccc'])) + context 'on a modern ruby', :unless => RUBY_VERSION == '1.8.7' do + it 'should raise an error with invalid YAML and no default' do + is_expected.to run.with_params('["one"'). + and_raise_error(Psych::SyntaxError) + end end + + context 'when running on ruby 1.8.7, which does not have Psych', :if => RUBY_VERSION == '1.8.7' do + it 'should raise an error with invalid YAML and no default' do + is_expected.to run.with_params('["one"'). + and_raise_error(ArgumentError) + end + end + + context 'with incorrect YAML data' do + it 'should support a structure for a default value' do + is_expected.to run.with_params('', {'a' => '1'}). + and_return({'a' => '1'}) + end + + [1, 1.2, nil, true, false, [], {}, :yaml].each do |value| + it "should return the default value for an incorrect #{value.inspect} (#{value.class}) parameter" do + is_expected.to run.with_params(value, 'default_value'). + and_return('default_value') + end + end + + context 'when running on modern rubies', :unless => RUBY_VERSION == '1.8.7' do + ['---', '...', '*8', ''].each do |value| + it "should return the default value for an incorrect #{value.inspect} string parameter" do + is_expected.to run.with_params(value, 'default_value'). + and_return('default_value') + end + end + end + + end + end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/pick_default_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/pick_default_spec.rb index db10cc3..e2fc64a 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/pick_default_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/pick_default_spec.rb @@ -1,58 +1,24 @@ -#!/usr/bin/env ruby -S rspec require 'spec_helper' -describe "the pick_default function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("pick_default")).to eq("function_pick_default") - end - - it 'should return the correct value' do - expect(scope.function_pick_default(['first', 'second'])).to eq('first') - end - - it 'should return the correct value if the first value is empty' do - expect(scope.function_pick_default(['', 'second'])).to eq('second') - end - - it 'should skip empty string values' do - expect(scope.function_pick_default(['', 'first'])).to eq('first') - end - - it 'should skip :undef values' do - expect(scope.function_pick_default([:undef, 'first'])).to eq('first') - end - - it 'should skip :undefined values' do - expect(scope.function_pick_default([:undefined, 'first'])).to eq('first') - end - - it 'should return the empty string if it is the last possibility' do - expect(scope.function_pick_default([:undef, :undefined, ''])).to eq('') - end - - it 'should return :undef if it is the last possibility' do - expect(scope.function_pick_default(['', :undefined, :undef])).to eq(:undef) - end - - it 'should return :undefined if it is the last possibility' do - expect(scope.function_pick_default([:undef, '', :undefined])).to eq(:undefined) - end - - it 'should return the empty string if it is the only possibility' do - expect(scope.function_pick_default([''])).to eq('') - end - - it 'should return :undef if it is the only possibility' do - expect(scope.function_pick_default([:undef])).to eq(:undef) - end - - it 'should return :undefined if it is the only possibility' do - expect(scope.function_pick_default([:undefined])).to eq(:undefined) - end - - it 'should error if no values are passed' do - expect { scope.function_pick_default([]) }.to raise_error(Puppet::Error, /Must receive at least one argument./) +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/pick_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/pick_spec.rb index 8be8f58..2c7caa8 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/pick_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/pick_spec.rb @@ -1,34 +1,12 @@ -#!/usr/bin/env ruby -S rspec require 'spec_helper' -describe "the pick function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("pick")).to eq("function_pick") - end - - it 'should return the correct value' do - expect(scope.function_pick(['first', 'second'])).to eq('first') - end - - it 'should return the correct value if the first value is empty' do - expect(scope.function_pick(['', 'second'])).to eq('second') - end - - it 'should remove empty string values' do - expect(scope.function_pick(['', 'first'])).to eq('first') - end - - it 'should remove :undef values' do - expect(scope.function_pick([:undef, 'first'])).to eq('first') - end - - it 'should remove :undefined values' do - expect(scope.function_pick([:undefined, 'first'])).to eq('first') - end - - it 'should error if no values are passed' do - expect { scope.function_pick([]) }.to( raise_error(Puppet::ParseError, "pick(): must receive at least one non empty value")) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/prefix_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/prefix_spec.rb index aec8a7d..3761022 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/prefix_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/prefix_spec.rb @@ -1,33 +1,28 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the prefix function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "raises a ParseError if there is less than 1 arguments" do - expect { scope.function_prefix([]) }.to raise_error(Puppet::ParseError, /number of arguments/) - end - - it "raises an error if the first argument is not an array" do - expect { - scope.function_prefix([Object.new]) - }.to raise_error(Puppet::ParseError, /expected first argument to be an Array/) - end - - - it "raises an error if the second argument is not a string" do - expect { - scope.function_prefix([['first', 'second'], 42]) - }.to raise_error(Puppet::ParseError, /expected second argument to be a String/) - end - - it "returns a prefixed array" do - result = scope.function_prefix([['a','b','c'], 'p']) - expect(result).to(eq(['pa','pb','pc'])) - end - - it "returns a prefixed hash" do - result = scope.function_prefix([{'a' => 'b','b' => 'c','c' => 'd'}, 'p']) - expect(result).to(eq({'pa'=>'b','pb'=>'c','pc'=>'d'})) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/private_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/private_spec.rb index c90282e..a13be64 100644 --- a/puphpet/puppet/modules/stdlib/spec/functions/private_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/private_spec.rb @@ -1,17 +1,13 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe Puppet::Parser::Functions.function(:private) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - subject do - function_name = Puppet::Parser::Functions.function(:private) - scope.method(function_name) - end - +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.") - subject.call [] + begin + subject.call [] + rescue + # ignore this + end end context "when called from inside module" do diff --git a/puphpet/puppet/modules/stdlib/spec/functions/pw_hash_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/pw_hash_spec.rb new file mode 100644 index 0000000..df5348c --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/pw_hash_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/range_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/range_spec.rb index ef86f97..492cad4 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/range_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/range_spec.rb @@ -1,86 +1,118 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the range function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +describe 'range' do + it { is_expected.not_to eq(nil) } - it "exists" do - expect(Puppet::Parser::Functions.function("range")).to eq("function_range") + 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 - it "raises a ParseError if there is less than 1 arguments" do - expect { scope.function_range([]) }.to raise_error Puppet::ParseError, /Wrong number of arguments.*0 for 1/ + 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 - describe 'with a letter range' do - it "returns a letter range" do - result = scope.function_range(["a","d"]) - expect(result).to eq ['a','b','c','d'] - end - - it "returns a letter range given a step of 1" do - result = scope.function_range(["a","d","1"]) - expect(result).to eq ['a','b','c','d'] - end - - it "returns a stepped letter range" do - result = scope.function_range(["a","d","2"]) - expect(result).to eq ['a','c'] - 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 - it "returns a stepped letter range given a negative step" do - result = scope.function_range(["a","d","-2"]) - expect(result).to eq ['a','c'] - 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 - describe 'with a number range' do - it "returns a number range" do - result = scope.function_range(["1","4"]) - expect(result).to eq [1,2,3,4] - 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 - it "returns a number range given a step of 1" do - result = scope.function_range(["1","4","1"]) - expect(result).to eq [1,2,3,4] - 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 - it "returns a stepped number range" do - result = scope.function_range(["1","4","2"]) - expect(result).to eq [1,3] - 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 - it "returns a stepped number range given a negative step" do - result = scope.function_range(["1","4","-2"]) - expect(result).to eq [1,3] - 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 - describe 'with a numeric-like string range' do - it "works with padded hostname like strings" do - expected = ("host01".."host10").to_a - expect(scope.function_range(["host01","host10"])).to eq expected - 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 - it "coerces zero padded digits to integers" do - expected = (0..10).to_a - expect(scope.function_range(["00", "10"])).to eq expected - 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 'with a numeric range' do - it "returns a range of numbers" do - expected = (1..10).to_a - expect(scope.function_range([1,10])).to eq expected - end - it "returns a range of numbers with step parameter" do - expected = (1..10).step(2).to_a - expect(scope.function_range([1,10,2])).to eq expected - end - it "works with mixed numeric like strings and numeric arguments" do - expected = (1..10).to_a - expect(scope.function_range(['1',10])).to eq expected - expect(scope.function_range([1,'10'])).to eq expected - 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/reject_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/reject_spec.rb index 88a992e..4863050 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/reject_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/reject_spec.rb @@ -1,20 +1,19 @@ -#!/usr/bin/env ruby - require 'spec_helper' -describe "the reject function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("reject")).to eq("function_reject") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_reject([]) }.to( raise_error(Puppet::ParseError)) - end +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 "should reject contents from an array" do - result = scope.function_reject([["1111", "aaabbb","bbbccc","dddeee"], "bbb"]) - expect(result).to(eq(["1111", "dddeee"])) - end + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/reverse_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/reverse_spec.rb index 1f04794..e00dee9 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/reverse_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/reverse_spec.rb @@ -1,28 +1,31 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the reverse function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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 "should exist" do - expect(Puppet::Parser::Functions.function("reverse")).to eq("function_reverse") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_reverse([]) }.to( raise_error(Puppet::ParseError)) - end + 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') } - it "should reverse a string" do - result = scope.function_reverse(["asdfghijkl"]) - expect(result).to(eq('lkjihgfdsa')) - end - - it "should accept objects which extend String" do - class AlsoString < String + 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 - - value = AlsoString.new('asdfghjkl') - result = scope.function_reverse([value]) - result.should(eq('lkjhgfdsa')) end end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/rstrip_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/rstrip_spec.rb index f6b4838..d2efac8 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/rstrip_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/rstrip_spec.rb @@ -1,33 +1,34 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the rstrip function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("rstrip")).to eq("function_rstrip") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_rstrip([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should rstrip a string" do - result = scope.function_rstrip(["asdf "]) - expect(result).to(eq('asdf')) - end - - it "should rstrip each element in an array" do - result = scope.function_rstrip([["a ","b ", "c "]]) - expect(result).to(eq(['a','b','c'])) - end - - it "should accept objects which extend String" do - class AlsoString < String - end - - value = AlsoString.new('asdf ') - result = scope.function_rstrip([value]) - result.should(eq('asdf')) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/seeded_rand_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/seeded_rand_spec.rb new file mode 100644 index 0000000..38e134e --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/seeded_rand_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +describe 'seeded_rand' do + 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(1).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 a string/) } + it { is_expected.to run.with_params(1, []).and_raise_error(ArgumentError, /second argument must be a string/) } + it { is_expected.to run.with_params(1, {}).and_raise_error(ArgumentError, /second argument must be a string/) } + + it "provides a random number strictly less than the given max" do + expect(seeded_rand(3, 'seed')).to satisfy {|n| n.to_i < 3 } + end + + it "provides a random number greater or equal to zero" do + expect(seeded_rand(3, 'seed')).to satisfy {|n| n.to_i >= 0 } + end + + it "provides the same 'random' value on subsequent calls for the same host" do + expect(seeded_rand(10, 'seed')).to eql(seeded_rand(10, 'seed')) + end + + it "allows seed to control the random value on a single host" do + first_random = seeded_rand(1000, 'seed1') + second_different_random = seeded_rand(1000, 'seed2') + + expect(first_random).not_to eql(second_different_random) + end + + it "should not return different values for different hosts" do + val1 = seeded_rand(1000, 'foo', :host => "first.host.com") + val2 = seeded_rand(1000, 'foo', :host => "second.host.com") + + expect(val1).to eql(val2) + end + + def seeded_rand(max, seed, args = {}) + host = args[:host] || '127.0.0.1' + + # 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) + + scope.function_seeded_rand([max, seed]) + end +end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/shuffle_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/shuffle_spec.rb index a62c1fb..ebc3a73 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/shuffle_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/shuffle_spec.rb @@ -1,33 +1,33 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the shuffle function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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/) } - it "should exist" do - expect(Puppet::Parser::Functions.function("shuffle")).to eq("function_shuffle") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_shuffle([]) }.to( raise_error(Puppet::ParseError)) - end + context 'when running with a specific seed' do + # make tests deterministic + before(:each) { srand(2) } - it "should shuffle a string and the result should be the same size" do - result = scope.function_shuffle(["asdf"]) - expect(result.size).to(eq(4)) - end + 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 "should shuffle a string but the sorted contents should still be the same" do - result = scope.function_shuffle(["adfs"]) - expect(result.split("").sort.join("")).to(eq("adfs")) - end + 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') } - it "should accept objects which extend String" do - class AlsoString < String + context 'when using a class extending String' do + it { is_expected.to run.with_params(AlsoString.new('asdfghjkl')).and_return('lkhdsfajg') } end - - value = AlsoString.new('asdf') - result = scope.function_shuffle([value]) - result.size.should(eq(4)) end end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/size_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/size_spec.rb index 18eb48f..c0047ee 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/size_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/size_spec.rb @@ -1,24 +1,35 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the size function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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 "should exist" do - expect(Puppet::Parser::Functions.function("size")).to eq("function_size") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_size([]) }.to( raise_error(Puppet::ParseError)) - end + 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 "should return the size of a string" do - result = scope.function_size(["asdf"]) - expect(result).to(eq(4)) - end + 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) } - it "should return the size of an array" do - result = scope.function_size([["a","b","c"]]) - expect(result).to(eq(3)) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/sort_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/sort_spec.rb index 4c2a66c..9abd039 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/sort_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/sort_spec.rb @@ -1,24 +1,24 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the sort function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("sort")).to eq("function_sort") - end - - it "should raise a ParseError if there is not 1 arguments" do - expect { scope.function_sort(['','']) }.to( raise_error(Puppet::ParseError)) +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 - it "should sort an array" do - result = scope.function_sort([["a","c","b"]]) - expect(result).to(eq(['a','b','c'])) + 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 - it "should sort a string" do - result = scope.function_sort(["acb"]) - expect(result).to(eq('abc')) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/squeeze_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/squeeze_spec.rb index cd0eb37..7f09c30 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/squeeze_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/squeeze_spec.rb @@ -1,24 +1,44 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the squeeze function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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) } - it "should exist" do - expect(Puppet::Parser::Functions.function("squeeze")).to eq("function_squeeze") + 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 - it "should raise a ParseError if there is less than 2 arguments" do - expect { scope.function_squeeze([]) }.to( raise_error(Puppet::ParseError)) + 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 - it "should squeeze a string" do - result = scope.function_squeeze(["aaabbbbcccc"]) - expect(result).to(eq('abc')) - end - - it "should squeeze all elements in an array" do - result = scope.function_squeeze([["aaabbbbcccc","dddfff"]]) - expect(result).to(eq(['abc','df'])) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/str2bool_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/str2bool_spec.rb index 1d205d7..7d8c47c 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/str2bool_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/str2bool_spec.rb @@ -1,31 +1,23 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the str2bool function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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/) } - it "should exist" do - expect(Puppet::Parser::Functions.function("str2bool")).to eq("function_str2bool") + describe 'when testing values that mean "true"' do + [ 'TRUE','1', 't', 'y', 'true', 'yes', true ].each do |value| + it { is_expected.to run.with_params(value).and_return(true) } + end end - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_str2bool([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should convert string 'true' to true" do - result = scope.function_str2bool(["true"]) - expect(result).to(eq(true)) - end - - it "should convert string 'undef' to false" do - result = scope.function_str2bool(["undef"]) - expect(result).to(eq(false)) - end - - it "should return the boolean it was called with" do - result = scope.function_str2bool([true]) - expect(result).to(eq(true)) - result = scope.function_str2bool([false]) - expect(result).to(eq(false)) + describe 'when testing values that mean "false"' do + [ 'FALSE','', '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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/str2saltedsha512_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/str2saltedsha512_spec.rb index ab7f57f..2e1e818 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/str2saltedsha512_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/str2saltedsha512_spec.rb @@ -1,45 +1,17 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the str2saltedsha512 function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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/) } - it "should exist" do - expect(Puppet::Parser::Functions.function("str2saltedsha512")).to eq("function_str2saltedsha512") - end - - it "should raise a ParseError if there is less than 1 argument" do - expect { scope.function_str2saltedsha512([]) }.to( raise_error(Puppet::ParseError) ) - end - - it "should raise a ParseError if there is more than 1 argument" do - expect { scope.function_str2saltedsha512(['foo', 'bar', 'baz']) }.to( raise_error(Puppet::ParseError) ) - end - - it "should return a salted-sha512 password hash 136 characters in length" do - result = scope.function_str2saltedsha512(["password"]) - expect(result.length).to(eq(136)) - end - - it "should raise an error if you pass a non-string password" do - expect { scope.function_str2saltedsha512([1234]) }.to( raise_error(Puppet::ParseError) ) - end - - it "should generate a valid password" do - # Allow the function to generate a password based on the string 'password' - password_hash = scope.function_str2saltedsha512(["password"]) - - # Separate the Salt and Password from the Password Hash - salt = password_hash[0..7] - password = password_hash[8..-1] - - # Convert the Salt and Password from Hex to Binary Data - str_salt = Array(salt.lines).pack('H*') - str_password = Array(password.lines).pack('H*') + context 'when running with a specific seed' do + # make tests deterministic + before(:each) { srand(2) } - # Combine the Binary Salt with 'password' and compare the end result - saltedpass = Digest::SHA512.digest(str_salt + 'password') - result = (str_salt + saltedpass).unpack('H*')[0] - expect(result).to eq(password_hash) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/strftime_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/strftime_spec.rb index ebec54b..e76774a 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/strftime_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/strftime_spec.rb @@ -1,9 +1,6 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the strftime function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - +describe 'strftime' do it "should exist" do expect(Puppet::Parser::Functions.function("strftime")).to eq("function_strftime") end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/strip_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/strip_spec.rb index 4ac8daf..689b6dd 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/strip_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/strip_spec.rb @@ -1,27 +1,34 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the strip function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - it "should exist" do - expect(Puppet::Parser::Functions.function("strip")).to eq("function_strip") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_strip([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should strip a string" do - result = scope.function_strip([" ab cd "]) - expect(result).to(eq('ab cd')) - end - - it "should accept objects which extend String" do - class AlsoString < String - end - - value = AlsoString.new(' as df ') - result = scope.function_strip([value]) - result.should(eq('as df')) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/suffix_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/suffix_spec.rb index c7783c6..b48a4eb 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/suffix_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/suffix_spec.rb @@ -1,27 +1,44 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the suffix function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "raises a ParseError if there is less than 1 arguments" do - expect { scope.function_suffix([]) }.to raise_error(Puppet::ParseError, /number of arguments/) - end - - it "raises an error if the first argument is not an array" do - expect { - scope.function_suffix([Object.new]) - }.to raise_error(Puppet::ParseError, /expected first argument to be an Array/) - end - - it "raises an error if the second argument is not a string" do - expect { - scope.function_suffix([['first', 'second'], 42]) - }.to raise_error(Puppet::ParseError, /expected second argument to be a String/) - end - - it "returns a suffixed array" do - result = scope.function_suffix([['a','b','c'], 'p']) - expect(result).to(eq(['ap','bp','cp'])) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/swapcase_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/swapcase_spec.rb index 791d1df..c175a15 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/swapcase_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/swapcase_spec.rb @@ -1,28 +1,40 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the swapcase function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("swapcase")).to eq("function_swapcase") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_swapcase([]) }.to( raise_error(Puppet::ParseError)) +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 - - it "should swapcase a string" do - result = scope.function_swapcase(["aaBBccDD"]) - expect(result).to(eq('AAbbCCdd')) + 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 - class AlsoString < String - end - - value = AlsoString.new("aaBBccDD") - result = scope.function_swapcase([value]) - result.should(eq("AAbbCCdd")) + is_expected.to run.with_params(AlsoString.new("OnE")).and_return('oNe') end end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/time_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/time_spec.rb index 6e22515..d157939 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/time_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/time_spec.rb @@ -1,29 +1,21 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the time function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +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) } - it "should exist" do - expect(Puppet::Parser::Functions.function("time")).to eq("function_time") - end - - it "should raise a ParseError if there is more than 2 arguments" do - expect { scope.function_time(['','']) }.to( raise_error(Puppet::ParseError)) - end - - it "should return a number" do - result = scope.function_time([]) - expect(result).to be_an(Integer) - end - - it "should be higher then when I wrote this test" do - result = scope.function_time([]) - expect(result).to(be > 1311953157) - end - - it "should be lower then 1.5 trillion" do - result = scope.function_time([]) - expect(result).to(be < 1500000000) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/to_bytes_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/to_bytes_spec.rb index 0f6ade9..2be23ff 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/to_bytes_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/to_bytes_spec.rb @@ -1,83 +1,72 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe "the to_bytes function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("to_bytes")).to eq("function_to_bytes") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_to_bytes([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should convert kB to B" do - result = scope.function_to_bytes(["4 kB"]) - expect(result).to(eq(4096)) - end - - it "should convert MB to B" do - result = scope.function_to_bytes(["4 MB"]) - expect(result).to(eq(4194304)) - end - - it "should convert GB to B" do - result = scope.function_to_bytes(["4 GB"]) - expect(result).to(eq(4294967296)) - end - - it "should convert TB to B" do - result = scope.function_to_bytes(["4 TB"]) - expect(result).to(eq(4398046511104)) - end - - it "should convert PB to B" do - result = scope.function_to_bytes(["4 PB"]) - expect(result).to(eq(4503599627370496)) - end - - it "should convert PB to B" do - result = scope.function_to_bytes(["4 EB"]) - expect(result).to(eq(4611686018427387904)) - end - - it "should work without B in unit" do - result = scope.function_to_bytes(["4 k"]) - expect(result).to(eq(4096)) - end - - it "should work without a space before unit" do - result = scope.function_to_bytes(["4k"]) - expect(result).to(eq(4096)) - end - - it "should work without a unit" do - result = scope.function_to_bytes(["5678"]) - expect(result).to(eq(5678)) - end - - it "should convert fractions" do - result = scope.function_to_bytes(["1.5 kB"]) - expect(result).to(eq(1536)) - end - - it "should convert scientific notation" do - result = scope.function_to_bytes(["1.5e2 B"]) - expect(result).to(eq(150)) - end - - it "should do nothing with a positive number" do - result = scope.function_to_bytes([5678]) - expect(result).to(eq(5678)) - end - - it "should should raise a ParseError if input isn't a number" do - expect { scope.function_to_bytes(["foo"]) }.to( raise_error(Puppet::ParseError)) - end - - it "should should raise a ParseError if prefix is unknown" do - expect { scope.function_to_bytes(["5 uB"]) }.to( raise_error(Puppet::ParseError)) +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/try_get_value_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/try_get_value_spec.rb new file mode 100644 index 0000000..38c0efd --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/try_get_value_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/type3x_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/type3x_spec.rb index d21236a..c3eb1de 100644 --- a/puphpet/puppet/modules/stdlib/spec/functions/type3x_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/type3x_spec.rb @@ -1,8 +1,6 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the type3x function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +describe 'type3x' do it "should exist" do expect(Puppet::Parser::Functions.function("type3x")).to eq("function_type3x") end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/type_of_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/type_of_spec.rb new file mode 100644 index 0000000..cc9ef78 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/type_of_spec.rb @@ -0,0 +1,25 @@ +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' do + it { is_expected.not_to eq(nil) } + end + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/type_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/type_spec.rb index b683fcf..4288df0 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/type_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/type_spec.rb @@ -1,8 +1,6 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the type function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } +describe 'type' do it "should exist" do expect(Puppet::Parser::Functions.function("type")).to eq("function_type") end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/union_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/union_spec.rb index 706f4cb..cfd38b6 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/union_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/union_spec.rb @@ -1,19 +1,24 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the union function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("union")).to eq("function_union") - end - - it "should raise a ParseError if there are fewer than 2 arguments" do - expect { scope.function_union([]) }.to( raise_error(Puppet::ParseError) ) +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 "should join two arrays together" do - result = scope.function_union([["a","b","c"],["b","c","d"]]) - expect(result).to(eq(["a","b","c","d"])) - 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/unique_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/unique_spec.rb index 7cd3a56..24257a0 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/unique_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/unique_spec.rb @@ -1,33 +1,27 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the unique function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("unique")).to eq("function_unique") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_unique([]) }.to( raise_error(Puppet::ParseError)) +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 - it "should remove duplicate elements in a string" do - result = scope.function_unique(["aabbc"]) - expect(result).to(eq('abc')) + 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 - it "should remove duplicate elements in an array" do - result = scope.function_unique([["a","a","b","b","c"]]) - expect(result).to(eq(['a','b','c'])) - end - - it "should accept objects which extend String" do - class AlsoString < String - end - - value = AlsoString.new('aabbc') - result = scope.function_unique([value]) - result.should(eq('abc')) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/unix2dos_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/unix2dos_spec.rb new file mode 100644 index 0000000..8537a26 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/unix2dos_spec.rb @@ -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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/upcase_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/upcase_spec.rb index 0689099..3b7b02d 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/upcase_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/upcase_spec.rb @@ -1,58 +1,26 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the upcase function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("upcase")).to eq("function_upcase") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_upcase([]) }.to(raise_error(Puppet::ParseError)) +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 - it "should upcase a string" do - result = scope.function_upcase(["abc"]) - expect(result).to(eq('ABC')) + 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 - it "should do nothing if a string is already upcase" do - result = scope.function_upcase(["ABC"]) - expect(result).to(eq('ABC')) + describe 'handling classes derived from String' do + it { is_expected.to run.with_params(AlsoString.new("ABC")).and_return("ABC") } end - it "should accept objects which extend String" do - class AlsoString < String - end - - value = AlsoString.new('abc') - result = scope.function_upcase([value]) - result.should(eq('ABC')) - end - - it 'should accept hashes and return uppercase' do - expect( - scope.function_upcase([{'test' => %w(this that and other thing)}]) - ).to eq({'TEST' => %w(THIS THAT AND OTHER THING)}) - end - - if :test.respond_to?(:upcase) - it 'should accept hashes of symbols' do - expect( - scope.function_upcase([{:test => [:this, :that, :other]}]) - ).to eq({:TEST => [:THIS, :THAT, :OTHER]}) - end - it 'should return upcase symbol' do - expect( - scope.function_upcase([:test]) - ).to eq(:TEST) - end - it 'should return mixed objects in upcease' do - expect( - scope.function_upcase([[:test, 'woot']]) - ).to eq([:TEST, 'WOOT']) - - 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/uriescape_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/uriescape_spec.rb index d0f37de..f05ec08 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/uriescape_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/uriescape_spec.rb @@ -1,40 +1,36 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the uriescape function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("uriescape")).to eq("function_uriescape") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_uriescape([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should uriescape a string" do - result = scope.function_uriescape([":/?#[]@!$&'()*+,;= \"{}"]) - expect(result).to(eq(':/?%23[]@!$&\'()*+,;=%20%22%7B%7D')) +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 - it "should uriescape an array of strings, while not touching up nonstrings" do - teststring = ":/?#[]@!$&'()*+,;= \"{}" - expectstring = ':/?%23[]@!$&\'()*+,;=%20%22%7B%7D' - result = scope.function_uriescape([[teststring, teststring, 1]]) - expect(result).to(eq([expectstring, expectstring, 1])) - end - - it "should do nothing if a string is already safe" do - result = scope.function_uriescape(["ABCdef"]) - expect(result).to(eq('ABCdef')) + 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 - it "should accept objects which extend String" do - class AlsoString < String + 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 - value = AlsoString.new('abc') - result = scope.function_uriescape([value]) - result.should(eq('abc')) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_absolute_path_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_absolute_path_spec.rb index 36c836b..4a8404d 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_absolute_path_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_absolute_path_spec.rb @@ -1,67 +1,32 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe Puppet::Parser::Functions.function(:validate_absolute_path) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - # The subject of these examples is the method itself. - subject do - # This makes sure the function is loaded within each test - function_name = Puppet::Parser::Functions.function(:validate_absolute_path) - scope.method(function_name) +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" do - def self.valid_paths - %w{ - C:/ - C:\\ - C:\\WINDOWS\\System32 - C:/windows/system32 - X:/foo/bar - X:\\foo\\bar - /var/tmp - /var/lib/puppet - /var/opt/../lib/puppet - } - end - - context "Without Puppet::Util.absolute_path? (e.g. Puppet <= 2.6)" do - before :each do - # The intent here is to mock Puppet to behave like Puppet 2.6 does. - # Puppet 2.6 does not have the absolute_path? method. This is only a - # convenience test, stdlib should be run with the Puppet 2.6.x in the - # $LOAD_PATH in addition to 2.7.x and master. - Puppet::Util.expects(:respond_to?).with(:absolute_path?).returns(false) - end - valid_paths.each do |path| - it "validate_absolute_path(#{path.inspect}) should not fail" do - expect { subject.call [path] }.not_to raise_error - end - end - valid_paths do - it "validate_absolute_path(#{valid_paths.inspect}) should not fail" do - expect { subject.call [valid_paths] }.not_to raise_error - end - end - end - - context "Puppet without mocking" do - valid_paths.each do |path| - it "validate_absolute_path(#{path.inspect}) should not fail" do - expect { subject.call [path] }.not_to raise_error - end - end - valid_paths do - it "validate_absolute_path(#{valid_paths.inspect}) should not fail" do - expect { subject.call [valid_paths] }.not_to raise_error - end - 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 paths' do - context 'Garbage inputs' do + describe 'invalid path handling' do + context 'garbage inputs' do [ nil, [ nil ], @@ -70,33 +35,26 @@ def self.valid_paths { }, '', ].each do |path| - it "validate_absolute_path(#{path.inspect}) should fail" do - expect { subject.call [path] }.to raise_error Puppet::ParseError - end + 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 - def self.rel_paths - %w{ - relative1 - . - .. - ./foo - ../foo - etc/puppetlabs/puppet - opt/puppet/bin - } - end - rel_paths.each do |path| - it "validate_absolute_path(#{path.inspect}) should fail" do - expect { subject.call [path] }.to raise_error Puppet::ParseError - end - end - rel_paths do - it "validate_absolute_path(#{rel_paths.inspect}) should fail" do - expect { subject.call [rel_paths] }.to raise_error Puppet::ParseError - 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_array_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_array_spec.rb index 4b31cfd..4ee7754 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_array_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_array_spec.rb @@ -1,38 +1,27 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe Puppet::Parser::Functions.function(:validate_array) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - describe 'when calling validate_array from puppet' do - - %w{ true false }.each do |the_string| - it "should not compile when #{the_string} is a string" do - Puppet[:code] = "validate_array('#{the_string}')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not an Array/) - end +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) } - it "should not compile when #{the_string} is a bare word" do - Puppet[:code] = "validate_array(#{the_string})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not an Array/) - end + 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 - it "should compile when multiple array arguments are passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = [ ] - $bar = [ 'one', 'two' ] - validate_array($foo, $bar) - ENDofPUPPETcode - scope.compiler.compile - end - - it "should not compile when an undef variable is passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = undef - validate_array($foo) - ENDofPUPPETcode - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not an Array/) + 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 + diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_augeas_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_augeas_spec.rb index c695ba2..4236649 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_augeas_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_augeas_spec.rb @@ -1,49 +1,29 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe Puppet::Parser::Functions.function(:validate_augeas), :if => Puppet.features.augeas? do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - # The subject of these examplres is the method itself. - subject do - # This makes sure the function is loaded within each test - function_name = Puppet::Parser::Functions.function(:validate_augeas) - scope.method(function_name) - end - - context 'Using Puppet::Parser::Scope.new' do - - describe 'Garbage inputs' do - inputs = [ - [ nil ], - [ [ nil ] ], - [ { 'foo' => 'bar' } ], - [ { } ], - [ '' ], - [ "one", "one", "MSG to User", "4th arg" ], - ] - - inputs.each do |input| - it "validate_augeas(#{input.inspect}) should fail" do - expect { subject.call [input] }.to raise_error Puppet::ParseError - end - end +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 + 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 "validate_augeas(#{input.inspect}) should not fail" do - expect { subject.call input }.not_to raise_error - end + it { is_expected.to run.with_params(*input) } end end - describe "Valid inputs which should raise an exception without a message" do + 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. @@ -53,14 +33,12 @@ ] inputs.each do |input| - it "validate_augeas(#{input.inspect}) should fail" do - expect { subject.call input }.to raise_error /validate_augeas.*?matched less than it should/ - end + it { is_expected.to run.with_params(*input).and_raise_error(Puppet::ParseError, /validate_augeas.*?matched less than it should/) } end end - describe "Nicer Error Messages" do - # The intent here is to make sure the function returns the 3rd argument + 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' ], @@ -68,35 +46,29 @@ ] inputs.each do |input| - it "validate_augeas(#{input.inspect}) should fail" do - expect { subject.call input }.to raise_error /#{input[2]}/ - end + it { is_expected.to run.with_params(*input).and_raise_error(Puppet::ParseError, /#{input[3]}/) } end end - describe "Passing simple unit tests" do + 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 "validate_augeas(#{input.inspect}) should fail" do - expect { subject.call input }.not_to raise_error - end + it { is_expected.to run.with_params(*input) } end end - describe "Failing simple unit tests" do + 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 "validate_augeas(#{input.inspect}) should fail" do - expect { subject.call input }.to raise_error /testing path/ - end + it { is_expected.to run.with_params(*input).and_raise_error(Puppet::ParseError, /testing path/) } end end end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_bool_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_bool_spec.rb index a352d3b..d9cdf57 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_bool_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_bool_spec.rb @@ -1,51 +1,25 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe Puppet::Parser::Functions.function(:validate_bool) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - describe 'when calling validate_bool from puppet' do - - %w{ true false }.each do |the_string| - - it "should not compile when #{the_string} is a string" do - Puppet[:code] = "validate_bool('#{the_string}')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/) - end - - it "should compile when #{the_string} is a bare word" do - Puppet[:code] = "validate_bool(#{the_string})" - scope.compiler.compile - end - - end - - it "should not compile when an arbitrary string is passed" do - Puppet[:code] = 'validate_bool("jeff and dan are awesome")' - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/) - end - - it "should not compile when no arguments are passed" do - Puppet[:code] = 'validate_bool()' - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /wrong number of arguments/) - end +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 - it "should compile when multiple boolean arguments are passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = true - $bar = false - validate_bool($foo, $bar, true, false) - ENDofPUPPETcode - scope.compiler.compile - 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 - it "should compile when multiple boolean arguments are passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = true - $bar = false - validate_bool($foo, $bar, true, false, 'jeff') - ENDofPUPPETcode - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a boolean/) - 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_cmd_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_cmd_spec.rb index 7cb9782..ab0cbc9 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_cmd_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_cmd_spec.rb @@ -1,85 +1,35 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -TESTEXE = File.exists?('/usr/bin/test') ? '/usr/bin/test' : '/bin/test' -TOUCHEXE = File.exists?('/usr/bin/touch') ? '/usr/bin/touch' : '/bin/touch' - -describe Puppet::Parser::Functions.function(:validate_cmd) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - subject do - function_name = Puppet::Parser::Functions.function(:validate_cmd) - scope.method(function_name) +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 'with no % placeholder' do - describe "with an explicit failure message" do - it "prints the failure message on error" do - expect { - subject.call ['', '/bin/false', 'failure message!'] - }.to raise_error Puppet::ParseError, /failure message!/ - end - end - - describe "on validation failure" do - it "includes the command error output" do - expect { - subject.call ['', "#{TOUCHEXE} /cant/touch/this"] - }.to raise_error Puppet::ParseError, /(cannot touch|o such file or)/ - end - - it "includes the command return value" do - expect { - subject.call ['', '/cant/run/this'] - }.to raise_error Puppet::ParseError, /returned 1\b/ - end - end - - describe "when performing actual validation" do - it "can positively validate file content" do - expect { subject.call ["non-empty", "#{TESTEXE} -s"] }.to_not raise_error - end - - it "can negatively validate file content" do - expect { - subject.call ["", "#{TESTEXE} -s"] - }.to raise_error Puppet::ParseError, /failed to validate.*test -s/ - 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 - end - - context 'with % placeholder' do - describe "with an explicit failure message" do - it "prints the failure message on error" do - expect { - subject.call ['', '/bin/false % -f', 'failure message!'] - }.to raise_error Puppet::ParseError, /failure message!/ - end - end - describe "on validation failure" do - it "includes the command error output" do - expect { - subject.call ['', "#{TOUCHEXE} /cant/touch/this"] - }.to raise_error Puppet::ParseError, /(cannot touch|o such file or)/ - end - - it "includes the command return value" do - expect { - subject.call ['', '/cant/run/this % -z'] - }.to raise_error Puppet::ParseError, /Execution of '\/cant\/run\/this .+ -z' returned 1/ - end - end - - describe "when performing actual validation" do - it "can positively validate file content" do - expect { subject.call ["non-empty", "#{TESTEXE} -s %"] }.to_not raise_error - end - - it "can negatively validate file content" do - expect { - subject.call ["", "#{TESTEXE} -s %"] - }.to raise_error Puppet::ParseError, /failed to validate.*test -s/ - 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_hash_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_hash_spec.rb index a0c35c2..2e8e59f 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_hash_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_hash_spec.rb @@ -1,43 +1,26 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe Puppet::Parser::Functions.function(:validate_hash) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - describe 'when calling validate_hash from puppet' do - - %w{ true false }.each do |the_string| - - it "should not compile when #{the_string} is a string" do - Puppet[:code] = "validate_hash('#{the_string}')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a Hash/) - end - - it "should not compile when #{the_string} is a bare word" do - Puppet[:code] = "validate_hash(#{the_string})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a Hash/) - end +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 - it "should compile when multiple hash arguments are passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = {} - $bar = { 'one' => 'two' } - validate_hash($foo, $bar) - ENDofPUPPETcode - scope.compiler.compile + 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 - - it "should not compile when an undef variable is passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = undef - validate_hash($foo) - ENDofPUPPETcode - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a Hash/) - end - end - end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_integer_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_integer_spec.rb index dff3415..4c0a9d7 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_integer_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_integer_spec.rb @@ -1,219 +1,90 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe Puppet::Parser::Functions.function(:validate_integer) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - describe 'when calling validate_integer from puppet without any argument or to many' do - it "should not compile when no argument is passed" do - Puppet[:code] = "validate_integer()" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /Wrong number of arguments/) - end - it "should not compile when more than three arguments are passed" do - Puppet[:code] = "validate_integer(1, 1, 1, 1)" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /Wrong number of arguments/) - end - end +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) } - describe 'when calling validate_integer from puppet only with input' do - %w{ 1 -1 }.each do |the_number| - it "should compile when #{the_number} is an encapsulated integer" do - Puppet[:code] = "validate_integer('#{the_number}')" - scope.compiler.compile - end - it "should compile when #{the_number} is an bare integer" do - Puppet[:code] = "validate_integer(#{the_number})" - scope.compiler.compile - end - end - - %w{ [1,2,3,4,5] ['1','2','3','4','5'] }.each do |the_number| - it "should compile when multiple Integer arguments are passed in an Array" do - Puppet[:code] = "validate_integer(#{the_number})" - scope.compiler.compile - end - end - - %w{ true false iAmAString 1test 7.0 -7.0 }.each do |the_number| - it "should not compile when #{the_number} is in a string" do - Puppet[:code] = "validate_integer('#{the_number}')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be an Integer/) - end - - it "should not compile when #{the_number} is a bare word" do - Puppet[:code] = "validate_integer(#{the_number})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be an Integer/) - end + [ 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 - it "should not compile when an Integer is part of a larger String" do - Puppet[:code] = "validate_integer('1 test')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be an Integer/) + 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 - it "should not compile when an Array with a non-Integer value is passed" do - Puppet[:code] = "validate_integer([1, '-7.0'])" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /at array position 1 to be an Integer/) + 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 "should not compile when a Hash is passed" do - Puppet[:code] = "validate_integer({ 1 => 2 })" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be an Integer or Array/) - end - - it "should not compile when an explicitly undef variable is passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = undef - validate_integer($foo) - ENDofPUPPETcode - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be an Integer/) - 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 - it "should not compile when an undefined variable is passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - validate_integer($foobarbazishouldnotexist) - ENDofPUPPETcode - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be an Integer/) - 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 - describe 'when calling validate_integer from puppet with input and a maximum' do - max = 10 - %w{ 1 -1 }.each do |the_number| - it "should compile when #{the_number} is lower than a maximum of #{max}" do - Puppet[:code] = "validate_integer(#{the_number},#{max})" - scope.compiler.compile + 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 - end - - it "should compile when an Integer is equal the maximum" do - Puppet[:code] = "validate_integer(#{max},#{max})" - scope.compiler.compile - end - - it "should not compile when #{max+1} is greater than a maximum of #{max}" do - Puppet[:code] = "validate_integer(#{max+1},#{max})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be smaller or equal to/) - end - %w{ [-10,1,2,3,4,5,10] ['-10','1','2','3','4','5','10'] }.each do |the_number| - it "should compile when each element of #{the_number} is lower than a maximum of #{max}" do - Puppet[:code] = "validate_integer(#{the_number},#{max})" - scope.compiler.compile + 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 - end - it "should not compile when an element of an Array [-10,1,2,3,4,5,#{max+1}] is greater than a maximum of #{max}" do - Puppet[:code] = "validate_integer([-10,1,2,3,4,5,#{max+1}],#{max})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be smaller or equal to/) - end - - %w{ true false iAmAString 1test 7.0 -7.0 }.each do |the_max| - it "should not compile when a non-Integer maximum #{the_max}, encapsulated in a String, is passed" do - Puppet[:code] = "validate_integer(1,'#{the_max}')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or an Integer/) - end - - it "should not compile when a non-Integer maximum #{the_max} bare word is passed" do - Puppet[:code] = "validate_integer(1,#{the_max})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or an Integer/) + 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 - - it "should not compile when an explicitly undefined variable is passed as maximum and no minimum is passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = undef - validate_integer(10, $foo) - ENDofPUPPETcode - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or an Integer/) - end - it "should not compile when an explicitly undef is passed as maximum and no minimum is passed" do - Puppet[:code] = "validate_integer(10, undef)" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or an Integer/) - end - it "should not compile when an empty string is passed as maximum and no minimum is passed" do - Puppet[:code] = "validate_integer(10, '')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or an Integer/) - end - it "should not compile when an undefined variable for a maximum is passed" do - Puppet[:code] = "validate_integer(10, $foobarbazishouldnotexist)" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or an Integer/) - end end - describe 'when calling validate_integer from puppet with input, a maximum and a minimum' do - it "should not compile when a minimum larger than maximum is passed" do - Puppet[:code] = "validate_integer(1,1,2)" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /second argument to be larger than third argument/) - end - - max = 10 - min = -10 - %w{ 1 -1 }.each do |the_number| - it "should compile when each element of #{the_number} is within a range from #{min} to #{max}" do - Puppet[:code] = "validate_integer(#{the_number},#{max},#{min})" - scope.compiler.compile - end - end - - it "should compile when an Integer is equal the minimum" do - Puppet[:code] = "validate_integer(#{min},#{max},#{min})" - scope.compiler.compile - end - - it "should compile when an Integer is equal the minimum and maximum" do - Puppet[:code] = "validate_integer(#{max},#{max},#{max})" - scope.compiler.compile - end - - it "should compile when an empty maximum is passed and the Integer is greater than the minimum" do - Puppet[:code] = "validate_integer(#{max},'',#{min})" - scope.compiler.compile - end - it "should compile when an explicitly undefined maximum is passed and the Integer is greater than the minimum" do - Puppet[:code] = "validate_integer(#{max},undef,#{min})" - scope.compiler.compile - end - it "should compile when an explicitly undefined variable is passed for maximum and the Integer is greater than the minimum" do - Puppet[:code] = <<-"ENDofPUPPETcode" - $foo = undef - validate_integer(#{max}, $foo, #{min}) - ENDofPUPPETcode - scope.compiler.compile - end - it "should not compile when no maximum value is given and the Integer is greater than the minimum" do - Puppet[:code] = "validate_integer(#{max},,#{min})" - expect { scope.compiler.compile }.to raise_error(Puppet::Error, /Syntax error at ','/) - end - - it "should not compile when #{min-1} is lower than a minimum of #{min}" do - Puppet[:code] = "validate_integer(#{min-1},#{max},#{min})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be greater or equal to/) - end - - %w{ [-10,1,2,3,4,5,10] ['-10','1','2','3','4','5','10'] }.each do |the_number| - it "should compile when each element of #{the_number} is within a range from #{min} to #{max}" do - Puppet[:code] = "validate_integer(#{the_number},#{max},#{min})" - scope.compiler.compile - end - end - - it "should not compile when an element of an Array [#{min-1},1,2,3,4,5,10] is lower than a minimum of #{min}" do - Puppet[:code] = "validate_integer([#{min-1},1,2,3,4,5,10],#{max},#{min})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be greater or equal to/) - end + it { is_expected.to run.with_params(10, 10, 10) } - %w{ true false iAmAString 1test 7.0 -7.0 }.each do |the_min| - it "should not compile when a non-Integer minimum #{the_min}, encapsulated in a String, is passed" do - Puppet[:code] = "validate_integer(1,#{max},'#{the_min}')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or an Integer/) - end - - it "should not compile when a non-Integer minimum #{the_min} bare word is passed" do - Puppet[:code] = "validate_integer(1,#{max},#{the_min})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or an Integer/) - end - end + describe 'empty upper limit is interpreted as infinity' do + it { is_expected.to run.with_params(11, '', 10) } end end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_ip_address_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_ip_address_spec.rb new file mode 100644 index 0000000..b56ce51 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_ip_address_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe 'validate_ip_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) } + end + + 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') } + 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') } + 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 IP/) } + it { is_expected.to run.with_params('0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IP/) } + it { is_expected.to run.with_params('0.0.0.256').and_raise_error(Puppet::ParseError, /is not a valid IP/) } + it { is_expected.to run.with_params('0.0.0.0.0').and_raise_error(Puppet::ParseError, /is not a valid IP/) } + 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 IP/) } + 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 IP/) } + end +end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_ipv4_address_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_ipv4_address_spec.rb index 45401a4..b6170d4 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_ipv4_address_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_ipv4_address_spec.rb @@ -1,64 +1,40 @@ -#! /usr/bin/env ruby -S rspec - -require "spec_helper" - -describe Puppet::Parser::Functions.function(:validate_ipv4_address) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - describe "when calling validate_ipv4_address from puppet" do - describe "when given IPv4 address strings" do - it "should compile with one argument" do - Puppet[:code] = "validate_ipv4_address('1.2.3.4')" - scope.compiler.compile - end - - it "should compile with multiple arguments" do - Puppet[:code] = "validate_ipv4_address('1.2.3.4', '5.6.7.8')" - scope.compiler.compile - end - end - - describe "when given an IPv6 address" do - it "should not compile" do - Puppet[:code] = "validate_ipv4_address('3ffe:505')" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /not a valid IPv4 address/) - end - end - - describe "when given other strings" do - it "should not compile" do - Puppet[:code] = "validate_ipv4_address('hello', 'world')" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /not a valid IPv4 address/) - end - end - - describe "when given numbers" do - it "should not compile" do - Puppet[:code] = "validate_ipv4_address(1, 2)" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /is not a valid IPv4 address/) - end - end - - describe "when given booleans" do - it "should not compile" do - Puppet[:code] = "validate_ipv4_address(true, false)" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /is not a string/) +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 - it "should not compile when no arguments are passed" do - Puppet[:code] = "validate_ipv4_address()" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /wrong number of arguments/) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_ipv6_address_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_ipv6_address_spec.rb index a839d90..7aaf006 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_ipv6_address_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_ipv6_address_spec.rb @@ -1,67 +1,32 @@ -#! /usr/bin/env ruby -S rspec - -require "spec_helper" - -describe Puppet::Parser::Functions.function(:validate_ipv6_address) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - describe "when calling validate_ipv6_address from puppet" do - describe "when given IPv6 address strings" do - it "should compile with one argument" do - Puppet[:code] = "validate_ipv6_address('3ffe:0505:0002::')" - scope.compiler.compile - end - - it "should compile with multiple arguments" do - Puppet[:code] = "validate_ipv6_address('3ffe:0505:0002::', '3ffe:0505:0001::')" - scope.compiler.compile - end - end - - describe "when given an ipv4 address" do - it "should not compile" do - Puppet[:code] = "validate_ipv6_address('1.2.3.4')" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /not a valid IPv6 address/) - end +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 "when given other strings" do - it "should not compile" do - Puppet[:code] = "validate_ipv6_address('hello', 'world')" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /not a valid IPv6 address/) + 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 - - # 1.8.7 is EOL'd and also absolutely insane about ipv6 - unless RUBY_VERSION == '1.8.7' - describe "when given numbers" do - it "should not compile" do - Puppet[:code] = "validate_ipv6_address(1, 2)" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /not a valid IPv6 address/) - end - end - end - - describe "when given booleans" do - it "should not compile" do - Puppet[:code] = "validate_ipv6_address(true, false)" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /is not a string/) - end - end - - it "should not compile when no arguments are passed" do - Puppet[:code] = "validate_ipv6_address()" - expect { - scope.compiler.compile - }.to raise_error(Puppet::ParseError, /wrong number of arguments/) - end end end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_numeric_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_numeric_spec.rb index c8b0e4d..9b8eb0e 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_numeric_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_numeric_spec.rb @@ -1,217 +1,89 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe Puppet::Parser::Functions.function(:validate_numeric) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - describe 'when calling validate_numeric from puppet without any argument or to many' do - it "should not compile when no argument is passed" do - Puppet[:code] = "validate_numeric()" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /Wrong number of arguments/) - end - it "should not compile when more than three arguments are passed" do - Puppet[:code] = "validate_numeric(1, 1, 1, 1)" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /Wrong number of arguments/) - end - end +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) } - describe 'when calling validate_numeric from puppet only with input' do - %w{ 1 -1 1.0 -1.0 }.each do |the_number| - it "should compile when #{the_number} is an encapsulated numeric" do - Puppet[:code] = "validate_numeric('#{the_number}')" - scope.compiler.compile - end - it "should compile when #{the_number} is a bare numeric" do - Puppet[:code] = "validate_numeric(#{the_number})" - scope.compiler.compile - end - end - - %w{ [1,2,3,4,5] ['1','2','3','4','5'] [1.1,2.2,3.3,4.4,5.5] ['1.1','2.2','3.3','4.4','5.5'] }.each do |the_number| - it "should compile when multiple Numeric arguments are passed in an Array" do - Puppet[:code] = "validate_numeric(#{the_number})" - scope.compiler.compile - end - end - - %w{ true false iAmAString 1test }.each do |the_number| - it "should not compile when #{the_number} is in a string" do - Puppet[:code] = "validate_numeric('#{the_number}')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be a Numeric/) - end - - it "should not compile when #{the_number} is a bare word" do - Puppet[:code] = "validate_numeric(#{the_number})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be a Numeric/) - end + [ 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 - it "should not compile when a Numeric is part of a larger String" do - Puppet[:code] = "validate_numeric('1.0 test')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be a Numeric/) + 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 - it "should not compile when an Array with a non-Numeric value is passed" do - Puppet[:code] = "validate_numeric([1, 'test'])" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /at array position 1 to be a Numeric/) + 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 "should not compile when a Hash is passed" do - Puppet[:code] = "validate_numeric({ 1 => 2 })" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be a Numeric or Array/) - end - - it "should not compile when an explicitly undef variable is passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = undef - validate_numeric($foo) - ENDofPUPPETcode - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be a Numeric/) - 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 - it "should not compile when an undefined variable is passed" do - Puppet[:code] = 'validate_numeric($foobarbazishouldnotexist)' - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be a Numeric/) - 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 - describe 'when calling validate_numeric from puppet with input and a maximum' do - max = 10 - %w{ 1 -1 1.0 -1.0 }.each do |the_number| - it "should compile when #{the_number} is lower than a maximum of #{max}" do - Puppet[:code] = "validate_numeric(#{the_number},#{max})" - scope.compiler.compile + 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 - end - - it "should compile when a Numeric is equal the maximum" do - Puppet[:code] = "validate_numeric(#{max},#{max})" - scope.compiler.compile - end - - it "should not compile when #{max+1} is greater than a maximum of #{max}" do - Puppet[:code] = "validate_numeric(#{max+1},#{max})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be smaller or equal to/) - end - %w{ [-10,1,2,3,4,5,10] ['-10','1','2','3','4','5','10'] }.each do |the_number| - it "should compile when each element of #{the_number} is lower than a maximum of #{max}" do - Puppet[:code] = "validate_numeric(#{the_number},#{max})" - scope.compiler.compile + 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 - end - it "should not compile when an element of an Array [-10,1,2,3,4,5,#{max+1}] is greater than a maximum of #{max}" do - Puppet[:code] = "validate_numeric([-10,1,2,3,4,5,#{max+1}],#{max})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be smaller or equal to/) - end - - %w{ true false iAmAString 1test }.each do |the_max| - it "should not compile when a non-Numeric maximum #{the_max}, encapsulated in a String, is passed" do - Puppet[:code] = "validate_numeric(1,'#{the_max}')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or a Numeric/) - end - - it "should not compile when a non-Numeric maximum #{the_max} bare word is passed" do - Puppet[:code] = "validate_numeric(1,#{the_max})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or a Numeric/) + 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 - - it "should not compile when an explicitly undefined variable is passed as maximum and no minimum is passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = undef - validate_numeric(10, $foo) - ENDofPUPPETcode - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or a Numeric/) - end - it "should not compile when an explicitly undef is passed as maximum and no minimum is passed" do - Puppet[:code] = "validate_numeric(10, undef)" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or a Numeric/) - end - it "should not compile when an empty string is passed as maximum and no minimum is passed" do - Puppet[:code] = "validate_numeric(10, '')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or a Numeric/) - end - it "should not compile when an undefined variable for a maximum is passed" do - Puppet[:code] = "validate_numeric(10, $foobarbazishouldnotexist)" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or a Numeric/) - end end - describe 'when calling validate_numeric from puppet with input, a maximum and a minimum' do - it "should not compile when a minimum larger than maximum is passed" do - Puppet[:code] = "validate_numeric(1,1,2)" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /second argument to be larger than third argument/) - end - - max = 10 - min = -10 - %w{ 1 -1 }.each do |the_number| - it "should compile when each element of #{the_number} is within a range from #{min} to #{max}" do - Puppet[:code] = "validate_numeric(#{the_number},#{max},#{min})" - scope.compiler.compile - end - end - - it "should compile when a Numeric is equal the minimum" do - Puppet[:code] = "validate_numeric(#{min},#{max},#{min})" - scope.compiler.compile - end - - it "should compile when a Numeric is equal the minimum and maximum" do - Puppet[:code] = "validate_numeric(#{max},#{max},#{max})" - scope.compiler.compile - end - - it "should compile when an empty maximum is passed and the Numeric is greater than the minimum" do - Puppet[:code] = "validate_numeric(#{max}.1,'',#{min})" - scope.compiler.compile - end - it "should compile when an explicitly undefined maximum is passed and the Numeric is greater than the minimum" do - Puppet[:code] = "validate_numeric(#{max}.1,undef,#{min})" - scope.compiler.compile - end - it "should compile when an explicitly undefined variable is passed for maximum and the Numeric is greater than the minimum" do - Puppet[:code] = <<-"ENDofPUPPETcode" - $foo = undef - validate_numeric(#{max}.1, $foo, #{min}) - ENDofPUPPETcode - scope.compiler.compile - end - it "should not compile when no maximum value is given and the Numeric is greater than the minimum" do - Puppet[:code] = "validate_numeric(#{max}.1,,#{min})" - expect { scope.compiler.compile }.to raise_error(Puppet::Error, /Syntax error at ','/) - end - - it "should not compile when #{min-1} is lower than a minimum of #{min}" do - Puppet[:code] = "validate_numeric(#{min-1.0},#{max},#{min})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be greater or equal to/) - end - - %w{ [-10,1,2,3,4,5,10] ['-10.0','1','2','3','4','5','10.0'] }.each do |the_number| - it "should compile when each element of #{the_number} is within a range from #{min} to #{max}" do - Puppet[:code] = "validate_numeric(#{the_number},#{max},#{min})" - scope.compiler.compile - end - end - - it "should not compile when an element of an Array [#{min-1.1},1,2,3,4,5,10.0] is lower than a minimum of #{min}" do - Puppet[:code] = "validate_numeric([#{min-1},1,2,3,4,5,10],#{max},#{min})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be greater or equal to/) - end + it { is_expected.to run.with_params(10.0, 10.0, 10.0) } - %w{ true false iAmAString 1test }.each do |the_min| - it "should not compile when a non-Numeric minimum #{the_min}, encapsulated in a String, is passed" do - Puppet[:code] = "validate_numeric(1,#{max},'#{the_min}')" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or a Numeric/) - end - - it "should not compile when a non-Numeric minimum #{the_min} bare word is passed" do - Puppet[:code] = "validate_numeric(1,#{max},#{the_min})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /to be unset or a Numeric/) - end - end + describe 'empty upper limit is interpreted as infinity' do + it { is_expected.to run.with_params(11, '', 10.0) } end end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_re_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_re_spec.rb index d29988b..3f90143 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_re_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_re_spec.rb @@ -1,75 +1,59 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe Puppet::Parser::Functions.function(:validate_re) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - # The subject of these examplres is the method itself. - subject do - # This makes sure the function is loaded within each test - function_name = Puppet::Parser::Functions.function(:validate_re) - scope.method(function_name) - end - - context 'Using Puppet::Parser::Scope.new' do - - describe 'Garbage inputs' do - inputs = [ - [ nil ], - [ [ nil ] ], - [ { 'foo' => 'bar' } ], - [ { } ], - [ '' ], - [ "one", "one", "MSG to User", "4th arg" ], - ] - - inputs.each do |input| - it "validate_re(#{input.inspect}) should fail" do - expect { subject.call [input] }.to raise_error Puppet::ParseError - end - end - end - - describe 'Valid inputs' do - inputs = [ - [ '/full/path/to/something', '^/full' ], - [ '/full/path/to/something', 'full' ], - [ '/full/path/to/something', ['full', 'absent'] ], - [ '/full/path/to/something', ['full', 'absent'], 'Message to the user' ], - ] - - inputs.each do |input| - it "validate_re(#{input.inspect}) should not fail" do - expect { subject.call input }.not_to raise_error - end - end - end - describe "Valid inputs which should raise an exception without a message" 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 = [ - [ "hello", [ "bye", "later", "adios" ] ], - [ "greetings", "salutations" ], - ] - - inputs.each do |input| - it "validate_re(#{input.inspect}) should fail" do - expect { subject.call input }.to raise_error /validate_re.*?does not match/ - end - end +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 "Nicer Error Messages" do - # The intent here is to make sure the function returns the 3rd argument - # in the exception thrown - inputs = [ - [ "hello", [ "bye", "later", "adios" ], "MSG to User" ], - [ "greetings", "salutations", "Error, greetings does not match salutations" ], - ] - inputs.each do |input| - it "validate_re(#{input.inspect}) should fail" do - expect { subject.call input }.to raise_error /#{input[2]}/ + 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/) } + + describe 'non-string inputs' do + [ + 1, # Fixnum + 3.14, # Float + nil, # NilClass + true, # TrueClass + false, # FalseClass + ["10"], # Array + :key, # Symbol + {:key=>"val"}, # Hash + ].each do |input| + it { is_expected.to run.with_params(input, '.*').and_raise_error(Puppet::ParseError, /needs to be a String/) } end end end diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_slength_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_slength_spec.rb index e23f61a..5a8fa6a 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_slength_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_slength_spec.rb @@ -1,67 +1,61 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe "the validate_slength function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("validate_slength")).to eq("function_validate_slength") +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 - describe "validating the input argument types" do - it "raises an error if there are less than two arguments" do - expect { scope.function_validate_slength([]) }.to raise_error Puppet::ParseError, /Wrong number of arguments/ - end - - it "raises an error if there are more than three arguments" do - expect { scope.function_validate_slength(['input', 1, 2, 3]) }.to raise_error Puppet::ParseError, /Wrong number of arguments/ - end - - it "raises an error if the first argument is not a string" do - expect { scope.function_validate_slength([Object.new, 2, 1]) }.to raise_error Puppet::ParseError, /Expected first argument.*got .*Object/ - end - - it "raises an error if the second argument cannot be cast to an Integer" do - expect { scope.function_validate_slength(['input', Object.new]) }.to raise_error Puppet::ParseError, /Expected second argument.*got .*Object/ - end - - it "raises an error if the third argument cannot be cast to an Integer" do - expect { scope.function_validate_slength(['input', 1, Object.new]) }.to raise_error Puppet::ParseError, /Expected third argument.*got .*Object/ + 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 - it "raises an error if the second argument is smaller than the third argument" do - expect { scope.function_validate_slength(['input', 1, 2]) }.to raise_error Puppet::ParseError, /Expected second argument to be larger than third argument/ + 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 - end - - describe "validating the input string length" do - describe "when the input is a string" do - it "fails validation if the string is larger than the max length" do - expect { scope.function_validate_slength(['input', 1]) }.to raise_error Puppet::ParseError, /Expected length .* between 0 and 1, was 5/ - end - - it "fails validation if the string is less than the min length" do - expect { scope.function_validate_slength(['input', 10, 6]) }.to raise_error Puppet::ParseError, /Expected length .* between 6 and 10, was 5/ - end - it "doesn't raise an error if the string is under the max length" do - scope.function_validate_slength(['input', 10]) + 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 - it "doesn't raise an error if the string is equal to the max length" do - scope.function_validate_slength(['input', 5]) + 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 - it "doesn't raise an error if the string is equal to the min length" do - scope.function_validate_slength(['input', 10, 5]) + 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 "when the input is an array" do - it "fails validation if one of the array elements is not a string" do - expect { scope.function_validate_slength([["a", "b", Object.new], 2]) }.to raise_error Puppet::ParseError, /Expected element at array position 2 .*String, got .*Object/ - 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/validate_string_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/validate_string_spec.rb index 3b4fb3e..f0c500e 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/validate_string_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/validate_string_spec.rb @@ -1,60 +1,21 @@ -#! /usr/bin/env ruby -S rspec - require 'spec_helper' -describe Puppet::Parser::Functions.function(:validate_string) do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - describe 'when calling validate_string from puppet' do - - %w{ foo bar baz }.each do |the_string| - - it "should compile when #{the_string} is a string" do - Puppet[:code] = "validate_string('#{the_string}')" - scope.compiler.compile - end - - it "should compile when #{the_string} is a bare word" do - Puppet[:code] = "validate_string(#{the_string})" - scope.compiler.compile - end - - end - - %w{ true false }.each do |the_string| - it "should compile when #{the_string} is a string" do - Puppet[:code] = "validate_string('#{the_string}')" - scope.compiler.compile - end - - it "should not compile when #{the_string} is a bare word" do - Puppet[:code] = "validate_string(#{the_string})" - expect { scope.compiler.compile }.to raise_error(Puppet::ParseError, /is not a string/) - end - end - - it "should compile when multiple string arguments are passed" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = '' - $bar = 'two' - validate_string($foo, $bar) - ENDofPUPPETcode - scope.compiler.compile - end +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) } - it "should compile when an explicitly undef variable is passed (NOTE THIS MAY NOT BE DESIRABLE)" do - Puppet[:code] = <<-'ENDofPUPPETcode' - $foo = undef - validate_string($foo) - ENDofPUPPETcode - scope.compiler.compile + 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 - it "should compile when an undefined variable is passed (NOTE THIS MAY NOT BE DESIRABLE)" do - Puppet[:code] = <<-'ENDofPUPPETcode' - validate_string($foobarbazishouldnotexist) - ENDofPUPPETcode - scope.compiler.compile + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/values_at_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/values_at_spec.rb index 86e3c31..a8348f3 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/values_at_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/values_at_spec.rb @@ -1,38 +1,49 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the values_at function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("values_at")).to eq("function_values_at") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_values_at([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should raise a ParseError if you try to use a range where stop is greater then start" do - expect { scope.function_values_at([['a','b'],["3-1"]]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return a value at from an array" do - result = scope.function_values_at([['a','b','c'],"1"]) - expect(result).to(eq(['b'])) - end - - it "should return a value at from an array when passed a range" do - result = scope.function_values_at([['a','b','c'],"0-1"]) - expect(result).to(eq(['a','b'])) +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 - it "should return chosen values from an array when passed number of indexes" do - result = scope.function_values_at([['a','b','c'],["0","2"]]) - expect(result).to(eq(['a','c'])) + 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 - it "should return chosen values from an array when passed ranges and multiple indexes" do - result = scope.function_values_at([['a','b','c','d','e','f','g'],["0","2","4-5"]]) - expect(result).to(eq(['a','c','e','f'])) + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/values_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/values_spec.rb index 08d21b0..4abf0bd 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/values_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/values_spec.rb @@ -1,31 +1,19 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the values function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("values")).to eq("function_values") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_values([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should return values from a hash" do - result = scope.function_values([{'a'=>'1','b'=>'2','c'=>'3'}]) - # =~ is the RSpec::Matchers::MatchArray matcher. - # A.K.A. "array with same elements" (multiset) matching - expect(result).to match_array(%w{ 1 2 3 }) - end - - it "should return a multiset" do - result = scope.function_values([{'a'=>'1','b'=>'3','c'=>'3'}]) - expect(result).to match_array(%w{ 1 3 3 }) - expect(result).not_to match_array(%w{ 1 3 }) - end - - it "should raise a ParseError unless a Hash is provided" do - expect { scope.function_values([['a','b','c']]) }.to( raise_error(Puppet::ParseError)) +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 diff --git a/puphpet/puppet/modules/stdlib/spec/functions/zip_spec.rb b/puphpet/puppet/modules/stdlib/spec/functions/zip_spec.rb index f265fce..abca7ee 100755 --- a/puphpet/puppet/modules/stdlib/spec/functions/zip_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/functions/zip_spec.rb @@ -1,31 +1,15 @@ -#! /usr/bin/env ruby -S rspec require 'spec_helper' -describe "the zip function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_zip([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should be able to zip an array" do - result = scope.function_zip([['1','2','3'],['4','5','6']]) - expect(result).to(eq([["1", "4"], ["2", "5"], ["3", "6"]])) - result = scope.function_zip([['1','2','3'],['4','5','6'], false]) - result.should(eq([["1", "4"], ["2", "5"], ["3", "6"]])) - end - - it "should be able to zip an array and flatten" do - result = scope.function_zip([['1','2','3'],['4','5','6'], true]) - result.should(eq(["1", "4", "2", "5", "3", "6"])) - end - - it "should accept objects which extend String for the second argument" do - class AlsoString < String - end - - value = AlsoString.new('false') - result = scope.function_zip([['1','2','3'],['4','5','6'],value]) - result.should(eq([["1", "4"], ["2", "5"], ["3", "6"]])) - end +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 diff --git a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/compiler.rb b/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/compiler.rb deleted file mode 100755 index 2f0ae4d..0000000 --- a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/compiler.rb +++ /dev/null @@ -1,47 +0,0 @@ -#! /usr/bin/env ruby -S rspec -module PuppetSpec::Compiler - def compile_to_catalog(string, node = Puppet::Node.new('foonode')) - Puppet[:code] = string - Puppet::Parser::Compiler.compile(node) - end - - def compile_to_ral(manifest) - catalog = compile_to_catalog(manifest) - ral = catalog.to_ral - ral.finalize - ral - end - - def compile_to_relationship_graph(manifest, prioritizer = Puppet::Graph::SequentialPrioritizer.new) - ral = compile_to_ral(manifest) - graph = Puppet::Graph::RelationshipGraph.new(prioritizer) - graph.populate_from(ral) - graph - end - - if Puppet.version.to_f >= 3.3 - def apply_compiled_manifest(manifest, prioritizer = Puppet::Graph::SequentialPrioritizer.new) - transaction = Puppet::Transaction.new(compile_to_ral(manifest), - Puppet::Transaction::Report.new("apply"), - prioritizer) - transaction.evaluate - transaction.report.finalize_report - - transaction - end - else - def apply_compiled_manifest(manifest) - transaction = Puppet::Transaction.new(compile_to_ral(manifest), Puppet::Transaction::Report.new("apply")) - transaction.evaluate - transaction.report.finalize_report - - transaction - end - end - - def order_resources_traversed_in(relationships) - order_seen = [] - relationships.traverse { |resource| order_seen << resource.ref } - order_seen - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/database.rb b/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/database.rb deleted file mode 100755 index f5c2341..0000000 --- a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/database.rb +++ /dev/null @@ -1,30 +0,0 @@ -#! /usr/bin/env ruby -S rspec -# This just makes some nice things available at global scope, and for setup of -# tests to use a real fake database, rather than a fake stubs-that-don't-work -# version of the same. Fun times. -def sqlite? - if $sqlite.nil? - begin - require 'sqlite3' - $sqlite = true - rescue LoadError - $sqlite = false - end - end - $sqlite -end - -def can_use_scratch_database? - sqlite? and Puppet.features.rails? -end - - -# This is expected to be called in your `before :each` block, and will get you -# ready to roll with a serious database and all. Cleanup is handled -# automatically for you. Nothing to do there. -def setup_scratch_database - Puppet[:dbadapter] = 'sqlite3' - Puppet[:dblocation] = ':memory:' - Puppet[:railslog] = PuppetSpec::Files.tmpfile('storeconfigs.log') - Puppet::Rails.init -end diff --git a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/files.rb b/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/files.rb deleted file mode 100755 index 71b38ff..0000000 --- a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/files.rb +++ /dev/null @@ -1,61 +0,0 @@ -#! /usr/bin/env ruby -S rspec -require 'fileutils' -require 'tempfile' -require 'tmpdir' -require 'pathname' - -# A support module for testing files. -module PuppetSpec::Files - def self.cleanup - $global_tempfiles ||= [] - while path = $global_tempfiles.pop do - begin - Dir.unstub(:entries) - FileUtils.rm_rf path, :secure => true - rescue Errno::ENOENT - # nothing to do - end - end - end - - def make_absolute(path) PuppetSpec::Files.make_absolute(path) end - def self.make_absolute(path) - path = File.expand_path(path) - path[0] = 'c' if Puppet.features.microsoft_windows? - path - end - - def tmpfile(name, dir = nil) PuppetSpec::Files.tmpfile(name, dir) end - def self.tmpfile(name, dir = nil) - # Generate a temporary file, just for the name... - source = dir ? Tempfile.new(name, dir) : Tempfile.new(name) - path = source.path - source.close! - - record_tmp(File.expand_path(path)) - - path - end - - def file_containing(name, contents) PuppetSpec::Files.file_containing(name, contents) end - def self.file_containing(name, contents) - file = tmpfile(name) - File.open(file, 'wb') { |f| f.write(contents) } - file - end - - def tmpdir(name) PuppetSpec::Files.tmpdir(name) end - def self.tmpdir(name) - dir = Dir.mktmpdir(name) - - record_tmp(dir) - - dir - end - - def self.record_tmp(tmp) - # ...record it for cleanup, - $global_tempfiles ||= [] - $global_tempfiles << tmp - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/fixtures.rb b/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/fixtures.rb deleted file mode 100755 index 81e9775..0000000 --- a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/fixtures.rb +++ /dev/null @@ -1,29 +0,0 @@ -#! /usr/bin/env ruby -S rspec -module PuppetSpec::Fixtures - def fixtures(*rest) - File.join(PuppetSpec::FIXTURE_DIR, *rest) - end - def my_fixture_dir - callers = caller - while line = callers.shift do - next unless found = line.match(%r{/spec/(.*)_spec\.rb:}) - return fixtures(found[1]) - end - fail "sorry, I couldn't work out your path from the caller stack!" - end - def my_fixture(name) - file = File.join(my_fixture_dir, name) - unless File.readable? file then - fail Puppet::DevError, "fixture '#{name}' for #{my_fixture_dir} is not readable" - end - return file - end - def my_fixtures(glob = '*', flags = 0) - files = Dir.glob(File.join(my_fixture_dir, glob), flags) - unless files.length > 0 then - fail Puppet::DevError, "fixture '#{glob}' for #{my_fixture_dir} had no files!" - end - block_given? and files.each do |file| yield file end - files - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/matchers.rb b/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/matchers.rb deleted file mode 100755 index 093d77c..0000000 --- a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/matchers.rb +++ /dev/null @@ -1,121 +0,0 @@ -#! /usr/bin/env ruby -S rspec -require 'stringio' - -######################################################################## -# Backward compatibility for Jenkins outdated environment. -module RSpec - module Matchers - module BlockAliases - alias_method :to, :should unless method_defined? :to - alias_method :to_not, :should_not unless method_defined? :to_not - alias_method :not_to, :should_not unless method_defined? :not_to - end - end -end - - -######################################################################## -# Custom matchers... -RSpec::Matchers.define :have_matching_element do |expected| - match do |actual| - actual.any? { |item| item =~ expected } - end -end - - -RSpec::Matchers.define :exit_with do |expected| - actual = nil - match do |block| - begin - block.call - rescue SystemExit => e - actual = e.status - end - actual and actual == expected - end - failure_message_for_should do |block| - "expected exit with code #{expected} but " + - (actual.nil? ? " exit was not called" : "we exited with #{actual} instead") - end - failure_message_for_should_not do |block| - "expected that exit would not be called with #{expected}" - end - description do - "expect exit with #{expected}" - end -end - -class HavePrintedMatcher - attr_accessor :expected, :actual - - def initialize(expected) - case expected - when String, Regexp - @expected = expected - else - @expected = expected.to_s - end - end - - def matches?(block) - begin - $stderr = $stdout = StringIO.new - $stdout.set_encoding('UTF-8') if $stdout.respond_to?(:set_encoding) - block.call - $stdout.rewind - @actual = $stdout.read - ensure - $stdout = STDOUT - $stderr = STDERR - end - - if @actual then - case @expected - when String - @actual.include? @expected - when Regexp - @expected.match @actual - end - else - false - end - end - - def failure_message_for_should - if @actual.nil? then - "expected #{@expected.inspect}, but nothing was printed" - else - "expected #{@expected.inspect} to be printed; got:\n#{@actual}" - end - end - - def failure_message_for_should_not - "expected #{@expected.inspect} to not be printed; got:\n#{@actual}" - end - - def description - "expect #{@expected.inspect} to be printed" - end -end - -def have_printed(what) - HavePrintedMatcher.new(what) -end - -RSpec::Matchers.define :equal_attributes_of do |expected| - match do |actual| - actual.instance_variables.all? do |attr| - actual.instance_variable_get(attr) == expected.instance_variable_get(attr) - end - end -end - -RSpec::Matchers.define :be_one_of do |*expected| - match do |actual| - expected.include? actual - end - - failure_message_for_should do |actual| - "expected #{actual.inspect} to be one of #{expected.map(&:inspect).join(' or ')}" - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/modules.rb b/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/modules.rb deleted file mode 100755 index 910c6d9..0000000 --- a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/modules.rb +++ /dev/null @@ -1,27 +0,0 @@ -#! /usr/bin/env ruby -S rspec -module PuppetSpec::Modules - class << self - def create(name, dir, options = {}) - module_dir = File.join(dir, name) - FileUtils.mkdir_p(module_dir) - - environment = options[:environment] - - if metadata = options[:metadata] - metadata[:source] ||= 'github' - metadata[:author] ||= 'puppetlabs' - metadata[:version] ||= '9.9.9' - metadata[:license] ||= 'to kill' - metadata[:dependencies] ||= [] - - metadata[:name] = "#{metadata[:author]}/#{name}" - - File.open(File.join(module_dir, 'metadata.json'), 'w') do |f| - f.write(metadata.to_pson) - end - end - - Puppet::Module.new(name, module_dir, environment) - end - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/pops.rb b/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/pops.rb deleted file mode 100755 index e056a52..0000000 --- a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/pops.rb +++ /dev/null @@ -1,17 +0,0 @@ -#! /usr/bin/env ruby -S rspec -module PuppetSpec::Pops - extend RSpec::Matchers::DSL - - # Checks if an Acceptor has a specific issue in its list of diagnostics - matcher :have_issue do |expected| - match do |actual| - actual.diagnostics.index { |i| i.issue == expected } != nil - end - failure_message_for_should do |actual| - "expected Acceptor[#{actual.diagnostics.collect { |i| i.issue.issue_code }.join(',')}] to contain issue #{expected.issue_code}" - end - failure_message_for_should_not do |actual| - "expected Acceptor[#{actual.diagnostics.collect { |i| i.issue.issue_code }.join(',')}] to not contain issue #{expected.issue_code}" - end - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/scope.rb b/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/scope.rb deleted file mode 100755 index 3847ede..0000000 --- a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/scope.rb +++ /dev/null @@ -1,15 +0,0 @@ -#! /usr/bin/env ruby -S rspec - -module PuppetSpec::Scope - # Initialize a new scope suitable for testing. - # - def create_test_scope_for_node(node_name) - node = Puppet::Node.new(node_name) - compiler = Puppet::Parser::Compiler.new(node) - scope = Puppet::Parser::Scope.new(compiler) - scope.source = Puppet::Resource::Type.new(:node, node_name) - scope.parent = compiler.topscope - scope - end - -end \ No newline at end of file diff --git a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/settings.rb b/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/settings.rb deleted file mode 100755 index 8ddcb97..0000000 --- a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/settings.rb +++ /dev/null @@ -1,16 +0,0 @@ -#! /usr/bin/env ruby -S rspec -module PuppetSpec::Settings - - # It would probably be preferable to refactor defaults.rb such that the real definitions of - # these settings were available as a variable, which was then accessible for use during tests. - # However, I'm not doing that yet because I don't want to introduce any additional moving parts - # to this already very large changeset. - # Would be nice to clean this up later. --cprice 2012-03-20 - TEST_APP_DEFAULT_DEFINITIONS = { - :name => { :default => "test", :desc => "name" }, - :logdir => { :type => :directory, :default => "test", :desc => "logdir" }, - :confdir => { :type => :directory, :default => "test", :desc => "confdir" }, - :vardir => { :type => :directory, :default => "test", :desc => "vardir" }, - :rundir => { :type => :directory, :default => "test", :desc => "rundir" }, - } -end diff --git a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/verbose.rb b/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/verbose.rb deleted file mode 100755 index b2683df..0000000 --- a/puphpet/puppet/modules/stdlib/spec/lib/puppet_spec/verbose.rb +++ /dev/null @@ -1,10 +0,0 @@ -#! /usr/bin/env ruby -S rspec -# Support code for running stuff with warnings disabled. -module Kernel - def with_verbose_disabled - verbose, $VERBOSE = $VERBOSE, nil - result = yield - $VERBOSE = verbose - return result - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/puppetlabs_spec_helper_clone.rb b/puphpet/puppet/modules/stdlib/spec/puppetlabs_spec_helper_clone.rb new file mode 100644 index 0000000..6a94a3b --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/puppetlabs_spec_helper_clone.rb @@ -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 /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 + diff --git a/puphpet/puppet/modules/stdlib/spec/spec_helper.rb b/puphpet/puppet/modules/stdlib/spec/spec_helper.rb index b490ca3..416036b 100755 --- a/puphpet/puppet/modules/stdlib/spec/spec_helper.rb +++ b/puphpet/puppet/modules/stdlib/spec/spec_helper.rb @@ -10,25 +10,40 @@ module PuppetSpec require 'puppet' require 'rspec-puppet' require 'puppetlabs_spec_helper/module_spec_helper' -require 'puppet_spec/verbose' -require 'puppet_spec/files' -require 'puppet_spec/settings' -require 'puppet_spec/fixtures' -require 'puppet_spec/matchers' -require 'puppet_spec/database' require 'monkey_patches/alias_should_to_must' -require 'mocha/setup' - +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::Util::Loader.any_instance.stubs(:load_all) 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 diff --git a/puphpet/puppet/modules/stdlib/spec/spec_helper_acceptance.rb b/puphpet/puppet/modules/stdlib/spec/spec_helper_acceptance.rb index 3203ce9..eda0d1a 100755 --- a/puphpet/puppet/modules/stdlib/spec/spec_helper_acceptance.rb +++ b/puphpet/puppet/modules/stdlib/spec/spec_helper_acceptance.rb @@ -1,28 +1,10 @@ #! /usr/bin/env ruby -S rspec require 'beaker-rspec' +require 'beaker/puppet_install_helper' UNSUPPORTED_PLATFORMS = [] -unless ENV['RS_PROVISION'] == 'no' or ENV['BEAKER_provision'] == 'no' - foss_opts = { - :default_action => 'gem_install', - :version => (ENV['PUPPET_VERSION'] ? ENV['PUPPET_VERSION'] : '3.7.2'), - } - - if default.is_pe?; then install_pe; else install_puppet( foss_opts ); end - - hosts.each do |host| - if host['platform'] !~ /windows/i - if host.is_pe? - on host, 'mkdir -p /etc/puppetlabs/facter/facts.d' - else - on host, "/bin/touch #{host['puppetpath']}/hiera.yaml" - on host, "mkdir -p #{host['distmoduledir']}" - on host, 'mkdir -p /etc/facter/facts.d' - end - end - end -end +run_puppet_install_helper RSpec.configure do |c| # Project root @@ -33,7 +15,7 @@ # Configure all nodes in nodeset c.before :suite do - if ENV['FUTURE_PARSER'] == 'true' + if ENV['FUTURE_PARSER'] == 'yes' default[:default_apply_opts] ||= {} default[:default_apply_opts].merge!({:parser => 'future'}) end @@ -43,8 +25,46 @@ end def is_future_parser_enabled? - if default[:default_apply_opts] + if default[:type] == 'aio' + return true + elsif default[:default_apply_opts] return default[:default_apply_opts][:parser] == 'future' end return false end + +def get_puppet_version + (on default, puppet('--version')).output.chomp +end + +RSpec.shared_context "with faked facts" do + let(:facts_d) do + puppet_version = get_puppet_version + 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 diff --git a/puphpet/puppet/modules/stdlib/spec/unit/facter/package_provider_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/facter/package_provider_spec.rb new file mode 100644 index 0000000..3954faf --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/unit/facter/package_provider_spec.rb @@ -0,0 +1,44 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' +require 'puppet/type' +require 'puppet/type/package' + +describe 'package_provider', :type => :fact do + before { Facter.clear } + after { Facter.clear } + + ['4.2.2', '3.7.1 (Puppet Enterprise 3.2.1)'].each do |puppetversion| + describe "on puppet ''#{puppetversion}''" do + before :each do + Facter.stubs(:value).returns puppetversion + end + + context "darwin" do + it "should return pkgdmg" do + provider = Puppet::Type.type(:package).provider(:pkgdmg) + Puppet::Type.type(:package).stubs(:defaultprovider).returns provider + + expect(Facter.fact(:package_provider).value).to eq('pkgdmg') + end + end + + context "centos 7" do + it "should return yum" do + provider = Puppet::Type.type(:package).provider(:yum) + Puppet::Type.type(:package).stubs(:defaultprovider).returns provider + + expect(Facter.fact(:package_provider).value).to eq('yum') + end + end + + context "ubuntu" do + it "should return apt" do + provider = Puppet::Type.type(:package).provider(:apt) + Puppet::Type.type(:package).stubs(:defaultprovider).returns provider + + expect(Facter.fact(:package_provider).value).to eq('apt') + end + end + end + end +end diff --git a/puphpet/puppet/modules/stdlib/spec/unit/facter/pe_version_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/facter/pe_version_spec.rb index 4d0349e..c11a1cd 100755 --- a/puphpet/puppet/modules/stdlib/spec/unit/facter/pe_version_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/unit/facter/pe_version_spec.rb @@ -14,6 +14,17 @@ Facter.collection.loader.load(:pe_version) end end + + context "When puppetversion is nil" do + before :each do + Facter.fact(:puppetversion).stubs(:value).returns(nil) + end + + it "pe_version is nil" do + expect(Facter.fact(:puppetversion).value).to be_nil + expect(Facter.fact(:pe_version).value).to be_nil + end + end context "If PE is installed" do %w{ 2.6.1 2.10.300 }.each do |version| @@ -73,4 +84,5 @@ expect(Facter.fact(:pe_patch_version).value).to be_nil end end + end diff --git a/puphpet/puppet/modules/stdlib/spec/unit/facter/root_home_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/facter/root_home_spec.rb index 98fe141..a5c2846 100755 --- a/puphpet/puppet/modules/stdlib/spec/unit/facter/root_home_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/unit/facter/root_home_spec.rb @@ -49,4 +49,17 @@ 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 diff --git a/puphpet/puppet/modules/stdlib/spec/unit/facter/service_provider_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/facter/service_provider_spec.rb new file mode 100644 index 0000000..ad8a5fc --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/unit/facter/service_provider_spec.rb @@ -0,0 +1,37 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' +require 'puppet/type' +require 'puppet/type/service' + +describe 'service_provider', :type => :fact do + before { Facter.clear } + after { Facter.clear } + + context "macosx" do + it "should return launchd" do + provider = Puppet::Type.type(:service).provider(:launchd) + Puppet::Type.type(:service).stubs(:defaultprovider).returns provider + + expect(Facter.fact(:service_provider).value).to eq('launchd') + end + end + + context "systemd" do + it "should return systemd" do + provider = Puppet::Type.type(:service).provider(:systemd) + Puppet::Type.type(:service).stubs(:defaultprovider).returns provider + + expect(Facter.fact(:service_provider).value).to eq('systemd') + end + end + + context "redhat" do + it "should return redhat" do + provider = Puppet::Type.type(:service).provider(:redhat) + Puppet::Type.type(:service).stubs(:defaultprovider).returns provider + + expect(Facter.fact(:service_provider).value).to eq('redhat') + end + end + +end diff --git a/puphpet/puppet/modules/stdlib/spec/unit/facter/util/puppet_settings_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/facter/util/puppet_settings_spec.rb index c06137d..c278b79 100755 --- a/puphpet/puppet/modules/stdlib/spec/unit/facter/util/puppet_settings_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/unit/facter/util/puppet_settings_spec.rb @@ -25,6 +25,7 @@ module Puppet; end before :each do Puppet.expects(:[]).with(:vardir).returns vardir end + it 'should yield to the block' do subject.with_puppet { Puppet[:vardir] } end diff --git a/puphpet/puppet/modules/stdlib/spec/unit/puppet/functions/type_of_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/puppet/functions/type_of_spec.rb deleted file mode 100644 index 8afb624..0000000 --- a/puphpet/puppet/modules/stdlib/spec/unit/puppet/functions/type_of_spec.rb +++ /dev/null @@ -1,33 +0,0 @@ -#! /usr/bin/env ruby -S rspec - -require 'spec_helper' - -if ENV["FUTURE_PARSER"] == 'yes' or Puppet.version >= "4" - require 'puppet/pops' - require 'puppet/loaders' - - describe 'the type_of function' do - before(:all) do - loaders = Puppet::Pops::Loaders.new(Puppet::Node::Environment.create(:testing, [File.join(fixtures, "modules")])) - Puppet.push_context({:loaders => loaders}, "test-examples") - end - - after(:all) do - Puppet::Pops::Loaders.clear - Puppet::pop_context() - end - - let(:func) do - # Load the function from the environment modulepath's modules (ie, fixtures) - Puppet.lookup(:loaders).private_environment_loader.load(:function, 'type_of') - end - - it 'gives the type of a string' do - expect(func.call({}, 'hello world')).to be_kind_of(Puppet::Pops::Types::PStringType) - end - - it 'gives the type of an integer' do - expect(func.call({}, 5)).to be_kind_of(Puppet::Pops::Types::PIntegerType) - end - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/basename_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/basename_spec.rb deleted file mode 100755 index 8a2d0dc..0000000 --- a/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/basename_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -#! /usr/bin/env ruby -S rspec -require 'spec_helper' - -describe "the basename function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - Puppet::Parser::Functions.function("basename").should == "function_basename" - end - - it "should raise a ParseError if there is less than 1 argument" do - lambda { scope.function_basename([]) }.should( raise_error(Puppet::ParseError)) - end - - it "should raise a ParseError if there are more than 2 arguments" do - lambda { scope.function_basename(['a', 'b', 'c']) }.should( raise_error(Puppet::ParseError)) - end - - it "should return basename for an absolute path" do - result = scope.function_basename(['/path/to/a/file.ext']) - result.should(eq('file.ext')) - end - - it "should return basename for a relative path" do - result = scope.function_basename(['path/to/a/file.ext']) - result.should(eq('file.ext')) - end - - it "should strip extention when extension specified (absolute path)" do - result = scope.function_basename(['/path/to/a/file.ext', '.ext']) - result.should(eq('file')) - end - - it "should strip extention when extension specified (relative path)" do - result = scope.function_basename(['path/to/a/file.ext', '.ext']) - result.should(eq('file')) - end - - it "should complain about non-string first argument" do - lambda { scope.function_basename([[]]) }.should( raise_error(Puppet::ParseError)) - end - - it "should complain about non-string second argument" do - lambda { scope.function_basename(['/path/to/a/file.ext', []]) }.should( raise_error(Puppet::ParseError)) - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/bool2str_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/bool2str_spec.rb deleted file mode 100755 index b878891..0000000 --- a/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/bool2str_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -#! /usr/bin/env ruby -S rspec -require 'spec_helper' - -describe "the bool2str function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("bool2str")).to eq("function_bool2str") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_bool2str([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should convert true to 'true'" do - result = scope.function_bool2str([true]) - expect(result).to(eq('true')) - end - - it "should convert true to a string" do - result = scope.function_bool2str([true]) - expect(result.class).to(eq(String)) - end - - it "should convert false to 'false'" do - result = scope.function_bool2str([false]) - expect(result).to(eq('false')) - end - - it "should convert false to a string" do - result = scope.function_bool2str([false]) - expect(result.class).to(eq(String)) - end - - it "should not accept a string" do - expect { scope.function_bool2str(["false"]) }.to( raise_error(Puppet::ParseError)) - end - - it "should not accept a nil value" do - expect { scope.function_bool2str([nil]) }.to( raise_error(Puppet::ParseError)) - end - - it "should not accept an undef" do - expect { scope.function_bool2str([:undef]) }.to( raise_error(Puppet::ParseError)) - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/camelcase_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/camelcase_spec.rb deleted file mode 100755 index 70382ad..0000000 --- a/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/camelcase_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -#! /usr/bin/env ruby -S rspec -require 'spec_helper' - -describe "the camelcase function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("camelcase")).to eq("function_camelcase") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_camelcase([]) }.to( raise_error(Puppet::ParseError)) - end - - it "should capitalize the beginning of a normal string" do - result = scope.function_camelcase(["abc"]) - expect(result).to(eq("Abc")) - end - - it "should camelcase an underscore-delimited string" do - result = scope.function_camelcase(["aa_bb_cc"]) - expect(result).to(eq("AaBbCc")) - end -end diff --git a/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/is_absolute_path_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/is_absolute_path_spec.rb new file mode 100644 index 0000000..8931208 --- /dev/null +++ b/puphpet/puppet/modules/stdlib/spec/unit/puppet/parser/functions/is_absolute_path_spec.rb @@ -0,0 +1,86 @@ +require 'spec_helper' + +describe :is_absolute_path do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + let(:function_args) do + [] + end + + let(:function) do + scope.function_is_absolute_path(function_args) + end + + + describe 'validate arity' do + let(:function_args) do + [1,2] + end + it "should raise a ParseError if there is more than 1 arguments" do + lambda { function }.should( raise_error(ArgumentError)) + end + + end + + it "should exist" do + Puppet::Parser::Functions.function(subject).should == "function_#{subject}" + end + + # help enforce good function defination + it 'should contain arity' do + + end + + it "should raise a ParseError if there is less than 1 arguments" do + lambda { function }.should( raise_error(ArgumentError)) + end + + + describe 'should retrun true' do + let(:return_value) do + true + end + + describe 'windows' do + let(:function_args) do + ['c:\temp\test.txt'] + end + it 'should return data' do + function.should eq(return_value) + end + end + + describe 'non-windows' do + let(:function_args) do + ['/temp/test.txt'] + end + + it 'should return data' do + function.should eq(return_value) + end + end + end + + describe 'should return false' do + let(:return_value) do + false + end + describe 'windows' do + let(:function_args) do + ['..\temp\test.txt'] + end + it 'should return data' do + function.should eq(return_value) + end + end + + describe 'non-windows' do + let(:function_args) do + ['../var/lib/puppet'] + end + it 'should return data' do + function.should eq(return_value) + end + end + end +end \ No newline at end of file diff --git a/puphpet/puppet/modules/stdlib/spec/unit/puppet/provider/file_line/ruby_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/puppet/provider/file_line/ruby_spec.rb index d2a129c..23e649c 100755 --- a/puphpet/puppet/modules/stdlib/spec/unit/puppet/provider/file_line/ruby_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/unit/puppet/provider/file_line/ruby_spec.rb @@ -36,8 +36,7 @@ expect(File.read(tmpfile).chomp).to eq('foo') end end - - context "when matching" do + 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: @@ -46,12 +45,64 @@ @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*=.*$', + :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 @@ -69,11 +120,11 @@ 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 + :name => 'foo', + :path => @tmpfile, + :line => 'foo = bar', + :match => '^foo\s*=.*$', + :multiple => true, } ) @provider = provider_class.new(@resource) @@ -89,11 +140,11 @@ expect { @resource = Puppet::Type::File_line.new( { - :name => 'foo', - :path => @tmpfile, - :line => 'foo = bar', - :match => '^foo\s*=.*$', - :multiple => 'asgadga' + :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\./) @@ -140,7 +191,54 @@ 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| @@ -154,7 +252,7 @@ end end - context 'with two lines matching the after expression' do + 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") @@ -164,6 +262,22 @@ 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 @@ -194,7 +308,12 @@ @tmpfile = tmp.path tmp.close! @resource = Puppet::Type::File_line.new( - {:name => 'foo', :path => @tmpfile, :line => 'foo', :ensure => 'absent' } + { + :name => 'foo', + :path => @tmpfile, + :line => 'foo', + :ensure => 'absent', + } ) @provider = provider_class.new(@resource) end @@ -222,4 +341,100 @@ 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 diff --git a/puphpet/puppet/modules/stdlib/spec/unit/puppet/type/file_line_spec.rb b/puphpet/puppet/modules/stdlib/spec/unit/puppet/type/file_line_spec.rb index 410d0bf..f1430f2 100755 --- a/puphpet/puppet/modules/stdlib/spec/unit/puppet/type/file_line_spec.rb +++ b/puphpet/puppet/modules/stdlib/spec/unit/puppet/type/file_line_spec.rb @@ -49,6 +49,9 @@ 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 diff --git a/puphpet/puppet/modules/stdlib/tests/init.pp b/puphpet/puppet/modules/stdlib/tests/init.pp deleted file mode 100644 index 9675d83..0000000 --- a/puphpet/puppet/modules/stdlib/tests/init.pp +++ /dev/null @@ -1 +0,0 @@ -include stdlib diff --git a/puphpet/puppet/modules/supervisord/.gitignore b/puphpet/puppet/modules/supervisord/.gitignore new file mode 100644 index 0000000..cda60c7 --- /dev/null +++ b/puphpet/puppet/modules/supervisord/.gitignore @@ -0,0 +1,7 @@ +Gemfile.lock +pkg/* +spec/fixtures +.rspec_system/ +.rvmrc +.vagrant +.bundle diff --git a/puphpet/puppet/modules/swap_file/.gitignore b/puphpet/puppet/modules/swap_file/.gitignore new file mode 100644 index 0000000..2264a4b --- /dev/null +++ b/puphpet/puppet/modules/swap_file/.gitignore @@ -0,0 +1,4 @@ +.*.sw? +pkg +spec/fixtures +.rspec_system diff --git a/puphpet/puppet/modules/timezone/.fixtures.yml b/puphpet/puppet/modules/timezone/.fixtures.yml new file mode 100644 index 0000000..5f2717c --- /dev/null +++ b/puphpet/puppet/modules/timezone/.fixtures.yml @@ -0,0 +1,7 @@ +fixtures: + repositories: + stdlib: + repo: https://github.com/puppetlabs/puppetlabs-stdlib.git + ref: 4.1.0 + symlinks: + timezone: "#{source_dir}" diff --git a/puphpet/puppet/modules/timezone/.gitignore b/puphpet/puppet/modules/timezone/.gitignore new file mode 100644 index 0000000..559171e --- /dev/null +++ b/puphpet/puppet/modules/timezone/.gitignore @@ -0,0 +1,6 @@ +pkg/ +*.swp +Gemfile.lock +spec/fixtures +/coverage/ +.vagrant diff --git a/puphpet/puppet/modules/timezone/.rspec b/puphpet/puppet/modules/timezone/.rspec new file mode 100644 index 0000000..6278ec5 --- /dev/null +++ b/puphpet/puppet/modules/timezone/.rspec @@ -0,0 +1,3 @@ +--format documentation +--color +--tty diff --git a/puphpet/puppet/modules/timezone/.travis.yml b/puphpet/puppet/modules/timezone/.travis.yml new file mode 100644 index 0000000..ef0bc98 --- /dev/null +++ b/puphpet/puppet/modules/timezone/.travis.yml @@ -0,0 +1,37 @@ +--- +branches: + only: + - master +language: ruby +bundler_args: --without development +script: bundle exec rake test +after_success: + - git clone -q git://github.com/puppetlabs/ghpublisher.git .forge-releng + - .forge-releng/publish +rvm: + - 1.8.7 + - 1.9.3 +env: + matrix: + - PUPPET_GEM_VERSION="~> 2.7.0" + - PUPPET_GEM_VERSION="~> 3.0.0" + - PUPPET_GEM_VERSION="~> 3.1.0" + - PUPPET_GEM_VERSION="~> 3.2.0" + - PUPPET_GEM_VERSION="~> 3.3.0" + - PUPPET_GEM_VERSION="~> 3.4.0" + global: + - PUBLISHER_LOGIN=saz + - secure: |- + XYhK2TXSAjVeXWONjNpxKrKA6ogF5kazF/81eP5i0FzRoXUI+yemSYsrlA8oIRZjL6qrfCIT + UYKBYeySBrJ4qM9K36mTiqOx1VuevAuM8GRTy4h52lx0MHa/puFvHwKbMbjkBVurhyyZg8mL + cAtGs+KU2/oehrdBgyVfgQ08M9E= +matrix: + include: + - rvm: 2.0.0 + env: PUPPET_GEM_VERSION="~> 3.2.0" + - rvm: 2.0.0 + env: PUPPET_GEM_VERSION="~> 3.3.0" + - rvm: 2.0.0 + env: PUPPET_GEM_VERSION="~> 3.4.0" +notifications: + email: false diff --git a/puphpet/puppet/modules/timezone/Gemfile b/puphpet/puppet/modules/timezone/Gemfile new file mode 100644 index 0000000..d7dce94 --- /dev/null +++ b/puphpet/puppet/modules/timezone/Gemfile @@ -0,0 +1,16 @@ +source 'https://rubygems.org' + +group :development, :test do + gem 'rake', :require => false + gem 'puppet-lint', :require => false + gem 'puppet-syntax', :require => false + gem 'rspec-puppet', :require => false, :git => 'https://github.com/rodjek/rspec-puppet.git' + gem 'rspec', '< 3.0.0', :require => false + gem 'puppetlabs_spec_helper', :require => false +end + +if puppetversion = ENV['PUPPET_GEM_VERSION'] + gem 'puppet', puppetversion, :require => false +else + gem 'puppet', :require => false +end diff --git a/puphpet/puppet/modules/timezone/LICENSE b/puphpet/puppet/modules/timezone/LICENSE new file mode 100644 index 0000000..57bc88a --- /dev/null +++ b/puphpet/puppet/modules/timezone/LICENSE @@ -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. + diff --git a/puphpet/puppet/modules/timezone/README.md b/puphpet/puppet/modules/timezone/README.md new file mode 100644 index 0000000..2469644 --- /dev/null +++ b/puphpet/puppet/modules/timezone/README.md @@ -0,0 +1,23 @@ +# puppet-timezone [![Build Status](https://secure.travis-ci.org/saz/puppet-timezone.png)](http://travis-ci.org/saz/puppet-timezone) + +Manage timezone settings via Puppet + +## Usage + +### Set timezone to UTC +``` + class { 'timezone': + timezone => 'UTC', + } +``` + +### Set timezone to Europe/Berlin +``` + class { 'timezone': + timezone => 'Europe/Berlin', + } +``` + +## Other class parameters +* ensure: present or absent, default: present +* autoupgrade: true or false, default: false. Auto-upgrade package, if there is a newer version diff --git a/puphpet/puppet/modules/timezone/Rakefile b/puphpet/puppet/modules/timezone/Rakefile new file mode 100644 index 0000000..cf5bfdb --- /dev/null +++ b/puphpet/puppet/modules/timezone/Rakefile @@ -0,0 +1,24 @@ +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-syntax/tasks/puppet-syntax' +require 'puppet-lint/tasks/puppet-lint' + +exclude_paths = [ + "pkg/**/*", + "vendor/**/*", + "spec/**/*", +] + +PuppetLint.configuration.send("disable_80chars") +PuppetLint.configuration.send('disable_class_inherits_from_params_class') +PuppetLint.configuration.log_format = "%{path}:%{linenumber}:%{check}:%{KIND}:%{message}" +PuppetLint.configuration.fail_on_warnings = true + +PuppetLint.configuration.ignore_paths = exclude_paths +PuppetSyntax.exclude_paths = exclude_paths + +desc "Run syntax, lint, and spec tests." +task :test => [ + :syntax, + :lint, + :spec, +] diff --git a/puphpet/puppet/modules/timezone/manifests/init.pp b/puphpet/puppet/modules/timezone/manifests/init.pp new file mode 100644 index 0000000..e01435d --- /dev/null +++ b/puphpet/puppet/modules/timezone/manifests/init.pp @@ -0,0 +1,109 @@ +# Class: timezone +# +# This module manages timezone settings +# +# Parameters: +# [*timezone*] +# The name of the timezone. +# Default: UTC +# +# [*ensure*] +# Ensure if present or absent. +# Default: present +# +# [*autoupgrade*] +# Upgrade package automatically, if there is a newer version. +# Default: false +# +# [*package*] +# Name of the package. +# Only set this, if your platform is not supported or you know, what you're doing. +# Default: auto-set, platform specific +# +# [*config_file*] +# Main configuration file. +# Only set this, if your platform is not supported or you know, what you're doing. +# Default: auto-set, platform specific +# +# [*zoneinfo_dir*] +# Source directory of zoneinfo files. +# Only set this, if your platform is not supported or you know, what you're doing. +# Default: auto-set, platform specific +# +# [*hwutc*] +# Is the hardware clock set to UTC? (true or false) +# Default: undefined +# +# Actions: +# Installs tzdata and configures timezone +# +# Requires: +# Nothing +# +# Sample Usage: +# class { 'timezone': +# timezone => 'Europe/Berlin', +# } +# +# [Remember: No empty lines between comments and class definition] +class timezone ( + $ensure = 'present', + $timezone = 'UTC', + $hwutc = '', + $autoupgrade = false +) inherits timezone::params { + + validate_bool($autoupgrade) + + case $ensure { + /(present)/: { + if $autoupgrade == true { + $package_ensure = 'latest' + } else { + $package_ensure = 'present' + } + $localtime_ensure = 'link' + $timezone_ensure = 'file' + } + /(absent)/: { + # Leave package installed, as it is a system dependency + $package_ensure = 'present' + $localtime_ensure = 'absent' + $timezone_ensure = 'absent' + } + default: { + fail('ensure parameter must be present or absent') + } + } + + if $timezone::params::package { + package { $timezone::params::package: + ensure => $package_ensure, + before => File[$timezone::params::localtime_file], + } + } + + if $timezone::params::timezone_file != false { + file { $timezone::params::timezone_file: + ensure => $timezone_ensure, + content => template($timezone::params::timezone_file_template), + } + if $ensure == 'present' and $timezone::params::timezone_update { + $e_command = $::osfamily ? { + /(Suse|Archlinux)/ => "${timezone::params::timezone_update} ${timezone}", + default => $timezone::params::timezone_update + } + exec { 'update_timezone': + command => $e_command, + path => '/usr/bin:/usr/sbin:/bin:/sbin', + subscribe => File[$timezone::params::timezone_file], + refreshonly => true, + } + } + } + + file { $timezone::params::localtime_file: + ensure => $localtime_ensure, + target => "${timezone::params::zoneinfo_dir}${timezone}", + } +} diff --git a/puphpet/puppet/modules/timezone/manifests/params.pp b/puphpet/puppet/modules/timezone/manifests/params.pp new file mode 100644 index 0000000..db5125a --- /dev/null +++ b/puphpet/puppet/modules/timezone/manifests/params.pp @@ -0,0 +1,68 @@ +# Class: timezone::params +# +# Defines all the variables used in the module. +# +class timezone::params { + case $::osfamily { + 'Debian': { + $package = 'tzdata' + $zoneinfo_dir = '/usr/share/zoneinfo/' + $localtime_file = '/etc/localtime' + $timezone_file = '/etc/timezone' + $timezone_file_template = 'timezone/timezone.erb' + $timezone_file_supports_comment = false + $timezone_update = 'dpkg-reconfigure -f noninteractive tzdata' + } + 'RedHat', 'Linux': { + $package = 'tzdata' + $zoneinfo_dir = '/usr/share/zoneinfo/' + $localtime_file = '/etc/localtime' + case $::operatingsystemmajrelease { + '7': { + $timezone_file = false + } + default: { + $timezone_file = '/etc/sysconfig/clock' + } + } + $timezone_file_template = 'timezone/clock.erb' + $timezone_update = false + } + 'Gentoo': { + $package = 'sys-libs/timezone-data' + $zoneinfo_dir = '/usr/share/zoneinfo/' + $localtime_file = '/etc/localtime' + $timezone_file = '/etc/timezone' + $timezone_file_template = 'timezone/timezone.erb' + $timezone_file_supports_comment = true + $timezone_update = 'emerge --config timezone-data' + } + 'Archlinux': { + $package = 'tzdata' + $zoneinfo_dir = '/usr/share/zoneinfo/' + $localtime_file = '/etc/localtime' + $timezone_file = false + $timezone_update = 'timedatectl set-timezone ' + } + 'Suse': { + $package = 'timezone' + $zoneinfo_dir = '/usr/share/zoneinfo/' + $localtime_file = '/etc/localtime' + $timezone_file = false + $timezone_update = 'zic -l ' + } + 'FreeBSD': { + $package = undef + $zoneinfo_dir = '/usr/share/zoneinfo/' + $localtime_file = '/etc/localtime' + $timezone_file = false + } + default: { + case $::operatingsystem { + default: { + fail("Unsupported platform: ${::osfamily}/${::operatingsystem}") + } + } + } + } +} diff --git a/puphpet/puppet/modules/timezone/metadata.json b/puphpet/puppet/modules/timezone/metadata.json new file mode 100644 index 0000000..9935c6c --- /dev/null +++ b/puphpet/puppet/modules/timezone/metadata.json @@ -0,0 +1,52 @@ +{ + "operatingsystem_support": [ + { + "operatingsystem": "RedHat" + }, + { + "operatingsystem": "CentOS" + }, + { + "operatingsystem": "OracleLinux" + }, + { + "operatingsystem": "Scientific" + }, + { + "operatingsystem": "Debian" + }, + { + "operatingsystem": "Ubuntu" + }, + { + "operatingsystem": "Gentoo" + }, + { + "operatingsystem": "ArchLinux" + } + ], + "requirements": [ + { + "name": "pe", + "version_requirement": "3.2.x" + }, + { + "name": "puppet", + "version_requirement": "3.x" + } + ], + "name": "saz-timezone", + "version": "3.3.0", + "source": "git://github.com/saz/puppet-timezone", + "author": "saz", + "license": "Apache License, Version 2.0", + "summary": "UNKNOWN", + "description": "Manage timezone settings via Puppet", + "project_page": "https://github.com/saz/puppet-timezone", + "dependencies": [ + { + "name": "puppetlabs/stdlib", + "version_requirement": ">= 2.3.0" + } + ] +} diff --git a/puphpet/puppet/modules/timezone/spec/classes/timezone_spec.rb b/puphpet/puppet/modules/timezone/spec/classes/timezone_spec.rb new file mode 100644 index 0000000..31292e8 --- /dev/null +++ b/puphpet/puppet/modules/timezone/spec/classes/timezone_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +describe 'timezone' do + ['Debian','RedHat','Gentoo','FreeBSD'].each do |osfamily| + describe "on supported osfamily: #{osfamily}" do + include_examples osfamily + end + end +end diff --git a/puphpet/puppet/modules/timezone/spec/spec_helper.rb b/puphpet/puppet/modules/timezone/spec/spec_helper.rb new file mode 100644 index 0000000..c2f9f56 --- /dev/null +++ b/puphpet/puppet/modules/timezone/spec/spec_helper.rb @@ -0,0 +1,8 @@ +require 'puppetlabs_spec_helper/module_spec_helper' +require 'pathname' + +dir = Pathname.new(__FILE__).parent +# Load all shared contexts and shared examples +Dir["#{dir}/support/**/*.rb"].sort.each {|f| require f} + +at_exit { RSpec::Puppet::Coverage.report! } diff --git a/puphpet/puppet/modules/timezone/spec/support/debian.rb b/puphpet/puppet/modules/timezone/spec/support/debian.rb new file mode 100644 index 0000000..921aa05 --- /dev/null +++ b/puphpet/puppet/modules/timezone/spec/support/debian.rb @@ -0,0 +1,49 @@ +shared_examples 'Debian' do + let(:facts) {{ :osfamily => "Debian" }} + + describe "when using default class parameters" do + let(:params) {{ }} + + it { should create_class('timezone') } + it { should contain_class('timezone::params') } + + it do + should contain_package('tzdata').with({ + :ensure => 'present', + :before => "File[/etc/localtime]", + }) + end + + it { should contain_file('/etc/timezone').with_ensure('file') } + it { should contain_file('/etc/timezone').with_content(/^UTC$/) } + it { should contain_exec('update_timezone').with_command(/^dpkg-reconfigure -f noninteractive tzdata$/) } + + it do + should contain_file('/etc/localtime').with({ + :ensure => 'link', + :target => '/usr/share/zoneinfo/UTC', + }) + end + + context 'when timezone => "Europe/Berlin"' do + let(:params) {{ :timezone => "Europe/Berlin" }} + + it { should contain_file('/etc/timezone').with_content(/^Europe\/Berlin$/) } + it { should contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } + end + + context 'when autoupgrade => true' do + let(:params) {{ :autoupgrade => true }} + it { should contain_package('tzdata').with_ensure('latest') } + end + + context 'when ensure => absent' do + let(:params) {{ :ensure => 'absent' }} + it { should contain_package('tzdata').with_ensure('present') } + it { should contain_file('/etc/timezone').with_ensure('absent') } + it { should contain_file('/etc/localtime').with_ensure('absent') } + end + + include_examples 'validate parameters' + end +end diff --git a/puphpet/puppet/modules/timezone/spec/support/freebsd.rb b/puphpet/puppet/modules/timezone/spec/support/freebsd.rb new file mode 100644 index 0000000..694801e --- /dev/null +++ b/puphpet/puppet/modules/timezone/spec/support/freebsd.rb @@ -0,0 +1,34 @@ +shared_examples 'FreeBSD' do + let(:facts) {{ :osfamily => "FreeBSD" }} + + describe "when using default class parameters" do + let(:params) {{ }} + + it { should create_class('timezone') } + it { should contain_class('timezone::params') } + + it do + should contain_file('/etc/localtime').with({ + :ensure => 'link', + :target => '/usr/share/zoneinfo/UTC', + }) + end + + context 'when timezone => "Europe/Berlin"' do + let(:params) {{ :timezone => "Europe/Berlin" }} + + it { should contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } + end + + context 'when autoupgrade => true' do + let(:params) {{ :autoupgrade => true }} + end + + context 'when ensure => absent' do + let(:params) {{ :ensure => 'absent' }} + it { should contain_file('/etc/localtime').with_ensure('absent') } + end + + include_examples 'validate parameters' + end +end diff --git a/puphpet/puppet/modules/timezone/spec/support/gentoo.rb b/puphpet/puppet/modules/timezone/spec/support/gentoo.rb new file mode 100644 index 0000000..eaf8192 --- /dev/null +++ b/puphpet/puppet/modules/timezone/spec/support/gentoo.rb @@ -0,0 +1,48 @@ +shared_examples 'Gentoo' do + let(:facts) {{ :osfamily => "Gentoo" }} + + describe "when using default class parameters" do + let(:params) {{ }} + + it { should create_class('timezone') } + it { should contain_class('timezone::params') } + + it do + should contain_package('sys-libs/timezone-data').with({ + :ensure => 'present', + :before => 'File[/etc/localtime]', + }) + end + + it { should contain_file('/etc/timezone').with_ensure('file') } + it { should contain_file('/etc/timezone').with_content(/^UTC$/) } + it { should contain_exec('update_timezone').with_command(/^emerge --config timezone-data$/) } + it do + should contain_file('/etc/localtime').with({ + :ensure => 'link', + :target => '/usr/share/zoneinfo/UTC', + }) + end + + context 'when timezone => "Europe/Berlin"' do + let(:params) {{ :timezone => "Europe/Berlin" }} + + it { should contain_file('/etc/timezone').with_content(/^Europe\/Berlin$/) } + it { should contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } + end + + context 'when autoupgrade => true' do + let(:params) {{ :autoupgrade => true }} + it { should contain_package('sys-libs/timezone-data').with_ensure('latest') } + end + + context 'when ensure => absent' do + let(:params) {{ :ensure => 'absent' }} + it { should contain_package('sys-libs/timezone-data').with_ensure('present') } + it { should contain_file('/etc/timezone').with_ensure('absent') } + it { should contain_file('/etc/localtime').with_ensure('absent') } + end + + include_examples 'validate parameters' + end +end diff --git a/puphpet/puppet/modules/timezone/spec/support/redhat.rb b/puphpet/puppet/modules/timezone/spec/support/redhat.rb new file mode 100644 index 0000000..d24ce99 --- /dev/null +++ b/puphpet/puppet/modules/timezone/spec/support/redhat.rb @@ -0,0 +1,55 @@ +shared_examples 'RedHat' do + let(:facts) {{ :osfamily => "RedHat", :operatingsystemmajrelease => '6' }} + + describe "when using default class parameters" do + let(:params) {{ }} + + it { should create_class('timezone') } + it { should contain_class('timezone::params') } + + it do + should contain_package('tzdata').with({ + :ensure => 'present', + :before => 'File[/etc/localtime]', + }) + end + + + it { should contain_file('/etc/sysconfig/clock').with_ensure('file') } + it { should contain_file('/etc/sysconfig/clock').with_content(/^ZONE="UTC"$/) } + it { should_not contain_exec('update_timezone') } + + it do + should contain_file('/etc/localtime').with({ + :ensure => 'link', + :target => '/usr/share/zoneinfo/UTC', + }) + end + + context 'when timezone => "Europe/Berlin"' do + let(:params) {{ :timezone => "Europe/Berlin" }} + + it { should contain_file('/etc/sysconfig/clock').with_content(/^ZONE="Europe\/Berlin"$/) } + it { should contain_file('/etc/localtime').with_target('/usr/share/zoneinfo/Europe/Berlin') } + end + + context 'when autoupgrade => true' do + let(:params) {{ :autoupgrade => true }} + it { should contain_package('tzdata').with_ensure('latest') } + end + + context 'when ensure => absent' do + let(:params) {{ :ensure => 'absent' }} + it { should contain_package('tzdata').with_ensure('present') } + it { should contain_file('/etc/sysconfig/clock').with_ensure('absent') } + it { should contain_file('/etc/localtime').with_ensure('absent') } + end + + context 'when RHEL 7' do + let(:facts) {{ :osfamily => "RedHat", :operatingsystemmajrelease => '7' }} + it { should_not contain_file('/etc/sysconfig/clock').with_ensure('file') } + end + + include_examples 'validate parameters' + end +end diff --git a/puphpet/puppet/modules/timezone/spec/support/validate_params.rb b/puphpet/puppet/modules/timezone/spec/support/validate_params.rb new file mode 100644 index 0000000..a49540f --- /dev/null +++ b/puphpet/puppet/modules/timezone/spec/support/validate_params.rb @@ -0,0 +1,10 @@ +shared_examples_for 'validate parameters' do + [ + 'autoupgrade', + ].each do |param| + context "with #{param} => 'foo'" do + let(:params) {{ param.to_sym => 'foo' }} + it { expect { should create_class('timezone') }.to raise_error(Puppet::Error, /is not a boolean/) } + end + end +end diff --git a/puphpet/puppet/modules/timezone/templates/clock.erb b/puphpet/puppet/modules/timezone/templates/clock.erb new file mode 100644 index 0000000..3c8b183 --- /dev/null +++ b/puphpet/puppet/modules/timezone/templates/clock.erb @@ -0,0 +1,5 @@ +# Managed by puppet - do not modify +ZONE="<%= @timezone %>" +<% if !@hwutc.empty? -%> +UTC=<%= @hwutc %> +<% end -%> diff --git a/puphpet/puppet/modules/timezone/templates/timezone.erb b/puphpet/puppet/modules/timezone/templates/timezone.erb new file mode 100644 index 0000000..f03a823 --- /dev/null +++ b/puphpet/puppet/modules/timezone/templates/timezone.erb @@ -0,0 +1,4 @@ +<%- if @timezone_file_supports_comment -%> +# Managed by puppet - do not modify +<%- end -%> +<%= @timezone %> diff --git a/puphpet/puppet/modules/timezone/tests/init.pp b/puphpet/puppet/modules/timezone/tests/init.pp new file mode 100644 index 0000000..07794dc --- /dev/null +++ b/puphpet/puppet/modules/timezone/tests/init.pp @@ -0,0 +1 @@ +include timezone diff --git a/puphpet/puppet/modules/vcsrepo/.gitignore b/puphpet/puppet/modules/vcsrepo/.gitignore new file mode 100644 index 0000000..ddd2d45 --- /dev/null +++ b/puphpet/puppet/modules/vcsrepo/.gitignore @@ -0,0 +1,4 @@ +coverage +.DS_Store +.#* +\#* diff --git a/puphpet/puppet/modules/yum/.fixtures.yml b/puphpet/puppet/modules/yum/.fixtures.yml index bb90cc1..75b2e55 100644 --- a/puphpet/puppet/modules/yum/.fixtures.yml +++ b/puphpet/puppet/modules/yum/.fixtures.yml @@ -1,10 +1,10 @@ fixtures: repositories: - "puppi": "git://github.com/example42/puppi.git" - "monitor": "git://github.com/example42/puppet-monitor.git" - "firewall": "git://github.com/example42/puppet-firewall.git" - "iptables": "git://github.com/example42/puppet-iptables.git" - "concat": "git://github.com/example42/puppet-concat.git" + "puppi": "https://github.com/example42/puppi.git" + "monitor": "https://github.com/example42/puppet-monitor.git" + "firewall": "https://github.com/example42/puppet-firewall.git" + "iptables": "https://github.com/example42/puppet-iptables.git" + "concat": "https://github.com/example42/puppet-concat.git" symlinks: "yum": "#{source_dir}" diff --git a/puphpet/puppet/modules/yum/.gemfile b/puphpet/puppet/modules/yum/.gemfile index 87be9a1..5e01bf6 100644 --- a/puphpet/puppet/modules/yum/.gemfile +++ b/puphpet/puppet/modules/yum/.gemfile @@ -3,5 +3,5 @@ source 'https://rubygems.org' puppetversion = ENV['PUPPET_VERSION'] gem 'puppet', puppetversion, :require => false gem 'puppet-lint' +gem 'rspec', '~> 3.1.0', :platforms => :ruby_18 gem 'puppetlabs_spec_helper', '>= 0.1.0' -gem 'rspec-puppet', '0.1.6' diff --git a/puphpet/puppet/modules/yum/.gitignore b/puphpet/puppet/modules/yum/.gitignore new file mode 100644 index 0000000..6eebfd2 --- /dev/null +++ b/puphpet/puppet/modules/yum/.gitignore @@ -0,0 +1,12 @@ +/.gradle +/.rvmrc +build +pkg/ +Session.vim +spec/fixtures +.*.sw[a-z] +*.un~ +.gemfile.lock +.bundle +vendor + diff --git a/puphpet/puppet/modules/yum/.travis.yml b/puphpet/puppet/modules/yum/.travis.yml index e4068f5..de6cd04 100644 --- a/puphpet/puppet/modules/yum/.travis.yml +++ b/puphpet/puppet/modules/yum/.travis.yml @@ -2,20 +2,43 @@ language: ruby rvm: - 1.8.7 - 1.9.3 + - 2.1.4 env: - PUPPET_VERSION="~> 2.6.0" - PUPPET_VERSION="~> 2.7.0" - PUPPET_VERSION="~> 3.0.0" - PUPPET_VERSION="~> 3.1.0" + - PUPPET_VERSION="~> 3.6.0" + - PUPPET_VERSION="~> 3.8.0" + - PUPPET_VERSION="~> 4.2" script: - - "rake spec SPEC_OPTS='--format documentation'" + - "bundle exec rake lint spec SPEC_OPTS='--format documentation'" matrix: exclude: + - rvm: 1.8.7 + env: PUPPET_VERSION="~> 4.2" - rvm: 1.9.3 env: PUPPET_VERSION="~> 2.6.0" gemfile: .gemfile + - rvm: 2.1.4 + env: PUPPET_VERSION="~> 2.6.0" + - rvm: 2.1.4 + env: PUPPET_VERSION="~> 2.7.0" + - rvm: 2.1.4 + env: PUPPET_VERSION="~> 3.0.0" + - rvm: 2.1.4 + env: PUPPET_VERSION="~> 3.1.0" + allow_failures: + - rvm: 1.8.7 + env: PUPPET_VERSION="~> 2.6.0" + - rvm: 1.8.7 + env: PUPPET_VERSION="~> 2.7.0" + - rvm: 1.9.3 + env: PUPPET_VERSION="~> 2.7.0" + gemfile: .gemfile +sudo: false notifications: email: - - al@lab42.it + - al@example42.com diff --git a/puphpet/puppet/modules/yum/Modulefile b/puphpet/puppet/modules/yum/Modulefile deleted file mode 100644 index e49c5cb..0000000 --- a/puphpet/puppet/modules/yum/Modulefile +++ /dev/null @@ -1,9 +0,0 @@ -name 'example42-yum' -version '2.1.16' -author 'Alessandro Franceschi' -license 'Apache2' -project_page 'http://www.example42.com' -source 'https://github.com/example42/puppet-yum' -summary 'Puppet module for yum' -description 'This module installs and manages yum and yum repositories' -dependency 'example42/puppi', '> 2.0.0' diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-CentOS-7 b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-CentOS-7 new file mode 100644 index 0000000..47f6d4d --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-CentOS-7 @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.5 (GNU/Linux) + +mQINBFOn/0sBEADLDyZ+DQHkcTHDQSE0a0B2iYAEXwpPvs67cJ4tmhe/iMOyVMh9 +Yw/vBIF8scm6T/vPN5fopsKiW9UsAhGKg0epC6y5ed+NAUHTEa6pSOdo7CyFDwtn +4HF61Esyb4gzPT6QiSr0zvdTtgYBRZjAEPFVu3Dio0oZ5UQZ7fzdZfeixMQ8VMTQ +4y4x5vik9B+cqmGiq9AW71ixlDYVWasgR093fXiD9NLT4DTtK+KLGYNjJ8eMRqfZ +Ws7g7C+9aEGHfsGZ/SxLOumx/GfiTloal0dnq8TC7XQ/JuNdB9qjoXzRF+faDUsj +WuvNSQEqUXW1dzJjBvroEvgTdfCJfRpIgOrc256qvDMp1SxchMFltPlo5mbSMKu1 +x1p4UkAzx543meMlRXOgx2/hnBm6H6L0FsSyDS6P224yF+30eeODD4Ju4BCyQ0jO +IpUxmUnApo/m0eRelI6TRl7jK6aGqSYUNhFBuFxSPKgKYBpFhVzRM63Jsvib82rY +438q3sIOUdxZY6pvMOWRkdUVoz7WBExTdx5NtGX4kdW5QtcQHM+2kht6sBnJsvcB +JYcYIwAUeA5vdRfwLKuZn6SgAUKdgeOtuf+cPR3/E68LZr784SlokiHLtQkfk98j +NXm6fJjXwJvwiM2IiFyg8aUwEEDX5U+QOCA0wYrgUQ/h8iathvBJKSc9jQARAQAB +tEJDZW50T1MtNyBLZXkgKENlbnRPUyA3IE9mZmljaWFsIFNpZ25pbmcgS2V5KSA8 +c2VjdXJpdHlAY2VudG9zLm9yZz6JAjUEEwECAB8FAlOn/0sCGwMGCwkIBwMCBBUC +CAMDFgIBAh4BAheAAAoJECTGqKf0qA61TN0P/2730Th8cM+d1pEON7n0F1YiyxqG +QzwpC2Fhr2UIsXpi/lWTXIG6AlRvrajjFhw9HktYjlF4oMG032SnI0XPdmrN29lL +F+ee1ANdyvtkw4mMu2yQweVxU7Ku4oATPBvWRv+6pCQPTOMe5xPG0ZPjPGNiJ0xw +4Ns+f5Q6Gqm927oHXpylUQEmuHKsCp3dK/kZaxJOXsmq6syY1gbrLj2Anq0iWWP4 +Tq8WMktUrTcc+zQ2pFR7ovEihK0Rvhmk6/N4+4JwAGijfhejxwNX8T6PCuYs5Jiv +hQvsI9FdIIlTP4XhFZ4N9ndnEwA4AH7tNBsmB3HEbLqUSmu2Rr8hGiT2Plc4Y9AO +aliW1kOMsZFYrX39krfRk2n2NXvieQJ/lw318gSGR67uckkz2ZekbCEpj/0mnHWD +3R6V7m95R6UYqjcw++Q5CtZ2tzmxomZTf42IGIKBbSVmIS75WY+cBULUx3PcZYHD +ZqAbB0Dl4MbdEH61kOI8EbN/TLl1i077r+9LXR1mOnlC3GLD03+XfY8eEBQf7137 +YSMiW5r/5xwQk7xEcKlbZdmUJp3ZDTQBXT06vavvp3jlkqqH9QOE8ViZZ6aKQLqv +pL+4bs52jzuGwTMT7gOR5MzD+vT0fVS7Xm8MjOxvZgbHsAgzyFGlI1ggUQmU7lu3 +uPNL0eRx4S1G4Jn5 +=OGYX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-EPEL b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-EPEL new file mode 100644 index 0000000..7a20304 --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-EPEL @@ -0,0 +1,29 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.5 (GNU/Linux) + +mQINBEvSKUIBEADLGnUj24ZVKW7liFN/JA5CgtzlNnKs7sBg7fVbNWryiE3URbn1 +JXvrdwHtkKyY96/ifZ1Ld3lE2gOF61bGZ2CWwJNee76Sp9Z+isP8RQXbG5jwj/4B +M9HK7phktqFVJ8VbY2jfTjcfxRvGM8YBwXF8hx0CDZURAjvf1xRSQJ7iAo58qcHn +XtxOAvQmAbR9z6Q/h/D+Y/PhoIJp1OV4VNHCbCs9M7HUVBpgC53PDcTUQuwcgeY6 +pQgo9eT1eLNSZVrJ5Bctivl1UcD6P6CIGkkeT2gNhqindRPngUXGXW7Qzoefe+fV +QqJSm7Tq2q9oqVZ46J964waCRItRySpuW5dxZO34WM6wsw2BP2MlACbH4l3luqtp +Xo3Bvfnk+HAFH3HcMuwdaulxv7zYKXCfNoSfgrpEfo2Ex4Im/I3WdtwME/Gbnwdq +3VJzgAxLVFhczDHwNkjmIdPAlNJ9/ixRjip4dgZtW8VcBCrNoL+LhDrIfjvnLdRu +vBHy9P3sCF7FZycaHlMWP6RiLtHnEMGcbZ8QpQHi2dReU1wyr9QgguGU+jqSXYar +1yEcsdRGasppNIZ8+Qawbm/a4doT10TEtPArhSoHlwbvqTDYjtfV92lC/2iwgO6g +YgG9XrO4V8dV39Ffm7oLFfvTbg5mv4Q/E6AWo/gkjmtxkculbyAvjFtYAQARAQAB +tCFFUEVMICg2KSA8ZXBlbEBmZWRvcmFwcm9qZWN0Lm9yZz6JAjYEEwECACAFAkvS +KUICGw8GCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRA7Sd8qBgi4lR/GD/wLGPv9 +qO39eyb9NlrwfKdUEo1tHxKdrhNz+XYrO4yVDTBZRPSuvL2yaoeSIhQOKhNPfEgT +9mdsbsgcfmoHxmGVcn+lbheWsSvcgrXuz0gLt8TGGKGGROAoLXpuUsb1HNtKEOwP +Q4z1uQ2nOz5hLRyDOV0I2LwYV8BjGIjBKUMFEUxFTsL7XOZkrAg/WbTH2PW3hrfS +WtcRA7EYonI3B80d39ffws7SmyKbS5PmZjqOPuTvV2F0tMhKIhncBwoojWZPExft +HpKhzKVh8fdDO/3P1y1Fk3Cin8UbCO9MWMFNR27fVzCANlEPljsHA+3Ez4F7uboF +p0OOEov4Yyi4BEbgqZnthTG4ub9nyiupIZ3ckPHr3nVcDUGcL6lQD/nkmNVIeLYP +x1uHPOSlWfuojAYgzRH6LL7Idg4FHHBA0to7FW8dQXFIOyNiJFAOT2j8P5+tVdq8 +wB0PDSH8yRpn4HdJ9RYquau4OkjluxOWf0uRaS//SUcCZh+1/KBEOmcvBHYRZA5J +l/nakCgxGb2paQOzqqpOcHKvlyLuzO5uybMXaipLExTGJXBlXrbbASfXa/yGYSAG +iVrGz9CE6676dMlm8F+s3XXE13QZrXmjloc6jwOljnfAkjTGXjiB7OULESed96MR +XtfLk0W5Ab9pd7tKDR6QHI7rgHXfCopRnZ2VVQ== +=V/6I +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-PGDG b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-PGDG new file mode 100644 index 0000000..8722c21 --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-PGDG @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.7 (GNU/Linux) + +mQGiBEeD8koRBACC1VBRsUwGr9gxFFRho9kZpdRUjBJoPhkeOTvp9LzkdAQMFngr +BFi6N0ov1kCX7LLwBmDG+JPR7N+XcH9YR1coSHpLVg+JNy2kFDd4zAyWxJafjZ3a +9zFg9Yx+0va1BJ2t4zVcmKS4aOfbgQ5KwIOWUujalQW5Y+Fw39Gn86qjbwCg5dIo +tkM0l19h2sx50D027pV5aPsD/2c9pfcFTbMhB0CcKS836GH1qY+NCAdUwPs646ee +Ex/k9Uy4qMwhl3HuCGGGa+N6Plyon7V0TzZuRGp/1742dE8IO+I/KLy2L1d1Fxrn +XOTBZd8qe6nBwh12OMcKrsPBVBxn+iSkaG3ULsgOtx+HHLfa1/p22L5+GzGdxizr +peBuA/90cCp+lYcEwdYaRoFVR501yDOTmmzBc1DrsyWP79QMEGzMqa393G0VnqXt +L4pGmunq66Agw2EhPcIt3pDYiCmEt/obdVtSJH6BtmSDB/zYhbE8u3vLP3jfFDa9 +KXxgtYj0NvuUVoRmxSKm8jtfmj1L7zoKNz3jl+Ba3L0WxIv4+bRBUG9zdGdyZVNR +TCBSUE0gQnVpbGRpbmcgUHJvamVjdCA8cGdzcWxycG1zLWhhY2tlcnNAcGdmb3Vu +ZHJ5Lm9yZz6IYAQTEQIAIAUCR4PySgIbIwYLCQgHAwIEFQIIAwQWAgMBAh4BAheA +AAoJEB8W0uFELfD4jnkAoMqd6ZwwsgYHZ3hP9vt+DJt1uDW7AKDbRwP8ESKFhwdJ +8m91RPBeJW/tMLkCDQRHg/JKEAgA64+ZXgcERPYfZYo4p+yMTJAAa9aqnE3U4Ni6 +ZMB57GPuEy8NfbNya+HiftO8hoozmJdcI6XFyRBCDUVCdZ8SE+PJdOx2FFqZVIu6 +dKnr8ykhgLpNNEFDG3boK9UfLj/5lYQ3Y550Iym1QKOgyrJYeAp6sZ+Nx2PavsP3 +nMFCSD67BqAbcLCVQN7a2dAUXfEbfXJjPHXTbo1/kxtzE+KCRTLdXEbSEe3nHO04 +K/EgTBjeBUOxnciH5RylJ2oGy/v4xr9ed7R1jJtshsDKMdWApwoLlCBJ63jg/4T/ +z/OtXmu4AvmWaJxaTl7fPf2GqSqqb6jLCrQAH7AIhXr9V0zPZwADBQgAlpptNQHl +u7euIdIujFwwcxyQGfee6BG+3zaNSEHMVQMuc6bxuvYmgM9r7aki/b0YMfjJBk8v +OJ3Eh1vDH/woJi2iJ13vQ21ot+1JP3fMd6NPR8/qEeDnmVXu7QAtlkmSKI9Rdnjz +FFSUJrQPHnKsH4V4uvAM+njwYD+VFiwlBPTKNeL8cdBb4tPN2cdVJzoAp57wkZAN +VA2tKxNsTJKBi8wukaLWX8+yPHiWCNWItvyB4WCEp/rZKG4A868NM5sZQMAabpLd +l4fTiGu68OYgK9qUPZvhEAL2C1jPDVHPkLm+ZsD+90Pe66w9vB00cxXuHLzm8Pad +GaCXCY8h3xi6VIhJBBgRAgAJBQJHg/JKAhsMAAoJEB8W0uFELfD4K4cAoJ4yug8y +1U0cZEiF5W25HDzMTtaDAKCaM1m3Cbd+AZ0NGWNg/VvIX9MsPA== +=au6K +-----END PGP PUBLIC KEY BLOCK----- + diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-RBEL b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-RBEL new file mode 100644 index 0000000..152fd79 --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-RBEL @@ -0,0 +1,36 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.14 (GNU/Linux) + +mQGiBEZ6qawRBAC2gDuA1sZioGh1VP/U0l+9RmzOdkWBGB3NfWqezAwt1Up+cP5o +h+UNkghOKbJVQ/zLyY/edYOppQ78yxT1X/J1RHNhs5bjqzWlQxMbT5/tt1N4PExu +gvO38RGFTV0DqIy3lQw5YIwp2le+G8MktYh2NKI4lG0AJoXZicNlI7+mEwCgmfw+ +CnsB/kb/xUD1dq6Mo3dYXVcEAKSFfqt+6jvJNxcIYfpQqjEslQsQmPKpXzK9CPyV +UCjUEOirbhPxV86u3Ge/yuy5USMvTTs+ztImabbH6UHBEP+tEw3LiuPUpfh+nEna +3Hz+U81PvUwGEwUMzCr+OemBXqGW7jl66NqKqm8YM3Pkvc4NlS/7slky9A/s6i8S +hToWA/9kP55aSbIXte5TbC88lx6YuLx7qW541ni38DmJfPN5hHywLGnM82MMQMbk +hg1v49+7TTNv44LJpGT7t8gsW9F4Z4rWoChhsldypeeqbDOIv4kFiXt/8122Ud9J +nE67CR9XUuS5Jp+gP6xxNr9/vbvqsOGMJAQkVgkBPVuKYv25gLQ3U2VyZ2lvIFJ1 +YmlvIChGcmFtZU9TIERldmVsb3BlcnMpIDxydWJpb2pyQGZyYW1lb3Mub3JnPohr +BBMRAgArAhsDBQkGE0x0BgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAUCTBs76AIZ +AQAKCRCOw9dP80W+dFhjAJ0dKy761iPcG+ALwEAuAgxDpUVBzgCdFxGCAZ7ELYvf +3uFc0Ou2ihDzvyy0IFNlcmdpbyBSdWJpbyA8c2VyZ2lvQHJ1YmlvLm5hbWU+iGYE +ExECACYCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAUJBhNMdAUCTBs7XgAKCRCO +w9dP80W+dDdtAJ9NYoW1ChfMyES7nQUlesEQ4aWXjQCeIoGxoOuIGyg6+AKr/2Wr +6fE1zt2IaQQTEQIAKQIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAhkBBQJIHsGo +BQkCuHFEAAoJEI7D10/zRb50KjgAnRTzzNIODKqrHnrHaUG8dWDCwmYjAJ48Hbcn +ZC6E8LGTeM8vPN0mMI9ijLkCDQRGeqm2EAgAh720kjA9bNDms+6agb6CirD9RkmZ +3G+OHd5iia3KbaUiBtC3PECg4UE8N54JuBNKdjgJQfdYSg2J0EZHyhZHdAVWjykE +tj/IKZKnAfUqKh44uT9OUPW8PChPo/gioLn+DexSAW7n19h7VIa1P3shYqYR/gz8 +zgfrXkFFpkpKnOLsXuF20JEEBIBdwrfYRJIBrUTYrfS/2GKLJjyutENkb9uI3JgQ +LfR6DckTaar4eeArjgvOxZRHiU0vRezetlbG8ZM9mSYrcMM3Xa5vLpFlDj6vYzat +RWEuZUfLgXWUVoVyFiNVXhpff/w7/bAb3WpXqjZd6sK8CCJJPNtnbLE7CwADBQf9 +EQjT9iiEZis35V9HqeLsxXVjPOGNuLiwjIpacI7CM3aGV1q7NXiCE4oWS/PvpHmu +W+XdXMPH4Bt2VmjZSarlAipTeNnOuiEXipUFIjAlNn1xNVRRd7T35zIvXLtmNtUe +nN1/mqZljKPbCbW1AgktH417t/vJfTnRWr9IgS3Am+o4q200i+1FjrQ/UI3s9+vg +5B+KASFP6HspNttl0kwzQ6SFIHAebd4DKHOj6ShxXPNl18W4R8qPqayrAFqdkgMJ +Jn8j2E8rmGYnssSfjck2kLtvNdTEAMjFnhg+oUapUzJAVeterudiWZFNrtn9ewnf +8SUiiYJlxb+nz545zo0gQIhJBBgRAgAJBQJGeqm2AhsMAAoJEI7D10/zRb50PJEA +mwTA+Sp3wvzwDr8sk7W7U4bBfw26AKCVoYw3mfTime+j3mFk1yk1yxjE2Q== +=iyOs +-----END PGP PUBLIC KEY BLOCK----- + diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-beta b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-beta new file mode 100644 index 0000000..b86da23 --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-beta @@ -0,0 +1,28 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.6 (GNU/Linux) + +mQGiBEWfBuERBACrwDH+6QvpyaOgzhXiemsIX+q4HlhX/HDmrmZOUd7i9VmZNogP +6LRRiTygn2+UphaGV3NDA36ZB/1JRpgvgpzbpZNeAoFvsljIbxGIwkH2JgRF6oNo +eGB3QYzDQJvYVIejk79M0ed3oor4w8OiNVcdxLyVIthFrjrrCqwRP3bLZwCgtY9t +Ezf5WL63Ue45vdht7A2GH+0D/iNAnWKsU7FUMFZrcwMaMbyP7YG8z0+zXUOgtgyP +tbgJG5yikNT3vJypb42gbKfcriUUDC5AeiRmkR8QPvYuOm34rM90+wx2LGqXWnHM +IyLAyl8TS3MQmePem8bfTGTNYxtt3Q7iadez2WYTLBSlmM6hbxZfdwm1hhyM0AJU +YyFUA/9kHH+CUBxKb1UgG7TSp53Po/5p/Yyuty+RJ7zIGv6SiN/JK4/ntWfm5WS5 +ZprSdE5ODoFQ/Gs3/VB/eolg2fBW1DcftH6lKHT3GKEOaicGX+T9eOMerZZedm5U +vDA9mFvWnOdOxK8LuRgVqip4jCnWICchpatmdP0whJQHQ6MGLLRMQ2VudE9TLTUg +QmV0YSBLZXkgKENlbnRPUyA1IEJldGEgU2lnbmluZyBLZXkpIDxjZW50b3MtNS1i +ZXRhLWtleUBjZW50b3Mub3JnPohkBBMRAgAkBQJFnwbhAhsDBQkSzAMABgsJCAcD +AgMVAgMDFgIBAh4BAheAAAoJEM/aaIEJLXsrWDkAoKcqa+AAdAWvp5qlJkGQiRy8 +aNFDAJ4qRfIxMiLinmjbqcuygWMp61wY5ohMBBMRAgAMBQJFnwhtBYMSzAF0AAoJ +EDjCFhY5bKCkG/wAn14LDlJqjZv1Wz0WNfhr80+qJrf6AKCaIZExwo4ApQpESk/F +SApLd/pEILkBDQRFnwbrEAQAwKzjI2aTB/sS9HuQ4CHCwrj4vr0HxMMwQikYBIvy +MYTtek04KDTKoJL5g3411DsfDW9VRGJdFCHvldgam/5UVfO6nywLkdwAA5TQA5dv +8YE8jTtwdy5Y1QKFc8LaIBZK0+ZbhEvdNfv67egvfcxZc5PvpBZ3C03n+iQ3wPcg +PhcAAwUD/iYkq4LG/je43Qa5rTz5kF5rIiX7Bk5vXT7XSFOFKwHy8V+PGEoVM1W8 ++EHIlmTycwIlsVp3by6qCDkMYu4V6VukxZNzJyeoMICiYIXUPh6NKHRoqaYlu6ZO +eFN1TQNXmodPk+iNtdbcby/zAklNqoO/dWSwd8NAo8s6WAHq3VPpiE8EGBECAA8F +AkWfBusCGwwFCRLMAwAACgkQz9pogQkteysXkACgoraCU0EBC+W8TuxrsePO20ma +D0IAoLRRQLTEXL0p3K0WE+LfyTr9EVG5 +=mH0S +-----END PGP PUBLIC KEY BLOCK----- + diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-kbsingh b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-kbsingh new file mode 100644 index 0000000..f8c688e --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-kbsingh @@ -0,0 +1,25 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.6 (GNU/Linux) + +mQGiBEIu6hwRBACOz2JFa1nW+seAKlVGOu0ykhdFVNI9E4/Abp2+8nsJIZyUwLAp +ei76rPD8WdptgIjtYOCsqz1TbP+eqeEG0LLihOdFRLUuAjQX4X7LLf5Qm+nvUB73 +uLbSf9Ptps2CMUEtu7+0wVoTbuC19HXUhUr5sRdCnJbPJBH6aAHG7Pl9ZwCguN9o +V7IKTnIQiZg0nxSjZ4V9e6UD/R7KoMwH3NPQQF7T7rJaBjSZcVHUPhAcNPNn+ms/ +Tw9mzHZ0mnQnOzSEW0ZUj9TkLN52VQ3WmGZKAv9yeVr0/230YIgmtH863lSystmk +LNO9brK0+3vKg5GRpV0/MSWSmf39WPAS1hXNXIFfYp1eGHUfed4FVNxrMTWHQozr +8JosA/wP+zGfM51bSAazLUqP/MEm7F9OFkuD7Sw97w55FyYlrPp1FQWrWczoiKHr +wS5NRCQbCGEEM/+j9id6CukxPLXxwMYCfeg5K0HxMaQT6hxbwjOzAzN3PBFytNel +09qdrdoSDa35twT0SAt+rzM+zvRI8ycizFG3lIih4UItWWve2bQ6S2FyYW5iaXIg +U2luZ2ggKGh0dHA6Ly93d3cua2FyYW4ub3JnLykgPGtic2luZ2hAa2FyYW4ub3Jn +PoheBBMRAgAeBQJCLuocAhsDBgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEDANvZ4+ +E89b/P4AnjufrDCS+TAEL0KpkYDURePbDCHBAJ4+0iI1Td4YrcnLwmQ1+XDCJ3Zr +a7kBDQRCLuocEAQAjAl48FM9eGtP6M9FgswlSPAuCcJct6wOHmd/qZ923HckJPAD +zIFRMlM6H8P0bKoaIluv7agZM7Gsf8NeTg3NEeMKqnibIAyvjYeSkceRIwvBCQ3A +YwWk+B2zLUAFMxnE31oA10zjCKUo7Dc6XDUxSY/qdLymZzyG/Ndav+vMOVsAAwUD +/RCFDuW/GSM/s3DO7XxrOBRTGQmf9v9tCYdZZD615+s8ghaa5oZTvp1cbTTWiSq8 +ybncfjVHz9HezDgQjJsFZtrYd4w2JD+7K0+8sZ+BUGo1dDSv4UgN8ACtaGJnShiq +s8pQWRZFqFa3waay8oUSTKHiTHdpxLi3x4HhK/8MTsxniEkEGBECAAkFAkIu6hwC +GwwACgkQMA29nj4Tz1tHSgCcDgKL4swEu7ShvI8nZt2JLmTKB5QAn0qZi2zbexbi +DX+bbalHM+xVnXZN +=rZT6 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-remi b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-remi new file mode 100644 index 0000000..3283386 --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-remi @@ -0,0 +1,24 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.7 (GNU/Linux) + +mQGiBEJny1wRBACRnbQgZ6qLmJSuGvi/EwrRL6aW610BbdpLQRL3dnwy5wI5t9T3 +/JEiEJ7GTvAwfiisEHifMfk2sRlWRf2EDQFttHyrrYXfY5L6UAF2IxixK5FL7PWA +/2a7tkw1IbCbt4IGG0aZJ6/xgQejrOLi4ewniqWuXCc+tLuWBZrGpE2QfwCggZ+L +0e6KPTHMP97T4xV81e3Ba5MD/3NwOQh0pVvZlW66Em8IJnBgM+eQh7pl4xq7nVOh +dEMJwVU0wDRKkXqQVghOxALOSAMapj5mDppEDzGLZHZNSRcvGEs2iPwo9vmY+Qhp +AyEBzE4blNR8pwPtAwL0W3cBKUx7ZhqmHr2FbNGYNO/hP4tO2ochCn5CxSwAfN1B +Qs5pBACOkTZMNC7CLsSUT5P4+64t04x/STlAFczEBcJBLF1T16oItDITJmAsPxbY +iee6JRfXmZKqmDP04fRdboWMcRjfDfCciSdIeGqP7vMcO25bDZB6x6++fOcmQpyD +1Fag3ZUq2yojgXWqVrgFHs/HB3QE7UQkykNp1fjQGbKK+5mWTrQkUmVtaSBDb2xs +ZXQgPFJQTVNARmFtaWxsZUNvbGxldC5jb20+iGAEExECACAFAkZ+MYoCGwMGCwkI +BwMCBBUCCAMEFgIDAQIeAQIXgAAKCRAATm9HAPl/Vv/UAJ9EL8ioMTsz/2EPbNuQ +MP5Xx/qPLACeK5rk2hb8VFubnEsbVxnxfxatGZ25AQ0EQmfLXRAEANwGvY+mIZzj +C1L5Nm2LbSGZNTN3NMbPFoqlMfmym8XFDXbdqjAHutGYEZH/PxRI6GC8YW5YK4E0 +HoBAH0b0F97JQEkKquahCakj0P5mGuH6Q8gDOfi6pHimnsSAGf+D+6ZwAn8bHnAa +o+HVmEITYi6s+Csrs+saYUcjhu9zhyBfAAMFA/9Rmfj9/URdHfD1u0RXuvFCaeOw +CYfH2/nvkx+bAcSIcbVm+tShA66ybdZ/gNnkFQKyGD9O8unSXqiELGcP8pcHTHsv +JzdD1k8DhdFNhux/WPRwbo/es6QcpIPa2JPjBCzfOTn9GXVdT4pn5tLG2gHayudK +8Sj1OI2vqGLMQzhxw4hJBBgRAgAJBQJCZ8tdAhsMAAoJEABOb0cA+X9WcSAAn11i +gC5ns/82kSprzBOU0BNwUeXZAJ0cvNmY7rvbyiJydyLsSxh/la6HKw== +=6Rbg +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-rpmforge-dag b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-rpmforge-dag new file mode 100644 index 0000000..8ee27f4 --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-rpmforge-dag @@ -0,0 +1,32 @@ +The following public key can be used to verify RPM packages +downloaded from http://dag.wieers.com/apt/ using 'rpm -K' +if you have the GNU GPG package. +Questions about this key should be sent to: +Dag Wieers + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.1 (GNU/Linux) + +mQGiBD9JMT0RBAC9Q2B0AloUMTxaK73sD0cOu1MMdD8yuDagbMlDtUYA1aGeJVO6 +TV02JLGr67OBY+UkYuC1c3PUwmb3+jakZd5bW1L8E2L705wS0129xQOZPz6J+alF +5rTzVkiefg8ch1yEcMayK20NdyOmhDGXQXNQS8OJFLTIC6bJs+7MZL83/wCg3cG3 +3q7MWHm3IpJb+6QKpB9YH58D/2WjPDK+7YIky/JbFBT4JPgTSBy611+bLqHA6PXq +39tzY6un8KDznAMNtm+NAsr6FEG8PHe406+tbgd7tBkecz3HPX8nR5v0JtDT+gzN +8fM3kAiAzjCHUAFWVAMAZLr5TXuoq4lGTTxvZbwTjZfyjCm7gIieCu8+qnPWh6hm +30NgA/0ZyEHG6I4rOWqPks4vZuD+wlp5XL8moBXEKfEVOMh2MCNDRGnvVHu1P3eD +oHOooVMt9sWrGcgxpYuupPNL4Uf6B6smiLlH6D4tEg+qCxC17zABI5572XJTJ170 +JklZJrPGtnkPrrKMamnN9MU4RjGmjh9JZPa7rKjZHyWP/z/CBrQ1RGFnIFdpZWVy +cyAoRGFnIEFwdCBSZXBvc2l0b3J5IHYxLjApIDxkYWdAd2llZXJzLmNvbT6IWQQT +EQIAGQUCP0kxPQQLBwMCAxUCAwMWAgECHgECF4AACgkQog5SFGuNeeYvDQCeKHST +hIq/WzFBXtJOnQkJGSqAoHoAnRtsJVWYmzYKHqzkRx1qAzL18Sd0iEYEEBECAAYF +Aj9JMWAACgkQoj2iXPqnmevnOACfRQaageMcESHVE1+RSuP3txPUvoEAoJAtOHon +g+3SzVNSZLn/g7/Ljfw+uQENBD9JMT8QBACj1QzRptL6hbpWl5DdQ2T+3ekEjJGt +llCwt4Mwt/yOHDhzLe8SzUNyYxTXUL4TPfFvVW9/j8WOkNGvffbs7g84k7a5h/+l +IJTTlP9V9NruDt1dlrBe+mWF6eCY55OFHjb6nOIkcJwKxRd3nGlWnLsz0ce9Hjrg +6lMrn0lPsMV6swADBQP9H42sss6mlqnJEFA97Fl3V9s+7UVJoAIA5uSVXxEOwVoh +Vq7uECQRvWzif6tzOY+vHkUxOBRvD6oIU6tlmuG3WByKyA1d0MTqMr3eWieSYf/L +n5VA9NuD7NwjFA1kLkoDwfSbsF51LppTMkUggzwgvwE46MB6yyuqAVI1kReAWw+I +RgQYEQIABgUCP0kxPwAKCRCiDlIUa4155oktAKDAzm9QYbDpk6SrQhkSFy016BjE +BACeJU1hpElFnUZCL4yKj4EuLnlo8kc= +=mqUt +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-webtatic-andy b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-webtatic-andy new file mode 100644 index 0000000..317b802 --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY-webtatic-andy @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.5 (GNU/Linux) + +mQGiBE1e+1MRBAD8j+KyOIpGNRN39gNy2E/1HG4ZoLFuxIOxI5/1FEuZB/GjYF5m +DvJerZukd0QCqCs72J6J+uWnfD/52t2XWTw4IHPpCWeyr9TWex3uOYmrYzY+0l0l +qsCsrhT0XGkAE0+/20oEP2+t/d+1q0yRcYZRwWK/ME2rUUX0jOa/B3Bc6wCg3blw +XdZNrv1wVNd1PCOUI79k0V0D+wfbybos8Cmdv2f8dD746fSR/hmp4SzpBDmPRRQu +0gtJAKI6ycTdotGq5zHfZj76kDQBudeIgdbWtqfckP2lK47i8lIENAyC4MK8dxh9 +Ts+b1LqXlbcPyixzImf4qoT5DT1lSEUPwoMRX8W/29GAcvnZpOwQ8g7DNmRBpFFY +8U2GBADz6uEeP3YwJAuL7pi77AalxR0WQAADMR59pGltQdXaZvANXoioU0W519Pb +nl3gKWDiTuwUDrwaSPoBbNLyX4s0AE7/0HSG02/eRjLB8toQpAH9xkK/u2WPe/do +erZg5yg1qhoCbEM7kJ2I/GBl6VbPedt2ORdsC4ZTWTnZJh6tYLQhQW5keSBUaG9t +cHNvbiA8YW5keUB3ZWJ0YXRpYy5jb20+iGAEExECACAFAk1e+1MCGwMGCwkIBwMC +BBUCCAMEFgIDAQIeAQIXgAAKCRC3Q0sGz0xP+TA0AJwJf5ZPeub8v+5CtZwdcZhV +LU0sjgCgrP3y54heBjF1vhZQ3rJywTmRLHe5Ag0ETV77UxAIAIQPLVFbqheJ90Kf +NF8TYt3ZIMpP5chw25OYq4tuZMzVJxKjUlM7KPQxUKquY/F9WpjH980LmICTb4Fz +txzn2bshIsGyg8pDUSnVK0NPY5uaq9bK4oht8wkr3FNFT2FpeqDIJyn+phIuEpIi +qt1LJyzzjobh9csaaGmNHvtrlkIggBj2n/ZQuGNhcYnKUZ/WGmkItCTSOfA++G+C +dCo1aPEymfbnJvaLB/mLyzA+r/r7LQM10cZEtqh5JdclJEh3CzZmx9HsRxCDZF8W +X/C4MmCwmIxmuU4vkVNhHFTQimQEUR8vg9ltiz8+xBjyE1Iav4MxfOYh3xjdJk1d +zlovyUcAAwUH/2KPgf0UQ1o+4IjOYinEEbNlrD1pKw5anUKwaaeQi0vm/oRG0E2F +ZCJ73OHxW/0hMrwbrGwXcm4NBARnAppg+/CecOVpkBgD5hrM+11DPhxdd1bjjfza +Pq8GmPp8SSsiTPUCoSlzojxL3Z05RNbvKVzxzxbYdx5h5XOTflI7bAHTY4AzGSDf +WaFljjCucht/d7u5empAd02haldUXWjT9RvY5RwnRZ+hjI47e+wUA0FMLHYtA1/0 +cwEIvpp2xwF/jpH3ODmnIGEeNoLyzAV7X0KAlSN8VRsh7igZRB9TRGI67aTjRgk8 +ayf/QNxAzwEk1MeDv67IFKNYVolxHCt4CtqISQQYEQIACQUCTV77UwIbDAAKCRC3 +Q0sGz0xP+dPiAKDUNJ5rkB9CRoMH9BC35d0fqXXeugCgwl/HYv52dWgatbyEGLet +etv5Qeg= +=nIAo +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY.art b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY.art new file mode 100644 index 0000000..825424e --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY.art @@ -0,0 +1,24 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.1 (GNU/Linux) + +mQGiBEGP+skRBACyZz7muj2OgWc9FxK+Hj7tWPnrfxEN+0PE+n8MtqH+dxwQpMTd +gDpOXxJa45GM5pEwB6CFSFK7Fb/faniF9fDbm1Ga7MpBupIBYLactkoOTZMuTlGB +T0O5ha4h26YLqFfQOtlEi7d0+BDDdfHRQw3o67ycgRnLgYSA79DISc3MywCgk2TR +yd5sRfZAG23b4EDl+D0+oaMEAK73J7zuxf6F6V5EaxLd/w4JVB2xW0Glcn0fACOe +8FV9lzcZuo2xPpdGuyj02f/xlqvEav3XqTfFU2no61mA2pamaRNhlo+CEfGc7qde +/1twfSgOYqzeCx7+aybyPo8Th41b80FT19mfkjBf6+5NbUHffRabFFh1FmcPVNBn +F3FoA/95nRIzqDMItdTRitaZn02dIGNjdwllBD75bSVEvaR9O5hjBo0VMc25DB7f +DM2qEO52wCQbAKw9zFC284ekZVDaK4aHYt7iobHaqJEpKHgsDut5WWuMiSLR+SsF +aBHIZ9HvrKWLSUQKHU6A1Hva0P0r3GnoCMc/VCVfrLl721SjPbQzQXRvbWljIFJv +Y2tldCBUdXJ0bGUgPGFkbWluQGF0b21pY3JvY2tldHR1cnRsZS5jb20+iFkEExEC +ABkFAkGP+skECwcDAgMVAgMDFgIBAh4BAheAAAoJEDKpURRevSdEzcQAn1hSHqTO +jwv/z/picpOnR+mgycwHAKCBex2ciyXo5xeaQ9w7OMf7Jsmon7kBDQRBj/rMEAQA +6JvRndqE4koK0e49fUkICm1X0ZEzsVg9VmUW+Zft5guCRxmGlYTmtlC7oJCToRP/ +m/xH5uIevGiJycRKB0Ix+Csl6f9QuTkQ7tSTHcaIKbI3tL1x6CCBoWeTGYaOJlvk +ubrmajiMFaBfopLH2firoSToDGoUvv4e7bImIHEgNr8AAwUEAND0YR9DOEZvc+Lq +Ta/PQyxkdZ75o+Ty/O64E3OmO1Tuw2ciSQXCcwrbrMSE6EHHetxtGCnOdkjjjtmH +AnxsxdONv/EJuQmLcoNcsigZZ4tfRdmtXgcbnOmXBgmy1ea1KvWcsmecNSAMJHwR +7vDDKzbj4mSmudzjapHeeOewFF10iEYEGBECAAYFAkGP+swACgkQMqlRFF69J0Sq +nQCfa/q9Y/oY4dOTGj6MsdmRIQkKZhYAoIscjinFwTru4FVi2MIEzUUMToDK +=NOIx +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY.atrpms b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY.atrpms new file mode 100644 index 0000000..860ace4 --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RPM-GPG-KEY.atrpms @@ -0,0 +1,20 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.6 (GNU/Linux) + +mQGiBD5gtCgRBACKIvjMF+20r9k/Uw2Hq6Y/qn1nM0AZEFalhglXP5pMm5bMgkcI +1vCWqJxSbhQhk8hSEenoszes8hyUxHj4hFFUDiRtAxOpCpGCsCnUddgQtHAQd+tm +aQsM6J3Jm/EZPtwR0lvwvRGvz2x6Rr95G8+42KK9x+mBYhLk0y3gAbBzhwCgnkDH +a97MGBT7gRLrmtFqiHrWlPkD/2tBaH6IEuoJhcAbNj9MukbhDOYJ6ic9Nzf6sR3t +ZG+XgQLLS2DNy8+HWcYJOjpJDEe8zWFDdUv3cL1D0U2f2e85FuJaMucHn+816iw8 +mNjZXJEoDE4LJ8Vv53fkevNZpdWmO2VtRwI+woDnIHYHukDLj2sWhVt+5W+uOKAE +OippA/9OzuWrwBtTR+Np8ApZGkxhxU1z0iEStV+kQNqJE7YoR4SGMuzEa3bFzrPx +k4qIU+rw4YgFgHrs1x08lXxNOZkq6avvbl60HqN2qF2UQL/YdU+5X3ixaJVaYYk8 +yuK+hp0Hx2DdBWmVhq6rEzIfpnFhF4qspwMWEiiBGjYDL62W7LQ0QVRycG1zLm5l +dCAocnBtIHNpZ25pbmcga2V5KSA8QXhlbC5UaGltbUBBVHJwbXMubmV0PohnBBMR +AgAnAhsDBgsJCAcDAgMVAgMDFgIBAh4BAheAAhkBBQJFfF9PBQkJGI4nAAoJEFCM +5eZmU0wrJ0IAnA0BdyRlq2S8ess55R8YMFnWAWXEAJ9Fa7cEHku4j4B83shCODps ++DYUZohnBBMRAgAnAhsDBQkDdMLsBgsJCAcDAgMVAgMDFgIBAh4BAheABQJAKteu +AhkBAAoJEFCM5eZmU0wrMMUAnRjS2PXQp0tsC/69IGMMxqU+8xeAAJ9XQjVAo+mU +kg/3AeBlMBIlFe5hDQ== +=23Fz +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RubyWorks.GPG.key b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RubyWorks.GPG.key new file mode 100644 index 0000000..b91a5a8 --- /dev/null +++ b/puphpet/puppet/modules/yum/files/CentOS.7/rpm-gpg/RubyWorks.GPG.key @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.6 (GNU/Linux) + +mQGiBEY5QQ0RBACfC1NbAdGFMOS/Y7P9hmNph2Wh3TJTh6IZpL+lTJBuZSEa6rp0 +CghS/yU3gGXUPaxAy91M7PXMv5p7S3U/SusZHATLhFdU5J4LuWMf4IiBy9FOB/aj +Q1s5vZ/i3YFaqolXsRP8TgIu4Lzp/j3+KAxFb3gF7lz64J/Et2Jil0OQzwCgkn9i +SoPEM6d9SCFOidhUuTHUhM0D/3UXl/FKPVFrFzjslFpaN9NgArRrmXKTOBWEqMLy +12pbTzOtv+p17Ot51q4h0ebEWrmVJ/h/7Is6QT6AKHuOIW+1/88fcSrmef//0Scz +wtEwVudkYA+kOGt1pwhapVYf1lWE9Z6L3V/MVdxXUesylGO6jJjOjpUB+ZBItwl7 +exkhA/4iemhq4D5Jp6r1Kv3aKSPNENdhTORyfZz4UfyOsUfYncaprP5IZja0j+rd +tQLIsH8hXvCT2kSAUY6nMGmzPgpgGamtHI6gH1ZmoNX2gEF7tzGNgKMbbUmwO89B +N56U7wm68AreXE8XviRjGjAtZWnouqe5X+EiUurdJkzRwU0c2rQpVGhvdWdodFdv +cmtzIDxydWJ5d29ya3NAdGhvdWdodHdvcmtzLmNvbT6IYAQTEQIAIAUCRjlBDQIb +AwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEHM/KlUQbeB0SSYAn0sgAx5ZK975 +wZiChkIqOCyFZ9PLAJ9laivkzqT2y+Kh9FGe3TP/CAhRTbkCDQRGOUEVEAgAqxJI +MFrYV3JKyeXHVKXHNd5Nf1WdqKi37VOdSTBftiehzZdR9hxkGEknYxnbBLGJR9YD +/uJ2+DRwNBcw2RrrEmb0DCZxcLQLZ3xYa7+WvcR4/Nir/3858SGJ+wmGCHKyX2So +M2TurmKu5bqyUUaBgf+IhKfwOr9zeK3rIRhUq/aiYkw8sWA8ruUvxXwLnbkK1aP9 +hfvSqScwjkfUVk6CQ6GFUD+4N4mNRtRcZz3gYa+0jSNeEJZQOJxRuE/gBHav3eyN +dm4VAFPF20BobvBVEcMhO0KaR/X4jW1G1eFAKLxI7cdx3+vLeNPaFwHiSMSknsNs +UiucI9oV+I5S/50ZrwADBwf/StYTK9KvPnY9ZqmirBpSh0Zl0xylMtAiMblG7pKv +qKTPNr9zXooheQBpAbnhOfju0DB/OtE4V21HqnbMws2aFvHecEbO5EmjwT7ZTltH +5vlbiPrXOc7SpP22FdkOYdunM2+nsA6398mpYFEiFFNAzX6pReN2tbbmXf6zxS9n +nHjMAgl5nMuOASLZrTrUX/7yu6ySS1hy0ZVfEoAFeILy4MV8y0lVjBQa2kNOCNpO +Cc+y1+4EHLS3fuN0x+tho3rhjKAzj8KOt4XnALn8OouRMx9G7ItC2U8kNzHHFRg5 +adT/+nEthVd9q9pYLrUaze7aMQyl+7cD1KzmSe34X9B6W4hJBBgRAgAJBQJGOUEV +AhsMAAoJEHM/KlUQbeB0O7QAn09h4qrKPhWD9eaiyMRS5YeARTYgAJ9WxLcQEvkA +yOSLb33CweehCrlTnQ== +=scSy +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-CentOS-7 b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-CentOS-7 new file mode 100644 index 0000000..47f6d4d --- /dev/null +++ b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-CentOS-7 @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.5 (GNU/Linux) + +mQINBFOn/0sBEADLDyZ+DQHkcTHDQSE0a0B2iYAEXwpPvs67cJ4tmhe/iMOyVMh9 +Yw/vBIF8scm6T/vPN5fopsKiW9UsAhGKg0epC6y5ed+NAUHTEa6pSOdo7CyFDwtn +4HF61Esyb4gzPT6QiSr0zvdTtgYBRZjAEPFVu3Dio0oZ5UQZ7fzdZfeixMQ8VMTQ +4y4x5vik9B+cqmGiq9AW71ixlDYVWasgR093fXiD9NLT4DTtK+KLGYNjJ8eMRqfZ +Ws7g7C+9aEGHfsGZ/SxLOumx/GfiTloal0dnq8TC7XQ/JuNdB9qjoXzRF+faDUsj +WuvNSQEqUXW1dzJjBvroEvgTdfCJfRpIgOrc256qvDMp1SxchMFltPlo5mbSMKu1 +x1p4UkAzx543meMlRXOgx2/hnBm6H6L0FsSyDS6P224yF+30eeODD4Ju4BCyQ0jO +IpUxmUnApo/m0eRelI6TRl7jK6aGqSYUNhFBuFxSPKgKYBpFhVzRM63Jsvib82rY +438q3sIOUdxZY6pvMOWRkdUVoz7WBExTdx5NtGX4kdW5QtcQHM+2kht6sBnJsvcB +JYcYIwAUeA5vdRfwLKuZn6SgAUKdgeOtuf+cPR3/E68LZr784SlokiHLtQkfk98j +NXm6fJjXwJvwiM2IiFyg8aUwEEDX5U+QOCA0wYrgUQ/h8iathvBJKSc9jQARAQAB +tEJDZW50T1MtNyBLZXkgKENlbnRPUyA3IE9mZmljaWFsIFNpZ25pbmcgS2V5KSA8 +c2VjdXJpdHlAY2VudG9zLm9yZz6JAjUEEwECAB8FAlOn/0sCGwMGCwkIBwMCBBUC +CAMDFgIBAh4BAheAAAoJECTGqKf0qA61TN0P/2730Th8cM+d1pEON7n0F1YiyxqG +QzwpC2Fhr2UIsXpi/lWTXIG6AlRvrajjFhw9HktYjlF4oMG032SnI0XPdmrN29lL +F+ee1ANdyvtkw4mMu2yQweVxU7Ku4oATPBvWRv+6pCQPTOMe5xPG0ZPjPGNiJ0xw +4Ns+f5Q6Gqm927oHXpylUQEmuHKsCp3dK/kZaxJOXsmq6syY1gbrLj2Anq0iWWP4 +Tq8WMktUrTcc+zQ2pFR7ovEihK0Rvhmk6/N4+4JwAGijfhejxwNX8T6PCuYs5Jiv +hQvsI9FdIIlTP4XhFZ4N9ndnEwA4AH7tNBsmB3HEbLqUSmu2Rr8hGiT2Plc4Y9AO +aliW1kOMsZFYrX39krfRk2n2NXvieQJ/lw318gSGR67uckkz2ZekbCEpj/0mnHWD +3R6V7m95R6UYqjcw++Q5CtZ2tzmxomZTf42IGIKBbSVmIS75WY+cBULUx3PcZYHD +ZqAbB0Dl4MbdEH61kOI8EbN/TLl1i077r+9LXR1mOnlC3GLD03+XfY8eEBQf7137 +YSMiW5r/5xwQk7xEcKlbZdmUJp3ZDTQBXT06vavvp3jlkqqH9QOE8ViZZ6aKQLqv +pL+4bs52jzuGwTMT7gOR5MzD+vT0fVS7Xm8MjOxvZgbHsAgzyFGlI1ggUQmU7lu3 +uPNL0eRx4S1G4Jn5 +=OGYX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-cloudera b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-cloudera new file mode 100644 index 0000000..57a77ac --- /dev/null +++ b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-cloudera @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.5 (GNU/Linux) + +mQGiBEpBgEURBAC+CL1a6BfVEoKAX1KcOHqq9Z10WdPGOgTM+AtnOVPJdJvIZcDk +YGUmycpaGxY3+xX1x8ZvxNb7WXiei8FMPm4sR/xQC/CF2iS5399tjLJqcDEjdqTV +/whQ4Rrg1JLGaHUjR0YmrOteT71xikEwlCalToxQuhBz7Nz4aBeDDPf9lwCgvG+x +CaOxict+He03g4HNSTZ0T0UEAIxKITpCA6ZvUPoEGhpn+Gt+wJK/ScB0FKCfW8Au +QQZP6tgxDEg0baasT8MxuXXE2+opaaWPTVa64ws7OvbyH5z1xhBOx4qRVBx8bZsF +YQUk/1PBvg6yA4Rmaqi7nTToHatP69/JMLfTyH8sXETMQ8z5T0LAD6a5ELAYBqql +bJWRA/4lkbaGIwkyLcOAop/g0SCERHt66ML1pwdjxvzE2rRKFUbjUbRZsHTqVq5E +BgpcTIeTuRy02yQ+Bh+JaBtYhn0AY5+t7jcCdJeTahS/7RKJPYPiSfbgI6zwpHM9 +kX4FT+0yDgnVF1H/h9p19Uv/3ahIgt7op/M1eAdH0/eP6Dv04rQnWXVtIE1haW50 +YWluZXIgPHdlYm1hc3RlckBjbG91ZGVyYS5jb20+iGAEExECACAFAkpBgEUCGwMG +CwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRD5DA2P6PhqzRo1AKCIHNWJSd7OipbZ +qp58f/BWaIBlDACggNRH4Hvg92t3xtwYFdohRWF2Xbi5Ag0ESkGARxAIAMaPPGfQ +vsLkyLyM3ePtkkHi0bew0XGW1CYxWOZLMu8wnJgMHpfPD2dLgp6PEh+zpi2SM1ie +QGAW6K040TSuC9P+LcZB7SxanIE7lONHjz7spGQift30WFZcaIgF+MuyZIihNh7v +tZ9ip8JZYPA88XRNU1CKuXx4r8iCDJ4ICksFKeOwQUuzf/IRJapzEZ0ixfVTwx91 +yG10TvHK63BRLXYHBML4Og9FaPZgFq2N9Yz4Wpu/Pn6tjZAMeSJXm2qNO2PSoTC/ +kapubpMwSmOBlZqrHi9lcIWricXE9dcyaGVRAf3CJRlX4ZNuwcQjyks5BFibU3/z +qlzP6KgwTgDmaaMAAwUH/04KRM3k6Ow2KkDt2BKWveOI24mkIQahUJ7/iZlKsL27 +3VcGQZ7jU28GT0FH9iYeAgbpLrrEuDAFZpGm9RoOVJGnxWX3DVL1+qkiS56pXfU+ +8atZlkCGx09IilJgf0ATlmYxbTtYliTRPK4lQYOfNB1v23bdlBwISjcDRkWu22ao +atSBzr/FARL6fdZZqp2qfWOmcteiLagioo6s0ogxKNQH5PldUQy9n2W/oOXss5sC +lnUNvzKlzzx/pFkT8ZUAvuLY0v8gykk586vbjiuPkg8uAOBhtnsSWwJ6nEPaRCnu +iwlqGxgXmnJ7UMzOimkuf0XvqavhkMEEAqRJkNLyWVuISQQYEQIACQUCSkGARwIb +DAAKCRD5DA2P6PhqzUV2AJ0eV3C407Y3Xi4d27clLsz/wW0HMgCghcxCmiOT2kWH +6Ya7d9nkKz2UM+Y= +=+VR8 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-elasticsearch b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-elasticsearch new file mode 100644 index 0000000..1b50dcc --- /dev/null +++ b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-elasticsearch @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.14 (GNU/Linux) + +mQENBFI3HsoBCADXDtbNJnxbPqB1vDNtCsqhe49vFYsZN9IOZsZXgp7aHjh6CJBD +A+bGFOwyhbd7at35jQjWAw1O3cfYsKAmFy+Ar3LHCMkV3oZspJACTIgCrwnkic/9 +CUliQe324qvObU2QRtP4Fl0zWcfb/S8UYzWXWIFuJqMvE9MaRY1bwUBvzoqavLGZ +j3SF1SPO+TB5QrHkrQHBsmX+Jda6d4Ylt8/t6CvMwgQNlrlzIO9WT+YN6zS+sqHd +1YK/aY5qhoLNhp9G/HxhcSVCkLq8SStj1ZZ1S9juBPoXV1ZWNbxFNGwOh/NYGldD +2kmBf3YgCqeLzHahsAEpvAm8TBa7Q9W21C8vABEBAAG0RUVsYXN0aWNzZWFyY2gg +KEVsYXN0aWNzZWFyY2ggU2lnbmluZyBLZXkpIDxkZXZfb3BzQGVsYXN0aWNzZWFy +Y2gub3JnPokBOAQTAQIAIgUCUjceygIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC +F4AACgkQ0n1mbNiOQrRzjAgAlTUQ1mgo3nK6BGXbj4XAJvuZDG0HILiUt+pPnz75 +nsf0NWhqR4yGFlmpuctgCmTD+HzYtV9fp9qW/bwVuJCNtKXk3sdzYABY+Yl0Cez/ +7C2GuGCOlbn0luCNT9BxJnh4mC9h/cKI3y5jvZ7wavwe41teqG14V+EoFSn3NPKm +TxcDTFrV7SmVPxCBcQze00cJhprKxkuZMPPVqpBS+JfDQtzUQD/LSFfhHj9eD+Xe +8d7sw+XvxB2aN4gnTlRzjL1nTRp0h2/IOGkqYfIG9rWmSLNlxhB2t+c0RsjdGM4/ +eRlPWylFbVMc5pmDpItrkWSnzBfkmXL3vO2X3WvwmSFiQbkBDQRSNx7KAQgA5JUl +zcMW5/cuyZR8alSacKqhSbvoSqqbzHKcUQZmlzNMKGTABFG1yRx9r+wa/fvqP6OT +RzRDvVS/cycws8YX7Ddum7x8uI95b9ye1/Xy5noPEm8cD+hplnpU+PBQZJ5XJ2I+ +1l9Nixx47wPGXeClLqcdn0ayd+v+Rwf3/XUJrvccG2YZUiQ4jWZkoxsA07xx7Bj+ +Lt8/FKG7sHRFvePFU0ZS6JFx9GJqjSBbHRRkam+4emW3uWgVfZxuwcUCn1ayNgRt +KiFv9jQrg2TIWEvzYx9tywTCxc+FFMWAlbCzi+m4WD+QUWWfDQ009U/WM0ks0Kww +EwSk/UDuToxGnKU2dQARAQABiQEfBBgBAgAJBQJSNx7KAhsMAAoJENJ9ZmzYjkK0 +c3MIAIE9hAR20mqJWLcsxLtrRs6uNF1VrpB+4n/55QU7oxA1iVBO6IFu4qgsF12J +TavnJ5MLaETlggXY+zDef9syTPXoQctpzcaNVDmedwo1SiL03uMoblOvWpMR/Y0j +6rm7IgrMWUDXDPvoPGjMl2q1iTeyHkMZEyUJ8SKsaHh4jV9wp9KmC8C+9CwMukL7 +vM5w8cgvJoAwsp3Fn59AxWthN3XJYcnMfStkIuWgR7U2r+a210W6vnUxU4oN0PmM +cursYPyeV0NX/KQeUeNMwGTFB6QHS/anRaGQewijkrYYoTNtfllxIu9XYmiBERQ/ +qPDlGRlOgVTd9xUfHFkzB52c70E= +=92oX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-erlang_solutions b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-erlang_solutions new file mode 100644 index 0000000..2dc29cb --- /dev/null +++ b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-erlang_solutions @@ -0,0 +1,52 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +mQINBE8v+uABEACgAlBUDDjc6PF7uI6mlTGnkemHF4trRINtocZKzvyKBmN+pPiV +CjJ3o6NwGmN/McHHyN1sB40n5IZbPtECi5hm+GmHWTkPG0jNQ0f9VDxoIb2eK/Xn +un2KmwJy7W0gth0++Eja5qE4G37o7AUr6hnwSUhFoQ8scahBxiAtya1M4FEeitsY +qY0azafah1Pl6c9I/sdyoH2T3casDByI6aiLK5iP+B5x2j1HKzGGkuTbOdMM0Jos +/pV8HbPBMCQdDhPOKSSEktKr3qgSD/fMzleusCQ5BYzlhAhr5OscCDny/LMiDBOF +8Au92q5DCkjsAlKz49DdpLjep4FwvBLq4DDGj9d8Bz28uUkKnYU8b+c8oPtf9E7D +Uc93i9Ddl6EmZ4QdaTZzR37oUIovKIChYNUh0FLNExhY6VsB3E/BJncaT5D2HkRQ +chUPl2lHVikeJhuHFGY3EkROXMYOxf6FrdVOJa13DflOBssDVwoul45ec9rxW/aA +UG7KCh4ySZ7C1ywSZSr6GXOfVdHjIaYgJpzee86TPnYxF81QpoXsH45tDOxMqMC2 +C1keWbzxvv3qxSGFAsCXSeKWNirCRPqsmEW1NpmLNIb2fm8LOru1hl/UknKu3Y1G +gJ/n6pJOB5cRLpconnssQ2iULSJeyrbVVNyXjQbHjj1DOhtrdDmmIEB/IQARAQAB +tDVFcmxhbmcgU29sdXRpb25zIEx0ZC4gPHBhY2thZ2VzQGVybGFuZy1zb2x1dGlv +bnMuY29tPokCOAQTAQIAIgUCTy/64AIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC +F4AACgkQ0ghQfKFPT8qeaQ//YAdT+Q206nwe9CauCKFzKfZVizWSXRa9n1pWyPWh +Cimag9gwCZisBasqVoQDP4qVgH6rJf97Z2/2//hK06hmnrtAodLWH2BgTE5nrDaa +XgAxIKDQJvJGKf+SMkZjL22ustpS1rHQ8R/vT9+XodGFVb/tzimN5mfWTlmAAl0/ +eRBbm7eEU41vij5P4NEE9hWFTclkxVws5m6iOLvJ+M8vQxt68ZaY6WBUgHxZXKHt +Mn/2OCnX2vg3mYzKWkhMUqgBzOWIBw6oH0kLOo34VqKyeqCubWO7Uu5JekrNrXT7 +K03wT+MAgIbmaYkVirTEF4JAqA8s37YFErOoM807pOTyE8Biao42v98F6h/l63qB +s1HBOG7LfuVXyG/reOlgGAlDFD8ShE2HP+UZ3/A/+LchKFAYt4bQG22KJtgWHgSk +ZNNaU7GPb2ai5TbjdvesZu9Wqq10T1dZC1txsZxl0uTDJh2HzzOshUCFxF7Yc2uq ++QBuX0aa9Z4x5Ls/UxTSV8a/XclOcTSIsSttUK5RIZNb2vaqF0Lh0kXaTErQiSq/ +SktmzFB09JqiYwXwiIYlYHpHBtWD9eiYtOuiRCf7qmV6g046n6QBq1j2d07SuqZM +AMpiDVY9zueUUpLWZvv77IBVE2TQ4kG7qSFPxSh+pPKoIwaDlo464WRrKqhijFl4 +m5y5Ag0ETy/64AEQAK1kcuQd5/vkEnionds1dGti5WPXKgmxYJEOE0K5ERYeZOZz +jHKKyn1sONY5BlZiHC97ISGSv8zuV2ER4GdJI8jH1OV7tx8dhy3ju2Uky5GiLwkJ +snfRLBFSBDD95Js4soZogIqsS9DxomfHD0nfet9ggR5ZYur/053xrY97ylPPvd96 +TYRXgNWz5qJX9YzExkAPhNUb6Qcw+Wr54n8lMBQQGl8rKZzVILRtiAo/XzhVWNAg +Ns4tSJlrcsS2qgn9vThtfkiFCwkPuTng+vUoRNSVvuHg1BcG/E5hhc/Gitmrynec +u1Exr2+FeuaG/1j2tQqBS7uwGgtJlDo0Ag1wKMoy790LX9uHS+0xx1x//wnkSQfY +Ob8cJWhWMsxZVngt9Pjs3ZL+bW2xxu/IOQ9OjXQMhJEwyf8/nMrcWnB0arIhqz+M +MX/XAfy/JwKD04LDdxngQD3NUOuuLIZWKuvx5WZr8+lSuc3gtthPFt43olIjY2Yi +HQhlcVKnV3xnXbaqaXptjXEkqi/K7jHtVn9Fpb3JAWNnIf5gaYTbdE2qQFiqPfWs +CQ1w5CHj2KPV3m/ckHiKu1oSvWFamocsEF0C3zYLdoDHKiuHesF0ZqCqIE9c0qkJ +gH+dxcbPhByCDIQbiyiHvXbs1SBM3VwTGhjvzlpLSCquBG5cAGMAnzNaMHr9ABEB +AAGJAh8EGAECAAkFAk8v+uACGwwACgkQ0ghQfKFPT8rwlw/+IGJTucS2T7+0FLDp +TKsdsBidPEOFEa19QBrIFM9sXdJXGyVRw/u/sVYOJYBYCZmGuqA/EB3mPNZHbsHX +pBRTIMGecH9qg55fm5t4WT93TbfbOjJCbbtsVONpig/NOYhVA63UUGasaLzVQ/6E +Ip4bmqSH4XhLrOT1J0yFe13MdfkJ6fxHJML1YeLrZhoVWApLQ9B70/CVfxqX5+oQ +Uwlxiiu6x2tExWCMrY2y9qXQOfk6bYZsNceoHrhXD876nn4pdMrJJoefD02OhT7L +/heeGCRolEzT5JsbTOr/HqyDoz6XP0Na30I4rJYRZKVUEDGT/XJaxhwX93QI2Kr/ +TvhgLtPDDngclxBuwfZ/gJMb8T83vN+fuhgjL8pHKaiQeneVuOMNpm5yxyAFr2ep +ux6ipe2UL9kUn7ZnfeiJc385cMTY9cZ30GjgdQr1o1EDwHiYm+ly4Licg5w5mYYx +Vx2bzOJLsGm9xAKp6G4xJHY89PE8y3bksO8pctGkkWmBPCCeH5PPFWrPhLcyiS9P +lvijXzabGtFaVDmxV5oGHW8orpirR3CMgn0DKE5QcH8412d9ByvjK3UcmBTwEnQk +Og0Ce4+ypBIERtufK1osg9lALv/abGtow2S6pdzfdFlISyiLA3HOUQ/spkuPvAe8 +ctmKvzuuerI6mVQjg/80PJ4fEV0= +=VAR1 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-icinga b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-icinga new file mode 100644 index 0000000..901c78c --- /dev/null +++ b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-icinga @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.19 (GNU/Linux) + +mQGiBFKHzk4RBACSHMIFTtfw4ZsNKAA03Gf5t7ovsKWnS7kcMYleAidypqhOmkGg +0petiYsMPYT+MOepCJFGNzwQwJhZrdLUxxMSWay4Xj0ArgpD9vbvU+gj8Tb02l+x +SqNGP8jXMV5UnK4gZsrYGLUPvx47uNNYRIRJAGOPYTvohhnFJiG402dzlwCg4u5I +1RdFplkp9JM6vNM9VBIAmcED/2jr7UQGsPs8YOiPkskGHLh/zXgO8SvcNAxCLgbp +BjGcF4Iso/A2TAI/2KGJW6kBW/Paf722ltU6s/6mutdXJppgNAz5nfpEt4uZKZyu +oSWf77179B2B/Wl1BsX/Oc3chscAgQb2pD/qPF/VYRJU+hvdQkq1zfi6cVsxyREV +k+IwA/46nXh51CQxE29ayuy1BoIOxezvuXFUXZ8rP6aCh4KaiN9AJoy7pBieCzsq +d7rPEeGIzBjI+yhEu8p92W6KWzL0xduWfYg9I7a2GTk8CaLX2OCLuwnKd7RVDyyZ +yzRjWs0T5U7SRAWspLStYxMdKert9lLyQiRHtLwmlgBPqa0gh7Q+SWNpbmdhIE9w +ZW4gU291cmNlIE1vbml0b3JpbmcgKEJ1aWxkIHNlcnZlcikgPGluZm9AaWNpbmdh +Lm9yZz6IYAQTEQIAIAUCUofOTgIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJ +EMbjGcM0QQaCgSQAnRjXdbsyqziqhmxfAKffNJYuMPwdAKCS/IRCVyQzApFBtIBQ +1xuoym/4C7kCDQRSh85OEAgAvPwjlURCi8z6+7i60no4n16dNcSzd6AT8Kizpv2r +9BmNBff/GNYGnHyob/DMtmO2esEuVG8w62rO9m1wzzXzjbtmtU7NZ1Tg+C+reU2I +GNVu3SYtEVK/UTJHAhLcgry9yD99610tYPN2Fx33Efse94mXOreBfCvDsmFGSc7j +GVNCWXpMR3jTYyGj1igYd5ztOzG63D8gPyOucTTl+RWN/G9EoGBv6sWqk5eCd1Fs +JlWyQX4BJn3YsCZx3uj1DWL0dAl2zqcn6m1M4oj1ozW47MqM/efKOcV6VvCs9SL8 +F/NFvZcH4LKzeupCQ5jEONqcTlVlnLlIqId95Z4DI4AV9wADBQf/S6sKA4oH49tD +Yb5xAfUyEp5ben05TzUJbXs0Z7hfRQzy9+vQbWGamWLgg3QRUVPx1e4IT+W5vEm5 +dggNTMEwlLMI7izCPDcD32B5oxNVxlfj428KGllYWCFj+edY+xKTvw/PHnn+drKs +LE65Gwx4BPHm9EqWHIBX6aPzbgbJZZ06f6jWVBi/N7e/5n8lkxXqS23DBKemapyu +S1i56sH7mQSMaRZP/iiOroAJemPNxv1IQkykxw2woWMmTLKLMCD/i+4DxejE50tK +dxaOLTc4HDCsattw/RVJO6fwE414IXHMv330z4HKWJevMQ+CmQGfswvCwgeBP9n8 +PItLjBQAXIhJBBgRAgAJBQJSh85OAhsMAAoJEMbjGcM0QQaCzpAAmwUNoRyySf9p +5G3/2UD1PMueIwOtAKDVVDXEq5LJPVg4iafNu0SRMwgP0Q== +=icbY +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-webtatic-el7 b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-webtatic-el7 new file mode 100644 index 0000000..345d073 --- /dev/null +++ b/puphpet/puppet/modules/yum/files/rpm-gpg/RPM-GPG-KEY-webtatic-el7 @@ -0,0 +1,29 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2 + +mQINBFOch44BEADUQkO69WbI65GuTf7e/PxkPMONyyjeV3wZjz1qHtDbryzQmoN9 +CJg4xLUd/Dd03peNRQJ7RL/l2qsCu1Mb7zSTqaDdExRGyweKw6mIGBumzvBBRXPw +97ezIEIiEmq3ZUKFGBSDU3VQI4Zzndn/NgSOa03tWn2VlrTyYsMHm07839OGn6bD +CdnxlzAv2Z6FxYKomo2jMNPQ9vyJ6h3dSUghFhAkZPlkfLPAdBxuFVnn3oyAElDa +F8G19BfRywg7tLQRE7aSuX9E7VqJo0QmZPqwy/oijb9NSEyDg9lO+y/naebX67NJ +L51+RdAXWBxAk3FtSANTz9v3LgszCTDpeSLgAz2zvwsAyuI/GbF0qPhv0QPsnQ+9 +ipbZoRTVo6zqBSITdK4kKs9WQXwYq40KzFFcL0d/fruYwCIAkOpBKJPCRYcX2rWj +usbuXBei9bB6aGFo5txLHoACpBh9eR4RDkEtcFrfnCJBWGs/JleyxFoL+jn4F+Nc +V73zWuSaYBmc7AMsE/3nu4iEOvYMDJB6KG7Vqz++ZIM2jjuyT4ujATpJlzr2SyIh +LlKhOLEv8sHZfqjzuN8eStycbSTm6EWQLR5R2oZODgI29hMk2C04JQ26+WjtJnr4 +U43bPgh39qTkXwjU+5kCb0D5YixIcvMFsTm4i2bEBBvD+0i0BU2eHbRMMwARAQAB +tCBXZWJ0YXRpYyBFTDcgPHJwbXNAd2VidGF0aWMuY29tPokCOQQTAQIAIwUCU5yH +jgIbAwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEOh/0jZi50yl0HQQAJzN +8/eq1aN38Uk/x0STbbcdmn4vKkYYP3asrz7LWWU6IPacEc4LDkpc/YumzllE3suw +/wISvg7G4hZohQIdnCOoqkZo7OTUbHKkDJZykhqOI8Fs+6Tc2UQnLA3+uTHthKeF +JBjiRD6LxwSdoPulHDFBEPNOr1gqo3bHS40PxjxX3kFYnv8CR59MXcOLiy3aaVhA +Szj+BHhtDQ95xCxW2Z0jpHJ3F5fM9RAl5kR1hjtvvXjq8DbLn8HjHfJyvitSKMoI +jBAl32er5nrattBAKgnvGNA+CRR7b5VuOvHbl/xih4GpSKxCjkRFjwbnV0JYOXcf +Q9C2Y2750qlRU1hTcPr7Suc/dK7lgzuCEtLIzwMp+22OvF0LLV5FCAGIr3MErC5S +ZZBwH7V44AUpvWJgO6+ral3Yn3BHjPazZu52Nj1A9PX3D+7M2iVWGmyADAS5pFbt +8RnOzEzTRqKVL37K1C8gaxkx1j8pNDdjTSk0JZeCcyi3dsPTe+wsdbfude1jzD8r +XUUW6y4OjQfWknGJpvQ7bfYkoYvINCWqdwUgaOGmrQ8omkeO4AjHsJ41/elz5FN6 +yG86FITDM4P64H8PBSCkFUYaYXrnWHWftjGcrGF6cFjZGLDh/pWL0vBgB7u+LoMa +EFPgVyg6CysBrTAT061QVX9O1bJTtxXAcG2vr/kv +=D3Nr +-----END PGP PUBLIC KEY BLOCK----- diff --git a/puphpet/puppet/modules/yum/manifests/cron.pp b/puphpet/puppet/modules/yum/manifests/cron.pp index ddb0461..fe84db3 100644 --- a/puphpet/puppet/modules/yum/manifests/cron.pp +++ b/puphpet/puppet/modules/yum/manifests/cron.pp @@ -37,11 +37,11 @@ } file { 'yum-cron': - ensure => $manage_update_file, - path => $yum::update_configuration_file, - content => template($yum::update_template), - require => Package['yum-cron'], - notify => Service['yum-cron'], + ensure => $manage_update_file, + path => $yum::update_configuration_file, + content => template($yum::update_template), + require => Package['yum-cron'], + notify => Service['yum-cron'], } } diff --git a/puphpet/puppet/modules/yum/manifests/defaults.pp b/puphpet/puppet/modules/yum/manifests/defaults.pp old mode 100755 new mode 100644 index eae0b10..2bd26b2 --- a/puphpet/puppet/modules/yum/manifests/defaults.pp +++ b/puphpet/puppet/modules/yum/manifests/defaults.pp @@ -14,10 +14,12 @@ if 'remi' in $yum::extrarepo { include yum::repo::remi } if 'remi_php55' in $yum::extrarepo { include yum::repo::remi_php55 } if 'remi_php56' in $yum::extrarepo { include yum::repo::remi_php56 } + if 'remi_php70' in $yum::extrarepo { include yum::repo::remi_php70 } if 'tmz' in $yum::extrarepo and $osver[0] != '4' { include yum::repo::tmz } if 'webtatic' in $yum::extrarepo { include yum::repo::webtatic } if 'puppetlabs' in $yum::extrarepo and $osver[0] != '4' { include yum::repo::puppetlabs } if 'puppetdevel' in $yum::extrarepo and $osver[0] != '4' { include yum::repo::puppetdevel } + if 'puppetlabs_collections' in $yum::extrarepo { include yum::repo::puppetlabs_collections } if 'nginx' in $yum::extrarepo and $osver[0] != '4' { include yum::repo::nginx } if 'mongodb' in $yum::extrarepo and $osver[0] != '4' { include yum::repo::mongodb } if 'repoforge' in $yum::extrarepo { include yum::repo::repoforge } @@ -30,16 +32,19 @@ if 'centalt' in $yum::extrarepo { include yum::repo::centalt } if 'elastix' in $yum::extrarepo { include yum::repo::elastix } if 'mysql_community' in $yum::extrarepo { include yum::repo::mysql_community } + if 'dell_omsa' in $yum::extrarepo { include yum::repo::dell_omsa } if $yum::bool_defaultrepo { case $::operatingsystem { centos: { + if $osver[0] == '7' { include yum::repo::centos7 } if $osver[0] == '6' { include yum::repo::centos6 } if $osver[0] == '5' { include yum::repo::centos5 } if $osver[0] == '4' { include yum::repo::centos4 } if 'centos-testing' in $yum::extrarepo { include yum::repo::centos_testing } if 'karan' in $yum::extrarepo { include yum::repo::karan } if 'atomic' in $yum::extrarepo { include yum::repo::atomic } + if 'scl' in $yum::extrarepo { include yum::repo::scl } } redhat: { } @@ -49,6 +54,9 @@ if 'centos-testing' in $yum::extrarepo { include yum::repo::centos_testing } if 'karan' in $yum::extrarepo { include yum::repo::karan } } + xenserver: { + include yum::repo::xenserver + } default: { } } } diff --git a/puphpet/puppet/modules/yum/manifests/init.pp b/puphpet/puppet/modules/yum/manifests/init.pp index 14cd02b..cefd9af 100644 --- a/puphpet/puppet/modules/yum/manifests/init.pp +++ b/puphpet/puppet/modules/yum/manifests/init.pp @@ -43,7 +43,7 @@ # (Epel is used by many modules) # Note: This variable is ignored if you provide a custom source_repo_dir # -# [*plugins_source_dir*] +# [*plugins_config_dir*] # The path of the plugins configuration directory # # [*repo_dir*] @@ -153,44 +153,61 @@ # [*log_file*] # Log file(s). Used by puppi # +# [*persist_dir*] +# Persistent information store directory path +# +# [*cache_dir*] +# cache and db files directory path +# # [*bool_priorities_plugin*] # Boolean. If true, the priorities plugin will be installed automatically # Default: true # class yum ( - $install_all_keys = params_lookup( 'install_all_keys' ), - $update = params_lookup( 'update' ), - $update_disable = params_lookup( 'update_disable' ), - $defaultrepo = params_lookup( 'defaultrepo' ), - $extrarepo = params_lookup( 'extrarepo' ), - $plugins_source_dir = params_lookup( 'plugins_source_dir' ), - $repo_dir = params_lookup( 'repo_dir' ), - $source_repo_dir = params_lookup( 'source_repo_dir' ), - $clean_repos = params_lookup( 'clean_repos' ), - $my_class = params_lookup( 'my_class' ), - $source = params_lookup( 'source' ), - $source_dir = params_lookup( 'source_dir' ), - $source_dir_purge = params_lookup( 'source_dir_purge' ), - $template = params_lookup( 'template' ), - $options = params_lookup( 'options' ), - $absent = params_lookup( 'absent' ), - $disable = params_lookup( 'disable' ), - $disableboot = params_lookup( 'disableboot' ), - $puppi = params_lookup( 'puppi' , 'global' ), - $puppi_helper = params_lookup( 'puppi_helper' , 'global' ), - $debug = params_lookup( 'debug' , 'global' ), - $audit_only = params_lookup( 'audit_only' , 'global' ), - $config_dir = params_lookup( 'config_dir' ), - $config_file = params_lookup( 'config_file' ), - $config_file_mode = params_lookup( 'config_file_mode' ), - $config_file_owner = params_lookup( 'config_file_owner' ), - $config_file_group = params_lookup( 'config_file_group' ), - $update_template = params_lookup( 'update_template' ), - $cron_param = params_lookup( 'cron_param' ), - $cron_mailto = params_lookup( 'cron_mailto' ), - $cron_dotw = params_lookup( 'cron_dotw' ), - $log_file = params_lookup( 'log_file' ), - $priorities_plugin = params_lookup( 'priorities_plugin' ) + $install_all_keys = params_lookup( 'install_all_keys' ), + $update = params_lookup( 'update' ), + $update_disable = params_lookup( 'update_disable' ), + $defaultrepo = params_lookup( 'defaultrepo' ), + $extrarepo = params_lookup( 'extrarepo' ), + $plugins_config_dir = params_lookup( 'plugins_config_dir' ), + $repo_dir = params_lookup( 'repo_dir' ), + $source_repo_dir = params_lookup( 'source_repo_dir' ), + $clean_repos = params_lookup( 'clean_repos' ), + $my_class = params_lookup( 'my_class' ), + $source = params_lookup( 'source' ), + $source_dir = params_lookup( 'source_dir' ), + $source_dir_purge = params_lookup( 'source_dir_purge' ), + $template = params_lookup( 'template' ), + $options = params_lookup( 'options' ), + $absent = params_lookup( 'absent' ), + $disable = params_lookup( 'disable' ), + $disableboot = params_lookup( 'disableboot' ), + $puppi = params_lookup( 'puppi' , 'global' ), + $puppi_helper = params_lookup( 'puppi_helper' , 'global' ), + $debug = params_lookup( 'debug' , 'global' ), + $audit_only = params_lookup( 'audit_only' , 'global' ), + $config_dir = params_lookup( 'config_dir' ), + $config_file = params_lookup( 'config_file' ), + $config_file_mode = params_lookup( 'config_file_mode' ), + $config_file_owner = params_lookup( 'config_file_owner' ), + $config_file_group = params_lookup( 'config_file_group' ), + $update_template = params_lookup( 'update_template' ), + $cron_param = params_lookup( 'cron_param' ), + $cron_mailto = params_lookup( 'cron_mailto' ), + $cron_dotw = params_lookup( 'cron_dotw' ), + $cron_clean_dotw = params_lookup( 'cron_clean_dotw' ), + $cron_update_cmd = params_lookup( 'cron_update_cmd' ), + $cron_update_messages = params_lookup( 'cron_update_messages' ), + $cron_apply_updates = params_lookup( 'cron_apply_updates' ), + $cron_random_sleep = params_lookup( 'cron_random_sleep' ), + $cron_emit_via = params_lookup( 'cron_emit_via' ), + $cron_email_host = params_lookup( 'cron_email_host' ), + $log_file = params_lookup( 'log_file' ), + $manage_persist_dir = params_lookup( 'manage_persist_dir' ), + $persist_dir = params_lookup( 'persist_dir'), + $manage_cache_dir = params_lookup( 'manage_cache_dir' ), + $cache_dir = params_lookup( 'cache_dir'), + $priorities_plugin = params_lookup( 'priorities_plugin' ) ) inherits yum::params { $bool_install_all_keys=any2bool($install_all_keys) @@ -205,8 +222,13 @@ $bool_audit_only=any2bool($audit_only) $bool_priorities_plugin=any2bool($priorities_plugin) $bool_update_disable=any2bool($update_disable) + $bool_manage_persist_dir=any2bool($manage_persist_dir) + $bool_manage_cache_dir=any2bool($manage_cache_dir) - $osver = split($::operatingsystemrelease, '[.]') + $osver = $::operatingsystem ? { + 'XenServer' => [ '5' ], + default => split($::operatingsystemrelease, '[.]') + } $manage_service_enable = $yum::bool_disableboot ? { true => false, @@ -258,17 +280,22 @@ default => false, } + # XXX param_lookup returns '' instead of undef + $real_source_repo_dir = $yum::source_repo_dir ? { + '' => undef, + default => $yum::source_repo_dir, + } file { 'yum.repo_dir': ensure => directory, path => $yum::repo_dir, - source => $yum::source_repo_dir, + source => $real_source_repo_dir, recurse => true, purge => $yum::bool_clean_repos, replace => $yum::manage_file_replace, audit => $yum::manage_audit, } - if $yum::source_repo_dir == undef { + if $real_source_repo_dir == undef { include yum::defaults } @@ -286,7 +313,7 @@ } # The whole yum configuration directory can be recursively overriden - if $yum::source_dir { + if $yum::source_dir and $yum::source_dir != '' { file { 'yum.dir': ensure => directory, path => $yum::config_dir, @@ -298,13 +325,36 @@ } } + # set the premissions for the cache and persist dirs recursively + if $bool_manage_persist_dir { + file { 'yum.persist.dir': + ensure => directory, + path => $yum::persist_dir, + mode => $yum::config_file_mode, + owner => $yum::config_file_owner, + group => $yum::config_file_group, + recurse => true, + } + } + + if $bool_manage_cache_dir { + file { 'yum.cache.dir': + ensure => directory, + path => $yum::cache_dir, + mode => $yum::config_file_mode, + owner => $yum::config_file_owner, + group => $yum::config_file_group, + recurse => true, + } + } + ### Manage Automatic Updates if $yum::manage_updates { include $yum::update } ### Include custom class if $my_class is set - if $yum::my_class { + if $yum::my_class and $yum::my_class != '' { include $yum::my_class } diff --git a/puphpet/puppet/modules/yum/manifests/managed_yumrepo.pp b/puphpet/puppet/modules/yum/manifests/managed_yumrepo.pp index b20e605..59623fc 100644 --- a/puphpet/puppet/modules/yum/manifests/managed_yumrepo.pp +++ b/puphpet/puppet/modules/yum/manifests/managed_yumrepo.pp @@ -16,7 +16,11 @@ $autokeyimport = 'no', $includepkgs = 'absent', $metadata_expire = 'absent', - $include = 'absent' + $include = 'absent', + $sslcacert = 'absent', + $sslclientcert = 'absent', + $sslclientkey = 'absent', + $sslverify = 'absent', ) { # ensure that everything is setup @@ -56,19 +60,23 @@ } } yumrepo { $name: - descr => $descr, - baseurl => $baseurl, - mirrorlist => $mirrorlist, - enabled => $enabled, - gpgcheck => $gpgcheck, - gpgkey => $gpgkey, - failovermethod => $failovermethod, - priority => $priority, - protect => $protect, - exclude => $exclude, - includepkgs => $includepkgs, - metadata_expire => $metadata_expire, - include => $include + descr => $descr, + baseurl => $baseurl, + mirrorlist => $mirrorlist, + enabled => $enabled, + gpgcheck => $gpgcheck, + gpgkey => $gpgkey, + failovermethod => $failovermethod, + priority => $priority, + protect => $protect, + exclude => $exclude, + includepkgs => $includepkgs, + metadata_expire => $metadata_expire, + include => $include, + sslcacert => $sslcacert, + sslclientcert => $sslclientcert, + sslclientkey => $sslclientkey, + sslverify => $sslverify } if $autokeyimport == 'yes' and $gpgkey != '' { diff --git a/puphpet/puppet/modules/yum/manifests/params.pp b/puphpet/puppet/modules/yum/manifests/params.pp index f9bd2aa..1dc02e3 100644 --- a/puphpet/puppet/modules/yum/manifests/params.pp +++ b/puphpet/puppet/modules/yum/manifests/params.pp @@ -12,12 +12,22 @@ $clean_repos = false + $my_class = '' + $plugins_config_dir = '/etc/yum/pluginconf.d' $source_repo_dir = undef $repo_dir = '/etc/yum.repos.d' + $manage_persist_dir = false + + $persist_dir = '/var/lib/yum' + + $manage_cache_dir = false + + $cache_dir = '/var/cache/yum' + $config_dir = '/etc/yum' $config_file = '/etc/yum.conf' @@ -52,6 +62,7 @@ $cron_param = '' $cron_dotw = '0123456' + $cron_clean_dotw = '0' # The following params are for cron.pp only for version 7 @@ -63,7 +74,7 @@ $cron_email_host = 'localhost' $source = '' - $source_dir = '' + $source_dir = undef $source_dir_purge = false $template = '' $options = '' diff --git a/puphpet/puppet/modules/yum/manifests/plugin.pp b/puphpet/puppet/modules/yum/manifests/plugin.pp index 6e5d372..735a948 100644 --- a/puphpet/puppet/modules/yum/manifests/plugin.pp +++ b/puphpet/puppet/modules/yum/manifests/plugin.pp @@ -1,4 +1,4 @@ -# Define: pagios::plugin +# Define: yum::plugin # # Adds a yum plugin # @@ -27,8 +27,8 @@ $ensure = bool2ensure( $enable ) $yum_plugins_prefix = $yum::osver[0] ? { - 5 => 'yum', - 6 => 'yum-plugin', + '5' => 'yum', + '6' => 'yum-plugin', default => 'yum-plugin', } @@ -43,12 +43,12 @@ if ( $source != '' ) { file { "yum_plugin_conf_${name}": - ensure => $ensure, - path => "${yum::plugins_config_dir}/${name}.conf", - owner => root, - group => root, - mode => '0755', - source => $source, + ensure => $ensure, + path => "${yum::plugins_config_dir}/${name}.conf", + owner => root, + group => root, + mode => '0644', + source => $source, } } } diff --git a/puphpet/puppet/modules/yum/manifests/plugin/security.pp b/puphpet/puppet/modules/yum/manifests/plugin/security.pp new file mode 100644 index 0000000..120599c --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/plugin/security.pp @@ -0,0 +1,10 @@ +# = Class yum::plugin::security +# +# +class yum::plugin::security ($ensure = present) { + + package { + 'yum-plugin-security': + ensure => $ensure + } +} diff --git a/puphpet/puppet/modules/yum/manifests/plugin/versionlock.pp b/puphpet/puppet/modules/yum/manifests/plugin/versionlock.pp new file mode 100644 index 0000000..e74b39a --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/plugin/versionlock.pp @@ -0,0 +1,20 @@ +# = Class yum::plugin::versionlock +# +# +class yum::plugin::versionlock ( + $ensure = present, + $path = '/etc/yum/pluginconf.d/versionlock.list', +) { + + package { 'yum-plugin-versionlock': + ensure => $ensure + } + + file { 'yum.versionlock.list': + ensure => $ensure, + path => $path, + owner => 'root', + group => 'root', + mode => '0644', + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/10gen.pp b/puphpet/puppet/modules/yum/manifests/repo/a10gen.pp similarity index 50% rename from puphpet/puppet/modules/yum/manifests/repo/10gen.pp rename to puphpet/puppet/modules/yum/manifests/repo/a10gen.pp index 9539d5b..83f2c8d 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/10gen.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/a10gen.pp @@ -1,13 +1,11 @@ -# = Class: yum::repo::10gen +# = Class: yum::repo::a10gen # # This class installs the 10gen repo for MongoDB # -class yum::repo::10gen ( - $baseurl = "http://downloads-distro.mongodb.org/repo/redhat/os/${::architecture}", -) { +class yum::repo::a10gen { yum::managed_yumrepo { '10gen': descr => '10gen Repository', - baseurl => $baseurl, + baseurl => "http://downloads-distro.mongodb.org/repo/redhat/os/${::architecture}", enabled => 1, gpgcheck => 0, } diff --git a/puphpet/puppet/modules/yum/manifests/repo/atomic.pp b/puphpet/puppet/modules/yum/manifests/repo/atomic.pp index 13a2414..08f4221 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/atomic.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/atomic.pp @@ -4,13 +4,13 @@ # class yum::repo::atomic { yum::managed_yumrepo { 'atomic': - descr => 'CentOS / Red Hat Enterprise Linux $releasever - atomicrocketturtle.com', - mirrorlist => 'http://www.atomicorp.com/channels/mirrorlist/atomic/centos-$releasever-$basearch', - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY.art', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY.art', - priority => 1, - exclude => 'nmap-ncat', + descr => 'CentOS / Red Hat Enterprise Linux $releasever - atomicrocketturtle.com', + mirrorlist => 'http://www.atomicorp.com/channels/mirrorlist/atomic/centos-$releasever-$basearch', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY.art', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY.art', + priority => 1, + exclude => 'nmap-ncat', } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/atrpms.pp b/puphpet/puppet/modules/yum/manifests/repo/atrpms.pp index fa446a0..8f8c8ac 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/atrpms.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/atrpms.pp @@ -3,17 +3,17 @@ # This class installs the atrpms repo # class yum::repo::atrpms ( - $baseurl = 'http://dl.atrpms.net/el$releasever-$basearch/atrpms/stable', + $baseurl = 'https://www.mirrorservice.org/sites/dl.atrpms.net/el$releasever-$basearch/atrpms/stable', ) { yum::managed_yumrepo { 'centos5-atrpms': - descr => 'CentOS $releasever - $basearch - ATrpms', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY.atrpms', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY.atrpms', - priority => 30, + descr => 'CentOS $releasever - $basearch - ATrpms', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY.atrpms', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY.atrpms', + priority => 30, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/cdh5.pp b/puphpet/puppet/modules/yum/manifests/repo/cdh5.pp new file mode 100644 index 0000000..e4e137b --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/cdh5.pp @@ -0,0 +1,29 @@ +# class yum::repo::cdh5 +# +class yum::repo::cdh5 ( + $baseurl = 'http://archive.cloudera.com/cdh5/redhat/6/x86_64/cdh/5/', + $baseurl_extras = 'http://archive.cloudera.com/gplextras5/redhat/6/x86_64/gplextras/5/' +) { + + yum::managed_yumrepo { 'cloudera-cdh5': + descr => "Cloudera's Distribution for Hadoop, Version 5", + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-cloudera', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-cloudera', + priority => 20, + failovermethod => 'priority', + } + + yum::managed_yumrepo { 'cloudera-gplextras5': + descr => "Cloudera's GPLExtras, Version 5", + baseurl => $baseurl_extras, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-cloudera', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-cloudera', + priority => 20, + failovermethod => 'priority', + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/centos4.pp b/puphpet/puppet/modules/yum/manifests/repo/centos4.pp index 7d0330d..2a344ae 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/centos4.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/centos4.pp @@ -10,7 +10,7 @@ enabled => 1, gpgcheck => 1, gpgkey => 'http://mirror.centos.org/centos/RPM-GPG-KEY-centos4', - priority => 1, + priority => 2, } yum::managed_yumrepo { 'updates': @@ -19,7 +19,7 @@ enabled => 1, gpgcheck => 1, gpgkey => 'http://mirror.centos.org/centos/RPM-GPG-KEY-centos4', - priority => 1, + priority => 2, } yum::managed_yumrepo { 'addons': @@ -28,7 +28,7 @@ enabled => 1, gpgcheck => 1, gpgkey => 'http://mirror.centos.org/centos/RPM-GPG-KEY-centos4', - priority => 1, + priority => 2, } yum::managed_yumrepo { 'extras': @@ -37,7 +37,7 @@ enabled => 1, gpgcheck => 1, gpgkey => 'http://mirror.centos.org/centos/RPM-GPG-KEY-centos4', - priority => 1, + priority => 2, } yum::managed_yumrepo { 'centosplus': @@ -46,7 +46,7 @@ enabled => 0, gpgcheck => 1, gpgkey => 'http://mirror.centos.org/centos/RPM-GPG-KEY-centos4', - priority => 2, + priority => 3, } yum::managed_yumrepo { 'contrib': @@ -55,7 +55,7 @@ enabled => 0, gpgcheck => 1, gpgkey => 'http://mirror.centos.org/centos/RPM-GPG-KEY-centos4', - priority => 2, + priority => 3, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/centos5.pp b/puphpet/puppet/modules/yum/manifests/repo/centos5.pp index c48cccd..2b4ed89 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/centos5.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/centos5.pp @@ -20,7 +20,7 @@ if $mirror_url { validate_re( $mirror_url, - '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\/[\w~-]*)*$', + '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\:[0-9]{1,5})?(?:\/[\w~-]*)*$', '$mirror must be a Clean URL with no query-string, a fully-qualified hostname and no trailing slash.' ) } @@ -64,7 +64,7 @@ gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5', gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-CentOS-5', - priority => 1, + priority => 2, } yum::managed_yumrepo { 'updates': @@ -75,7 +75,7 @@ enabled => 1, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5', - priority => 1, + priority => 2, } yum::managed_yumrepo { 'addons': @@ -86,7 +86,7 @@ enabled => 1, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5', - priority => 1, + priority => 2, } yum::managed_yumrepo { 'extras': @@ -97,7 +97,7 @@ enabled => 1, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5', - priority => 1, + priority => 2, } yum::managed_yumrepo { 'centosplus': diff --git a/puphpet/puppet/modules/yum/manifests/repo/centos6.pp b/puphpet/puppet/modules/yum/manifests/repo/centos6.pp index ddfdaf4..680a66d 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/centos6.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/centos6.pp @@ -20,7 +20,7 @@ if $mirror_url { validate_re( $mirror_url, - '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\/[\w~-]*)*$', + '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\:[0-9]{1,5})?(?:\/[\w~-]*)*$', '$mirror must be a Clean URL with no query-string, a fully-qualified hostname and no trailing slash.' ) } @@ -59,7 +59,7 @@ gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6', gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-CentOS-6', - priority => 1, + priority => 2, } yum::managed_yumrepo { 'updates': @@ -70,7 +70,7 @@ enabled => 1, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6', - priority => 1, + priority => 2, } yum::managed_yumrepo { 'extras': @@ -81,7 +81,7 @@ enabled => 1, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6', - priority => 1, + priority => 2, } yum::managed_yumrepo { 'centosplus': @@ -92,7 +92,7 @@ enabled => 1, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6', - priority => 2, + priority => 3, } yum::managed_yumrepo { 'contrib': diff --git a/puphpet/puppet/modules/yum/manifests/repo/centos7.pp b/puphpet/puppet/modules/yum/manifests/repo/centos7.pp new file mode 100644 index 0000000..49fe813 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/centos7.pp @@ -0,0 +1,93 @@ +# = Class: yum::repo::centos7 +# +# Base Centos7 repos +# +# == Parameters: +# +# [*mirror_url*] +# A clean URL to a mirror of `rsync://msync.centos.org::CentOS`. +# The paramater is interpolated with the known directory structure to +# create a the final baseurl parameter for each yumrepo so it must be +# "clean", i.e., without a query string like `?key1=valA&key2=valB`. +# Additionally, it may not contain a trailing slash. +# Example: `http://mirror.example.com/pub/rpm/centos` +# Default: `undef` +# +class yum::repo::centos7 ( + $mirror_url = undef, +) { + + if $mirror_url { + validate_re( + $mirror_url, + '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\/[\w~-]*)*$', + '$mirror must be a Clean URL with no query-string, a fully-qualified hostname and no trailing slash.' + ) + } + + $baseurl_base = $mirror_url ? { + undef => undef, + default => "${mirror_url}/\$releasever/os/\$basearch/", + } + + $baseurl_updates = $mirror_url ? { + undef => undef, + default => "${mirror_url}/\$releasever/updates/\$basearch/", + } + + $baseurl_extras = $mirror_url ? { + undef => undef, + default => "${mirror_url}/\$releasever/extras/\$basearch/", + } + + $baseurl_centosplus = $mirror_url ? { + undef => undef, + default => "${mirror_url}/\$releasever/centosplus/\$basearch/", + } + + yum::managed_yumrepo { 'base': + descr => 'CentOS-$releasever - Base', + baseurl => $baseurl_base, + mirrorlist => 'http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os', + failovermethod => 'priority', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-CentOS-7', + priority => 2, + } + + yum::managed_yumrepo { 'updates': + descr => 'CentOS-$releasever - Updates', + baseurl => $baseurl_updates, + mirrorlist => 'http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates', + failovermethod => 'priority', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7', + priority => 2, + } + + yum::managed_yumrepo { 'extras': + descr => 'CentOS-$releasever - Extras', + baseurl => $baseurl_extras, + mirrorlist => 'http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras', + failovermethod => 'priority', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7', + priority => 2, + } + + yum::managed_yumrepo { 'centosplus': + descr => 'CentOS-$releasever - Centosplus', + baseurl => $baseurl_centosplus, + mirrorlist => 'http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus', + failovermethod => 'priority', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7', + priority => 3, + } + +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/ceph.pp b/puphpet/puppet/modules/yum/manifests/repo/ceph.pp index 33449ec..5488540 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/ceph.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/ceph.pp @@ -3,12 +3,12 @@ # This class installs the official ceph repo # class yum::repo::ceph ( - $release = 'emperor' + $release = 'emperor', ) { yum::managed_yumrepo { 'ceph': descr => "Ceph ${release} repository", - baseurl => "http://ceph.com/rpm-${release}/\$releasever/\$basearch", + baseurl => "http://ceph.com/rpm-${release}/el\$releasever/\$basearch", enabled => 1, gpgcheck => 1, failovermethod => 'priority', diff --git a/puphpet/puppet/modules/yum/manifests/repo/cuda.pp b/puphpet/puppet/modules/yum/manifests/repo/cuda.pp new file mode 100644 index 0000000..9070925 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/cuda.pp @@ -0,0 +1,15 @@ +# +# This class installs the cuda repo +# +class yum::repo::cuda ( + $baseurl = 'http://developer.download.nvidia.com/compute/cuda/repos/rhel$releasever/$basearch/' +) { + + yum::managed_yumrepo { 'cuda': + descr => 'NVIDIA Cuda for CentOS', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 0, + priority => 90, + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/dell_omsa.pp b/puphpet/puppet/modules/yum/manifests/repo/dell_omsa.pp new file mode 100644 index 0000000..85d529f --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/dell_omsa.pp @@ -0,0 +1,24 @@ +# = Class: yum::repo::dell_omsa +# +# This class installs the DELL OpenManage repo +# +class yum::repo::dell_omsa { + yum::managed_yumrepo { 'dell-omsa-indep': + descr => 'Dell OMSA repository - Hardware independent', + enabled => 1, + gpgcheck => 1, + mirrorlist => 'http://linux.dell.com/repo/hardware/latest/mirrors.cgi?osname=el$releasever&basearch=$basearch&native=1&dellsysidpluginver=$dellsysidpluginver', + failovermethod => 'priority', + gpgkey => 'http://linux.dell.com/repo/hardware/latest/RPM-GPG-KEY-dell http://linux.dell.com/repo/hardware/latest/RPM-GPG-KEY-libsmbios', + } + + yum::managed_yumrepo { 'dell-omsa-specific': + descr => 'Dell OMSA repository - Hardware specific', + enabled => 1, + gpgcheck => 1, + mirrorlist => 'http://linux.dell.com/repo/hardware/latest/mirrors.cgi?osname=el$releasever&basearch=$basearch&native=1&sys_ven_id=$sys_ven_id&sys_dev_id=$sys_dev_id&dellsysidpluginver=$dellsysidpluginver', + failovermethod => 'priority', + gpgkey => 'http://linux.dell.com/repo/hardware/latest/RPM-GPG-KEY-dell http://linux.dell.com/repo/hardware/latest/RPM-GPG-KEY-libsmbios', + } + +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/devtools.pp b/puphpet/puppet/modules/yum/manifests/repo/devtools.pp index a506da9..074eb19 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/devtools.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/devtools.pp @@ -8,10 +8,10 @@ require yum yum::managed_yumrepo { 'devtools': - descr => 'Devtools for CentOS', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 0, - priority => 90, + descr => 'Devtools for CentOS', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 0, + priority => 90, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/devtools2.pp b/puphpet/puppet/modules/yum/manifests/repo/devtools2.pp new file mode 100644 index 0000000..8c92b5d --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/devtools2.pp @@ -0,0 +1,17 @@ +# +# This class installs the devtools2 repo +# +class yum::repo::devtools2 ( + $baseurl = 'http://people.centos.org/tru/devtools-2/$releasever/$basearch/RPMS' +) { + + require yum + + yum::managed_yumrepo { 'devtools2': + descr => 'Devtools2 for CentOS', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 0, + priority => 90, + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/elasticsearch10.pp b/puphpet/puppet/modules/yum/manifests/repo/elasticsearch10.pp index f0f30f9..f4d62fd 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/elasticsearch10.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/elasticsearch10.pp @@ -7,11 +7,12 @@ ) { yum::managed_yumrepo { 'elasticsearch-1.0': - descr => 'Elasticsearch repository for 1.0.x packages', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 1, - gpgkey => 'http://packages.elasticsearch.org/GPG-KEY-elasticsearch', + descr => 'Elasticsearch repository for 1.0.x packages', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elasticsearch', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-elasticsearch', } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/elasticsearch17.pp b/puphpet/puppet/modules/yum/manifests/repo/elasticsearch17.pp new file mode 100644 index 0000000..c9ab34e --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/elasticsearch17.pp @@ -0,0 +1,18 @@ +# = Class: yum::repo::elasticsearch17 +# +# This class installs the elasticsearch17 repo +# +class yum::repo::elasticsearch17 ( + $baseurl = 'http://packages.elasticsearch.org/elasticsearch/1.7/centos', +) { + + yum::managed_yumrepo { 'elasticsearch-1.7': + descr => 'Elasticsearch repository for 1.7.x packages', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elasticsearch', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-elasticsearch', + } + +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/elasticsearch90.pp b/puphpet/puppet/modules/yum/manifests/repo/elasticsearch90.pp index 46b205e..043915b 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/elasticsearch90.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/elasticsearch90.pp @@ -7,11 +7,12 @@ ) { yum::managed_yumrepo { 'elasticsearch-0.90': - descr => 'Elasticsearch repository for 0.90.x packages', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 1, - gpgkey => 'http://packages.elasticsearch.org/GPG-KEY-elasticsearch', + descr => 'Elasticsearch repository for 0.90.x packages', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elasticsearch', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-elasticsearch', } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/elastix.pp b/puphpet/puppet/modules/yum/manifests/repo/elastix.pp index 9a042b1..e2da8c5 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/elastix.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/elastix.pp @@ -5,51 +5,51 @@ class yum::repo::elastix { yum::managed_yumrepo { 'elastix-base': - descr => 'Base RPM Repository for Elastix', - mirrorlist => 'http://mirror.elastix.org/?release=2&arch=$basearch&repo=base', - enabled => 1, - gpgcheck => 1, - gpgkey => 'http://repo.elastix.org/elastix/RPM-GPG-KEY-Elastix', - autokeyimport => 'yes', + descr => 'Base RPM Repository for Elastix', + mirrorlist => 'http://mirror.elastix.org/?release=2&arch=$basearch&repo=base', + enabled => 1, + gpgcheck => 1, + gpgkey => 'http://repo.elastix.org/elastix/RPM-GPG-KEY-Elastix', + autokeyimport => 'yes', } yum::managed_yumrepo { 'elastix-updates': - descr => 'Updates RPM Repository for Elastix', - mirrorlist => 'http://mirror.elastix.org/?release=2&arch=$basearch&repo=updates', - enabled => 1, - gpgcheck => 1, - gpgkey => 'http://repo.elastix.org/elastix/RPM-GPG-KEY-Elastix', + descr => 'Updates RPM Repository for Elastix', + mirrorlist => 'http://mirror.elastix.org/?release=2&arch=$basearch&repo=updates', + enabled => 1, + gpgcheck => 1, + gpgkey => 'http://repo.elastix.org/elastix/RPM-GPG-KEY-Elastix', } yum::managed_yumrepo { 'elastix-beta': - descr => 'Beta RPM Repository for Elastix', - mirrorlist => 'http://mirror.elastix.org/?release=2&arch=$basearch&repo=beta', - enabled => 0, - gpgcheck => 1, - gpgkey => 'http://repo.elastix.org/elastix/RPM-GPG-KEY-Elastix', + descr => 'Beta RPM Repository for Elastix', + mirrorlist => 'http://mirror.elastix.org/?release=2&arch=$basearch&repo=beta', + enabled => 0, + gpgcheck => 1, + gpgkey => 'http://repo.elastix.org/elastix/RPM-GPG-KEY-Elastix', } yum::managed_yumrepo { 'elastix-extras': - descr => 'Extras RPM Repository for Elastix', - mirrorlist => 'http://mirror.elastix.org/?release=2&arch=$basearch&repo=extras', - enabled => 1, - gpgcheck => 1, - gpgkey => 'http://repo.elastix.org/elastix/RPM-GPG-KEY-Elastix', + descr => 'Extras RPM Repository for Elastix', + mirrorlist => 'http://mirror.elastix.org/?release=2&arch=$basearch&repo=extras', + enabled => 1, + gpgcheck => 1, + gpgkey => 'http://repo.elastix.org/elastix/RPM-GPG-KEY-Elastix', } yum::managed_yumrepo { 'elastix-commercial-addons': - descr => 'Commercial-Addons RPM Repository for Elastix', - mirrorlist => 'http://mirror.elastix.org/?release=2&arch=$basearch&repo=commercial_addons', - enabled => 1, - gpgcheck => 1, - gpgkey => 'http://repo.elastix.org/elastix/RPM-GPG-KEY-Elastix', + descr => 'Commercial-Addons RPM Repository for Elastix', + mirrorlist => 'http://mirror.elastix.org/?release=2&arch=$basearch&repo=commercial_addons', + enabled => 1, + gpgcheck => 1, + gpgkey => 'http://repo.elastix.org/elastix/RPM-GPG-KEY-Elastix', } yum::managed_yumrepo { 'elastix-LowayResearch': - descr => 'Loway Research Yum Repository', - baseurl => 'http://yum.loway.ch/RPMS', - enabled => 1, - gpgcheck => 0, + descr => 'Loway Research Yum Repository', + baseurl => 'http://yum.loway.ch/RPMS', + enabled => 1, + gpgcheck => 0, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/elrepo.pp b/puphpet/puppet/modules/yum/manifests/repo/elrepo.pp index 60ae3e0..cdab70b 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/elrepo.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/elrepo.pp @@ -20,7 +20,7 @@ if $mirror_url { validate_re( $mirror_url, - '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\/[\w~-]*)*$', + '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\:[0-9]{1,5})?(?:\/[\w~-]*)*$', '$mirror must be a Clean URL with no query-string, a fully-qualified hostname and no trailing slash.' ) } diff --git a/puphpet/puppet/modules/yum/manifests/repo/epel.pp b/puphpet/puppet/modules/yum/manifests/repo/epel.pp index 4039d81..2e97575 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/epel.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/epel.pp @@ -14,21 +14,21 @@ # Default: `undef` # class yum::repo::epel ( - $mirror_url = undef, + $mirror_url = undef ) { if $mirror_url { validate_re( $mirror_url, - '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\/[\w~-]*)*$', + '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\:[0-9]{1,5})?(?:\/[\w~-]*)*$', '$mirror must be a Clean URL with no query-string, a fully-qualified hostname and no trailing slash.' ) } - if $::operatingsystem == 'Amazon' { - $osver = [ '6' ] - } else { - $osver = split($::operatingsystemrelease, '[.]') + $osver = $::operatingsystem ? { + 'Amazon' => [ '6' ], + 'XenServer' => [ '5' ], + default => split($::operatingsystemrelease, '[.]') } $baseurl_epel = $mirror_url ? { diff --git a/puphpet/puppet/modules/yum/manifests/repo/esl.pp b/puphpet/puppet/modules/yum/manifests/repo/esl.pp index e3168be..112670d 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/esl.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/esl.pp @@ -7,12 +7,13 @@ ) { yum::managed_yumrepo { 'esl': - descr => 'Erlang Solutions', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 0, - gpgkey => 'http://packages.erlang-solutions.com/rpm/erlang_solutions.asc', - priority => 10, + descr => 'Erlang Solutions', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 0, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-erlang_solutions', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-elasticsearch', + priority => 10, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/foreman.pp b/puphpet/puppet/modules/yum/manifests/repo/foreman.pp index adf1bf4..2816ece 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/foreman.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/foreman.pp @@ -3,17 +3,19 @@ # This class installs the foreman repo # class yum::repo::foreman ( - $baseurl_main = 'http://yum.theforeman.org/stable/', + $baseurl_main = "http://yum.theforeman.org/releases/latest/el${::operatingsystemmajrelease}/${::hardwaremodel}/", $baseurl_plugins = undef, ) { - + if $::operatingsystemmajrelease < 6 { + warning('The Foreman repo is only available for RHEL >= 6') + } yum::managed_yumrepo { 'foreman': descr => 'Foreman Repo', baseurl => $baseurl_main, enabled => 1, gpgcheck => 1, failovermethod => 'priority', - gpgkey => 'http://yum.theforeman.org/RPM-GPG-KEY-foreman', + gpgkey => 'http://yum.theforeman.org/releases/latest/RPM-GPG-KEY-foreman', priority => 1, } diff --git a/puphpet/puppet/modules/yum/manifests/repo/icinga.pp b/puphpet/puppet/modules/yum/manifests/repo/icinga.pp new file mode 100644 index 0000000..eae20b4 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/icinga.pp @@ -0,0 +1,20 @@ +# = Class: yum::repo::icinga +# +# This class installs the icinga repo +# +class yum::repo::icinga ( + $baseurl = 'http://packages.icinga.org/epel/$releasever/release/', +) { + + yum::managed_yumrepo { 'icinga': + descr => 'ICINGA (stable release for epel)', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-icinga', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-icinga', + priority => 1, + failovermethod => 'priority', + } + +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/integ_ganeti.pp b/puphpet/puppet/modules/yum/manifests/repo/integ_ganeti.pp index f43eb97..16a7918 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/integ_ganeti.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/integ_ganeti.pp @@ -20,7 +20,7 @@ if $mirror_url { validate_re( $mirror_url, - '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\/[\w~-]*)*$', + '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\:[0-9]{1,5})?(?:\/[\w~-]*)*$', '$mirror must be a Clean URL with no query-string, a fully-qualified hostname and no trailing slash.' ) } @@ -51,19 +51,19 @@ } yum::managed_yumrepo { 'integ-ganeti': - descr => "Integ Ganeti Packages ${osver[0]} - \$basearch", - baseurl => $baseurl_integ_ganeti, - enabled => 1, - gpgcheck => 0, - priority => 15, + descr => "Integ Ganeti Packages ${osver[0]} - \$basearch", + baseurl => $baseurl_integ_ganeti, + enabled => 1, + gpgcheck => 0, + priority => 15, } yum::managed_yumrepo { 'integ-ganeti-source': - descr => "Integ Ganeti Packages ${osver[0]} - Source", - baseurl => $baseurl_integ_ganeti_source, - enabled => 0, - gpgcheck => 0, - priority => 15, + descr => "Integ Ganeti Packages ${osver[0]} - Source", + baseurl => $baseurl_integ_ganeti_source, + enabled => 0, + gpgcheck => 0, + priority => 15, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/karan.pp b/puphpet/puppet/modules/yum/manifests/repo/karan.pp index 96059ec..c85a934 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/karan.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/karan.pp @@ -5,13 +5,13 @@ class yum::repo::karan { yum::managed_yumrepo { 'kbs-CentOS-Extras': - descr => 'CentOS.Karan.Org-EL$releasever - Stable', - baseurl => 'http://centos.karan.org/el$releasever/extras/stable/$basearch/RPMS/', - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-kbsingh', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-kbsingh', - priority => 20, + descr => 'CentOS.Karan.Org-EL$releasever - Stable', + baseurl => 'http://centos.karan.org/el$releasever/extras/stable/$basearch/RPMS/', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-kbsingh', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-kbsingh', + priority => 20, } yum::managed_yumrepo { 'kbs-CentOS-Extras-Testing': diff --git a/puphpet/puppet/modules/yum/manifests/repo/kibana41.pp b/puphpet/puppet/modules/yum/manifests/repo/kibana41.pp new file mode 100644 index 0000000..c3bf343 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/kibana41.pp @@ -0,0 +1,18 @@ +# = Class: yum::repo::kibana41 +# +# This class installs the kibana41 repo +# +class yum::repo::kibana41 ( + $baseurl = 'http://packages.elasticsearch.org/kibana/4.1/centos', +) { + + yum::managed_yumrepo { 'kibana-4.1': + descr => 'Elasticsearch repository for kibana 4.1', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elasticsearch', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-elasticsearch', + } + +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/logstash13.pp b/puphpet/puppet/modules/yum/manifests/repo/logstash13.pp index ca08b9c..06f6653 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/logstash13.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/logstash13.pp @@ -7,11 +7,12 @@ ) { yum::managed_yumrepo { 'logstash-1.3': - descr => 'logstash repository for 1.3.x packages', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 1, - gpgkey => 'http://packages.elasticsearch.org/GPG-KEY-elasticsearch', + descr => 'logstash repository for 1.3.x packages', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elasticsearch', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-elasticsearch', } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/logstash14.pp b/puphpet/puppet/modules/yum/manifests/repo/logstash14.pp index c7f6736..a5854fd 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/logstash14.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/logstash14.pp @@ -1,17 +1,18 @@ # = Class: yum::repo::logstash14 # -# This class installs the logstash13 repo +# This class installs the logstash14 repo # class yum::repo::logstash14 ( $baseurl = 'http://packages.elasticsearch.org/logstash/1.4/centos', ) { yum::managed_yumrepo { 'logstash-1.4': - descr => 'logstash repository for 1.4.x packages', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 1, - gpgkey => 'http://packages.elasticsearch.org/GPG-KEY-elasticsearch', + descr => 'logstash repository for 1.4.x packages', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elasticsearch', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-elasticsearch', } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/logstashforwarder.pp b/puphpet/puppet/modules/yum/manifests/repo/logstashforwarder.pp new file mode 100644 index 0000000..aa74a8c --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/logstashforwarder.pp @@ -0,0 +1,18 @@ +# = Class: yum::repo::logstashforwarder +# +# This class installs the logstashforwarder (former lumberjack) repo. +# +class yum::repo::logstashforwarder ( + $baseurl = 'http://packages.elasticsearch.org/logstashforwarder/centos', +) { + + yum::managed_yumrepo { 'logstashfowarder': + descr => 'logstashforwarder repository for logstashforwarder packages', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elasticsearch', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-elasticsearch', + } + +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/mod_pagespeed.pp b/puphpet/puppet/modules/yum/manifests/repo/mod_pagespeed.pp index 942b293..432922c 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/mod_pagespeed.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/mod_pagespeed.pp @@ -6,9 +6,9 @@ $baseurl = 'http://dl.google.com/linux/mod-pagespeed/rpm/stable/$basearch', ) { yum::managed_yumrepo { 'mod-pagespeed': - descr => 'mod-pagespeed', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 1 + descr => 'mod-pagespeed', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/mongodb.pp b/puphpet/puppet/modules/yum/manifests/repo/mongodb.pp index 9cf2050..4c2b93e 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/mongodb.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/mongodb.pp @@ -7,10 +7,10 @@ ) { yum::managed_yumrepo { 'mongodb': - descr => '10gen MongoDB Repo', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 0, + descr => '10gen MongoDB Repo', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 0, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/mysql_community.pp b/puphpet/puppet/modules/yum/manifests/repo/mysql_community.pp index 82b6a64..9c2a2e3 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/mysql_community.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/mysql_community.pp @@ -6,52 +6,63 @@ $enabled_version = '5.6' ) { yum::managed_yumrepo { 'mysql-connectors-community': - descr => 'MySQL Connectors Community', - baseurl => 'http://repo.mysql.com/yum/mysql-connectors-community/el/6/$basearch/', - enabled => '1', - gpgcheck => '1', - gpgkey => 'file:/etc/pki/rpm-gpg/RPM-GPG-KEY-mysql', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-mysql' - + descr => 'MySQL Connectors Community', + baseurl => 'http://repo.mysql.com/yum/mysql-connectors-community/el/6/$basearch/', + enabled => '1', + gpgcheck => '1', + gpgkey => 'file:/etc/pki/rpm-gpg/RPM-GPG-KEY-mysql', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-mysql' } yum::managed_yumrepo { 'mysql-tools-community': - descr => 'MySQL Tools Community', - baseurl => 'http://repo.mysql.com/yum/mysql-tools-community/el/6/$basearch/', - enabled => '1', - gpgcheck => '1', - gpgkey => 'file:/etc/pki/rpm-gpg/RPM-GPG-KEY-mysql', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-mysql' + descr => 'MySQL Tools Community', + baseurl => 'http://repo.mysql.com/yum/mysql-tools-community/el/6/$basearch/', + enabled => '1', + gpgcheck => '1', + gpgkey => 'file:/etc/pki/rpm-gpg/RPM-GPG-KEY-mysql', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-mysql' } # Enable to use MySQL 5.5 + $enabled_55 = $enabled_version ? { + '5.5' => '1', + default => '0', + } yum::managed_yumrepo { 'mysql55-community': - descr => 'MySQL 5.5 Community Server', - baseurl => 'http://repo.mysql.com/yum/mysql-5.5-community/el/6/$basearch/', - enabled => $enabled_version ? { '5.5' => '1', default => '0' }, - gpgcheck => '1', - gpgkey => 'file:/etc/pki/rpm-gpg/RPM-GPG-KEY-mysql', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-mysql' + descr => 'MySQL 5.5 Community Server', + baseurl => 'http://repo.mysql.com/yum/mysql-5.5-community/el/6/$basearch/', + enabled => $enabled_55, + gpgcheck => '1', + gpgkey => 'file:/etc/pki/rpm-gpg/RPM-GPG-KEY-mysql', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-mysql' } # Enable to use MySQL 5.6 + $enabled_56 = $enabled_version ? { + '5.6' => '1', + default => '0', + } yum::managed_yumrepo { 'mysql56-community': - descr => 'MySQL 5.6 Community Server', - baseurl => 'http://repo.mysql.com/yum/mysql-5.6-community/el/6/$basearch/', - enabled => $enabled_version ? { '5.6' => '1', default => '0' }, - gpgcheck => '1', - gpgkey => 'file:/etc/pki/rpm-gpg/RPM-GPG-KEY-mysql', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-mysql' + descr => 'MySQL 5.6 Community Server', + baseurl => 'http://repo.mysql.com/yum/mysql-5.6-community/el/6/$basearch/', + enabled => $enabled_56, + gpgcheck => '1', + gpgkey => 'file:/etc/pki/rpm-gpg/RPM-GPG-KEY-mysql', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-mysql' } # Note: MySQL 5.7 is currently in development. For use at your own risk. # Please read with sub pages: https://dev.mysql.com/doc/relnotes/mysql/5.7/en/ + $enabled_57 = $enabled_version ? { + '5.7' => '1', + default => '0', + } yum::managed_yumrepo { 'mysql57-community-dmr': - descr => 'MySQL 5.7 Community Server Development Milestone Release', - baseurl => 'http://repo.mysql.com/yum/mysql-5.7-community/el/6/$basearch/', - enabled => $enabled_version ? { '5.7' => '1', default => '0' }, - gpgcheck => '1', - gpgkey => 'file:/etc/pki/rpm-gpg/RPM-GPG-KEY-mysql', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-mysql' + descr => 'MySQL 5.7 Community Server Development Milestone Release', + baseurl => 'http://repo.mysql.com/yum/mysql-5.7-community/el/6/$basearch/', + enabled => $enabled_57, + gpgcheck => '1', + gpgkey => 'file:/etc/pki/rpm-gpg/RPM-GPG-KEY-mysql', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-mysql' } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/openshift3.pp b/puphpet/puppet/modules/yum/manifests/repo/openshift3.pp new file mode 100644 index 0000000..fd252d5 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/openshift3.pp @@ -0,0 +1,14 @@ +# = Class: yum::repo::openshift3 +# +# This class installs the openshift3 repo +# +class yum::repo::openshift3 { + yum::managed_yumrepo { 'openshift3': + descr => 'RedHat Openshift 3 $basearch repo', + baseurl => 'https://mirror.openshift.com/pub/openshift-v3/dependencies/centos7/$basearch/', + enabled => 1, + gpgcheck => 0, + failovermethod => 'priority', + priority => 1, + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/openshift_server.pp b/puphpet/puppet/modules/yum/manifests/repo/openshift_server.pp new file mode 100644 index 0000000..7050119 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/openshift_server.pp @@ -0,0 +1,32 @@ +# = Class: yum::repo::openshift-server +# +# This class installs the openshift-server repo for CentOS6 +# Used for puppet-openshift_origin (https://github.com/openshift/puppet-openshift_origin) +# when setting 'install_method' to 'none' in addition with 'yum::repo::epel' and 'yum::repo::jenkins' +# +class yum::repo::openshift_server ($version=4) { + if $::operatingsystemrelease !~ /^6/ { + warning('The module \'Yum::Repo::Openshift-server\' works only for RHEL6') + } + yum::managed_yumrepo { 'openshift-origin': + descr => 'Openshift Origin', + baseurl => "https://mirror.openshift.com/pub/origin-server/release/${version}/rhel-6/packages/${::architecture}", + enabled => 1, + gpgcheck => 0, + failovermethod => 'priority', + priority => 1, + mirrorlist => absent, + require => Package['yum-plugin-priorities'], + } + + yum::managed_yumrepo { 'openshift-deps': + descr => 'Openshift Dependencies', + baseurl => "https://mirror.openshift.com/pub/origin-server/release/${version}/rhel-6/dependencies/${::architecture}", + enabled => 1, + gpgcheck => 0, + failovermethod => 'priority', + priority => 1, + mirrorlist => absent, + require => Package['yum-plugin-priorities'], + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/percona.pp b/puphpet/puppet/modules/yum/manifests/repo/percona.pp new file mode 100644 index 0000000..0fb15ba --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/percona.pp @@ -0,0 +1,15 @@ +# = Class: yum::repo::percona +# +# This class installs the Percona RPM Repository +# +class yum::repo::percona { + yum::managed_yumrepo { 'percona': + descr => 'Percona RPM Repository (http://www.percona.com/percona-lab.html)', + baseurl => 'http://repo.percona.com/centos/$releasever/os/$basearch/', + enabled => 1, + gpgcheck => 1, + failovermethod => 'priority', + gpgkey => 'http://www.percona.com/downloads/RPM-GPG-KEY-percona', + priority => 1, + } +} \ No newline at end of file diff --git a/puphpet/puppet/modules/yum/manifests/repo/pgdg91.pp b/puphpet/puppet/modules/yum/manifests/repo/pgdg91.pp index 2802c29..49b37aa 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/pgdg91.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/pgdg91.pp @@ -7,13 +7,13 @@ ) { yum::managed_yumrepo { 'pgdg91': - descr => 'PostgreSQL 9.1 $releasever - $basearch', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-PGDG', - priority => 20, + descr => 'PostgreSQL 9.1 $releasever - $basearch', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-PGDG', + priority => 20, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/pgdg92.pp b/puphpet/puppet/modules/yum/manifests/repo/pgdg92.pp index fda421d..78ac034 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/pgdg92.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/pgdg92.pp @@ -7,13 +7,13 @@ ) { yum::managed_yumrepo { 'pgdg92': - descr => 'PostgreSQL 9.2 $releasever - $basearch', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-PGDG', - priority => 20, + descr => 'PostgreSQL 9.2 $releasever - $basearch', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-PGDG', + priority => 20, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/pgdg93.pp b/puphpet/puppet/modules/yum/manifests/repo/pgdg93.pp index 56fd1ef..e74fb22 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/pgdg93.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/pgdg93.pp @@ -7,13 +7,13 @@ ) { yum::managed_yumrepo { 'pgdg93': - descr => 'PostgreSQL 9.3 $releasever - $basearch', - baseurl => $baseurl, - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-PGDG', - priority => 20, + descr => 'PostgreSQL 9.3 $releasever - $basearch', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-PGDG', + priority => 20, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/pgdg94.pp b/puphpet/puppet/modules/yum/manifests/repo/pgdg94.pp new file mode 100644 index 0000000..9fee4dd --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/pgdg94.pp @@ -0,0 +1,15 @@ +# = Class: yum::repo::pdgd94 +# +# This class installs the postgresql 9.4 repo +# +class yum::repo::pgdg94 { + yum::managed_yumrepo { 'pgdg94': + descr => 'PostgreSQL 9.4 $releasever - $basearch', + baseurl => 'http://yum.postgresql.org/9.4/redhat/rhel-$releasever-$basearch', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-PGDG', + priority => 20, + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/pgdg95.pp b/puphpet/puppet/modules/yum/manifests/repo/pgdg95.pp new file mode 100644 index 0000000..f01532e --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/pgdg95.pp @@ -0,0 +1,15 @@ +# = Class: yum::repo::pdgd95 +# +# This class installs the postgresql 9.5 repo +# +class yum::repo::pgdg95 { + yum::managed_yumrepo { 'pgdg95': + descr => 'PostgreSQL 9.5 $releasever - $basearch', + baseurl => 'http://yum.postgresql.org/9.5/redhat/rhel-$releasever-$basearch', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-PGDG', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-PGDG', + priority => 20, + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/pulp.pp b/puphpet/puppet/modules/yum/manifests/repo/pulp.pp new file mode 100644 index 0000000..a7891b9 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/pulp.pp @@ -0,0 +1,20 @@ +# = Class: yum::repo::pulp +# +# This class installs the pulp repo for CentOS7 +# +class yum::repo::pulp { + if $::operatingsystemmajrelease !~ /^(5|6|7)$/ { + warning('The module \'Yum::Repo::Pulp\' works only for RHEL 5,6 and 7.') + } + + yum::managed_yumrepo { 'pulp-2-stable': + descr => 'Pulp 2 Production Releases', + baseurl => "https://repos.fedorapeople.org/repos/pulp/pulp/stable/2/${::operatingsystemmajrelease}/${::architecture}/", + enabled => 1, + gpgcheck => 1, + gpgkey => 'https://repos.fedorapeople.org/repos/pulp/pulp/GPG-RPM-KEY-pulp-2', + failovermethod => 'priority', + priority => 10, + mirrorlist => absent, + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/puppetlabs.pp b/puphpet/puppet/modules/yum/manifests/repo/puppetlabs.pp index 3d322b1..8e811a3 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/puppetlabs.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/puppetlabs.pp @@ -6,10 +6,13 @@ $baseurl_products = '', $baseurl_dependencies = '', ) { - $osver = split($::operatingsystemrelease, '[.]') + $osver = $::operatingsystem ? { + 'XenServer' => [ '5' ], + default => split($::operatingsystemrelease, '[.]') + } $release = $::operatingsystem ? { - /(?i:Centos|RedHat|Scientific|CloudLinux)/ => $osver[0], - default => '6', + /(?i:Centos|RedHat|Scientific|CloudLinux|XenServer)/ => $osver[0], + default => '6', } $real_baseurl_products = $baseurl_products ? { diff --git a/puphpet/puppet/modules/yum/manifests/repo/puppetlabs_collections.pp b/puphpet/puppet/modules/yum/manifests/repo/puppetlabs_collections.pp new file mode 100644 index 0000000..9164be4 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/puppetlabs_collections.pp @@ -0,0 +1,33 @@ +# = Class: yum::repo::puppetlabs_collections +# +# This class installs the puppetlabs-collections repo +# +class yum::repo::puppetlabs_collections ( + $baseurl = '', + $collection = '1', +) { + $osver = $::operatingsystem ? { + 'XenServer' => [ '5' ], + default => split($::operatingsystemrelease, '[.]') + } + $release = $::operatingsystem ? { + /(?i:Centos|RedHat|Scientific|CloudLinux|XenServer)/ => $osver[0], + default => '6', + } + + $real_baseurl = $baseurl ? { + '' => "http://yum.puppetlabs.com/el/${release}/PC${collection}/\$basearch", + default => $baseurl, + } + + yum::managed_yumrepo { 'puppetlabs': + descr => 'Puppet Labs Puppet Collections', + baseurl => $real_baseurl, + enabled => 1, + gpgcheck => 1, + failovermethod => 'priority', + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-puppetlabs', + } + +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/remi.pp b/puphpet/puppet/modules/yum/manifests/repo/remi.pp index f27d6c9..6e3e179 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/remi.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/remi.pp @@ -4,22 +4,22 @@ # class yum::repo::remi { yum::managed_yumrepo { 'remi': - descr => 'Les RPM de remi pour Enterpise Linux $releasever - $basearch', - mirrorlist => 'http://rpms.famillecollet.com/enterprise/$releasever/remi/mirror', - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-remi', - priority => 1, + descr => 'Les RPM de remi pour Enterpise Linux $releasever - $basearch', + mirrorlist => 'http://rpms.famillecollet.com/enterprise/$releasever/remi/mirror', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-remi', + priority => 1, } yum::managed_yumrepo { 'remi-test': - descr => 'Les RPM de remi pour Enterpise Linux $releasever - $basearch - Test', - mirrorlist => 'http://rpms.famillecollet.com/enterprise/$releasever/test/mirror', - enabled => 0, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-remi', - priority => 1, + descr => 'Les RPM de remi pour Enterpise Linux $releasever - $basearch - Test', + mirrorlist => 'http://rpms.famillecollet.com/enterprise/$releasever/test/mirror', + enabled => 0, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-remi', + priority => 1, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/remi_php55.pp b/puphpet/puppet/modules/yum/manifests/repo/remi_php55.pp old mode 100755 new mode 100644 index 13a9412..59e784d --- a/puphpet/puppet/modules/yum/manifests/repo/remi_php55.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/remi_php55.pp @@ -4,12 +4,12 @@ # class yum::repo::remi_php55 { yum::managed_yumrepo { 'remi-php55': - descr => 'Les RPM de remi pour Enterpise Linux $releasever - $basearch - PHP 5.5', - mirrorlist => 'http://rpms.famillecollet.com/enterprise/$releasever/php55/mirror', - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-remi', - priority => 1, + descr => 'Les RPM de remi pour Enterpise Linux $releasever - $basearch - PHP 5.5', + mirrorlist => 'http://rpms.famillecollet.com/enterprise/$releasever/php55/mirror', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-remi', + priority => 1, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/remi_php56.pp b/puphpet/puppet/modules/yum/manifests/repo/remi_php56.pp old mode 100755 new mode 100644 index 15a1aa2..1b93132 --- a/puphpet/puppet/modules/yum/manifests/repo/remi_php56.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/remi_php56.pp @@ -4,12 +4,12 @@ # class yum::repo::remi_php56 { yum::managed_yumrepo { 'remi-php56': - descr => 'Les RPM de remi pour Enterpise Linux $releasever - $basearch - PHP 5.6', - mirrorlist => 'http://rpms.famillecollet.com/enterprise/$releasever/php56/mirror', - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-remi', - priority => 1, + descr => 'Les RPM de remi pour Enterpise Linux $releasever - $basearch - PHP 5.6', + mirrorlist => 'http://rpms.famillecollet.com/enterprise/$releasever/php56/mirror', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-remi', + priority => 1, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/remi_php70.pp b/puphpet/puppet/modules/yum/manifests/repo/remi_php70.pp new file mode 100644 index 0000000..5d87341 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/remi_php70.pp @@ -0,0 +1,24 @@ +# = Class: yum::repo::remi_php70 +# +# This class installs the remi-php70 repo +# +class yum::repo::remi_php70 { + yum::managed_yumrepo { 'remi-php70': + descr => 'Remi\'s PHP 7.0 RPM repository for Enterprise Linux 7 - $basearch', + mirrorlist => 'http://rpms.remirepo.net/enterprise/7/php70/mirror', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-remi', + priority => 1, + } + + yum::managed_yumrepo { 'remi-php70-debuginfo': + descr => 'Remi\'s PHP 7.0 RPM repository for Enterprise Linux 7 - $basearch - debuginfo', + baseurl => 'http://rpms.remirepo.net/enterprise/7/debug-php70/$basearch/', + enabled => 0, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-remi', + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/repoforge.pp b/puphpet/puppet/modules/yum/manifests/repo/repoforge.pp index b43e57d..ab95d10 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/repoforge.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/repoforge.pp @@ -4,15 +4,17 @@ # class yum::repo::repoforge { + $osver = split($::operatingsystemrelease, '[.]') + yum::managed_yumrepo { 'repoforge': - descr => 'RepoForge packages', - baseurl => 'http://apt.sw.be/redhat/el$releasever/en/$basearch/rpmforge', - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-rpmforge-dag', - priority => 1, - exclude => 'nagios-*', + descr => 'RepoForge packages', + baseurl => "http://apt.sw.be/redhat/el${osver[0]}/en/\$basearch/rpmforge", + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-rpmforge-dag', + priority => 1, + exclude => 'nagios-*', } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/repoforgeextras.pp b/puphpet/puppet/modules/yum/manifests/repo/repoforgeextras.pp index 5242b58..5a4c73f 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/repoforgeextras.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/repoforgeextras.pp @@ -4,9 +4,11 @@ # class yum::repo::repoforgeextras { + $osver = split($::operatingsystemrelease, '[.]') + yum::managed_yumrepo { 'repoforgeextras': descr => 'RepoForge extra packages', - baseurl => 'http://apt.sw.be/redhat/el$releasever/en/$basearch/extras', + baseurl => "http://apt.sw.be/redhat/el${osver[0]}/en/\$basearch/extras", enabled => 1, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag', diff --git a/puphpet/puppet/modules/yum/manifests/repo/rpmforge.pp b/puphpet/puppet/modules/yum/manifests/repo/rpmforge.pp index 529de25..6783c0e 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/rpmforge.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/rpmforge.pp @@ -1,10 +1,14 @@ # = Class: yum::repo::rpmforge # -# This class installs the rpmforce repo +# This class installs the rpmforge repo # class yum::repo::rpmforge { $osver = split($::operatingsystemrelease, '[.]') case $osver[0] { + '7': { + $baseurl = 'http://apt.sw.be/redhat/el7/en/$basearch/rpmforge' + $mirrorlist = 'http://apt.sw.be/redhat/el7/en/mirrors-rpmforge' + } '6': { $baseurl = 'http://apt.sw.be/redhat/el6/en/$basearch/rpmforge' $mirrorlist = 'http://apt.sw.be/redhat/el6/en/mirrors-rpmforge' @@ -13,17 +17,17 @@ $baseurl = 'http://apt.sw.be/redhat/el5/en/$basearch/rpmforge' $mirrorlist = 'http://apt.sw.be/redhat/el5/en/mirrors-rpmforge' } - default: { fail("Unsupported version of Enterprise Linux") } + default: { fail('Unsupported version of Enterprise Linux') } } yum::managed_yumrepo { 'rpmforge': - baseurl => $baseurl, - mirrorlist => $mirrorlist, - descr => 'RHEL $releasever - RPMforge.net - dag', - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-rpmforge-dag', - priority => 30, + baseurl => $baseurl, + mirrorlist => $mirrorlist, + descr => 'RHEL $releasever - RPMforge.net - dag', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-rpmforge-dag', + priority => 30, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/rsyslog_v7.pp b/puphpet/puppet/modules/yum/manifests/repo/rsyslog_v7.pp index d2f2ba2..a1eadda 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/rsyslog_v7.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/rsyslog_v7.pp @@ -6,14 +6,6 @@ $mirror_url = undef ) { - if $mirror_url { - validate_re( - $mirror_url, - '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\/[\w~-]*)*$', - '$mirror must be a Clean URL with no query-string, a fully-qualified hostname and no trailing slash.' - ) - } - $real_mirror_url = $mirror_url ? { default => $mirror_url, undef => 'http://rpms.adiscon.com/v7-stable/epel-$releasever/$basearch' @@ -24,10 +16,9 @@ baseurl => $real_mirror_url, enabled => 1, gpgcheck => 1, - gpgkey => "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Adiscon", - gpgkey_source => "puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-Adiscon", + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Adiscon', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-Adiscon', priority => 10, failovermethod => 'priority', } - } diff --git a/puphpet/puppet/modules/yum/manifests/repo/rundeck1.pp b/puphpet/puppet/modules/yum/manifests/repo/rundeck1.pp index fd16681..cfb82ad 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/rundeck1.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/rundeck1.pp @@ -1,3 +1,4 @@ +# class yum::repo::rundeck1 { require yum diff --git a/puphpet/puppet/modules/yum/manifests/repo/rundeck2.pp b/puphpet/puppet/modules/yum/manifests/repo/rundeck2.pp index a67754f..0654afc 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/rundeck2.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/rundeck2.pp @@ -1,3 +1,4 @@ +# class yum::repo::rundeck2 ( $baseurl = 'http://dl.bintray.com/rundeck/rundeck-rpm' ){ diff --git a/puphpet/puppet/modules/yum/manifests/repo/sclruby200.pp b/puphpet/puppet/modules/yum/manifests/repo/sclruby200.pp new file mode 100644 index 0000000..b23f457 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/sclruby200.pp @@ -0,0 +1,29 @@ +# = Class: yum::repo::scl +# +# This class installs the scl ruby200 repo +# +class yum::repo::sclruby200 ( + $baseurl = '' +) { + + $osver = split($::operatingsystemrelease, '[.]') + $release = $::operatingsystem ? { + /(?i:Centos|RedHat|Scientific)/ => $osver[0], + default => '6', + } + + $real_baseurl = $baseurl ? { + '' => "https://www.softwarecollections.org/repos/rhscl/ruby200/epel-${release}-\$basearch/", + default => $baseurl, + } + + yum::managed_yumrepo { 'scl-ruby200': + descr => 'CentOS-$releasever - SCL Ruby200', + baseurl => $real_baseurl, + enabled => 1, + gpgcheck => 0, + priority => 20, + failovermethod => 'priority', + } + +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/shibboleth.pp b/puphpet/puppet/modules/yum/manifests/repo/shibboleth.pp new file mode 100644 index 0000000..4611b7e --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/shibboleth.pp @@ -0,0 +1,14 @@ +# = Class: yum::repo::shibboleth +# +# This class installs the shibboleth repo +# +class yum::repo::shibboleth { + yum::managed_yumrepo { 'shibboleth': + descr => 'Shibboleth yum repository', + baseurl => 'http://download.opensuse.org/repositories/security:/shibboleth/CentOS_$releasever/', + enabled => 1, + gpgcheck => 0, + failovermethod => 'priority', + priority => 1, + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/sl5.pp b/puphpet/puppet/modules/yum/manifests/repo/sl5.pp index 39f2633..03427ab 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/sl5.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/sl5.pp @@ -20,7 +20,7 @@ if $mirror_url { validate_re( $mirror_url, - '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\/[\w~-]*)*$', + '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\:[0-9]{1,5})?(?:\/[\w~-]*)*$', '$mirror must be a Clean URL with no query-string, a fully-qualified hostname and no trailing slash.' ) } diff --git a/puphpet/puppet/modules/yum/manifests/repo/sl6.pp b/puphpet/puppet/modules/yum/manifests/repo/sl6.pp index 4e2daa4..9e2aa41 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/sl6.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/sl6.pp @@ -20,7 +20,7 @@ if $mirror_url { validate_re( $mirror_url, - '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\/[\w~-]*)*$', + '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\:[0-9]{1,5})?(?:\/[\w~-]*)*$', '$mirror must be a Clean URL with no query-string, a fully-qualified hostname and no trailing slash.' ) } @@ -49,6 +49,7 @@ gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-sl file:///etc/pki/rpm-gpg/RPM-GPG-KEY-dawson', gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-sl', + priority => 2, } yum::managed_yumrepo { 'sl6x-security': @@ -59,6 +60,7 @@ enabled => 1, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-sl file:///etc/pki/rpm-gpg/RPM-GPG-KEY-dawson', + priority => 2, } yum::managed_yumrepo { 'sl6x-fastbugs': @@ -69,6 +71,7 @@ enabled => 0, gpgcheck => 1, gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-sl file:///etc/pki/rpm-gpg/RPM-GPG-KEY-dawson', + priority => 2, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/tengen.pp b/puphpet/puppet/modules/yum/manifests/repo/tengen.pp new file mode 100644 index 0000000..b73f084 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/tengen.pp @@ -0,0 +1,14 @@ +# = Class: yum::repo::tengen +# +# This class installs the tengen repo for MongoDB +# +class yum::repo::tengen ( + $baseurl = "http://downloads-distro.mongodb.org/repo/redhat/os/${::architecture}", +) { + yum::managed_yumrepo { 'tengen': + descr => 'tengen Repository', + baseurl => $baseurl, + enabled => 1, + gpgcheck => 0, + } +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/vmware_tools.pp b/puphpet/puppet/modules/yum/manifests/repo/vmware_tools.pp index 86ff231..a11ab55 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/vmware_tools.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/vmware_tools.pp @@ -1,3 +1,4 @@ +# class yum::repo::vmware_tools ( $baseurl = 'http://packages.vmware.com/tools/esx/5.1latest/rhel$releasever/$basearch', ) { diff --git a/puphpet/puppet/modules/yum/manifests/repo/webtatic.pp b/puphpet/puppet/modules/yum/manifests/repo/webtatic.pp index adf9c5d..0fb588e 100644 --- a/puphpet/puppet/modules/yum/manifests/repo/webtatic.pp +++ b/puphpet/puppet/modules/yum/manifests/repo/webtatic.pp @@ -4,16 +4,27 @@ # class yum::repo::webtatic { $osver = split($::operatingsystemrelease, '[.]') + $mirrorlist = $osver[0] ? { + '5' => 'http://repo.webtatic.com/yum/centos/5/$basearch/mirrorlist', + '6' => 'http://repo.webtatic.com/yum/el6/$basearch/mirrorlist', + '7' => 'http://repo.webtatic.com/yum/el7/$basearch/mirrorlist', + } + $gpgkey = $osver[0] ? { + '7' => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-webtatic-el7', + default => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-webtatic-andy', + } + $gpgkey_source = $osver[0] ? { + '7' => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-webtatic-el7', + default => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-webtatic-andy', + } + yum::managed_yumrepo { 'webtatic': - descr => 'Webtatic Repository $releasever - $basearch', - mirrorlist => $osver[0] ? { - 5 => 'http://repo.webtatic.com/yum/centos/5/$basearch/mirrorlist', - 6 => 'http://repo.webtatic.com/yum/el6/$basearch/mirrorlist', - }, - enabled => 1, - gpgcheck => 1, - gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-webtatic-andy', - gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-webtatic-andy', - priority => 1, + descr => 'Webtatic Repository $releasever - $basearch', + mirrorlist => $mirrorlist, + enabled => 1, + gpgcheck => 1, + gpgkey => $gpgkey, + gpgkey_source => $gpgkey_source, + priority => 1, } } diff --git a/puphpet/puppet/modules/yum/manifests/repo/xenserver.pp b/puphpet/puppet/modules/yum/manifests/repo/xenserver.pp new file mode 100644 index 0000000..39f5a41 --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/xenserver.pp @@ -0,0 +1,125 @@ +# = Class: yum::repo::xenserver +# +# Base Centos5 and Citrix repos for XenServer +# +# == Parameters: +# +# [*mirror_url*] +# A clean URL to a mirror of `rsync://msync.centos.org::CentOS`. +# The paramater is interpolated with the known directory structure to +# create a the final baseurl parameter for each yumrepo so it must be +# "clean", i.e., without a query string like `?key1=valA&key2=valB`. +# Additionally, it may not contain a trailing slash. +# Example: `http://mirror.example.com/pub/rpm/centos` +# Default: `undef` +# +class yum::repo::xenserver ( + $mirror_url = undef, +) { + + if $mirror_url { + validate_re( + $mirror_url, + '^(?:https?|ftp):\/\/[\da-zA-Z-][\da-zA-Z\.-]*\.[a-zA-Z]{2,6}\.?(?:\:[0-9]{1,5})?(?:\/[\w~-]*)*$', + '$mirror must be a Clean URL with no query-string, a fully-qualified hostname and no trailing slash.' + ) + } + + $baseurl_base = $mirror_url ? { + undef => undef, + default => "${mirror_url}/\$releasever/os/\$basearch/", + } + + $baseurl_updates = $mirror_url ? { + undef => undef, + default => "${mirror_url}/\$releasever/updates/\$basearch/", + } + + $baseurl_addons = $mirror_url ? { + undef => undef, + default => "${mirror_url}/\$releasever/addons/\$basearch/", + } + + $baseurl_extras = $mirror_url ? { + undef => undef, + default => "${mirror_url}/\$releasever/extras/\$basearch/", + } + + $baseurl_centosplus = $mirror_url ? { + undef => undef, + default => "${mirror_url}/\$releasever/centosplus/\$basearch/", + } + + $baseurl_contrib = $mirror_url ? { + undef => undef, + default => "${mirror_url}/\$releasever/contrib/\$basearch/", + } + + $xenserver_release = split($::lsbdistrelease, '[-]') + $xenserver_base_release = $xenserver_release[0] + + yum::managed_yumrepo { 'base': + descr => 'CentOS-$releasever - Base', + baseurl => $baseurl_base, + mirrorlist => 'http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os', + failovermethod => 'priority', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5', + gpgkey_source => 'puppet:///modules/yum/rpm-gpg/RPM-GPG-KEY-CentOS-5', + priority => 1, + exclude => 'kernel-xen*, *xen*', + } + + yum::managed_yumrepo { 'updates': + descr => 'CentOS-$releasever - Updates', + baseurl => $baseurl_updates, + mirrorlist => 'http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates', + failovermethod => 'priority', + enabled => 1, + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5', + priority => 1, + exclude => 'kernel-xen*, *xen*', + } + + yum::managed_yumrepo { 'extras': + descr => 'CentOS-$releasever - Extras', + baseurl => $baseurl_extras, + mirrorlist => 'http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras', + failovermethod => 'priority', + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5', + priority => 1, + } + + yum::managed_yumrepo { 'centosplus': + descr => 'CentOS-$releasever - Centosplus', + baseurl => $baseurl_centosplus, + mirrorlist => 'http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus', + failovermethod => 'priority', + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5', + priority => 2, + } + + yum::managed_yumrepo { 'contrib': + descr => 'CentOS-$releasever - Contrib', + baseurl => $baseurl_contrib, + mirrorlist => 'http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=contrib', + failovermethod => 'priority', + gpgcheck => 1, + gpgkey => 'file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5', + priority => 10, + } + + yum::managed_yumrepo { 'Citrix': + descr => "XenServer ${xenserver_base_release} updates", + mirrorlist => "http://updates.vmd.citrix.com/XenServer/${xenserver_base_release}/domain0/mirrorlist", + enabled => 1, + gpgcheck => 1, + gpgkey => 'http://updates.vmd.citrix.com/XenServer/RPM-GPG-KEY-6.2.0', + priority => 1, + } + +} diff --git a/puphpet/puppet/modules/yum/manifests/repo/zabbix24.pp b/puphpet/puppet/modules/yum/manifests/repo/zabbix24.pp new file mode 100644 index 0000000..f182c5e --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/repo/zabbix24.pp @@ -0,0 +1,15 @@ +# = Class: yum::repo::zabbix24 +# +# This class installs the zabbix 2.4 repo +# +class yum::repo::zabbix24 { + yum::managed_yumrepo { 'zabbix24': + descr => 'Zabbix 2.4 $releasever - $basearch repo', + baseurl => 'http://repo.zabbix.com/zabbix/2.4/rhel/$releasever/$basearch/', + enabled => 1, + gpgcheck => 1, + failovermethod => 'priority', + gpgkey => 'http://repo.zabbix.com/RPM-GPG-KEY-ZABBIX', + priority => 1, + } +} diff --git a/puphpet/puppet/modules/yum/manifests/versionlock.pp b/puphpet/puppet/modules/yum/manifests/versionlock.pp new file mode 100644 index 0000000..596feec --- /dev/null +++ b/puphpet/puppet/modules/yum/manifests/versionlock.pp @@ -0,0 +1,24 @@ +# = Define yum::versionlock +# +define yum::versionlock ( + $ensure = present, + $path = '/etc/yum/pluginconf.d/versionlock.list', +) { + + include yum::plugin::versionlock + + if ($name =~ /^[0-9]+:.+\*$/) { + $manage_name = $name + } elsif ($name =~ /^[0-9]+:.+-.+-.+\./) { + $manage_name= $name + } else { + fail('Package name must be formated as \'EPOCH:NAME-VERSION-RELEASE.ARCH\'') + } + + file_line { "versionlock.list-${name}": + ensure => $ensure, + line => $manage_name, + path => $path, + require => Class['yum::plugin::versionlock'] + } +} diff --git a/puphpet/puppet/modules/yum/metadata.json b/puphpet/puppet/modules/yum/metadata.json new file mode 100644 index 0000000..030c67d --- /dev/null +++ b/puphpet/puppet/modules/yum/metadata.json @@ -0,0 +1,21 @@ +{ + "name": "example42-yum", + "version": "2.1.25", + "summary": "Puppet module for yum", + "author": "Alessandro Franceschi", + "description": "This module installs and manages yum and several different yum repos", + "dependencies": [ + { + "name": "example42/puppi", + "version_requirement": ">=2.0.0" + } + ], + "types": [ + + ], + "checksums": { + }, + "source": "https://github.com/example42/puppet-yum", + "project_page": "http://www.example42.com", + "license": "Apache2" +} diff --git a/puphpet/puppet/modules/yum/spec/classes/yum_spec.rb b/puphpet/puppet/modules/yum/spec/classes/yum_spec.rb index 62d9f9c..9166e10 100644 --- a/puphpet/puppet/modules/yum/spec/classes/yum_spec.rb +++ b/puphpet/puppet/modules/yum/spec/classes/yum_spec.rb @@ -4,7 +4,7 @@ let(:title) { 'yum' } let(:node) { 'rspec.example42.com' } - let(:facts) { { :ipaddress => '10.42.42.42' } } + let(:facts) { { :ipaddress => '10.42.42.42', :operatingsystemrelease => '6.6' } } describe 'Test minimal installation' do it { should contain_file('yum.conf').with_ensure('present') } diff --git a/puphpet/puppet/modules/yum/templates/yum-cron.erb b/puphpet/puppet/modules/yum/templates/yum-cron.erb index f4f5971..dcce6c4 100644 --- a/puphpet/puppet/modules/yum/templates/yum-cron.erb +++ b/puphpet/puppet/modules/yum/templates/yum-cron.erb @@ -52,7 +52,8 @@ DAYS_OF_WEEK=<%= scope.lookupvar('yum::cron_dotw') %> # which day should it do cleanup on? defaults to 0 (Sunday). If this day isn't in the # DAYS_OF_WEEK above, it'll never happen -CLEANDAY="0" +#CLEANDAY="0" +CLEANDAY="<%= scope.lookupvar('yum::cron_clean_dotw') %>" # set to yes to make the yum-cron service to wait for transactions to complete SERVICE_WAITS=yes diff --git a/puphpet/puppet/nodes/MailCatcher.pp b/puphpet/puppet/nodes/MailCatcher.pp deleted file mode 100644 index be3792f..0000000 --- a/puphpet/puppet/nodes/MailCatcher.pp +++ /dev/null @@ -1,60 +0,0 @@ -class puphpet_mailcatcher ( - $mailcatcher -) { - - include puphpet::supervisord - - if ! defined(Package['tilt']) { - package { 'tilt': - ensure => '1.3', - provider => 'gem', - before => Class['mailcatcher'] - } - } - - if $::operatingsystem == 'ubuntu' and $lsbdistcodename == 'trusty' { - package { 'rubygems': - ensure => absent, - } - } - - $settings = delete( - $mailcatcher['settings'], - 'from_email_method' - ) - - create_resources('class', { 'mailcatcher' => $settings }) - - if ! defined(Puphpet::Firewall::Port[$settings['smtp_port']]) { - puphpet::firewall::port { $settings['smtp_port']: } - } - - if ! defined(Puphpet::Firewall::Port[$settings['http_port']]) { - puphpet::firewall::port { $settings['http_port']: } - } - - $path = $settings['mailcatcher_path'] - - $options = sort(join_keys_to_values({ - ' --smtp-ip' => $settings['smtp_ip'], - ' --smtp-port' => $settings['smtp_port'], - ' --http-ip' => $settings['http_ip'], - ' --http-port' => $settings['http_port'] - }, ' ')) - - supervisord::program { 'mailcatcher': - command => "${path}/mailcatcher ${options} -f", - priority => '100', - user => 'mailcatcher', - autostart => true, - autorestart => 'true', - environment => { - 'PATH' => "/bin:/sbin:/usr/bin:/usr/sbin:${path}" - }, - require => [ - Class['mailcatcher::config'], - File['/var/log/mailcatcher'] - ], - } - -} diff --git a/puphpet/puppet/nodes/MongoDb.pp b/puphpet/puppet/nodes/MongoDb.pp deleted file mode 100644 index a29bd72..0000000 --- a/puphpet/puppet/nodes/MongoDb.pp +++ /dev/null @@ -1,54 +0,0 @@ -class puphpet_mongodb ( - $mongodb, - $apache, - $nginx, - $php -) { - - if array_true($apache, 'install') or array_true($nginx, 'install') { - $webserver_restart = true - } else { - $webserver_restart = false - } - - file { ['/data', '/data/db']: - ensure => directory, - mode => '0775', - before => Class['mongodb::globals'], - } - - Class['mongodb::globals'] - -> Class['mongodb::server'] - - class { 'mongodb::globals': - manage_package_repo => true, - } - - create_resources('class', { - 'mongodb::server' => $mongodb['settings'] - }) - - if $::osfamily == 'redhat' { - class { 'mongodb::client': - require => Class['mongodb::server'] - } - } - - each( $mongodb['databases'] ) |$key, $database| { - $merged = delete(merge($database, { - 'dbname' => $database['name'], - }), 'name') - - create_resources( puphpet::mongodb::db, { - "${database['user']}@${database['name']}" => $merged - }) - } - - if array_true($php, 'install') and ! defined(Puphpet::Php::Pecl['mongo']) { - puphpet::php::pecl { 'mongo': - service_autorestart => $webserver_restart, - require => Class['mongodb::server'] - } - } - -} diff --git a/puphpet/puppet/nodes/NodeJs.pp b/puphpet/puppet/nodes/NodeJs.pp deleted file mode 100644 index 36d574c..0000000 --- a/puphpet/puppet/nodes/NodeJs.pp +++ /dev/null @@ -1,24 +0,0 @@ -class puphpet_nodejs ( - $nodejs -) { - - include puphpet::nodejs - - each( $nodejs['npm_packages'] ) |$package| { - $npm_array = split($package, '@') - - if count($npm_array) == 2 { - $npm_ensure = $npm_array[1] - } else { - $npm_ensure = present - } - - if ! defined(Package[$npm_array[0]]) { - package { $npm_array[0]: - ensure => $npm_ensure, - provider => npm, - } - } - } - -} diff --git a/puphpet/puppet/nodes/Ruby.pp b/puphpet/puppet/nodes/Ruby.pp deleted file mode 100644 index 77923e1..0000000 --- a/puphpet/puppet/nodes/Ruby.pp +++ /dev/null @@ -1,15 +0,0 @@ -class puphpet_ruby ( - $ruby -) { - - User <| title == $::ssh_username |> { - groups +> 'rvm' - } - - if array_true($ruby, 'versions') and count($ruby['versions']) > 0 { - puphpet::ruby::dotfile { 'do': } - - create_resources(puphpet::ruby::install, $ruby['versions']) - } - -} diff --git a/puphpet/ruby/puppet.rb b/puphpet/ruby/puppet.rb new file mode 100644 index 0000000..d473d5c --- /dev/null +++ b/puphpet/ruby/puppet.rb @@ -0,0 +1,277 @@ +require "digest/md5" + +require "log4r" + +module VagrantPlugins + module Puppet + class Plugin < Vagrant.plugin("2") + module Provisioner + class PuppetError < Vagrant::Errors::VagrantError + error_namespace("vagrant.provisioners.puppet") + end + + class Puppet < Vagrant.plugin("2", :provisioner) + def initialize(machine, config) + super + + @logger = Log4r::Logger.new("vagrant::provisioners::puppet") + end + + def configure(root_config) + # Calculate the paths we're going to use based on the environment + root_path = @machine.env.root_path + @expanded_module_paths = @config.expanded_module_paths(root_path) + + # Setup the module paths + @module_paths = [] + @expanded_module_paths.each_with_index do |path, _| + key = Digest::MD5.hexdigest(path.to_s) + @module_paths << [path, File.join(config.temp_dir, "modules-#{key}")] + end + + folder_opts = {} + folder_opts[:type] = @config.synced_folder_type if @config.synced_folder_type + folder_opts[:owner] = "root" if !@config.synced_folder_type + folder_opts[:args] = @config.synced_folder_args if @config.synced_folder_args + folder_opts[:nfs__quiet] = true + + if @config.environment_path.is_a?(Array) + # Share the environments directory with the guest + if @config.environment_path[0].to_sym == :host + root_config.vm.synced_folder( + File.expand_path(@config.environment_path[1], root_path), + environments_guest_path, folder_opts) + end + end + if @config.manifest_file + @manifest_file = File.join(manifests_guest_path, @config.manifest_file) + # Share the manifests directory with the guest + if @config.manifests_path[0].to_sym == :host + root_config.vm.synced_folder( + File.expand_path(@config.manifests_path[1], root_path), + manifests_guest_path, folder_opts) + end + end + + # Share the module paths + @module_paths.each do |from, to| + root_config.vm.synced_folder(from, to, folder_opts) + end + end + + def parse_environment_metadata + # Parse out the environment manifest path since puppet apply doesnt do that for us. + environment_conf = File.join(environments_guest_path, @config.environment, "environment.conf") + if @machine.communicate.test("test -e #{environment_conf}", sudo: true) + @machine.communicate.sudo("cat #{environment_conf}") do | type, data| + if type == :stdout + data.each_line do |line| + if line =~ /^\s*manifest\s+=\s+([^\s]+)/ + @manifest_file = $1 + @manifest_file.gsub! "$codedir", File.dirname(environments_guest_path) + @manifest_file.gsub! "$environment", @config.environment + if !@manifest_file.start_with? "/" + @manifest_file = File.join(environments_guest_path, @config.environment, @manifest_file) + end + @logger.debug("Using manifest from environment.conf: #{@manifest_file}") + end + end + end + end + end + end + + def provision + # If the machine has a wait for reboot functionality, then + # do that (primarily Windows) + if @machine.guest.capability?(:wait_for_reboot) + @machine.guest.capability(:wait_for_reboot) + end + + # In environment mode we still need to specify a manifest file, if its not, use the one from env config if specified. + if !@manifest_file + @manifest_file = "#{environments_guest_path}/#{@config.environment}/manifests" + parse_environment_metadata + end + # Check that the shared folders are properly shared + check = [] + if @config.manifests_path.is_a?(Array) && @config.manifests_path[0] == :host + check << manifests_guest_path + end + if @config.environment_path.is_a?(Array) && @config.environment_path[0] == :host + check << environments_guest_path + end + @module_paths.each do |host_path, guest_path| + check << guest_path + end + + # Make sure the temporary directory is properly set up + @machine.communicate.tap do |comm| + comm.sudo("mkdir -p #{config.temp_dir}") + comm.sudo("chmod 0777 #{config.temp_dir}") + end + + verify_shared_folders(check) + + # Verify Puppet is installed and run it + puppet_bin = "puppet" + verify_binary(puppet_bin) + + # Upload Hiera configuration if we have it + @hiera_config_path = nil + if config.hiera_config_path + local_hiera_path = File.expand_path(config.hiera_config_path, + @machine.env.root_path) + @hiera_config_path = File.join(config.temp_dir, "hiera.yaml") + @machine.communicate.upload(local_hiera_path, @hiera_config_path) + end + + run_puppet_apply + end + + def manifests_guest_path + if config.manifests_path[0] == :host + # The path is on the host, so point to where it is shared + key = Digest::MD5.hexdigest(config.manifests_path[1]) + File.join(config.temp_dir, "manifests-#{key}") + else + # The path is on the VM, so just point directly to it + config.manifests_path[1] + end + end + + def environments_guest_path + if config.environment_path[0] == :host + # The path is on the host, so point to where it is shared + File.join(config.temp_dir, "environments") + else + # The path is on the VM, so just point directly to it + config.environment_path[1] + end + end + + def verify_binary(binary) + # Determine the command to use to test whether Puppet is available. + # This is very platform dependent. + test_cmd = "sh -c 'command -v #{binary}'" + if windows? + test_cmd = "where #{binary}" + if @config.binary_path + test_cmd = "where \"#{@config.binary_path}:#{binary}\"" + end + end + + if !machine.communicate.test(test_cmd) + @config.binary_path = "/opt/puppetlabs/bin/" + @machine.communicate.sudo( + "test -x /opt/puppetlabs/bin/#{binary}", + error_class: PuppetError, + error_key: :not_detected, + binary: binary) + end + end + + def run_puppet_apply + default_module_path = "/etc/puppet/modules" + if windows? + default_module_path = "/ProgramData/PuppetLabs/puppet/etc/modules" + end + + options = [config.options].flatten + module_paths = @module_paths.map { |_, to| to } + if !@module_paths.empty? + # Append the default module path + module_paths << default_module_path + + # Add the command line switch to add the module path + module_path_sep = windows? ? ";" : ":" + options << "--modulepath '#{module_paths.join(module_path_sep)}'" + end + + if @hiera_config_path + options << "--hiera_config=#{@hiera_config_path}" + end + + if !@machine.env.ui.color? + options << "--color=false" + end + + options << "--detailed-exitcodes" + if config.environment_path + options << "--environmentpath #{environments_guest_path}/" + options << "--environment #{@config.environment}" + end + + options << @manifest_file + options = options.join(" ") + + # Build up the custom facts if we have any + facter = "" + if !config.facter.empty? + facts = [] + config.facter.each do |key, value| + facts << "FACTER_#{key}='#{value}'" + end + + # If we're on Windows, we need to use the PowerShell style + if windows? + facts.map! { |v| "$env:#{v};" } + end + + facter = "#{facts.join(" ")} " + end + + puppet_bin = "puppet" + if @config.binary_path + puppet_bin = File.join(@config.binary_path, puppet_bin) + end + + command = "#{facter} #{puppet_bin} apply #{options}" + if config.working_directory + if windows? + command = "cd #{config.working_directory}; if (`$?) \{ #{command} \}" + else + command = "cd #{config.working_directory} && #{command}" + end + end + + if config.environment_path + @machine.ui.info(I18n.t( + "vagrant.provisioners.puppet.running_puppet_env", + environment: config.environment)) + else + @machine.ui.info(I18n.t( + "vagrant.provisioners.puppet.running_puppet", + manifest: config.manifest_file)) + end + + opts = { + elevated: true, + error_class: Vagrant::Errors::VagrantError, + error_key: :ssh_bad_exit_status_muted, + good_exit: [0,2], + } + @machine.communicate.sudo(command, opts) do |type, data| + if !data.chomp.empty? + @machine.ui.info(data.chomp) + end + end + end + + def verify_shared_folders(folders) + folders.each do |folder| + @logger.debug("Checking for shared folder: #{folder}") + if !@machine.communicate.test("test -d #{folder}", sudo: true) + raise PuppetError, :missing_shared_folders + end + end + end + + def windows? + @machine.config.vm.communicator == :winrm + end + end + end + end + end +end diff --git a/puphpet/shell/check-puppet-modules.sh b/puphpet/shell/check-puppet-modules.sh index 67e84c5..5f2d20d 100644 --- a/puphpet/shell/check-puppet-modules.sh +++ b/puphpet/shell/check-puppet-modules.sh @@ -23,6 +23,6 @@ SAVE_TO="/.puphpet-stuff/puppet-modules.zip" echo "Downloading missing Puppet modules" wget --quiet --tries=5 --connect-timeout=10 -O ${SAVE_TO} ${URL} -uz ${SAVE_TO} ${MODULES_FOLDER} > /dev/null 2>&1 +uz ${SAVE_TO} ${MODULES_FOLDER} echo "Done downloading missing Puppet modules" diff --git a/puphpet/shell/initial-setup.sh b/puphpet/shell/initial-setup.sh index fe855e3..86c8bad 100644 --- a/puphpet/shell/initial-setup.sh +++ b/puphpet/shell/initial-setup.sh @@ -20,18 +20,30 @@ fi touch '/.puphpet-stuff/vagrant-core-folder.txt' echo "${VAGRANT_CORE_FOLDER}" > '/.puphpet-stuff/vagrant-core-folder.txt' -# Adding this here with a datestamped filename for future issues like #1189 -# apt repos become stale, Ubuntu/Debian move stuff around and break existing -# boxes that no longer require apt-get update. Force it one more time. Update -# datestamp as required for future breaks. -if [[ ! -f '/.puphpet-stuff/initial-setup-apt-get-update' ]]; then +if [[ ! -f '/.puphpet-stuff/init-apt-get-update' ]] && [[ "${OS}" == 'debian' || "${OS}" == 'ubuntu' ]]; then + apt-get update + + touch '/.puphpet-stuff/init-apt-get-update' +fi + +# Use Anacron to run `apt-get update` once a week to keep repos fresh +if [[ ! -f '/.puphpet-stuff/anacron-installed' ]]; then if [ "${OS}" == 'debian' ] || [ "${OS}" == 'ubuntu' ]; then - echo 'Running initial-setup apt-get update' - apt-get update >/dev/null - echo 'Finished running initial-setup apt-get update' + echo 'Installing Anacron' + apt-get update + apt-get -y install anacron + + cat >/etc/cron.weekly/autoupdt << 'EOL' +#!/bin/bash + +apt-get update +apt-get autoclean +EOL + + echo 'Finished installing Anacron' fi - touch '/.puphpet-stuff/initial-setup-repo-update' + touch '/.puphpet-stuff/anacron-installed' fi # CentOS comes with tty enabled. RHEL has realized this is stupid, so we can @@ -44,17 +56,16 @@ fi # Digital Ocean seems to be missing iptables-persistent! # See https://github.com/puphpet/puphpet/issues/1575 -if [[ ! -f '/.puphpet-stuff/iptables-persistent-installed' ]] && [ "${OS}" == 'debian' ] || [ "${OS}" == 'ubuntu' ]; then - apt-get -y install iptables-persistent > /dev/null 2>&1 +if [[ ! -f '/.puphpet-stuff/iptables-persistent-installed' ]] && [[ "${OS}" == 'debian' || "${OS}" == 'ubuntu' ]]; then + apt-get -y install iptables-persistent touch '/.puphpet-stuff/iptables-persistent-installed' fi -if [[ ! -f '/.puphpet-stuff/resolv-conf-changed' ]]; then - echo "nameserver 8.8.8.8" > /etc/resolv.conf - echo "nameserver 8.8.4.4" >> /etc/resolv.conf +if [[ ! -f '/.puphpet-stuff/software-properties-common' ]] && [[ "${OS}" == 'debian' || "${OS}" == 'ubuntu' ]]; then + apt-get -y install software-properties-common python-software-properties - touch '/.puphpet-stuff/resolv-conf-changed' + touch '/.puphpet-stuff/software-properties-common' fi if [[ -f '/.puphpet-stuff/initial-setup-base-packages' ]]; then @@ -63,28 +74,25 @@ fi if [ "${OS}" == 'debian' ] || [ "${OS}" == 'ubuntu' ]; then echo 'Installing curl' - apt-get -y install curl >/dev/null + apt-get -y install curl echo 'Finished installing curl' echo 'Installing git' - apt-get -y install git-core >/dev/null + apt-get -y install git-core echo 'Finished installing git' if [[ "${CODENAME}" == 'lucid' || "${CODENAME}" == 'precise' ]]; then echo 'Installing basic curl packages' - apt-get -y install libcurl3 libcurl4-gnutls-dev curl >/dev/null + apt-get -y install libcurl3 libcurl4-gnutls-dev echo 'Finished installing basic curl packages' fi echo 'Installing build-essential packages' - apt-get -y install build-essential >/dev/null + apt-get -y install build-essential echo 'Finished installing build-essential packages' elif [[ "${OS}" == 'centos' ]]; then echo 'Adding repos: elrepo, epel, scl' perl -p -i -e 's@enabled=1@enabled=0@gi' /etc/yum/pluginconf.d/fastestmirror.conf - perl -p -i -e 's@#baseurl=http://mirror.centos.org/centos/\$releasever/os/\$basearch/@baseurl=http://mirror.rackspace.com/CentOS//\$releasever/os/\$basearch/\nenabled=1@gi' /etc/yum.repos.d/CentOS-Base.repo - perl -p -i -e 's@#baseurl=http://mirror.centos.org/centos/\$releasever/updates/\$basearch/@baseurl=http://mirror.rackspace.com/CentOS//\$releasever/updates/\$basearch/\nenabled=1@gi' /etc/yum.repos.d/CentOS-Base.repo - perl -p -i -e 's@#baseurl=http://mirror.centos.org/centos/\$releasever/extras/\$basearch/@baseurl=http://mirror.rackspace.com/CentOS//\$releasever/extras/\$basearch/\nenabled=1@gi' /etc/yum.repos.d/CentOS-Base.repo if [ "${RELEASE}" == 6 ]; then EL_REPO='http://www.elrepo.org/elrepo-release-6-6.el6.elrepo.noarch.rpm' @@ -94,23 +102,23 @@ elif [[ "${OS}" == 'centos' ]]; then EPEL='https://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm' fi - yum -y --nogpgcheck install "${EL_REPO}" >/dev/null - yum -y --nogpgcheck install "${EPEL}" >/dev/null - yum -y install centos-release-SCL >/dev/null - yum clean all >/dev/null - yum -y check-update >/dev/null + yum -y --nogpgcheck install "${EL_REPO}" + yum -y --nogpgcheck install "${EPEL}" + yum -y install centos-release-SCL + yum clean all + yum -y check-update echo 'Finished adding repos: elrep, epel, scl' echo 'Installing curl' - yum -y install curl >/dev/null + yum -y install curl echo 'Finished installing curl' echo 'Installing git' - yum -y install git >/dev/null + yum -y install git echo 'Finished installing git' echo 'Installing Development Tools' - yum -y groupinstall 'Development Tools' >/dev/null + yum -y groupinstall 'Development Tools' echo 'Finished installing Development Tools' fi diff --git a/puphpet/shell/install-puppet.sh b/puphpet/shell/install-puppet.sh index 47c737f..2f4ced2 100644 --- a/puphpet/shell/install-puppet.sh +++ b/puphpet/shell/install-puppet.sh @@ -8,60 +8,27 @@ OS=$(/bin/bash "${VAGRANT_CORE_FOLDER}/shell/os-detect.sh" ID) RELEASE=$(/bin/bash "${VAGRANT_CORE_FOLDER}/shell/os-detect.sh" RELEASE) CODENAME=$(/bin/bash "${VAGRANT_CORE_FOLDER}/shell/os-detect.sh" CODENAME) -# deep_merge gem required by hiera -if [[ ! -f /.puphpet-stuff/install-deep_merge-03122015 ]]; then - gem install deep_merge --no-ri --no-rdoc - touch /.puphpet-stuff/install-deep_merge-03122015 +if [[ ! -f /.puphpet-stuff/install-puppet ]]; then + echo 'Installing Puppet' + + if [ "${OS}" == 'debian' ] || [ "${OS}" == 'ubuntu' ]; then + URL="https://apt.puppetlabs.com/puppetlabs-release-pc1-${CODENAME}.deb" + wget --quiet --tries=5 --connect-timeout=10 -O /.puphpet-stuff/puppetlabs-release-pc1.deb ${URL} + dpkg -i /.puphpet-stuff/puppetlabs-release-pc1.deb + apt-get update + apt-get -y install puppet-agent + elif [[ "${OS}" == 'centos' ]]; then + if [ "${RELEASE}" == 6 ]; then + rpm -Uvh https://yum.puppetlabs.com/puppetlabs-release-pc1-el-6.noarch.rpm + yum -y install puppet-agent + fi + fi + + rm -f /usr/bin/puppet + ln -s /opt/puppetlabs/bin/puppet /usr/bin/puppet + + echo 'Finished installing Puppet' + touch /.puphpet-stuff/install-puppet fi -if [[ ! -f /.puphpet-stuff/install-activesupport-03132015 ]]; then - gem install activesupport --no-ri --no-rdoc - touch /.puphpet-stuff/install-activesupport-03132015 -fi - -if [[ ! -f /.puphpet-stuff/install-vine-03202015 ]]; then - gem install vine --no-ri --no-rdoc - touch /.puphpet-stuff/install-vine-03202015 -fi - -if [[ ! -f /.puphpet-stuff/install-augeas-04232015 ]] && [ "${OS}" == 'centos' ]; then - echo 'Upgrading augeas' - yum -y remove augeas* >/dev/null - - AUGEAS='http://dl.fedoraproject.org/pub/epel/5/x86_64/augeas-1.2.0-1.el5.x86_64.rpm' - AUG_LIBS='http://dl.fedoraproject.org/pub/epel/5/x86_64/augeas-libs-1.2.0-1.el5.x86_64.rpm' - yum -y --nogpgcheck install "${AUG_LIBS}" >/dev/null - yum -y --nogpgcheck --setopt=protected_multilib=false install "${AUGEAS}" >/dev/null - touch /.puphpet-stuff/install-augeas-04232015 - echo 'Finished upgrading augeas' -fi - -if [[ -f /.puphpet-stuff/install-puppet-3.4.3 ]]; then - exit 0 -fi - -rm -rf /usr/bin/puppet - -if [ "${OS}" == 'debian' ] || [ "${OS}" == 'ubuntu' ]; then - apt-get -y install augeas-tools libaugeas-dev -elif [[ "${OS}" == 'centos' ]]; then - yum -y install augeas-devel -fi - -echo 'Installing Puppet requirements' -gem install haml hiera facter json ruby-augeas deep_merge --no-ri --no-rdoc -echo 'Finished installing Puppet requirements' - -echo 'Installing Puppet 3.4.3' -gem install puppet --version 3.4.3 --no-ri --no-rdoc -echo 'Finished installing Puppet 3.4.3' - -cat >/usr/bin/puppet << 'EOL' -#!/bin/bash - -rvm ruby-1.9.3-p551 do puppet "$@" -EOL - -chmod +x /usr/bin/puppet - -touch /.puphpet-stuff/install-puppet-3.4.3 +/opt/puppetlabs/puppet/bin/gem install deep_merge activesupport vine --no-ri --no-rdoc diff --git a/puphpet/shell/install-ruby.sh b/puphpet/shell/install-ruby.sh deleted file mode 100644 index 32601e2..0000000 --- a/puphpet/shell/install-ruby.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -export DEBIAN_FRONTEND=noninteractive - -VAGRANT_CORE_FOLDER=$(cat '/.puphpet-stuff/vagrant-core-folder.txt') - -OS=$(/bin/bash "${VAGRANT_CORE_FOLDER}/shell/os-detect.sh" ID) -RELEASE=$(/bin/bash "${VAGRANT_CORE_FOLDER}/shell/os-detect.sh" RELEASE) -CODENAME=$(/bin/bash "${VAGRANT_CORE_FOLDER}/shell/os-detect.sh" CODENAME) - -if [[ -f /.puphpet-stuff/install-ruby-1.9.3-p551 ]]; then - exit 0 -fi - -rm -rf /usr/bin/ruby /usr/bin/gem /usr/bin/rvm /usr/local/rvm - -echo 'Installing RVM and Ruby 1.9.3' - -if [ "${OS}" == 'debian' ] || [ "${OS}" == 'ubuntu' ]; then - gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys D39DC0E3 -elif [[ "${OS}" == 'centos' ]]; then - gpg2 --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys D39DC0E3 -fi - -curl -sSL https://get.rvm.io | bash -s stable --quiet-curl --ruby=ruby-1.9.3-p551 - -source /usr/local/rvm/scripts/rvm - -if [[ -f '/root/.bashrc' ]] && ! grep -q 'source /usr/local/rvm/scripts/rvm' /root/.bashrc; then - echo 'source /usr/local/rvm/scripts/rvm' >> /root/.bashrc -fi - -if [[ -f '/etc/profile' ]] && ! grep -q 'source /usr/local/rvm/scripts/rvm' /etc/profile; then - echo 'source /usr/local/rvm/scripts/rvm' >> /etc/profile -fi - -/usr/local/rvm/bin/rvm cleanup all -gem update --system >/dev/null -echo 'y' | rvm rvmrc warning ignore all.rvmrcs - -echo 'Finished installing RVM and Ruby 1.9.3' - -touch /.puphpet-stuff/install-ruby-1.9.3-p551 diff --git a/puphpet/vagrant/Vagrantfile-aws b/puphpet/vagrant/Vagrantfile-aws index 874eb94..1f5ca48 100644 --- a/puphpet/vagrant/Vagrantfile-aws +++ b/puphpet/vagrant/Vagrantfile-aws @@ -1,6 +1,9 @@ +# -*- mode: ruby -*- + ENV['VAGRANT_DEFAULT_PROVIDER'] = 'aws' Vagrant.configure('2') do |config| + config.vm.define :aws config.vm.box = 'dummy' config.vm.hostname = "#{data['vm']['hostname']}" @@ -39,8 +42,11 @@ Vagrant.configure('2') do |config| s.args = '/vagrant/puphpet' end config.vm.provision :shell, :path => 'puphpet/shell/check-puppet-modules.sh' - config.vm.provision :shell, :path => 'puphpet/shell/install-ruby.sh' config.vm.provision :shell, :path => 'puphpet/shell/install-puppet.sh' + config.vm.provision :shell do |s| + s.path = 'puphpet/shell/execute-files.sh' + s.args = ['exec-preprovision'] + end config.vm.provision :puppet do |puppet| ssh_username = !data['ssh']['username'].nil? ? data['ssh']['username'] : 'vagrant' @@ -49,7 +55,7 @@ Vagrant.configure('2') do |config| 'provisioner_type' => ENV['VAGRANT_DEFAULT_PROVIDER'], } puppet.manifests_path = "#{data['vm']['provision']['puppet']['manifests_path']}" - puppet.manifest_file = "#{data['vm']['provision']['puppet']['manifest_file']}" + puppet.manifest_file = "" puppet.module_path = "#{data['vm']['provision']['puppet']['module_path']}" if !data['vm']['provision']['puppet']['options'].empty? diff --git a/puphpet/vagrant/Vagrantfile-digitalocean b/puphpet/vagrant/Vagrantfile-digitalocean index 9d1ffa5..13c21bd 100644 --- a/puphpet/vagrant/Vagrantfile-digitalocean +++ b/puphpet/vagrant/Vagrantfile-digitalocean @@ -1,6 +1,9 @@ +# -*- mode: ruby -*- + ENV['VAGRANT_DEFAULT_PROVIDER'] = 'digital_ocean' Vagrant.configure('2') do |config| + config.vm.define :digital_ocean config.vm.box = 'dummy' config.vm.hostname = "#{data['vm']['hostname']}" config.nfs.functional = false @@ -33,8 +36,11 @@ Vagrant.configure('2') do |config| s.args = '/vagrant/puphpet' end config.vm.provision :shell, :path => 'puphpet/shell/check-puppet-modules.sh' - config.vm.provision :shell, :path => 'puphpet/shell/install-ruby.sh' config.vm.provision :shell, :path => 'puphpet/shell/install-puppet.sh' + config.vm.provision :shell do |s| + s.path = 'puphpet/shell/execute-files.sh' + s.args = ['exec-preprovision'] + end config.vm.provision :puppet do |puppet| ssh_username = !data['ssh']['username'].nil? ? data['ssh']['username'] : 'vagrant' @@ -43,7 +49,7 @@ Vagrant.configure('2') do |config| 'provisioner_type' => ENV['VAGRANT_DEFAULT_PROVIDER'], } puppet.manifests_path = "#{data['vm']['provision']['puppet']['manifests_path']}" - puppet.manifest_file = "#{data['vm']['provision']['puppet']['manifest_file']}" + puppet.manifest_file = "" puppet.module_path = "#{data['vm']['provision']['puppet']['module_path']}" if !data['vm']['provision']['puppet']['options'].empty? diff --git a/puphpet/vagrant/Vagrantfile-gce b/puphpet/vagrant/Vagrantfile-gce index ba709cb..6f9bbba 100644 --- a/puphpet/vagrant/Vagrantfile-gce +++ b/puphpet/vagrant/Vagrantfile-gce @@ -1,8 +1,11 @@ +# -*- mode: ruby -*- + ENV['VAGRANT_DEFAULT_PROVIDER'] = 'google' require 'fog/version' Vagrant.configure('2') do |config| + config.vm.define :gce config.vm.box = 'gce' config.vm.hostname = "#{data['vm']['hostname']}" @@ -31,8 +34,11 @@ Vagrant.configure('2') do |config| s.args = '/vagrant/puphpet' end config.vm.provision :shell, :path => 'puphpet/shell/check-puppet-modules.sh' - config.vm.provision :shell, :path => 'puphpet/shell/install-ruby.sh' config.vm.provision :shell, :path => 'puphpet/shell/install-puppet.sh' + config.vm.provision :shell do |s| + s.path = 'puphpet/shell/execute-files.sh' + s.args = ['exec-preprovision'] + end config.vm.provision :puppet do |puppet| ssh_username = !data['ssh']['username'].nil? ? data['ssh']['username'] : 'vagrant' @@ -41,7 +47,7 @@ Vagrant.configure('2') do |config| 'provisioner_type' => ENV['VAGRANT_DEFAULT_PROVIDER'], } puppet.manifests_path = "#{data['vm']['provision']['puppet']['manifests_path']}" - puppet.manifest_file = "#{data['vm']['provision']['puppet']['manifest_file']}" + puppet.manifest_file = "" puppet.module_path = "#{data['vm']['provision']['puppet']['module_path']}" if !data['vm']['provision']['puppet']['options'].empty? diff --git a/puphpet/vagrant/Vagrantfile-ikoulacloud b/puphpet/vagrant/Vagrantfile-ikoulacloud index b71a84e..75d9427 100644 --- a/puphpet/vagrant/Vagrantfile-ikoulacloud +++ b/puphpet/vagrant/Vagrantfile-ikoulacloud @@ -1,6 +1,9 @@ +# -*- mode: ruby -*- + ENV['VAGRANT_DEFAULT_PROVIDER'] = 'cloudstack' Vagrant.configure('2') do |config| + config.vm.define :cloudstack config.vm.box = 'dummy' config.vm.hostname = "#{data['vm']['hostname']}" @@ -47,8 +50,11 @@ Vagrant.configure('2') do |config| s.args = '/vagrant/puphpet' end config.vm.provision :shell, :path => 'puphpet/shell/check-puppet-modules.sh' - config.vm.provision :shell, :path => 'puphpet/shell/install-ruby.sh' config.vm.provision :shell, :path => 'puphpet/shell/install-puppet.sh' + config.vm.provision :shell do |s| + s.path = 'puphpet/shell/execute-files.sh' + s.args = ['exec-preprovision'] + end config.vm.provision :puppet do |puppet| ssh_username = !data['ssh']['username'].nil? ? data['ssh']['username'] : 'vagrant' @@ -57,7 +63,7 @@ Vagrant.configure('2') do |config| 'provisioner_type' => ENV['VAGRANT_DEFAULT_PROVIDER'], } puppet.manifests_path = "#{data['vm']['provision']['puppet']['manifests_path']}" - puppet.manifest_file = "#{data['vm']['provision']['puppet']['manifest_file']}" + puppet.manifest_file = "" puppet.module_path = "#{data['vm']['provision']['puppet']['module_path']}" if !data['vm']['provision']['puppet']['options'].empty? diff --git a/puphpet/vagrant/Vagrantfile-linode b/puphpet/vagrant/Vagrantfile-linode index cf876e5..f96399b 100644 --- a/puphpet/vagrant/Vagrantfile-linode +++ b/puphpet/vagrant/Vagrantfile-linode @@ -1,6 +1,9 @@ +# -*- mode: ruby -*- + ENV['VAGRANT_DEFAULT_PROVIDER'] = 'linode' Vagrant.configure('2') do |config| + config.vm.define :linode config.vm.box = 'dummy' config.vm.hostname = "#{data['vm']['hostname']}" @@ -26,8 +29,11 @@ Vagrant.configure('2') do |config| s.args = '/vagrant/puphpet' end config.vm.provision :shell, :path => 'puphpet/shell/check-puppet-modules.sh' - config.vm.provision :shell, :path => 'puphpet/shell/install-ruby.sh' config.vm.provision :shell, :path => 'puphpet/shell/install-puppet.sh' + config.vm.provision :shell do |s| + s.path = 'puphpet/shell/execute-files.sh' + s.args = ['exec-preprovision'] + end config.vm.provision :puppet do |puppet| ssh_username = !data['ssh']['username'].nil? ? data['ssh']['username'] : 'vagrant' @@ -36,7 +42,7 @@ Vagrant.configure('2') do |config| 'provisioner_type' => ENV['VAGRANT_DEFAULT_PROVIDER'], } puppet.manifests_path = "#{data['vm']['provision']['puppet']['manifests_path']}" - puppet.manifest_file = "#{data['vm']['provision']['puppet']['manifest_file']}" + puppet.manifest_file = "" puppet.module_path = "#{data['vm']['provision']['puppet']['module_path']}" if !data['vm']['provision']['puppet']['options'].empty? diff --git a/puphpet/vagrant/Vagrantfile-local b/puphpet/vagrant/Vagrantfile-local index 01cbee5..924fd92 100644 --- a/puphpet/vagrant/Vagrantfile-local +++ b/puphpet/vagrant/Vagrantfile-local @@ -1,10 +1,19 @@ +# -*- mode: ruby -*- + vagrant_home = (ENV['VAGRANT_HOME'].to_s.split.join.length > 0) ? ENV['VAGRANT_HOME'] : "#{ENV['HOME']}/.vagrant.d" vagrant_dot = (ENV['VAGRANT_DOTFILE_PATH'].to_s.split.join.length > 0) ? ENV['VAGRANT_DOTFILE_PATH'] : "#{dir}/.vagrant" Vagrant.configure('2') do |config| + config.vm.define :local config.vm.box = "#{data['vm']['box']}" config.vm.box_url = "#{data['vm']['box_url']}" + if data['vm']['box_version'].to_s != '' + config.vm.box_version = "#{data['vm']['box_version']}" + end + + config.ssh.insert_key = data['ssh']['insert_key'] + if data['vm']['hostname'].to_s.strip.length != 0 config.vm.hostname = "#{data['vm']['hostname']}" end @@ -12,7 +21,7 @@ Vagrant.configure('2') do |config| if data['vm']['network']['private_network'].to_s != '' config.vm.network 'private_network', ip: "#{data['vm']['network']['private_network']}" end - + if data['vm']['network']['public_network'].to_s != '' config.vm.network 'public_network' if data['vm']['network']['public_network'].to_s != '1' @@ -26,6 +35,28 @@ Vagrant.configure('2') do |config| end end + if Vagrant.has_plugin?('vagrant-proxyconf') + case data['proxy']['enabled'] + when true,'true',1,'1' + config.proxy.enabled = true + when false, 'false',0,'0' + config.proxy.enabled = false + end + + if data['proxy']['http'].to_s != '' + config.proxy.http = "#{data['proxy']['http']}" + end + if data['proxy']['https'].to_s != '' + config.proxy.https = "#{data['proxy']['https']}" + end + if data['proxy']['ftp'].to_s != '' + config.proxy.ftp = "#{data['proxy']['ftp']}" + end + if data['proxy']['no_proxy'].to_s != '' + config.proxy.no_proxy = "#{data['proxy']['no_proxy']}" + end + end + if !data['vm']['post_up_message'].nil? config.vm.post_up_message = "#{data['vm']['post_up_message']}" end @@ -33,6 +64,12 @@ Vagrant.configure('2') do |config| if Vagrant.has_plugin?('vagrant-hostmanager') hosts = Array.new() + if !configValues['hosts'].nil? + configValues['hosts'].each do |host| + hosts.push(host) + end + end + if !configValues['apache']['install'].nil? && configValues['apache']['install'].to_i == 1 && configValues['apache']['vhosts'].is_a?(Hash) @@ -69,6 +106,8 @@ Vagrant.configure('2') do |config| config.hostmanager.ignore_private_ip = false config.hostmanager.include_offline = false config.hostmanager.aliases = hosts + + config.vm.provision :hostmanager end end @@ -84,17 +123,19 @@ Vagrant.configure('2') do |config| if folder['sync_type'] == 'nfs' if Vagrant.has_plugin?('vagrant-bindfs') config.vm.synced_folder "#{folder['source']}", "/mnt/vagrant-#{i}", id: "#{i}", type: 'nfs' - config.bindfs.bind_folder "/mnt/vagrant-#{i}", "#{folder['target']}", owner: sync_owner, group: sync_group, perms: "u=rwX:g=rwX:o=rD" + config.bindfs.bind_folder "/mnt/vagrant-#{i}", "#{folder['target']}", after: :provision, force_user: sync_owner, force_group: sync_group, perms: "u=rwX:g=rwX:o=rD", o: 'nonempty' else - config.vm.synced_folder "#{folder['source']}", "#{folder['target']}", id: "#{i}", type: 'nfs' + config.vm.synced_folder "#{folder['source']}", "#{folder['target']}", id: "#{i}", type: 'nfs', :nfs => { :mount_options => ["dmode=777","fmode=666"] } end elsif folder['sync_type'] == 'smb' smb__host = !folder['smb']['smb_host'].nil? ? folder['smb']['smb_host'] : nil smb__username = !folder['smb']['smb_username'].nil? ? folder['smb']['smb_username'] : nil smb__password = !folder['smb']['smb_password'].nil? ? folder['smb']['smb_password'] : nil + smb__dir_options = !folder['smb']['mount_options']['dir_mode'].nil? ? folder['smb']['mount_options']['dir_mode'] : 0775 + smb__file_options = !folder['smb']['mount_options']['file_mode'].nil? ? folder['smb']['mount_options']['file_mode'] : 0664 config.vm.synced_folder "#{folder['source']}", "#{folder['target']}", id: "#{i}", type: 'smb', - group: sync_group, owner: sync_owner, smb_host: smb__host, smb_username: smb__username, smb_password: smb__password + group: sync_group, owner: sync_owner, smb_host: smb__host, smb_username: smb__username, smb_password: smb__password, mount_options: ["dir_mode=#{smb__dir_options},file_mode=#{smb__file_options}"] elsif folder['sync_type'] == 'rsync' rsync_args = !folder['rsync']['args'].nil? ? folder['rsync']['args'] : ['--verbose', '--archive', '-z'] rsync_auto = !folder['rsync']['auto'].nil? ? folder['rsync']['auto'] : true @@ -139,7 +180,7 @@ Vagrant.configure('2') do |config| virtualbox.customize ['modifyvm', :id, '--memory', "#{data['vm']['memory']}"] virtualbox.customize ['modifyvm', :id, '--cpus', "#{data['vm']['cpus']}"] - + if !data['vm']['provider']['virtualbox']['showgui'].nil? && data['vm']['provider']['virtualbox']['showgui'].to_i == 1 virtualbox.gui = true @@ -192,16 +233,28 @@ Vagrant.configure('2') do |config| config.vm.provider 'parallels' do |v| data['vm']['provider']['parallels'].each do |key, value| - if key == 'memsize' - next - end - if key == 'cpus' + if ['memsize', 'cpus', 'use_linked_clone', 'check_guest_tools', 'update_guest_tools'].include? key next end v.customize ['set', :id, "--#{key}", "#{value}"] end + if !data['vm']['provider']['parallels']['use_linked_clone'].nil? && + data['vm']['provider']['parallels']['use_linked_clone'].to_i == 1 + v.use_linked_clone = true + end + + if !data['vm']['provider']['parallels']['check_guest_tools'].nil? && + data['vm']['provider']['parallels']['check_guest_tools'].to_i == 1 + v.check_guest_tools = true + end + + if !data['vm']['provider']['parallels']['update_guest_tools'].nil? && + data['vm']['provider']['parallels']['update_guest_tools'].to_i == 1 + v.update_guest_tools = true + end + v.memory = "#{data['vm']['memory']}" v.cpus = "#{data['vm']['cpus']}" @@ -226,8 +279,11 @@ Vagrant.configure('2') do |config| kg.args = "#{ssh_username}" end config.vm.provision :shell, :path => 'puphpet/shell/check-puppet-modules.sh' - config.vm.provision :shell, :path => 'puphpet/shell/install-ruby.sh' config.vm.provision :shell, :path => 'puphpet/shell/install-puppet.sh' + config.vm.provision :shell do |s| + s.path = 'puphpet/shell/execute-files.sh' + s.args = ['exec-preprovision'] + end config.vm.provision :puppet do |puppet| puppet.facter = { @@ -236,7 +292,7 @@ Vagrant.configure('2') do |config| 'provisioner_type' => ENV['VAGRANT_DEFAULT_PROVIDER'], } puppet.manifests_path = "#{data['vm']['provision']['puppet']['manifests_path']}" - puppet.manifest_file = "#{data['vm']['provision']['puppet']['manifest_file']}" + puppet.manifest_file = "" puppet.module_path = "#{data['vm']['provision']['puppet']['module_path']}" if !data['vm']['provision']['puppet']['options'].empty? diff --git a/puphpet/vagrant/Vagrantfile-rackspace b/puphpet/vagrant/Vagrantfile-rackspace index 3850a72..c51b34c 100644 --- a/puphpet/vagrant/Vagrantfile-rackspace +++ b/puphpet/vagrant/Vagrantfile-rackspace @@ -1,8 +1,11 @@ +# -*- mode: ruby -*- + ENV['VAGRANT_DEFAULT_PROVIDER'] = 'rackspace' require 'fog/version' Vagrant.configure('2') do |config| + config.vm.define :rackspace config.vm.box = 'dummy' config.vm.hostname = "#{data['vm']['hostname']}" config.nfs.functional = false @@ -34,8 +37,11 @@ Vagrant.configure('2') do |config| s.args = '/vagrant/puphpet' end config.vm.provision :shell, :path => 'puphpet/shell/check-puppet-modules.sh' - config.vm.provision :shell, :path => 'puphpet/shell/install-ruby.sh' config.vm.provision :shell, :path => 'puphpet/shell/install-puppet.sh' + config.vm.provision :shell do |s| + s.path = 'puphpet/shell/execute-files.sh' + s.args = ['exec-preprovision'] + end config.vm.provision :puppet do |puppet| ssh_username = !data['ssh']['username'].nil? ? data['ssh']['username'] : 'vagrant' @@ -44,7 +50,7 @@ Vagrant.configure('2') do |config| 'provisioner_type' => ENV['VAGRANT_DEFAULT_PROVIDER'], } puppet.manifests_path = "#{data['vm']['provision']['puppet']['manifests_path']}" - puppet.manifest_file = "#{data['vm']['provision']['puppet']['manifest_file']}" + puppet.manifest_file = "" puppet.module_path = "#{data['vm']['provision']['puppet']['module_path']}" if !data['vm']['provision']['puppet']['options'].empty? diff --git a/puphpet/vagrant/Vagrantfile-softlayer b/puphpet/vagrant/Vagrantfile-softlayer index 8121d13..6a63c8a 100644 --- a/puphpet/vagrant/Vagrantfile-softlayer +++ b/puphpet/vagrant/Vagrantfile-softlayer @@ -1,6 +1,9 @@ +# -*- mode: ruby -*- + ENV['VAGRANT_DEFAULT_PROVIDER'] = 'softlayer' Vagrant.configure('2') do |config| + config.vm.define :softlayer config.nfs.functional = false config.ssh.username = 'root' config.ssh.private_key_path = "#{data['ssh']['private_key_path']}" @@ -29,8 +32,11 @@ Vagrant.configure('2') do |config| s.args = '/vagrant/puphpet' end config.vm.provision :shell, :path => 'puphpet/shell/check-puppet-modules.sh' - config.vm.provision :shell, :path => 'puphpet/shell/install-ruby.sh' config.vm.provision :shell, :path => 'puphpet/shell/install-puppet.sh' + config.vm.provision :shell do |s| + s.path = 'puphpet/shell/execute-files.sh' + s.args = ['exec-preprovision'] + end config.vm.provision :puppet do |puppet| puppet.facter = { @@ -38,7 +44,7 @@ Vagrant.configure('2') do |config| 'provisioner_type' => ENV['VAGRANT_DEFAULT_PROVIDER'], } puppet.manifests_path = "#{data['vm']['provision']['puppet']['manifests_path']}" - puppet.manifest_file = "#{data['vm']['provision']['puppet']['manifest_file']}" + puppet.manifest_file = "" puppet.module_path = "#{data['vm']['provision']['puppet']['module_path']}" if !data['vm']['provision']['puppet']['options'].empty?