diff --git a/Puppetfile b/Puppetfile index 8c590559d..23128a1af 100644 --- a/Puppetfile +++ b/Puppetfile @@ -1,5 +1,5 @@ mod 'apache', - :commit => 'dc26c77d8890af0df5063b021b52cd91eddaca56', + :commit => '8df51aafe71921181999a9f3d1845ce2d98acb8f', :git => 'https://github.com/puppetlabs/puppetlabs-apache.git' mod 'aviator', @@ -7,7 +7,7 @@ mod 'aviator', :git => 'https://github.com/aimonb/puppet_aviator.git' mod 'ceilometer', - :commit => '8d17c36818d99231a64d20f50ea708d59306fe22', + :commit => '0ec70ff60f620a1af29ae64a646ee7e5ad98ebb9', :git => 'https://github.com/stackforge/puppet-ceilometer.git' mod 'certmonger', @@ -15,7 +15,7 @@ mod 'certmonger', :git => 'https://github.com/rcritten/puppet-certmonger.git' mod 'cinder', - :commit => 'a6727a0d235b40b89891767e5ead133678e60ec2', + :commit => 'cc7279832bb7bd2840c831219f5f00a0f2efb8a3', :git => 'https://github.com/stackforge/puppet-cinder.git' mod 'common', @@ -23,7 +23,7 @@ mod 'common', :git => 'https://github.com/purpleidea/puppet-common.git' mod 'concat', - :commit => '52d0f1d6809c9f1d8453f9e3ca10d792e67acc89', + :commit => '30cb251b8699028a7b15c2b855f62ba5ce276401', :git => 'https://github.com/puppetlabs/puppetlabs-concat.git' mod 'firewall', @@ -35,27 +35,27 @@ mod 'galera', :git => 'https://github.com/redhat-openstack/puppet-galera.git' mod 'glance', - :commit => '9c1b0a90d93913548dbada13076cac1470cc5993', + :commit => 'c0feafd0e9705870349b6b75ef1727ddd6b81035', :git => 'https://github.com/stackforge/puppet-glance.git' mod 'gluster', - :commit => '467620e575b8b8fb42d1980f97ae1b5863641483', + :commit => '4b96b871dc414727160b51a7a454c518382ea9aa', :git => 'https://github.com/purpleidea/puppet-gluster.git' mod 'gnocchi', - :commit => '4438badb1499ceed11b32287f861de2ce5961122', + :commit => '135849d3f11592f6e6b1d4d86ac161a265ad3d28', :git => 'https://github.com/stackforge/puppet-gnocchi.git' mod 'haproxy', - :commit => '957437013add0c92d6ff934de942867e304036f0', + :commit => '33ceaf932fb694e54fc3d917580e2c89e40f0ae7', :git => 'https://github.com/puppetlabs/puppetlabs-haproxy.git' mod 'heat', - :commit => 'bbeb24c51aa3573300a74fbcaf80d8fce3e2b8f7', + :commit => '80e16dc9758ee6307f99ad3a14d5d26d70629fcd', :git => 'https://github.com/stackforge/puppet-heat.git' mod 'horizon', - :commit => '4155185fef6d566246796d448c9e1c2557f4481c', + :commit => '32ed597ccc069086bcb0a0e1e722638072d18fcf', :git => 'https://github.com/stackforge/puppet-horizon.git' mod 'inifile', @@ -71,11 +71,11 @@ mod 'ironic', :git => 'https://github.com/stackforge/puppet-ironic.git' mod 'keystone', - :commit => '4f684b24dbd8a089bd542f2767ab56ba2aea6654', + :commit => 'feacfd425186acf86237306c99d4c5a7cdbc2867', :git => 'https://github.com/stackforge/puppet-keystone.git' mod 'manila', - :commit => 'cf654ec8d6f693ec353562a57718add762f167dd', + :commit => '41dc76b9518fb36b1217b89b4f605c99e00b7e1c', :git => 'https://github.com/stackforge/puppet-manila.git' mod 'memcached', @@ -83,7 +83,7 @@ mod 'memcached', :git => 'https://github.com/saz/puppet-memcached.git' mod 'module-collectd', - :commit => '91e1dafad3182e64979dfeba1633f0b32bcc0649', + :commit => '1bd511019fe1da9b305b259862aa27516f083be6', :git => 'https://github.com/pdxcat/puppet-module-collectd.git' mod 'module-data', @@ -95,7 +95,7 @@ mod 'mongodb', :git => 'https://github.com/puppetlabs/puppetlabs-mongodb.git' mod 'mysql', - :commit => '5de035c60d899df305e1f3e30267726895d055da', + :commit => '873dea342fd05821e4998c10066b99bdf25777e6', :git => 'https://github.com/puppetlabs/puppetlabs-mysql.git' mod 'n1k_vsm', @@ -111,7 +111,7 @@ mod 'neutron', :git => 'https://github.com/stackforge/puppet-neutron.git' mod 'nova', - :commit => 'c191303e6b368f0124e27b6545595a69fd188662', + :commit => '7f40c612d2fc25b9ceb91899c2c634e5e05ee3b9', :git => 'https://github.com/stackforge/puppet-nova.git' mod 'nssdb', @@ -119,7 +119,7 @@ mod 'nssdb', :git => 'https://github.com/rcritten/puppet-nssdb.git' mod 'ntp', - :commit => '286acbacdb9aaa3f1255d7486078730e380195f4', + :commit => '060c453a9bbd87d1bf229db70ee6367033a2910e', :git => 'https://github.com/puppetlabs/puppetlabs-ntp' mod 'openstack_extras', @@ -127,7 +127,7 @@ mod 'openstack_extras', :git => 'https://github.com/stackforge/puppet-openstack_extras.git' mod 'openstacklib', - :commit => 'e76240c180f969fda194f295496421cbc1e4352a', + :commit => '423707b0f944ba052bb86a1cc23e5866a3640376', :git => 'https://github.com/stackforge/puppet-openstacklib.git' mod 'pacemaker', @@ -143,7 +143,7 @@ mod 'qpid', :git => 'https://github.com/dprince/puppet-qpid' mod 'rabbitmq', - :commit => '7dd5c7420f823babe3baf88bec67c8e43760d00e', + :commit => '2c3fd7ea004272257b8efaa098cd2ea18b2b7751', :git => 'https://github.com/puppetlabs/puppetlabs-rabbitmq.git' mod 'redis', @@ -155,11 +155,11 @@ mod 'remote', :git => 'https://github.com/paramite/puppet-remote.git' mod 'rsync', - :commit => '699650bf7e7339e1653f83143637595a0029aa51', + :commit => 'f8081918a503a7301772c93373eb70b90d399538', :git => 'https://github.com/puppetlabs/puppetlabs-rsync.git' mod 'sahara', - :commit => '303e514db06b34db1ab26e84edbbdf91d98d6679', + :commit => '7dfdc87303f40bddd2fc72c974fbddb3d16f04d0', :git => 'https://github.com/stackforge/puppet-sahara.git' mod 'ssh', @@ -171,11 +171,11 @@ mod 'staging', :git => 'https://github.com/nanliu/puppet-staging.git' mod 'stdlib', - :commit => '14a02ea21e14111071a921e82cdf3cd1f518c7f3', + :commit => '2a8d7acd7e8ce84826cb8293308721fe7b4095ea', :git => 'https://github.com/puppetlabs/puppetlabs-stdlib.git' mod 'swift', - :commit => '96ad9dd2237d9d9165025fd76e3c4b7f348ea2f1', + :commit => 'f67877f1fa2dbb33702f61cee3c9df76ba541181', :git => 'https://github.com/stackforge/puppet-swift.git' mod 'sysctl', @@ -183,7 +183,7 @@ mod 'sysctl', :git => 'https://github.com/puppetlabs/puppetlabs-sysctl.git' mod 'tempest', - :commit => '098c4b855e5a6da843bae057d56afd89b171894f', + :commit => '301f58f60317a816572596fce1f0093ad4f8e8e0', :git => 'https://github.com/stackforge/puppet-tempest.git' mod 'timezone', @@ -191,7 +191,7 @@ mod 'timezone', :git => 'https://github.com/saz/puppet-timezone.git' mod 'tripleo', - :commit => '6f5c208f8df4df034637acd1b5fd6f4b71012d8a', + :commit => 'e0921709d946d8db95f2a399a1b9da93d6b73d06', :git => 'https://github.com/stackforge/puppet-tripleo.git' mod 'trove', @@ -199,7 +199,7 @@ mod 'trove', :git => 'https://github.com/stackforge/puppet-trove' mod 'vcsrepo', - :commit => '3d4547646d49295c91bb002fa885e187c2d89feb', + :commit => '210ca5acd8eecc909eae248745e24f0debd66ffc', :git => 'https://github.com/puppetlabs/puppetlabs-vcsrepo.git' mod 'vlan', @@ -207,10 +207,10 @@ mod 'vlan', :git => 'https://github.com/derekhiggins/puppet-vlan.git' mod 'vswitch', - :commit => '331726326a275da158a62cafdd49fb961a71d3e2', + :commit => '5079b23938aa2d98dea86e89c05194fd3deb3a29', :git => 'https://github.com/stackforge/puppet-vswitch.git' mod 'xinetd', - :commit => '5e31388979e8f3a667899fad5cefa95289e22281', + :commit => '4f16fc824e04d724a486634bd9c26ef549f10ff5', :git => 'https://github.com/puppetlabs/puppetlabs-xinetd.git' diff --git a/apache/.fixtures.yml b/apache/.fixtures.yml index 6eddf260f..4645a757f 100644 --- a/apache/.fixtures.yml +++ b/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/apache/README.md b/apache/README.md index 5a6a356fa..c64da7ae8 100644 --- a/apache/README.md +++ b/apache/README.md @@ -347,6 +347,10 @@ Sets the amount of time the server waits for subsequent requests on a persistent Sets the limit of the number of requests allowed per connection when KeepAlive is on. Defaults to '100'. +#####`lib_path` + +Specifies the location where apache module files are stored. It should not be configured manually without special reason. + #####`loadfile_name` Sets the file name for the module loadfile. Should be in the format *.load. This can be used to set the module load order. @@ -811,9 +815,9 @@ Installs Apache mod_status and uses the status.conf.erb template. These are the ```puppet class { 'apache::mod::status': - allow_from = ['127.0.0.1','::1'], - extended_status = 'On', - status_path = '/server-status', + allow_from => ['127.0.0.1','::1'], + extended_status => 'On', + status_path => '/server-status', ){ @@ -826,9 +830,9 @@ Installs Apache mod_expires and uses the expires.conf.erb template. These are th ```puppet class { 'apache::mod::expires': - expires_active = true, - expires_default = undef, - expires_by_type = undef, + expires_active => true, + expires_default => undef, + expires_by_type => undef, ){ @@ -839,7 +843,7 @@ Installs Apache mod_expires and uses the expires.conf.erb template. These are th ```puppet class { 'apache::mod::expires': - expires_by_type = [ + expires_by_type => [ { 'text/json' => 'access plus 1 month' }, { 'text/html' => 'access plus 1 year' }, ] @@ -868,8 +872,8 @@ To specify an alternate mod\_wsgi package name to install and the name of the mo 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', + package_name => 'python27-mod_wsgi', + mod_path => 'python27-mod_wsgi.so', } ``` diff --git a/apache/lib/puppet/parser/functions/validate_apache_log_level.rb b/apache/lib/puppet/parser/functions/validate_apache_log_level.rb new file mode 100644 index 000000000..8a1ade0be --- /dev/null +++ b/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/apache/manifests/dev.pp b/apache/manifests/dev.pp index 6bd865606..b1947e934 100644 --- a/apache/manifests/dev.pp +++ b/apache/manifests/dev.pp @@ -1,7 +1,4 @@ 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 if $packages { # FreeBSD doesn't have dev packages to install diff --git a/apache/manifests/init.pp b/apache/manifests/init.pp index 0b8544f93..37d866ad6 100644 --- a/apache/manifests/init.pp +++ b/apache/manifests/init.pp @@ -48,6 +48,7 @@ $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, $manage_user = true, @@ -124,10 +125,7 @@ } } - $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, diff --git a/apache/manifests/mod.pp b/apache/manifests/mod.pp index 0891bf0b7..bc52d2e20 100644 --- a/apache/manifests/mod.pp +++ b/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, diff --git a/apache/manifests/mod/expires.pp b/apache/manifests/mod/expires.pp index 8c1ce8441..10542916a 100644 --- a/apache/manifests/mod/expires.pp +++ b/apache/manifests/mod/expires.pp @@ -6,9 +6,9 @@ ::apache::mod { 'expires': } # Template uses - # $expries_active - # $expries_default - # $expries_by_type + # $expires_active + # $expires_default + # $expires_by_type file { 'expires.conf': ensure => file, path => "${::apache::mod_dir}/expires.conf", diff --git a/apache/manifests/mod/wsgi.pp b/apache/manifests/mod/wsgi.pp index 80f9738ff..bff5b46b7 100644 --- a/apache/manifests/mod/wsgi.pp +++ b/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/apache/manifests/mpm.pp b/apache/manifests/mpm.pp index a5cca4988..2478184f5 100644 --- a/apache/manifests/mpm.pp +++ b/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']) { diff --git a/apache/manifests/package.pp b/apache/manifests/package.pp index 395c03103..728b26010 100644 --- a/apache/manifests/package.pp +++ b/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 { @@ -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/apache/manifests/vhost.pp b/apache/manifests/vhost.pp index 70d2a57bb..bbb5e61f2 100644 --- a/apache/manifests/vhost.pp +++ b/apache/manifests/vhost.pp @@ -125,7 +125,7 @@ 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. @@ -186,8 +186,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 { @@ -625,9 +624,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 { concat::fragment { "${name}-proxy": target => "${priority_real}${filename}.conf", order => 140, diff --git a/apache/spec/acceptance/vhost_spec.rb b/apache/spec/acceptance/vhost_spec.rb index 6fe87c5a8..b5d51e91f 100644 --- a/apache/spec/acceptance/vhost_spec.rb +++ b/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 @@ -498,6 +525,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 diff --git a/apache/spec/classes/dev_spec.rb b/apache/spec/classes/dev_spec.rb index e2e0b47af..eb3d76593 100644 --- a/apache/spec/classes/dev_spec.rb +++ b/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/apache/spec/classes/mod/dev_spec.rb b/apache/spec/classes/mod/dev_spec.rb index f65338977..1686a0275 100644 --- a/apache/spec/classes/mod/dev_spec.rb +++ b/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/apache/spec/unit/puppet/parser/functions/validate_apache_log_level.rb b/apache/spec/unit/puppet/parser/functions/validate_apache_log_level.rb new file mode 100644 index 000000000..dfef66eea --- /dev/null +++ b/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/ceilometer/.fixtures.yml b/ceilometer/.fixtures.yml index 8e65f3bb6..5e57356ff 100644 --- a/ceilometer/.fixtures.yml +++ b/ceilometer/.fixtures.yml @@ -1,9 +1,10 @@ fixtures: repositories: 'apache': 'git://github.com/puppetlabs/puppetlabs-apache.git' - 'concat': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'concat': + 'repo': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'ref': '1.2.1' 'inifile': 'git://github.com/puppetlabs/puppetlabs-inifile' - 'concat': 'git://github.com/puppetlabs/puppetlabs-concat.git' 'keystone': 'git://github.com/stackforge/puppet-keystone.git' 'mysql': 'git://github.com/puppetlabs/puppetlabs-mysql.git' 'nova': 'git://github.com/stackforge/puppet-nova.git' diff --git a/ceilometer/manifests/collector.pp b/ceilometer/manifests/collector.pp index 3088fb419..c651a01bb 100644 --- a/ceilometer/manifests/collector.pp +++ b/ceilometer/manifests/collector.pp @@ -13,16 +13,38 @@ # (optional) ensure state for package. # Defaults to 'present' # +# [*udp_address*] +# (optional) the ceilometer collector udp bind address. +# Set it empty to disable the collector listener. +# Defaults to '0.0.0.0' +# +# [*udp_port*] +# (optional) the ceilometer collector udp bind port. +# Defaults to '4952' +# class ceilometer::collector ( $manage_service = true, $enabled = true, $package_ensure = 'present', + $udp_address = '0.0.0.0', + $udp_port = '4952', ) { include ::ceilometer::params Ceilometer_config<||> ~> Service['ceilometer-collector'] + # We accept udp_address to be set to empty instead of the usual undef to stay + # close to the "strange" upstream interface. + if (is_ip_address($udp_address) != true and $udp_address != '' ){ + fail("${udp_address} is not a valid ip and is not empty") + } + + ceilometer_config { + 'collector/udp_address' : value => $udp_address; + 'collector/udp_port' : value => $udp_port; + } + Package[$::ceilometer::params::collector_package_name] -> Service['ceilometer-collector'] ensure_resource( 'package', [$::ceilometer::params::collector_package_name], { ensure => $package_ensure } diff --git a/ceilometer/spec/classes/ceilometer_agent_polling_spec.rb b/ceilometer/spec/classes/ceilometer_agent_polling_spec.rb index 289214689..c729031d2 100644 --- a/ceilometer/spec/classes/ceilometer_agent_polling_spec.rb +++ b/ceilometer/spec/classes/ceilometer_agent_polling_spec.rb @@ -21,30 +21,30 @@ shared_examples_for 'ceilometer-polling' do - it { should contain_class('ceilometer::params') } + it { is_expected.to contain_class('ceilometer::params') } context 'when compute_namespace => true' do it 'adds ceilometer user to nova group and, if required, to libvirt group' do if platform_params[:libvirt_group] - should contain_user('ceilometer').with_groups(['nova', "#{platform_params[:libvirt_group]}"]) + is_expected.to contain_user('ceilometer').with_groups(['nova', "#{platform_params[:libvirt_group]}"]) else - should contain_user('ceilometer').with_groups('nova') + is_expected.to contain_user('ceilometer').with_groups('nova') end end it 'ensures nova-common is installed before the package ceilometer-common' do - should contain_package('nova-common').with( + is_expected.to contain_package('nova-common').with( :before => /Package\[ceilometer-common\]/ ) end it 'configures nova notification driver' do - should contain_file_line_after('nova-notification-driver-common').with( + is_expected.to contain_file_line_after('nova-notification-driver-common').with( :line => 'notification_driver=nova.openstack.common.notifier.rpc_notifier', :path => '/etc/nova/nova.conf', :notify => 'Service[nova-compute]' ) - should contain_file_line_after('nova-notification-driver-ceilometer').with( + is_expected.to contain_file_line_after('nova-notification-driver-ceilometer').with( :line => 'notification_driver=ceilometer.compute.nova_notifier', :path => '/etc/nova/nova.conf', :notify => 'Service[nova-compute]' @@ -53,7 +53,7 @@ end it 'installs ceilometer-polling package' do - should contain_package('ceilometer-polling').with( + is_expected.to contain_package('ceilometer-polling').with( :ensure => 'latest', :name => platform_params[:agent_package_name], :before => /Service\[ceilometer-polling\]/, @@ -62,11 +62,11 @@ end it 'configures central agent' do - should contain_ceilometer_config('DEFAULT/polling_namespaces').with_value('central,compute,ipmi') + is_expected.to contain_ceilometer_config('DEFAULT/polling_namespaces').with_value('central,compute,ipmi') end it 'ensures ceilometer-common is installed before the service' do - should contain_package('ceilometer-common').with( + is_expected.to contain_package('ceilometer-common').with( :before => /Service\[ceilometer-polling\]/ ) end @@ -78,7 +78,7 @@ end it 'configures ceilometer-polling service' do - should contain_service('ceilometer-polling').with( + is_expected.to contain_service('ceilometer-polling').with( :ensure => (params[:manage_service] && params[:enabled]) ? 'running' : 'stopped', :name => platform_params[:agent_service_name], :enable => params[:enabled], @@ -97,7 +97,7 @@ end it 'configures ceilometer-polling service' do - should contain_service('ceilometer-polling').with( + is_expected.to contain_service('ceilometer-polling').with( :ensure => nil, :name => platform_params[:agent_service_name], :enable => false, @@ -108,7 +108,7 @@ end it 'configures central agent' do - should contain_ceilometer_config('coordination/backend_url').with_value( params[:coordination_url] ) + is_expected.to contain_ceilometer_config('coordination/backend_url').with_value( params[:coordination_url] ) end end diff --git a/ceilometer/spec/classes/ceilometer_api_spec.rb b/ceilometer/spec/classes/ceilometer_api_spec.rb index 7b0c87500..e54eea1a9 100644 --- a/ceilometer/spec/classes/ceilometer_api_spec.rb +++ b/ceilometer/spec/classes/ceilometer_api_spec.rb @@ -165,12 +165,12 @@ }) end it 'configures identity_uri' do - should contain_ceilometer_config('keystone_authtoken/identity_uri').with_value("https://foo.bar:1234/"); + is_expected.to contain_ceilometer_config('keystone_authtoken/identity_uri').with_value("https://foo.bar:1234/"); # since only auth_uri is set the deprecated auth parameters should # still get set in case they are still in use - should contain_ceilometer_config('keystone_authtoken/auth_host').with_value('127.0.0.1'); - should contain_ceilometer_config('keystone_authtoken/auth_port').with_value('35357'); - should contain_ceilometer_config('keystone_authtoken/auth_protocol').with_value('http'); + is_expected.to contain_ceilometer_config('keystone_authtoken/auth_host').with_value('127.0.0.1'); + is_expected.to contain_ceilometer_config('keystone_authtoken/auth_port').with_value('35357'); + is_expected.to contain_ceilometer_config('keystone_authtoken/auth_protocol').with_value('http'); end end @@ -185,12 +185,12 @@ }) end it 'configures identity_uri and auth_uri but deprecates old auth settings' do - should contain_ceilometer_config('keystone_authtoken/identity_uri').with_value("https://foo.bar:35357/"); - should contain_ceilometer_config('keystone_authtoken/auth_uri').with_value("https://foo.bar:5000/v2.0/"); - should contain_ceilometer_config('keystone_authtoken/auth_admin_prefix').with(:ensure => 'absent') - should contain_ceilometer_config('keystone_authtoken/auth_port').with(:ensure => 'absent') - should contain_ceilometer_config('keystone_authtoken/auth_protocol').with(:ensure => 'absent') - should contain_ceilometer_config('keystone_authtoken/auth_host').with(:ensure => 'absent') + is_expected.to contain_ceilometer_config('keystone_authtoken/identity_uri').with_value("https://foo.bar:35357/"); + is_expected.to contain_ceilometer_config('keystone_authtoken/auth_uri').with_value("https://foo.bar:5000/v2.0/"); + is_expected.to contain_ceilometer_config('keystone_authtoken/auth_admin_prefix').with(:ensure => 'absent') + is_expected.to contain_ceilometer_config('keystone_authtoken/auth_port').with(:ensure => 'absent') + is_expected.to contain_ceilometer_config('keystone_authtoken/auth_protocol').with(:ensure => 'absent') + is_expected.to contain_ceilometer_config('keystone_authtoken/auth_host').with(:ensure => 'absent') end end diff --git a/ceilometer/spec/classes/ceilometer_collector_spec.rb b/ceilometer/spec/classes/ceilometer_collector_spec.rb index 314c61b94..7b3261eef 100644 --- a/ceilometer/spec/classes/ceilometer_collector_spec.rb +++ b/ceilometer/spec/classes/ceilometer_collector_spec.rb @@ -8,6 +8,39 @@ shared_examples_for 'ceilometer-collector' do + context 'when invalid ip is passed' do + let :params do + { :udp_address => '300.0.0.0' } + end + it 'should fail' do + is_expected.to raise_error(Puppet::Error, /is not a valid ip and is not empty/) + end + end + + context 'when a valid ipv6 is passed' do + before do + pre_condition << "class { 'ceilometer::db': }" + end + let :params do + { :udp_address => '::1' } + end + it 'shouldn\'t fail' do + is_expected.to_not raise_error + end + end + + context 'when an empty string passed' do + before do + pre_condition << "class { 'ceilometer::db': }" + end + let :params do + { :udp_address => '' } + end + it 'should disable the listener' do + is_expected.to contain_ceilometer_config('collector/udp_address').with_value( '' ) + end + end + context 'when enabled' do before do pre_condition << "class { 'ceilometer::db': }" @@ -15,6 +48,11 @@ it { is_expected.to contain_class('ceilometer::params') } + it 'configures ceilometer-collector server' do + is_expected.to contain_ceilometer_config('collector/udp_address').with_value( '0.0.0.0' ) + is_expected.to contain_ceilometer_config('collector/udp_port').with_value( '4952' ) + end + it 'installs ceilometer-collector package' do is_expected.to contain_package(platform_params[:collector_package_name]).with( :ensure => 'present' @@ -44,7 +82,6 @@ # Catalog compilation does not crash for lack of ceilometer::db it { is_expected.to compile } - it 'configures ceilometer-collector service' do is_expected.to contain_service('ceilometer-collector').with( :ensure => 'stopped', diff --git a/ceilometer/spec/unit/provider/ceilometer_config/ini_setting_spec.rb b/ceilometer/spec/unit/provider/ceilometer_config/ini_setting_spec.rb new file mode 100644 index 000000000..172766dc2 --- /dev/null +++ b/ceilometer/spec/unit/provider/ceilometer_config/ini_setting_spec.rb @@ -0,0 +1,42 @@ +$LOAD_PATH.push( + File.join( + File.dirname(__FILE__), + '..', + '..', + '..', + 'fixtures', + 'modules', + 'inifile', + 'lib') +) + +require 'spec_helper' + +provider_class = Puppet::Type.type(:ceilometer_config).provider(:ini_setting) + +describe provider_class do + + it 'should default to the default setting when no other one is specified' do + resource = Puppet::Type::Ceilometer_config.new( + { + :name => 'DEFAULT/foo', + :value => 'bar' + } + ) + provider = provider_class.new(resource) + expect(provider.section).to eq('DEFAULT') + expect(provider.setting).to eq('foo') + end + + it 'should allow setting to be set explicitly' do + resource = Puppet::Type::Ceilometer_config.new( + { + :name => 'dude/foo', + :value => 'bar' + } + ) + provider = provider_class.new(resource) + expect(provider.section).to eq('dude') + expect(provider.setting).to eq('foo') + end +end diff --git a/ceilometer/spec/unit/type/ceilometer_config_spec.rb b/ceilometer/spec/unit/type/ceilometer_config_spec.rb new file mode 100644 index 000000000..226507eb9 --- /dev/null +++ b/ceilometer/spec/unit/type/ceilometer_config_spec.rb @@ -0,0 +1,53 @@ +require 'puppet' +require 'puppet/type/ceilometer_config' + +describe 'Puppet::Type.type(:ceilometer_config)' do + before :each do + @ceilometer_config = Puppet::Type.type(:ceilometer_config).new(:name => 'DEFAULT/foo', :value => 'bar') + end + + it 'should require a name' do + expect { + Puppet::Type.type(:ceilometer_config).new({}) + }.to raise_error(Puppet::Error, 'Title or name must be provided') + end + + it 'should not expect a name with whitespace' do + expect { + Puppet::Type.type(:ceilometer_config).new(:name => 'f oo') + }.to raise_error(Puppet::Error, /Parameter name failed/) + end + + it 'should fail when there is no section' do + expect { + Puppet::Type.type(:ceilometer_config).new(:name => 'foo') + }.to raise_error(Puppet::Error, /Parameter name failed/) + end + + it 'should not require a value when ensure is absent' do + Puppet::Type.type(:ceilometer_config).new(:name => 'DEFAULT/foo', :ensure => :absent) + end + + it 'should accept a valid value' do + @ceilometer_config[:value] = 'bar' + expect(@ceilometer_config[:value]).to eq('bar') + end + + it 'should not accept a value with whitespace' do + @ceilometer_config[:value] = 'b ar' + expect(@ceilometer_config[:value]).to eq('b ar') + end + + it 'should accept valid ensure values' do + @ceilometer_config[:ensure] = :present + expect(@ceilometer_config[:ensure]).to eq(:present) + @ceilometer_config[:ensure] = :absent + expect(@ceilometer_config[:ensure]).to eq(:absent) + end + + it 'should not accept invalid ensure values' do + expect { + @ceilometer_config[:ensure] = :latest + }.to raise_error(Puppet::Error, /Invalid value/) + end +end diff --git a/cinder/.fixtures.yml b/cinder/.fixtures.yml index affff36e5..257dcf62a 100644 --- a/cinder/.fixtures.yml +++ b/cinder/.fixtures.yml @@ -1,7 +1,9 @@ fixtures: repositories: 'apt': 'git://github.com/puppetlabs/puppetlabs-apt.git' - 'concat': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'concat': + 'repo': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'ref': '1.2.1' 'inifile': 'git://github.com/puppetlabs/puppetlabs-inifile' 'keystone': 'git://github.com/stackforge/puppet-keystone.git' 'mysql': 'git://github.com/puppetlabs/puppetlabs-mysql.git' diff --git a/cinder/manifests/api.pp b/cinder/manifests/api.pp index a47c0ae4d..44932ba13 100644 --- a/cinder/manifests/api.pp +++ b/cinder/manifests/api.pp @@ -119,6 +119,10 @@ # try_sleep: 10 # Defaults to {} # +# [*sync_db*] +# (Optional) Run db sync on the node. +# Defaults to true +# class cinder::api ( $keystone_password, $keystone_enabled = true, @@ -137,6 +141,7 @@ $ratelimits_factory = 'cinder.api.v1.limits:RateLimitingMiddleware.factory', $validate = false, + $sync_db = true, # DEPRECATED PARAMETERS $validation_options = {}, $keystone_auth_uri = false, @@ -168,16 +173,18 @@ } if $enabled { - Cinder_config<||> ~> Exec['cinder-manage db_sync'] + if $sync_db { + Cinder_config<||> ~> Exec['cinder-manage db_sync'] - exec { 'cinder-manage db_sync': - command => $::cinder::params::db_sync_command, - path => '/usr/bin', - user => 'cinder', - refreshonly => true, - logoutput => 'on_failure', - subscribe => Package['cinder'], - before => Service['cinder-api'], + exec { 'cinder-manage db_sync': + command => $::cinder::params::db_sync_command, + path => '/usr/bin', + user => 'cinder', + refreshonly => true, + logoutput => 'on_failure', + subscribe => Package['cinder'], + before => Service['cinder-api'], + } } if $manage_service { $ensure = 'running' diff --git a/cinder/manifests/backend/netapp.pp b/cinder/manifests/backend/netapp.pp index 2a5b01681..4c7141343 100644 --- a/cinder/manifests/backend/netapp.pp +++ b/cinder/manifests/backend/netapp.pp @@ -11,17 +11,17 @@ # # [*netapp_password*] # (required) Password for the administrative user account specified in the -# netapp_login parameter. +# netapp_login option. # # [*netapp_server_hostname*] # (required) The hostname (or IP address) for the storage system or proxy # server. # # [*netapp_server_port*] -# (optional) The TCP port to use for communication with ONTAPI on the -# storage system. Traditionally, port 80 is used for HTTP and port 443 is -# used for HTTPS; however, this value should be changed if an alternate -# port has been configured on the storage system or proxy server. +# (optional) The TCP port to use for communication with the storage +# system or proxy. If not specified, Data ONTAP drivers will use 80 +# for HTTP and 443 for HTTPS; E-Series will use 8080 for HTTP and +# 8443 for HTTPS. # Defaults to 80 # # [*netapp_size_multiplier*] @@ -32,46 +32,48 @@ # # [*netapp_storage_family*] # (optional) The storage family type used on the storage system; valid values -# are ontap_7mode for using Data ONTAP operating in 7-Mode or ontap_cluster +# are ontap_7mode for using Data ONTAP operating in 7-Mode, ontap_cluster # for using clustered Data ONTAP, or eseries for NetApp E-Series. # Defaults to ontap_cluster # # [*netapp_storage_protocol*] # (optional) The storage protocol to be used on the data path with the storage -# system; valid values are iscsi or nfs. +# system. Valid values are iscsi, fc, nfs. # Defaults to nfs # # [*netapp_transport_type*] -# (optional) The transport protocol used when communicating with ONTAPI on the -# storage system or proxy server. Valid values are http or https. +# (optional) The transport protocol used when communicating with the storage +# system or proxy server. Valid values are http or https. # Defaults to http # # [*netapp_vfiler*] # (optional) The vFiler unit on which provisioning of block storage volumes # will be done. This parameter is only used by the driver when connecting to -# an instance with a storage family of Data ONTAP operating in 7-Mode and the -# storage protocol selected is iSCSI. Only use this parameter when utilizing -# the MultiStore feature on the NetApp storage system. -# Defaults to '' +# an instance with a storage family of Data ONTAP operating in 7-Mode. Only +# use this parameter when utilizing the MultiStore feature on the NetApp +# storage system. +# Defaults to undef # # [*netapp_volume_list*] # (optional) This parameter is only utilized when the storage protocol is -# configured to use iSCSI. This parameter is used to restrict provisioning to -# the specified controller volumes. Specify the value of this parameter to be -# a comma separated list of NetApp controller volume names to be used for -# provisioning. -# Defaults to '' +# configured to use iSCSI or FC. This parameter is used to restrict +# provisioning to the specified controller volumes. Specify the value of +# this parameter to be a comma separated list of NetApp controller volume +# names to be used for provisioning. +# Defaults to undef # # [*netapp_vserver*] -# (optional) This parameter specifies the virtual storage server (Vserver) +# (optional) This option specifies the virtual storage server (Vserver) # name on the storage cluster on which provisioning of block storage volumes -# should occur. If using the NFS storage protocol, this parameter is mandatory -# for storage service catalog support (utilized by Cinder volume type -# extra_specs support). If this parameter is specified, the exports belonging -# to the Vserver will only be used for provisioning in the future. Block -# storage volumes on exports not belonging to the Vserver specified by -# this parameter will continue to function normally. -# Defaults to '' +# should occur. +# Defaults to undef +# +# [*netapp_partner_backend_name*] +# (optional) The name of the config.conf stanza for a Data ONTAP (7-mode) +# HA partner. This option is only used by the driver when connecting to an +# instance with a storage family of Data ONTAP operating in 7-Mode, and it is +# required if the storage protocol selected is FC. +# Defaults to undef # # [*expiry_thres_minutes*] # (optional) This parameter specifies the threshold for last access time for @@ -107,7 +109,7 @@ # (optional) This option specifies the path of the NetApp Copy Offload tool # binary. Ensure that the binary has execute permissions set which allow the # effective user of the cinder-volume process to execute the file. -# Defaults to '' +# Defaults to undef # # [*netapp_controller_ips*] # (optional) This option is only utilized when the storage family is @@ -115,18 +117,24 @@ # specified controllers. Specify the value of this option to be a comma # separated list of controller hostnames or IP addresses to be used for # provisioning. -# Defaults to '' +# Defaults to undef # # [*netapp_sa_password*] # (optional) Password for the NetApp E-Series storage array. -# Defaults to '' +# Defaults to undef # # [*netapp_storage_pools*] # (optional) This option is used to restrict provisioning to the specified # storage pools. Only dynamic disk pools are currently supported. Specify the # value of this option to be a comma separated list of disk pool names to be # used for provisioning. -# Defaults to '' +# Defaults to undef +# +# [*netapp_eseries_host_type*] +# (optional) This option is used to define how the controllers in the +# E-Series storage array will work with the particular operating system on +# the hosts that are connected to it. +# Defaults to 'linux_dm_mp' # # [*netapp_webservice_path*] # (optional) This option is used to specify the path to the E-Series proxy @@ -171,18 +179,20 @@ $netapp_storage_family = 'ontap_cluster', $netapp_storage_protocol = 'nfs', $netapp_transport_type = 'http', - $netapp_vfiler = '', - $netapp_volume_list = '', - $netapp_vserver = '', + $netapp_vfiler = undef, + $netapp_volume_list = undef, + $netapp_vserver = undef, + $netapp_partner_backend_name = undef, $expiry_thres_minutes = '720', $thres_avl_size_perc_start = '20', $thres_avl_size_perc_stop = '60', $nfs_shares = undef, $nfs_shares_config = '/etc/cinder/shares.conf', - $netapp_copyoffload_tool_path = '', - $netapp_controller_ips = '', - $netapp_sa_password = '', - $netapp_storage_pools = '', + $netapp_copyoffload_tool_path = undef, + $netapp_controller_ips = undef, + $netapp_sa_password = undef, + $netapp_storage_pools = undef, + $netapp_eseries_host_type = 'linux_dm_mp', $netapp_webservice_path = '/devmgr/v2', $extra_options = {}, ) { @@ -210,6 +220,7 @@ "${volume_backend_name}/netapp_vfiler": value => $netapp_vfiler; "${volume_backend_name}/netapp_volume_list": value => $netapp_volume_list; "${volume_backend_name}/netapp_vserver": value => $netapp_vserver; + "${volume_backend_name}/netapp_partner_backend_name": value => $netapp_partner_backend_name; "${volume_backend_name}/expiry_thres_minutes": value => $expiry_thres_minutes; "${volume_backend_name}/thres_avl_size_perc_start": value => $thres_avl_size_perc_start; "${volume_backend_name}/thres_avl_size_perc_stop": value => $thres_avl_size_perc_stop; @@ -218,6 +229,7 @@ "${volume_backend_name}/netapp_controller_ips": value => $netapp_controller_ips; "${volume_backend_name}/netapp_sa_password": value => $netapp_sa_password, secret => true; "${volume_backend_name}/netapp_storage_pools": value => $netapp_storage_pools; + "${volume_backend_name}/netapp_eseries_host_type": value => $netapp_eseries_host_type; "${volume_backend_name}/netapp_webservice_path": value => $netapp_webservice_path; } diff --git a/cinder/manifests/params.pp b/cinder/manifests/params.pp index 5bdb7bb5f..7f7f4aec4 100644 --- a/cinder/manifests/params.pp +++ b/cinder/manifests/params.pp @@ -42,7 +42,7 @@ $lio_package_name = 'targetcli' case $::operatingsystem { - 'RedHat', 'CentOS', 'Scientific': { + 'RedHat', 'CentOS', 'Scientific', 'OracleLinux': { if (versioncmp($::operatingsystemmajrelease, '7') >= 0) { $iscsi_helper = 'lioadm' } else { diff --git a/cinder/manifests/volume/netapp.pp b/cinder/manifests/volume/netapp.pp index 5dd8ef9f5..4fc3066de 100644 --- a/cinder/manifests/volume/netapp.pp +++ b/cinder/manifests/volume/netapp.pp @@ -6,20 +6,21 @@ # # [*netapp_login*] # (required) Administrative user account name used to access the storage -# system. +# system or proxy server. # # [*netapp_password*] # (required) Password for the administrative user account specified in the -# netapp_login parameter. +# netapp_login option. # # [*netapp_server_hostname*] -# (required) The hostname (or IP address) for the storage system. +# (required) The hostname (or IP address) for the storage system or proxy +# server. # # [*netapp_server_port*] -# (optional) The TCP port to use for communication with ONTAPI on the -# storage system. Traditionally, port 80 is used for HTTP and port 443 is -# used for HTTPS; however, this value should be changed if an alternate -# port has been configured on the storage system. +# (optional) The TCP port to use for communication with the storage +# system or proxy. If not specified, Data ONTAP drivers will use 80 +# for HTTP and 443 for HTTPS; E-Series will use 8080 for HTTP and +# 8443 for HTTPS. # Defaults to 80 # # [*netapp_size_multiplier*] @@ -30,46 +31,48 @@ # # [*netapp_storage_family*] # (optional) The storage family type used on the storage system; valid values -# are ontap_7mode for using Data ONTAP operating in 7-Mode or ontap_cluster -# for using clustered Data ONTAP. +# are ontap_7mode for using Data ONTAP operating in 7-Mode, ontap_cluster +# for using clustered Data ONTAP, or eseries for NetApp E-Series. # Defaults to ontap_cluster # # [*netapp_storage_protocol*] # (optional) The storage protocol to be used on the data path with the storage -# system; valid values are iscsi or nfs. +# system. Valid values are iscsi, fc, nfs. # Defaults to nfs # # [*netapp_transport_type*] -# (optional) The transport protocol used when communicating with ONTAPI on the -# storage system. Valid values are http or https. +# (optional) The transport protocol used when communicating with the storage +# system or proxy server. Valid values are http or https. # Defaults to http # # [*netapp_vfiler*] # (optional) The vFiler unit on which provisioning of block storage volumes # will be done. This parameter is only used by the driver when connecting to -# an instance with a storage family of Data ONTAP operating in 7-Mode and the -# storage protocol selected is iSCSI. Only use this parameter when utilizing -# the MultiStore feature on the NetApp storage system. -# Defaults to '' +# an instance with a storage family of Data ONTAP operating in 7-Mode. Only +# use this parameter when utilizing the MultiStore feature on the NetApp +# storage system. +# Defaults to undef # # [*netapp_volume_list*] # (optional) This parameter is only utilized when the storage protocol is -# configured to use iSCSI. This parameter is used to restrict provisioning to -# the specified controller volumes. Specify the value of this parameter to be -# a comma separated list of NetApp controller volume names to be used for -# provisioning. -# Defaults to '' +# configured to use iSCSI or FC. This parameter is used to restrict +# provisioning to the specified controller volumes. Specify the value of +# this parameter to be a comma separated list of NetApp controller volume +# names to be used for provisioning. +# Defaults to undef # # [*netapp_vserver*] -# (optional) This parameter specifies the virtual storage server (Vserver) +# (optional) This option specifies the virtual storage server (Vserver) # name on the storage cluster on which provisioning of block storage volumes -# should occur. If using the NFS storage protocol, this parameter is mandatory -# for storage service catalog support (utilized by Cinder volume type -# extra_specs support). If this parameter is specified, the exports belonging -# to the Vserver will only be used for provisioning in the future. Block -# storage volumes on exports not belonging to the Vserver specified by -# this parameter will continue to function normally. -# Defaults to '' +# should occur. +# Defaults to undef +# +# [*netapp_partner_backend_name*] +# (optional) The name of the config.conf stanza for a Data ONTAP (7-mode) +# HA partner. This option is only used by the driver when connecting to an +# instance with a storage family of Data ONTAP operating in 7-Mode, and it is +# required if the storage protocol selected is FC. +# Defaults to undef # # [*expiry_thres_minutes*] # (optional) This parameter specifies the threshold for last access time for @@ -86,10 +89,10 @@ # Defaults to 20 # # [*thres_avl_size_perc_stop*] -# (optional) When the percentage of available space on an NFS share has reached the -# percentage specified by this parameter, the driver will stop clearing files -# from the NFS image cache that have not been accessed in the last M -# 'minutes, where M is the value of the expiry_thres_minutes parameter. +# (optional) When the percentage of available space on an NFS share has +# reached the percentage specified by this parameter, the driver will stop +# clearing files from the NFS image cache that have not been accessed in the +# last M minutes, where M is the value of the expiry_thres_minutes parameter. # Defaults to 60 # # [*nfs_shares*] @@ -105,7 +108,7 @@ # (optional) This option specifies the path of the NetApp Copy Offload tool # binary. Ensure that the binary has execute permissions set which allow the # effective user of the cinder-volume process to execute the file. -# Defaults to '' +# Defaults to undef # # [*netapp_controller_ips*] # (optional) This option is only utilized when the storage family is @@ -113,18 +116,24 @@ # specified controllers. Specify the value of this option to be a comma # separated list of controller hostnames or IP addresses to be used for # provisioning. -# Defaults to '' +# Defaults to undef # # [*netapp_sa_password*] # (optional) Password for the NetApp E-Series storage array. -# Defaults to '' +# Defaults to undef # # [*netapp_storage_pools*] # (optional) This option is used to restrict provisioning to the specified # storage pools. Only dynamic disk pools are currently supported. Specify the # value of this option to be a comma separated list of disk pool names to be # used for provisioning. -# Defaults to '' +# Defaults to undef +# +# [*netapp_eseries_host_type*] +# (optional) This option is used to define how the controllers in the +# E-Series storage array will work with the particular operating system on +# the hosts that are connected to it. +# Defaults to 'linux_dm_mp' # # [*netapp_webservice_path*] # (optional) This option is used to specify the path to the E-Series proxy @@ -168,18 +177,20 @@ $netapp_storage_family = 'ontap_cluster', $netapp_storage_protocol = 'nfs', $netapp_transport_type = 'http', - $netapp_vfiler = '', - $netapp_volume_list = '', - $netapp_vserver = '', + $netapp_vfiler = undef, + $netapp_volume_list = undef, + $netapp_vserver = undef, + $netapp_partner_backend_name = undef, $expiry_thres_minutes = '720', $thres_avl_size_perc_start = '20', $thres_avl_size_perc_stop = '60', $nfs_shares = undef, $nfs_shares_config = '/etc/cinder/shares.conf', - $netapp_copyoffload_tool_path = '', - $netapp_controller_ips = '', - $netapp_sa_password = '', - $netapp_storage_pools = '', + $netapp_copyoffload_tool_path = undef, + $netapp_controller_ips = undef, + $netapp_sa_password = undef, + $netapp_storage_pools = undef, + $netapp_eseries_host_type = 'linux_dm_mp', $netapp_webservice_path = '/devmgr/v2', $extra_options = {}, ) { @@ -196,6 +207,7 @@ netapp_vfiler => $netapp_vfiler, netapp_volume_list => $netapp_volume_list, netapp_vserver => $netapp_vserver, + netapp_partner_backend_name => $netapp_partner_backend_name, expiry_thres_minutes => $expiry_thres_minutes, thres_avl_size_perc_start => $thres_avl_size_perc_start, thres_avl_size_perc_stop => $thres_avl_size_perc_stop, @@ -205,6 +217,7 @@ netapp_controller_ips => $netapp_controller_ips, netapp_sa_password => $netapp_sa_password, netapp_storage_pools => $netapp_storage_pools, + netapp_eseries_host_type => $netapp_eseries_host_type, netapp_webservice_path => $netapp_webservice_path, extra_options => $extra_options, } diff --git a/cinder/spec/classes/cinder_api_spec.rb b/cinder/spec/classes/cinder_api_spec.rb index ab610b561..6b262ea18 100644 --- a/cinder/spec/classes/cinder_api_spec.rb +++ b/cinder/spec/classes/cinder_api_spec.rb @@ -117,6 +117,17 @@ end end + describe 'with sync_db set to false' do + let :params do + { + :keystone_password => 'dummy', + :enabled => 'true', + :sync_db => false, + } + end + it { is_expected.not_to contain_exec('cinder-manage db_sync') } + end + [ '/keystone', '/keystone/admin' ].each do |keystone_auth_admin_prefix| describe "with keystone_auth_admin_prefix containing correct value #{keystone_auth_admin_prefix}" do let :params do diff --git a/cinder/spec/classes/cinder_volume_netapp_spec.rb b/cinder/spec/classes/cinder_volume_netapp_spec.rb index e22c25f55..b2ce5c203 100644 --- a/cinder/spec/classes/cinder_volume_netapp_spec.rb +++ b/cinder/spec/classes/cinder_volume_netapp_spec.rb @@ -4,9 +4,17 @@ let :params do { - :netapp_login => 'netapp', - :netapp_password => 'password', - :netapp_server_hostname => '127.0.0.2', + :netapp_login => 'netapp', + :netapp_password => 'password', + :netapp_server_hostname => '127.0.0.2', + :netapp_vfiler => 'netapp_vfiler', + :netapp_volume_list => 'vol1,vol2', + :netapp_vserver => 'netapp_vserver', + :netapp_partner_backend_name => 'fc2', + :netapp_copyoffload_tool_path => '/tmp/na_copyoffload_64', + :netapp_controller_ips => '10.0.0.2,10.0.0.3', + :netapp_sa_password => 'password', + :netapp_storage_pools => 'pool1,pool2', } end @@ -17,17 +25,11 @@ :netapp_storage_family => 'ontap_cluster', :netapp_storage_protocol => 'nfs', :netapp_transport_type => 'http', - :netapp_vfiler => '', - :netapp_volume_list => '', - :netapp_vserver => '', :expiry_thres_minutes => '720', :thres_avl_size_perc_start => '20', :thres_avl_size_perc_stop => '60', :nfs_shares_config => '/etc/cinder/shares.conf', - :netapp_copyoffload_tool_path => '', - :netapp_controller_ips => '', - :netapp_sa_password => '', - :netapp_storage_pools => '', + :netapp_eseries_host_type => 'linux_dm_mp', :netapp_webservice_path => '/devmgr/v2', } end diff --git a/cinder/spec/defines/cinder_backend_netapp_spec.rb b/cinder/spec/defines/cinder_backend_netapp_spec.rb index 082d86b23..2bdc0efa8 100644 --- a/cinder/spec/defines/cinder_backend_netapp_spec.rb +++ b/cinder/spec/defines/cinder_backend_netapp_spec.rb @@ -6,10 +6,18 @@ let :params do { - :volume_backend_name => 'netapp-cdot-nfs', - :netapp_login => 'netapp', - :netapp_password => 'password', - :netapp_server_hostname => '127.0.0.2', + :volume_backend_name => 'netapp-cdot-nfs', + :netapp_login => 'netapp', + :netapp_password => 'password', + :netapp_server_hostname => '127.0.0.2', + :netapp_vfiler => 'netapp_vfiler', + :netapp_volume_list => 'vol1,vol2', + :netapp_vserver => 'netapp_vserver', + :netapp_partner_backend_name => 'fc2', + :netapp_copyoffload_tool_path => '/tmp/na_copyoffload_64', + :netapp_controller_ips => '10.0.0.2,10.0.0.3', + :netapp_sa_password => 'password', + :netapp_storage_pools => 'pool1,pool2', } end @@ -20,17 +28,11 @@ :netapp_storage_family => 'ontap_cluster', :netapp_storage_protocol => 'nfs', :netapp_transport_type => 'http', - :netapp_vfiler => '', - :netapp_volume_list => '', - :netapp_vserver => '', :expiry_thres_minutes => '720', :thres_avl_size_perc_start => '20', :thres_avl_size_perc_stop => '60', :nfs_shares_config => '/etc/cinder/shares.conf', - :netapp_copyoffload_tool_path => '', - :netapp_controller_ips => '', - :netapp_sa_password => '', - :netapp_storage_pools => '', + :netapp_eseries_host_type => 'linux_dm_mp', :netapp_webservice_path => '/devmgr/v2', } end diff --git a/concat/.fixtures.yml b/concat/.fixtures.yml index 67added0a..3d0f23a98 100644 --- a/concat/.fixtures.yml +++ b/concat/.fixtures.yml @@ -2,6 +2,9 @@ fixtures: repositories: 'stdlib': repo: 'git://github.com/puppetlabs/puppetlabs-stdlib.git' - ref: '4.2.0' + ref: '4.5.1' + 'file_concat': + repo: 'git://github.com/electrical/puppet-lib-file_concat.git' + ref: '1.0.1' symlinks: 'concat': '#{source_dir}' diff --git a/concat/.gitignore b/concat/.gitignore index b5db85e05..ef01482d1 100644 --- a/concat/.gitignore +++ b/concat/.gitignore @@ -7,3 +7,4 @@ spec/fixtures/ coverage/ .idea/ *.iml +*.swp diff --git a/concat/Gemfile b/concat/Gemfile index cc4048aec..f7319c221 100644 --- a/concat/Gemfile +++ b/concat/Gemfile @@ -12,13 +12,14 @@ 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 'rspec-core', '~> 3.1.7', :require => false + gem 'rspec-puppet', '~> 2.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 + gem 'pry' end beaker_version = ENV['BEAKER_VERSION'] diff --git a/concat/README.md b/concat/README.md index 873f6478a..aba73b42c 100644 --- a/concat/README.md +++ b/concat/README.md @@ -9,9 +9,9 @@ * [Beginning with concat](#beginning-with-concat) 4. [Usage - Configuration options and additional functionality](#usage) 5. [Reference - An under-the-hood peek at what the module is doing and how](#reference) - * [Public Defines](#public-defines) + * [Defines](#defines) * [Parameters](#parameters) - * [Deprecations](#deprecations) + * [Removed functionality](#removed-functionality) 6. [Limitations - OS compatibility, etc.](#limitations) 7. [Development - Guide for contributing to the module](#development) @@ -21,14 +21,13 @@ The concat module lets you construct files from multiple ordered fragments of te ##Module Description -The concat module lets you gather `concat::fragment` resources from your other modules and order them through a single `concat` resource into a coherent file. It does this through a Ruby script and a temporary holding space for the fragments. +The concat module lets you gather `concat::fragment` resources from your other modules and order them into a coherent file through a single `concat` resource. ##Setup ###What concat affects -* Installs `concatfragments.rb`. -* Adds a `concat/` directory into Puppet's `vardir`. +The concat module requires the [file_concat module](https://forge.puppetlabs.com/ispavailability/file_concat). If you don't have file_concat installed, concat installs it for you. ###Beginning with concat @@ -123,9 +122,7 @@ When you're finished, the motd file will look something like this: ##Reference -**Note**: Several of this module's parameters and features have been deprecated. See the [Deprecations](#deprecations) section below. - -###Public defines +###Defines * `concat`: Manages a file, compiled from one or more text fragments. * `concat::fragment`: Manages a fragment of text to be compiled into a file. @@ -143,15 +140,6 @@ Specifies whether (and how) to back up the destination file before overwriting i Specifies whether the destination file should exist. Setting to 'absent' tells Puppet to delete the destination file if it exists, and negates the effect of any other parameters. Valid options: 'present' and 'absent'. Default value: 'present'. - -#####`ensure_newline` - -Specifies whether to ensure there's a new line at the end of each fragment. Valid options: 'true' and 'false'. Default value: 'false'. - -#####`force` - -In case no fragments have been added, this parameter specifies whether to go ahead and create a potentially empty file. Valid options: 'true' and 'false'. Default value: 'false'. - #####`group` Specifies a permissions group for the destination file. Valid options: a string containing a group name. Default value: undefined. @@ -168,12 +156,10 @@ You can override this setting for individual fragments by adjusting the `order` #####`owner` - Specifies the owner of the destination file. Valid options: a string containing a username. Default value: undefined. #####`path` - Specifies a destination file for the combined fragments. Valid options: a string containing an absolute path. Default value: the title of your declared resource. #####`replace` @@ -184,12 +170,11 @@ Specifies whether to overwrite the destination file if it already exists. Valid Specifies a validation command to apply to the destination file. Requires Puppet version 3.5 or newer. Valid options: a string to be passed to a file resource. Default value: undefined. -#####`warn` - -Specifies whether to add a warning message at the top of the destination file so users know it was autogenerated by Puppet. Valid options: 'true', 'false', or a string to be delivered as a warning message. Default value: 'false'. +#####`warn_header` +Specifies whether to add a header message at the top of the destination file so users know it was autogenerated by Puppet. In earlier versions of the concat module, this parameter was called `warn`. Valid options: the booleans 'true' and 'false', or a string to serve as the header. Default value: 'false'. -If you set this parameter to 'true', Puppet adds the following message: +If you set 'warn_header' to 'true', `concat` adds the following message: ~~~ # This file is managed by Puppet. DO NOT EDIT. @@ -197,17 +182,12 @@ If you set this parameter to 'true', Puppet adds the following message: ####`concat::fragment` - Except where noted, all the below parameters are optional. #####`content` Supplies the content of the fragment. **Note**: You must supply either a `content` parameter or a `source` parameter. Valid options: a string. Default value: undef. -#####`ensure` - -Specifies whether the fragment should be included in the destination file or discarded. Valid options: 'present' and 'absent'. Default value: 'present'. - #####`order` Reorders your fragments within the destination file. Fragments that share the same order number are ordered by name. Valid options: a string (recommended) or an integer. Default value: '10'. @@ -220,51 +200,26 @@ Specifies a file to read into the content of the fragment. **Note**: You must su *Required.* Specifies the destination file of the fragment. Valid options: a string containing an absolute path. -###Deprecations - -**`concat` has the following deprecations** - -#####`gnu` - -Generates a catalog compile time warning and has no effect. This parameter was silently ignored in version `1.0.0` and will be removed in a future release. - -#####stringified 'true'/'false' values deprecated in `warn` - -Passing stringified boolean values (strings of 'true' and 'false') to the `warn` parameter of `concat` is deprecated. Generates a catalog compile time warning, and will be silently treated as the concatenated file header/warning message in a future release. - -Please migrate to using the Puppet DSL's native [Boolean data -type](http://docs.puppetlabs.com/puppet/3/reference/lang_datatypes.html#booleans). - - -**`concat::fragment` has the following deprecations** - -#####`backup` - -Generates a catalog compile time warning and has no effect. In the `1.0.0` release this parameter controlled file bucketing of the file fragment. Bucketing the fragment(s) is redundant with bucketing the final concatenated file and this feature has been removed. - - -#####`group` - -Generates a catalog compile time warning and has no effect. Had no user-visible effect in version `1.0.0` and will be removed in a future release. - -#####`mode` - -Generates a catalog compile time warning and has no effect. Had no user-visible effect in version `1.0.0` and will be removed in a future release. - - -#####`owner` - -Generates a catalog compile time warning and has no effect. Had no user-visible effect in version `1.0.0` and will be removed in a future release. +###Removed functionality -#####file paths are deprecated in `ensure` +The following functionality existed in previous versions of the concat module, but were removed in version 2.0.0: -Passing a value other than 'present' or 'absent' in the `ensure` parameter of `concat::fragment` is **deprecated**, and generates a catalog compile time warning. The warning will become a catalog compilation failure in a future release. +Parameters removed from `concat`: +* `ensure_newline` +* `force` +* `warn` (replaced by `warn_header`) -If you want to use the content of a file as a fragment please use the [`source`](#source) parameter. +Parameters removed from `concat::fragment`: +* `ensure` +* `gnu` +* `backup` +* `group` +* `mode` +* `owner` -####`concat::setup` +The `concat::setup` class has also been removed. -The `concat::setup` class should no longer be directly included in the manifest. It will be removed in a future release. +Prior to concat version 2.0.0, if you set the `warn` parameter to a string value of 'true', 'false', 'yes', 'no', 'on', or 'off', the module translated the string to the corresponding boolean value. In concat version 2.0.0 and newer, the `warn_header` parameter treats those values the same as other strings and uses them as the content of your header message. To avoid that, pass the 'true' and 'false' values as booleans instead of strings. ##Limitations diff --git a/concat/files/concatfragments.rb b/concat/files/concatfragments.rb deleted file mode 100644 index b16f3e13c..000000000 --- a/concat/files/concatfragments.rb +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env ruby -# Script to concat files to a config file. -# -# Given a directory like this: -# /path/to/conf.d -# |-- fragments -# | |-- 00_named.conf -# | |-- 10_domain.net -# | `-- zz_footer -# -# The script supports a test option that will build the concat file to a temp location and -# use /usr/bin/cmp to verify if it should be run or not. This would result in the concat happening -# twice on each run but gives you the option to have an unless option in your execs to inhibit rebuilds. -# -# Without the test option and the unless combo your services that depend on the final file would end up -# restarting on each run, or in other manifest models some changes might get missed. -# -# OPTIONS: -# -o The file to create from the sources -# -d The directory where the fragments are kept -# -t Test to find out if a build is needed, basically concats the files to a temp -# location and compare with what's in the final location, return codes are designed -# for use with unless on an exec resource -# -w Add a shell style comment at the top of the created file to warn users that it -# is generated by puppet -# -f Enables the creation of empty output files when no fragments are found -# -n Sort the output numerically rather than the default alpha sort -# -# the command: -# -# concatfragments.rb -o /path/to/conffile.cfg -d /path/to/conf.d -# -# creates /path/to/conf.d/fragments.concat and copies the resulting -# file to /path/to/conffile.cfg. The files will be sorted alphabetically -# pass the -n switch to sort numerically. -# -# The script does error checking on the various dirs and files to make -# sure things don't fail. -require 'optparse' -require 'fileutils' - -settings = { - :outfile => "", - :workdir => "", - :test => false, - :force => false, - :warn => "", - :sortarg => "", - :newline => false -} - -OptionParser.new do |opts| - opts.banner = "Usage: #{$0} [options]" - opts.separator "Specific options:" - - opts.on("-o", "--outfile OUTFILE", String, "The file to create from the sources") do |o| - settings[:outfile] = o - end - - opts.on("-d", "--workdir WORKDIR", String, "The directory where the fragments are kept") do |d| - settings[:workdir] = d - end - - opts.on("-t", "--test", "Test to find out if a build is needed") do - settings[:test] = true - end - - opts.separator "Other options:" - opts.on("-w", "--warn WARNMSG", String, - "Add a shell style comment at the top of the created file to warn users that it is generated by puppet") do |w| - settings[:warn] = w - end - - opts.on("-f", "--force", "Enables the creation of empty output files when no fragments are found") do - settings[:force] = true - end - - opts.on("-n", "--sort", "Sort the output numerically rather than the default alpha sort") do - settings[:sortarg] = "-n" - end - - opts.on("-l", "--line", "Append a newline") do - settings[:newline] = true - end -end.parse! - -# do we have -o? -raise 'Please specify an output file with -o' unless !settings[:outfile].empty? - -# do we have -d? -raise 'Please specify fragments directory with -d' unless !settings[:workdir].empty? - -# can we write to -o? -if File.file?(settings[:outfile]) - if !File.writable?(settings[:outfile]) - raise "Cannot write to #{settings[:outfile]}" - end -else - if !File.writable?(File.dirname(settings[:outfile])) - raise "Cannot write to dirname #{File.dirname(settings[:outfile])} to create #{settings[:outfile]}" - end -end - -# do we have a fragments subdir inside the work dir? -if !File.directory?(File.join(settings[:workdir], "fragments")) && !File.executable?(File.join(settings[:workdir], "fragments")) - raise "Cannot access the fragments directory" -end - -# are there actually any fragments? -if (Dir.entries(File.join(settings[:workdir], "fragments")) - %w{ . .. }).empty? - if !settings[:force] - raise "The fragments directory is empty, cowardly refusing to make empty config files" - end -end - -Dir.chdir(settings[:workdir]) - -if settings[:warn].empty? - File.open("fragments.concat", 'w') { |f| f.write("") } -else - File.open("fragments.concat", 'w') { |f| f.write("#{settings[:warn]}\n") } -end - -# find all the files in the fragments directory, sort them numerically and concat to fragments.concat in the working dir -open('fragments.concat', 'a') do |f| - fragments = Dir.entries("fragments").sort - if settings[:sortarg] == '-n' - fragments = fragments.sort_by { |v| v.split('_').map(&:to_i) } - end - fragments.each { |entry| - if File.file?(File.join("fragments", entry)) - f << File.read(File.join("fragments", entry)) - - # append a newline if we were asked to (invoked with -l) - if settings[:newline] - f << "\n" - end - - end - } -end - -if !settings[:test] - # This is a real run, copy the file to outfile - FileUtils.cp 'fragments.concat', settings[:outfile] -else - # Just compare the result to outfile to help the exec decide - if FileUtils.cmp 'fragments.concat', settings[:outfile] - exit 0 - else - exit 1 - end -end diff --git a/concat/lib/facter/concat_basedir.rb b/concat/lib/facter/concat_basedir.rb deleted file mode 100644 index bfac07102..000000000 --- a/concat/lib/facter/concat_basedir.rb +++ /dev/null @@ -1,11 +0,0 @@ -# == Fact: concat_basedir -# -# A custom fact that sets the default location for fragments -# -# "${::vardir}/concat/" -# -Facter.add("concat_basedir") do - setcode do - File.join(Puppet[:vardir],"concat") - end -end diff --git a/concat/lib/puppet/parser/functions/concat_getparam.rb b/concat/lib/puppet/parser/functions/concat_getparam.rb deleted file mode 100644 index 1757bdc54..000000000 --- a/concat/lib/puppet/parser/functions/concat_getparam.rb +++ /dev/null @@ -1,35 +0,0 @@ -# Test whether a given class or definition is defined -require 'puppet/parser/functions' - -Puppet::Parser::Functions.newfunction(:concat_getparam, - :type => :rvalue, - :doc => <<-'ENDOFDOC' -Takes a resource reference and name of the parameter and -returns value of resource's parameter. - -*Examples:* - - define example_resource($param) { - } - - example_resource { "example_resource_instance": - param => "param_value" - } - - concat_getparam(Example_resource["example_resource_instance"], "param") - -Would return: param_value -ENDOFDOC -) do |vals| - reference, param = vals - raise(ArgumentError, 'Must specify a reference') unless reference - raise(ArgumentError, 'Must specify name of a parameter') unless param and param.instance_of? String - - return '' if param.empty? - - if resource = findresource(reference.to_s) - return resource[param] if resource[param] - end - - return '' -end diff --git a/concat/lib/puppet/parser/functions/concat_is_bool.rb b/concat/lib/puppet/parser/functions/concat_is_bool.rb deleted file mode 100644 index c2c2a9f2e..000000000 --- a/concat/lib/puppet/parser/functions/concat_is_bool.rb +++ /dev/null @@ -1,22 +0,0 @@ -# -# concat_is_bool.rb -# - -module Puppet::Parser::Functions - newfunction(:concat_is_bool, :type => :rvalue, :doc => <<-EOS -Returns true if the variable passed to this function is a boolean. - EOS - ) do |arguments| - - raise(Puppet::ParseError, "concat_is_bool(): Wrong number of arguments " + - "given (#{arguments.size} for 1)") if arguments.size != 1 - - type = arguments[0] - - result = type.is_a?(TrueClass) || type.is_a?(FalseClass) - - return result - end -end - -# vim: set ts=2 sw=2 et : diff --git a/concat/manifests/fragment.pp b/concat/manifests/fragment.pp index b6a2b0232..a3d42ef00 100644 --- a/concat/manifests/fragment.pp +++ b/concat/manifests/fragment.pp @@ -1,6 +1,6 @@ # == Define: concat::fragment # -# Puts a file fragment into a directory previous setup using concat +# Creates a file_fragment in the catalogue # # === Options: # @@ -13,114 +13,43 @@ # [*order*] # By default all files gets a 10_ prefix in the directory you can set it to # anything else using this to influence the order of the content in the file -# [*ensure*] -# Present/Absent or destination to a file to include another file -# [*mode*] -# Deprecated -# [*owner*] -# Deprecated -# [*group*] -# Deprecated -# [*backup*] -# Deprecated # define concat::fragment( $target, + $ensure = undef, $content = undef, $source = undef, $order = '10', - $ensure = undef, - $mode = undef, - $owner = undef, - $group = undef, - $backup = undef ) { validate_string($target) + + if $ensure != undef { + warning('The $ensure parameter to concat::fragment is deprecated and has no effect.') + } + validate_string($content) if !(is_string($source) or is_array($source)) { fail('$source is not a string or an Array.') } + if !(is_string($order) or is_integer($order)) { fail('$order is not a string or integer.') } elsif (is_string($order) and $order =~ /[:\n\/]/) { fail("Order cannot contain '/', ':', or '\n'.") } - if $mode { - warning('The $mode parameter to concat::fragment is deprecated and has no effect') - } - if $owner { - warning('The $owner parameter to concat::fragment is deprecated and has no effect') - } - if $group { - warning('The $group parameter to concat::fragment is deprecated and has no effect') - } - if $backup { - warning('The $backup parameter to concat::fragment is deprecated and has no effect') - } - if $ensure == undef { - $my_ensure = concat_getparam(Concat[$target], 'ensure') - } else { - if ! ($ensure in [ 'present', 'absent' ]) { - warning('Passing a value other than \'present\' or \'absent\' as the $ensure parameter to concat::fragment is deprecated. If you want to use the content of a file as a fragment please use the $source parameter.') - } - $my_ensure = $ensure - } - - include concat::setup - $safe_name = regsubst($name, '[/:\n]', '_', 'GM') - $safe_target_name = regsubst($target, '[/:\n]', '_', 'GM') - $concatdir = $concat::setup::concatdir - $fragdir = "${concatdir}/${safe_target_name}" - $fragowner = $concat::setup::fragment_owner - $fraggroup = $concat::setup::fragment_group - $fragmode = $concat::setup::fragment_mode - - # The file type's semantics are problematic in that ensure => present will - # not over write a pre-existing symlink. We are attempting to provide - # backwards compatiblity with previous concat::fragment versions that - # supported the file type's ensure => /target syntax - - # be paranoid and only allow the fragment's file resource's ensure param to - # be file, absent, or a file target - $safe_ensure = $my_ensure ? { - '' => 'file', - undef => 'file', - 'file' => 'file', - 'present' => 'file', - 'absent' => 'absent', - default => $my_ensure, - } - - # if it looks line ensure => /target syntax was used, fish that out - if ! ($my_ensure in ['', 'present', 'absent', 'file' ]) { - $ensure_target = $my_ensure - } else { - $ensure_target = undef - } - - # the file type's semantics only allows one of: ensure => /target, content, - # or source - if ($ensure_target and $source) or - ($ensure_target and $content) or - ($source and $content) { - fail('You cannot specify more than one of $content, $source, $ensure => /target') - } - - if ! ($content or $source or $ensure_target) { + if ! ($content or $source) { crit('No content, source or symlink specified') + } elsif ($content and $source) { + fail("Can't use 'source' and 'content' at the same time") } - file { "${fragdir}/fragments/${order}_${safe_name}": - ensure => $safe_ensure, - owner => $fragowner, - group => $fraggroup, - mode => $fragmode, - source => $source, + $safe_target_name = regsubst($target, '[/:\n\s\\]', '_', 'GM') + + file_fragment { $name: + tag => $safe_target_name, + order => $order, content => $content, - backup => false, - replace => true, - alias => "concat_fragment_${name}", - notify => Exec["concat_${target}"] + source => $source, } } diff --git a/concat/manifests/init.pp b/concat/manifests/init.pp index fa05a1004..69dc46efd 100644 --- a/concat/manifests/init.pp +++ b/concat/manifests/init.pp @@ -16,34 +16,21 @@ # Who will own the file # [*mode*] # The mode of the final file -# [*force*] -# Enables creating empty files if no fragments are present -# [*warn*] +# [*warn_header*] # Adds a normal shell style comment top of the file indicating that it is # built by puppet -# [*force*] # [*backup*] # Controls the filebucketing behavior of the final file and see File type # reference for its use. Defaults to 'puppet' # [*replace*] # Whether to replace a file that already exists on the local system # [*order*] -# [*ensure_newline*] -# [*gnu*] -# Deprecated +# Select whether to order associated fragments by 'alpha' or 'numeric'. +# Defaults to 'alpha'. # # === Actions: -# * Creates fragment directories if it didn't exist already -# * Executes the concatfragments.rb script to build the final file, this -# script will create directory/fragments.concat. Execution happens only -# when: -# * The directory changes -# * fragments.concat != final destination, this means rebuilds will happen -# whenever someone changes or deletes the final file. Checking is done -# using /usr/bin/cmp. -# * The Exec gets notified by something else - like the concat::fragment -# define -# * Copies the file over to the final destination using a file resource +# * Creates a file_concat resource from the electrical/puppet-lib-file_concat library. +# * Creates file_fragment resources from electrical/puppet-lib-file_concat # # === Aliases: # @@ -52,6 +39,7 @@ # * The final file can be referenced as File["/path/to/file"] or # File["concat_/path/to/file"] # + define concat( $ensure = 'present', $path = $name, @@ -59,13 +47,11 @@ $group = undef, $mode = '0644', $warn = false, - $force = false, + $force = undef, $backup = 'puppet', $replace = true, $order = 'alpha', - $ensure_newline = false, $validate_cmd = undef, - $gnu = undef ) { validate_re($ensure, '^present$|^absent$') validate_absolute_path($path) @@ -75,190 +61,63 @@ if ! (is_string($warn) or $warn == true or $warn == false) { fail('$warn is not a string or boolean') } - validate_bool($force) - if ! concat_is_bool($backup) and ! is_string($backup) { + if ! is_bool($backup) and ! is_string($backup) { fail('$backup must be string or bool!') } validate_bool($replace) validate_re($order, '^alpha$|^numeric$') - validate_bool($ensure_newline) if $validate_cmd and ! is_string($validate_cmd) { fail('$validate_cmd must be a string') } - if $gnu { - warning('The $gnu parameter to concat is deprecated and has no effect') - } - include concat::setup + if $force != undef { + warning('The $force parameter to concat is deprecated and has no effect.') + } - $safe_name = regsubst($name, '[/:]', '_', 'G') - $concatdir = $concat::setup::concatdir - $fragdir = "${concatdir}/${safe_name}" - $concat_name = 'fragments.concat.out' - $script_command = $concat::setup::script_command - $default_warn_message = '# This file is managed by Puppet. DO NOT EDIT.' - $bool_warn_message = 'Using stringified boolean values (\'true\', \'yes\', \'on\', \'false\', \'no\', \'off\') to represent boolean true/false as the $warn parameter to concat is deprecated and will be treated as the warning message in a future release' + $safe_name = regsubst($name, '[/:\n\s\\]', '_', 'G') + $default_warn_message = "# This file is managed by Puppet. DO NOT EDIT.\n" case $warn { true: { $warn_message = $default_warn_message - } - 'true', 'yes', 'on': { - warning($bool_warn_message) - $warn_message = $default_warn_message + $append_header = true } false: { $warn_message = '' } - 'false', 'no', 'off': { - warning($bool_warn_message) - $warn_message = '' - } default: { $warn_message = $warn + $append_header = true } } - $warnmsg_escaped = regsubst($warn_message, '\'', '\'\\\'\'', 'G') - $warnflag = $warnmsg_escaped ? { - '' => '', - default => "-w '${warnmsg_escaped}'" - } - - $forceflag = $force ? { - true => '-f', - false => '', - } - - $orderflag = $order ? { - 'numeric' => '-n', - 'alpha' => '', - } - - $newlineflag = $ensure_newline ? { - true => '-l', - false => '', - } - - File { - backup => false, - } - - # reset poisoned Exec defaults - Exec { - user => undef, - group => undef, - } - if $ensure == 'present' { - file { $fragdir: - ensure => directory, - mode => '0750', - } - - file { "${fragdir}/fragments": - ensure => directory, - mode => '0750', - force => true, - ignore => ['.svn', '.git', '.gitignore'], - notify => Exec["concat_${name}"], - purge => true, - recurse => true, - } - - file { "${fragdir}/fragments.concat": - ensure => present, - mode => '0640', - } - - file { "${fragdir}/${concat_name}": - ensure => present, - mode => '0640', - } - - file { $name: - ensure => present, + file_concat { $name: + tag => $safe_name, + path => $path, owner => $owner, group => $group, mode => $mode, replace => $replace, - path => $path, - alias => "concat_${name}", - source => "${fragdir}/${concat_name}", backup => $backup, + order => $order, + validate_cmd => $validate_cmd, } - # Only newer versions of puppet 3.x support the validate_cmd parameter - if $validate_cmd { - File[$name] { - validate_cmd => $validate_cmd, - } - } - - # remove extra whitespace from string interpolation to make testing easier - $command = strip(regsubst("${script_command} -o \"${fragdir}/${concat_name}\" -d \"${fragdir}\" ${warnflag} ${forceflag} ${orderflag} ${newlineflag}", '\s+', ' ', 'G')) - - # make sure ruby is in the path for PE - if defined('$is_pe') and $::is_pe { - if $::kernel == 'windows' { - $command_path = "${::env_windows_installdir}/bin:${::path}" - } else { - $command_path = "/opt/puppet/bin:${::path}" + if $append_header { + file_fragment { "#{$name}_header": + tag => $safe_name, + content => $warn_message, + order => '0', } - } else { - $command_path = $::path - } - - # if puppet is running as root, this exec should also run as root to allow - # the concatfragments.rb script to potentially be installed in path that - # may not be accessible by a target non-root owner. - exec { "concat_${name}": - alias => "concat_${fragdir}", - command => $command, - notify => File[$name], - subscribe => File[$fragdir], - unless => "${command} -t", - path => $command_path, - require => [ - File[$fragdir], - File["${fragdir}/fragments"], - File["${fragdir}/fragments.concat"], - ], } } else { - file { [ - $fragdir, - "${fragdir}/fragments", - "${fragdir}/fragments.concat", - "${fragdir}/${concat_name}" - ]: - ensure => absent, - force => true, - } - - file { $path: - ensure => absent, + file_concat { $name: + ensure => $ensure, + tag => $safe_name, + path => $path, backup => $backup, } - - $absent_exec_command = $::kernel ? { - 'windows' => 'cmd.exe /c exit 0', - default => 'true', - } - - $absent_exec_path = $::kernel ? { - 'windows' => $::path, - default => '/bin:/usr/bin', - } - - # Need to have an unless here for idempotency. - exec { "concat_${name}": - alias => "concat_${fragdir}", - command => $absent_exec_command, - unless => $absent_exec_command, - path => $absent_exec_path, - } } } -# vim:sw=2:ts=2:expandtab:textwidth=79 diff --git a/concat/manifests/setup.pp b/concat/manifests/setup.pp deleted file mode 100644 index 95cce4a16..000000000 --- a/concat/manifests/setup.pp +++ /dev/null @@ -1,65 +0,0 @@ -# === Class: concat::setup -# -# Sets up the concat system. This is a private class. -# -# [$concatdir] -# is where the fragments live and is set on the fact concat_basedir. -# Since puppet should always manage files in $concatdir and they should -# not be deleted ever, /tmp is not an option. -# -# It also copies out the concatfragments.{sh,rb} file to ${concatdir}/bin -# -class concat::setup { - if $caller_module_name != $module_name { - warning("${name} is deprecated as a public API of the ${module_name} module and should no longer be directly included in the manifest.") - } - - if $::concat_basedir { - $concatdir = $::concat_basedir - } else { - fail ('$concat_basedir not defined. Try running again with pluginsync=true on the [master] and/or [main] section of your node\'s \'/etc/puppet/puppet.conf\'.') - } - - # owner,group and mode of fragment files (on windows owner and access rights should - # be inherited from concatdir and not explicitly set to avoid problems) - $fragment_owner = $::osfamily ? { 'windows' => undef, default => $::id } - $fragment_mode = $::osfamily ? { 'windows' => undef, default => '0640' } - # test on gid fact availability to support older facter versions - if defined('$gid') and $::gid and $::osfamily != 'Windows' { - $fragment_group = $::gid - } else { - $fragment_group = undef - } - - $script_name = 'concatfragments.rb' - - $script_path = "${concatdir}/bin/${script_name}" - - $script_owner = $::osfamily ? { 'windows' => undef, default => $::id } - - $script_group = $script_owner ? { 'root' => '0', default => undef } - - $script_mode = $::osfamily ? { 'windows' => undef, default => '0755' } - - $script_command = $::osfamily? { - 'windows' => "ruby.exe '${script_path}'", - default => $script_path - } - - File { - backup => false, - } - - file { $script_path: - ensure => file, - owner => $script_owner, - group => $script_group, - mode => $script_mode, - source => "puppet:///modules/concat/${script_name}", - } - - file { [ $concatdir, "${concatdir}/bin" ]: - ensure => directory, - mode => '0755', - } -} diff --git a/concat/metadata.json b/concat/metadata.json index 9d7a46dd0..137499e92 100644 --- a/concat/metadata.json +++ b/concat/metadata.json @@ -1,6 +1,6 @@ { "name": "puppetlabs-concat", - "version": "1.2.0", + "version": "2.0.0", "author": "Puppet Labs", "summary": "Construct files from multiple fragments.", "license": "Apache-2.0", @@ -105,6 +105,7 @@ } ], "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":">= 3.2.0 < 5.0.0"} + {"name":"puppetlabs/stdlib","version_requirement":">= 3.2.0 < 5.0.0"}, + {"name":"electrical/file_concat","version_requirement":">= 1.0.1"} ] } diff --git a/concat/spec/acceptance/backup_spec.rb b/concat/spec/acceptance/backup_spec.rb index 1d3a5dfe3..0a737a556 100644 --- a/concat/spec/acceptance/backup_spec.rb +++ b/concat/spec/acceptance/backup_spec.rb @@ -26,7 +26,7 @@ it 'applies the manifest twice with "Filebucketed" stdout and no stderr' do apply_manifest(pp, :catch_failures => true) do |r| - expect(r.stdout).to match(/Filebucketed #{basedir}\/file to puppet with sum 0140c31db86293a1a1e080ce9b91305f/) # sum is for file contents of 'old contents' + expect(r.stdout).to match(/Filebucketed #{basedir}\/file to puppet with sum 0140c31db86293a1a1e080ce9b91305f/) end apply_manifest(pp, :catch_changes => true) end diff --git a/concat/spec/acceptance/concat_spec.rb b/concat/spec/acceptance/concat_spec.rb index c5c972774..c281954b7 100644 --- a/concat/spec/acceptance/concat_spec.rb +++ b/concat/spec/acceptance/concat_spec.rb @@ -38,56 +38,6 @@ apply_manifest(pp, :catch_failures => true) apply_manifest(pp, :catch_changes => true) end - - describe file("#{vardir}/concat") do - it { should be_directory } - it { should be_owned_by username } - it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) { - should be_mode 755 - } - end - describe file("#{vardir}/concat/bin") do - it { should be_directory } - it { should be_owned_by username } - it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) { - should be_mode 755 - } - end - describe file("#{vardir}/concat/bin/#{scriptname}") do - it { should be_file } - it { should be_owned_by username } - it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) { - should be_mode 755 - } - end - describe file("#{vardir}/concat/#{safe_basedir}_file") do - it { should be_directory } - it { should be_owned_by username } - it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) { - should be_mode 750 - } - end - describe file("#{vardir}/concat/#{safe_basedir}_file/fragments") do - it { should be_directory } - it { should be_owned_by username } - it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) { - should be_mode 750 - } - end - describe file("#{vardir}/concat/#{safe_basedir}_file/fragments.concat") do - it { should be_file } - it { should be_owned_by username } - it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) { - should be_mode 640 - } - end - describe file("#{vardir}/concat/#{safe_basedir}_file/fragments.concat.out") do - it { should be_file } - it { should be_owned_by username } - it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) { - should be_mode 640 - } - end end context 'owner/group root' do @@ -133,20 +83,6 @@ should match '2' } end - describe file("#{vardir}/concat/#{safe_basedir}_file/fragments/01_1") do - it { should be_file } - it { should be_owned_by username } - it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) { - should be_mode 640 - } - end - describe file("#{vardir}/concat/#{safe_basedir}_file/fragments/02_2") do - it { should be_file } - it { should be_owned_by username } - it("should be mode", :unless => (fact('osfamily') == 'AIX' or fact('osfamily') == 'windows')) { - should be_mode 640 - } - end end context 'ensure' do diff --git a/concat/spec/acceptance/deprecation_warnings_spec.rb b/concat/spec/acceptance/deprecation_warnings_spec.rb index 11133ea9f..8a689a76b 100644 --- a/concat/spec/acceptance/deprecation_warnings_spec.rb +++ b/concat/spec/acceptance/deprecation_warnings_spec.rb @@ -10,229 +10,35 @@ end end - context 'concat gnu parameter' do + context 'concat force parameter' do pp = <<-EOS concat { '#{basedir}/file': - gnu => 'foo', + force => false, } concat::fragment { 'foo': target => '#{basedir}/file', content => 'bar', } EOS - w = 'The $gnu parameter to concat is deprecated and has no effect' + w = 'The $force parameter to concat is deprecated and has no effect.' it_behaves_like 'has_warning', pp, w end - context 'concat warn parameter =>' do - ['true', 'yes', 'on'].each do |warn| - context warn do - pp = <<-EOS - concat { '#{basedir}/file': - warn => '#{warn}', - } - concat::fragment { 'foo': - target => '#{basedir}/file', - content => 'bar', - } - EOS - w = 'Using stringified boolean values (\'true\', \'yes\', \'on\', \'false\', \'no\', \'off\') to represent boolean true/false as the $warn parameter to concat is deprecated and will be treated as the warning message in a future release' - - it_behaves_like 'has_warning', pp, w - - describe file("#{basedir}/file") do - it { should be_file } - its(:content) { - should match '# This file is managed by Puppet. DO NOT EDIT.' - should match 'bar' - } - end - end - end - - ['false', 'no', 'off'].each do |warn| - context warn do - pp = <<-EOS - concat { '#{basedir}/file': - warn => '#{warn}', - } - concat::fragment { 'foo': - target => '#{basedir}/file', - content => 'bar', - } - EOS - w = 'Using stringified boolean values (\'true\', \'yes\', \'on\', \'false\', \'no\', \'off\') to represent boolean true/false as the $warn parameter to concat is deprecated and will be treated as the warning message in a future release' - - it_behaves_like 'has_warning', pp, w - - describe file("#{basedir}/file") do - it { should be_file } - its(:content) { - should_not match '# This file is managed by Puppet. DO NOT EDIT.' - should match 'bar' - } - end - end - end - end - - context 'concat::fragment ensure parameter', :unless => fact('osfamily') == 'windows' do + context 'concat::fragment ensure parameter' do context 'target file exists' do - before(:all) do - pp = <<-EOS - file { '#{basedir}': - ensure => directory, - } - file { '#{basedir}/file1': - content => "file1 contents\n", - } - EOS - apply_manifest(pp) - end - - pp = <<-EOS - concat { '#{basedir}/file': } - concat::fragment { 'foo': - target => '#{basedir}/file', - ensure => '#{basedir}/file1', - } - EOS - w = 'Passing a value other than \'present\' or \'absent\' as the $ensure parameter to concat::fragment is deprecated. If you want to use the content of a file as a fragment please use the $source parameter.' - - it_behaves_like 'has_warning', pp, w - - describe file("#{basedir}/file") do - it { should be_file } - its(:content) { should match 'file1 contents' } - end - - describe 'the fragment can be changed from a symlink to a plain file', :unless => (fact("osfamily") == "windows") do - pp = <<-EOS - concat { '#{basedir}/file': } - concat::fragment { 'foo': - target => '#{basedir}/file', - content => 'new content', - } - EOS - - it 'applies the manifest twice with no stderr' do - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - end - - describe file("#{basedir}/file") do - it { should be_file } - its(:content) { - should match 'new content' - should_not match 'file1 contents' - } - end - end - end # target file exists - - context 'target does not exist', :unless => fact('osfamily') == 'windows' do - pp = <<-EOS - concat { '#{basedir}/file': } - concat::fragment { 'foo': - target => '#{basedir}/file', - ensure => '#{basedir}/file1', - } - EOS - w = 'Passing a value other than \'present\' or \'absent\' as the $ensure parameter to concat::fragment is deprecated. If you want to use the content of a file as a fragment please use the $source parameter.' - - it_behaves_like 'has_warning', pp, w - - describe file("#{basedir}/file") do - it { should be_file } - end - - describe 'the fragment can be changed from a symlink to a plain file', :unless => (fact('osfamily') == 'windows') do - pp = <<-EOS - concat { '#{basedir}/file': } - concat::fragment { 'foo': - target => '#{basedir}/file', - content => 'new content', - } - EOS - - it 'applies the manifest twice with no stderr' do - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - end - - describe file("#{basedir}/file") do - it { should be_file } - its(:content) { should match 'new content' } - end - end - end # target file exists - - end # concat::fragment ensure parameter - - context 'concat::fragment mode parameter' do pp = <<-EOS - concat { '#{basedir}/file': } - concat::fragment { 'foo': - target => '#{basedir}/file', - content => 'bar', - mode => 'bar', - } - EOS - w = 'The $mode parameter to concat::fragment is deprecated and has no effect' - - it_behaves_like 'has_warning', pp, w - end - - context 'concat::fragment owner parameter' do - pp = <<-EOS - concat { '#{basedir}/file': } - concat::fragment { 'foo': - target => '#{basedir}/file', - content => 'bar', - owner => 'bar', - } - EOS - w = 'The $owner parameter to concat::fragment is deprecated and has no effect' - - it_behaves_like 'has_warning', pp, w - end - - context 'concat::fragment group parameter' do - pp = <<-EOS - concat { '#{basedir}/file': } - concat::fragment { 'foo': - target => '#{basedir}/file', - content => 'bar', - group => 'bar', + concat { '#{basedir}/file': } - EOS - w = 'The $group parameter to concat::fragment is deprecated and has no effect' - - it_behaves_like 'has_warning', pp, w - end - - context 'concat::fragment backup parameter' do - pp = <<-EOS - concat { '#{basedir}/file': } concat::fragment { 'foo': target => '#{basedir}/file', + ensure => false, content => 'bar', - backup => 'bar', } EOS - w = 'The $backup parameter to concat::fragment is deprecated and has no effect' - - it_behaves_like 'has_warning', pp, w - end - - context 'include concat::setup' do - pp = <<-EOS - include concat::setup - EOS - w = 'concat::setup is deprecated as a public API of the concat module and should no longer be directly included in the manifest.' + w = 'The $ensure parameter to concat::fragment is deprecated and has no effect.' it_behaves_like 'has_warning', pp, w + end end - end diff --git a/concat/spec/acceptance/empty_spec.rb b/concat/spec/acceptance/empty_spec.rb deleted file mode 100644 index 4ab6e1e60..000000000 --- a/concat/spec/acceptance/empty_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'spec_helper_acceptance' - -describe 'concat force empty parameter' do - basedir = default.tmpdir('concat') - context 'should run successfully' do - pp = <<-EOS - concat { '#{basedir}/file': - mode => '0644', - force => true, - } - EOS - - it 'applies the manifest twice with no stderr' do - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - end - - describe file("#{basedir}/file") do - it { should be_file } - its(:content) { should_not match /1\n2/ } - end - end -end diff --git a/concat/spec/acceptance/fragment_source_spec.rb b/concat/spec/acceptance/fragment_source_spec.rb index a174e02b4..5d66e4d98 100644 --- a/concat/spec/acceptance/fragment_source_spec.rb +++ b/concat/spec/acceptance/fragment_source_spec.rb @@ -145,7 +145,7 @@ EOS it 'applies the manifest with resource failures' do - apply_manifest(pp, :expect_failures => true) + expect(apply_manifest(pp, :catch_failures => true).stderr).to match(/Failed to generate additional resources using 'eval_generate'/) end describe file("#{basedir}/fail_no_source") do #FIXME: Serverspec::Type::File doesn't support exists? for some reason. so... hack. diff --git a/concat/spec/acceptance/newline_spec.rb b/concat/spec/acceptance/newline_spec.rb deleted file mode 100644 index c1fa16a10..000000000 --- a/concat/spec/acceptance/newline_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -require 'spec_helper_acceptance' - -describe 'concat ensure_newline parameter' do - basedir = default.tmpdir('concat') - context '=> false' do - before(:all) do - pp = <<-EOS - file { '#{basedir}': - ensure => directory - } - EOS - - apply_manifest(pp) - end - pp = <<-EOS - concat { '#{basedir}/file': - ensure_newline => false, - } - concat::fragment { '1': - target => '#{basedir}/file', - content => '1', - } - concat::fragment { '2': - target => '#{basedir}/file', - content => '2', - } - EOS - - it 'applies the manifest twice with no stderr' do - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - end - - describe file("#{basedir}/file") do - it { should be_file } - its(:content) { should match '12' } - end - end - - context '=> true' do - pp = <<-EOS - concat { '#{basedir}/file': - ensure_newline => true, - } - concat::fragment { '1': - target => '#{basedir}/file', - content => '1', - } - concat::fragment { '2': - target => '#{basedir}/file', - content => '2', - } - EOS - - it 'applies the manifest twice with no stderr' do - apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) - end - - describe file("#{basedir}/file") do - it { should be_file } - its(:content) { - should match /1\n2\n/ - } - end - end -end diff --git a/concat/spec/acceptance/nodesets/default.yml b/concat/spec/acceptance/nodesets/default.yml index 063983549..4e2cb809e 100644 --- a/concat/spec/acceptance/nodesets/default.yml +++ b/concat/spec/acceptance/nodesets/default.yml @@ -1,10 +1,10 @@ HOSTS: - centos-64-x64: + centos-65-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 : centos-65-x64-vbox436-nocm + box_url : http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box hypervisor : vagrant CONFIG: - type: git + type: foss diff --git a/concat/spec/acceptance/order_spec.rb b/concat/spec/acceptance/order_spec.rb index c158dd880..b746b1c9c 100644 --- a/concat/spec/acceptance/order_spec.rb +++ b/concat/spec/acceptance/order_spec.rb @@ -37,7 +37,7 @@ end describe 'alpha' do - it_behaves_like 'sortby', 'alpha', /string10string1string2/ + it_behaves_like 'sortby', 'alpha', /string1string10string2/ end describe 'numeric' do @@ -83,7 +83,7 @@ end end describe 'alpha' do - it_should_behave_like 'order_by', 'alpha', /string2string1string3/ + it_should_behave_like 'order_by', 'alpha', /string3string2string1/ end describe 'numeric' do it_should_behave_like 'order_by', 'numeric', /string3string2string1/ diff --git a/concat/spec/acceptance/replace_spec.rb b/concat/spec/acceptance/replace_spec.rb index bd597ed19..68d7383fe 100644 --- a/concat/spec/acceptance/replace_spec.rb +++ b/concat/spec/acceptance/replace_spec.rb @@ -226,7 +226,7 @@ end end - # XXX concat's force param currently enables the creation of empty files + # XXX # when there are no fragments, and the replace param will only replace # files and symlinks, not directories. The semantics either need to be # changed, extended, or a new param introduced to control directory @@ -234,7 +234,6 @@ context 'should succeed', :pending => 'not yet implemented' do pp = <<-EOS concat { '#{basedir}/file': - force => true, } concat::fragment { '1': diff --git a/concat/spec/acceptance/warn_spec.rb b/concat/spec/acceptance/warn_header_spec.rb similarity index 98% rename from concat/spec/acceptance/warn_spec.rb rename to concat/spec/acceptance/warn_header_spec.rb index 2788607c8..b73414e34 100644 --- a/concat/spec/acceptance/warn_spec.rb +++ b/concat/spec/acceptance/warn_header_spec.rb @@ -71,7 +71,7 @@ context '# foo should overide default warning message' do pp = <<-EOS concat { '#{basedir}/file': - warn => '# foo', + warn => "# foo\n", } concat::fragment { '1': diff --git a/concat/spec/spec_helper_acceptance.rb b/concat/spec/spec_helper_acceptance.rb index da994f8df..56c6ea767 100644 --- a/concat/spec/spec_helper_acceptance.rb +++ b/concat/spec/spec_helper_acceptance.rb @@ -16,21 +16,29 @@ hosts.each do |host| on hosts, "mkdir -p #{host['distmoduledir']}" if host['platform'] =~ /sles-1/i || host['platform'] =~ /solaris-1/i - get_stdlib = <<-EOS + get_deps = <<-EOS package{'wget':} - exec{'download': + exec{'download-stdlib': command => "wget -P /root/ https://forgeapi.puppetlabs.com/v3/files/puppetlabs-stdlib-4.5.1.tar.gz --no-check-certificate", path => ['/opt/csw/bin/','/usr/bin/'] } + exec{'download-file_concat': + command => "wget -P /root/ https://forgeapi.puppetlabs.com/v3/files/electrical-file_concat-1.0.1.tar.gz --no-check-certificate", + path => ['/opt/csw/bin/','/usr/bin/'] + } EOS - apply_manifest_on(host, get_stdlib) + apply_manifest_on(host, get_deps) # have to use force otherwise it checks ssl cert even though it is a local file on host, puppet('module install /root/puppetlabs-stdlib-4.5.1.tar.gz --force --ignore-dependencies'), {:acceptable_exit_codes => [0, 1]} + on host, puppet('module install /root/electrical-file_concat-1.0.1.tar.gz --force --ignore-dependencies'), {:acceptable_exit_codes => [0, 1]} elsif host['platform'] =~ /windows/i on host, shell('curl -k -o c:/puppetlabs-stdlib-4.5.1.tar.gz https://forgeapi.puppetlabs.com/v3/files/puppetlabs-stdlib-4.5.1.tar.gz') on host, puppet('module install c:/puppetlabs-stdlib-4.5.1.tar.gz --force --ignore-dependencies'), {:acceptable_exit_codes => [0, 1]} + on host, shell('curl -k -o c:/electrical-file_concat-1.0.1.tar.gz https://forgeapi.puppetlabs.com/v3/files/electrical-file_concat-1.0.1.tar.gz') + on host, puppet('module install c:/electrical-file_concat-1.0.1.tar.gz --force --ignore-dependencies'), {:acceptable_exit_codes => [0, 1]} else on host, puppet('module install puppetlabs-stdlib'), {:acceptable_exit_codes => [0, 1]} + on host, puppet('module install electrical-file_concat'), {:acceptable_exit_codes => [0, 1]} end end end diff --git a/concat/spec/unit/classes/concat_setup_spec.rb b/concat/spec/unit/classes/concat_setup_spec.rb deleted file mode 100644 index e97a29caa..000000000 --- a/concat/spec/unit/classes/concat_setup_spec.rb +++ /dev/null @@ -1,96 +0,0 @@ -require 'spec_helper' - -describe 'concat::setup', :type => :class do - - shared_examples 'setup' do |concatdir| - concatdir = '/foo' if concatdir.nil? - - let(:facts) do - { - :concat_basedir => concatdir, - :caller_module_name => 'Test', - :osfamily => 'Debian', - :id => 'root', - :is_pe => false, - } - end - - it do - should contain_file("#{concatdir}/bin/concatfragments.rb").with({ - :mode => '0755', - :source => 'puppet:///modules/concat/concatfragments.rb', - :backup => false, - }) - end - - [concatdir, "#{concatdir}/bin"].each do |file| - it do - should contain_file(file).with({ - :ensure => 'directory', - :mode => '0755', - :backup => false, - }) - end - end - end - - context 'facts' do - context 'concat_basedir =>' do - context '/foo' do - it_behaves_like 'setup', '/foo' - end - end - end # facts - - context 'deprecated as a public class' do - it 'should create a warning' do - skip('rspec-puppet support for testing warning()') - end - end - - context "on osfamily Solaris" do - concatdir = '/foo' - let(:facts) do - { - :concat_basedir => concatdir, - :caller_module_name => 'Test', - :osfamily => 'Solaris', - :id => 'root', - :is_pe => false, - } - end - - it do - should contain_file("#{concatdir}/bin/concatfragments.rb").with({ - :ensure => 'file', - :owner => 'root', - :mode => '0755', - :source => 'puppet:///modules/concat/concatfragments.rb', - :backup => false, - }) - end - end # on osfamily Solaris - - context "on osfamily windows" do - concatdir = '/foo' - let(:facts) do - { - :concat_basedir => concatdir, - :caller_module_name => 'Test', - :osfamily => 'windows', - :id => 'batman', - :is_pe => false, - } - end - - it do - should contain_file("#{concatdir}/bin/concatfragments.rb").with({ - :ensure => 'file', - :owner => nil, - :mode => nil, - :source => 'puppet:///modules/concat/concatfragments.rb', - :backup => false, - }) - end - end # on osfamily windows -end diff --git a/concat/spec/unit/defines/concat_fragment_spec.rb b/concat/spec/unit/defines/concat_fragment_spec.rb index 1dc7c38f4..98be58a18 100644 --- a/concat/spec/unit/defines/concat_fragment_spec.rb +++ b/concat/spec/unit/defines/concat_fragment_spec.rb @@ -9,50 +9,21 @@ :content => nil, :source => nil, :order => 10, - :ensure => 'present', }.merge(params) - safe_name = title.gsub(/[\/\n]/, '_') - safe_target_name = p[:target].gsub(/[\/\n]/, '_') - concatdir = '/var/lib/puppet/concat' - fragdir = "#{concatdir}/#{safe_target_name}" id = 'root' gid = 'root' - if p[:ensure] == 'absent' - safe_ensure = p[:ensure] - else - safe_ensure = 'file' - end let(:title) { title } - let(:facts) do - { - :concat_basedir => concatdir, - :id => id, - :gid => gid, - :osfamily => 'Debian', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - :is_pe => false, - } - end let(:params) { params } let(:pre_condition) do "concat{ '#{p[:target]}': }" end it do - should contain_class('concat::setup') should contain_concat(p[:target]) - should contain_file("#{fragdir}/fragments/#{p[:order]}_#{safe_name}").with({ - :ensure => safe_ensure, - :owner => id, - :group => gid, - :mode => '0640', - :source => p[:source], - :content => p[:content], - :alias => "concat_fragment_#{title}", - :backup => false, - }) + should contain_file_concat(p[:target]) + should contain_file_fragment(title) end end @@ -60,6 +31,7 @@ ['0', '1', 'a', 'z'].each do |title| it_behaves_like 'fragment', title, { :target => '/etc/motd', + :content => "content for #{title}" } end end # title @@ -69,42 +41,21 @@ context target do it_behaves_like 'fragment', target, { :target => '/etc/motd', + :content => "content for #{target}" } end end context 'false' do let(:title) { 'motd_header' } - let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }} let(:params) {{ :target => false }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not a string/) + expect { catalogue }.to raise_error(Puppet::Error, /is not a string/) end end end # target => - context 'ensure =>' do - ['present', 'absent'].each do |ens| - context ens do - it_behaves_like 'fragment', 'motd_header', { - :ensure => ens, - :target => '/etc/motd', - } - end - end - - context 'any value other than \'present\' or \'absent\'' do - let(:title) { 'motd_header' } - let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }} - let(:params) {{ :ensure => 'invalid', :target => '/etc/motd' }} - - it 'should create a warning' do - skip('rspec-puppet support for testing warning()') - end - end - end # ensure => - context 'content =>' do ['', 'ashp is our hero'].each do |content| context content do @@ -117,11 +68,10 @@ context 'false' do let(:title) { 'motd_header' } - let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }} let(:params) {{ :content => false, :target => '/etc/motd' }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not a string/) + expect { catalogue }.to raise_error(Puppet::Error, /is not a string/) end end end # content => @@ -138,193 +88,28 @@ context 'false' do let(:title) { 'motd_header' } - let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }} let(:params) {{ :source => false, :target => '/etc/motd' }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not a string or an Array/) + expect { catalogue }.to raise_error(Puppet::Error, /is not a string or an Array/) end end end # source => - context 'order =>' do - ['', '42', 'a', 'z'].each do |order| - context '\'\'' do - it_behaves_like 'fragment', 'motd_header', { - :order => order, - :target => '/etc/motd', - } - end - end - - context 'false' do - let(:title) { 'motd_header' } - let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }} - let(:params) {{ :order => false, :target => '/etc/motd' }} - - it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not a string or integer/) - end - end - - context '123:456' do - let(:title) { 'motd_header' } - let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }} - let(:params) {{ :order => '123:456', :target => '/etc/motd' }} - - it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /cannot contain/) - end - end - context '123/456' do - let(:title) { 'motd_header' } - let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }} - let(:params) {{ :order => '123/456', :target => '/etc/motd' }} - - it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /cannot contain/) - end - end - context '123\n456' do - let(:title) { 'motd_header' } - let(:facts) {{ :concat_basedir => '/tmp', :is_pe => false }} - let(:params) {{ :order => "123\n456", :target => '/etc/motd' }} - - it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /cannot contain/) - end - end - end # order => - context 'more than one content source' do - error_msg = 'You cannot specify more than one of $content, $source, $ensure => /target' - - context 'ensure => target and source' do - let(:title) { 'motd_header' } - let(:facts) do - { - :concat_basedir => '/tmp', - :osfamily => 'Debian', - :id => 'root', - :is_pe => false, - :gid => 'root', - } - end - let(:params) do - { - :target => '/etc/motd', - :ensure => '/foo', - :source => '/bar', - } - end - - it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /#{Regexp.escape(error_msg)}/m) - end - end - - context 'ensure => target and content' do - let(:title) { 'motd_header' } - let(:facts) do - { - :concat_basedir => '/tmp', - :osfamily => 'Debian', - :id => 'root', - :is_pe => false, - :gid => 'root', - } - end - let(:params) do - { - :target => '/etc/motd', - :ensure => '/foo', - :content => 'bar', - } - end - - it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /#{Regexp.escape(error_msg)}/m) - end - end - context 'source and content' do let(:title) { 'motd_header' } - let(:facts) do - { - :concat_basedir => '/tmp', - :osfamily => 'Debian', - :id => 'root', - :is_pe => false, - :gid => 'root', - } - end let(:params) do { - :target => '/etc/motd', + :target => '/etc/motd', :source => '/foo', :content => 'bar', } end it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /#{Regexp.escape(error_msg)}/m) + expect { catalogue }.to raise_error(Puppet::Error, /Can't use 'source' and 'content' at the same time/) end end - end # more than one content source - - describe 'deprecated parameter' do - context 'mode =>' do - context '1755' do - it_behaves_like 'fragment', 'motd_header', { - :mode => '1755', - :target => '/etc/motd', - } - - it 'should create a warning' do - skip('rspec-puppet support for testing warning()') - end - end - end # mode => - - context 'owner =>' do - context 'apenny' do - it_behaves_like 'fragment', 'motd_header', { - :owner => 'apenny', - :target => '/etc/motd', - } - - it 'should create a warning' do - skip('rspec-puppet support for testing warning()') - end - end - end # owner => - - context 'group =>' do - context 'apenny' do - it_behaves_like 'fragment', 'motd_header', { - :group => 'apenny', - :target => '/etc/motd', - } - - it 'should create a warning' do - skip('rspec-puppet support for testing warning()') - end - end - end # group => - - context 'backup =>' do - context 'foo' do - it_behaves_like 'fragment', 'motd_header', { - :backup => 'foo', - :target => '/etc/motd', - } - - it 'should create a warning' do - skip('rspec-puppet support for testing warning()') - end - end - end # backup => - end # deprecated params - end diff --git a/concat/spec/unit/defines/concat_spec.rb b/concat/spec/unit/defines/concat_spec.rb index a748f9607..35767aea6 100644 --- a/concat/spec/unit/defines/concat_spec.rb +++ b/concat/spec/unit/defines/concat_spec.rb @@ -14,29 +14,22 @@ :group => nil, :mode => '0644', :warn => false, - :force => false, :backup => 'puppet', :replace => true, - :order => 'alpha', - :ensure_newline => false, - :validate_cmd => nil, }.merge(params) safe_name = title.gsub('/', '_') - concatdir = '/var/lib/puppet/concat' - fragdir = "#{concatdir}/#{safe_name}" concat_name = 'fragments.concat.out' - default_warn_message = '# This file is managed by Puppet. DO NOT EDIT.' + default_warn_message = "# This file is managed by Puppet. DO NOT EDIT.\n" file_defaults = { - :backup => false, + :backup => p[:backup], } let(:title) { title } let(:params) { params } let(:facts) do { - :concat_basedir => concatdir, :id => id, :osfamily => 'Debian', :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', @@ -47,118 +40,23 @@ if p[:ensure] == 'present' it do - should contain_file(fragdir).with(file_defaults.merge({ - :ensure => 'directory', - :mode => '0750', - })) - end - - it do - should contain_file("#{fragdir}/fragments").with(file_defaults.merge({ - :ensure => 'directory', - :mode => '0750', - :force => true, - :ignore => ['.svn', '.git', '.gitignore'], - :purge => true, - :recurse => true, - })) - end - - [ - "#{fragdir}/fragments.concat", - "#{fragdir}/#{concat_name}", - ].each do |file| - it do - should contain_file(file).with(file_defaults.merge({ - :ensure => 'present', - :mode => '0640', - })) - end - end - - it do - should contain_file(title).with(file_defaults.merge({ + should contain_concat(title).with(file_defaults.merge({ :ensure => 'present', :owner => p[:owner], :group => p[:group], :mode => p[:mode], - :replace => p[:replace], :path => p[:path], - :alias => "concat_#{title}", - :source => "#{fragdir}/#{concat_name}", - :validate_cmd => p[:validate_cmd], :backup => p[:backup], + :replace => p[:replace], })) end - - cmd = "#{concatdir}/bin/concatfragments.rb " + - "-o \"#{concatdir}/#{safe_name}/fragments.concat.out\" " + - "-d \"#{concatdir}/#{safe_name}\"" - - # flag order: fragdir, warnflag, forceflag, orderflag, newlineflag - if p.has_key?(:warn) - case p[:warn] - when TrueClass - message = default_warn_message - when 'true', 'yes', 'on' - # should generate a stringified boolean warning - message = default_warn_message - when FalseClass - message = nil - when 'false', 'no', 'off' - # should generate a stringified boolean warning - message = nil - else - message = p[:warn] - end - - unless message.nil? - cmd += " -w \'#{message}\'" - end - end - - cmd += " -f" if p[:force] - cmd += " -n" if p[:order] == 'numeric' - cmd += " -l" if p[:ensure_newline] == true - - it do - should contain_exec("concat_#{title}").with({ - :alias => "concat_#{fragdir}", - :command => cmd, - :unless => "#{cmd} -t", - }) - end else - [ - fragdir, - "#{fragdir}/fragments", - "#{fragdir}/fragments.concat", - "#{fragdir}/#{concat_name}", - ].each do |file| - it do - should contain_file(file).with(file_defaults.merge({ - :ensure => 'absent', - :backup => false, - :force => true, - })) - end - end - it do - should contain_file(title).with(file_defaults.merge({ + should contain_concat(title).with(file_defaults.merge({ :ensure => 'absent', :backup => p[:backup], })) end - - it do - should contain_exec("concat_#{title}").with({ - :alias => "concat_#{fragdir}", - :command => 'true', - :unless => 'true', - :path => '/bin:/usr/bin', - }) - end end end @@ -176,14 +74,14 @@ context title do let(:title) { title } it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not an absolute path/) + expect { catalogue }.to raise_error(Puppet::Error, /is not an absolute path/) end end end end context 'with path param' do - ['./foo', 'foo', 'foo/bar'].each do |title| + ['/foo', 'foo', 'foo/bar'].each do |title| context title do it_behaves_like 'concat', title, { :path => '/etc/foo.bar' } end @@ -206,7 +104,7 @@ let(:title) { '/etc/foo.bar' } let(:params) {{ :ensure => 'invalid' }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /#{Regexp.escape('does not match "^present$|^absent$"')}/) + expect { catalogue }.to raise_error(Puppet::Error, /#{Regexp.escape('does not match "^present$|^absent$"')}/) end end end # ensure => @@ -221,7 +119,7 @@ let(:title) { '/etc/foo.bar' } let(:params) {{ :path => path }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not an absolute path/) + expect { catalogue }.to raise_error(Puppet::Error, /is not an absolute path/) end end end @@ -236,7 +134,7 @@ let(:title) { '/etc/foo.bar' } let(:params) {{ :owner => false }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not a string/) + expect { catalogue }.to raise_error(Puppet::Error, /is not a string/) end end end # owner => @@ -250,7 +148,7 @@ let(:title) { '/etc/foo.bar' } let(:params) {{ :group => false }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not a string/) + expect { catalogue }.to raise_error(Puppet::Error, /is not a string/) end end end # group => @@ -264,7 +162,7 @@ let(:title) { '/etc/foo.bar' } let(:params) {{ :mode => false }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not a string/) + expect { catalogue }.to raise_error(Puppet::Error, /is not a string/) end end end # mode => @@ -292,27 +190,11 @@ let(:title) { '/etc/foo.bar' } let(:params) {{ :warn => 123 }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not a string or boolean/) + expect { catalogue }.to raise_error(Puppet::Error, /is not a string or boolean/) end end end # warn => - context 'force =>' do - [true, false].each do |force| - context force do - it_behaves_like 'concat', '/etc/foo.bar', { :force => force } - end - end - - context '123' do - let(:title) { '/etc/foo.bar' } - let(:params) {{ :force => 123 }} - it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not a boolean/) - end - end - end # force => - context 'backup =>' do context 'reverse' do it_behaves_like 'concat', '/etc/foo.bar', { :backup => 'reverse' } @@ -330,7 +212,7 @@ let(:title) { '/etc/foo.bar' } let(:params) {{ :backup => [] }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /backup must be string or bool/) + expect { catalogue }.to raise_error(Puppet::Error, /backup must be string or bool/) end end end # backup => @@ -346,7 +228,7 @@ let(:title) { '/etc/foo.bar' } let(:params) {{ :replace => 123 }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not a boolean/) + expect { catalogue }.to raise_error(Puppet::Error, /is not a boolean/) end end end # replace => @@ -362,55 +244,8 @@ let(:title) { '/etc/foo.bar' } let(:params) {{ :order => 'invalid' }} it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /#{Regexp.escape('does not match "^alpha$|^numeric$"')}/) + expect { catalogue }.to raise_error(Puppet::Error, /#{Regexp.escape('does not match "^alpha$|^numeric$"')}/) end end end # order => - - context 'ensure_newline =>' do - [true, false].each do |ensure_newline| - context 'true' do - it_behaves_like 'concat', '/etc/foo.bar', { :ensure_newline => ensure_newline} - end - end - - context '123' do - let(:title) { '/etc/foo.bar' } - let(:params) {{ :ensure_newline => 123 }} - it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /is not a boolean/) - end - end - end # ensure_newline => - - context 'validate_cmd =>' do - context '/usr/bin/test -e %' do - it_behaves_like 'concat', '/etc/foo.bar', { :validate_cmd => '/usr/bin/test -e %' } - end - - [ 1234, true ].each do |cmd| - context cmd do - let(:title) { '/etc/foo.bar' } - let(:params) {{ :validate_cmd => cmd }} - it 'should fail' do - expect { should }.to raise_error(Puppet::Error, /\$validate_cmd must be a string/) - end - end - end - end # validate_cmd => - - describe 'deprecated parameter' do - context 'gnu =>' do - context 'foo' do - it_behaves_like 'concat', '/etc/foo.bar', { :gnu => 'foo'} - - it 'should create a warning' do - skip('rspec-puppet support for testing warning()') - end - end - end - end - end - -# vim:sw=2:ts=2:expandtab:textwidth=79 diff --git a/concat/spec/unit/facts/concat_basedir_spec.rb b/concat/spec/unit/facts/concat_basedir_spec.rb deleted file mode 100644 index 41bc90f15..000000000 --- a/concat/spec/unit/facts/concat_basedir_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'spec_helper' - -describe 'concat_basedir', :type => :fact do - before(:each) { Facter.clear } - - context 'Puppet[:vardir] ==' do - it '/var/lib/puppet' do - Puppet.stubs(:[]).with(:vardir).returns('/var/lib/puppet') - Facter.fact(:concat_basedir).value.should == '/var/lib/puppet/concat' - end - - it '/home/apenny/.puppet/var' do - Puppet.stubs(:[]).with(:vardir).returns('/home/apenny/.puppet/var') - Facter.fact(:concat_basedir).value.should == '/home/apenny/.puppet/var/concat' - end - end - -end diff --git a/concat/tests/init.pp b/concat/tests/init.pp index fd2142718..c7f193463 100644 --- a/concat/tests/init.pp +++ b/concat/tests/init.pp @@ -1,6 +1,5 @@ concat { '/tmp/concat': ensure => present, - force => true, owner => 'root', group => 'root', mode => '0644', diff --git a/glance/lib/puppet/provider/glance.rb b/glance/lib/puppet/provider/glance.rb index 6f7bbee06..2501d63c9 100644 --- a/glance/lib/puppet/provider/glance.rb +++ b/glance/lib/puppet/provider/glance.rb @@ -16,7 +16,7 @@ def self.get_glance_credentials glance_file['keystone_authtoken']['admin_tenant_name'] and glance_file['keystone_authtoken']['admin_user'] and glance_file['keystone_authtoken']['admin_password'] and - glance_file['DEFAULT']['os_region_name'] + glance_file['glance_store']['os_region_name'] g = {} g['auth_host'] = glance_file['keystone_authtoken']['auth_host'].strip @@ -25,7 +25,7 @@ def self.get_glance_credentials g['admin_tenant_name'] = glance_file['keystone_authtoken']['admin_tenant_name'].strip g['admin_user'] = glance_file['keystone_authtoken']['admin_user'].strip g['admin_password'] = glance_file['keystone_authtoken']['admin_password'].strip - g['os_region_name'] = glance_file['DEFAULT']['os_region_name'].strip + g['os_region_name'] = glance_file['glance_store']['os_region_name'].strip # auth_admin_prefix not required to be set. g['auth_admin_prefix'] = (glance_file['keystone_authtoken']['auth_admin_prefix'] || '').strip @@ -36,14 +36,14 @@ def self.get_glance_credentials glance_file['keystone_authtoken']['admin_tenant_name'] and glance_file['keystone_authtoken']['admin_user'] and glance_file['keystone_authtoken']['admin_password'] and - glance_file['DEFAULT']['os_region_name'] + glance_file['glance_store']['os_region_name'] g = {} g['identity_uri'] = glance_file['keystone_authtoken']['identity_uri'].strip g['admin_tenant_name'] = glance_file['keystone_authtoken']['admin_tenant_name'].strip g['admin_user'] = glance_file['keystone_authtoken']['admin_user'].strip g['admin_password'] = glance_file['keystone_authtoken']['admin_password'].strip - g['os_region_name'] = glance_file['DEFAULT']['os_region_name'].strip + g['os_region_name'] = glance_file['glance_store']['os_region_name'].strip return g else diff --git a/glance/lib/puppet/provider/glance_image/glance.rb b/glance/lib/puppet/provider/glance_image/glance.rb index 7be1ace9d..fae22e032 100644 --- a/glance/lib/puppet/provider/glance_image/glance.rb +++ b/glance/lib/puppet/provider/glance_image/glance.rb @@ -92,10 +92,6 @@ def destroy @property_hash[:ensure] = :absent end - def location=(value) - auth_glance('image-update', id, "--location=#{value}") - end - def is_public=(value) auth_glance('image-update', id, "--is-public=#{value}") end diff --git a/glance/lib/puppet/type/glance_image.rb b/glance/lib/puppet/type/glance_image.rb index 8ee348a9a..10e577efe 100644 --- a/glance/lib/puppet/type/glance_image.rb +++ b/glance/lib/puppet/type/glance_image.rb @@ -36,7 +36,7 @@ end end - newproperty(:location) do + newparam(:location) do desc "The permanent location of the image. Optional" newvalues(/\S+/) end diff --git a/glance/manifests/api.pp b/glance/manifests/api.pp index bb58e9100..26dc0b386 100644 --- a/glance/manifests/api.pp +++ b/glance/manifests/api.pp @@ -8,7 +8,9 @@ # (required) Password used to authentication. # # [*package_ensure*] -# (optional) Ensure state for package. Defaults to 'present'. +# (optional) Ensure state for package. On RedHat platforms this +# setting is ignored and the setting from the glance class is used +# because there is only one glance package. Defaults to 'present'. # # [*verbose*] # (optional) Rather to log the glance api service at verbose level. @@ -237,12 +239,14 @@ warning('The mysql_module parameter is deprecated. The latest 2.x mysql module will be used.') } - ensure_packages([$glance::params::api_package_name], - { - ensure => $package_ensure, - tag => ['openstack'], - } - ) + if ( $glance::params::api_package_name != $glance::params::registry_package_name ) { + ensure_packages([$glance::params::api_package_name], + { + ensure => $package_ensure, + tag => ['openstack'], + } + ) + } Package[$glance::params::api_package_name] -> File['/etc/glance/'] Package[$glance::params::api_package_name] -> Class['glance::policy'] diff --git a/glance/manifests/init.pp b/glance/manifests/init.pp index 5dec9033b..3b1042252 100644 --- a/glance/manifests/init.pp +++ b/glance/manifests/init.pp @@ -2,7 +2,16 @@ # == class: glance # # base glance config. # -class glance { +# === parameters: +# +# [*package_ensure*] +# (Optional) Ensure state for package. On Ubuntu this setting +# is ignored since Ubuntu has separate API and registry packages. +# Defaults to 'present' +# +class glance( + $package_ensure = 'present' +) { include ::glance::params @@ -12,4 +21,12 @@ # == class: glance group => 'root', mode => '0770', } + + if ( $glance::params::api_package_name == $glance::params::registry_package_name ) { + package { $glance::params::api_package_name : + ensure => $package_ensure, + name => $::glance::params::package_name, + tag => ['openstack'], + } + } } diff --git a/glance/manifests/params.pp b/glance/manifests/params.pp index 8be763a13..61df5b8db 100644 --- a/glance/manifests/params.pp +++ b/glance/manifests/params.pp @@ -10,8 +10,8 @@ case $::osfamily { 'RedHat': { - $api_package_name = 'openstack-glance-api' - $registry_package_name = 'openstack-glance-registry' + $api_package_name = 'openstack-glance' + $registry_package_name = 'openstack-glance' $api_service_name = 'openstack-glance-api' $registry_service_name = 'openstack-glance-registry' $db_sync_command = 'glance-manage --config-file=/etc/glance/glance-registry.conf db_sync' diff --git a/glance/manifests/registry.pp b/glance/manifests/registry.pp index e11a9b086..b30d7f565 100644 --- a/glance/manifests/registry.pp +++ b/glance/manifests/registry.pp @@ -8,7 +8,9 @@ # (required) The keystone password for administrative user # # [*package_ensure*] -# (optional) Ensure state for package. Defaults to 'present'. +# (optional) Ensure state for package. Defaults to 'present'. On RedHat +# platforms this setting is ignored and the setting from the glance class is +# used because there is only one glance package. # # [*verbose*] # (optional) Enable verbose logs (true|false). Defaults to false. @@ -160,12 +162,14 @@ warning('The mysql_module parameter is deprecated. The latest 2.x mysql module will be used.') } - ensure_packages( [$glance::params::registry_package_name], - { - ensure => $package_ensure, - tag => ['openstack'], - } - ) + if ( $glance::params::api_package_name != $glance::params::registry_package_name ) { + ensure_packages( [$glance::params::registry_package_name], + { + ensure => $package_ensure, + tag => ['openstack'], + } + ) + } Package[$glance::params::registry_package_name] -> File['/etc/glance/'] Package[$glance::params::registry_package_name] -> Glance_registry_config<||> diff --git a/glance/spec/classes/glance_api_spec.rb b/glance/spec/classes/glance_api_spec.rb index f796b4909..bdac287a0 100644 --- a/glance/spec/classes/glance_api_spec.rb +++ b/glance/spec/classes/glance_api_spec.rb @@ -434,6 +434,8 @@ end let(:params) { default_params } + # We only test this on Debian platforms, since on RedHat there isn't a + # separate package for glance API. ['present', 'latest'].each do |package_ensure| context "with package_ensure '#{package_ensure}'" do let(:params) { default_params.merge({ :package_ensure => package_ensure }) } @@ -451,15 +453,9 @@ end let(:params) { default_params } - ['present', 'latest'].each do |package_ensure| - context "with package_ensure '#{package_ensure}'" do - let(:params) { default_params.merge({ :package_ensure => package_ensure }) } - it { is_expected.to contain_package('openstack-glance-api').with( - :ensure => package_ensure, - :tag => ['openstack'] - )} - end - end + it { is_expected.to contain_package('openstack-glance').with( + :tag => ['openstack'], + )} end describe 'on unknown platforms' do diff --git a/glance/spec/classes/glance_cache_cleaner_spec.rb b/glance/spec/classes/glance_cache_cleaner_spec.rb index 6f9c34f81..ccb87845b 100644 --- a/glance/spec/classes/glance_cache_cleaner_spec.rb +++ b/glance/spec/classes/glance_cache_cleaner_spec.rb @@ -59,7 +59,7 @@ { :osfamily => 'RedHat' } end include_examples 'glance cache cleaner' - it { is_expected.to contain_cron('glance-cache-cleaner').with(:require => 'Package[openstack-glance-api]')} + it { is_expected.to contain_cron('glance-cache-cleaner').with(:require => 'Package[openstack-glance]')} end end diff --git a/glance/spec/classes/glance_cache_pruner_spec.rb b/glance/spec/classes/glance_cache_pruner_spec.rb index cc58932e7..1d08b33fc 100644 --- a/glance/spec/classes/glance_cache_pruner_spec.rb +++ b/glance/spec/classes/glance_cache_pruner_spec.rb @@ -59,7 +59,7 @@ { :osfamily => 'RedHat' } end include_examples 'glance cache pruner' - it { is_expected.to contain_cron('glance-cache-pruner').with(:require => 'Package[openstack-glance-api]')} + it { is_expected.to contain_cron('glance-cache-pruner').with(:require => 'Package[openstack-glance]')} end end diff --git a/glance/spec/classes/glance_registry_spec.rb b/glance/spec/classes/glance_registry_spec.rb index 34e3ae26c..2bb888ca2 100644 --- a/glance/spec/classes/glance_registry_spec.rb +++ b/glance/spec/classes/glance_registry_spec.rb @@ -347,6 +347,8 @@ { :osfamily => 'Debian' } end + # We only test this on Debian platforms, since on RedHat there isn't a + # separate package for glance registry. ['present', 'latest'].each do |package_ensure| context "with package_ensure '#{package_ensure}'" do let(:params) { default_params.merge({ :package_ensure => package_ensure }) } @@ -364,16 +366,7 @@ end let(:params) { default_params } - ['present', 'latest'].each do |package_ensure| - context "with package_ensure '#{package_ensure}'" do - let(:params) { default_params.merge({ :package_ensure => package_ensure }) } - it { is_expected.to contain_package('openstack-glance-registry').with( - :ensure => package_ensure, - :tag => ['openstack'] - )} - end - end - + it { is_expected.to contain_package('openstack-glance')} end describe 'on unknown platforms' do diff --git a/glance/spec/classes/glance_spec.rb b/glance/spec/classes/glance_spec.rb index 968b69764..075cec5eb 100644 --- a/glance/spec/classes/glance_spec.rb +++ b/glance/spec/classes/glance_spec.rb @@ -49,7 +49,9 @@ end let(:params) { default_params } - it { is_expected.to_not contain_package('openstack-glance') } + it { is_expected.to contain_package('openstack-glance').with( + :tag => ['openstack'], + )} end end diff --git a/glance/spec/unit/provider/glance_spec.rb b/glance/spec/unit/provider/glance_spec.rb index 14d418b97..344ec4a21 100644 --- a/glance/spec/unit/provider/glance_spec.rb +++ b/glance/spec/unit/provider/glance_spec.rb @@ -36,7 +36,7 @@ 'admin_user' => 'user', 'admin_password' => 'pass' }, - 'DEFAULT' => + 'glance_store' => { 'os_region_name' => 'SomeRegion', } diff --git a/gluster/manifests/brick.pp b/gluster/manifests/brick.pp index ee308f29c..69939f9b4 100644 --- a/gluster/manifests/brick.pp +++ b/gluster/manifests/brick.pp @@ -539,7 +539,7 @@ recurse => false, # don't recurse into directory purge => false, # don't purge unmanaged files force => false, # don't purge subdirs and links - require => Exec["gluster-brick-mkfs-${name}"], + require => Exec["gluster-brick-mkdir-${name}"], } } } diff --git a/gluster/manifests/mount.pp b/gluster/manifests/mount.pp index db437a35e..ae066f898 100644 --- a/gluster/manifests/mount.pp +++ b/gluster/manifests/mount.pp @@ -27,6 +27,8 @@ $ip = '', # you can specify which ip address to use (if multiple) $type = 'glusterfs', # use 'glusterfs' or 'nfs' $shorewall = false, + $owner = '', # mount owner + $group = '', # mount group ) { include gluster::params @@ -142,6 +144,14 @@ purge => false, # don't purge unmanaged files force => false, # don't purge subdirs and links alias => "${short_name}", # don't allow duplicates name's + owner => "${owner}" ? { # make sure owner is undef if not specified + '' => undef, + default => $owner, + }, + group => "${group}" ? { # make sure group is undef if not specified + '' => undef, + default => $group, + } } # TODO: review packages content against nfs fstype mount option diff --git a/gluster/manifests/volume/property/data.pp b/gluster/manifests/volume/property/data.pp index eaf7df2c8..356db3f8c 100644 --- a/gluster/manifests/volume/property/data.pp +++ b/gluster/manifests/volume/property/data.pp @@ -104,7 +104,7 @@ # Sets the quorum percentage for the trusted storage pool. 'cluster.server-quorum-ratio' => 'integer', # in % default: (null) - # If set to server, enables the specified volume to participate in quorum. + # If set to server, enables the specified volume to participate in quorum. 'cluster.server-quorum-type' => 'string', # default: (null) # Size of the stripe unit that would be read from or written to the striped servers. @@ -295,6 +295,9 @@ # Number of pages that will be pre-fetched 'performance.read-ahead-page-count' => 'integer', # default: 4 + # enable/disable readdir-ahead translator in the volume. + 'performance.readdir-ahead' => 'offon', # default: off + # enable/disable meta-data caching translator in the volume. 'performance.stat-prefetch' => 'onoff', # default: on diff --git a/gnocchi/spec/unit/provider/gnocchi_config/ini_setting_spec.rb b/gnocchi/spec/unit/provider/gnocchi_config/ini_setting_spec.rb index fa617c6bc..059a5a2f5 100644 --- a/gnocchi/spec/unit/provider/gnocchi_config/ini_setting_spec.rb +++ b/gnocchi/spec/unit/provider/gnocchi_config/ini_setting_spec.rb @@ -22,8 +22,8 @@ {:name => 'DEFAULT/foo', :value => 'bar'} ) provider = provider_class.new(resource) - provider.section.should == 'DEFAULT' - provider.setting.should == 'foo' + expect(provider.section).to eq('DEFAULT') + expect(provider.setting).to eq('foo') end it 'should allow setting to be set explicitly' do @@ -31,7 +31,7 @@ {:name => 'dude/foo', :value => 'bar'} ) provider = provider_class.new(resource) - provider.section.should == 'dude' - provider.setting.should == 'foo' + expect(provider.section).to eq('dude') + expect(provider.setting).to eq('foo') end end diff --git a/gnocchi/spec/unit/type/gnocchi_config_spec.rb b/gnocchi/spec/unit/type/gnocchi_config_spec.rb index 24a0caf75..d711b0345 100644 --- a/gnocchi/spec/unit/type/gnocchi_config_spec.rb +++ b/gnocchi/spec/unit/type/gnocchi_config_spec.rb @@ -29,19 +29,19 @@ it 'should accept a valid value' do @gnocchi_config[:value] = 'bar' - @gnocchi_config[:value].should == 'bar' + expect(@gnocchi_config[:value]).to eq('bar') end it 'should not accept a value with whitespace' do @gnocchi_config[:value] = 'b ar' - @gnocchi_config[:value].should == 'b ar' + expect(@gnocchi_config[:value]).to eq('b ar') end it 'should accept valid ensure values' do @gnocchi_config[:ensure] = :present - @gnocchi_config[:ensure].should == :present + expect(@gnocchi_config[:ensure]).to eq(:present) @gnocchi_config[:ensure] = :absent - @gnocchi_config[:ensure].should == :absent + expect(@gnocchi_config[:ensure]).to eq(:absent) end it 'should not accept invalid ensure values' do diff --git a/haproxy/.gitignore b/haproxy/.gitignore index b5db85e05..2652ac5e9 100644 --- a/haproxy/.gitignore +++ b/haproxy/.gitignore @@ -1,4 +1,5 @@ pkg/ +log/ Gemfile.lock vendor/ spec/fixtures/ diff --git a/haproxy/README.md b/haproxy/README.md index 0e4db97cf..9cd355750 100644 --- a/haproxy/README.md +++ b/haproxy/README.md @@ -280,7 +280,7 @@ Using storeconfigs, you can export the `haproxy::balancermember` resources on al Sets the backend service's name. Generally, it will be the namevar of the defined resource type. This value appears right after the 'backend' statement in haproxy.cfg #####`options` -A hash of options that are inserted into the backend service configuration block. +A hash or array of options that are inserted into the backend service configuration block. If you need to control exactly the order in which these options will appear in the backend service configuration block supply the options as an array of hashes, where each hash has one key-value pair that represents the option and its value. #####`collect_exported` Enables exported resources from `haproxy::balancermember` to be collected, serving as a form of autodiscovery. Displays as a Boolean and defaults to 'true'. @@ -303,6 +303,22 @@ haproxy::backend { 'puppet00': } ``` +If option order is important use an array of hashes for the `options` parameter to have the backend options appear in the resulting backend configuration block in the exact order in which they are specified in Puppet: + +```puppet +haproxy::backend { 'puppet00': + options => [ + { 'option' => [ + 'tcplog', + 'ssl-hello-chk', + ] + }, + { 'balance' => 'roundrobin' }, + { 'cookie' => 'C00 insert' }, + ], +} +``` + ####Defined type: `haproxy::frontend` This type sets up a frontend service configuration block in haproxy.cfg. The HAProxy daemon uses the directives in the .cfg file to determine which ports/IPs to listen on and route traffic on those ports/IPs to specified balancermembers. @@ -337,7 +353,7 @@ Sets the mode of operation for the frontend service. Valid values are 'undef', ' Sets the frontend service's name. Generally, it will be the namevar of the defined resource type. This value appears right after the 'fronted' statement in haproxy.cfg. #####`options` -A hash of options that are inserted into the frontend service configuration block. +A hash or array of options that are inserted into the backend service configuration block. If you need to control exactly the order in which these options will appear in the backend service configuration block supply the options as an array of hashes, where each hash has one key-value pair that represents the option and its value. See Example section right below. #####`ports` Sets the ports to listen on for the address specified in `ipaddress`. Accepts a single, comma-separated string or an array of strings, which may be ports or hyphenated port ranges. @@ -353,9 +369,8 @@ haproxy::frontend { 'puppet00': mode => 'tcp', bind_options => 'accept-proxy', options => { - 'option' => [ 'default_backend', 'puppet_backend00'], + 'default_backend' => 'puppet_backend00', 'timeout client' => '30', - 'balance' => 'roundrobin' 'option' => [ 'tcplog', 'accept-invalid-http-request', @@ -364,6 +379,26 @@ haproxy::frontend { 'puppet00': } ``` +If option order is important use an array of hashes for the `options` parameter to have the frontend options appear in the resulting frontned configuration block in the exact order in which they are specified in Puppet: + +```puppet +haproxy::frontend { 'puppet00': + ipaddress => $::ipaddress, + ports => '18140', + mode => 'tcp', + bind_options => 'accept-proxy', + options => [ + { 'default_backend' => 'puppet_backend00' }, + { 'timeout client' => '30' }, + { 'option' => [ + 'tcplog', + 'accept-invalid-http-request', + ], + } + ], +} +``` + ####Defined type: `haproxy::listen` This type sets up a listening service configuration block inside the haproxy.cfg file on an HAProxy load balancer. Each listening service configuration needs one or more load balancer member server (declared with the [`haproxy::balancermember`](#defined-type-balancermember) defined type). @@ -405,7 +440,7 @@ Specifies the mode of operation for the listening service. Valid values are 'und Sets the listening service's name. Generally, it will be the namevar of the defined resource type. This value appears right after the 'listen' statement in haproxy.cfg. #####`options` -A hash of options that are inserted into the listening service configuration block. +A hash or array of options that are inserted into the backend service configuration block. If you need to control exactly the order in which these options will appear in the backend service configuration block supply the options as an array of hashes, where each hash has one key-value pair that represents the option and its value. See Example sections for backend and frontend above. #####`ports` Sets the ports to listen on for the address specified in `ipaddress`. Accepts a single, comma-separated string or an array of strings, which may be ports or hyphenated port ranges. @@ -485,7 +520,7 @@ Sets the port on which the peer is going to share the state. ##Limitations -RedHat and Debian family OSes are officially supported. Tested and built on Ubuntu and CentOS. +RedHat and Debian family OSes are officially supported. Tested and built on Ubuntu and CentOS. Also compatible with Gentoo. ##Development diff --git a/haproxy/manifests/install.pp b/haproxy/manifests/install.pp index 6856d1909..e5890a28a 100644 --- a/haproxy/manifests/install.pp +++ b/haproxy/manifests/install.pp @@ -8,4 +8,14 @@ ensure => $haproxy::_package_ensure, alias => 'haproxy', } + + # Create default configuration directory, gentoo portage does not create it + if $::osfamily == 'Gentoo' { + file { '/etc/haproxy': + ensure => directory, + owner => 'root', + group => 'root', + require => Package[$haproxy::package_name] + } + } } diff --git a/haproxy/manifests/params.pp b/haproxy/manifests/params.pp index 7ac6458d9..dc955244b 100644 --- a/haproxy/manifests/params.pp +++ b/haproxy/manifests/params.pp @@ -6,7 +6,7 @@ # class haproxy::params { case $::osfamily { - 'Archlinux', 'Debian', 'RedHat': { + 'Archlinux', 'Debian', 'Redhat', 'Gentoo' : { $package_name = 'haproxy' $global_options = { 'log' => "${::ipaddress} local0", diff --git a/haproxy/spec/classes/haproxy_spec.rb b/haproxy/spec/classes/haproxy_spec.rb index 0b1244e26..ab0d79dab 100644 --- a/haproxy/spec/classes/haproxy_spec.rb +++ b/haproxy/spec/classes/haproxy_spec.rb @@ -9,7 +9,7 @@ end context 'on supported platforms' do describe 'for OS-agnostic configuration' do - ['Debian', 'RedHat', 'Archlinux', 'FreeBSD',].each do |osfamily| + ['Debian', 'RedHat', 'Archlinux', 'FreeBSD', 'Gentoo',].each do |osfamily| context "on #{osfamily} family operatingsystems" do let(:facts) do { :osfamily => osfamily }.merge default_facts @@ -53,7 +53,7 @@ end describe 'for linux operating systems' do - ['Debian', 'RedHat', 'Archlinux', ].each do |osfamily| + ['Debian', 'RedHat', 'Archlinux', 'Gentoo', ].each do |osfamily| context "on #{osfamily} family operatingsystems" do let(:facts) do { :osfamily => osfamily }.merge default_facts @@ -337,6 +337,12 @@ { :osfamily => 'RedHat' }.merge default_facts end end + context 'only on Gentoo family operatingsystems' do + let(:facts) do + { :osfamily => 'Gentoo' }.merge default_facts + end + end + end end diff --git a/haproxy/spec/defines/frontend_spec.rb b/haproxy/spec/defines/frontend_spec.rb index aff45e3ef..977d8f432 100644 --- a/haproxy/spec/defines/frontend_spec.rb +++ b/haproxy/spec/defines/frontend_spec.rb @@ -213,5 +213,32 @@ ) } end + context "when frontend options are specified as an array of hashes" do + let(:params) do + { + :name => 'apache', + :bind => { + '0.0.0.0:48001-48003' => [], + }, + :mode => 'http', + :options => [ + { 'reqadd' => 'X-Forwarded-Proto:\ https' }, + { 'default_backend' => 'dev00_webapp' }, + { 'capture request header' => [ 'X-Forwarded-For len 50', 'Host len 15', 'Referrer len 15' ] }, + { 'acl' => [ 'dst_dev01 dst_port 48001', 'dst_dev02 dst_port 48002', 'dst_dev03 dst_port 48003' ] }, + { 'use_backend' => [ 'dev01_webapp if dst_dev01', 'dev02_webapp if dst_dev02', 'dev03_webapp if dst_dev03' ] }, + { 'option' => [ 'httplog', 'http-server-close', 'forwardfor except 127.0.0.1' ] }, + { 'compression' => 'algo gzip', + 'bind-process' => 'all' } + ], + } + end + it { should contain_concat__fragment('apache_frontend_block').with( + 'order' => '15-apache-00', + 'target' => '/etc/haproxy/haproxy.cfg', + 'content' => "\nfrontend apache\n bind 0.0.0.0:48001-48003 \n mode http\n reqadd X-Forwarded-Proto:\\ https\n default_backend dev00_webapp\n capture request header X-Forwarded-For len 50\n capture request header Host len 15\n capture request header Referrer len 15\n acl dst_dev01 dst_port 48001\n acl dst_dev02 dst_port 48002\n acl dst_dev03 dst_port 48003\n use_backend dev01_webapp if dst_dev01\n use_backend dev02_webapp if dst_dev02\n use_backend dev03_webapp if dst_dev03\n option httplog\n option http-server-close\n option forwardfor except 127.0.0.1\n bind-process all\n compression algo gzip\n" + ) } + end + # C9950 C9951 C9952 WONTFIX end diff --git a/haproxy/spec/defines/listen_spec.rb b/haproxy/spec/defines/listen_spec.rb index 51ca6c2d6..fbad4b077 100644 --- a/haproxy/spec/defines/listen_spec.rb +++ b/haproxy/spec/defines/listen_spec.rb @@ -241,4 +241,31 @@ ) } end + context "when listen options are specified as an array of hashes" do + let(:params) do + { + :name => 'apache', + :bind => { + '0.0.0.0:48001-48003' => [], + }, + :mode => 'http', + :options => [ + { 'reqadd' => 'X-Forwarded-Proto:\ https' }, + { 'default_backend' => 'dev00_webapp' }, + { 'capture request header' => [ 'X-Forwarded-For len 50', 'Host len 15', 'Referrer len 15' ] }, + { 'acl' => [ 'dst_dev01 dst_port 48001', 'dst_dev02 dst_port 48002', 'dst_dev03 dst_port 48003' ] }, + { 'use_backend' => [ 'dev01_webapp if dst_dev01', 'dev02_webapp if dst_dev02', 'dev03_webapp if dst_dev03' ] }, + { 'option' => [ 'httplog', 'http-server-close', 'forwardfor except 127.0.0.1' ] }, + { 'compression' => 'algo gzip', + 'bind-process' => 'all' } + ], + } + end + it { should contain_concat__fragment('apache_listen_block').with( + 'order' => '20-apache-00', + 'target' => '/etc/haproxy/haproxy.cfg', + 'content' => "\nlisten apache\n bind 0.0.0.0:48001-48003 \n mode http\n reqadd X-Forwarded-Proto:\\ https\n default_backend dev00_webapp\n capture request header X-Forwarded-For len 50\n capture request header Host len 15\n capture request header Referrer len 15\n acl dst_dev01 dst_port 48001\n acl dst_dev02 dst_port 48002\n acl dst_dev03 dst_port 48003\n use_backend dev01_webapp if dst_dev01\n use_backend dev02_webapp if dst_dev02\n use_backend dev03_webapp if dst_dev03\n option httplog\n option http-server-close\n option forwardfor except 127.0.0.1\n bind-process all\n compression algo gzip\n" + ) } + end + end diff --git a/haproxy/templates/fragments/_options.erb b/haproxy/templates/fragments/_options.erb index 52ba2d8f4..a61f238ab 100644 --- a/haproxy/templates/fragments/_options.erb +++ b/haproxy/templates/fragments/_options.erb @@ -1,5 +1,19 @@ +<% if @options.is_a?(Hash) -%> <% @options.sort.each do |key, val| -%> <% Array(val).each do |item| -%> <%= key %> <%= item %> <% end -%> <% end -%> +<% elsif @options.is_a?(Array) -%> +<%# Iterate over array elements; each element is a hash (containing key-value -%> +<%# pairs); in case a hash contains more than one key-value pair the hash is -%> +<%# sorted by key name before outputting the key name (= option name) and its -%> +<%# value (or values, one per line) -%> +<% @options.each do |option| -%> +<% option.sort.map do |key, val| -%> +<% Array(val).each do |item| -%> + <%= key %> <%= item %> +<% end -%> +<% end -%> +<% end -%> +<% end -%> diff --git a/heat/.fixtures.yml b/heat/.fixtures.yml index e3874587c..d31679dfa 100644 --- a/heat/.fixtures.yml +++ b/heat/.fixtures.yml @@ -1,7 +1,9 @@ fixtures: repositories: 'inifile': 'git://github.com/puppetlabs/puppetlabs-inifile' - 'concat': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'concat': + 'repo': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'ref': '1.2.1' 'keystone': 'git://github.com/stackforge/puppet-keystone.git' 'mysql': 'git://github.com/puppetlabs/puppetlabs-mysql.git' 'nova': 'git://github.com/stackforge/puppet-nova.git' diff --git a/heat/manifests/api.pp b/heat/manifests/api.pp index b90a4e0cb..ee1c2d67c 100644 --- a/heat/manifests/api.pp +++ b/heat/manifests/api.pp @@ -95,7 +95,7 @@ hasrestart => true, require => [Package['heat-common'], Package['heat-api']], - subscribe => Exec['heat-dbsync'], + subscribe => $::heat::subscribe_sync_db, } heat_config { diff --git a/heat/manifests/api_cfn.pp b/heat/manifests/api_cfn.pp index 9738eb415..ab7603f87 100644 --- a/heat/manifests/api_cfn.pp +++ b/heat/manifests/api_cfn.pp @@ -98,7 +98,7 @@ enable => $enabled, hasstatus => true, hasrestart => true, - subscribe => Exec['heat-dbsync'], + subscribe => $::heat::subscribe_sync_db, } heat_config { diff --git a/heat/manifests/api_cloudwatch.pp b/heat/manifests/api_cloudwatch.pp index 8f4a64cd5..034bd3af3 100644 --- a/heat/manifests/api_cloudwatch.pp +++ b/heat/manifests/api_cloudwatch.pp @@ -98,7 +98,7 @@ enable => $enabled, hasstatus => true, hasrestart => true, - subscribe => Exec['heat-dbsync'], + subscribe => $::heat::subscribe_sync_db, } heat_config { diff --git a/heat/manifests/engine.pp b/heat/manifests/engine.pp index 6a62cec02..0dc9dcb2c 100644 --- a/heat/manifests/engine.pp +++ b/heat/manifests/engine.pp @@ -67,6 +67,7 @@ $configure_delegated_roles = true, #DEPRECATED ) { + include ::heat include ::heat::params Heat_config<||> ~> Service['heat-engine'] @@ -77,7 +78,7 @@ ensure => installed, name => $::heat::params::engine_package_name, tag => 'openstack', - notify => Exec['heat-dbsync'], + notify => $::heat::subscribe_sync_db, } if $manage_service { @@ -104,7 +105,7 @@ require => [ File['/etc/heat/heat.conf'], Package['heat-common'], Package['heat-engine']], - subscribe => Exec['heat-dbsync'], + subscribe => $::heat::subscribe_sync_db, } heat_config { diff --git a/heat/manifests/init.pp b/heat/manifests/init.pp index 0d56db64b..c20b3c8c7 100644 --- a/heat/manifests/init.pp +++ b/heat/manifests/init.pp @@ -164,6 +164,10 @@ # (Optional) Enable the stack-abandon feature. # Defaults to undef # +# [*sync_db*] +# (Optional) Run db sync on nodes after connection setting has been set. +# Defaults to true +# # === Deprecated Parameters # # [*mysql_module*] @@ -229,6 +233,7 @@ $region_name = undef, $enable_stack_adopt = undef, $enable_stack_abandon = undef, + $sync_db = true, # Deprecated parameters $mysql_module = undef, $sql_connection = undef, @@ -506,14 +511,17 @@ value => $database_idle_timeout; } - Heat_config['database/connection'] ~> Exec['heat-dbsync'] + if $sync_db { + $subscribe_sync_db = Exec['heat-dbsync'] + Heat_config['database/connection'] ~> Exec['heat-dbsync'] - exec { 'heat-dbsync': - command => $::heat::params::dbsync_command, - path => '/usr/bin', - user => 'heat', - refreshonly => true, - logoutput => on_failure, + exec { 'heat-dbsync': + command => $::heat::params::dbsync_command, + path => '/usr/bin', + user => 'heat', + refreshonly => true, + logoutput => on_failure, + } } } diff --git a/heat/manifests/keystone/domain.pp b/heat/manifests/keystone/domain.pp index 6a6768efa..35f675ff8 100644 --- a/heat/manifests/keystone/domain.pp +++ b/heat/manifests/keystone/domain.pp @@ -41,6 +41,7 @@ include ::heat::params $cmd_evn = [ + "OS_TENANT_NAME=${keystone_tenant}", "OS_USERNAME=${keystone_admin}", "OS_PASSWORD=${keystone_password}", "OS_AUTH_URL=${auth_url}", diff --git a/heat/spec/classes/heat_api_cfn_spec.rb b/heat/spec/classes/heat_api_cfn_spec.rb index 20ffeb31e..6af343a98 100644 --- a/heat/spec/classes/heat_api_cfn_spec.rb +++ b/heat/spec/classes/heat_api_cfn_spec.rb @@ -100,6 +100,17 @@ is_expected.to contain_service('heat-api-cfn').that_subscribes_to('Exec[heat-dbsync]') end end + + context 'with $sync_db set to false in ::heat' do + let :pre_condition do + "class {'heat': sync_db => false}" + end + + it 'configures heat-api-cfn service to not subscribe to the dbsync resource' do + is_expected.to contain_service('heat-api-cfn').that_subscribes_to(nil) + end + end + end diff --git a/heat/spec/classes/heat_api_cloudwatch_spec.rb b/heat/spec/classes/heat_api_cloudwatch_spec.rb index a61caa6e8..7077d87c1 100644 --- a/heat/spec/classes/heat_api_cloudwatch_spec.rb +++ b/heat/spec/classes/heat_api_cloudwatch_spec.rb @@ -100,6 +100,17 @@ is_expected.to contain_service('heat-api-cloudwatch').that_subscribes_to('Exec[heat-dbsync]') end end + + context 'with $sync_db set to false in ::heat' do + let :pre_condition do + "class {'heat': sync_db => false}" + end + + it 'configures heat-api-cloudwatch service to not subscribe to the dbsync resource' do + is_expected.to contain_service('heat-api-cloudwatch').that_subscribes_to(nil) + end + end + end context 'on Debian platforms' do diff --git a/heat/spec/classes/heat_api_spec.rb b/heat/spec/classes/heat_api_spec.rb index 32ccb7552..91589ff1c 100644 --- a/heat/spec/classes/heat_api_spec.rb +++ b/heat/spec/classes/heat_api_spec.rb @@ -103,6 +103,16 @@ is_expected.to contain_service('heat-api').that_subscribes_to('Exec[heat-dbsync]') end end + + context 'with $sync_db set to false in ::heat' do + let :pre_condition do + "class {'heat': sync_db => false}" + end + + it 'configures heat-api service to not subscribe to the dbsync resource' do + is_expected.to contain_service('heat-api').that_subscribes_to(nil) + end + end end context 'on Debian platforms' do diff --git a/heat/spec/classes/heat_engine_spec.rb b/heat/spec/classes/heat_engine_spec.rb index 495d088d8..fad0c8164 100644 --- a/heat/spec/classes/heat_engine_spec.rb +++ b/heat/spec/classes/heat_engine_spec.rb @@ -99,6 +99,21 @@ :subscribe => 'Exec[heat-dbsync]' ) } end + context 'with $sync_db set to false in ::heat' do + let :pre_condition do + "class {'heat': sync_db => false}" + end + + it 'configures heat-engine service to not subscribe to the dbsync resource' do + is_expected.to contain_service('heat-engine').that_subscribes_to(nil) + end + + it 'configures the heat-engine package to not be notified by the dbsync resource ' do + is_expected.to contain_package('heat-engine').with( + :notify => nil, + ) + end + end end context 'on Debian platforms' do diff --git a/heat/spec/classes/heat_keystone_domain_spec.rb b/heat/spec/classes/heat_keystone_domain_spec.rb index 81c1d0904..0eba85d82 100644 --- a/heat/spec/classes/heat_keystone_domain_spec.rb +++ b/heat/spec/classes/heat_keystone_domain_spec.rb @@ -38,6 +38,7 @@ :require => 'Package[heat-common]', :logoutput => 'on_failure', :environment => [ + "OS_TENANT_NAME=#{params[:keystone_tenant]}", "OS_USERNAME=#{params[:keystone_admin]}", "OS_PASSWORD=#{params[:keystone_password]}", "OS_AUTH_URL=#{params[:auth_url]}", diff --git a/horizon/.fixtures.yml b/horizon/.fixtures.yml index eb613b734..4b00834e8 100644 --- a/horizon/.fixtures.yml +++ b/horizon/.fixtures.yml @@ -1,7 +1,9 @@ fixtures: repositories: 'apache': 'git://github.com/puppetlabs/puppetlabs-apache.git' - 'concat': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'concat': + 'repo': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'ref': '1.2.1' 'stdlib': 'git://github.com/puppetlabs/puppetlabs-stdlib.git' symlinks: "horizon": "#{source_dir}" diff --git a/horizon/Gemfile b/horizon/Gemfile index 748d075cb..65c29c4ef 100644 --- a/horizon/Gemfile +++ b/horizon/Gemfile @@ -2,6 +2,7 @@ source 'https://rubygems.org' group :development, :test do gem 'puppetlabs_spec_helper', :require => false + gem 'rspec-puppet', '~> 2.0.0', :require => false gem 'puppet-lint', '~> 1.1.0' gem 'metadata-json-lint' @@ -16,9 +17,6 @@ group :development, :test do gem 'puppet-lint-variable_contains_upcase' gem 'puppet-lint-numericvariable' - gem 'rspec-puppet', '~> 1.0.1' - gem 'rake', '10.1.1' - gem 'rspec', '< 2.99' gem 'json' gem 'webmock' end diff --git a/horizon/manifests/init.pp b/horizon/manifests/init.pp index 246f4a107..a9c00c443 100644 --- a/horizon/manifests/init.pp +++ b/horizon/manifests/init.pp @@ -118,6 +118,11 @@ # security groups. Defaults to True. # 'enable_vpn': Boolean to enable or disable Neutron's VPNaaS feature. # Defaults to False. +# 'enable_distributed_router': Boolean to enable or disable Neutron +# distributed virtual router (DVR) feature in the Router panel. +# Defaults to False. +# 'enable_ha_router': Enable or disable HA (High Availability) mode in +# Neutron virtual router in the Router panel. Defaults to False. # 'profile_support': A string indiciating which plugin-specific # profiles to enable. Defaults to 'None', other options include # 'cisco'. @@ -255,12 +260,14 @@ # be merged with user-provided options when the local_settings.py.erb # template is interpolated. $neutron_defaults = { - 'enable_lb' => false, - 'enable_firewall' => false, - 'enable_quotas' => true, - 'enable_security_group' => true, - 'enable_vpn' => false, - 'profile_support' => 'None', + 'enable_lb' => false, + 'enable_firewall' => false, + 'enable_quotas' => true, + 'enable_security_group' => true, + 'enable_vpn' => false, + 'enable_distributed_router' => false, + 'enable_ha_router' => false, + 'profile_support' => 'None', } Service <| title == 'memcached' |> -> Class['horizon'] diff --git a/horizon/spec/classes/horizon_init_spec.rb b/horizon/spec/classes/horizon_init_spec.rb index c38caf12d..4e18df81f 100644 --- a/horizon/spec/classes/horizon_init_spec.rb +++ b/horizon/spec/classes/horizon_init_spec.rb @@ -25,20 +25,20 @@ context 'with default parameters' do it { - should contain_package('python-lesscpy').with_ensure('present') - should contain_package('horizon').with( + is_expected.to contain_package('python-lesscpy').with_ensure('present') + is_expected.to contain_package('horizon').with( :ensure => 'present', :tag => 'openstack' ) } - it { should contain_exec('refresh_horizon_django_cache').with({ + it { is_expected.to contain_exec('refresh_horizon_django_cache').with({ :command => '/usr/share/openstack-dashboard/manage.py compress', :refreshonly => true, })} - it { should contain_concat(platforms_params[:config_file]).that_notifies('Exec[refresh_horizon_django_cache]') } + it { is_expected.to contain_concat(platforms_params[:config_file]).that_notifies('Exec[refresh_horizon_django_cache]') } it 'configures apache' do - should contain_class('horizon::wsgi::apache').with({ + is_expected.to contain_class('horizon::wsgi::apache').with({ :servername => 'some.host.tld', :listen_ssl => false, :servername => 'some.host.tld', @@ -47,7 +47,7 @@ end it 'generates local_settings.py' do - verify_concat_fragment_contents(subject, 'local_settings.py', [ + verify_concat_fragment_contents(catalogue, 'local_settings.py', [ 'DEBUG = False', "ALLOWED_HOSTS = ['*', ]", "SECRET_KEY = 'elj1IWiLoWHgcyYxFVLj7cM5rGOOxWl0'", @@ -60,6 +60,8 @@ " 'enable_quotas': True,", " 'enable_security_group': True,", " 'enable_vpn': False,", + " 'enable_distributed_router': False,", + " 'enable_ha_router': False,", 'API_RESULT_LIMIT = 1000', "LOGIN_URL = '#{platforms_params[:root_url]}/auth/login/'", "LOGOUT_URL = '#{platforms_params[:root_url]}/auth/logout/'", @@ -69,13 +71,13 @@ ]) # From internals of verify_contents, get the contents to check for absence of a line - content = subject.resource('concat::fragment', 'local_settings.py').send(:parameters)[:content] + content = catalogue.resource('concat::fragment', 'local_settings.py').send(:parameters)[:content] # With default options, should _not_ have a line to configure SESSION_ENGINE - content.should_not match(/^SESSION_ENGINE/) + expect(content).not_to match(/^SESSION_ENGINE/) end - it { should_not contain_file(params[:file_upload_temp_dir]) } + it { is_expected.not_to contain_file(params[:file_upload_temp_dir]) } end context 'with overridden parameters' do @@ -92,14 +94,15 @@ :compress_offline => false, :hypervisor_options => {'can_set_mount_point' => false, 'can_set_password' => true }, :cinder_options => {'enable_backup' => true }, - :neutron_options => {'enable_lb' => true, 'enable_firewall' => true, 'enable_quotas' => false, 'enable_security_group' => false, 'enable_vpn' => true, 'profile_support' => 'cisco' }, + :neutron_options => {'enable_lb' => true, 'enable_firewall' => true, 'enable_quotas' => false, 'enable_security_group' => false, 'enable_vpn' => true, + 'enable_distributed_router' => false, 'enable_ha_router' => false, 'profile_support' => 'cisco', }, :file_upload_temp_dir => '/var/spool/horizon', :secure_cookies => true }) end it 'generates local_settings.py' do - verify_concat_fragment_contents(subject, 'local_settings.py', [ + verify_concat_fragment_contents(catalogue, 'local_settings.py', [ 'DEBUG = True', "ALLOWED_HOSTS = ['*', ]", 'CSRF_COOKIE_SECURE = True', @@ -126,9 +129,9 @@ ]) end - it { should_not contain_file(platforms_params[:config_file]).that_notifies('Exec[refresh_horizon_django_cache]') } + it { is_expected.not_to contain_file(platforms_params[:config_file]).that_notifies('Exec[refresh_horizon_django_cache]') } - it { should contain_file(params[:file_upload_temp_dir]) } + it { is_expected.to contain_file(params[:file_upload_temp_dir]) } end context 'with overridden parameters and cache_server_ip array' do @@ -139,12 +142,12 @@ end it 'generates local_settings.py' do - verify_concat_fragment_contents(subject, 'local_settings.py', [ + verify_concat_fragment_contents(catalogue, 'local_settings.py', [ " 'LOCATION': [ '10.0.0.1:11211','10.0.0.2:11211', ],", ]) end - it { should contain_exec('refresh_horizon_django_cache') } + it { is_expected.to contain_exec('refresh_horizon_django_cache') } end context 'with vhost_extra_params' do @@ -155,7 +158,7 @@ end it 'configures apache' do - should contain_class('horizon::wsgi::apache').with({ + is_expected.to contain_class('horizon::wsgi::apache').with({ :extra_params => { 'add_listen' => false }, }) end @@ -174,7 +177,7 @@ end it 'configures apache' do - should contain_class('horizon::wsgi::apache').with({ + is_expected.to contain_class('horizon::wsgi::apache').with({ :bind_address => nil, :listen_ssl => true, :horizon_cert => '/etc/pki/tls/certs/httpd.crt', @@ -190,7 +193,7 @@ end it 'does not configure apache' do - should_not contain_class('horizon::wsgi::apache') + is_expected.not_to contain_class('horizon::wsgi::apache') end end @@ -205,7 +208,7 @@ end it 'AVAILABLE_REGIONS is configured' do - verify_concat_fragment_contents(subject, 'local_settings.py', [ + verify_concat_fragment_contents(catalogue, 'local_settings.py', [ "AVAILABLE_REGIONS = [", " ('http://region-1.example.com:5000/v2.0', 'Region-1'),", " ('http://region-2.example.com:5000/v2.0', 'Region-2'),", @@ -227,7 +230,7 @@ end it 'POLICY_FILES_PATH and POLICY_FILES are configured' do - verify_concat_fragment_contents(subject, 'local_settings.py', [ + verify_concat_fragment_contents(catalogue, 'local_settings.py', [ "POLICY_FILES_PATH = '/opt/openstack-dashboard'", "POLICY_FILES = {", " 'compute': 'nova_policy.json',", @@ -248,7 +251,7 @@ end it 'uses the custom local_settings.py template' do - verify_concat_fragment_contents(subject, 'local_settings.py', [ + verify_concat_fragment_contents(catalogue, 'local_settings.py', [ '# Custom local_settings.py', 'DEBUG = True', "HORIZON_CONFIG = {", @@ -277,7 +280,7 @@ }) end - it { should_not contain_file(params[:file_upload_temp_dir]) } + it { is_expected.not_to contain_file(params[:file_upload_temp_dir]) } end end diff --git a/horizon/spec/classes/horizon_wsgi_apache_spec.rb b/horizon/spec/classes/horizon_wsgi_apache_spec.rb index 7a7b9ef15..90ba62397 100644 --- a/horizon/spec/classes/horizon_wsgi_apache_spec.rb +++ b/horizon/spec/classes/horizon_wsgi_apache_spec.rb @@ -29,13 +29,13 @@ context 'with default parameters' do it 'configures apache' do - should contain_class('horizon::params') - should contain_class('apache') - should contain_class('apache::mod::wsgi') - should contain_service('httpd').with_name(platforms_params[:http_service]) - should contain_file(platforms_params[:httpd_config_file]) - should contain_package('horizon').with_ensure('present') - should contain_apache__vhost('horizon_vhost').with( + is_expected.to contain_class('horizon::params') + is_expected.to contain_class('apache') + is_expected.to contain_class('apache::mod::wsgi') + is_expected.to contain_service('httpd').with_name(platforms_params[:http_service]) + is_expected.to contain_file(platforms_params[:httpd_config_file]) + is_expected.to contain_package('horizon').with_ensure('present') + is_expected.to contain_apache__vhost('horizon_vhost').with( 'servername' => 'some.host.tld', 'access_log_file' => 'horizon_access.log', 'error_log_file' => 'horizon_error.log', @@ -62,13 +62,13 @@ end it 'configures apache' do - should contain_class('horizon::params') - should contain_class('apache') - should contain_class('apache::mod::wsgi') - should contain_service('httpd').with_name(platforms_params[:http_service]) - should contain_file(platforms_params[:httpd_config_file]) - should contain_package('horizon').with_ensure('present') - should contain_apache__vhost('horizon_vhost').with( + is_expected.to contain_class('horizon::params') + is_expected.to contain_class('apache') + is_expected.to contain_class('apache::mod::wsgi') + is_expected.to contain_service('httpd').with_name(platforms_params[:http_service]) + is_expected.to contain_file(platforms_params[:httpd_config_file]) + is_expected.to contain_package('horizon').with_ensure('present') + is_expected.to contain_apache__vhost('horizon_vhost').with( 'servername' => 'some.host.tld', 'access_log_file' => 'horizon_access.log', 'error_log_file' => 'horizon_error.log', @@ -100,9 +100,9 @@ context 'with required parameters' do it 'configures apache for SSL' do - should contain_class('apache::mod::ssl') + is_expected.to contain_class('apache::mod::ssl') end - it { should contain_apache__vhost('horizon_ssl_vhost').with( + it { is_expected.to contain_apache__vhost('horizon_ssl_vhost').with( 'servername' => 'some.host.tld', 'access_log_file' => 'horizon_ssl_access.log', 'error_log_file' => 'horizon_ssl_error.log', @@ -121,7 +121,7 @@ 'wsgi_script_aliases' => { platforms_params[:root_url] => '/usr/share/openstack-dashboard/openstack_dashboard/wsgi/django.wsgi' } )} - it { should contain_apache__vhost('horizon_vhost').with( + it { is_expected.to contain_apache__vhost('horizon_vhost').with( 'servername' => 'some.host.tld', 'access_log_file' => 'horizon_access.log', 'error_log_file' => 'horizon_error.log', @@ -167,7 +167,7 @@ end it 'configures apache' do - should contain_apache__vhost('horizon_vhost').with( + is_expected.to contain_apache__vhost('horizon_vhost').with( 'add_listen' => false, 'docroot' => '/tmp' ) @@ -201,7 +201,7 @@ it_behaves_like 'apache for horizon' it { - should contain_class('apache::mod::wsgi').with(:wsgi_socket_prefix => '/var/run/wsgi') + is_expected.to contain_class('apache::mod::wsgi').with(:wsgi_socket_prefix => '/var/run/wsgi') } end diff --git a/horizon/spec/shared_examples.rb b/horizon/spec/shared_examples.rb index 51e11c0ba..fec0eacc9 100644 --- a/horizon/spec/shared_examples.rb +++ b/horizon/spec/shared_examples.rb @@ -1,5 +1,5 @@ shared_examples_for "a Puppet::Error" do |description| it "with message matching #{description.inspect}" do - expect { subject }.to raise_error(Puppet::Error, description) + expect { is_expected.to have_class_count(1) }.to raise_error(Puppet::Error, description) end end diff --git a/horizon/spec/spec_helper.rb b/horizon/spec/spec_helper.rb index b3bca421a..605a8ad05 100644 --- a/horizon/spec/spec_helper.rb +++ b/horizon/spec/spec_helper.rb @@ -8,5 +8,5 @@ def verify_concat_fragment_contents(subject, title, expected_lines) content = subject.resource('concat::fragment', title).send(:parameters)[:content] - (content.split("\n") & expected_lines).should == expected_lines + expect(content.split("\n") & expected_lines).to eq(expected_lines) end diff --git a/horizon/spec/unit/puppet/parser/functions/os_any2array_spec.rb b/horizon/spec/unit/puppet/parser/functions/os_any2array_spec.rb index dd5bbe2c3..70a993981 100644 --- a/horizon/spec/unit/puppet/parser/functions/os_any2array_spec.rb +++ b/horizon/spec/unit/puppet/parser/functions/os_any2array_spec.rb @@ -5,51 +5,51 @@ let(:scope) { PuppetlabsSpec::PuppetInternals.scope } it "should exist" do - Puppet::Parser::Functions.function("os_any2array").should == "function_os_any2array" + expect(Puppet::Parser::Functions.function("os_any2array")).to eq("function_os_any2array") end it "should return an empty array if there is less than 1 argument" do result = scope.function_os_any2array([]) - result.should(eq([])) + expect(result).to(eq([])) end it "should convert boolean true to [ true ] " do result = scope.function_os_any2array([true]) - result.should(eq([true])) + expect(result).to(eq([true])) end it "should convert one object to [object]" do result = scope.function_os_any2array(['one']) - result.should(eq(['one'])) + expect(result).to(eq(['one'])) end it "should convert multiple objects to [objects]" do result = scope.function_os_any2array(['one', 'two']) - result.should(eq(['one', 'two'])) + expect(result).to(eq(['one', 'two'])) end it "should return empty array it was called with" do result = scope.function_os_any2array([[]]) - result.should(eq([])) + expect(result).to(eq([])) end it "should return one-member array it was called with" do result = scope.function_os_any2array([['string']]) - result.should(eq(['string'])) + expect(result).to(eq(['string'])) end it "should return multi-member array it was called with" do result = scope.function_os_any2array([['one', 'two']]) - result.should(eq(['one', 'two'])) + expect(result).to(eq(['one', 'two'])) end it "should return members of a hash it was called with" do result = scope.function_os_any2array([{ 'key' => 'value' }]) - result.should(eq(['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_os_any2array([{ }]) - result.should(eq([])) + expect(result).to(eq([])) end end diff --git a/horizon/templates/local_settings.py.erb b/horizon/templates/local_settings.py.erb index dbeb9e880..944c00ea4 100644 --- a/horizon/templates/local_settings.py.erb +++ b/horizon/templates/local_settings.py.erb @@ -202,6 +202,8 @@ OPENSTACK_NEUTRON_NETWORK = { 'enable_quotas': <%= @neutron_options['enable_quotas'].to_s.capitalize %>, 'enable_security_group': <%= @neutron_options['enable_security_group'].to_s.capitalize %>, 'enable_vpn': <%= @neutron_options['enable_vpn'].to_s.capitalize %>, + 'enable_distributed_router': <%= @neutron_options['enable_distributed_router'].to_s.capitalize %>, + 'enable_ha_router': <%= @neutron_options['enable_ha_router'].to_s.capitalize %>, # The profile_support option is used to detect if an externa lrouter can be # configured via the dashboard. When using specific plugins the # profile_support can be turned on if needed. diff --git a/keystone/.fixtures.yml b/keystone/.fixtures.yml index 066d4105e..73f11ff6c 100644 --- a/keystone/.fixtures.yml +++ b/keystone/.fixtures.yml @@ -1,7 +1,9 @@ fixtures: repositories: 'apache': 'git://github.com/puppetlabs/puppetlabs-apache.git' - 'concat': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'concat': + 'repo': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'ref': '1.2.1' 'apt': 'git://github.com/puppetlabs/puppetlabs-apt.git' 'mysql': 'git://github.com/puppetlabs/puppetlabs-mysql.git' 'openstacklib': 'git://github.com/stackforge/puppet-openstacklib.git' diff --git a/keystone/lib/puppet/provider/keystone.rb b/keystone/lib/puppet/provider/keystone.rb index b398a8e30..b5112290c 100644 --- a/keystone/lib/puppet/provider/keystone.rb +++ b/keystone/lib/puppet/provider/keystone.rb @@ -24,10 +24,10 @@ def keystone_request(service, action, object, credentials, error, *properties) def self.keystone_request(service, action, object, credentials, error, *properties) credentials = { - 'token' => get_admin_token, - 'auth_url' => get_admin_endpoint, + 'token' => get_admin_token, + 'url' => get_admin_endpoint, } - raise error unless (credentials['token'] && credentials['auth_url']) + raise error unless (credentials['token'] && credentials['url']) auth_args = token_auth_args(credentials) args = [object, properties, auth_args].flatten.compact authenticate_request(service, action, args) diff --git a/keystone/lib/puppet/provider/keystone_user/openstack.rb b/keystone/lib/puppet/provider/keystone_user/openstack.rb index 6dcf99586..6c8d04aa2 100644 --- a/keystone/lib/puppet/provider/keystone_user/openstack.rb +++ b/keystone/lib/puppet/provider/keystone_user/openstack.rb @@ -62,6 +62,8 @@ def password return nil if resource[:password] == nil # if the user is disabled then the password can't be changed return resource[:password] if resource[:enabled] == :false + # if replacing password is disabled, then don't change it + return resource[:password] if resource[:replace_password] == :false # we can't get the value of the password but we can test to see if the one we know # about works, if it doesn't then return nil, causing it to be reset endpoint = nil @@ -157,6 +159,14 @@ def tenant end end + def replace_password + instance(resource[:name])[:replace_password] + end + + def replace_password=(value) + @property_flush[:replace_password] = value + end + def email=(value) @property_flush[:email] = value end diff --git a/keystone/lib/puppet/type/keystone_user.rb b/keystone/lib/puppet/type/keystone_user.rb index e27f14cd6..ce3a5623d 100644 --- a/keystone/lib/puppet/type/keystone_user.rb +++ b/keystone/lib/puppet/type/keystone_user.rb @@ -61,6 +61,14 @@ def should_to_s( newvalue ) end end + newparam(:replace_password) do + newvalues(/(t|T)rue/, /(f|F)alse/, true, false) + defaultto(true) + munge do |value| + value.to_s.downcase.to_sym + end + end + autorequire(:keystone_tenant) do self[:tenant] end diff --git a/keystone/manifests/init.pp b/keystone/manifests/init.pp index cf27b1c0c..4750e165d 100644 --- a/keystone/manifests/init.pp +++ b/keystone/manifests/init.pp @@ -339,6 +339,10 @@ # (optional) The number of worker processes to serve the public WSGI application. # Defaults to max($::processorcount, 2) # +# [*sync_db*] +# (Optional) Run db sync on the node. +# Defaults to true +# # == Dependencies # None # @@ -438,6 +442,7 @@ $max_token_size = undef, $admin_workers = max($::processorcount, 2), $public_workers = max($::processorcount, 2), + $sync_db = true, # DEPRECATED PARAMETERS $mysql_module = undef, $compute_port = undef, @@ -805,7 +810,7 @@ fail('Invalid service_name. Either keystone/openstack-keystone for running as a standalone service, or httpd for being run by a httpd server') } - if $enabled { + if $enabled and $sync_db { include ::keystone::db::sync Class['::keystone::db::sync'] ~> Service[$service_name] } diff --git a/keystone/spec/classes/keystone_spec.rb b/keystone/spec/classes/keystone_spec.rb index f34ff7193..fe2c0033d 100644 --- a/keystone/spec/classes/keystone_spec.rb +++ b/keystone/spec/classes/keystone_spec.rb @@ -457,6 +457,17 @@ it { is_expected.to contain_keystone_config("token/expiration").with_value('3600') } end + describe 'when sync_db is set to false' do + let :params do + { + 'admin_token' => 'service_token', + 'sync_db' => false, + } + end + + it { is_expected.not_to contain_exec('keystone-manage db_sync') } + end + describe 'configure memcache servers if set' do let :params do { diff --git a/keystone/spec/unit/provider/keystone_endpoint/openstack_spec.rb b/keystone/spec/unit/provider/keystone_endpoint/openstack_spec.rb index a0ac7523e..d88f246ea 100644 --- a/keystone/spec/unit/provider/keystone_endpoint/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_endpoint/openstack_spec.rb @@ -16,10 +16,10 @@ :internal_url => 'http://127.0.0.1:5001/v2.0', :admin_url => 'http://127.0.0.1:5002/v2.0', :auth => { - 'username' => 'test', - 'password' => 'abc123', - 'tenant_name' => 'foo', - 'auth_url' => 'http://127.0.0.1:5000/v2.0', + 'username' => 'test', + 'password' => 'abc123', + 'project_name' => 'foo', + 'auth_url' => 'http://127.0.0.1:5000/v2.0', } } end @@ -35,12 +35,12 @@ describe '#create' do it 'creates an endpoint' do provider.class.stubs(:openstack) - .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL" "1cb05cfed7c24279be884ba4f6520262","foo","bar","","http://127.0.0.1:5000/v2.0","http://127.0.0.1:5001/v2.0","http://127.0.0.1:5002/v2.0" ') provider.class.stubs(:openstack) - .with('endpoint', 'create', '--format', 'shell', [['bar', '--region', 'foo', '--publicurl', 'http://127.0.0.1:5000/v2.0', '--internalurl', 'http://127.0.0.1:5001/v2.0', '--adminurl', 'http://127.0.0.1:5002/v2.0', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('endpoint', 'create', '--format', 'shell', [['bar', '--region', 'foo', '--publicurl', 'http://127.0.0.1:5000/v2.0', '--internalurl', 'http://127.0.0.1:5001/v2.0', '--adminurl', 'http://127.0.0.1:5002/v2.0', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('adminurl="http://127.0.0.1:5002/v2.0" id="3a5c4378981e4112a0d44902a43e16ef" internalurl="http://127.0.0.1:5001/v2.0" @@ -58,12 +58,12 @@ describe '#destroy' do it 'destroys an endpoint' do provider.class.stubs(:openstack) - .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL" "1cb05cfed7c24279be884ba4f6520262","foo","bar","","http://127.0.0.1:5000/v2.0","http://127.0.0.1:5001/v2.0","http://127.0.0.1:5002/v2.0" ') provider.class.stubs(:openstack) - .with('endpoint', 'delete', [['1cb05cfed7c24279be884ba4f6520262', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('endpoint', 'delete', [['1cb05cfed7c24279be884ba4f6520262', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) expect(provider.destroy).to be_nil # We don't really care that it's nil, only that it runs successfully end @@ -74,7 +74,7 @@ subject(:response) do provider.class.stubs(:openstack) - .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL" "1cb05cfed7c24279be884ba4f6520262","foo","bar","","http://127.0.0.1:5000/v2.0","http://127.0.0.1:5001/v2.0","http://127.0.0.1:5002/v2.0" ') @@ -88,7 +88,7 @@ subject(:response) do provider.class.stubs(:openstack) - .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL"') response = provider.exists? end @@ -100,7 +100,7 @@ describe '#instances' do it 'finds every tenant' do provider.class.stubs(:openstack) - .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('endpoint', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Region","Service Name","Service Type","PublicURL","AdminURL","InternalURL" "1cb05cfed7c24279be884ba4f6520262","foo","bar","","http://127.0.0.1:5000/v2.0","http://127.0.0.1:5001/v2.0","http://127.0.0.1:5002/v2.0" ') diff --git a/keystone/spec/unit/provider/keystone_role/openstack_spec.rb b/keystone/spec/unit/provider/keystone_role/openstack_spec.rb index 179574fea..13f877b97 100644 --- a/keystone/spec/unit/provider/keystone_role/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_role/openstack_spec.rb @@ -13,10 +13,10 @@ :name => 'foo', :ensure => 'present', :auth => { - 'username' => 'test', - 'password' => 'abc123', - 'tenant_name' => 'foo', - 'auth_url' => 'http://127.0.0.1:5000/v2.0', + 'username' => 'test', + 'password' => 'abc123', + 'project_name' => 'foo', + 'auth_url' => 'http://127.0.0.1:5000/v2.0', } } end @@ -32,12 +32,12 @@ describe '#create' do it 'creates a role' do provider.class.stubs(:openstack) - .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name" "1cb05cfed7c24279be884ba4f6520262","foo" ') provider.class.stubs(:openstack) - .with('role', 'create', '--format', 'shell', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'create', '--format', 'shell', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('name="foo"') provider.create expect(provider.exists?).to be_truthy @@ -47,10 +47,10 @@ describe '#destroy' do it 'destroys a role' do provider.class.stubs(:openstack) - .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name"') provider.class.stubs(:openstack) - .with('role', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.destroy expect(provider.exists?).to be_falsey end @@ -62,7 +62,7 @@ subject(:response) do provider.class.stubs(:openstack) - .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name" "1cb05cfed7c24279be884ba4f6520262","foo" ') @@ -76,7 +76,7 @@ subject(:response) do provider.class.stubs(:openstack) - .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name"') response = provider.exists? end @@ -88,7 +88,7 @@ describe '#instances' do it 'finds every role' do provider.class.stubs(:openstack) - .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name" "1cb05cfed7c24279be884ba4f6520262","foo" ') diff --git a/keystone/spec/unit/provider/keystone_service/openstack_spec.rb b/keystone/spec/unit/provider/keystone_service/openstack_spec.rb index 5b9814f91..622d000d8 100644 --- a/keystone/spec/unit/provider/keystone_service/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_service/openstack_spec.rb @@ -15,10 +15,10 @@ :ensure => 'present', :type => 'foo', :auth => { - 'username' => 'test', - 'password' => 'abc123', - 'tenant_name' => 'foo', - 'auth_url' => 'http://127.0.0.1:5000/v2.0', + 'username' => 'test', + 'password' => 'abc123', + 'project_name' => 'foo', + 'auth_url' => 'http://127.0.0.1:5000/v2.0', } } end @@ -34,12 +34,12 @@ describe '#create' do it 'creates a service' do provider.class.stubs(:openstack) - .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Type","Description" "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo" ') provider.class.stubs(:openstack) - .with('service', 'create', '--format', 'shell', [['foo', '--description', 'foo', '--type', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('service', 'create', '--format', 'shell', [['foo', '--description', 'foo', '--type', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('description="foo" enabled="True" id="8f0dd4c0abc44240998fbb3f5089ecbf" @@ -54,10 +54,10 @@ describe '#destroy' do it 'destroys a service' do provider.class.stubs(:openstack) - .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Type","Description"') provider.class.stubs(:openstack) - .with('service', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('service', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.destroy expect(provider.exists?).to be_falsey end @@ -69,7 +69,7 @@ subject(:response) do provider.class.stubs(:openstack) - .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Type","Description" "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo" ') @@ -83,7 +83,7 @@ subject(:response) do provider.class.stubs(:openstack) - .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Type","Description"') response = provider.exists? end @@ -95,7 +95,7 @@ describe '#instances' do it 'finds every service' do provider.class.stubs(:openstack) - .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('service', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Type","Description" "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo" ') diff --git a/keystone/spec/unit/provider/keystone_tenant/openstack_spec.rb b/keystone/spec/unit/provider/keystone_tenant/openstack_spec.rb index 11861fc8b..fe7d73b26 100644 --- a/keystone/spec/unit/provider/keystone_tenant/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_tenant/openstack_spec.rb @@ -15,10 +15,10 @@ :ensure => 'present', :enabled => 'True', :auth => { - 'username' => 'test', - 'password' => 'abc123', - 'tenant_name' => 'foo', - 'auth_url' => 'http://127.0.0.1:5000/v2.0', + 'username' => 'test', + 'password' => 'abc123', + 'project_name' => 'foo', + 'auth_url' => 'http://127.0.0.1:5000/v2.0', } } end @@ -34,12 +34,12 @@ describe '#create' do it 'creates a tenant' do provider.class.stubs(:openstack) - .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Description","Enabled" "1cb05cfed7c24279be884ba4f6520262","foo","foo",True ') provider.class.stubs(:openstack) - .with('project', 'create', '--format', 'shell', [['foo', '--enable', '--description', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('project', 'create', '--format', 'shell', [['foo', '--enable', '--description', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('description="foo" enabled="True" name="foo" @@ -52,10 +52,10 @@ describe '#destroy' do it 'destroys a tenant' do provider.class.stubs(:openstack) - .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Description","Enabled"') provider.class.stubs(:openstack) - .with('project', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('project', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.destroy expect(provider.exists?).to be_falsey end @@ -67,7 +67,7 @@ subject(:response) do provider.class.stubs(:openstack) - .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Description","Enabled" "1cb05cfed7c24279be884ba4f6520262","foo","foo",True ') @@ -81,7 +81,7 @@ subject(:response) do provider.class.stubs(:openstack) - .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Description","Enabled"') response = provider.exists? end @@ -93,7 +93,7 @@ describe '#instances' do it 'finds every tenant' do provider.class.stubs(:openstack) - .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Description","Enabled" "1cb05cfed7c24279be884ba4f6520262","foo","foo",True ') diff --git a/keystone/spec/unit/provider/keystone_user/openstack_spec.rb b/keystone/spec/unit/provider/keystone_user/openstack_spec.rb index 5b87ca18e..51d1dfce2 100644 --- a/keystone/spec/unit/provider/keystone_user/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_user/openstack_spec.rb @@ -15,10 +15,10 @@ :tenant => 'foo', :email => 'foo@example.com', :auth => { - 'username' => 'test', - 'password' => 'abc123', - 'tenant_name' => 'foo', - 'auth_url' => 'http://127.0.0.1:5000/v2.0', + 'username' => 'test', + 'password' => 'abc123', + 'project_name' => 'foo', + 'auth_url' => 'http://127.0.0.1:5000/v2.0', } } end @@ -36,12 +36,12 @@ describe '#create' do it 'creates a user' do provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","Email","Enabled" "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True ') provider.class.stubs(:openstack) - .with('user', 'create', '--format', 'shell', [['foo', '--enable', '--password', 'foo', '--project', 'foo', '--email', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'create', '--format', 'shell', [['foo', '--enable', '--password', 'foo', '--project', 'foo', '--email', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('email="foo@example.com" enabled="True" id="12b23f07d4a3448d8189521ab09610b0" @@ -57,10 +57,10 @@ describe '#destroy' do it 'destroys a user' do provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","Email","Enabled"') provider.class.stubs(:openstack) - .with('user', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'delete', [['foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.destroy expect(provider.exists?).to be_falsey end @@ -72,7 +72,7 @@ subject(:response) do provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","Email","Enabled" "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True ') @@ -86,7 +86,7 @@ subject(:response) do provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","Email","Enabled"') response = provider.exists? end @@ -98,7 +98,7 @@ describe '#instances' do it 'finds every user' do provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","Email","Enabled" "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True ') @@ -110,7 +110,7 @@ describe '#tenant' do it 'gets the tenant with default backend' do provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","Email","Enabled" "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True ') @@ -119,12 +119,12 @@ end it 'gets the tenant with LDAP backend' do provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","Email","Enabled" "1cb05cfed7c24279be884ba4f6520262","foo","","foo@example.com",True ') provider.class.expects(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","User" "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo" ') @@ -136,9 +136,9 @@ context 'when using default backend' do it 'sets the tenant' do provider.class.expects(:openstack) - .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.class.expects(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","User" "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo" ') @@ -148,52 +148,52 @@ context 'when using LDAP read-write backend' do it 'sets the tenant when _member_ role exists' do provider.class.expects(:openstack) - .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.class.expects(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('') provider.class.expects(:openstack) - .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('name="_member_"') provider.class.expects(:openstack) - .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.tenant=('bar') end it 'sets the tenant when _member_ role does not exist' do provider.class.expects(:openstack) - .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.class.expects(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('') provider.class.expects(:openstack) - .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .raises(Puppet::ExecutionFailure, 'no such role _member_') provider.class.expects(:openstack) - .with('role', 'create', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'create', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('name="_member_"') provider.class.expects(:openstack) - .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.tenant=('bar') end end context 'when using LDAP read-only backend' do it 'sets the tenant when _member_ role exists' do provider.class.expects(:openstack) - .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .raises(Puppet::ExecutionFailure, 'You are not authorized to perform the requested action: LDAP user update') provider.class.expects(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user role', 'list', '--quiet', '--format', 'csv', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('') provider.class.expects(:openstack) - .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'show', '--format', 'shell', [['_member_', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('name="_member_"') provider.class.expects(:openstack) - .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.tenant=('bar') end it 'sets the tenant and gets an unexpected exception message' do provider.class.expects(:openstack) - .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'set', [['foo', '--project', 'bar', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .raises(Puppet::ExecutionFailure, 'unknown error message') expect{ provider.tenant=('bar') }.to raise_error(Puppet::ExecutionFailure, /unknown error message/) end @@ -212,10 +212,10 @@ :tenant => 'foo', :email => 'foo@example.com', :auth => { - 'username' => 'test', - 'password' => 'abc123', - 'tenant_name' => 'foo', - 'auth_url' => 'https://127.0.0.1:5000/v2.0', + 'username' => 'test', + 'password' => 'abc123', + 'project_name' => 'foo', + 'auth_url' => 'https://127.0.0.1:5000/v2.0', } } end @@ -250,5 +250,39 @@ password = provider.password expect(password).to eq(nil) end + + describe 'when updating a user with unmanaged password' do + + let(:user_attrs) do + { + :name => 'foo', + :ensure => 'present', + :enabled => 'True', + :password => 'foo', + :replace_password => 'False', + :tenant => 'foo', + :email => 'foo@example.com', + :auth => { + 'username' => 'test', + 'password' => 'abc123', + 'tenant_name' => 'foo', + 'auth_url' => 'http://127.0.0.1:5000/v2.0', + } + } + end + + let(:resource) do + Puppet::Type::Keystone_user.new(user_attrs) + end + + let :provider do + provider_class.new(resource) + end + + it 'should not try to check password' do + expect(provider.password).to eq('foo') + end + end + end end diff --git a/keystone/spec/unit/provider/keystone_user_role/openstack_spec.rb b/keystone/spec/unit/provider/keystone_user_role/openstack_spec.rb index f3c35dcf6..1be2bd64f 100644 --- a/keystone/spec/unit/provider/keystone_user_role/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_user_role/openstack_spec.rb @@ -14,10 +14,10 @@ :ensure => 'present', :roles => ['foo', 'bar'], :auth => { - 'username' => 'test', - 'password' => 'abc123', - 'tenant_name' => 'foo', - 'auth_url' => 'http://127.0.0.1:5000/v2.0', + 'username' => 'test', + 'password' => 'abc123', + 'project_name' => 'foo', + 'auth_url' => 'http://127.0.0.1:5000/v2.0', } } end @@ -32,12 +32,12 @@ before(:each) do provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name" "1cb05cfed7c24279be884ba4f6520262","foo@example.com" ') provider.class.stubs(:openstack) - .with('project', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('project', 'list', '--quiet', '--format', 'csv', [['--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name" "1cb05cfed7c24279be884ba4f6520262","foo" ') @@ -46,15 +46,15 @@ describe '#create' do it 'adds all the roles to the user' do provider.class.stubs(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user role', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","User" "1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com" "1cb05cfed7c24279be884ba4f6520263","bar","foo","foo@example.com" ') provider.class.stubs(:openstack) - .with('role', 'add', [['foo', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'add', [['foo', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.class.stubs(:openstack) - .with('role', 'add', [['bar', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'add', [['bar', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.create expect(provider.exists?).to be_truthy end @@ -63,12 +63,12 @@ describe '#destroy' do it 'removes all the roles from a user' do provider.class.stubs(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user role', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","User"') provider.class.stubs(:openstack) - .with('role', 'remove', [['foo', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'remove', [['foo', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.class.stubs(:openstack) - .with('role', 'remove', [['bar', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('role', 'remove', [['bar', '--project', 'foo', '--user', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) provider.destroy expect(provider.exists?).to be_falsey end @@ -78,7 +78,7 @@ describe '#exists' do subject(:response) do provider.class.stubs(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('user role', 'list', '--quiet', '--format', 'csv', [['--project', 'foo', 'foo@example.com', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'foo', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Project","User" "1cb05ed7c24279be884ba4f6520262","foo","foo","foo@example.com" "1cb05ed7c24279be884ba4f6520262","bar","foo","foo@example.com" diff --git a/manila/.fixtures.yml b/manila/.fixtures.yml index d123fc253..1faf718fa 100644 --- a/manila/.fixtures.yml +++ b/manila/.fixtures.yml @@ -1,7 +1,9 @@ fixtures: repositories: 'apt': 'git://github.com/puppetlabs/puppetlabs-apt.git' - 'concat': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'concat': + 'repo': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'ref': '1.2.1' 'inifile': 'git://github.com/puppetlabs/puppetlabs-inifile' 'keystone': 'git://github.com/stackforge/puppet-keystone.git' 'glance': 'git://github.com/stackforge/puppet-glance.git' diff --git a/module-collectd/.gitignore b/module-collectd/.gitignore index 7cc4f8287..00f205494 100644 --- a/module-collectd/.gitignore +++ b/module-collectd/.gitignore @@ -1,5 +1,4 @@ pkg/ -Gemfile.lock .rspec_system *.swp .bundle/ diff --git a/module-collectd/Gemfile.lock b/module-collectd/Gemfile.lock new file mode 100644 index 000000000..3e406d83c --- /dev/null +++ b/module-collectd/Gemfile.lock @@ -0,0 +1,232 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (2.2.8) + activesupport (4.2.0) + 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.6) + archive-tar-minitar (0.5.2) + autoparse (0.3.3) + addressable (>= 2.3.1) + extlib (>= 0.9.15) + multi_json (>= 1.0.0) + aws-sdk (1.60.2) + aws-sdk-v1 (= 1.60.2) + aws-sdk-v1 (1.60.2) + json (~> 1.4) + nokogiri (>= 1.4.4) + beaker (2.1.0) + aws-sdk (~> 1.57) + docker-api + fission (~> 0.4) + fog (~> 1.25) + google-api-client (~> 0.7) + hocon (~> 0.0.4) + inifile (~> 2.0) + json (~> 1.8) + minitest (~> 5.4) + net-scp (~> 1.2) + net-ssh (~> 2.9) + rbvmomi (~> 1.8) + unf (~> 0.1) + beaker-rspec (4.0.0) + beaker (~> 2.0) + rspec + serverspec (~> 1.0) + specinfra (~> 1.0) + builder (3.2.2) + diff-lcs (1.2.5) + docile (1.1.5) + docker-api (1.17.0) + archive-tar-minitar + excon (>= 0.38.0) + json + excon (0.42.1) + extlib (0.9.16) + facter (2.3.0) + CFPropertyList (~> 2.2.6) + faraday (0.9.0) + multipart-post (>= 1.2, < 3) + fission (0.5.0) + CFPropertyList (~> 2.2) + fog (1.26.0) + fog-atmos + fog-brightbox (~> 0.4) + fog-core (~> 1.27, >= 1.27.1) + fog-ecloud + fog-json + fog-profitbricks + fog-radosgw (>= 0.0.2) + fog-sakuracloud (>= 0.0.4) + 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-brightbox (0.7.1) + fog-core (~> 1.22) + fog-json + inflecto (~> 0.0.2) + fog-core (1.27.2) + builder + excon (~> 0.38) + formatador (~> 0.2) + mime-types + net-scp (~> 1.1) + net-ssh (>= 2.1.3) + fog-ecloud (0.0.2) + fog-core + fog-xml + fog-json (1.0.0) + multi_json (~> 1.0) + fog-profitbricks (0.0.1) + fog-core + fog-xml + nokogiri + fog-radosgw (0.0.3) + fog-core (>= 1.21.0) + fog-json + fog-xml (>= 0.0.1) + fog-sakuracloud (0.1.1) + fog-core + fog-json + fog-softlayer (0.3.26) + fog-core + fog-json + fog-storm_on_demand (0.1.0) + fog-core + fog-json + fog-terremark (0.0.3) + fog-core + fog-xml + fog-vmfusion (0.0.1) + fission + fog-core + fog-voxel (0.0.2) + fog-core + fog-xml + fog-xml (0.1.1) + fog-core + nokogiri (~> 1.5, >= 1.5.11) + formatador (0.2.5) + google-api-client (0.8.1.1) + activesupport (>= 3.2) + addressable (~> 2.3) + autoparse (~> 0.3) + extlib (~> 0.9) + faraday (~> 0.9) + launchy (~> 2.4) + multi_json (~> 1.10) + retriable (~> 1.4) + signet (~> 0.6) + hiera (1.3.4) + json_pure + highline (1.6.21) + hocon (0.0.6) + i18n (0.7.0) + inflecto (0.0.2) + inifile (2.0.2) + ipaddress (0.8.0) + json (1.8.1) + json_pure (1.8.1) + jwt (1.2.0) + launchy (2.4.3) + addressable (~> 2.3) + metaclass (0.0.4) + mime-types (2.4.3) + mini_portile (0.6.1) + minitest (5.5.0) + mocha (1.1.0) + metaclass (~> 0.0.1) + multi_json (1.10.1) + multipart-post (2.0.0) + net-scp (1.2.1) + net-ssh (>= 2.6.5) + net-ssh (2.9.1) + nokogiri (1.6.5) + mini_portile (~> 0.6.0) + puppet (3.7.3) + facter (> 1.6, < 3) + hiera (~> 1.0) + json_pure + puppet-lint (1.1.0) + puppet-syntax (1.4.0) + rake + puppet_facts (0.2.1) + puppetlabs_spec_helper (0.8.2) + mocha + puppet-lint + puppet-syntax + rake + rspec + rspec-puppet + rake (10.4.2) + rbvmomi (1.8.2) + builder + nokogiri (>= 1.4.1) + trollop + 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.2) + rspec-puppet (1.0.1) + rspec + serverspec (1.16.0) + highline + net-ssh + rspec (~> 2.99) + rspec-its + specinfra (~> 1.27) + signet (0.6.0) + addressable (~> 2.3) + extlib (~> 0.9) + faraday (~> 0.9) + jwt (~> 1.0) + multi_json (~> 1.10) + simplecov (0.9.1) + docile (~> 1.1.0) + multi_json (~> 1.0) + simplecov-html (~> 0.8.0) + simplecov-html (0.8.0) + specinfra (1.27.5) + thread_safe (0.3.4) + trollop (2.0) + tzinfo (1.2.2) + thread_safe (~> 0.1) + unf (0.1.4) + unf_ext + unf_ext (0.0.6) + +PLATFORMS + ruby + +DEPENDENCIES + beaker-rspec + facter + json + puppet + puppet-lint + puppet_facts + puppetlabs_spec_helper + rake + rspec-puppet + serverspec + simplecov diff --git a/module-collectd/README.md b/module-collectd/README.md index d540a6acc..03b611fea 100644 --- a/module-collectd/README.md +++ b/module-collectd/README.md @@ -908,6 +908,10 @@ class { 'collectd::plugin::zfs_arc': See metadata.json for supported platforms +##Known issues + +Some plugins will need two runs of Puppet to fully generate the configuration for collectd. See [this issue](https://github.com/pdxcat/puppet-module-collectd/issues/162). + ##Development ### Running tests @@ -923,3 +927,13 @@ bundle exec rake lint bundle exec rake validate bundle exec rake spec SPEC_OPTS='--format documentation' ``` + +### Version scoping + +Some plugins or some options in plugins are only available for recent versions of collectd. + +This module shall not use unsupported configuration directives. Look at [templates/loadplugin.conf.erb](https://github.com/pdxcat/puppet-module-collectd/blob/master/templates/loadplugin.conf.erb) for a hands-on example. + +Please make use of the search by branch/tags on the collectd github to see when a function has been first released. + +Reading the [collectd.conf.pod](https://github.com/collectd/collectd/blob/master/src/collectd.conf.pod) file is good, validating the presence of the code in the .c files is even better. \ No newline at end of file diff --git a/module-collectd/Rakefile b/module-collectd/Rakefile index 902062317..a64429cae 100644 --- a/module-collectd/Rakefile +++ b/module-collectd/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('disable_80chars') PuppetLint.configuration.send('disable_class_inherits_from_params_class') PuppetLint.configuration.send('disable_class_parameter_defaults') diff --git a/module-collectd/manifests/plugin/curl_json.pp b/module-collectd/manifests/plugin/curl_json.pp index b571b4a1f..f571bb9c4 100644 --- a/module-collectd/manifests/plugin/curl_json.pp +++ b/module-collectd/manifests/plugin/curl_json.pp @@ -3,6 +3,7 @@ $url, $instance, $keys, + $ensure = present, $user = undef, $password = undef, $order = '10', diff --git a/module-collectd/manifests/plugin/exec.pp b/module-collectd/manifests/plugin/exec.pp index 873dac9f5..f9317db79 100644 --- a/module-collectd/manifests/plugin/exec.pp +++ b/module-collectd/manifests/plugin/exec.pp @@ -16,8 +16,8 @@ # This is deprecated file naming ensuring old style file removed, and should be removed in next major relese file { "${name}.load-deprecated": - path => "${conf_dir}/${name}.conf", ensure => absent, + path => "${conf_dir}/${name}.conf", } # End deprecation diff --git a/module-collectd/manifests/plugin/genericjmx/connection.pp b/module-collectd/manifests/plugin/genericjmx/connection.pp index 23d475acb..b08432e37 100644 --- a/module-collectd/manifests/plugin/genericjmx/connection.pp +++ b/module-collectd/manifests/plugin/genericjmx/connection.pp @@ -1,11 +1,11 @@ # https://collectd.org/wiki/index.php/Plugin:GenericJMX define collectd::plugin::genericjmx::connection ( - $host = $name, + $collect, $service_url, + $host = $name, $user = undef, $password = undef, $instance_prefix = undef, - $collect, ) { include collectd::plugin::genericjmx concat::fragment { "collectd_plugin_genericjmx_conf_${name}": diff --git a/module-collectd/manifests/plugin/genericjmx/mbean.pp b/module-collectd/manifests/plugin/genericjmx/mbean.pp index 68f0e1435..98aa2d33d 100644 --- a/module-collectd/manifests/plugin/genericjmx/mbean.pp +++ b/module-collectd/manifests/plugin/genericjmx/mbean.pp @@ -1,9 +1,9 @@ # https://collectd.org/wiki/index.php/Plugin:GenericJMX define collectd::plugin::genericjmx::mbean ( $object_name, + $values, $instance_prefix = undef, $instance_from = undef, - $values, ) { include collectd::plugin::genericjmx validate_array($values) diff --git a/module-collectd/manifests/plugin/mysql.pp b/module-collectd/manifests/plugin/mysql.pp index 4dcd03895..f8573a9bd 100644 --- a/module-collectd/manifests/plugin/mysql.pp +++ b/module-collectd/manifests/plugin/mysql.pp @@ -1,6 +1,7 @@ # MySQL plugin # https://collectd.org/wiki/index.php/Plugin:MySQL class collectd::plugin::mysql ( + $ensure = present, $interval = undef, ){ diff --git a/module-collectd/manifests/plugin/mysql/database.pp b/module-collectd/manifests/plugin/mysql/database.pp index 9216e9a02..e736ea1e5 100644 --- a/module-collectd/manifests/plugin/mysql/database.pp +++ b/module-collectd/manifests/plugin/mysql/database.pp @@ -28,7 +28,7 @@ file { "${name}.conf": ensure => $ensure, path => "${conf_dir}/mysql-${name}.conf", - mode => '0644', + mode => '0640', owner => 'root', group => $collectd::params::root_group, content => template('collectd/mysql-database.conf.erb'), diff --git a/module-collectd/manifests/plugin/network/server.pp b/module-collectd/manifests/plugin/network/server.pp index 8e5aad589..c271b5e31 100644 --- a/module-collectd/manifests/plugin/network/server.pp +++ b/module-collectd/manifests/plugin/network/server.pp @@ -6,6 +6,7 @@ $port = undef, $securitylevel = undef, $interface = undef, + $forward = undef, ) { include collectd::params include collectd::plugin::network diff --git a/module-collectd/manifests/plugin/ping.pp b/module-collectd/manifests/plugin/ping.pp index 88c4411f2..eee249bc2 100644 --- a/module-collectd/manifests/plugin/ping.pp +++ b/module-collectd/manifests/plugin/ping.pp @@ -1,6 +1,7 @@ # See http://collectd.org/documentation/manpages/collectd.conf.5.shtml#plugin_ping define collectd::plugin::ping ( $hosts, + $ensure = present, $interval = undef, $timeout = undef, $ttl = undef, diff --git a/module-collectd/manifests/plugin/snmp/data.pp b/module-collectd/manifests/plugin/snmp/data.pp index 116221edb..097e17255 100644 --- a/module-collectd/manifests/plugin/snmp/data.pp +++ b/module-collectd/manifests/plugin/snmp/data.pp @@ -1,10 +1,10 @@ # https://collectd.org/wiki/index.php/Plugin:SNMP define collectd::plugin::snmp::data ( - $ensure = present, - $type, - $table = false, $instance, + $type, $values, + $ensure = present, + $table = false, ) { include collectd include collectd::plugin::snmp diff --git a/module-collectd/manifests/plugin/snmp/host.pp b/module-collectd/manifests/plugin/snmp/host.pp index 698163139..03495f723 100644 --- a/module-collectd/manifests/plugin/snmp/host.pp +++ b/module-collectd/manifests/plugin/snmp/host.pp @@ -1,10 +1,10 @@ # https://collectd.org/wiki/index.php/Plugin:SNMP define collectd::plugin::snmp::host ( + $collect, $ensure = present, $address = $name, $version = 1, $community = 'public', - $collect, $interval = undef, ) { include collectd diff --git a/module-collectd/templates/plugin/network/server.conf.erb b/module-collectd/templates/plugin/network/server.conf.erb index daab982ba..417bf0674 100644 --- a/module-collectd/templates/plugin/network/server.conf.erb +++ b/module-collectd/templates/plugin/network/server.conf.erb @@ -17,4 +17,7 @@ <% else -%> Server "<%= @name %>" "<%= @port %>" <% end -%> +<% if ! @forward.nil? -%> + Forward <%= @forward %> +<% end -%> diff --git a/module-collectd/templates/plugin/rrdcached.conf.erb b/module-collectd/templates/plugin/rrdcached.conf.erb index b469924d8..92917a88f 100644 --- a/module-collectd/templates/plugin/rrdcached.conf.erb +++ b/module-collectd/templates/plugin/rrdcached.conf.erb @@ -2,10 +2,10 @@ DaemonAddress "<%= @daemonaddress %>" DataDir "<%= @datadir %>" <% unless @createfiles.nil? -%> - CreateFiles "<%= @createfiles %>" + CreateFiles <%= @createfiles %> <% end -%> <% unless @createfilesasync.nil? -%> - CreateFilesAsync "<%= @createfilesasync %>" + CreateFilesAsync <%= @createfilesasync %> <% end -%> <% if @stepsize -%> StepSize "<%= @stepsize %>" diff --git a/module-collectd/tests/plugins/iptables.pp b/module-collectd/tests/plugins/iptables.pp index fac2e3a5c..e1fec41d7 100644 --- a/module-collectd/tests/plugins/iptables.pp +++ b/module-collectd/tests/plugins/iptables.pp @@ -1,7 +1,7 @@ include collectd class { 'collectd::plugin::iptables': - chains => { + chains => { 'nat' => 'In_SSH', 'filter' => 'HTTP' }, diff --git a/module-collectd/tests/plugins/mysql.pp b/module-collectd/tests/plugins/mysql.pp index 6c5f4d6e0..7eafd4f6b 100644 --- a/module-collectd/tests/plugins/mysql.pp +++ b/module-collectd/tests/plugins/mysql.pp @@ -1,8 +1,8 @@ include collectd collectd::plugin::mysql::database { 'puppetdb': - host => 'localhost', - username => 'stahmna', - password => 'yermom', - port => '3306', + host => 'localhost', + username => 'stahmna', + password => 'yermom', + port => '3306', } diff --git a/module-collectd/tests/plugins/perl.pp b/module-collectd/tests/plugins/perl.pp index 55672845b..cf5c1554e 100644 --- a/module-collectd/tests/plugins/perl.pp +++ b/module-collectd/tests/plugins/perl.pp @@ -16,8 +16,8 @@ destination => '/tmp', order => 99, config => { - 'foo' => 'bar', - 'key' => [ 'val1', 'val2' ], + 'foo' => 'bar', + 'key' => [ 'val1', 'val2' ], } } @@ -37,17 +37,17 @@ collectd::plugin::perl::plugin { 'baar': - module => 'Collectd::Plugins::Bar', - provider => 'package', - source => 'perl-Collectd-Plugins-Bar', - config => { - 'foo' => 'bar', - 'more' => { + module => 'Collectd::Plugins::Bar', + provider => 'package', + source => 'perl-Collectd-Plugins-Bar', + config => { + 'foo' => 'bar', + 'more' => { 'complex' => 'structure', 'no' => [ 'a', 'b' ], 'yes' => { - 'last' => 'level', - 'and' => [ 'array' , 'thing' ] + 'last' => 'level', + 'and' => [ 'array' , 'thing' ] }, }, }, diff --git a/module-collectd/tests/purge_config.pp b/module-collectd/tests/purge_config.pp index 4ca79ff7c..858dcc403 100644 --- a/module-collectd/tests/purge_config.pp +++ b/module-collectd/tests/purge_config.pp @@ -1,7 +1,7 @@ class { 'collectd': - purge => true, - recurse => true, - purge_config => true, + purge => true, + recurse => true, + purge_config => true, } diff --git a/mysql/manifests/backup/mysqlbackup.pp b/mysql/manifests/backup/mysqlbackup.pp index a3a722208..9d92b6c0e 100644 --- a/mysql/manifests/backup/mysqlbackup.pp +++ b/mysql/manifests/backup/mysqlbackup.pp @@ -1,27 +1,26 @@ # See README.me for usage. class mysql::backup::mysqlbackup ( - $backupuser, - $backuppassword, - $backupdir, - $backupdirmode = '0700', - $backupdirowner = 'root', - $backupdirgroup = 'root', - $backupcompress = true, - $backuprotate = 30, - $ignore_events = true, + $backupuser = '', + $backuppassword = '', + $backupdir = '', + $backupdirmode = '0700', + $backupdirowner = 'root', + $backupdirgroup = $mysql::params::root_group, + $backupcompress = true, + $backuprotate = 30, + $ignore_events = true, $delete_before_dump = false, - $backupdatabases = [], - $file_per_database = false, - $ensure = 'present', - $time = ['23', '5'], - $postscript = false, - $execpath = '/usr/bin:/usr/sbin:/bin:/sbin', + $backupdatabases = [], + $file_per_database = false, + $ensure = 'present', + $time = ['23', '5'], + $postscript = false, + $execpath = '/usr/bin:/usr/sbin:/bin:/sbin', ) { mysql_user { "${backupuser}@localhost": ensure => $ensure, password_hash => mysql_password($backuppassword), - provider => 'mysql', require => Class['mysql::server::root_password'], } diff --git a/mysql/manifests/backup/mysqldump.pp b/mysql/manifests/backup/mysqldump.pp index 89ec32f1e..51f912c5d 100644 --- a/mysql/manifests/backup/mysqldump.pp +++ b/mysql/manifests/backup/mysqldump.pp @@ -1,27 +1,26 @@ # See README.me for usage. class mysql::backup::mysqldump ( - $backupuser, - $backuppassword, - $backupdir, - $backupdirmode = '0700', - $backupdirowner = 'root', - $backupdirgroup = 'root', - $backupcompress = true, - $backuprotate = 30, - $ignore_events = true, + $backupuser = '', + $backuppassword = '', + $backupdir = '', + $backupdirmode = '0700', + $backupdirowner = 'root', + $backupdirgroup = $mysql::params::root_group, + $backupcompress = true, + $backuprotate = 30, + $ignore_events = true, $delete_before_dump = false, - $backupdatabases = [], - $file_per_database = false, - $ensure = 'present', - $time = ['23', '5'], - $postscript = false, - $execpath = '/usr/bin:/usr/sbin:/bin:/sbin', + $backupdatabases = [], + $file_per_database = false, + $ensure = 'present', + $time = ['23', '5'], + $postscript = false, + $execpath = '/usr/bin:/usr/sbin:/bin:/sbin', ) { mysql_user { "${backupuser}@localhost": ensure => $ensure, password_hash => mysql_password($backuppassword), - provider => 'mysql', require => Class['mysql::server::root_password'], } @@ -47,7 +46,7 @@ path => '/usr/local/sbin/mysqlbackup.sh', mode => '0700', owner => 'root', - group => 'root', + group => $mysql::params::root_group, content => template('mysql/mysqlbackup.sh.erb'), } diff --git a/mysql/manifests/backup/xtrabackup.pp b/mysql/manifests/backup/xtrabackup.pp index 37eb1a7af..fb4ed6203 100644 --- a/mysql/manifests/backup/xtrabackup.pp +++ b/mysql/manifests/backup/xtrabackup.pp @@ -1,28 +1,27 @@ # See README.me for usage. class mysql::backup::xtrabackup ( - $backupuser, - $backuppassword, - $backupdir, - $backupmethod = 'mysqldump', - $backupdirmode = '0700', - $backupdirowner = 'root', - $backupdirgroup = 'root', - $backupcompress = true, - $backuprotate = 30, - $ignore_events = true, + $backupuser = '', + $backuppassword = '', + $backupdir = '', + $backupmethod = 'mysqldump', + $backupdirmode = '0700', + $backupdirowner = 'root', + $backupdirgroup = $mysql::params::root_group, + $backupcompress = true, + $backuprotate = 30, + $ignore_events = true, $delete_before_dump = false, - $backupdatabases = [], - $file_per_database = false, - $ensure = 'present', - $time = ['23', '5'], - $postscript = false, - $execpath = '/usr/bin:/usr/sbin:/bin:/sbin', + $backupdatabases = [], + $file_per_database = false, + $ensure = 'present', + $time = ['23', '5'], + $postscript = false, + $execpath = '/usr/bin:/usr/sbin:/bin:/sbin', ) { mysql_user { "${backupuser}@localhost": ensure => $ensure, password_hash => mysql_password($backuppassword), - provider => 'mysql', require => Class['mysql::server::root_password'], } diff --git a/mysql/manifests/client/install.pp b/mysql/manifests/client/install.pp index 8ffff5b0c..26e5ec276 100644 --- a/mysql/manifests/client/install.pp +++ b/mysql/manifests/client/install.pp @@ -1,3 +1,4 @@ +# See README.md. class mysql::client::install { if $mysql::client::package_manage { diff --git a/mysql/manifests/server/account_security.pp b/mysql/manifests/server/account_security.pp index 07bdf0133..252572e88 100644 --- a/mysql/manifests/server/account_security.pp +++ b/mysql/manifests/server/account_security.pp @@ -1,3 +1,4 @@ +# See README.md. class mysql::server::account_security { mysql_user { [ 'root@127.0.0.1', diff --git a/mysql/manifests/server/monitor.pp b/mysql/manifests/server/monitor.pp index 9e86b92c7..6b1860983 100644 --- a/mysql/manifests/server/monitor.pp +++ b/mysql/manifests/server/monitor.pp @@ -1,8 +1,8 @@ #This is a helper class to add a monitoring user to the database class mysql::server::monitor ( - $mysql_monitor_username, - $mysql_monitor_password, - $mysql_monitor_hostname + $mysql_monitor_username = '', + $mysql_monitor_password = '', + $mysql_monitor_hostname = '' ) { Anchor['mysql::server::end'] -> Class['mysql::server::monitor'] diff --git a/mysql/manifests/server/service.pp b/mysql/manifests/server/service.pp index 30ff300aa..4d33def68 100644 --- a/mysql/manifests/server/service.pp +++ b/mysql/manifests/server/service.pp @@ -18,10 +18,12 @@ $mysqluser = $options['mysqld']['user'] } - file { $options['mysqld']['log-error']: - ensure => present, - owner => $mysqluser, - group => $::mysql::server::mysql_group, + if $options['mysqld']['log-error'] { + file { $options['mysqld']['log-error']: + ensure => present, + owner => $mysqluser, + group => $::mysql::server::mysql_group, + } } service { 'mysqld': diff --git a/mysql/spec/acceptance/mysql_server_spec.rb b/mysql/spec/acceptance/mysql_server_spec.rb index 06646cbbe..f41e04cad 100644 --- a/mysql/spec/acceptance/mysql_server_spec.rb +++ b/mysql/spec/acceptance/mysql_server_spec.rb @@ -51,5 +51,18 @@ class { 'mysql::server': apply_manifest(pp, :catch_changes => true) end end + + describe 'configuration needed for syslog' do + it 'should work with no errors' do + pp = <<-EOS + class { 'mysql::server': + override_options => { 'mysqld' => { 'log-error' => undef }, 'mysqld_safe' => { 'log-error' => false, 'syslog' => true }}, + } + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + end end diff --git a/mysql/templates/mysqlbackup.sh.erb b/mysql/templates/mysqlbackup.sh.erb index e3ab7cc28..21482087f 100755 --- a/mysql/templates/mysqlbackup.sh.erb +++ b/mysql/templates/mysqlbackup.sh.erb @@ -1,4 +1,8 @@ +<%- if @kernel == 'Linux' -%> #!/bin/bash +<%- else -%> +#!/bin/sh +<%- end -%> # # MySQL Backup Script # Dumps mysql databases to a file for another backup tool to pick up. @@ -27,7 +31,9 @@ PATH=<%= @execpath %> +<%- if @kernel == 'Linux' -%> set -o pipefail +<%- end -%> cleanup() { diff --git a/nova/.fixtures.yml b/nova/.fixtures.yml index 782b316a4..af20848b4 100644 --- a/nova/.fixtures.yml +++ b/nova/.fixtures.yml @@ -1,7 +1,9 @@ fixtures: repositories: 'cinder': 'git://github.com/stackforge/puppet-cinder.git' - 'concat': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'concat': + 'repo': 'git://github.com/puppetlabs/puppetlabs-concat.git' + 'ref': '1.2.1' 'inifile': 'git://github.com/puppetlabs/puppetlabs-inifile' 'keystone': 'git://github.com/stackforge/puppet-keystone.git' 'mysql': 'git://github.com/puppetlabs/puppetlabs-mysql.git' diff --git a/nova/manifests/compute.pp b/nova/manifests/compute.pp index b67b972d6..53b0f2d86 100644 --- a/nova/manifests/compute.pp +++ b/nova/manifests/compute.pp @@ -42,7 +42,7 @@ # # [*vncproxy_path*] # (optional) The path at the end of the uri for communication with the VNC proxy server -# Defaults to './vnc_auto.html' +# Defaults to '/vnc_auto.html' # # [*vnc_keymap*] # (optional) The keymap to use with VNC (ls -alh /usr/share/qemu/keymaps to list available keymaps) @@ -142,13 +142,7 @@ } if ($vnc_enabled) { - if ($vncproxy_host) { - $vncproxy_base_url = "${vncproxy_protocol}://${vncproxy_host}:${vncproxy_port}${vncproxy_path}" - # config for vnc proxy - nova_config { - 'DEFAULT/novncproxy_base_url': value => $vncproxy_base_url; - } - } + include ::nova::vncproxy::common } nova_config { diff --git a/nova/manifests/compute/rbd.pp b/nova/manifests/compute/rbd.pp index d520c0ecf..c0c89a45e 100644 --- a/nova/manifests/compute/rbd.pp +++ b/nova/manifests/compute/rbd.pp @@ -38,6 +38,13 @@ # Required to use cephx. # Default to false. # +# [*libvirt_rbd_secret_key*] +# (optional) The cephx key to use as key for the libvirt secret, +# it must be base64 encoded; when not provided this key will be +# requested to the ceph cluster, which assumes the node is +# provided of the client.admin keyring as well. +# Default to undef. +# # [*rbd_keyring*] # (optional) The keyring name to use when retrieving the RBD secret # Default to 'client.nova' @@ -46,6 +53,7 @@ class nova::compute::rbd ( $libvirt_rbd_user, $libvirt_rbd_secret_uuid = false, + $libvirt_rbd_secret_key = undef, $libvirt_images_rbd_pool = 'rbd', $libvirt_images_rbd_ceph_conf = '/etc/ceph/ceph.conf', $rbd_keyring = 'client.nova', @@ -75,8 +83,13 @@ require => File['/etc/nova/secret.xml'] } + if $libvirt_rbd_secret_key { + $libvirt_key = $libvirt_rbd_secret_key + } else { + $libvirt_key = "$(ceph auth get-key ${rbd_keyring})" + } exec { 'set-secret-value virsh': - command => "/usr/bin/virsh secret-set-value --secret ${libvirt_rbd_secret_uuid} --base64 $(ceph auth get-key ${rbd_keyring})", + command => "/usr/bin/virsh secret-set-value --secret ${libvirt_rbd_secret_uuid} --base64 ${libvirt_key}", unless => "/usr/bin/virsh secret-get-value ${libvirt_rbd_secret_uuid}", require => Exec['get-or-set virsh secret'] } diff --git a/nova/manifests/init.pp b/nova/manifests/init.pp index 634f06ab2..08e3937d2 100644 --- a/nova/manifests/init.pp +++ b/nova/manifests/init.pp @@ -463,63 +463,63 @@ if $rpc_backend == 'nova.openstack.common.rpc.impl_kombu' or $rpc_backend == 'rabbit' { # I may want to support exporting and collecting these nova_config { - 'DEFAULT/rabbit_password': value => $rabbit_password, secret => true; - 'DEFAULT/rabbit_userid': value => $rabbit_userid; - 'DEFAULT/rabbit_virtual_host': value => $rabbit_virtual_host; - 'DEFAULT/rabbit_use_ssl': value => $rabbit_use_ssl; + 'oslo_messaging_rabbit/rabbit_password': value => $rabbit_password, secret => true; + 'oslo_messaging_rabbit/rabbit_userid': value => $rabbit_userid; + 'oslo_messaging_rabbit/rabbit_virtual_host': value => $rabbit_virtual_host; + 'oslo_messaging_rabbit/rabbit_use_ssl': value => $rabbit_use_ssl; 'DEFAULT/amqp_durable_queues': value => $amqp_durable_queues; } if $rabbit_use_ssl { if $kombu_ssl_ca_certs { - nova_config { 'DEFAULT/kombu_ssl_ca_certs': value => $kombu_ssl_ca_certs; } + nova_config { 'oslo_messaging_rabbit/kombu_ssl_ca_certs': value => $kombu_ssl_ca_certs; } } else { - nova_config { 'DEFAULT/kombu_ssl_ca_certs': ensure => absent; } + nova_config { 'oslo_messaging_rabbit/kombu_ssl_ca_certs': ensure => absent; } } if $kombu_ssl_certfile or $kombu_ssl_keyfile { nova_config { - 'DEFAULT/kombu_ssl_certfile': value => $kombu_ssl_certfile; - 'DEFAULT/kombu_ssl_keyfile': value => $kombu_ssl_keyfile; + 'oslo_messaging_rabbit/kombu_ssl_certfile': value => $kombu_ssl_certfile; + 'oslo_messaging_rabbit/kombu_ssl_keyfile': value => $kombu_ssl_keyfile; } } else { nova_config { - 'DEFAULT/kombu_ssl_certfile': ensure => absent; - 'DEFAULT/kombu_ssl_keyfile': ensure => absent; + 'oslo_messaging_rabbit/kombu_ssl_certfile': ensure => absent; + 'oslo_messaging_rabbit/kombu_ssl_keyfile': ensure => absent; } } if $kombu_ssl_version { - nova_config { 'DEFAULT/kombu_ssl_version': value => $kombu_ssl_version; } + nova_config { 'oslo_messaging_rabbit/kombu_ssl_version': value => $kombu_ssl_version; } } else { - nova_config { 'DEFAULT/kombu_ssl_version': ensure => absent; } + nova_config { 'oslo_messaging_rabbit/kombu_ssl_version': ensure => absent; } } } else { nova_config { - 'DEFAULT/kombu_ssl_ca_certs': ensure => absent; - 'DEFAULT/kombu_ssl_certfile': ensure => absent; - 'DEFAULT/kombu_ssl_keyfile': ensure => absent; - 'DEFAULT/kombu_ssl_version': ensure => absent; + 'oslo_messaging_rabbit/kombu_ssl_ca_certs': ensure => absent; + 'oslo_messaging_rabbit/kombu_ssl_certfile': ensure => absent; + 'oslo_messaging_rabbit/kombu_ssl_keyfile': ensure => absent; + 'oslo_messaging_rabbit/kombu_ssl_version': ensure => absent; } } if $rabbit_hosts { - nova_config { 'DEFAULT/rabbit_hosts': value => join($rabbit_hosts, ',') } + nova_config { 'oslo_messaging_rabbit/rabbit_hosts': value => join($rabbit_hosts, ',') } } else { - nova_config { 'DEFAULT/rabbit_host': value => $rabbit_host } - nova_config { 'DEFAULT/rabbit_port': value => $rabbit_port } - nova_config { 'DEFAULT/rabbit_hosts': value => "${rabbit_host}:${rabbit_port}" } + nova_config { 'oslo_messaging_rabbit/rabbit_host': value => $rabbit_host } + nova_config { 'oslo_messaging_rabbit/rabbit_port': value => $rabbit_port } + nova_config { 'oslo_messaging_rabbit/rabbit_hosts': value => "${rabbit_host}:${rabbit_port}" } } if $rabbit_ha_queues == undef { if $rabbit_hosts { - nova_config { 'DEFAULT/rabbit_ha_queues': value => true } + nova_config { 'oslo_messaging_rabbit/rabbit_ha_queues': value => true } } else { - nova_config { 'DEFAULT/rabbit_ha_queues': value => false } + nova_config { 'oslo_messaging_rabbit/rabbit_ha_queues': value => false } } } else { - nova_config { 'DEFAULT/rabbit_ha_queues': value => $rabbit_ha_queues } + nova_config { 'oslo_messaging_rabbit/rabbit_ha_queues': value => $rabbit_ha_queues } } } diff --git a/nova/manifests/params.pp b/nova/manifests/params.pp index b24ec182d..50f9b014f 100644 --- a/nova/manifests/params.pp +++ b/nova/manifests/params.pp @@ -47,7 +47,7 @@ 'Fedora': { $special_service_provider = undef } - 'RedHat', 'CentOS', 'Scientific': { + 'RedHat', 'CentOS', 'Scientific', 'OracleLinux': { if (versioncmp($::operatingsystemmajrelease, '7') < 0) { $special_service_provider = 'init' } else { diff --git a/nova/manifests/vncproxy.pp b/nova/manifests/vncproxy.pp index eb33a3dc0..63ba31faa 100644 --- a/nova/manifests/vncproxy.pp +++ b/nova/manifests/vncproxy.pp @@ -24,18 +24,27 @@ # (optional) The state of the nova-novncproxy package # Defaults to 'present' # +# [*vncproxy_protocol*] +# (optional) The protocol to communicate with the VNC proxy server +# Defaults to 'http' +# +# [*vncproxy_path*] +# (optional) The path at the end of the uri for communication with the VNC +# proxy server +# Defaults to '/vnc_auto.html' +# class nova::vncproxy( - $enabled = false, - $manage_service = true, - $host = '0.0.0.0', - $port = '6080', - $ensure_package = 'present' + $enabled = false, + $manage_service = true, + $vncproxy_protocol = 'http', + $host = '0.0.0.0', + $port = '6080', + $vncproxy_path = '/vnc_auto.html', + $ensure_package = 'present' ) { include ::nova::params - # TODO make this work on Fedora - # See http://nova.openstack.org/runnova/vncconsole.html for more details. nova_config { @@ -43,6 +52,8 @@ 'DEFAULT/novncproxy_port': value => $port; } + include ::nova::vncproxy::common + if ! defined(Package['python-numpy']) { package { 'python-numpy': ensure => present, diff --git a/nova/manifests/vncproxy/common.pp b/nova/manifests/vncproxy/common.pp new file mode 100644 index 000000000..15b46330d --- /dev/null +++ b/nova/manifests/vncproxy/common.pp @@ -0,0 +1,54 @@ +# == Class: nova::vncproxy::common +# +# [*vncproxy_host*] +# (optional) The host of the VNC proxy server +# Defaults to false +# +# [*vncproxy_protocol*] +# (optional) The protocol to communicate with the VNC proxy server +# Defaults to 'http' +# +# [*vncproxy_port*] +# (optional) The port to communicate with the VNC proxy server +# Defaults to '6080' +# +# [*vncproxy_path*] +# (optional) The path at the end of the uri for communication with the VNC proxy server +# Defaults to '/vnc_auto.html' +# +class nova::vncproxy::common ( + $vncproxy_host = undef, + $vncproxy_protocol = undef, + $vncproxy_port = undef, + $vncproxy_path = undef, +) { + + $vncproxy_host_real = pick( + $vncproxy_host, + $::nova::compute::vncproxy_host, + $::nova::vncproxy::host, + false) + $vncproxy_protocol_real = pick( + $vncproxy_protocol, + $::nova::compute::vncproxy_protocol, + $::nova::vncproxy::vncproxy_protocol, + 'http') + $vncproxy_port_real = pick( + $vncproxy_port, + $::nova::compute::vncproxy_port, + $::nova::vncproxy::port, + 6080) + $vncproxy_path_real = pick( + $vncproxy_path, + $::nova::compute::vncproxy_path, + $::nova::vncproxy::vncproxy_path, + '/vnc_auto.html') + + if ($vncproxy_host_real) { + $vncproxy_base_url = "${vncproxy_protocol_real}://${vncproxy_host_real}:${vncproxy_port_real}${vncproxy_path_real}" + # config for vnc proxy + nova_config { + 'DEFAULT/novncproxy_base_url': value => $vncproxy_base_url; + } + } +} diff --git a/nova/spec/classes/nova_compute_rbd_spec.rb b/nova/spec/classes/nova_compute_rbd_spec.rb index f442810f8..87c529f23 100644 --- a/nova/spec/classes/nova_compute_rbd_spec.rb +++ b/nova/spec/classes/nova_compute_rbd_spec.rb @@ -90,6 +90,21 @@ end end + context 'when using cephx and passing libvirt_rbd_secret_key' do + before :each do + params.merge!( + :libvirt_rbd_secret_uuid => 'UUID', + :libvirt_rbd_secret_key => 'LIBVIRT/SECRET/KEY', + ) + end + + it 'set libvirt secret key from passed key' do + is_expected.to contain_exec('set-secret-value virsh').with( + :command => "/usr/bin/virsh secret-set-value --secret #{params[:libvirt_rbd_secret_uuid]} --base64 #{params[:libvirt_rbd_secret_key]}" + ) + end + end + end context 'on Debian platforms' do diff --git a/nova/spec/classes/nova_init_spec.rb b/nova/spec/classes/nova_init_spec.rb index aacf4a4e6..fc319b1b1 100644 --- a/nova/spec/classes/nova_init_spec.rb +++ b/nova/spec/classes/nova_init_spec.rb @@ -57,11 +57,11 @@ it 'configures rabbit' do is_expected.to contain_nova_config('DEFAULT/rpc_backend').with_value('rabbit') - is_expected.to contain_nova_config('DEFAULT/rabbit_host').with_value('localhost') - is_expected.to contain_nova_config('DEFAULT/rabbit_password').with_value('guest').with_secret(true) - is_expected.to contain_nova_config('DEFAULT/rabbit_port').with_value('5672') - is_expected.to contain_nova_config('DEFAULT/rabbit_userid').with_value('guest') - is_expected.to contain_nova_config('DEFAULT/rabbit_virtual_host').with_value('/') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_host').with_value('localhost') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_password').with_value('guest').with_secret(true) + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_port').with_value('5672') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_userid').with_value('guest') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_virtual_host').with_value('/') end it 'configures various things' do @@ -128,11 +128,11 @@ it 'configures rabbit' do is_expected.to contain_nova_config('DEFAULT/rpc_backend').with_value('rabbit') - is_expected.to contain_nova_config('DEFAULT/rabbit_host').with_value('rabbit') - is_expected.to contain_nova_config('DEFAULT/rabbit_password').with_value('password').with_secret(true) - is_expected.to contain_nova_config('DEFAULT/rabbit_port').with_value('5673') - is_expected.to contain_nova_config('DEFAULT/rabbit_userid').with_value('rabbit_user') - is_expected.to contain_nova_config('DEFAULT/rabbit_virtual_host').with_value('/') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_host').with_value('rabbit') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_password').with_value('password').with_secret(true) + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_port').with_value('5673') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_userid').with_value('rabbit_user') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_virtual_host').with_value('/') end it 'configures memcached_servers' do @@ -221,16 +221,16 @@ end it 'configures rabbit' do - is_expected.to_not contain_nova_config('DEFAULT/rabbit_host') - is_expected.to_not contain_nova_config('DEFAULT/rabbit_port') - is_expected.to contain_nova_config('DEFAULT/rabbit_hosts').with_value('rabbit:5673,rabbit2:5674') - is_expected.to contain_nova_config('DEFAULT/rabbit_ha_queues').with_value(true) - is_expected.to contain_nova_config('DEFAULT/rabbit_use_ssl').with_value(false) + is_expected.to_not contain_nova_config('oslo_messaging_rabbit/rabbit_host') + is_expected.to_not contain_nova_config('oslo_messaging_rabbit/rabbit_port') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_hosts').with_value('rabbit:5673,rabbit2:5674') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_ha_queues').with_value(true) + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_use_ssl').with_value(false) is_expected.to contain_nova_config('DEFAULT/amqp_durable_queues').with_value(false) - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_ca_certs').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_certfile').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_keyfile').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_version').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_ca_certs').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_certfile').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_keyfile').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_version').with_ensure('absent') end end @@ -240,11 +240,11 @@ end it 'configures rabbit' do - is_expected.to_not contain_nova_config('DEFAULT/rabbit_host') - is_expected.to_not contain_nova_config('DEFAULT/rabbit_port') - is_expected.to contain_nova_config('DEFAULT/rabbit_hosts').with_value('rabbit:5673') - is_expected.to contain_nova_config('DEFAULT/rabbit_ha_queues').with_value(true) - is_expected.to contain_nova_config('DEFAULT/rabbit_use_ssl').with_value(false) + is_expected.to_not contain_nova_config('oslo_messaging_rabbit/rabbit_host') + is_expected.to_not contain_nova_config('oslo_messaging_rabbit/rabbit_port') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_hosts').with_value('rabbit:5673') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_ha_queues').with_value(true) + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_use_ssl').with_value(false) is_expected.to contain_nova_config('DEFAULT/amqp_durable_queues').with_value(false) end end @@ -255,7 +255,7 @@ end it 'configures rabbit' do - is_expected.to contain_nova_config('DEFAULT/rabbit_ha_queues').with_value(true) + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_ha_queues').with_value(true) end end @@ -266,16 +266,16 @@ end it 'configures rabbit' do - is_expected.to_not contain_nova_config('DEFAULT/rabbit_host') - is_expected.to_not contain_nova_config('DEFAULT/rabbit_port') - is_expected.to contain_nova_config('DEFAULT/rabbit_hosts').with_value('rabbit:5673') - is_expected.to contain_nova_config('DEFAULT/rabbit_ha_queues').with_value(true) - is_expected.to contain_nova_config('DEFAULT/rabbit_use_ssl').with_value(false) + is_expected.to_not contain_nova_config('oslo_messaging_rabbit/rabbit_host') + is_expected.to_not contain_nova_config('oslo_messaging_rabbit/rabbit_port') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_hosts').with_value('rabbit:5673') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_ha_queues').with_value(true) + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_use_ssl').with_value(false) is_expected.to contain_nova_config('DEFAULT/amqp_durable_queues').with_value(true) - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_ca_certs').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_certfile').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_keyfile').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_version').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_ca_certs').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_certfile').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_keyfile').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_version').with_ensure('absent') end end @@ -290,11 +290,11 @@ end it 'configures rabbit' do - is_expected.to contain_nova_config('DEFAULT/rabbit_use_ssl').with_value(true) - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_ca_certs').with_value('/etc/ca.cert') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_certfile').with_value('/etc/certfile') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_keyfile').with_value('/etc/key') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_version').with_value('TLSv1') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_use_ssl').with_value(true) + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_ca_certs').with_value('/etc/ca.cert') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_certfile').with_value('/etc/certfile') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_keyfile').with_value('/etc/key') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_version').with_value('TLSv1') end end @@ -305,11 +305,11 @@ end it 'configures rabbit' do - is_expected.to contain_nova_config('DEFAULT/rabbit_use_ssl').with_value(true) - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_ca_certs').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_certfile').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_keyfile').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_version').with_value('TLSv1') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_use_ssl').with_value(true) + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_ca_certs').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_certfile').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_keyfile').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_version').with_value('TLSv1') end end @@ -323,11 +323,11 @@ end it 'configures rabbit' do - is_expected.to contain_nova_config('DEFAULT/rabbit_use_ssl').with_value('false') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_ca_certs').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_certfile').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_keyfile').with_ensure('absent') - is_expected.to contain_nova_config('DEFAULT/kombu_ssl_version').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/rabbit_use_ssl').with_value('false') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_ca_certs').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_certfile').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_keyfile').with_ensure('absent') + is_expected.to contain_nova_config('oslo_messaging_rabbit/kombu_ssl_version').with_ensure('absent') end end diff --git a/nova/spec/classes/nova_vnc_proxy_spec.rb b/nova/spec/classes/nova_vnc_proxy_spec.rb index c24f347ad..4fe3ab612 100644 --- a/nova/spec/classes/nova_vnc_proxy_spec.rb +++ b/nova/spec/classes/nova_vnc_proxy_spec.rb @@ -22,6 +22,7 @@ it { is_expected.to contain_nova_config('DEFAULT/novncproxy_host').with(:value => '0.0.0.0') } it { is_expected.to contain_nova_config('DEFAULT/novncproxy_port').with(:value => '6080') } + it { is_expected.to contain_nova_config('DEFAULT/novncproxy_base_url').with(:value => 'http://0.0.0.0:6080/vnc_auto.html') } it { is_expected.to contain_package('nova-vncproxy').with( :name => 'nova-novncproxy', diff --git a/nova/spec/spec_helper.rb b/nova/spec/spec_helper.rb index 53d4dd02d..172614e99 100644 --- a/nova/spec/spec_helper.rb +++ b/nova/spec/spec_helper.rb @@ -5,3 +5,5 @@ c.alias_it_should_behave_like_to :it_configures, 'configures' c.alias_it_should_behave_like_to :it_raises, 'raises' end + +at_exit { RSpec::Puppet::Coverage.report! } diff --git a/ntp/.gitignore b/ntp/.gitignore index b5db85e05..874db461f 100644 --- a/ntp/.gitignore +++ b/ntp/.gitignore @@ -7,3 +7,4 @@ spec/fixtures/ coverage/ .idea/ *.iml +log/ diff --git a/ntp/README.markdown b/ntp/README.markdown index f7209ef9c..353923f16 100644 --- a/ntp/README.markdown +++ b/ntp/README.markdown @@ -191,10 +191,22 @@ 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. + +####`maxpoll` + +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` Tells Puppet whether the NTP package should be installed, and what version. Valid options: 'present', 'latest', or a specific version number. Default value: 'present' @@ -209,7 +221,11 @@ Tells Puppet what NTP package to manage. Valid options: string. Default value: ' ####`panic` -Specifies whether NTP should "panic" in the event of a very large clock skew. Valid options: 'true' or 'false'. Default value: 'true' (except on virtual machines, where major time shifts are normal) +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` @@ -257,10 +273,22 @@ Tells Puppet whether to manage the NTP service. Valid options: 'true' or 'false' Tells Puppet what NTP service to manage. Valid options: string. Default value: varies by operating system +####`stepout` + +Tells puppet to change stepout. Applies only if `tinker` value is 'true'. Valid options: unsigned shortint digit. Default value: undef. + +####`tinker` + +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' +####`udlc_stratum` + +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 + ##Limitations This module has been tested on [all PE-supported platforms](https://forge.puppetlabs.com/supported#compat-matrix), and no issues have been identified. diff --git a/ntp/manifests/init.pp b/ntp/manifests/init.pp index 14adf5952..1eea5a036 100644 --- a/ntp/manifests/init.pp +++ b/ntp/manifests/init.pp @@ -7,6 +7,7 @@ $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, @@ -14,10 +15,13 @@ $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, @@ -26,7 +30,10 @@ $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) @@ -36,15 +43,18 @@ 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) @@ -54,7 +64,10 @@ 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/ntp/manifests/params.pp b/ntp/manifests/params.pp index 47a898001..cf9c01180 100644 --- a/ntp/manifests/params.pp +++ b/ntp/manifests/params.pp @@ -8,12 +8,17 @@ $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 $broadcastclient = false @@ -21,14 +26,6 @@ # Allow a list of fudge options $fudge = [] - # On virtual machines allow large clock skews. - # TODO Change this to str2bool($::is_virtual) when stdlib dependency is >= 4.0.0 - # NOTE The "x${var}" is just to avoid lint quoted variable warning. - $panic = "x${::is_virtual}" ? { - 'xtrue' => false, - default => true, - } - $default_config = '/etc/ntp.conf' $default_keys_file = '/etc/ntp/keys' $default_driftfile = '/var/lib/ntp/drift' @@ -40,6 +37,15 @@ default => true, } + if str2bool($::is_virtual) { + $tinker = true + $panic = 0 + } + else { + $tinker = false + $panic = undef + } + case $::osfamily { 'AIX': { $config = $default_config @@ -58,6 +64,7 @@ '2.debian.pool.ntp.org', '3.debian.pool.ntp.org', ] + $maxpoll = undef } 'Debian': { $config = $default_config @@ -78,6 +85,7 @@ '2.debian.pool.ntp.org', '3.debian.pool.ntp.org', ] + $maxpoll = undef } 'RedHat': { $config = $default_config @@ -97,6 +105,7 @@ '1.centos.pool.ntp.org', '2.centos.pool.ntp.org', ] + $maxpoll = undef } 'Suse': { if $::operatingsystem == 'SLES' and $::operatingsystemmajrelease == '12' @@ -123,6 +132,7 @@ '2.opensuse.pool.ntp.org', '3.opensuse.pool.ntp.org', ] + $maxpoll = undef } 'FreeBSD': { $config = $default_config @@ -138,11 +148,12 @@ $service_name = $default_service_name $iburst_enable = true $servers = [ - '0.freebsd.pool.ntp.org maxpoll 9', - '1.freebsd.pool.ntp.org maxpoll 9', - '2.freebsd.pool.ntp.org maxpoll 9', - '3.freebsd.pool.ntp.org 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 = $default_config @@ -162,6 +173,7 @@ '1.pool.ntp.org', '2.pool.ntp.org', ] + $maxpoll = undef } 'Solaris': { $config = '/etc/inet/ntp.conf' @@ -185,6 +197,7 @@ '2.pool.ntp.org', '3.pool.ntp.org', ] + $maxpoll = undef } # Gentoo was added as its own $::osfamily in Facter 1.7.0 'Gentoo': { @@ -206,6 +219,7 @@ '2.gentoo.pool.ntp.org', '3.gentoo.pool.ntp.org', ] + $maxpoll = undef } 'Linux': { # Account for distributions that don't have $::osfamily specific settings. @@ -230,6 +244,7 @@ '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/ntp/metadata.json b/ntp/metadata.json index 962d11e4a..96366b7bb 100644 --- a/ntp/metadata.json +++ b/ntp/metadata.json @@ -90,6 +90,6 @@ ], "description": "NTP Module for Debian, Ubuntu, CentOS, RHEL, OEL, Fedora, FreeBSD, ArchLinux and Gentoo.", "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":">= 4.5.0 < 5.0.0"} + {"name":"puppetlabs/stdlib","version_requirement":">= 4.6.0 < 5.0.0"} ] } diff --git a/ntp/spec/acceptance/ntp_parameters_spec.rb b/ntp/spec/acceptance/ntp_parameters_spec.rb index e4c230d7e..2ac554d9c 100644 --- a/ntp/spec/acceptance/ntp_parameters_spec.rb +++ b/ntp/spec/acceptance/ntp_parameters_spec.rb @@ -139,33 +139,33 @@ class { 'ntp': 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("#{config}") do - its(:content) { should match 'tinker panic' } + 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("#{config}") do - its(:content) { should_not match 'tinker panic 0' } + its(:content) { should match 'tinker panic 1' } end end @@ -181,4 +181,16 @@ class { 'ntp': 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 } + its(:content) { should match 'stratum 10' } + end + end + end diff --git a/ntp/spec/classes/ntp_spec.rb b/ntp/spec/classes/ntp_spec.rb index 522afbd00..81489db6e 100644 --- a/ntp/spec/classes/ntp_spec.rb +++ b/ntp/spec/classes/ntp_spec.rb @@ -87,11 +87,12 @@ context "when set" do let(:params) {{ :servers => ['a', 'b', 'c', 'd'], - :preferred_servers => ['a', 'b'] + :preferred_servers => ['a', 'b'], + :iburst_enable => false, }} it { should contain_file('/etc/ntp.conf').with({ - 'content' => /server a( iburst)? prefer\nserver b( iburst)? prefer\nserver c( iburst)?\nserver d( iburst)?/}) + '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 @@ -247,7 +248,7 @@ it do should contain_file('/etc/ntp.conf').with({ - 'content' => /iburst\n/, + 'content' => /iburst/, }) end end @@ -265,6 +266,181 @@ end end + 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 + + 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 '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 'with parameter logfile' do context 'when set to true' do let(:params) {{ @@ -291,6 +467,33 @@ 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 end @@ -363,7 +566,7 @@ it 'uses the freebsd ntp servers by default' do should contain_file('/etc/ntp.conf').with({ - 'content' => /server \d.freebsd.pool.ntp.org maxpoll 9 iburst/, + 'content' => /server \d.freebsd.pool.ntp.org iburst maxpoll 9/, }) end end diff --git a/ntp/spec/spec_helper_acceptance.rb b/ntp/spec/spec_helper_acceptance.rb index 1a4bea19a..6b6f1b8fa 100644 --- a/ntp/spec/spec_helper_acceptance.rb +++ b/ntp/spec/spec_helper_acceptance.rb @@ -20,7 +20,7 @@ on host, "mkdir -p #{host['distmoduledir']}" if host['platform'] =~ /sles-12/i || host['platform'] =~ /solaris-11/i apply_manifest_on(host, 'package{"git":}') - on host, 'git clone -b 4.3.x https://github.com/puppetlabs/puppetlabs-stdlib /etc/puppetlabs/puppet/modules/stdlib' + on host, 'git clone -b 4.6.x https://github.com/puppetlabs/puppetlabs-stdlib /etc/puppetlabs/puppet/modules/stdlib' else on host, puppet('module install puppetlabs-stdlib'), {:acceptable_exit_codes => [0, 1]} end diff --git a/ntp/templates/ntp.conf.erb b/ntp/templates/ntp.conf.erb index 2393087f1..c913569b8 100644 --- a/ntp/templates/ntp.conf.erb +++ b/ntp/templates/ntp.conf.erb @@ -1,9 +1,11 @@ # 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 -%> @@ -34,15 +36,21 @@ interface listen <%= interface %> 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 @iburst_enable == true -%> iburst<% end %><% 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 @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 +fudge 127.127.1.0 stratum <%= @udlc_stratum %> restrict 127.127.1.0 <% end -%> @@ -54,6 +62,13 @@ driftfile <%= @driftfile %> 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? -%> @@ -70,3 +85,8 @@ controlkey <%= @keys_controlkey %> <% [@fudge].flatten.each do |entry| -%> fudge <%= entry %> <% end -%> + +<% unless @leapfile.nil? -%> +# Leapfile +leapfile <%= @leapfile %> +<% end -%> diff --git a/openstacklib/.fixtures.yml b/openstacklib/.fixtures.yml index a07981ce7..bcf98bc41 100644 --- a/openstacklib/.fixtures.yml +++ b/openstacklib/.fixtures.yml @@ -1,12 +1,12 @@ fixtures: repositories: apache: git://github.com/puppetlabs/puppetlabs-apache.git - concat: git://github.com/puppetlabs/puppetlabs-concat.git + concat: + repo: 'git://github.com/puppetlabs/puppetlabs-concat.git' + ref: '1.2.1' mysql: git://github.com/puppetlabs/puppetlabs-mysql.git postgresql: git://github.com/puppetlabs/puppetlabs-postgresql.git stdlib: git://github.com/puppetlabs/puppetlabs-stdlib.git - rabbitmq: - repo: 'git://github.com/puppetlabs/puppetlabs-rabbitmq' - ref: 'origin/4.x' + rabbitmq: 'git://github.com/puppetlabs/puppetlabs-rabbitmq' symlinks: 'openstacklib': "#{source_dir}" diff --git a/openstacklib/lib/puppet/provider/openstack.rb b/openstacklib/lib/puppet/provider/openstack.rb index ec1cffe2b..391e327f0 100644 --- a/openstacklib/lib/puppet/provider/openstack.rb +++ b/openstacklib/lib/puppet/provider/openstack.rb @@ -106,46 +106,51 @@ def authenticate_request(service, action, *args) private def password_credentials_set?(auth_params) - auth_params && auth_params['username'] && auth_params['password'] && auth_params['tenant_name'] && auth_params['auth_url'] + auth_params && auth_params['username'] && auth_params['password'] && auth_params['project_name'] && auth_params['auth_url'] end - def openrc_set?(auth_params) auth_params && auth_params['openrc'] end - def service_credentials_set?(auth_params) - auth_params && auth_params['token'] && auth_params['auth_url'] + auth_params && auth_params['token'] && auth_params['url'] end - def self.env_vars_set? - ENV['OS_USERNAME'] && ENV['OS_PASSWORD'] && ENV['OS_TENANT_NAME'] && ENV['OS_AUTH_URL'] + ENV['OS_USERNAME'] && ENV['OS_PASSWORD'] && ENV['OS_PROJECT_NAME'] && ENV['OS_AUTH_URL'] end - def env_vars_set? self.class.env_vars_set? end + def self.password_auth_args(credentials) + creds = [ '--os-username', credentials['username'], + '--os-password', credentials['password'], + '--os-project-name', credentials['project_name'], + '--os-auth-url', credentials['auth_url'] ] + + if credentials.include?('project_domain_name') + creds << '--os-project-domain-name' + creds << credentials['project_domain_name'] + end + if credentials.include?('user_domain_name') + creds << '--os-user-domain-name' + creds << credentials['user_domain_name'] + end - def self.password_auth_args(credentials) - ['--os-username', credentials['username'], - '--os-password', credentials['password'], - '--os-tenant-name', credentials['tenant_name'], - '--os-auth-url', credentials['auth_url']] + creds end def password_auth_args(credentials) self.class.password_auth_args(credentials) end - def self.token_auth_args(credentials) - ['--os-token', credentials['token'], - '--os-url', credentials['auth_url']] + [ '--os-token', credentials['token'], + '--os-url', credentials['url'] ] end def token_auth_args(credentials) @@ -163,7 +168,6 @@ def get_credentials_from_openrc(file) return creds end - def self.get_credentials_from_env env = ENV.to_hash.dup.delete_if { |key, _| ! (key =~ /^OS_/) } credentials = {} diff --git a/openstacklib/lib/puppet/util/openstack.rb b/openstacklib/lib/puppet/util/openstack.rb index 867964afb..916aa8e16 100644 --- a/openstacklib/lib/puppet/util/openstack.rb +++ b/openstacklib/lib/puppet/util/openstack.rb @@ -5,27 +5,46 @@ def self.add_openstack_type_methods(type, comment) type.newparam(:auth) do desc < { + 'username' => 'test', + 'password' => 'changeme', + 'project_name' => 'test', + 'auth_url' => 'http://localhost:35357/v2.0' +} + +or altenatively for Keystone API V3: auth => { - 'username' => 'test', - 'password' => 'passw0rd', - 'tenant_name' => 'test', - 'auth_url' => 'http://localhost:35357/v2.0', + 'username' => 'test', + 'password' => 'changeme', + 'project_name' => 'test', + 'project_domain_name' => 'domain1', + 'user_domain_name' => 'domain1', + 'auth_url' => 'http://localhost:35357/v3' } -or a path to an openrc file containing these credentials, e.g.: +2. Using a path to an openrc file containing these credentials auth => { - 'openrc' => '/root/openrc', + 'openrc' => '/root/openrc' } -or a service token and host, e.g.: +3. Using a service token + +For Keystone API V2: +auth => { + 'token' => 'example', + 'url' => 'http://localhost:35357/v2.0' +} +Alternatively for Keystone API V3: auth => { - 'service_token' => 'ADMIN', - 'auth_url' => 'http://localhost:35357/v2.0', + 'token' => 'example', + 'url' => 'http://localhost:35357/v3.0' } If not present, the provider will look for environment variables for diff --git a/openstacklib/manifests/wsgi/apache.pp b/openstacklib/manifests/wsgi/apache.pp index 9baf1cb4f..06eaef6ec 100644 --- a/openstacklib/manifests/wsgi/apache.pp +++ b/openstacklib/manifests/wsgi/apache.pp @@ -170,7 +170,7 @@ } $wsgi_daemon_process_options = { - owner => $user, + user => $user, group => $group, processes => $workers, threads => $threads, diff --git a/openstacklib/spec/defines/openstacklib_wsgi_apache_spec.rb b/openstacklib/spec/defines/openstacklib_wsgi_apache_spec.rb index 3fc529d04..15bd3f0b4 100644 --- a/openstacklib/spec/defines/openstacklib_wsgi_apache_spec.rb +++ b/openstacklib/spec/defines/openstacklib_wsgi_apache_spec.rb @@ -65,17 +65,23 @@ )} it { is_expected.to contain_apache__vhost('keystone_wsgi').with( - 'servername' => 'some.host.tld', - 'ip' => nil, - 'port' => '5000', - 'docroot' => '/var/www/cgi-bin/keystone', - 'docroot_owner' => 'keystone', - 'docroot_group' => 'keystone', - 'ssl' => 'true', - 'wsgi_daemon_process' => 'keystone_wsgi', - 'wsgi_process_group' => 'keystone_wsgi', - 'wsgi_script_aliases' => { '/' => "/var/www/cgi-bin/keystone/main" }, - 'require' => 'File[keystone_wsgi]' + 'servername' => 'some.host.tld', + 'ip' => nil, + 'port' => '5000', + 'docroot' => '/var/www/cgi-bin/keystone', + 'docroot_owner' => 'keystone', + 'docroot_group' => 'keystone', + 'ssl' => 'true', + 'wsgi_daemon_process' => 'keystone_wsgi', + 'wsgi_process_group' => 'keystone_wsgi', + 'wsgi_script_aliases' => { '/' => "/var/www/cgi-bin/keystone/main" }, + 'wsgi_daemon_process_options' => { + 'user' => 'keystone', + 'group' => 'keystone', + 'processes' => 1, + 'threads' => global_facts[:processorcount], + }, + 'require' => 'File[keystone_wsgi]' )} it { is_expected.to contain_file("#{platform_parameters[:httpd_ports_file]}") } end diff --git a/openstacklib/spec/unit/provider/openstack_spec.rb b/openstacklib/spec/unit/provider/openstack_spec.rb index c5f5efe13..558c49086 100644 --- a/openstacklib/spec/unit/provider/openstack_spec.rb +++ b/openstacklib/spec/unit/provider/openstack_spec.rb @@ -8,10 +8,10 @@ describe Puppet::Provider::Openstack do before(:each) do - ENV['OS_USERNAME'] = nil - ENV['OS_PASSWORD'] = nil - ENV['OS_TENANT_NAME'] = nil - ENV['OS_AUTH_URL'] = nil + ENV['OS_USERNAME'] = nil + ENV['OS_PASSWORD'] = nil + ENV['OS_PROJECT_NAME'] = nil + ENV['OS_AUTH_URL'] = nil end let(:type) do @@ -22,12 +22,36 @@ end end - shared_examples 'authenticating with environment variables' do + shared_examples 'authenticating with environment variables using API v2' do it 'makes a successful request' do - ENV['OS_USERNAME'] = 'test' - ENV['OS_PASSWORD'] = 'abc123' - ENV['OS_TENANT_NAME'] = 'test' - ENV['OS_AUTH_URL'] = 'http://127.0.0.1:35357/v2.0' + ENV['OS_USERNAME'] = 'test' + ENV['OS_PASSWORD'] = 'abc123' + ENV['OS_PROJECT_NAME'] = 'test' + ENV['OS_AUTH_URL'] = 'http://127.0.0.1:35357/v2.0' + if provider.class == Class + provider.stubs(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', [[ '--long' ]]) + .returns('"ID","Name","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True +') + else + provider.class.stubs(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', [[ '--long' ]]) + .returns('"ID","Name","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True +') + end + response = provider.request('project', 'list', nil, nil, '--long' ) + expect(response.first[:description]).to match /Test tenant/ + end + end + + shared_examples 'authenticating with environment variables using API v3' do + it 'makes a successful request' do + ENV['OS_USERNAME'] = 'test' + ENV['OS_PASSWORD'] = 'abc123' + ENV['OS_PROJECT_NAME'] = 'test' + ENV['OS_AUTH_URL'] = 'http://127.0.0.1:35357/v3' if provider.class == Class provider.stubs(:openstack) .with('project', 'list', '--quiet', '--format', 'csv', [[ '--long' ]]) @@ -59,10 +83,10 @@ { :name => 'stubresource', :auth => { - 'username' => 'test', - 'password' => 'abc123', - 'tenant_name' => 'test', - 'auth_url' => 'http://127.0.0.1:5000/v2.0', + 'username' => 'test', + 'password' => 'abc123', + 'project_name' => 'test', + 'auth_url' => 'http://127.0.0.1:5000/v2.0', } } end @@ -72,7 +96,7 @@ it 'makes a successful request' do provider.class.stubs(:openstack) - .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Description","Enabled" "1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True ') @@ -82,7 +106,7 @@ end context 'with valid openrc file in parameters' do - mock = "export OS_USERNAME='test'\nexport OS_PASSWORD='abc123'\nexport OS_TENANT_NAME='test'\nexport OS_AUTH_URL='http://127.0.0.1:5000/v2.0'" + mock = "export OS_USERNAME='test'\nexport OS_PASSWORD='abc123'\nexport OS_PROJECT_NAME='test'\nexport OS_AUTH_URL='http://127.0.0.1:5000/v2.0'" let(:resource_attrs) do { :name => 'stubresource', @@ -98,7 +122,7 @@ it 'makes a successful request' do File.expects(:open).with('/root/openrc').returns(StringIO.new(mock)) provider.class.stubs(:openstack) - .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .returns('"ID","Name","Description","Enabled" "1cb05cfed7c24279be884ba4f6520262","test","Test tenant",True ') @@ -113,7 +137,7 @@ :name => 'stubresource', :auth => { 'token' => 'secrettoken', - 'auth_url' => 'http://127.0.0.1:5000/v2.0' + 'url' => 'http://127.0.0.1:5000/v2.0' } } end @@ -149,7 +173,7 @@ end context 'with valid password credentials in environment variables' do - it_behaves_like 'authenticating with environment variables' do + it_behaves_like 'authenticating with environment variables using API v2' do let(:resource_attrs) do { :name => 'stubresource', @@ -179,10 +203,10 @@ { :name => 'stubresource', :auth => { - 'username' => 'test', - 'password' => 'abc123', - 'tenant_name' => 'test', - 'auth_url' => 'http://127.0.0.1:5000/v2.0', + 'username' => 'test', + 'password' => 'abc123', + 'project_name' => 'test', + 'auth_url' => 'http://127.0.0.1:5000/v2.0', } } end @@ -191,7 +215,7 @@ end it 'retries' do provider.class.stubs(:openstack) - .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-tenant-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) + .with('project', 'list', '--quiet', '--format', 'csv', [['--long', '--os-username', 'test', '--os-password', 'abc123', '--os-project-name', 'test', '--os-auth-url', 'http://127.0.0.1:5000/v2.0']]) .raises(Puppet::ExecutionFailure, 'Unable to establish connection') .then .returns('') @@ -205,7 +229,7 @@ describe '::request' do context 'with valid password credentials in environment variables' do - it_behaves_like 'authenticating with environment variables' do + it_behaves_like 'authenticating with environment variables using API v2' do let(:resource_attrs) do { :name => 'stubresource', diff --git a/rabbitmq/README.md b/rabbitmq/README.md index 7471a72fb..2b88d2f51 100644 --- a/rabbitmq/README.md +++ b/rabbitmq/README.md @@ -224,7 +224,8 @@ This value has no default and must be set explicitly if using clustering. ####`file_limit` -Set rabbitmq file ulimit. Defaults to 16384. Only available on systems with `$::osfamily == 'Debian'` +Set rabbitmq file ulimit. Defaults to 16384. Only available on systems with +`$::osfamily == 'Debian'` or `$::osfamily == 'RedHat'`. ####`key_content` diff --git a/rabbitmq/lib/puppet/provider/rabbitmq_binding/rabbitmqadmin.rb b/rabbitmq/lib/puppet/provider/rabbitmq_binding/rabbitmqadmin.rb index e0eebd025..e1b06b419 100644 --- a/rabbitmq/lib/puppet/provider/rabbitmq_binding/rabbitmqadmin.rb +++ b/rabbitmq/lib/puppet/provider/rabbitmq_binding/rabbitmqadmin.rb @@ -90,6 +90,8 @@ def create vhost_opt, "--user=#{resource[:user]}", "--password=#{resource[:password]}", + '-c', + '/etc/rabbitmq/rabbitmqadmin.conf', "source=#{name}", "destination=#{destination}", "arguments=#{arguments.to_json}", @@ -103,7 +105,7 @@ def destroy vhost_opt = should_vhost ? "--vhost=#{should_vhost}" : '' name = resource[:name].split('@').first destination = resource[:name].split('@')[1] - rabbitmqadmin('delete', 'binding', vhost_opt, "--user=#{resource[:user]}", "--password=#{resource[:password]}", "source=#{name}", "destination_type=#{resource[:destination_type]}", "destination=#{destination}") + rabbitmqadmin('delete', 'binding', vhost_opt, "--user=#{resource[:user]}", "--password=#{resource[:password]}", '-c', '/etc/rabbitmq/rabbitmqadmin.conf', "source=#{name}", "destination_type=#{resource[:destination_type]}", "destination=#{destination}") @property_hash[:ensure] = :absent end diff --git a/rabbitmq/lib/puppet/provider/rabbitmq_queue/rabbitmqadmin.rb b/rabbitmq/lib/puppet/provider/rabbitmq_queue/rabbitmqadmin.rb index b0ecb1f5a..eeffa953c 100644 --- a/rabbitmq/lib/puppet/provider/rabbitmq_queue/rabbitmqadmin.rb +++ b/rabbitmq/lib/puppet/provider/rabbitmq_queue/rabbitmqadmin.rb @@ -87,6 +87,8 @@ def create vhost_opt, "--user=#{resource[:user]}", "--password=#{resource[:password]}", + '-c', + '/etc/rabbitmq/rabbitmqadmin.conf', "name=#{name}", "durable=#{resource[:durable]}", "auto_delete=#{resource[:auto_delete]}", @@ -98,7 +100,7 @@ def create def destroy vhost_opt = should_vhost ? "--vhost=#{should_vhost}" : '' name = resource[:name].rpartition('@').first - rabbitmqadmin('delete', 'queue', vhost_opt, "--user=#{resource[:user]}", "--password=#{resource[:password]}", "name=#{name}") + rabbitmqadmin('delete', 'queue', vhost_opt, "--user=#{resource[:user]}", "--password=#{resource[:password]}", '-c', '/etc/rabbitmq/rabbitmqadmin.conf', "name=#{name}") @property_hash[:ensure] = :absent end diff --git a/rabbitmq/lib/puppet/provider/rabbitmq_user/rabbitmqctl.rb b/rabbitmq/lib/puppet/provider/rabbitmq_user/rabbitmqctl.rb index 3980e7556..da37886cb 100644 --- a/rabbitmq/lib/puppet/provider/rabbitmq_user/rabbitmqctl.rb +++ b/rabbitmq/lib/puppet/provider/rabbitmq_user/rabbitmqctl.rb @@ -45,8 +45,8 @@ def password def check_password - response = rabbitmqctl('eval', 'rabbit_auth_backend_internal:check_user_login(<<"' + resource[:name] + '">>, [{password, <<"' + resource[:password] +'">>}]).') - if response.include? 'invalid credentials' + response = rabbitmqctl('eval', 'rabbit_access_control:check_user_pass_login(list_to_binary("' + resource[:name] + '"), list_to_binary("' + resource[:password] +'")).') + if response.include? 'refused' false else true diff --git a/rabbitmq/manifests/config.pp b/rabbitmq/manifests/config.pp index a2fb56a7e..5e3f1ef6e 100644 --- a/rabbitmq/manifests/config.pp +++ b/rabbitmq/manifests/config.pp @@ -106,14 +106,48 @@ } } - if $::osfamily == 'Debian' { - file { '/etc/default/rabbitmq-server': - ensure => file, - content => template('rabbitmq/default.erb'), - mode => '0644', - owner => '0', - group => '0', - notify => Class['rabbitmq::service'], + case $::osfamily { + 'Debian': { + file { '/etc/default/rabbitmq-server': + ensure => file, + content => template('rabbitmq/default.erb'), + mode => '0644', + owner => '0', + group => '0', + notify => Class['rabbitmq::service'], + } + } + 'RedHat': { + if versioncmp($::operatingsystemmajrelease, '7') >= 0 { + file { '/etc/systemd/system/rabbitmq-server.service.d': + ensure => directory, + owner => '0', + group => '0', + mode => '0755', + } -> + file { '/etc/systemd/system/rabbitmq-server.service.d/limits.conf': + content => template('rabbitmq/rabbitmq-server.service.d/limits.conf'), + owner => '0', + group => '0', + mode => '0644', + notify => Exec['rabbitmq-systemd-reload'], + } + exec { 'rabbitmq-systemd-reload': + command => '/usr/bin/systemctl daemon-reload', + 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'], + } + } + } + default: { } } diff --git a/rabbitmq/manifests/init.pp b/rabbitmq/manifests/init.pp index 5946fe57d..4e115f9b2 100644 --- a/rabbitmq/manifests/init.pp +++ b/rabbitmq/manifests/init.pp @@ -200,10 +200,9 @@ include '::rabbitmq::install::rabbitmqadmin' rabbitmq_plugin { 'rabbitmq_management': - ensure => present, - require => Class['rabbitmq::install'], - notify => Class['rabbitmq::service'], - provider => 'rabbitmqplugins' + ensure => present, + require => Class['rabbitmq::install'], + notify => Class['rabbitmq::service'], } Class['::rabbitmq::service'] -> Class['::rabbitmq::install::rabbitmqadmin'] @@ -212,19 +211,17 @@ if $stomp_ensure { rabbitmq_plugin { 'rabbitmq_stomp': - ensure => present, - require => Class['rabbitmq::install'], - notify => Class['rabbitmq::service'], - provider => 'rabbitmqplugins' + ensure => present, + require => Class['rabbitmq::install'], + notify => Class['rabbitmq::service'], } } if ($ldap_auth) { rabbitmq_plugin { 'rabbitmq_auth_backend_ldap': - ensure => present, - require => Class['rabbitmq::install'], - notify => Class['rabbitmq::service'], - provider => 'rabbitmqplugins', + ensure => present, + require => Class['rabbitmq::install'], + notify => Class['rabbitmq::service'], } } diff --git a/rabbitmq/spec/acceptance/queue_spec.rb b/rabbitmq/spec/acceptance/queue_spec.rb new file mode 100644 index 000000000..a1643a632 --- /dev/null +++ b/rabbitmq/spec/acceptance/queue_spec.rb @@ -0,0 +1,157 @@ +require 'spec_helper_acceptance' + +describe 'rabbitmq binding:' do + + + context "create binding and queue resources when rabbit using default management port" do + it 'should run successfully' do + pp = <<-EOS + if $::osfamily == 'RedHat' { + class { 'erlang': epel_enable => true } + Class['erlang'] -> Class['::rabbitmq'] + } + class { '::rabbitmq': + service_manage => true, + port => '5672', + delete_guest_user => true, + admin_enable => true, + } -> + + rabbitmq_user { 'dan': + admin => true, + password => 'bar', + tags => ['monitoring', 'tag1'], + } -> + + rabbitmq_user_permissions { 'dan@host1': + configure_permission => '.*', + read_permission => '.*', + write_permission => '.*', + } + + rabbitmq_vhost { 'host1': + ensure => present, + } -> + + rabbitmq_exchange { 'exchange1@host1': + user => 'dan', + password => 'bar', + type => 'topic', + ensure => present, + } -> + + rabbitmq_queue { 'queue1@host1': + user => 'dan', + password => 'bar', + durable => true, + auto_delete => false, + ensure => present, + } -> + + rabbitmq_binding { 'exchange1@queue1@host1': + user => 'dan', + password => 'bar', + destination_type => 'queue', + routing_key => '#', + ensure => present, + } + + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + it 'should have the binding' do + shell('rabbitmqctl list_bindings -q -p host1') do |r| + expect(r.stdout).to match(/exchange1\sexchange\squeue1\squeue\s#/) + expect(r.exit_code).to be_zero + end + end + + it 'should have the queue' do + shell('rabbitmqctl list_queues -q -p host1') do |r| + expect(r.stdout).to match(/queue1/) + expect(r.exit_code).to be_zero + end + end + + end + + context "create binding and queue resources when rabbit using a non-default management port" do + it 'should run successfully' do + pp = <<-EOS + if $::osfamily == 'RedHat' { + class { 'erlang': epel_enable => true } + Class['erlang'] -> Class['::rabbitmq'] + } + class { '::rabbitmq': + service_manage => true, + port => '5672', + management_port => '11111', + delete_guest_user => true, + admin_enable => true, + } -> + + rabbitmq_user { 'dan': + admin => true, + password => 'bar', + tags => ['monitoring', 'tag1'], + } -> + + rabbitmq_user_permissions { 'dan@host2': + configure_permission => '.*', + read_permission => '.*', + write_permission => '.*', + } + + rabbitmq_vhost { 'host2': + ensure => present, + } -> + + rabbitmq_exchange { 'exchange2@host2': + user => 'dan', + password => 'bar', + type => 'topic', + ensure => present, + } -> + + rabbitmq_queue { 'queue2@host2': + user => 'dan', + password => 'bar', + durable => true, + auto_delete => false, + ensure => present, + } -> + + rabbitmq_binding { 'exchange2@queue2@host2': + user => 'dan', + password => 'bar', + destination_type => 'queue', + routing_key => '#', + ensure => present, + } + + EOS + + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + it 'should have the binding' do + shell('rabbitmqctl list_bindings -q -p host2') do |r| + expect(r.stdout).to match(/exchange2\sexchange\squeue2\squeue\s#/) + expect(r.exit_code).to be_zero + end + end + + it 'should have the queue' do + shell('rabbitmqctl list_queues -q -p host2') do |r| + expect(r.stdout).to match(/queue2/) + expect(r.exit_code).to be_zero + end + end + + end + +end diff --git a/rabbitmq/spec/classes/rabbitmq_spec.rb b/rabbitmq/spec/classes/rabbitmq_spec.rb index 6ddc26f25..47a5c9860 100644 --- a/rabbitmq/spec/classes/rabbitmq_spec.rb +++ b/rabbitmq/spec/classes/rabbitmq_spec.rb @@ -248,6 +248,144 @@ end end + context 'on RedHat 7.0 or more' do + 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' + ) } + + it { should contain_exec('rabbitmq-systemd-reload').with( + 'command' => '/usr/bin/systemctl daemon-reload', + 'notify' => 'Class[Rabbitmq::Service]', + 'refreshonly' => true + ) } + 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', + 'group' => '0', + 'mode' => '0644', + 'notify' => 'Exec[rabbitmq-systemd-reload]', + 'content' => '[Service] +LimitNOFILE=unlimited +' + ) } + end + + 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', + 'group' => '0', + 'mode' => '0644', + 'notify' => 'Exec[rabbitmq-systemd-reload]', + 'content' => '[Service] +LimitNOFILE=infinity +' + ) } + end + + 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', + 'mode' => '0644', + 'notify' => 'Exec[rabbitmq-systemd-reload]', + 'content' => '[Service] +LimitNOFILE=-1 +' + ) } + end + + context 'with file_limit => \'1234\'' do + let(:params) {{ :file_limit => '1234' }} + it { should contain_file('/etc/systemd/system/rabbitmq-server.service.d/limits.conf').with( + 'owner' => '0', + 'group' => '0', + 'mode' => '0644', + 'notify' => 'Exec[rabbitmq-systemd-reload]', + 'content' => '[Service] +LimitNOFILE=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 + + 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| context "on #{distro}" do let(:facts) {{ diff --git a/rabbitmq/spec/unit/puppet/provider/rabbitmq_binding/rabbitmqadmin_spec.rb b/rabbitmq/spec/unit/puppet/provider/rabbitmq_binding/rabbitmqadmin_spec.rb index d1ff0667c..50594efee 100644 --- a/rabbitmq/spec/unit/puppet/provider/rabbitmq_binding/rabbitmqadmin_spec.rb +++ b/rabbitmq/spec/unit/puppet/provider/rabbitmq_binding/rabbitmqadmin_spec.rb @@ -28,12 +28,12 @@ end it 'should call rabbitmqadmin to create' do - @provider.expects(:rabbitmqadmin).with('declare', 'binding', '--vhost=/', '--user=guest', '--password=guest', 'source=source', 'destination=target', 'arguments={}', 'routing_key=blablub', 'destination_type=queue') + @provider.expects(:rabbitmqadmin).with('declare', 'binding', '--vhost=/', '--user=guest', '--password=guest', '-c', '/etc/rabbitmq/rabbitmqadmin.conf', 'source=source', 'destination=target', 'arguments={}', 'routing_key=blablub', 'destination_type=queue') @provider.create end it 'should call rabbitmqadmin to destroy' do - @provider.expects(:rabbitmqadmin).with('delete', 'binding', '--vhost=/', '--user=guest', '--password=guest', 'source=source', 'destination_type=queue', 'destination=target') + @provider.expects(:rabbitmqadmin).with('delete', 'binding', '--vhost=/', '--user=guest', '--password=guest', '-c', '/etc/rabbitmq/rabbitmqadmin.conf', 'source=source', 'destination_type=queue', 'destination=target') @provider.destroy end @@ -52,7 +52,7 @@ end it 'should call rabbitmqadmin to create' do - @provider.expects(:rabbitmqadmin).with('declare', 'binding', '--vhost=/', '--user=colin', '--password=secret', 'source=source', 'destination=test2', 'arguments={}', 'routing_key=blablubd', 'destination_type=queue') + @provider.expects(:rabbitmqadmin).with('declare', 'binding', '--vhost=/', '--user=colin', '--password=secret', '-c', '/etc/rabbitmq/rabbitmqadmin.conf', 'source=source', 'destination=test2', 'arguments={}', 'routing_key=blablubd', 'destination_type=queue') @provider.create end end diff --git a/rabbitmq/spec/unit/puppet/provider/rabbitmq_queue/rabbitmqadmin_spec.rb b/rabbitmq/spec/unit/puppet/provider/rabbitmq_queue/rabbitmqadmin_spec.rb index 97410a8b4..85843da8a 100644 --- a/rabbitmq/spec/unit/puppet/provider/rabbitmq_queue/rabbitmqadmin_spec.rb +++ b/rabbitmq/spec/unit/puppet/provider/rabbitmq_queue/rabbitmqadmin_spec.rb @@ -29,12 +29,12 @@ end it 'should call rabbitmqadmin to create' do - @provider.expects(:rabbitmqadmin).with('declare', 'queue', '--vhost=/', '--user=guest', '--password=guest', 'name=test', 'durable=true', 'auto_delete=false', 'arguments={}') + @provider.expects(:rabbitmqadmin).with('declare', 'queue', '--vhost=/', '--user=guest', '--password=guest', '-c', '/etc/rabbitmq/rabbitmqadmin.conf', 'name=test', 'durable=true', 'auto_delete=false', 'arguments={}') @provider.create end it 'should call rabbitmqadmin to destroy' do - @provider.expects(:rabbitmqadmin).with('delete', 'queue', '--vhost=/', '--user=guest', '--password=guest', 'name=test') + @provider.expects(:rabbitmqadmin).with('delete', 'queue', '--vhost=/', '--user=guest', '--password=guest', '-c', '/etc/rabbitmq/rabbitmqadmin.conf', 'name=test') @provider.destroy end @@ -53,7 +53,7 @@ end it 'should call rabbitmqadmin to create' do - @provider.expects(:rabbitmqadmin).with('declare', 'queue', '--vhost=/', '--user=colin', '--password=secret', 'name=test', 'durable=true', 'auto_delete=false', 'arguments={}') + @provider.expects(:rabbitmqadmin).with('declare', 'queue', '--vhost=/', '--user=colin', '--password=secret', '-c', '/etc/rabbitmq/rabbitmqadmin.conf', 'name=test', 'durable=true', 'auto_delete=false', 'arguments={}') @provider.create end end diff --git a/rabbitmq/templates/limits.conf b/rabbitmq/templates/limits.conf new file mode 100644 index 000000000..bb017fd9c --- /dev/null +++ b/rabbitmq/templates/limits.conf @@ -0,0 +1,2 @@ +rabbitmq soft nofile <%= @file_limit %> +rabbitmq hard nofile <%= @file_limit %> diff --git a/rabbitmq/templates/rabbitmq-server.service.d/limits.conf b/rabbitmq/templates/rabbitmq-server.service.d/limits.conf new file mode 100644 index 000000000..78773864e --- /dev/null +++ b/rabbitmq/templates/rabbitmq-server.service.d/limits.conf @@ -0,0 +1,2 @@ +[Service] +LimitNOFILE=<%= @file_limit %> diff --git a/rsync/manifests/server.pp b/rsync/manifests/server.pp index 65804c189..30d9b11e2 100644 --- a/rsync/manifests/server.pp +++ b/rsync/manifests/server.pp @@ -17,8 +17,13 @@ $conf_file = $::osfamily ? { 'Debian' => '/etc/rsyncd.conf', + 'suse' => '/etc/rsyncd.conf', default => '/etc/rsync.conf', } + $servicename = $::osfamily ? { + 'suse' => 'rsyncd', + default => 'rsync', + } if $use_xinetd { include xinetd @@ -30,7 +35,7 @@ require => Package['rsync'], } } else { - service { 'rsync': + service { $servicename: ensure => running, enable => true, hasstatus => true, diff --git a/rsync/metadata.json b/rsync/metadata.json index 7187040f3..e88c08b8b 100644 --- a/rsync/metadata.json +++ b/rsync/metadata.json @@ -8,7 +8,7 @@ "project_page": "https://github.com/puppetlabs/puppetlabs-rsync", "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":">=2.2.1"}, + {"name":"puppetlabs/stdlib","version_requirement":">=4.2.0"}, {"name":"puppetlabs/xinetd","version_requirement":">=1.1.0"}, {"name":"puppetlabs/concat","version_requirement":">= 1.1.1"} ] diff --git a/rsync/spec/classes/server_spec.rb b/rsync/spec/classes/server_spec.rb index 0b52ce5fe..19ad7a977 100644 --- a/rsync/spec/classes/server_spec.rb +++ b/rsync/spec/classes/server_spec.rb @@ -82,4 +82,19 @@ } end + describe 'on SuSE, use_xinetd => false' do + let(:params) do + { + :use_xinetd => false, + } + end + let(:facts) do + { + :osfamily => 'SuSE', + :concat_basedir => '/dne', + } + end + + it{ is_expected.to contain_service('rsyncd') } + end end diff --git a/sahara/manifests/notify/rabbitmq.pp b/sahara/manifests/notify/rabbitmq.pp index 54791918e..1cb2a7cd0 100644 --- a/sahara/manifests/notify/rabbitmq.pp +++ b/sahara/manifests/notify/rabbitmq.pp @@ -105,29 +105,37 @@ $kombu_reconnect_delay = '1.0', ) { if $rabbit_use_ssl { - if !$kombu_ssl_keyfile { - fail('kombu_ssl_keyfile must be set when using SSL in rabbit') - } - if !$kombu_ssl_certfile { - fail('kombu_ssl_certfile must be set when using SSL in rabbit') + + if $kombu_ssl_ca_certs { + sahara_config { 'DEFAULT/kombu_ssl_ca_certs': value => $kombu_ssl_ca_certs; } + } else { + sahara_config { 'DEFAULT/kombu_ssl_ca_certs': ensure => absent; } } - if !$kombu_ssl_ca_certs { - fail('kombu_ssl_ca_certs must be set when using SSL in rabbit') + + if $kombu_ssl_certfile or $kombu_ssl_keyfile { + sahara_config { + 'DEFAULT/kombu_ssl_certfile': value => $kombu_ssl_certfile; + 'DEFAULT/kombu_ssl_keyfile': value => $kombu_ssl_keyfile; + } + } else { + sahara_config { + 'DEFAULT/kombu_ssl_certfile': ensure => absent; + 'DEFAULT/kombu_ssl_keyfile': ensure => absent; + } } - sahara_config { - 'DEFAULT/kombu_ssl_version': value => $kombu_ssl_version; - 'DEFAULT/kombu_ssl_keyfile': value => $kombu_ssl_keyfile; - 'DEFAULT/kombu_ssl_certfile': value => $kombu_ssl_certfile; - 'DEFAULT/kombu_ssl_ca_certs': value => $kombu_ssl_ca_certs; - 'DEFAULT/kombu_reconnect_delay': value => $kombu_reconnect_delay; + + if $kombu_ssl_version { + sahara_config { 'DEFAULT/kombu_ssl_version': value => $kombu_ssl_version; } + } else { + sahara_config { 'DEFAULT/kombu_ssl_version': ensure => absent; } } + } else { sahara_config { - 'DEFAULT/kombu_ssl_version': ensure => absent; - 'DEFAULT/kombu_ssl_keyfile': ensure => absent; - 'DEFAULT/kombu_ssl_certfile': ensure => absent; 'DEFAULT/kombu_ssl_ca_certs': ensure => absent; - 'DEFAULT/kombu_reconnect_delay': ensure => absent; + 'DEFAULT/kombu_ssl_certfile': ensure => absent; + 'DEFAULT/kombu_ssl_keyfile': ensure => absent; + 'DEFAULT/kombu_ssl_version': ensure => absent; } } @@ -161,5 +169,6 @@ 'DEFAULT/rabbit_max_retries': value => $rabbit_max_retries; 'DEFAULT/notification_topics': value => $notification_topics; 'DEFAULT/control_exchange': value => $control_exchange; + 'DEFAULT/kombu_reconnect_delay': value => $kombu_reconnect_delay; } } diff --git a/sahara/spec/classes/sahara_notify_rabbitmq_spec.rb b/sahara/spec/classes/sahara_notify_rabbitmq_spec.rb index eb4f5dbd3..40cdc67f6 100644 --- a/sahara/spec/classes/sahara_notify_rabbitmq_spec.rb +++ b/sahara/spec/classes/sahara_notify_rabbitmq_spec.rb @@ -57,6 +57,18 @@ it { is_expected.to contain_sahara_config('DEFAULT/kombu_ssl_version').with_value('TLSv1') } end + describe 'with rabbit ssl cert parameters' do + let :params do + { + :rabbit_password => 'pass', + :rabbit_use_ssl => 'true', + } + end + + it { is_expected.to contain_sahara_config('DEFAULT/rabbit_use_ssl').with_value('true') } + it { is_expected.to contain_sahara_config('DEFAULT/kombu_ssl_version').with_value('TLSv1') } + end + describe 'with rabbit ssl disabled' do let :params do { diff --git a/stdlib/.travis.yml b/stdlib/.travis.yml index 503e1844d..b29f7e782 100644 --- a/stdlib/.travis.yml +++ b/stdlib/.travis.yml @@ -6,13 +6,19 @@ script: "bundle exec rake validate && bundle exec rake lint && bundle exec rake matrix: fast_finish: true include: + - rvm: 1.9.3 + env: PUPPET_GEM_VERSION="~> 3.4.0" - 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: 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" notifications: email: false diff --git a/stdlib/CHANGELOG.md b/stdlib/CHANGELOG.md index 138569507..c17e7509a 100644 --- a/stdlib/CHANGELOG.md +++ b/stdlib/CHANGELOG.md @@ -1,17 +1,32 @@ -##2015-01-14 - Supported Release 4.6.0 +##2015-04-14 - Supported Release 4.6.0 ###Summary -Improved functionality and preparing for Puppet Next with new parser +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 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 +- 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 time 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 -- Several test case fixes -- Ensure_resource is more verbose on debug mode +- 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 diff --git a/stdlib/README.markdown b/stdlib/README.markdown index 293a81aca..38890882a 100644 --- a/stdlib/README.markdown +++ b/stdlib/README.markdown @@ -244,6 +244,23 @@ This function flattens any deeply nested arrays and returns a single flat array Returns the largest integer less than or equal to the argument. Takes a single numeric value as an 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 a random number of times based on a node's fqdn. *Type*: rvalue @@ -500,6 +517,24 @@ Calling the class or definition from outside the current module will fail. For e *Type*: statement +#### `pw_hash` + +Hashes a password using the crypt function. Provides a hash usable on most POSIX systems. + +The first argument to this function is the password to hash. If it is undef or an empty string, this function returns undef. + +The second argument to this function is which type of hash to use. It will be converted into the appropriate crypt(3) hash specifier. Valid hash types are: + +|Hash type |Specifier| +|---------------------|---------| +|MD5 |1 | +|SHA-256 |5 | +|SHA-512 (recommended)|6 | + +The third argument to this function is the salt to use. + +Note: this uses the Puppet Master's implementation of crypt(3). If your environment contains several different operating systems, ensure that they are compatible before using this function. + #### `range` 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]. diff --git a/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb b/stdlib/lib/puppet/parser/functions/fqdn_rand_string.rb new file mode 100644 index 000000000..2bb1287e0 --- /dev/null +++ b/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/stdlib/lib/puppet/parser/functions/loadyaml.rb b/stdlib/lib/puppet/parser/functions/loadyaml.rb index 10c400501..ca655f6ea 100644 --- a/stdlib/lib/puppet/parser/functions/loadyaml.rb +++ b/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/stdlib/lib/puppet/parser/functions/pw_hash.rb b/stdlib/lib/puppet/parser/functions/pw_hash.rb new file mode 100644 index 000000000..ad3e39375 --- /dev/null +++ b/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? + + # handle weak implementations of String#crypt + if 'test'.crypt('$1$1') != '$1$1$Bp8CU9Oujr9SSEw53WV6G.' + # JRuby < 1.7.17 + if RUBY_PLATFORM == 'java' + # override String#crypt for password variable + def password.crypt(salt) + # puppetserver bundles Apache Commons Codec + org.apache.commons.codec.digest.Crypt.crypt(self.to_java_bytes, salt) + end + else + # MS Windows and other systems that don't support enhanced salts + raise Puppet::ParseError, 'system does not support enhanced salts' + end + end + password.crypt("$#{hash_type}$#{args[2]}") +end diff --git a/stdlib/lib/puppet/provider/file_line/ruby.rb b/stdlib/lib/puppet/provider/file_line/ruby.rb index ae1a8b3db..e7854f001 100644 --- a/stdlib/lib/puppet/provider/file_line/ruby.rb +++ b/stdlib/lib/puppet/provider/file_line/ruby.rb @@ -34,13 +34,22 @@ def lines def handle_create_with_match() regex = resource[:match] ? Regexp.new(resource[:match]) : nil + regex_after = resource[:after] ? Regexp.new(resource[:after]) : nil match_count = count_matches(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) + 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) @@ -78,7 +87,10 @@ def count_matches(regex) # # @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/stdlib/lib/puppet/type/file_line.rb b/stdlib/lib/puppet/type/file_line.rb index df263e6a7..29f95382a 100644 --- a/stdlib/lib/puppet/type/file_line.rb +++ b/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,6 +22,18 @@ 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. + **Autorequires:** If Puppet is managing the file that will contain the line being managed, the file_line resource will autorequire that file. @@ -36,12 +49,15 @@ 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 comparisson is performed against the line value and if it does not' + + ' match an exception will be raised. ' 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 +66,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 diff --git a/stdlib/metadata.json b/stdlib/metadata.json index 27def9c08..51b73f78f 100644 --- a/stdlib/metadata.json +++ b/stdlib/metadata.json @@ -1,6 +1,6 @@ { "name": "puppetlabs-stdlib", - "version": "4.5.1", + "version": "4.6.0", "author": "puppetlabs", "summary": "Standard library of resources for Puppet modules.", "license": "Apache-2.0", diff --git a/stdlib/spec/acceptance/fqdn_rand_string_spec.rb b/stdlib/spec/acceptance/fqdn_rand_string_spec.rb new file mode 100644 index 000000000..8fe1a6955 --- /dev/null +++ b/stdlib/spec/acceptance/fqdn_rand_string_spec.rb @@ -0,0 +1,60 @@ +#! /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 + 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' + 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}'") + end + end + it 'generates random alphanumeric strings' do + shell("echo fqdn=fakehost.localdomain > '#{facts_d}/fqdn.txt'") + 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 seeds' do + shell("echo fqdn=fakehost.localdomain > '#{facts_d}/fqdn.txt'") + 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 + end + describe 'failure' do + it 'handles improper argument counts' + it 'handles non-numbers for length argument' + end +end diff --git a/stdlib/spec/acceptance/pw_hash_spec.rb b/stdlib/spec/acceptance/pw_hash_spec.rb new file mode 100644 index 000000000..eddb78288 --- /dev/null +++ b/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']).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/stdlib/spec/functions/fqdn_rand_string_spec.rb b/stdlib/spec/functions/fqdn_rand_string_spec.rb new file mode 100644 index 000000000..949d930c7 --- /dev/null +++ b/stdlib/spec/functions/fqdn_rand_string_spec.rb @@ -0,0 +1,91 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the fqdn_rand_string function" do + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + expect(Puppet::Parser::Functions.function("fqdn_rand_string")).to eq("function_fqdn_rand_string") + end + + it "should raise an ArgumentError if there is less than 1 argument" do + expect { fqdn_rand_string() }.to( raise_error(ArgumentError, /wrong number of arguments/)) + end + + it "should raise an ArgumentError if argument 1 isn't a positive integer" do + expect { fqdn_rand_string(0) }.to( raise_error(ArgumentError, /first argument must be a positive integer/)) + expect { fqdn_rand_string(-1) }.to( raise_error(ArgumentError, /first argument must be a positive integer/)) + expect { fqdn_rand_string(0.5) }.to( raise_error(ArgumentError, /first argument must be a positive integer/)) + end + + it "provides a valid alphanumeric string when no character set is provided" do + length = 100 + string = %r{\A[a-zA-Z0-9]{#{length}}\z} + expect(fqdn_rand_string(length).match(string)).not_to eq(nil) + end + + it "provides a valid alphanumeric string when an undef character set is provided" do + length = 100 + string = %r{\A[a-zA-Z0-9]{#{length}}\z} + expect(fqdn_rand_string(length, :charset => nil).match(string)).not_to eq(nil) + end + + it "provides a valid alphanumeric string when an empty character set is provided" do + length = 100 + string = %r{\A[a-zA-Z0-9]{#{length}}\z} + expect(fqdn_rand_string(length, :charset => '').match(string)).not_to eq(nil) + end + + it "uses a provided character set" do + length = 100 + charset = '!@#$%^&*()-_=+' + string = %r{\A[#{charset}]{#{length}}\z} + expect(fqdn_rand_string(length, :charset => charset).match(string)).not_to eq(nil) + end + + it "provides a random string exactly as long as the given length" do + expect(fqdn_rand_string(10).size).to eql(10) + end + + 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] || [] + + scope = PuppetlabsSpec::PuppetInternals.scope + scope.stubs(:[]).with("::fqdn").returns(host) + 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/stdlib/spec/functions/loadyaml_spec.rb b/stdlib/spec/functions/loadyaml_spec.rb index cdc3d6f51..4b8d40623 100755 --- a/stdlib/spec/functions/loadyaml_spec.rb +++ b/stdlib/spec/functions/loadyaml_spec.rb @@ -14,6 +14,12 @@ expect { scope.function_loadyaml([]) }.to raise_error(Puppet::ParseError) end + it "should return nil when file does not exist" do + yaml_file = tmpfilename ('yamlfile') + result = scope.function_loadyaml([yaml_file]) + expect(result).to(eq(nil)) + end + it "should convert YAML file to a data structure" do yaml_file = tmpfilename ('yamlfile') File.open(yaml_file, 'w') do |fh| diff --git a/stdlib/spec/functions/pw_hash_spec.rb b/stdlib/spec/functions/pw_hash_spec.rb new file mode 100644 index 000000000..337809085 --- /dev/null +++ b/stdlib/spec/functions/pw_hash_spec.rb @@ -0,0 +1,96 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' + +describe "the pw_hash function" do + + before :all do + @enhanced_salts_supported = RUBY_PLATFORM == 'java' + end + + let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + + it "should exist" do + expect(Puppet::Parser::Functions.function("pw_hash")).to eq("function_pw_hash") + end + + it "should raise an ArgumentError if there are less than 3 arguments" do + expect { scope.function_pw_hash([]) }.to( raise_error(ArgumentError, /[Ww]rong number of arguments/) ) + expect { scope.function_pw_hash(['password']) }.to( raise_error(ArgumentError, /[Ww]rong number of arguments/) ) + expect { scope.function_pw_hash(['password', 'sha-512']) }.to( raise_error(ArgumentError, /[Ww]rong number of arguments/) ) + end + + it "should raise an ArgumentError if there are more than 3 arguments" do + expect { scope.function_pw_hash(['password', 'sha-512', 'salt', 5]) }.to( raise_error(ArgumentError, /[Ww]rong number of arguments/) ) + end + + it "should raise an ArgumentError if the first argument is not a string" do + expect { scope.function_pw_hash([['password'], 'sha-512', 'salt']) }.to( raise_error(ArgumentError, /first argument must be a string/) ) + # in Puppet 3, numbers are passed as strings, so we can't test that + end + + it "should return nil if the first argument is empty" do + expect(scope.function_pw_hash(['', 'sha-512', 'salt'])).to eq(nil) + end + + it "should return nil if the first argument is undef" do + expect(scope.function_pw_hash([nil, 'sha-512', 'salt'])).to eq(nil) + end + + it "should raise an ArgumentError if the second argument is an invalid hash type" do + expect { scope.function_pw_hash(['', 'invalid', 'salt']) }.to( raise_error(ArgumentError, /not a valid hash type/) ) + end + + it "should raise an ArgumentError if the second argument is not a string" do + expect { scope.function_pw_hash(['', [], 'salt']) }.to( raise_error(ArgumentError, /second argument must be a string/) ) + end + + it "should raise an ArgumentError if the third argument is not a string" do + expect { scope.function_pw_hash(['password', 'sha-512', ['salt']]) }.to( raise_error(ArgumentError, /third argument must be a string/) ) + # in Puppet 3, numbers are passed as strings, so we can't test that + end + + it "should raise an ArgumentError if the third argument is empty" do + expect { scope.function_pw_hash(['password', 'sha-512', '']) }.to( raise_error(ArgumentError, /third argument must not be empty/) ) + end + + it "should raise an ArgumentError if the third argument has invalid characters" do + expect { scope.function_pw_hash(['password', 'sha-512', '%']) }.to( raise_error(ArgumentError, /characters in salt must be in the set/) ) + end + + it "should fail on platforms with weak implementations of String#crypt" do + String.any_instance.expects(:crypt).with('$1$1').returns('$1SoNol0Ye6Xk') + expect { scope.function_pw_hash(['password', 'sha-512', 'salt']) }.to( raise_error(Puppet::ParseError, /system does not support enhanced salts/) ) + end + + if @enhanced_salts_supported + describe "on systems with enhanced salts support" do + it "should return a hashed password" do + result = scope.function_pw_hash(['password', 'sha-512', 'salt']) + expect(result).to eql('$6$salt$IxDD3jeSOb5eB1CX5LBsqZFVkJdido3OUILO5Ifz5iwMuTS4XMS130MTSuDDl3aCI6WouIL9AjRbLCelDCy.g.') + end + + it "should use the specified salt" do + result = scope.function_pw_hash(['password', 'sha-512', 'salt']) + expect(result).to match('salt') + end + + it "should use the specified hash type" do + resultmd5 = scope.function_pw_hash(['password', 'md5', 'salt']) + resultsha256 = scope.function_pw_hash(['password', 'sha-256', 'salt']) + resultsha512 = scope.function_pw_hash(['password', 'sha-512', 'salt']) + + expect(resultmd5).to eql('$1$salt$qJH7.N4xYta3aEG/dfqo/0') + expect(resultsha256).to eql('$5$salt$Gcm6FsVtF/Qa77ZKD.iwsJlCVPY0XSMgLJL0Hnww/c1') + expect(resultsha512).to eql('$6$salt$IxDD3jeSOb5eB1CX5LBsqZFVkJdido3OUILO5Ifz5iwMuTS4XMS130MTSuDDl3aCI6WouIL9AjRbLCelDCy.g.') + end + + it "should generate a valid hash" do + password_hash = scope.function_pw_hash(['password', 'sha-512', 'salt']) + + hash_parts = password_hash.match(%r{\A\$(.*)\$([a-zA-Z0-9./]+)\$([a-zA-Z0-9./]+)\z}) + + expect(hash_parts).not_to eql(nil) + end + end + end +end diff --git a/stdlib/spec/functions/validate_augeas_spec.rb b/stdlib/spec/functions/validate_augeas_spec.rb index c695ba2eb..99523ab77 100755 --- a/stdlib/spec/functions/validate_augeas_spec.rb +++ b/stdlib/spec/functions/validate_augeas_spec.rb @@ -60,7 +60,7 @@ end describe "Nicer Error Messages" do - # The intent here is to make sure the function returns the 3rd argument + # 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' ], @@ -69,7 +69,7 @@ inputs.each do |input| it "validate_augeas(#{input.inspect}) should fail" do - expect { subject.call input }.to raise_error /#{input[2]}/ + expect { subject.call input }.to raise_error /#{input[3]}/ end end end diff --git a/stdlib/spec/unit/puppet/provider/file_line/ruby_spec.rb b/stdlib/spec/unit/puppet/provider/file_line/ruby_spec.rb index d2a129c32..a84fc78e7 100755 --- a/stdlib/spec/unit/puppet/provider/file_line/ruby_spec.rb +++ b/stdlib/spec/unit/puppet/provider/file_line/ruby_spec.rb @@ -46,12 +46,12 @@ @tmpfile = tmp.path tmp.close! @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*=.*$', + } ) @provider = provider_class.new(@resource) end @@ -69,11 +69,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 +89,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 +140,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| @@ -194,7 +241,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 diff --git a/swift/.fixtures.yml b/swift/.fixtures.yml index e503cd723..5b3af39a5 100644 --- a/swift/.fixtures.yml +++ b/swift/.fixtures.yml @@ -1,13 +1,17 @@ fixtures: repositories: "apt": "git://github.com/puppetlabs/puppetlabs-apt.git" - "concat": "git://github.com/puppetlabs/puppetlabs-concat.git" + "concat": + "repo": "git://github.com/puppetlabs/puppetlabs-concat.git" + "ref": "1.2.1" "inifile": "git://github.com/puppetlabs/puppetlabs-inifile" "keystone": "git://github.com/stackforge/puppet-keystone.git" "memcached": "git://github.com/saz/puppet-memcached.git" "openstacklib": "git://github.com/stackforge/puppet-openstacklib.git" "rsync": "git://github.com/puppetlabs/puppetlabs-rsync.git" - "ssh": "git://github.com/saz/puppet-ssh.git" + "ssh": + repo: "git://github.com/saz/puppet-ssh.git" + ref: "v2.4.0" "stdlib": "git://github.com/puppetlabs/puppetlabs-stdlib.git" "xinetd": "git://github.com/puppetlabs/puppetlabs-xinetd.git" symlinks: diff --git a/swift/lib/puppet/provider/swift_ring_builder.rb b/swift/lib/puppet/provider/swift_ring_builder.rb index 7a1bf45ba..2b30cc8bd 100644 --- a/swift/lib/puppet/provider/swift_ring_builder.rb +++ b/swift/lib/puppet/provider/swift_ring_builder.rb @@ -8,6 +8,14 @@ def self.instances end end + def self.address_string(address) + ip = IPAddr.new(address) + if ip.ipv6? + '[' + ip.to_s + ']' + else + ip.to_s + end + end def self.lookup_ring object_hash = {} @@ -30,7 +38,8 @@ def self.lookup_ring # Swift 1.8+ output example: if row =~ /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\d+)\s+\S+\s+\d+\s+(\S+)\s+(\d+\.\d+)\s+(\d+)\s*((-|\s-?)?\d+\.\d+)\s*(\S*)/ - object_hash["#{$4}:#{$5}/#{$6}"] = { + address = address_string("#{$4}") + object_hash["#{address}:#{$5}/#{$6}"] = { :id => $1, :region => $2, :zone => $3, @@ -43,7 +52,8 @@ def self.lookup_ring # Swift 1.8.0 output example: elsif row =~ /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\d+)\s+(\S+)\s+(\d+\.\d+)\s+(\d+)\s*((-|\s-?)?\d+\.\d+)\s*(\S*)/ - object_hash["#{$4}:#{$5}/#{$6}"] = { + address = address_string("#{$4}") + object_hash["#{address}:#{$5}/#{$6}"] = { :id => $1, :region => $2, :zone => $3, @@ -55,7 +65,8 @@ def self.lookup_ring # This regex is for older swift versions elsif row =~ /^\s+(\d+)\s+(\d+)\s+(\S+)\s+(\d+)\s+(\S+)\s+(\d+\.\d+)\s+(\d+)\s+(-?\d+\.\d+)\s+(\S*)$/ - object_hash["#{$3}:#{$4}/#{$5}"] = { + address = address_string("#{$3}") + object_hash["#{address}:#{$4}/#{$5}"] = { :id => $1, :region => 'none', :zone => $2, diff --git a/swift/lib/puppet/type/ring_account_device.rb b/swift/lib/puppet/type/ring_account_device.rb index 5174f23d2..6882193a2 100644 --- a/swift/lib/puppet/type/ring_account_device.rb +++ b/swift/lib/puppet/type/ring_account_device.rb @@ -1,15 +1,19 @@ Puppet::Type.newtype(:ring_account_device) do require 'ipaddr' + require 'uri' ensurable newparam(:name, :namevar => true) do validate do |value| - address = value.split(':') - raise(Puppet::Error, "invalid name #{value}, should contain address:port/device") unless address.size == 2 - port_device = address[1].split('/') - raise(Puppet::Error, "namevar should contain a device") unless port_device.size == 2 - IPAddr.new(address[0]) + # we have to have URI Scheme so we just add http:// and ignore it later + uri = URI('http://' + value) + address = uri.host + port_device = uri.port + if ['','/'].include?(uri.path) + raise(Puppet::Error, "namevar should contain a device") + end + IPAddr.new(address) end end diff --git a/swift/lib/puppet/type/ring_container_device.rb b/swift/lib/puppet/type/ring_container_device.rb index 60144b068..2aec5edcf 100644 --- a/swift/lib/puppet/type/ring_container_device.rb +++ b/swift/lib/puppet/type/ring_container_device.rb @@ -1,15 +1,19 @@ Puppet::Type.newtype(:ring_container_device) do require 'ipaddr' + require 'uri' ensurable newparam(:name, :namevar => true) do validate do |value| - address = value.split(':') - raise(Puppet::Error, "invalid name #{value}, should contain address:port/device") unless address.size == 2 - port_device = address[1].split('/') - raise(Puppet::Error, "namevar should contain a device") unless port_device.size == 2 - IPAddr.new(address[0]) + # we have to have URI Scheme so we just add http:// and ignore it later + uri = URI('http://' + value) + address = uri.host + port_device = uri.port + if ['','/'].include?(uri.path) + raise(Puppet::Error, "namevar should contain a device") + end + IPAddr.new(address) end end diff --git a/swift/lib/puppet/type/ring_object_device.rb b/swift/lib/puppet/type/ring_object_device.rb index 2de2d806f..a977ce415 100644 --- a/swift/lib/puppet/type/ring_object_device.rb +++ b/swift/lib/puppet/type/ring_object_device.rb @@ -1,15 +1,19 @@ Puppet::Type.newtype(:ring_object_device) do require 'ipaddr' + require 'uri' ensurable newparam(:name, :namevar => true) do validate do |value| - address = value.split(':') - raise(Puppet::Error, "invalid name #{value}, should contain address:port/device") unless address.size == 2 - port_device = address[1].split('/') - raise(Puppet::Error, "namevar should contain a device") unless port_device.size == 2 - IPAddr.new(address[0]) + # we have to have URI Scheme so we just add http:// and ignore it later + uri = URI('http://' + value) + address = uri.host + port_device = uri.port + if ['','/'].include?(uri.path) + raise(Puppet::Error, "namevar should contain a device") + end + IPAddr.new(address) end end diff --git a/swift/manifests/client.pp b/swift/manifests/client.pp index 757a74785..088d97315 100644 --- a/swift/manifests/client.pp +++ b/swift/manifests/client.pp @@ -17,6 +17,7 @@ package { 'swiftclient': ensure => $ensure, name => $::swift::params::client_package, + tag => 'openstack', } } diff --git a/swift/manifests/init.pp b/swift/manifests/init.pp index 2163f3e5d..b6595eef5 100644 --- a/swift/manifests/init.pp +++ b/swift/manifests/init.pp @@ -39,6 +39,7 @@ package { 'swift': ensure => $package_ensure, name => $::swift::params::package_name, + tag => 'openstack', } } diff --git a/swift/manifests/proxy.pp b/swift/manifests/proxy.pp index 503a8d54a..c6613450e 100644 --- a/swift/manifests/proxy.pp +++ b/swift/manifests/proxy.pp @@ -135,6 +135,8 @@ include ::swift::params include ::concat::setup + Swift_config<| |> ~> Service['swift-proxy'] + validate_bool($account_autocreate) validate_bool($allow_account_management) validate_array($pipeline) @@ -164,6 +166,7 @@ package { 'swift-proxy': ensure => $package_ensure, name => $::swift::params::proxy_package_name, + tag => 'openstack', } concat { '/etc/swift/proxy-server.conf': diff --git a/swift/manifests/proxy/swift3.pp b/swift/manifests/proxy/swift3.pp index 5eecba4f5..dec0e0dea 100644 --- a/swift/manifests/proxy/swift3.pp +++ b/swift/manifests/proxy/swift3.pp @@ -29,6 +29,7 @@ package { 'swift-plugin-s3': ensure => $ensure, name => $::swift::params::swift3, + tag => 'openstack', } concat::fragment { 'swift_swift3': diff --git a/swift/manifests/storage/account.pp b/swift/manifests/storage/account.pp index 3a66d6783..72f130ca7 100644 --- a/swift/manifests/storage/account.pp +++ b/swift/manifests/storage/account.pp @@ -18,6 +18,10 @@ $enabled = true, $package_ensure = 'present' ) { + + Swift_config<| |> ~> Service['swift-account-reaper'] + Swift_config<| |> ~> Service['swift-account-auditor'] + swift::storage::generic { 'account': manage_service => $manage_service, enabled => $enabled, diff --git a/swift/manifests/storage/container.pp b/swift/manifests/storage/container.pp index f11bc03b8..aa054f526 100644 --- a/swift/manifests/storage/container.pp +++ b/swift/manifests/storage/container.pp @@ -23,6 +23,10 @@ $package_ensure = 'present', $allowed_sync_hosts = ['127.0.0.1'], ) { + + Swift_config<| |> ~> Service['swift-container-updater'] + Swift_config<| |> ~> Service['swift-container-auditor'] + swift::storage::generic { 'container': manage_service => $manage_service, enabled => $enabled, @@ -71,5 +75,6 @@ provider => $::swift::params::service_provider, require => File['/etc/init/swift-container-sync.conf', '/etc/init.d/swift-container-sync'], } + Swift_config<| |> ~> Service['swift-container-sync'] } } diff --git a/swift/manifests/storage/generic.pp b/swift/manifests/storage/generic.pp index 928d52e97..88948d01c 100644 --- a/swift/manifests/storage/generic.pp +++ b/swift/manifests/storage/generic.pp @@ -38,6 +38,7 @@ include ::swift::params Class['swift::storage'] -> Swift::Storage::Generic[$name] + Swift_config<| |> ~> Service["swift-${name}"] validate_re($name, '^object|container|account$') @@ -46,6 +47,7 @@ # this is a way to dynamically build the variables to lookup # sorry its so ugly :( name => inline_template("<%= scope.lookupvar('::swift::params::${name}_package_name') %>"), + tag => 'openstack', before => Service["swift-${name}", "swift-${name}-replicator"], } diff --git a/swift/manifests/storage/object.pp b/swift/manifests/storage/object.pp index 2055843df..243e0d97d 100644 --- a/swift/manifests/storage/object.pp +++ b/swift/manifests/storage/object.pp @@ -18,6 +18,10 @@ $enabled = true, $package_ensure = 'present' ) { + + Swift_config<| |> ~> Service['swift-object-updater'] + Swift_config<| |> ~> Service['swift-object-auditor'] + swift::storage::generic { 'object': manage_service => $manage_service, enabled => $enabled, diff --git a/swift/metadata.json b/swift/metadata.json index 6b1886470..0dfd0e06a 100644 --- a/swift/metadata.json +++ b/swift/metadata.json @@ -38,6 +38,6 @@ { "name": "puppetlabs/xinetd", "version_requirement": ">=1.0.1 <2.0.0" }, { "name": "puppetlabs/concat", "version_requirement": ">=1.0.0 <2.0.0" }, { "name": "saz/memcached", "version_requirement": ">=2.0.2 <3.0.0" }, - { "name": "saz/ssh", "version_requirement": ">=1.0.2 <2.0.0" } + { "name": "saz/ssh", "version_requirement": ">=2.0.0 <3.0.0" } ] } diff --git a/swift/spec/classes/swift_client_spec.rb b/swift/spec/classes/swift_client_spec.rb index 06e1e68fd..b4da0905e 100644 --- a/swift/spec/classes/swift_client_spec.rb +++ b/swift/spec/classes/swift_client_spec.rb @@ -1,20 +1,45 @@ require 'spec_helper' describe 'swift::client' do - it { is_expected.to contain_package('swiftclient').with( - :ensure => 'present', - :name => 'python-swiftclient' - )} - let :facts do - {:osfamily => 'Debian'} + + let :params do + {} + end + + let :default_params do + { :package_ensure => 'present' } + end + + shared_examples_for 'swift client' do + let :p do + default_params.merge(params) + end + + it { is_expected.to contain_class('swift::params') } + + it 'installs swift client package' do + is_expected.to contain_package('swiftclient').with( + :name => 'python-swiftclient', + :ensure => p[:package_ensure], + :tag => 'openstack' + ) + end + + end + + context 'on Debian platform' do + let :facts do + { :osfamily => 'Debian' } + end + + it_configures 'swift client' end - context 'with params' do - let :params do - {:ensure => 'latest'} + + context 'on RedHat platform' do + let :facts do + { :osfamily => 'RedHat' } end - it { is_expected.to contain_package('swiftclient').with( - :ensure => 'latest', - :name => 'python-swiftclient' - )} + + it_configures 'swift client' end end diff --git a/swift/spec/classes/swift_keystone_auth_spec.rb b/swift/spec/classes/swift_keystone_auth_spec.rb index 1e1e4960a..ecdf8c1e2 100644 --- a/swift/spec/classes/swift_keystone_auth_spec.rb +++ b/swift/spec/classes/swift_keystone_auth_spec.rb @@ -150,18 +150,18 @@ }) end it 'configures correct user name' do - should contain_keystone_user('swift') + is_expected.to contain_keystone_user('swift') end it 'configures correct user role' do - should contain_keystone_user_role('swift@services') + is_expected.to contain_keystone_user_role('swift@services') end it 'configures correct service name' do - should contain_keystone_service('swift_service') - should contain_keystone_service('swift_service_s3') + is_expected.to contain_keystone_service('swift_service') + is_expected.to contain_keystone_service('swift_service_s3') end it 'configures correct endpoint name' do - should contain_keystone_endpoint('RegionOne/swift_service') - should contain_keystone_endpoint('RegionOne/swift_service_s3') + is_expected.to contain_keystone_endpoint('RegionOne/swift_service') + is_expected.to contain_keystone_endpoint('RegionOne/swift_service_s3') end end diff --git a/swift/spec/defines/swift_storage_generic_spec.rb b/swift/spec/defines/swift_storage_generic_spec.rb index 77992c494..b63e8ed97 100644 --- a/swift/spec/defines/swift_storage_generic_spec.rb +++ b/swift/spec/defines/swift_storage_generic_spec.rb @@ -46,7 +46,10 @@ class { 'swift::storage': storage_local_net_ip => '10.0.0.1' }" let :params do param_set end - it { is_expected.to contain_package("swift-#{t}").with_ensure(param_hash[:package_ensure]) } + it { is_expected.to contain_package("swift-#{t}").with( + :ensure => param_hash[:package_ensure], + :tag => 'openstack' + )} it { is_expected.to contain_service("swift-#{t}").with( :ensure => 'running', :enable => true, diff --git a/swift/spec/unit/puppet/type/ring_account_device_spec.rb b/swift/spec/unit/puppet/type/ring_account_device_spec.rb index 98b3f0a49..11d5923ea 100644 --- a/swift/spec/unit/puppet/type/ring_account_device_spec.rb +++ b/swift/spec/unit/puppet/type/ring_account_device_spec.rb @@ -1,10 +1,9 @@ require 'puppet' describe Puppet::Type.type(:ring_account_device) do - - it 'should fail if the name has no ":"' do + it 'should fail if the name does not contain valid ipaddress' do expect { - Puppet::Type.type(:ring_account_device).new(:name => 'foo/bar') - }.to raise_error(Puppet::Error, /should contain address:port\/device/) + Puppet::Type.type(:ring_account_device).new(:name => '192.168.1.256:80/a') + }.to raise_error(Puppet::ResourceError, /invalid address/) end it 'should fail if the name does not contain a "/"' do diff --git a/swift/spec/unit/puppet/type/ring_container_device_spec.rb b/swift/spec/unit/puppet/type/ring_container_device_spec.rb index 80b436ab2..1b2cea8d1 100644 --- a/swift/spec/unit/puppet/type/ring_container_device_spec.rb +++ b/swift/spec/unit/puppet/type/ring_container_device_spec.rb @@ -1,16 +1,15 @@ require 'puppet' describe Puppet::Type.type(:ring_container_device) do - - it 'should fail if the name has no ":"' do + it 'should fail if the name does not contain valid ipaddress' do expect { - Puppet::Type.type(:ring_account_device).new(:name => 'foo/bar') - }.to raise_error(Puppet::Error, /should contain address:port\/device/) + Puppet::Type.type(:ring_container_device).new(:name => '192.168.1.256:80/a') + }.to raise_error(Puppet::ResourceError, /invalid address/) end it 'should fail if the name does not contain a "/"' do expect { - Puppet::Type.type(:ring_account_device).new(:name => 'foo:80') + Puppet::Type.type(:ring_container_device).new(:name => 'foo:80') }.to raise_error(Puppet::Error, /should contain a device/) end end diff --git a/swift/spec/unit/puppet/type/ring_object_device_spec.rb b/swift/spec/unit/puppet/type/ring_object_device_spec.rb index 05861bb17..4897f78cb 100644 --- a/swift/spec/unit/puppet/type/ring_object_device_spec.rb +++ b/swift/spec/unit/puppet/type/ring_object_device_spec.rb @@ -1,15 +1,14 @@ require 'puppet' describe Puppet::Type.type(:ring_object_device) do - - it 'should fail if the name has no ":"' do + it 'should fail if the name does not contain valid ipaddress' do expect { - Puppet::Type.type(:ring_account_device).new(:name => 'foo/bar') - }.to raise_error(Puppet::Error, /should contain address:port\/device/) + Puppet::Type.type(:ring_object_device).new(:name => '192.168.1.256:80/a') + }.to raise_error(Puppet::ResourceError, /invalid address/) end it 'should fail if the name does not contain a "/"' do expect { - Puppet::Type.type(:ring_account_device).new(:name => 'foo:80') + Puppet::Type.type(:ring_object_device).new(:name => 'foo:80') }.to raise_error(Puppet::Error, /should contain a device/) end end diff --git a/swift/templates/proxy-server.conf.erb b/swift/templates/proxy-server.conf.erb index 1a7987387..f6db44d09 100644 --- a/swift/templates/proxy-server.conf.erb +++ b/swift/templates/proxy-server.conf.erb @@ -33,6 +33,7 @@ log_handoffs = <%= @log_handoffs %> allow_account_management = <%= @allow_account_management %> account_autocreate = <%= @account_autocreate %> <% if @read_affinity -%> +sorting_method = affinity read_affinity = <%= @read_affinity -%> <% end %> <% if @write_affinity -%> diff --git a/tempest/spec/classes/tempest_spec.rb b/tempest/spec/classes/tempest_spec.rb index 9c6eba208..478c3f431 100644 --- a/tempest/spec/classes/tempest_spec.rb +++ b/tempest/spec/classes/tempest_spec.rb @@ -103,11 +103,21 @@ :image_name => 'image name', :image_name_alt => 'image name alt', :public_network_name => 'network name', - :neutron_available => true } + :neutron_available => true, + :install_from_source => true + } end describe "should install tempest" do it 'installs packages' do + + is_expected.to contain_package('git') + is_expected.to contain_package('python-setuptools') + + platform_params[:dev_packages].each do |package| + is_expected.to contain_package("#{package}") + end + is_expected.to contain_class('tempest::params') is_expected.to contain_exec('install-pip').with( @@ -176,6 +186,7 @@ is_expected.to contain_tempest_config('service_available/nova').with(:value => true) is_expected.to contain_tempest_config('service_available/swift').with(:value => false) is_expected.to contain_tempest_config('whitebox/db_uri').with(:value => nil) + is_expected.to contain_tempest_config('cli/cli_dir').with(:value => nil) end it 'set glance id' do @@ -208,7 +219,17 @@ context 'on Debian platforms' do let :facts do - { :osfamily => 'Debian' } + { :osfamily => 'Debian' } + end + + let :platform_params do + { :dev_packages => ['python-dev', + 'libxslt1-dev', + 'libxml2-dev', + 'libssl-dev', + 'libffi-dev', + 'patch', + 'gcc' ] } end it_behaves_like 'tempest' @@ -219,6 +240,16 @@ { :osfamily => 'RedHat' } end + let :platform_params do + { :dev_packages => ['python-devel', + 'libxslt-devel', + 'libxml2-devel', + 'openssl-devel', + 'libffi-devel', + 'patch', + 'gcc' ] } + end + it_behaves_like 'tempest' end diff --git a/tempest/spec/spec_helper.rb b/tempest/spec/spec_helper.rb index 6d13239e4..2d7f9eea4 100644 --- a/tempest/spec/spec_helper.rb +++ b/tempest/spec/spec_helper.rb @@ -4,3 +4,5 @@ RSpec.configure do |c| c.alias_it_should_behave_like_to :it_raises, 'raises' end + +at_exit { RSpec::Puppet::Coverage.report! } diff --git a/tripleo/manifests/loadbalancer.pp b/tripleo/manifests/loadbalancer.pp index 1d605076f..6601cf92a 100644 --- a/tripleo/manifests/loadbalancer.pp +++ b/tripleo/manifests/loadbalancer.pp @@ -58,6 +58,10 @@ # FQDN of the Galera master node # Defaults to undef # +# [*galera_master_ip*] +# IP of the Galera master node +# Defaults to undef +# # [*keystone_admin*] # (optional) Enable or not Keystone Admin API binding # Defaults to false @@ -130,6 +134,10 @@ # (optional) Enable or not RabbitMQ binding # Defaults to false # +# [*redis*] +# (optional) Enable or not Redis binding +# Defaults to false +# class tripleo::loadbalancer ( $controller_virtual_ip, $control_virtual_interface, @@ -139,6 +147,7 @@ $controller_hosts = undef, $controller_hosts_names = undef, $galera_master_hostname = undef, + $galera_master_ip = undef, $keystone_admin = false, $keystone_public = false, $neutron = false, @@ -157,6 +166,7 @@ $horizon = false, $mysql = false, $rabbitmq = false, + $redis = false, ) { if !$controller_host and !$controller_hosts { @@ -540,17 +550,23 @@ }, collect_exported => false, } - if downcase($galera_master_hostname) == $::hostname or !$galera_master_hostname { - $options_real = ['check', 'inter 2000', 'rise 2', 'fall 5'] - } else { - $options_real = ['check', 'inter 2000', 'rise 2', 'fall 5', 'backup'] - } + haproxy::balancermember { 'mysql': listening_service => 'mysql', ports => '3306', - ipaddresses => $controller_hosts_real, - server_names => $controller_hosts_names_real, - options => $options_real, + ipaddresses => $galera_master_ip, + server_names => $galera_master_hostname, + options => ['check', 'inter 2000', 'rise 2', 'fall 5'], + } + + $controller_hosts_without_galera_master = delete($controller_hosts_real, $galera_master_ip) + $controller_hosts_names_without_galera_master = delete($controller_hosts_names_real, downcase($galera_master_hostname)) + haproxy::balancermember { 'mysql-backup': + listening_service => 'mysql', + ports => '3306', + ipaddresses => $controller_hosts_without_galera_master, + server_names => $controller_hosts_names_without_galera_master, + options => ['check', 'inter 2000', 'rise 2', 'fall 5', 'backup'], } } @@ -572,4 +588,26 @@ } } + if $redis { + haproxy::listen { 'redis': + ipaddress => [$controller_virtual_ip], + ports => 6379, + options => { + 'timeout' => [ 'client 0', 'server 0' ], + 'mode' => 'tcp', + 'balance' => 'first', + 'option' => ['tcp-check',], + 'tcp-check' => ['send info\ replication\r\n','expect string role:master'], + }, + collect_exported => false, + } + haproxy::balancermember { 'redis': + listening_service => 'redis', + ports => '6379', + ipaddresses => $controller_hosts_real, + server_names => $controller_hosts_names_real, + options => ['check', 'inter 2000', 'rise 2', 'fall 5'], + } + } + } diff --git a/tripleo/manifests/redis_notification.pp b/tripleo/manifests/redis_notification.pp new file mode 100644 index 000000000..ad059a08f --- /dev/null +++ b/tripleo/manifests/redis_notification.pp @@ -0,0 +1,38 @@ +# Copyright 2015 Red Hat, Inc. +# All Rights Reserved. +# +# 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. +# +# == Class: tripleo::redis_notification +# +# Configure the Redis notification script that talks to HAProxy +# +# === Parameters: +# +# [*haproxy_monitor_ip*] +# (String) IP address on which HAProxy is listening on +# Defaults to 127.0.0.1 +# +class tripleo::redis_notification ( + $haproxy_monitor_ip = '127.0.0.1', +) { + + file { '/usr/local/bin/redis-notifications.sh' : + ensure => file, + content => template('tripleo/redis/redis-notifications.sh.erb'), + owner => 'root', + group => 'root', + mode => '0755', + } + +} diff --git a/tripleo/templates/redis/redis-notifications.sh.erb b/tripleo/templates/redis/redis-notifications.sh.erb new file mode 100644 index 000000000..aa368e9fa --- /dev/null +++ b/tripleo/templates/redis/redis-notifications.sh.erb @@ -0,0 +1,30 @@ +#!/bin/bash +HAPROXY="<%= @haproxy_monitor_ip %>:1993" +CMD="$1" +ARGS="$2" +ARG1=`echo $ARGS | awk '{print $1}'` + + +call_curl () { + DATA=`echo "s=$1&action=$2&b=%234" | sed -e s/:/%3A/` + curl --silent -o /dev/null $HAPROXY --data "$DATA" + echo curl $HAPROXY --data "$DATA" + return 0 +} + + +[ "$CMD" = "+odown" ] && [ "$ARG1" = "master" ] && \ + call_curl `echo $ARGS | awk '{print $2 ":" $3 ":" $4}'` 'disable' + +[ "$CMD" = "+sdown" ] && [ "$ARG1" = "slave" ] && \ + call_curl `echo $ARGS | awk '{print $6 ":" $3 ":" $4}'` 'disable' + +[ "$CMD" = "+switch-master" ] && \ + call_curl `echo $ARGS | awk '{print $1 ":" $4 ":" $5}'` 'enable' && + call_curl `echo $ARGS | awk '{print $1 ":" $2 ":" $3}'` 'disable' + +[ "$CMD" = "-odown" ] && [ "$ARG1" = "master" ] && \ + call_curl `echo $ARGS | awk '{print $2 ":" $3 ":" $4}'` 'enable' + +# without exit code, sentinel thinks the script is still running and locks any further execution +exit 0 diff --git a/vcsrepo/README.markdown b/vcsrepo/README.markdown index 9671fc592..2433d99ff 100644 --- a/vcsrepo/README.markdown +++ b/vcsrepo/README.markdown @@ -49,7 +49,7 @@ Also, this module, like Puppet generally, will not create parent directories for To get started with the vcsrepo module, you must simply define the type `vcsrepo` with a path to your repository and the [type of VCS](#Usage) you're using in `provider` (in the below example, Git). - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, } @@ -75,14 +75,14 @@ The vcsrepo module works with the following VCSs: To create a blank repository suitable for use as a central repository, define `vcsrepo` without `source` or `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, } If you're defining `vcsrepo` for a central or official repository, you may want to make it a bare repository. You do this by setting `ensure` to 'bare' rather than 'present'. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => bare, provider => git, } @@ -91,17 +91,17 @@ If you're defining `vcsrepo` for a central or official repository, you may want To get the current HEAD on the master branch, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, - source => "git://example.com/repo.git", + source => 'git://example.com/repo.git', } To get a specific revision or branch (can be a commit SHA, tag, or branch name), **SHA** - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, source => 'git://example.com/repo.git', @@ -110,7 +110,7 @@ To get a specific revision or branch (can be a commit SHA, tag, or branch name), **Tag** - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, source => 'git://example.com/repo.git', @@ -119,7 +119,7 @@ To get a specific revision or branch (can be a commit SHA, tag, or branch name), **Branch name** - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, source => 'git://example.com/repo.git', @@ -128,7 +128,7 @@ To get a specific revision or branch (can be a commit SHA, tag, or branch name), To check out a branch as a specific user, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, source => 'git://example.com/repo.git', @@ -138,7 +138,7 @@ To check out a branch as a specific user, To keep the repository at the latest revision (**WARNING:** this will always overwrite local changes to the repository), - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => latest, provider => git, source => 'git://example.com/repo.git', @@ -147,7 +147,7 @@ To keep the repository at the latest revision (**WARNING:** this will always ove To clone the repository but skip initialiazing submodules, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => latest, provider => git, source => 'git://example.com/repo.git', @@ -157,12 +157,12 @@ To clone the repository but skip initialiazing submodules, ##### Using multiple remotes with a repository Instead of specifying a single string in the 'source' property, you can specify a hash with multiple name => URL mappings, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => git, source => { - "origin" => "https://github.com/puppetlabs/puppetlabs-vcsrepo.git", - "other_remote" => "https://github.com/other_user/puppetlabs-vcsrepo.git" + origin => 'https://github.com/puppetlabs/puppetlabs-vcsrepo.git', + other_remote => 'https://github.com/other_user/puppetlabs-vcsrepo.git' }, } @@ -187,7 +187,7 @@ For more examples using Git, see `examples/git/`. To create a blank repository suitable for use as a central repository, define `vcsrepo` without `source` or `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => bzr, } @@ -196,7 +196,7 @@ define `vcsrepo` without `source` or `revision`. Provide the `source` location to branch from an existing repository. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => bzr, source => 'lp:myproj', @@ -205,7 +205,7 @@ Provide the `source` location to branch from an existing repository. For a specific revision, use `revision` with a valid revisionspec (see `bzr help revisionspec` for more information on formatting a revision). - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => bzr, source => 'lp:myproj', @@ -228,7 +228,7 @@ For more examples using Bazaar, see `examples/bzr/`. To create a blank repository suitable for use as a central repository, define `vcsrepo` without `source` or `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => cvs, } @@ -237,39 +237,39 @@ define `vcsrepo` without `source` or `revision`. To get the current mainline, - vcsrepo { "/path/to/workspace": + vcsrepo { '/path/to/workspace': ensure => present, provider => cvs, - source => ":pserver:anonymous@example.com:/sources/myproj", + source => ':pserver:anonymous@example.com:/sources/myproj', } To get a specific module on the current mainline, - vcsrepo {"/vagrant/lockss-daemon-source": + vcsrepo {'/vagrant/lockss-daemon-source': ensure => present, provider => cvs, - source => ":pserver:anonymous@lockss.cvs.sourceforge.net:/cvsroot/lockss", - module => "lockss-daemon", + source => ':pserver:anonymous@lockss.cvs.sourceforge.net:/cvsroot/lockss', + module => 'lockss-daemon', } You can use the `compression` parameter to set the GZIP compression levels for your repository history. - vcsrepo { "/path/to/workspace": + vcsrepo { '/path/to/workspace': ensure => present, provider => cvs, compression => 3, - source => ":pserver:anonymous@example.com:/sources/myproj", + source => ':pserver:anonymous@example.com:/sources/myproj', } For a specific tag, use `revision`. - vcsrepo { "/path/to/workspace": + vcsrepo { '/path/to/workspace': ensure => present, provider => cvs, compression => 3, - source => ":pserver:anonymous@example.com:/sources/myproj", - revision => "SOMETAG", + source => ':pserver:anonymous@example.com:/sources/myproj', + revision => 'SOMETAG', } #####Sources that use SSH @@ -287,7 +287,7 @@ For for more examples using CVS, see `examples/cvs/`. To create a blank repository suitable for use as a central repository, define `vcsrepo` without `source` or `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, } @@ -296,51 +296,51 @@ define `vcsrepo` without `source` or `revision`. To get the default branch tip, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, - source => "http://hg.example.com/myrepo", + source => 'http://hg.example.com/myrepo', } For a specific changeset, use `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, - source => "http://hg.example.com/myrepo", + source => 'http://hg.example.com/myrepo', revision => '21ea4598c962', } You can also set `revision` to a tag. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, - source => "http://hg.example.com/myrepo", + source => 'http://hg.example.com/myrepo', revision => '1.1.2', } To check out as a specific user, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, - source => "http://hg.example.com/myrepo", + source => 'http://hg.example.com/myrepo', user => 'user', } To specify an SSH identity key, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => hg, - source => "ssh://hg@hg.example.com/myrepo", - identity => "/home/user/.ssh/id_dsa, + source => 'ssh://hg@hg.example.com/myrepo', + identity => '/home/user/.ssh/id_dsa', } To specify a username and password for HTTP Basic authentication, - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => latest, provider => hg, source => 'http://hg.example.com/myrepo', @@ -364,7 +364,7 @@ To create an empty Workspace, define a `vcsrepo` without a `source` or `revision Environment variables P4PORT, P4USER, etc... are used to define the Perforce server connection settings. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => p4 } @@ -378,7 +378,7 @@ A Perforce configuration file can be used by setting the `P4CONFIG` environment defining `p4config`. If a configuration is defined, then the environment variable for `P4CLIENT` is replaced. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => p4, p4config => '.p4config' @@ -388,7 +388,7 @@ defining `p4config`. If a configuration is defined, then the environment variab To sync a depot path to head, ensure `latest`: - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => latest, provider => p4, source => '//depot/branch/...' @@ -396,7 +396,7 @@ To sync a depot path to head, ensure `latest`: For a specific changelist, ensure `present` and specify a `revision`: - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => p4, source => '//depot/branch/...', @@ -405,7 +405,7 @@ For a specific changelist, ensure `present` and specify a `revision`: You can also set `revision` to a label: - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => p4, source => '//depot/branch/...', @@ -428,7 +428,7 @@ For examples you can run, see `examples/p4/` To create a blank repository suitable for use as a central repository, define `vcsrepo` without `source` or `revision`. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => svn, } @@ -437,18 +437,18 @@ define `vcsrepo` without `source` or `revision`. Provide a `source` pointing to the branch/tag you want to check out from a repository. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => svn, - source => "svn://svnrepo/hello/branches/foo", + source => 'svn://svnrepo/hello/branches/foo', } You can also provide a specific revision. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => svn, - source => "svn://svnrepo/hello/branches/foo", + source => 'svn://svnrepo/hello/branches/foo', revision => '1234', } @@ -456,11 +456,11 @@ You can also provide a specific revision. To use a specific configuration directory, provide a `configuration` parameter which should be a directory path on the local system where your svn configuration files are. Typically, it is '/path/to/.subversion'. - vcsrepo { "/path/to/repo": + vcsrepo { '/path/to/repo': ensure => present, provider => svn, - source => "svn://svnrepo/hello/branches/foo", - configuration => "/path/to/.subversion", + source => 'svn://svnrepo/hello/branches/foo', + configuration => '/path/to/.subversion', } #####Sources that use SSH diff --git a/vswitch/Gemfile b/vswitch/Gemfile index f3182fde2..b0b2d45ff 100644 --- a/vswitch/Gemfile +++ b/vswitch/Gemfile @@ -2,10 +2,20 @@ source 'https://rubygems.org' group :development, :test do gem 'puppetlabs_spec_helper', :require => false - gem 'puppet-lint', '~> 0.3.2' - gem 'rspec-puppet', '~> 1.0.1' - gem 'rake', '10.1.1' - gem 'rspec', '< 2.99' + gem 'rspec-puppet', '~> 2.0.0', :require => false + + gem 'metadata-json-lint' + gem 'puppet-lint-param-docs' + gem 'puppet-lint-absolute_classname-check' + gem 'puppet-lint-absolute_template_path' + gem 'puppet-lint-trailing_newline-check' + + # Puppet 4.x related lint checks + gem 'puppet-lint-unquoted_string-check' + gem 'puppet-lint-leading_zero-check' + gem 'puppet-lint-variable_contains_upcase' + gem 'puppet-lint-numericvariable' + gem 'json' gem 'webmock' end diff --git a/vswitch/manifests/init.pp b/vswitch/manifests/init.pp index 196e655b8..d0d51cab8 100644 --- a/vswitch/manifests/init.pp +++ b/vswitch/manifests/init.pp @@ -27,6 +27,6 @@ class vswitch ( $provider = $vswitch::params::provider ) { - $cls = "vswitch::${provider}" + $cls = "::vswitch::${provider}" include $cls } diff --git a/vswitch/manifests/ovs.pp b/vswitch/manifests/ovs.pp index 9ce892ccf..e04c6226f 100644 --- a/vswitch/manifests/ovs.pp +++ b/vswitch/manifests/ovs.pp @@ -1,10 +1,14 @@ # vswitch: open-vswitch # +# [*package_ensure*] +# (Optional) State of the openvswitch package +# Defaults to 'present'. +# class vswitch::ovs( $package_ensure = 'present' ) { - include 'vswitch::params' + include ::vswitch::params case $::osfamily { 'Debian': { @@ -21,27 +25,27 @@ $ovs_status = '/etc/init.d/openvswitch-switch status | fgrep "is running"' } } - service {'openvswitch': - ensure => true, - enable => true, - name => $::vswitch::params::ovs_service_name, - hasstatus => false, # the supplied command returns true even if it's not running + service { 'openvswitch': + ensure => true, + enable => true, + name => $::vswitch::params::ovs_service_name, + hasstatus => false, # the supplied command returns true even if it's not running # Not perfect - should spot if either service is not running - but it'll do - status => $ovs_status + status => $ovs_status, } exec { 'rebuild-ovsmod': command => '/usr/sbin/dpkg-reconfigure openvswitch-datapath-dkms > /tmp/reconf-log', creates => "/lib/modules/${::kernelrelease}/updates/dkms/openvswitch_mod.ko", require => [Package['openvswitch-datapath-dkms', $kernelheaders_pkg]], before => Package['openvswitch-switch'], - refreshonly => true + refreshonly => true, } } 'Redhat': { - service {'openvswitch': - ensure => true, - enable => true, - name => $::vswitch::params::ovs_service_name, + service { 'openvswitch': + ensure => true, + enable => true, + name => $::vswitch::params::ovs_service_name, } } default: { @@ -50,8 +54,8 @@ } package { $::vswitch::params::ovs_package_name: - ensure => $package_ensure, - before => Service['openvswitch'], + ensure => $package_ensure, + before => Service['openvswitch'], } Service['openvswitch'] -> Vs_port<||> diff --git a/vswitch/metadata.json b/vswitch/metadata.json index 69c3b704e..d16d076dd 100644 --- a/vswitch/metadata.json +++ b/vswitch/metadata.json @@ -3,7 +3,7 @@ "version": "1.0.0", "source": "https://github.com/stackforge/puppet-vswitch", "author": "Endre Karlson, Dan Bode and StackForge Contributors", - "license": "Apache License 2.0", + "license": "Apache-2.0", "source": "git://github.com/stackforge/puppet-vswitch.git", "project_page": "https://launchpad.net/puppet-vswitch", "issues_url": "https://bugs.launchpad.net/puppet-vswitch", diff --git a/vswitch/spec/classes/vswitch_ovs_spec.rb b/vswitch/spec/classes/vswitch_ovs_spec.rb index de7e14651..c3b0d2928 100644 --- a/vswitch/spec/classes/vswitch_ovs_spec.rb +++ b/vswitch/spec/classes/vswitch_ovs_spec.rb @@ -10,13 +10,13 @@ it 'should contain the correct package and service' do - should contain_service('openvswitch').with( + is_expected.to contain_service('openvswitch').with( :ensure => true, :enable => true, :name => 'openvswitch' ) - should contain_package('openvswitch').with( + is_expected.to contain_package('openvswitch').with( :name => 'openvswitch', :ensure => 'present', :before => 'Service[openvswitch]' diff --git a/xinetd/.travis.yml b/xinetd/.travis.yml index e69e7f5be..b523f5ba1 100644 --- a/xinetd/.travis.yml +++ b/xinetd/.travis.yml @@ -1,6 +1,6 @@ --- language: ruby -bundler_args: --without development +bundler_args: --without system_tests script: "bundle exec rake spec SPEC_OPTS='--format documentation'" rvm: - 1.8.7 diff --git a/xinetd/Gemfile b/xinetd/Gemfile index 6d274a4b2..3cdc63c34 100644 --- a/xinetd/Gemfile +++ b/xinetd/Gemfile @@ -1,10 +1,13 @@ source 'https://rubygems.org' -group :development, :test do +group :development, :unit_test do gem 'rake', :require => false gem 'rspec-puppet', '~> 1.0', :require => false gem 'puppetlabs_spec_helper', :require => false gem 'puppet-lint', :require => false +end + +group :system_tests do gem 'serverspec', :require => false gem 'rspec-system', :require => false gem 'rspec-system-puppet', :require => false diff --git a/xinetd/README.md b/xinetd/README.md index ada4d0e9d..21dc2ab0d 100644 --- a/xinetd/README.md +++ b/xinetd/README.md @@ -24,6 +24,31 @@ package names and service needs. * `service_hasrestart` * `service_hasstatus` +Additionally, all the global defaults in the main xinetd.conf can be set. By +default they are *not* set, allowing the internal xinetd defaults to be used: +(see `man xinetd.conf` for full descriptions) + + * `enabled` - Takes a list of service ID's to enable. + * `disabled` - Takes a list of service ID's to disable. + * `log_type` - Determines where the service log output is sent. + * `log_on_failure` - Determines what information is logged when a server cannot be started. + * `log_on_success` - Determines what information is logged when a server is started and when that server exits. + * `no_access` - Determines the remote hosts to which the particular service is unavailable. + * `only_from` - Determines the remote hosts to which the particular service is available. + * `max_load` - Takes a floating point value as the load at which the service will stop accepting connections. + * `instances` - Determines the number of servers that can be simultaneously active for a service (the default is no limit). + * `per_source` - This specifies the maximum instances of this service per source IP address. + * `bind` - Allows a service to be bound to a specific interface on the machine. + * `mdns` - On systems that support mdns registration of services (currently only Mac OS X), this will enable or disable registration of the service. + * `v6only` - Set to yes to use IPv6 only. + * `passenv` - The value of this attribute is a list of environment variables from xinetd's environment that will be passed to the server. + * `env` - The value of this attribute is a list of environment variables that will be added to the environment before starting a server. + * `groups` - If the groups attribute is set to "yes", then the server is executed with access to the groups that the server's effective UID has access to. + * `umask` - Sets the inherited umask for the service. + * `banner` - Takes the name of a file to be splatted at the remote host when a connection to that service is established. + * `banner_fail` - Takes the name of a file to be splatted at the remote host when a connection to that service is denied. + * `banner_success` - Takes the name of a file to be splatted at the remote host when a connection to that service is granted. + ## Definition: xinetd::service Sets up a xinetd service. All parameters match up with xinetd.conf(5) man diff --git a/xinetd/Rakefile b/xinetd/Rakefile index bb60173e5..4b927db0b 100644 --- a/xinetd/Rakefile +++ b/xinetd/Rakefile @@ -1,2 +1,5 @@ require 'puppetlabs_spec_helper/rake_tasks' -require 'rspec-system/rake_task' +begin + require 'rspec-system/rake_task' +rescue LoadError +end diff --git a/xinetd/manifests/init.pp b/xinetd/manifests/init.pp index 226793da6..aa0b4923e 100644 --- a/xinetd/manifests/init.pp +++ b/xinetd/manifests/init.pp @@ -19,7 +19,27 @@ $service_status = $xinetd::params::service_status, $service_hasrestart = $xinetd::params::service_hasrestart, $service_hasstatus = $xinetd::params::service_hasstatus, - $purge_confdir = false, + $enabled = undef, + $disabled = undef, + $log_type = undef, + $log_on_failure = undef, + $log_on_success = undef, + $no_access = undef, + $only_from = undef, + $max_load = undef, + $instances = undef, + $per_source = undef, + $bind = undef, + $mdns = undef, + $v6only = undef, + $env = undef, + $passenv = undef, + $groups = undef, + $umask = undef, + $banner = undef, + $banner_fail = undef, + $banner_success = undef, + $purge_confdir = undef, ) inherits xinetd::params { File { diff --git a/xinetd/manifests/service.pp b/xinetd/manifests/service.pp index 3a0371fc3..43d122d71 100644 --- a/xinetd/manifests/service.pp +++ b/xinetd/manifests/service.pp @@ -89,7 +89,8 @@ $access_times = undef, $log_type = undef, $bind = undef, - $nice = undef + $nice = undef, + $env = undef, ) { include xinetd diff --git a/xinetd/spec/classes/xinetd_init_spec.rb b/xinetd/spec/classes/xinetd_init_spec.rb index 39b471bbb..7728cd544 100644 --- a/xinetd/spec/classes/xinetd_init_spec.rb +++ b/xinetd/spec/classes/xinetd_init_spec.rb @@ -2,22 +2,109 @@ describe 'xinetd' do - let :facts do - { :osfamily => 'Debian' } + context 'When using default values' do + let :facts do + { :osfamily => 'Debian' } + end + it { + should contain_package('xinetd') + should contain_file('/etc/xinetd.conf') + should contain_service('xinetd') + } + it { + # Ensure that the config file allows xinetd to use its own defaults + should contain_file('/etc/xinetd.conf').without_content(/enabled *=/) + should contain_file('/etc/xinetd.conf').without_content(/disabled *=/) + should contain_file('/etc/xinetd.conf').without_content(/log_type *=/) + should contain_file('/etc/xinetd.conf').without_content(/log_on_failure *=/) + should contain_file('/etc/xinetd.conf').without_content(/log_on_success *=/) + should contain_file('/etc/xinetd.conf').without_content(/no_access *=/) + should contain_file('/etc/xinetd.conf').without_content(/only_from *=/) + should contain_file('/etc/xinetd.conf').without_content(/max_load *=/) + should contain_file('/etc/xinetd.conf').without_content(/instances *=/) + should contain_file('/etc/xinetd.conf').without_content(/per_source *=/) + should contain_file('/etc/xinetd.conf').without_content(/bind *=/) + should contain_file('/etc/xinetd.conf').without_content(/mdns *=/) + should contain_file('/etc/xinetd.conf').without_content(/v6only *=/) + should contain_file('/etc/xinetd.conf').without_content(/passenv *=/) + should contain_file('/etc/xinetd.conf').without_content(/env *=/) + should contain_file('/etc/xinetd.conf').without_content(/groups *=/) + should contain_file('/etc/xinetd.conf').without_content(/umask *=/) + should contain_file('/etc/xinetd.conf').without_content(/banner *=/) + should contain_file('/etc/xinetd.conf').without_content(/banner_fail *=/) + should contain_file('/etc/xinetd.conf').without_content(/banner_success *=/) + } end - describe 'with defaults' do + context 'When overriding the default vaules' do + let :facts do + { :osfamily => 'Debian' } + end + let :params do + { :enabled => 'tftp nrpe', + :disabled => 'time echo', + :log_type => 'SYSLOG daemon info', + :log_on_failure => 'HOST', + :log_on_success => 'PID HOST DURATION EXIT', + :no_access => '128.138.209.10', + :only_from => '127.0.0.1', + :max_load => '2', + :instances => '50', + :per_source => '50', + :bind => '0.0.0.0', + :mdns => 'yes', + :v6only => 'no', + :env => 'foo=bar', + :passenv => 'yes', + :groups => 'yes', + :umask => '002', + :banner => '/etc/banner', + :banner_fail => '/etc/banner.fail', + :banner_success => '/etc/banner.good', + } + end + it { + # Ensure that the config file allows xinetd to use its own defaults + should contain_file('/etc/xinetd.conf').with_content(/enabled *= tftp nrpe/) + should contain_file('/etc/xinetd.conf').with_content(/disabled *= time echo/) + should contain_file('/etc/xinetd.conf').with_content(/log_type *= SYSLOG daemon info/) + should contain_file('/etc/xinetd.conf').with_content(/log_on_failure *= HOST/) + should contain_file('/etc/xinetd.conf').with_content(/log_on_success *= PID HOST DURATION EXIT/) + should contain_file('/etc/xinetd.conf').with_content(/no_access *= 128.138.209.10/) + should contain_file('/etc/xinetd.conf').with_content(/only_from *= 127.0.0.1/) + should contain_file('/etc/xinetd.conf').with_content(/max_load *= 2/) + should contain_file('/etc/xinetd.conf').with_content(/instances *= 50/) + should contain_file('/etc/xinetd.conf').with_content(/per_source *= 50/) + should contain_file('/etc/xinetd.conf').with_content(/bind *= 0.0.0.0/) + should contain_file('/etc/xinetd.conf').with_content(/mdns *= yes/) + should contain_file('/etc/xinetd.conf').with_content(/v6only *= no/) + should contain_file('/etc/xinetd.conf').with_content(/env *= foo=bar/) + should contain_file('/etc/xinetd.conf').with_content(/passenv *= yes/) + should contain_file('/etc/xinetd.conf').with_content(/passenv *= yes/) + should contain_file('/etc/xinetd.conf').with_content(/groups *= yes/) + should contain_file('/etc/xinetd.conf').with_content(/umask *= 002/) + should contain_file('/etc/xinetd.conf').with_content(/banner *= \/etc\/banner/) + should contain_file('/etc/xinetd.conf').with_content(/banner_fail *= \/etc\/banner\.fail/) + should contain_file('/etc/xinetd.conf').with_content(/banner_success *= \/etc\/banner\.good/) + } + end + + context 'with defaults' do + let :facts do + { :osfamily => 'Debian' } + end it { should contain_package('xinetd') should contain_file('/etc/xinetd.conf') should contain_file('/etc/xinetd.d').with_ensure('directory') - should contain_file('/etc/xinetd.d').with_recurse(false) - should contain_file('/etc/xinetd.d').with_purge(false) should contain_service('xinetd') } end - describe 'with managed confdir' do + context 'with managed confdir' do + let :facts do + { :osfamily => 'Debian' } + end let :params do { :purge_confdir => true } end diff --git a/xinetd/templates/service.erb b/xinetd/templates/service.erb index a35f15471..cf44c3683 100644 --- a/xinetd/templates/service.erb +++ b/xinetd/templates/service.erb @@ -54,4 +54,7 @@ service <%= @service_name %> <% if @nice -%> nice = <%= @nice %> <% end -%> +<% if @env -%> + env = <%= @env %> +<% end -%> } diff --git a/xinetd/templates/xinetd.conf.erb b/xinetd/templates/xinetd.conf.erb index 3a0842966..e9412577c 100644 --- a/xinetd/templates/xinetd.conf.erb +++ b/xinetd/templates/xinetd.conf.erb @@ -11,41 +11,79 @@ defaults { # The next two items are intended to be a quick access place to # temporarily enable or disable services. -# -# enabled = -# disabled = +<% if @enabled -%> + enabled = <%= @enabled -%> +<% end %> +<% if @disabled -%> + disabled = <%= @disabled -%> +<% end %> # Define general logging characteristics. - log_type = SYSLOG daemon info - log_on_failure = HOST - log_on_success = PID HOST DURATION EXIT +<% if @log_type -%> + log_type = <%= @log_type -%> +<% end %> +<% if @log_on_failure -%> + log_on_failure = <%= @log_on_failure -%> +<% end %> +<% if @log_on_success -%> + log_on_success = <%= @log_on_success -%> +<% end %> # Define access restriction defaults -# -# no_access = -# only_from = -# max_load = 0 - cps = 50 10 - instances = 50 - per_source = 10 +<% if @no_access -%> + no_access = <%= @no_access -%> +<% end %> +<% if @only_from -%> + only_from = <%= @only_from -%> +<% end %> +<% if @max_load -%> + max_load = <%= @max_load -%> +<% end %> +<% if @cps -%> + cps = <%= @cps -%> +<% end %> +<% if @instances -%> + instances = <%= @instances -%> +<% end %> +<% if @per_source -%> + per_source = <%= @per_source -%> +<% end %> # Address and networking defaults -# -# bind = -# mdns = yes - v6only = no +<% if @bind -%> + bind = <%= @bind -%> +<% end %> +<% if @mdns -%> + mdns = <%= @mdns -%> +<% end %> +<% if @v6only -%> + v6only = <%= @v6only -%> +<% end %> # setup environmental attributes -# -# passenv = - groups = yes - umask = 002 +<% if @env -%> + env = <%= @env -%> +<% end %> +<% if @passenv -%> + passenv = <%= @passenv -%> +<% end %> +<% if @groups -%> + groups = <%= @groups -%> +<% end %> +<% if @umask -%> + umask = <%= @umask -%> +<% end %> # Generally, banners are not used. This sets up their global defaults -# -# banner = -# banner_fail = -# banner_success = +<% if @banner -%> + banner = <%= @banner -%> +<% end %> +<% if @banner_fail -%> + banner_fail = <%= @banner_fail -%> +<% end %> +<% if @banner_success -%> + banner_success = <%= @banner_success -%> +<% end %> } includedir <%= @confdir %>