From b0b40873dfbc04b9a5649f99eee2fc1095fb7267 Mon Sep 17 00:00:00 2001 From: Ivan Chavero Date: Thu, 6 Aug 2015 16:19:34 -0600 Subject: [PATCH 01/54] Update n1k_vsm to 7b57af350fdb25830e0136658324f9c51e49657f 7b57af350fdb25830e0136658324f9c51e49657f Add support for tagged interfaces and require ovs module Fixes: rhbz#1227059 Change-Id: Ia2788196f524d3df822ee0492c03d44841e1bb1c (cherry picked from commit 5a0dbe3df4d3104624ba235cc1e87997816048c5) --- Puppetfile | 2 +- n1k_vsm/manifests/init.pp | 7 ++++--- n1k_vsm/manifests/pkgprep_ovscfg.pp | 29 +++++++++++++++-------------- n1k_vsm/manifests/vsmprep.pp | 2 +- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/Puppetfile b/Puppetfile index 1b6a7987b..045e237b6 100644 --- a/Puppetfile +++ b/Puppetfile @@ -111,7 +111,7 @@ mod 'mysql', :git => 'https://github.com/puppetlabs/puppetlabs-mysql.git' mod 'n1k_vsm', - :commit => 'ed391d3d9bdcccef3e2de3b0da98e654237d99a5', + :commit => '7b57af350fdb25830e0136658324f9c51e49657f', :git => 'https://github.com/stackforge/puppet-n1k-vsm.git' mod 'nagios', diff --git a/n1k_vsm/manifests/init.pp b/n1k_vsm/manifests/init.pp index a9ee4e83c..13307a44e 100644 --- a/n1k_vsm/manifests/init.pp +++ b/n1k_vsm/manifests/init.pp @@ -76,10 +76,11 @@ $ovsbridge = 'vsm-br' #VSM installation will be done only once. Will not respond to puppet sync - $_phy_ip_addr = inline_template("<%= scope.lookupvar('::ipaddress_${n1k_vsm::phy_if_bridge}') %>") + $_phy_if_bridge = regsubst($n1k_vsm::phy_if_bridge, '[.:-]+', '_', 'G') + $_phy_ip_addr = inline_template("<%= scope.lookupvar('::ipaddress_${_phy_if_bridge}') %>") if $_phy_ip_addr != '' { - $phy_ip_addr = inline_template("<%= scope.lookupvar('::ipaddress_${n1k_vsm::phy_if_bridge}') %>") - $phy_ip_mask = inline_template("<%= scope.lookupvar('::netmask_${n1k_vsm::phy_if_bridge}') %>") + $phy_ip_addr = inline_template("<%= scope.lookupvar('::ipaddress_${_phy_if_bridge}') %>") + $phy_ip_mask = inline_template("<%= scope.lookupvar('::netmask_${_phy_if_bridge}') %>") $gw_intf = $n1k_vsm::phy_gateway include n1k_vsm::pkgprep_ovscfg } diff --git a/n1k_vsm/manifests/pkgprep_ovscfg.pp b/n1k_vsm/manifests/pkgprep_ovscfg.pp index 577cd9fb4..073fd985f 100644 --- a/n1k_vsm/manifests/pkgprep_ovscfg.pp +++ b/n1k_vsm/manifests/pkgprep_ovscfg.pp @@ -53,17 +53,8 @@ unless => '/usr/bin/virsh net-info default | /bin/grep -c \'Autostart: .* no\'', } - package { 'Package_ovs': - ensure => installed, - name => 'openvswitch', - } - - # bring up OVS and perform interface configuration - service { 'Service_ovs': - ensure => running, - name => 'openvswitch', - enable => true, - } + # Ensure OVS is present + require vswitch::ovs package { 'genisoimage': ensure => installed, @@ -110,14 +101,22 @@ 'set BOOTPROTO none', 'set ONBOOT yes', "set NAME ${n1k_vsm::phy_if_bridge}", - 'rm IPADDR', + 'set DEFROUTE no', + 'set IPADDR ""', 'rm NETMASK', 'rm GATEWAY', 'set USERCTL no', ], - notify => Service['Service_network'], } - # Make sure that networking comes fine after reboot + exec { 'Flap_n1kv_phy_if': + command => "/sbin/ifdown ${n1k_vsm::phy_if_bridge} && /sbin/ifup ${n1k_vsm::phy_if_bridge}", + require => augeas['Augeas_modify_ifcfg-phy_if_bridge'], + } + exec { 'Flap_n1kv_bridge': + command => "/sbin/ifdown ${n1k_vsm::ovsbridge} && /sbin/ifup ${n1k_vsm::ovsbridge}", + require => augeas['Augeas_modify_ifcfg-ovsbridge'], + } + # Make sure that networking comes fine after reboot- add init file and restart networking file { 'Create_Init_File': replace => 'yes', path => '/etc/init.d/n1kv', @@ -125,6 +124,8 @@ group => 'root', mode => '0775', source => 'puppet:///modules/n1k_vsm/n1kv', + require => exec['Flap_n1kv_phy_if', 'Flap_n1kv_bridge'], + notify => Service['Service_network'], } } # endif of if "${n1k_vsm::gw_intf}" != "${n1k_vsm::ovsbridge}" } diff --git a/n1k_vsm/manifests/vsmprep.pp b/n1k_vsm/manifests/vsmprep.pp index 32447022f..f7046662a 100644 --- a/n1k_vsm/manifests/vsmprep.pp +++ b/n1k_vsm/manifests/vsmprep.pp @@ -80,7 +80,7 @@ # Now generate ovf xml file and repackage the iso exec { 'Exec_VSM_Repackage_Script': - command => "/tmp/repackiso.py -i/var/spool/cisco/vsm/${n1k_vsm::n1kv_version}.iso -d${n1k_vsm::vsm_domain_id} -n${n1k_vsm::vsmname} -m${n1k_vsm::mgmtip} -s${n1k_vsm::mgmtnetmask} -g${n1k_vsm::mgmtgateway} -p${n1k_vsm::vsm_admin_passwd} -r${n1k_vsm::vsm_role} -f/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_repacked.iso ", + command => "/tmp/repackiso.py -i${vsm_path}/n1000v-dk9.${n1k_vsm::n1kv_version}.iso -d${n1k_vsm::vsm_domain_id} -n${n1k_vsm::vsmname} -m${n1k_vsm::mgmtip} -s${n1k_vsm::mgmtnetmask} -g${n1k_vsm::mgmtgateway} -p${n1k_vsm::vsm_admin_passwd} -r${n1k_vsm::vsm_role} -f/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_repacked.iso ", unless => "/usr/bin/virsh list --all | grep -c ${n1k_vsm::vsmname}", } From 0fb9a874a93fb3b49249105a85d122dcdb6a41dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=A1gr?= Date: Tue, 8 Sep 2015 15:02:24 +0200 Subject: [PATCH 02/54] Automatic update This module update commit was generated by Bade. For more info please check https://github.com/paramite/bade This commit is setting modules to following state: ceilometer - old commit: f17b3442402529281bdca9b2f70697e04bcfe216 - new commit: 05926aaaba5f733f7be1f3e57b59db3ee1385db3 cinder - old commit: 15fd1a81b047342e71bfe939cf059eb4fd143e4d - new commit: b2163382956032f6df37d8a02f18a4abf89b7008 glance - old commit: 0bb7577f7e4189495a148ca91f4f92c118e499e7 - new commit: c2d8e72f594b0caab0ace8c17d59717a3dd13385 heat - old commit: 8e742b8d09e3bded06e9529ccd5e7f38e527ab5d - new commit: 108e9b092698e423840cef6ac24233313b9470b1 horizon - old commit: 6e11fbf346560dab461964e53bcb1c817707abc5 - new commit: 79e373bebc010c25410a684437ae41b60e8eefc8 ironic - old commit: 886a9c0aa2c8ac6167e2d95a60c55bbd6977f82b - new commit: 88c228cca9d74072a5e944acf0063418b9bdfe4e keystone - old commit: e0e87604b8199c0ac0d443999153f88fb7797a9c - new commit: 5f9080f3adf14921f025038533bfcb9ebdee564c manila - old commit: ff018bdef812bacfe512663c1cc0b92c7d1f26b2 - new commit: b94391158dc7c392986db9b0eb63562dde411ea1 neutron - old commit: 36b463c003f94fe23c3d9eff207bbf5005ee470c - new commit: c683ca5fc31111b7b0569cc71e9b959e62d21c4b nova - old commit: cb2d487fb9baf2c1902182973e29982b5389e769 - new commit: 52e7f810a50f15e2c32cd1270374899ef7df675f openstack_extras - old commit: ab8ddaff93e06d7fdbfb2c61ffe9113562dd82ad - new commit: 2d08ba975b65c613fbdc08812cbf30e7d6c9d6e4 openstacklib - old commit: 78ef674e0e6bc73b3a0af7833025dc9786eaeaeb - new commit: fcfffcf47069119805e44cc712739ba0c1e4603d sahara - old commit: 56d9a841bff7389d1128d40dad4a319988d547f1 - new commit: 6e79d710a97d7c43aea766bbfa8c4d782a7c2049 swift - old commit: 275fb9b111bbb30148e762afc0798aa891091cf2 - new commit: d736e6a00e8ff1e4f05c8fbc9535908fc2112587 tempest - old commit: ab9601ff339f6acb40901291133c03cf1b45d5ee - new commit: 4cc2ad2e827e1117d79dbab1bc91283428ffdc78 trove - old commit: 2636a384f67c2ac1513ac709f3ae4525668ccb62 - new commit: 1c5d6895c86fdb99501c72ef999864268bb7a389 tuskar - old commit: 85a3991330f36903cd66a6e12512b54ab758ec41 - new commit: 09e2ced9be2cdf5d94dd6310e9df3a3155ab549b vswitch - old commit: e73073a120d833958d22925a1badbc1ccdc0f15a - new commit: 5992d41a238c93bcf6bd6989c23d3c7577c48b69 Change-Id: Ia115e24cf0e98b808ee2d2b64a67924ea6d6db79 --- Puppetfile | 36 +- ceilometer/CHANGELOG.md | 29 + ceilometer/README.md | 2 +- ceilometer/manifests/api.pp | 52 +- ceilometer/manifests/params.pp | 2 +- ceilometer/metadata.json | 8 +- .../acceptance/ceilometer_wsgi_apache_spec.rb | 133 +++++ .../spec/classes/ceilometer_api_spec.rb | 52 +- .../classes/ceilometer_wsgi_apache_spec.rb | 2 +- ceilometer/spec/spec_helper_acceptance.rb | 2 +- cinder/CHANGELOG.md | 49 ++ cinder/README.md | 2 +- cinder/manifests/ceilometer.pp | 13 +- cinder/metadata.json | 8 +- cinder/spec/classes/cinder_ceilometer_spec.rb | 2 +- cinder/spec/spec_helper_acceptance.rb | 2 +- glance/CHANGELOG.md | 28 + glance/README.md | 2 +- glance/manifests/backend/swift.pp | 8 +- glance/metadata.json | 8 +- .../spec/classes/glance_backend_swift_spec.rb | 7 +- glance/spec/spec_helper_acceptance.rb | 2 +- heat/CHANGELOG.md | 33 ++ heat/README.md | 2 +- heat/metadata.json | 8 +- heat/spec/spec_helper_acceptance.rb | 2 +- horizon/CHANGELOG.md | 21 + horizon/README.md | 2 +- horizon/metadata.json | 4 +- horizon/spec/spec_helper_acceptance.rb | 2 +- ironic/CHANGELOG.md | 4 + ironic/README.md | 2 + ironic/metadata.json | 12 +- ironic/spec/spec_helper_acceptance.rb | 2 +- keystone/CHANGELOG.md | 40 ++ keystone/README.md | 2 +- keystone/examples/v3_basic.pp | 47 ++ keystone/ext/keystone_test_v3.rb | 64 +++ keystone/lib/puppet/provider/keystone.rb | 163 +++--- .../provider/keystone_user/openstack.rb | 188 ++++-- .../provider/keystone_user_role/openstack.rb | 131 ++++- keystone/lib/puppet/type/keystone_domain.rb | 4 +- keystone/lib/puppet/type/keystone_endpoint.rb | 4 +- keystone/lib/puppet/type/keystone_role.rb | 4 +- keystone/lib/puppet/type/keystone_service.rb | 4 +- keystone/lib/puppet/type/keystone_tenant.rb | 4 +- keystone/lib/puppet/type/keystone_user.rb | 31 +- .../lib/puppet/type/keystone_user_role.rb | 26 +- keystone/manifests/endpoint.pp | 20 + keystone/manifests/init.pp | 41 ++ keystone/manifests/resource/authtoken.pp | 253 ++++++++ .../manifests/resource/service_identity.pp | 46 +- keystone/manifests/roles/admin.pp | 26 +- keystone/metadata.json | 6 +- .../spec/acceptance/basic_keystone_spec.rb | 132 ++++- .../acceptance/keystone_wsgi_apache_spec.rb | 232 ++++++++ .../spec/classes/keystone_endpoint_spec.rb | 15 + .../spec/classes/keystone_roles_admin_spec.rb | 87 ++- keystone/spec/classes/keystone_spec.rb | 68 ++- .../keystone_resource_authtoken_spec.rb | 198 +++++++ ...keystone_resource_service_identity_spec.rb | 63 ++ keystone/spec/spec_helper_acceptance.rb | 2 +- .../keystone_paste_ini/ini_setting_spec.rb | 4 +- .../provider/keystone_user/openstack_spec.rb | 543 ++++++++++++++---- .../keystone_user_role/openstack_spec.rb | 264 +++++++-- .../spec/unit/type/keystone_paste_ini_spec.rb | 2 +- keystone/spec/unit/type/keystone_user_spec.rb | 25 + manila/CHANGELOG.md | 4 + manila/README.md | 2 +- manila/manifests/init.pp | 4 +- manila/metadata.json | 14 +- manila/spec/classes/manila_spec.rb | 4 +- manila/spec/spec_helper_acceptance.rb | 2 +- neutron/CHANGELOG.md | 48 ++ neutron/README.md | 2 +- neutron/manifests/agents/ml2/ovs.pp | 4 +- neutron/manifests/agents/n1kv_vem.pp | 5 + .../manifests/plugins/ml2/cisco/nexus1000v.pp | 119 ++++ neutron/manifests/plugins/ml2/mech_driver.pp | 4 +- neutron/metadata.json | 12 +- .../classes/neutron_agents_ml2_ovs_spec.rb | 21 +- .../classes/neutron_agents_n1kv_vem_spec.rb | 27 + .../classes/neutron_plugins_cisco_ml2_spec.rb | 53 ++ .../spec/classes/neutron_plugins_ml2_spec.rb | 2 +- neutron/spec/spec_helper_acceptance.rb | 2 +- neutron/templates/n1kv.conf.erb | 15 + nova/CHANGELOG.md | 49 ++ nova/README.md | 2 +- .../provider/nova_network/nova_manage.rb | 11 +- nova/lib/puppet/type/nova_network.rb | 10 + nova/manifests/compute/ironic.pp | 8 +- nova/manifests/compute/libvirt.pp | 7 +- nova/manifests/compute/vmware.pp | 18 +- nova/manifests/compute/xenserver.pp | 19 +- nova/manifests/manage/network.pp | 36 +- nova/manifests/network.pp | 23 +- nova/manifests/scheduler.pp | 4 +- nova/metadata.json | 12 +- nova/spec/classes/nova_compute_ironic_spec.rb | 38 +- .../spec/classes/nova_compute_libvirt_spec.rb | 4 +- nova/spec/classes/nova_compute_vmware_spec.rb | 4 +- .../classes/nova_compute_xenserver_spec.rb | 12 +- nova/spec/classes/nova_scheduler_spec.rb | 2 +- .../spec/defines/nova_manage_networks_spec.rb | 28 +- nova/spec/spec_helper_acceptance.rb | 2 +- openstack_extras/CHANGELOG.md | 26 + openstack_extras/README.md | 2 +- openstack_extras/metadata.json | 4 +- openstacklib/CHANGELOG.md | 23 + openstacklib/README.md | 3 +- openstacklib/metadata.json | 4 +- openstacklib/spec/spec_helper_acceptance.rb | 2 +- sahara/CHANGELOG.md | 4 + sahara/README.md | 2 + sahara/examples/basic.pp | 14 +- sahara/manifests/init.pp | 160 ++++-- sahara/manifests/notify/qpid.pp | 87 ++- sahara/manifests/notify/rabbitmq.pp | 25 +- sahara/manifests/notify/zeromq.pp | 69 ++- sahara/metadata.json | 12 +- sahara/spec/acceptance/basic_sahara_spec.rb | 2 +- sahara/spec/classes/sahara_init_spec.rb | 62 +- .../spec/classes/sahara_notify_qpid_spec.rb | 34 +- .../classes/sahara_notify_rabbitmq_spec.rb | 13 +- sahara/spec/spec_helper_acceptance.rb | 2 +- swift/CHANGELOG.md | 34 ++ swift/README.md | 2 +- swift/metadata.json | 6 +- swift/spec/spec_helper_acceptance.rb | 2 +- tempest/CHANGELOG.md | 14 + tempest/README.markdown | 2 +- tempest/manifests/config.pp | 30 + tempest/manifests/init.pp | 6 + tempest/metadata.json | 4 +- tempest/spec/classes/tempest_config_spec.rb | 20 + tempest/spec/classes/tempest_spec.rb | 3 + tempest/spec/spec_helper_acceptance.rb | 2 +- trove/CHANGELOG.md | 4 + trove/README.md | 2 + trove/manifests/config.pp | 84 +++ trove/manifests/keystone/auth.pp | 6 +- trove/metadata.json | 12 +- trove/spec/classes/trove_config_spec.rb | 63 ++ .../spec/classes/trove_keystone_auth_spec.rb | 8 + trove/spec/spec_helper_acceptance.rb | 2 +- tuskar/CHANGELOG.md | 4 + tuskar/README.md | 2 + tuskar/metadata.json | 12 +- vswitch/CHANGELOG.md | 14 + vswitch/README.md | 2 +- vswitch/metadata.json | 6 +- vswitch/spec/spec_helper_acceptance.rb | 2 +- 152 files changed, 4070 insertions(+), 743 deletions(-) create mode 100644 ceilometer/spec/acceptance/ceilometer_wsgi_apache_spec.rb create mode 100644 ironic/CHANGELOG.md create mode 100644 keystone/examples/v3_basic.pp create mode 100644 keystone/ext/keystone_test_v3.rb create mode 100644 keystone/manifests/resource/authtoken.pp create mode 100644 keystone/spec/acceptance/keystone_wsgi_apache_spec.rb create mode 100644 keystone/spec/defines/keystone_resource_authtoken_spec.rb create mode 100644 keystone/spec/unit/type/keystone_user_spec.rb create mode 100644 manila/CHANGELOG.md create mode 100644 neutron/manifests/plugins/ml2/cisco/nexus1000v.pp create mode 100644 sahara/CHANGELOG.md create mode 100644 tempest/manifests/config.pp create mode 100644 tempest/spec/classes/tempest_config_spec.rb create mode 100644 trove/CHANGELOG.md create mode 100644 trove/manifests/config.pp create mode 100644 trove/spec/classes/trove_config_spec.rb create mode 100644 tuskar/CHANGELOG.md create mode 100644 vswitch/CHANGELOG.md diff --git a/Puppetfile b/Puppetfile index 045e237b6..d436cb192 100644 --- a/Puppetfile +++ b/Puppetfile @@ -7,7 +7,7 @@ mod 'aviator', :git => 'https://github.com/aimonb/puppet_aviator.git' mod 'ceilometer', - :commit => 'f17b3442402529281bdca9b2f70697e04bcfe216', + :commit => '05926aaaba5f733f7be1f3e57b59db3ee1385db3', :git => 'https://github.com/openstack/puppet-ceilometer.git' mod 'ceph', @@ -19,7 +19,7 @@ mod 'certmonger', :git => 'https://github.com/rcritten/puppet-certmonger.git' mod 'cinder', - :commit => '15fd1a81b047342e71bfe939cf059eb4fd143e4d', + :commit => 'b2163382956032f6df37d8a02f18a4abf89b7008', :git => 'https://github.com/openstack/puppet-cinder.git' mod 'common', @@ -43,7 +43,7 @@ mod 'galera', :git => 'https://github.com/redhat-openstack/puppet-galera.git' mod 'glance', - :commit => '0bb7577f7e4189495a148ca91f4f92c118e499e7', + :commit => 'c2d8e72f594b0caab0ace8c17d59717a3dd13385', :git => 'https://github.com/openstack/puppet-glance.git' mod 'gluster', @@ -59,11 +59,11 @@ mod 'haproxy', :git => 'https://github.com/puppetlabs/puppetlabs-haproxy.git' mod 'heat', - :commit => '8e742b8d09e3bded06e9529ccd5e7f38e527ab5d', + :commit => '108e9b092698e423840cef6ac24233313b9470b1', :git => 'https://github.com/openstack/puppet-heat.git' mod 'horizon', - :commit => '6e11fbf346560dab461964e53bcb1c817707abc5', + :commit => '79e373bebc010c25410a684437ae41b60e8eefc8', :git => 'https://github.com/openstack/puppet-horizon.git' mod 'inifile', @@ -75,7 +75,7 @@ mod 'ipa', :git => 'https://github.com/xbezdick/puppet-ipa-1.git' mod 'ironic', - :commit => '886a9c0aa2c8ac6167e2d95a60c55bbd6977f82b', + :commit => '88c228cca9d74072a5e944acf0063418b9bdfe4e', :git => 'https://github.com/openstack/puppet-ironic.git' mod 'keepalived', @@ -83,11 +83,11 @@ mod 'keepalived', :git => 'https://github.com/Unyonsys/puppet-module-keepalived.git' mod 'keystone', - :commit => 'e0e87604b8199c0ac0d443999153f88fb7797a9c', + :commit => '5f9080f3adf14921f025038533bfcb9ebdee564c', :git => 'https://github.com/openstack/puppet-keystone.git' mod 'manila', - :commit => 'ff018bdef812bacfe512663c1cc0b92c7d1f26b2', + :commit => 'b94391158dc7c392986db9b0eb63562dde411ea1', :git => 'https://github.com/openstack/puppet-manila.git' mod 'memcached', @@ -119,11 +119,11 @@ mod 'nagios', :git => 'https://github.com/gildub/puppet-nagios-openstack.git' mod 'neutron', - :commit => '36b463c003f94fe23c3d9eff207bbf5005ee470c', + :commit => 'c683ca5fc31111b7b0569cc71e9b959e62d21c4b', :git => 'https://github.com/openstack/puppet-neutron.git' mod 'nova', - :commit => 'cb2d487fb9baf2c1902182973e29982b5389e769', + :commit => '52e7f810a50f15e2c32cd1270374899ef7df675f', :git => 'https://github.com/openstack/puppet-nova.git' mod 'nssdb', @@ -135,11 +135,11 @@ mod 'ntp', :git => 'https://github.com/puppetlabs/puppetlabs-ntp' mod 'openstack_extras', - :commit => 'ab8ddaff93e06d7fdbfb2c61ffe9113562dd82ad', + :commit => '2d08ba975b65c613fbdc08812cbf30e7d6c9d6e4', :git => 'https://github.com/openstack/puppet-openstack_extras.git' mod 'openstacklib', - :commit => '78ef674e0e6bc73b3a0af7833025dc9786eaeaeb', + :commit => 'fcfffcf47069119805e44cc712739ba0c1e4603d', :git => 'https://github.com/openstack/puppet-openstacklib.git' mod 'pacemaker', @@ -171,7 +171,7 @@ mod 'rsync', :git => 'https://github.com/puppetlabs/puppetlabs-rsync.git' mod 'sahara', - :commit => '56d9a841bff7389d1128d40dad4a319988d547f1', + :commit => '6e79d710a97d7c43aea766bbfa8c4d782a7c2049', :git => 'https://github.com/openstack/puppet-sahara.git' mod 'snmp', @@ -191,7 +191,7 @@ mod 'stdlib', :git => 'https://github.com/puppetlabs/puppetlabs-stdlib.git' mod 'swift', - :commit => '275fb9b111bbb30148e762afc0798aa891091cf2', + :commit => 'd736e6a00e8ff1e4f05c8fbc9535908fc2112587', :git => 'https://github.com/openstack/puppet-swift.git' mod 'sysctl', @@ -199,7 +199,7 @@ mod 'sysctl', :git => 'https://github.com/puppetlabs/puppetlabs-sysctl.git' mod 'tempest', - :commit => 'ab9601ff339f6acb40901291133c03cf1b45d5ee', + :commit => '4cc2ad2e827e1117d79dbab1bc91283428ffdc78', :git => 'https://github.com/openstack/puppet-tempest.git' mod 'timezone', @@ -211,11 +211,11 @@ mod 'tripleo', :git => 'https://github.com/openstack/puppet-tripleo.git' mod 'trove', - :commit => '2636a384f67c2ac1513ac709f3ae4525668ccb62', + :commit => '1c5d6895c86fdb99501c72ef999864268bb7a389', :git => 'https://github.com/openstack/puppet-trove' mod 'tuskar', - :commit => '85a3991330f36903cd66a6e12512b54ab758ec41', + :commit => '09e2ced9be2cdf5d94dd6310e9df3a3155ab549b', :git => 'https://github.com/openstack/puppet-tuskar.git' mod 'vcsrepo', @@ -227,7 +227,7 @@ mod 'vlan', :git => 'https://github.com/derekhiggins/puppet-vlan.git' mod 'vswitch', - :commit => 'e73073a120d833958d22925a1badbc1ccdc0f15a', + :commit => '5992d41a238c93bcf6bd6989c23d3c7577c48b69', :git => 'https://github.com/openstack/puppet-vswitch.git' mod 'xinetd', diff --git a/ceilometer/CHANGELOG.md b/ceilometer/CHANGELOG.md index d5913be17..e29904bed 100644 --- a/ceilometer/CHANGELOG.md +++ b/ceilometer/CHANGELOG.md @@ -1,3 +1,32 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a backwards-incompatible major release for OpenStack Kilo. + +####Backwards-incompatible changes +- Move rabbit/kombu settings to oslo_messaging_rabbit section + +####Features +- Puppet 4.x support +- make crontab for expirer optional +- Refactorise Keystone resources management +- db: Added postgresql backend using openstacklib helper +- Implement Ceilometer-API as a WSGI process support +- Add support for ceilometer-polling agent +- Add support for identity_uri +- Tag all Ceilometer packages +- Add udp_address/udp_port parameters for collector. +- Deprecate old public, internal and admin parameters + +####Bugfixes +- Ensure python-mysqldb is installed before MySQL db_sync +- Fix dependency on nova-common package + +####Maintenance +- Acceptance tests with Beaker +- Fix spec tests for RSpec 3.x and Puppet 4.x + + ##2015-06-17 - 5.1.0 ###Summary diff --git a/ceilometer/README.md b/ceilometer/README.md index 7bd699a77..56155b2f9 100644 --- a/ceilometer/README.md +++ b/ceilometer/README.md @@ -1,7 +1,7 @@ Ceilometer ========== -5.1.0 - 2014.2 - Juno +6.0.0 - 2015.1 - Kilo #### Table of Contents diff --git a/ceilometer/manifests/api.pp b/ceilometer/manifests/api.pp index 66d71d38b..9bcb67937 100644 --- a/ceilometer/manifests/api.pp +++ b/ceilometer/manifests/api.pp @@ -64,6 +64,15 @@ # (optional) ensure state for package. # Defaults to 'present' # +# [*service_name*] +# (optional) Name of the service that will be providing the +# server functionality of ceilometer-api. +# If the value is 'httpd', this means ceilometer-api will be a web +# service, and you must use another class to configure that +# web service. For example, use class { 'ceilometer::wsgi::apache'...} +# to make keystone be a web app using apache mod_wsgi. +# Defaults to '$::ceilometer::params::api_service_name' +# class ceilometer::api ( $manage_service = true, $enabled = true, @@ -75,23 +84,24 @@ $keystone_identity_uri = false, $host = '0.0.0.0', $port = '8777', + $service_name = $::ceilometer::params::api_service_name, # DEPRECATED PARAMETERS $keystone_host = '127.0.0.1', $keystone_port = '35357', $keystone_auth_admin_prefix = false, $keystone_protocol = 'http', -) { +) inherits ceilometer::params { include ::ceilometer::params include ::ceilometer::policy validate_string($keystone_password) - Ceilometer_config<||> ~> Service['ceilometer-api'] - Class['ceilometer::policy'] ~> Service['ceilometer-api'] + Ceilometer_config<||> ~> Service[$service_name] + Class['ceilometer::policy'] ~> Service[$service_name] Package['ceilometer-api'] -> Ceilometer_config<||> - Package['ceilometer-api'] -> Service['ceilometer-api'] + Package['ceilometer-api'] -> Service[$service_name] Package['ceilometer-api'] -> Class['ceilometer::policy'] package { 'ceilometer-api': ensure => $package_ensure, @@ -106,16 +116,30 @@ $service_ensure = 'stopped' } } - - Package['ceilometer-common'] -> Service['ceilometer-api'] - service { 'ceilometer-api': - ensure => $service_ensure, - name => $::ceilometer::params::api_service_name, - enable => $enabled, - hasstatus => true, - hasrestart => true, - require => Class['ceilometer::db'], - subscribe => Exec['ceilometer-dbsync'] + Package['ceilometer-common'] -> Service[$service_name] + + if $service_name == $::ceilometer::params::api_service_name { + service { 'ceilometer-api': + ensure => $service_ensure, + name => $::ceilometer::params::api_service_name, + enable => $enabled, + hasstatus => true, + hasrestart => true, + require => Class['ceilometer::db'], + subscribe => Exec['ceilometer-dbsync'], + tag => 'ceilometer-service', + } + } elsif $service_name == 'httpd' { + include ::apache::params + service { 'ceilometer-api': + ensure => 'stopped', + name => $::ceilometer::params::api_service_name, + enable => false, + tag => 'ceilometer-service', + } + Class['ceilometer::db'] -> Service[$service_name] + } else { + fail('Invalid service_name. Either keystone/openstack-ceilometer-api for running as a standalone service, or httpd for being run by a httpd server') } ceilometer_config { diff --git a/ceilometer/manifests/params.pp b/ceilometer/manifests/params.pp index 524c2f902..a1923230b 100644 --- a/ceilometer/manifests/params.pp +++ b/ceilometer/manifests/params.pp @@ -68,7 +68,7 @@ } } $ceilometer_wsgi_script_path = '/usr/lib/cgi-bin/ceilometer' - $ceilometer_wsgi_script_source = '/usr/share/ceilometer/app.wsgi' + $ceilometer_wsgi_script_source = '/usr/lib/python2.7/dist-packages/ceilometer/api/app.wsgi' } default: { fail("Unsupported osfamily: ${::osfamily} operatingsystem: \ diff --git a/ceilometer/metadata.json b/ceilometer/metadata.json index 0b32dd6bb..c7d82fc99 100644 --- a/ceilometer/metadata.json +++ b/ceilometer/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-ceilometer", - "version": "5.1.0", + "name": "openstack-ceilometer", + "version": "6.0.0", "author": "eNovance and OpenStack Contributors", "summary": "Puppet module for OpenStack Ceilometer", "license": "Apache-2.0", @@ -33,8 +33,8 @@ "dependencies": [ { "name": "puppetlabs/apache", "version_requirement": ">=1.0.0 <2.0.0" }, { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/ceilometer/spec/acceptance/ceilometer_wsgi_apache_spec.rb b/ceilometer/spec/acceptance/ceilometer_wsgi_apache_spec.rb new file mode 100644 index 000000000..d731de218 --- /dev/null +++ b/ceilometer/spec/acceptance/ceilometer_wsgi_apache_spec.rb @@ -0,0 +1,133 @@ +require 'spec_helper_acceptance' + +describe 'ceilometer with mysql' do + + context 'default parameters' do + + it 'should work with no errors' do + pp= <<-EOS + Exec { logoutput => 'on_failure' } + + # Common resources + case $::osfamily { + 'Debian': { + include ::apt + class { '::openstack_extras::repo::debian::ubuntu': + release => 'kilo', + package_require => true, + } + $package_provider = 'apt' + } + 'RedHat': { + class { '::openstack_extras::repo::redhat::redhat': + release => 'kilo', + } + package { 'openstack-selinux': ensure => 'latest' } + $package_provider = 'yum' + } + default: { + fail("Unsupported osfamily (${::osfamily})") + } + } + + class { '::mysql::server': } + + class { '::rabbitmq': + delete_guest_user => true, + package_provider => $package_provider, + } + + rabbitmq_vhost { '/': + provider => 'rabbitmqctl', + require => Class['rabbitmq'], + } + + rabbitmq_user { 'ceilometer': + admin => true, + password => 'an_even_bigger_secret', + provider => 'rabbitmqctl', + require => Class['rabbitmq'], + } + + rabbitmq_user_permissions { 'ceilometer@/': + configure_permission => '.*', + write_permission => '.*', + read_permission => '.*', + provider => 'rabbitmqctl', + require => Class['rabbitmq'], + } + + + # Keystone resources, needed by Ceilometer to run + class { '::keystone::db::mysql': + password => 'keystone', + } + class { '::keystone': + verbose => true, + debug => true, + database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone', + admin_token => 'admin_token', + enabled => true, + } + class { '::keystone::roles::admin': + email => 'test@example.tld', + password => 'a_big_secret', + } + class { '::keystone::endpoint': + public_url => "https://${::fqdn}:5000/", + admin_url => "https://${::fqdn}:35357/", + } + + # Ceilometer resources + class { '::ceilometer': + metering_secret => 'secrete', + rabbit_userid => 'ceilometer', + rabbit_password => 'an_even_bigger_secret', + rabbit_host => '127.0.0.1', + } + # Until https://review.openstack.org/177593 is merged: + Package<| title == 'python-mysqldb' |> -> Class['ceilometer::db'] + class { '::ceilometer::db::mysql': + password => 'a_big_secret', + } + class { '::ceilometer::db': + database_connection => 'mysql://ceilometer:a_big_secret@127.0.0.1/ceilometer?charset=utf8', + } + class { '::ceilometer::keystone::auth': + password => 'a_big_secret', + } + class { '::ceilometer::client': } + class { '::ceilometer::collector': } + class { '::ceilometer::expirer': } + class { '::ceilometer::alarm::evaluator': } + class { '::ceilometer::alarm::notifier': } + class { '::ceilometer::agent::central': } + class { '::ceilometer::agent::notification': } + class { '::ceilometer::api': + enabled => true, + keystone_password => 'a_big_secret', + keystone_identity_uri => 'http://127.0.0.1:35357/', + service_name => 'httpd', + } + include ::apache + class { '::ceilometer::wsgi::apache': + ssl => false, + } + EOS + + + # Run it twice and test for idempotency + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe port(8777) do + it { is_expected.to be_listening } + end + + describe cron do + it { is_expected.to have_entry('1 0 * * * ceilometer-expirer').with_user('ceilometer') } + end + + end +end diff --git a/ceilometer/spec/classes/ceilometer_api_spec.rb b/ceilometer/spec/classes/ceilometer_api_spec.rb index e54eea1a9..6ada5b8be 100644 --- a/ceilometer/spec/classes/ceilometer_api_spec.rb +++ b/ceilometer/spec/classes/ceilometer_api_spec.rb @@ -3,7 +3,8 @@ describe 'ceilometer::api' do let :pre_condition do - "class { 'ceilometer': metering_secret => 's3cr3t' }" + "class { 'ceilometer': metering_secret => 's3cr3t' } + include ::ceilometer::db" end let :params do @@ -113,11 +114,51 @@ ) end end + + context 'when running ceilometer-api in wsgi' do + before do + params.merge!({ :service_name => 'httpd' }) + end + + let :pre_condition do + "include ::apache + include ::ceilometer::db + class { 'ceilometer': metering_secret => 's3cr3t' }" + end + + it 'configures ceilometer-api service with Apache' do + is_expected.to contain_service('ceilometer-api').with( + :ensure => 'stopped', + :name => platform_params[:api_service_name], + :enable => false, + :tag => 'ceilometer-service', + ) + end + end + + context 'when service_name is not valid' do + before do + params.merge!({ :service_name => 'foobar' }) + end + + let :pre_condition do + "include ::apache + include ::ceilometer::db + class { 'ceilometer': metering_secret => 's3cr3t' }" + end + + it_raises 'a Puppet::Error', /Invalid service_name/ + end end context 'on Debian platforms' do let :facts do - { :osfamily => 'Debian' } + { :osfamily => 'Debian', + :operatingsystem => 'Debian', + :operatingsystemrelease => '8.0', + :concat_basedir => '/var/lib/puppet/concat', + :fqdn => 'some.host.tld', + :processorcount => 2 } end let :platform_params do @@ -130,7 +171,12 @@ context 'on RedHat platforms' do let :facts do - { :osfamily => 'RedHat' } + { :osfamily => 'RedHat', + :operatingsystem => 'RedHat', + :operatingsystemrelease => '7.1', + :fqdn => 'some.host.tld', + :concat_basedir => '/var/lib/puppet/concat', + :processorcount => 2 } end let :platform_params do diff --git a/ceilometer/spec/classes/ceilometer_wsgi_apache_spec.rb b/ceilometer/spec/classes/ceilometer_wsgi_apache_spec.rb index b7c689900..ad4c07654 100644 --- a/ceilometer/spec/classes/ceilometer_wsgi_apache_spec.rb +++ b/ceilometer/spec/classes/ceilometer_wsgi_apache_spec.rb @@ -119,7 +119,7 @@ :httpd_service_name => 'apache2', :httpd_ports_file => '/etc/apache2/ports.conf', :wsgi_script_path => '/usr/lib/cgi-bin/ceilometer', - :wsgi_script_source => '/usr/share/ceilometer/app.wsgi' + :wsgi_script_source => '/usr/lib/python2.7/dist-packages/ceilometer/api/app.wsgi' } end diff --git a/ceilometer/spec/spec_helper_acceptance.rb b/ceilometer/spec/spec_helper_acceptance.rb index 429e807c4..6031cb8d4 100644 --- a/ceilometer/spec/spec_helper_acceptance.rb +++ b/ceilometer/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git -b stable/kilo clone https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/cinder/CHANGELOG.md b/cinder/CHANGELOG.md index d087182b2..34e0ab23d 100644 --- a/cinder/CHANGELOG.md +++ b/cinder/CHANGELOG.md @@ -1,3 +1,52 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a backwards-incompatible major release for OpenStack Kilo. + +####Backwards-incompatible changes +- Iscsi: Change default $volume_driver +- Switch to TLSv1 as SSLv3 is considered insecure and is disabled by default +- Remove POSIX users, groups, and file modes +- Move rabbit/kombu settings to oslo_messaging_rabbit section +- Also removed deprecated parameters + +####Features +- Puppet 4.x support +- Refactorise Keystone resources management +- Add an option to not configure RabbitMQ service +- Run db_sync when upgrading packages +- Makes kombu_ssl_* parameters optional when rabbit_use_ssl => true +- Adds ability to override service name for service catalog +- Support the enable_v*_api settings +- Support iSER driver within the ISCSITarget flow +- ISCSI: Allow one to specify volumes_dir path +- Backends: Add an extra_options door +- Support identity_uri and auth_uri properly +- Make scheduler_driver option can be cleaned up +- Tag all Cinder packages +- Adds OracleLinux support +- Create a sync_db boolean for Cinder +- Update NetApp params for Kilo +- Add nfs_mount_options variable when backend is NetApp +- Add support for NFS Backup +- Decouple $sync_db from $enabled +- Add backup compression parameter +- Introduce public_url, internal_url and admin_url +- Added support for DellStorageCenter ISCSI cinder driver +- Add cinder::scheduler::filter for managing scheduler.filter +- NetApp: use $name for configuration group name (allows to run multiple NetApp + backends) +- Lint documentation parameters +- HP 3par iscsi backend module +- MySQL: change default MySQL collate to utf8_general_ci + +####Bugfixes +- Fix db_sync dependencies + +####Maintenance +- Acceptance tests with Beaker +- Fix spec tests for RSpec 3.x and Puppet 4.x + ##2015-06-17 - 5.1.0 ###Summary diff --git a/cinder/README.md b/cinder/README.md index 538178c12..937488a3a 100644 --- a/cinder/README.md +++ b/cinder/README.md @@ -1,7 +1,7 @@ cinder ======= -5.1.0 - 2014.2 - Juno +6.0.0 - 2015.1 - Kilo #### Table of Contents diff --git a/cinder/manifests/ceilometer.pp b/cinder/manifests/ceilometer.pp index 813ea687d..c13374b35 100644 --- a/cinder/manifests/ceilometer.pp +++ b/cinder/manifests/ceilometer.pp @@ -7,16 +7,17 @@ # # [*notification_driver*] # (option) Driver or drivers to handle sending notifications. -# Notice: rabbit_notifier has been deprecated in Grizzly, use rpc_notifier instead. +# The default value of 'messagingv2' is for enabling notifications via +# oslo.messaging. 'cinder.openstack.common.notifier.rpc_notifier' is the +# backwards compatible option that will be deprecated. Prior to Grizzly, +# 'cinder.openstack.common.notifier.rabbit_notifier' was used. oslo.messaging +# was adopted in icehouse/juno. See LP#1425713. # - - class cinder::ceilometer ( - $notification_driver = 'cinder.openstack.common.notifier.rpc_notifier' + $notification_driver = 'messagingv2', ) { cinder_config { - 'DEFAULT/notification_driver': value => $notification_driver; + 'DEFAULT/notification_driver': value => $notification_driver; } } - diff --git a/cinder/metadata.json b/cinder/metadata.json index 3b718d866..438e83f27 100644 --- a/cinder/metadata.json +++ b/cinder/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-cinder", - "version": "5.1.0", + "name": "openstack-cinder", + "version": "6.0.0", "author": "Puppet Labs and OpenStack Contributors", "summary": "Puppet module for OpenStack Cinder", "license": "Apache-2.0", @@ -33,9 +33,9 @@ "dependencies": [ { "name": "dprince/qpid", "version_requirement": ">=1.0.0 <2.0.0" }, { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/rabbitmq", "version_requirement": ">=2.0.2 <6.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/cinder/spec/classes/cinder_ceilometer_spec.rb b/cinder/spec/classes/cinder_ceilometer_spec.rb index fdb9b49ee..1d268c1a7 100644 --- a/cinder/spec/classes/cinder_ceilometer_spec.rb +++ b/cinder/spec/classes/cinder_ceilometer_spec.rb @@ -5,7 +5,7 @@ describe 'with default parameters' do it 'contains default values' do is_expected.to contain_cinder_config('DEFAULT/notification_driver').with( - :value => 'cinder.openstack.common.notifier.rpc_notifier') + :value => 'messagingv2') end end end diff --git a/cinder/spec/spec_helper_acceptance.rb b/cinder/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/cinder/spec/spec_helper_acceptance.rb +++ b/cinder/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/glance/CHANGELOG.md b/glance/CHANGELOG.md index 1e69f7f3f..c3a1b33fc 100644 --- a/glance/CHANGELOG.md +++ b/glance/CHANGELOG.md @@ -1,3 +1,31 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a backwards-incompatible major release for OpenStack Kilo. + +####Backwards-incompatible changes +- Move rabbit/kombu settings to oslo_messaging_rabbit section +- Remove sql_connection and sql_idle_timeout deprecated parameters +- api: change default pipeline +- Separate api and registry packages for Red Hat +- python-ceph no longer exists in el7, use python-rbd + +####Features +- Puppet 4.x support +- Refactorise Keystone resources management +- Migrate postgresql backend to use openstacklib::db::postgresql +- Add support for identity_uri +- Service Validation for Glance-API +- Create a sync_db boolean for Glance +- make service description configurable + +####Bugfixes +- Fix API/Registry ensure for Ubuntu + +####Maintenance +- Acceptance tests with Beaker +- Fix spec tests for RSpec 3.x and Puppet 4.x + ##2015-06-17 - 5.1.0 ###Summary diff --git a/glance/README.md b/glance/README.md index a980477ae..7d471435c 100644 --- a/glance/README.md +++ b/glance/README.md @@ -1,7 +1,7 @@ glance ======= -5.1.0 - 2014.2 - Juno +6.0.0 - 2015.1 - Kilo #### Table of Contents diff --git a/glance/manifests/backend/swift.pp b/glance/manifests/backend/swift.pp index 6065acff0..ea3a34b57 100644 --- a/glance/manifests/backend/swift.pp +++ b/glance/manifests/backend/swift.pp @@ -29,6 +29,9 @@ # == class: glance::backend::swift # [*swift_store_endpoint_type*] # Optional. Default: 'internalURL' # +# [*swift_store_region*] +# Optional. Default: undef +# class glance::backend::swift( $swift_store_user, $swift_store_key, @@ -37,7 +40,8 @@ # == class: glance::backend::swift $swift_store_auth_version = '2', $swift_store_large_object_size = '5120', $swift_store_create_container_on_put = false, - $swift_store_endpoint_type = 'internalURL' + $swift_store_endpoint_type = 'internalURL', + $swift_store_region = undef, ) { glance_api_config { @@ -45,6 +49,7 @@ # == class: glance::backend::swift 'glance_store/swift_store_user': value => $swift_store_user; 'glance_store/swift_store_key': value => $swift_store_key; 'glance_store/swift_store_auth_address': value => $swift_store_auth_address; + 'glance_store/swift_store_region': value => $swift_store_region; 'glance_store/swift_store_container': value => $swift_store_container; 'glance_store/swift_store_auth_version': value => $swift_store_auth_version; 'glance_store/swift_store_create_container_on_put': @@ -59,6 +64,7 @@ # == class: glance::backend::swift 'glance_store/swift_store_user': value => $swift_store_user; 'glance_store/swift_store_key': value => $swift_store_key; 'glance_store/swift_store_auth_address': value => $swift_store_auth_address; + 'glance_store/swift_store_region': value => $swift_store_region; 'glance_store/swift_store_container': value => $swift_store_container; 'glance_store/swift_store_auth_version': value => $swift_store_auth_version; 'glance_store/swift_store_create_container_on_put': diff --git a/glance/metadata.json b/glance/metadata.json index 33e155644..c9c386242 100644 --- a/glance/metadata.json +++ b/glance/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-glance", - "version": "5.1.0", + "name": "openstack-glance", + "version": "6.0.0", "author": "Puppet Labs and OpenStack Contributors", "summary": "Puppet module for OpenStack Glance", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "description": "Installs and configures OpenStack Glance (Image Service).", "dependencies": [ { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/glance/spec/classes/glance_backend_swift_spec.rb b/glance/spec/classes/glance_backend_swift_spec.rb index 65d09ddd7..0993b5a4e 100644 --- a/glance/spec/classes/glance_backend_swift_spec.rb +++ b/glance/spec/classes/glance_backend_swift_spec.rb @@ -30,6 +30,7 @@ is_expected.to contain_glance_api_config('glance_store/swift_store_container').with_value('glance') is_expected.to contain_glance_api_config('glance_store/swift_store_create_container_on_put').with_value(false) is_expected.to contain_glance_api_config('glance_store/swift_store_endpoint_type').with_value('internalURL') + is_expected.to contain_glance_api_config('glance_store/swift_store_region').with_value(nil) end it 'configures glance-cache.conf' do @@ -40,6 +41,7 @@ is_expected.to contain_glance_cache_config('glance_store/swift_store_auth_address').with_value('127.0.0.1:5000/v2.0/') is_expected.to contain_glance_cache_config('glance_store/swift_store_container').with_value('glance') is_expected.to contain_glance_cache_config('glance_store/swift_store_create_container_on_put').with_value(false) + is_expected.to contain_glance_cache_config('glance_store/swift_store_region').with_value(nil) end end @@ -53,7 +55,8 @@ :swift_store_auth_address => '127.0.0.2:8080/v1.0/', :swift_store_container => 'swift', :swift_store_create_container_on_put => true, - :swift_store_endpoint_type => 'publicURL' + :swift_store_endpoint_type => 'publicURL', + :swift_store_region => 'RegionTwo' } end @@ -64,6 +67,7 @@ is_expected.to contain_glance_api_config('glance_store/swift_store_large_object_size').with_value('100') is_expected.to contain_glance_api_config('glance_store/swift_store_auth_address').with_value('127.0.0.2:8080/v1.0/') is_expected.to contain_glance_api_config('glance_store/swift_store_endpoint_type').with_value('publicURL') + is_expected.to contain_glance_api_config('glance_store/swift_store_region').with_value('RegionTwo') end it 'configures glance-cache.conf' do @@ -72,6 +76,7 @@ is_expected.to contain_glance_cache_config('glance_store/swift_store_auth_version').with_value('1') is_expected.to contain_glance_cache_config('glance_store/swift_store_large_object_size').with_value('100') is_expected.to contain_glance_cache_config('glance_store/swift_store_auth_address').with_value('127.0.0.2:8080/v1.0/') + is_expected.to contain_glance_cache_config('glance_store/swift_store_region').with_value('RegionTwo') end end end diff --git a/glance/spec/spec_helper_acceptance.rb b/glance/spec/spec_helper_acceptance.rb index e29c01cd3..b25e26b7e 100644 --- a/glance/spec/spec_helper_acceptance.rb +++ b/glance/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/heat/CHANGELOG.md b/heat/CHANGELOG.md index fd37e6d33..131c7b961 100644 --- a/heat/CHANGELOG.md +++ b/heat/CHANGELOG.md @@ -1,3 +1,36 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a backwards-incompatible major release for OpenStack Kilo. + +####Backwards-incompatible changes +- Move rabbit/kombu settings to oslo_messaging_rabbit section + +####Features +- Puppet 4.x support +- Implement Keystone domain creation +- Log output of heat-keystone-setup-domain +- Refactorise Keystone resources management +- Move keystone role creation to keystone area +- Support region_name for Heat +- Mark heat's keystone password as secret +- Add support for identity_uri +- Make configuring the service optional +- Set instance_user in heat +- Added missing enable_stack_abandon configuration option +- Tag all Heat packages +- Create a sync_db boolean for Heat +- Engine: validate auth_encryption_key +- Allow setting default config/signal transport +- Run db_sync when heat-common is upgraded +- Introduce public_url, internal_url and admin_url + +####Maintenance +- Acceptance tests with Beaker +- Fix spec tests for RSpec 3.x and Puppet 4.x +- Rename keystone_v2_authenticate method +- Make package_ensure consistent across classes + ##2015-06-17 - 5.1.0 ###Summary diff --git a/heat/README.md b/heat/README.md index b75cd196f..246c4b6d7 100644 --- a/heat/README.md +++ b/heat/README.md @@ -1,7 +1,7 @@ puppet-heat ============= -5.1.0 - 2014.2 - Juno +6.0.0 - 2015.1 - Kilo #### Table of Contents diff --git a/heat/metadata.json b/heat/metadata.json index 7ad7a6cbb..9834175f6 100644 --- a/heat/metadata.json +++ b/heat/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-heat", - "version": "5.1.0", + "name": "openstack-heat", + "version": "6.0.0", "author": "eNovance and OpenStack Contributors", "summary": "Puppet module for OpenStack Heat", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "description": "Installs and configures OpenStack Heat (Orchestration).", "dependencies": [ { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/heat/spec/spec_helper_acceptance.rb b/heat/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/heat/spec/spec_helper_acceptance.rb +++ b/heat/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/horizon/CHANGELOG.md b/horizon/CHANGELOG.md index df1c6c51b..196a2328a 100644 --- a/horizon/CHANGELOG.md +++ b/horizon/CHANGELOG.md @@ -1,3 +1,24 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a backwards-incompatible major release for OpenStack Kilo. + +####Backwards-incompatible changes +- Remove some old deprecated parameters + +####Features +- Puppet 4.x support +- Sort policy files in local_settings.py +- Add support for Neutron DVR and L3 HA options +- Collect static files before compressing them +- Add support to add Tuskar-ui config to local_settings +- Add support for WEBROOT in local_settings +- Add 'log_handler' parameter + +####Maintenance +- Acceptance tests with Beaker +- Fix spec tests for RSpec 3.x and Puppet 4.x + ##2015-06-17 - 5.1.0 ###Summary diff --git a/horizon/README.md b/horizon/README.md index 0f775e353..caefbcbfa 100644 --- a/horizon/README.md +++ b/horizon/README.md @@ -1,7 +1,7 @@ horizon ======= -5.1.0 - 2014.2 - Juno +6.0.0 - 2015.1 - Kilo #### Table of Contents diff --git a/horizon/metadata.json b/horizon/metadata.json index 1c580c18a..5dddaea48 100644 --- a/horizon/metadata.json +++ b/horizon/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-horizon", - "version": "5.1.0", + "name": "openstack-horizon", + "version": "6.0.0", "author": "Puppet Labs and OpenStack Contributors", "summary": "Puppet module for OpenStack Horizon", "license": "Apache-2.0", diff --git a/horizon/spec/spec_helper_acceptance.rb b/horizon/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/horizon/spec/spec_helper_acceptance.rb +++ b/horizon/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/ironic/CHANGELOG.md b/ironic/CHANGELOG.md new file mode 100644 index 000000000..6a0701c08 --- /dev/null +++ b/ironic/CHANGELOG.md @@ -0,0 +1,4 @@ +##2015-07-08 - 6.0.0 +###Summary + +- Initial release of the puppet-ironic module diff --git a/ironic/README.md b/ironic/README.md index 289f0154c..15198183d 100644 --- a/ironic/README.md +++ b/ironic/README.md @@ -1,6 +1,8 @@ puppet-ironic ============= +6.0.0 - 2015.1 - Kilo + #### Table of Contents 1. [Overview - What is the ironic module?](#overview) diff --git a/ironic/metadata.json b/ironic/metadata.json index d86bbfd56..61dc596dd 100644 --- a/ironic/metadata.json +++ b/ironic/metadata.json @@ -1,10 +1,10 @@ { - "name": "stackforge-ironic", - "version": "5.0.0", - "author": "eNovance and StackForge Contributors", + "name": "openstack-ironic", + "version": "6.0.0", + "author": "eNovance and OpenStack Contributors", "summary": "Puppet module for OpenStack Ironic", "license": "Apache-2.0", - "source": "git://github.com/stackforge/puppet-ironic.git", + "source": "git://github.com/openstack/puppet-ironic.git", "project_page": "https://launchpad.net/puppet-ironic", "issues_url": "https://bugs.launchpad.net/puppet-ironic", "requirements": [ @@ -32,8 +32,8 @@ "description": "Installs and configures OpenStack Ironic (Bare metal).", "dependencies": [ { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/ironic/spec/spec_helper_acceptance.rb b/ironic/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/ironic/spec/spec_helper_acceptance.rb +++ b/ironic/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/keystone/CHANGELOG.md b/keystone/CHANGELOG.md index 973da8fb1..33c0f5e06 100644 --- a/keystone/CHANGELOG.md +++ b/keystone/CHANGELOG.md @@ -1,3 +1,43 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a backwards-incompatible major release for OpenStack Kilo. + +####Backwards-incompatible changes +- Remove deprecated parameters +- MySQL: change default MySQL collate to utf8_general_ci +- Move openstackclient to openstacklib + +####Features +- Puppet 4.x support +- Support Keystone v3 API +- Allow disabling or delaying the token_flush cron +- Migrate postgresql backend to use openstacklib::db::postgresql +- Add max_token_size optional parameter +- Add admin_workers and public_workers configuration options +- Add support for LDAP connection pools +- Add a package ensure for openstackclient +- Enable setting the revoke/token driver +- Add manage_service feature +- Makes distinct use of url vs auth_url +- Create a sync_db boolean for Keystone +- LDAP: add support to configure credential driver +- Support notification_format +- Allow custom file source for wsgi scripts +- Decouple sync_db from enabled +- Add support for Fernet Tokens + +####Bugfixes +- Crontab: ensure the script is run with bash shell +- Copy latest keystone.py from Keystone upstream +- Fix deprecated LDAP config options +- Fix service keystone conflict when running in apache + +####Maintenance +- Acceptance tests with Beaker +- Fix spec tests for RSpec 3.x and Puppet 4.x +- Restructures authentication for resource providers + ##2015-06-17 - 5.1.0 ###Summary diff --git a/keystone/README.md b/keystone/README.md index df6023740..e35380cc9 100644 --- a/keystone/README.md +++ b/keystone/README.md @@ -1,7 +1,7 @@ keystone ======= -5.1.0 - 2014.2 - Juno +6.0.0 - 2015.1 - Kilo #### Table of Contents diff --git a/keystone/examples/v3_basic.pp b/keystone/examples/v3_basic.pp new file mode 100644 index 000000000..5777d2b5b --- /dev/null +++ b/keystone/examples/v3_basic.pp @@ -0,0 +1,47 @@ +# Example using v3 domains. The admin user is created in the domain +# named 'admin_domain', and assigned the role 'admin' in the 'admin' +# project in the domain 'admin_domain'. The keystone service account is +# created in default domain, and assigned the +# role 'admin' in the project 'services' in the default domain. +# NOTE: Until all of the other services support using Keystone v3 +# with keystone_authtoken middleware that supports v3, they cannot +# specify a domain for authentication, and so have to be in the +# default domain. +# +# To be sure everything is working, run: +# $ export OS_IDENTITY_API_VERSION=3 +# $ export OS_USERNAME=admin +# $ export OS_USER_DOMAIN_NAME=admin_domain +# $ export OS_PASSWORD=ChangeMe +# $ export OS_PROJECT_NAME=admin +# $ export OS_PROJECT_DOMAIN_NAME=admin_domain +# $ export OS_AUTH_URL=http://keystone.local:35357/v3 +# $ openstack user list +# + +Exec { logoutput => 'on_failure' } + + +class { '::mysql::server': } +class { '::keystone::db::mysql': + password => 'keystone', +} +class { '::keystone': + verbose => true, + debug => true, + database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone', + admin_token => 'admin_token', + enabled => true, +} +class { '::keystone::roles::admin': + email => 'test@example.tld', + password => 'a_big_secret', + admin => 'admin', # username + admin_tenant => 'admin', # project name + admin_user_domain => 'admin', # domain for user + admin_tenant_domain => 'admin', # domain for project +} +class { '::keystone::endpoint': + public_url => 'http://127.0.0.1:5000/', + admin_url => 'http://127.0.0.1:35357/', +} diff --git a/keystone/ext/keystone_test_v3.rb b/keystone/ext/keystone_test_v3.rb new file mode 100644 index 000000000..0d7550e32 --- /dev/null +++ b/keystone/ext/keystone_test_v3.rb @@ -0,0 +1,64 @@ +#!/usr/bin/env ruby +# this script verifies that keystone has +# been successfully installed using the instructions +# found here: http://keystone.openstack.org/configuration.html +# and can use the v3 api http://developer.openstack.org/api-ref-identity-v3.html + +begin + require 'rubygems' +rescue + puts 'Could not require rubygems. This assumes puppet is not installed as a gem' +end +require 'open3' +require 'fileutils' +require 'puppet' +require 'pp' + +username='admin' +password='a_big_secret' +# required to get a real services catalog +project='openstack' +user_domain='admin' +project_domain='admin' + +# shared secret +service_token='admin_token' + +def run_command(cmd) + Open3.popen3(cmd) do |stdin, stdout, stderr| + begin + stdout = stdout.read + puts "Response from token request:#{stdout}" + return stdout + rescue Exception => e + puts "Request failed, this sh*t is borked :( : details: #{e}" + exit 1 + end + end +end + +puts `puppet apply -e "package {curl: ensure => present }"` +get_token = %(curl -D - -d '{"auth":{"identity":{"methods":["password"],"password":{"user":{"domain":{"name":"#{user_domain}"},"name":"#{username}","password": "#{password}"}}},"scope":{"project":{"domain":{"name":"#{project_domain}"},"name": "#{project}"}}}}' -H "Content-type: application/json" http://localhost:35357/v3/auth/tokens) +token = nil + +puts "Running auth command: #{get_token}" +rawoutput = run_command(get_token) +if rawoutput =~ /X-Subject-Token: ([\w]+)/ + token = $1 +else + puts "No token in output! #{rawoutput}" + exit 1 +end + +if token + puts "We were able to retrieve a token" + puts token + verify_token = "curl -H 'X-Auth-Token: #{service_token}' 'X-Subject-Token: #{token}' http://localhost:35357/v3/auth/tokens" + puts 'verifying token' + run_command(verify_token) + ['endpoints', 'projects', 'users'].each do |x| + puts "getting #{x}" + get_keystone_data = "curl -H 'X-Auth-Token: #{token}' http://localhost:35357/v3/#{x}" + pp PSON.load(run_command(get_keystone_data)) + end +end diff --git a/keystone/lib/puppet/provider/keystone.rb b/keystone/lib/puppet/provider/keystone.rb index 849868bcb..03700a81c 100644 --- a/keystone/lib/puppet/provider/keystone.rb +++ b/keystone/lib/puppet/provider/keystone.rb @@ -10,62 +10,37 @@ class Puppet::Provider::Keystone < Puppet::Provider::Openstack INI_FILENAME = '/etc/keystone/keystone.conf' - def self.get_endpoint - endpoint = nil - if ENV['OS_AUTH_URL'] - endpoint = ENV['OS_AUTH_URL'] - else - endpoint = get_os_vars_from_rcfile(rc_filename)['OS_AUTH_URL'] - unless endpoint - # This is from legacy but seems wrong, we want auth_url not url! - endpoint = get_admin_endpoint - end - end - unless endpoint - raise(Puppet::Error::OpenstackAuthInputError, 'Could not find auth url to check user password.') - end - endpoint - end - def self.admin_endpoint @admin_endpoint ||= get_admin_endpoint end - # use the domain in this order: - # 1 - the domain name specified in the resource definition - resource[:domain] - # 2 - the domain name part of the resource name/title e.g. user_name::user_domain - # if passed in by name_and_domain above - # 3 - use the specified default_domain_name - # 4 - lookup the default domain - # 5 - use 'Default' - the "default" default domain if no other one is configured - # Usage: name_and_domain(resource[:name], resource[:domain], default_domain_name) - def self.name_and_domain(namedomstr, domain_from_resource=nil, default_domain_name=nil) - name, domain = Util.split_domain(namedomstr) - ret = [name] - if domain_from_resource - ret << domain_from_resource - elsif domain - ret << domain - elsif default_domain_name - ret << default_domain_name - elsif default_domain - ret << default_domain - else - ret << 'Default' - end - ret - end - def self.admin_token @admin_token ||= get_admin_token end - def self.get_admin_token - if keystone_file and keystone_file['DEFAULT'] and keystone_file['DEFAULT']['admin_token'] - return "#{keystone_file['DEFAULT']['admin_token'].strip}" + def self.default_domain + domain_hash[default_domain_id] + end + + def self.default_domain_id + return @default_domain_id if @default_domain_id + if keystone_file and keystone_file['identity'] and keystone_file['identity']['default_domain_id'] + @default_domain_id = "#{keystone_file['identity']['default_domain_id'].strip}" else - return nil + @default_domain_id = 'default' end + @default_domain_id + end + + def self.domain_hash + return @domain_hash if @domain_hash + list = request('domain', 'list') + @domain_hash = Hash[list.collect{|domain| [domain[:id], domain[:name]]}] + @domain_hash + end + + def self.domain_name_from_id(id) + domain_hash[id] end def self.get_admin_endpoint @@ -104,49 +79,36 @@ def self.get_admin_endpoint "#{protocol}://#{host}:#{admin_port}/v#{@credentials.version}/" end - def self.request(service, action, properties=nil) - super - rescue Puppet::Error::OpenstackAuthInputError => error - request_by_service_token(service, action, error, properties) + + def self.get_admin_token + if keystone_file and keystone_file['DEFAULT'] and keystone_file['DEFAULT']['admin_token'] + return "#{keystone_file['DEFAULT']['admin_token'].strip}" + else + return nil + end end - def self.request_by_service_token(service, action, error, properties=nil) - properties ||= [] - @credentials.token = get_admin_token - @credentials.url = get_admin_endpoint - raise error unless @credentials.service_token_set? - Puppet::Provider::Openstack.request(service, action, properties, @credentials) + def self.get_endpoint + endpoint = nil + if ENV['OS_AUTH_URL'] + endpoint = ENV['OS_AUTH_URL'] + else + endpoint = get_os_vars_from_rcfile(rc_filename)['OS_AUTH_URL'] + unless endpoint + # This is from legacy but seems wrong, we want auth_url not url! + endpoint = get_admin_endpoint + end + end + unless endpoint + raise(Puppet::Error::OpenstackAuthInputError, 'Could not find auth url to check user password.') + end + endpoint end def self.ini_filename INI_FILENAME end - def self.default_domain - domain_hash[default_domain_id] - end - - def self.domain_hash - return @domain_hash if @domain_hash - list = request('domain', 'list') - @domain_hash = Hash[list.collect{|domain| [domain[:id], domain[:name]]}] - @domain_hash - end - - def self.domain_name_from_id(id) - domain_hash[id] - end - - def self.default_domain_id - return @default_domain_id if @default_domain_id - if keystone_file and keystone_file['identity'] and keystone_file['identity']['default_domain_id'] - @default_domain_id = "#{keystone_file['identity']['default_domain_id'].strip}" - else - @default_domain_id = 'default' - end - @default_domain_id - end - def self.keystone_file return @keystone_file if @keystone_file if File.exists?(ini_filename) @@ -156,6 +118,45 @@ def self.keystone_file end end + # use the domain in this order: + # 1 - the domain name specified in the resource definition - resource[:domain] + # 2 - the domain name part of the resource name/title e.g. user_name::user_domain + # if passed in by name_and_domain above + # 3 - use the specified default_domain_name + # 4 - lookup the default domain + # 5 - use 'Default' - the "default" default domain if no other one is configured + # Usage: name_and_domain(resource[:name], resource[:domain], default_domain_name) + def self.name_and_domain(namedomstr, domain_from_resource=nil, default_domain_name=nil) + name, domain = Util.split_domain(namedomstr) + ret = [name] + if domain_from_resource + ret << domain_from_resource + elsif domain + ret << domain + elsif default_domain_name + ret << default_domain_name + elsif default_domain + ret << default_domain + else + ret << 'Default' + end + ret + end + + def self.request(service, action, properties=nil) + super + rescue Puppet::Error::OpenstackAuthInputError => error + request_by_service_token(service, action, error, properties) + end + + def self.request_by_service_token(service, action, error, properties=nil) + properties ||= [] + @credentials.token = get_admin_token + @credentials.url = get_admin_endpoint + raise error unless @credentials.service_token_set? + Puppet::Provider::Openstack.request(service, action, properties, @credentials) + end + # Helper functions to use on the pre-validated enabled field def bool_to_sym(bool) bool == true ? :true : :false diff --git a/keystone/lib/puppet/provider/keystone_user/openstack.rb b/keystone/lib/puppet/provider/keystone_user/openstack.rb index 98a34cd3c..eb1e303fd 100644 --- a/keystone/lib/puppet/provider/keystone_user/openstack.rb +++ b/keystone/lib/puppet/provider/keystone_user/openstack.rb @@ -7,7 +7,7 @@ desc "Provider to manage keystone users." - @credentials = Puppet::Provider::Openstack::CredentialsV2_0.new + @credentials = Puppet::Provider::Openstack::CredentialsV3.new def initialize(value={}) super(value) @@ -15,7 +15,9 @@ def initialize(value={}) end def create - properties = [resource[:name]] + # see if resource[:domain], or user specified as user::domain + user_name, user_domain = self.class.name_and_domain(resource[:name], resource[:domain]) + properties = [user_name] if resource[:enabled] == :true properties << '--enable' elsif resource[:enabled] == :false @@ -24,18 +26,26 @@ def create if resource[:password] properties << '--password' << resource[:password] end - if resource[:tenant] - properties << '--project' << resource[:tenant] - end if resource[:email] properties << '--email' << resource[:email] end - self.class.request('user', 'create', properties) + if user_domain + properties << '--domain' + properties << user_domain + end + @property_hash = self.class.request('user', 'create', properties) + @property_hash[:domain] = user_domain + if resource[:tenant] + # DEPRECATED - To be removed in next release (Liberty) + # https://bugs.launchpad.net/puppet-keystone/+bug/1472437 + project_id = Puppet::Resource.indirection.find("Keystone_tenant/#{resource[:tenant]}")[:id] + set_project(resource[:tenant], project_id) + end @property_hash[:ensure] = :present end def destroy - self.class.request('user', 'delete', @property_hash[:id]) + self.class.request('user', 'delete', id) @property_hash.clear end @@ -89,11 +99,23 @@ def password res = resource[:password] else # Password validation - credentials = Puppet::Provider::Openstack::CredentialsV2_0.new - credentials.auth_url = self.class.get_endpoint - credentials.password = resource[:password] - credentials.project_name = resource[:tenant] - credentials.username = resource[:name] + credentials = Puppet::Provider::Openstack::CredentialsV3.new + credentials.auth_url = self.class.get_endpoint + credentials.password = resource[:password] + credentials.user_id = id + # NOTE: The only reason we use username is so that the openstack provider + # will know we are doing v3password auth - otherwise, it is not used. The + # user_id uniquely identifies the user including domain. + credentials.username, unused = self.class.name_and_domain(resource[:name], domain) + # Need to specify a project id to get a project scoped token. List + # all of the projects for the user, and use the id from the first one. + projects = self.class.request('project', 'list', ['--user', id, '--long']) + if projects && projects[0] && projects[0][:id] + credentials.project_id = projects[0][:id] + else + # last chance - try a domain scoped token + credentials.domain_name = domain + end begin token = Puppet::Provider::Openstack.request('token', 'issue', ['--format', 'value'], credentials) rescue Puppet::Error::OpenstackUnauthorizedError @@ -117,6 +139,51 @@ def replace_password=(value) @property_flush[:replace_password] = value end + def find_project_for_user(projname, project_id = nil) + # DEPRECATED - To be removed in next release (Liberty) + # https://bugs.launchpad.net/puppet-keystone/+bug/1472437 + user_name, user_domain = self.class.name_and_domain(resource[:name], resource[:domain]) + project_name, project_domain = self.class.name_and_domain(projname, nil, user_domain) + self.class.request('project', 'list', ['--user', id, '--long']).each do |project| + if (project_id == project[:id]) || + ((projname == project_name) && (project_domain == self.class.domain_name_from_id(project[:domain_id]))) + return project[:name] + end + end + return nil + end + + def set_project(newproject, project_id = nil) + # DEPRECATED - To be removed in next release (Liberty) + # https://bugs.launchpad.net/puppet-keystone/+bug/1472437 + unless project_id + project_id = Puppet::Resource.indirection.find("Keystone_tenant/#{newproject}")[:id] + end + # Currently the only way to assign a user to a tenant not using user-create + # is to use role-add - this means we also need a role - there is usual + # a default role called _member_ which can be used for this purpose. What + # usually happens in a puppet module is that immediately after calling + # keystone_user, the module will then assign a role to that user. It is + # ok for a user to have the _member_ role and another role. + default_role = "_member_" + begin + self.class.request('role', 'show', default_role) + rescue + self.class.request('role', 'create', default_role) + end + # finally, assign the user to the project with the role + self.class.request('role', 'add', [default_role, '--project', project_id, '--user', id]) + newproject + end + + # DEPRECATED - To be removed in next release (Liberty) + # https://bugs.launchpad.net/puppet-keystone/+bug/1472437 + def tenant=(value) + @property_hash[:tenant] = set_project(value) + end + + # DEPRECATED - To be removed in next release (Liberty) + # https://bugs.launchpad.net/puppet-keystone/+bug/1472437 def tenant return resource[:tenant] if sym_to_bool(resource[:ignore_default_tenant]) # use the one returned from instances @@ -130,40 +197,52 @@ def tenant if tenant_name.nil? or tenant_name.empty? return nil # nothing found, nothing given end - # If the user list command doesn't report the project, it might still be there - # We don't need to know exactly what it is, we just need to know whether it's - # the one we're trying to set. - roles = self.class.request('user role', 'list', [resource[:name], '--project', tenant_name]) - if roles.empty? - return nil - else - return tenant_name - end + project_id = Puppet::Resource.indirection.find("Keystone_tenant/#{tenant_name}")[:id] + find_project_for_user(tenant_name, project_id) end - def tenant=(value) - self.class.request('user', 'set', [resource[:name], '--project', value]) - rescue Puppet::ExecutionFailure => e - if e.message =~ /You are not authorized to perform the requested action: LDAP user update/ - # read-only LDAP identity backend - just fall through - else - raise e - end - # note: read-write ldap will silently fail, not raise an exception - else - @property_hash[:tenant] = self.class.set_project(value, resource[:name]) + def domain + @property_hash[:domain] + end + + def domain_id + @property_hash[:domain_id] end def self.instances - list = request('user', 'list', '--long') - list.collect do |user| + instance_hash = {} + request('user', 'list', ['--long']).each do |user| + # The field says "domain" but it is really the domain_id + domname = domain_name_from_id(user[:domain]) + if instance_hash.include?(user[:name]) # not unique + curdomid = instance_hash[user[:name]][:domain] + if curdomid != default_domain_id + # Move the user from the short name slot to the long name slot + # because it is not in the default domain. + curdomname = domain_name_from_id(curdomid) + instance_hash["#{user[:name]}::#{curdomname}"] = instance_hash[user[:name]] + # Use the short name slot for the new user + instance_hash[user[:name]] = user + else + # Use the long name for the new user + instance_hash["#{user[:name]}::#{domname}"] = user + end + else + # Unique (for now) - store in short name slot + instance_hash[user[:name]] = user + end + end + instance_hash.keys.collect do |user_name| + user = instance_hash[user_name] new( - :name => user[:name], + :name => user_name, :ensure => :present, :enabled => user[:enabled].downcase.chomp == 'true' ? true : false, :password => user[:password], - :project => user[:project], :email => user[:email], + :description => user[:description], + :domain => domain_name_from_id(user[:domain]), + :domain_id => user[:domain], :id => user[:id] ) end @@ -171,34 +250,19 @@ def self.instances def self.prefetch(resources) users = instances - resources.keys.each do |name| - if provider = users.find{ |user| user.name == name } - resources[name].provider = provider + resources.each do |resname, resource| + # resname may be specified as just "name" or "name::domain" + name, resdomain = name_and_domain(resname, resource[:domain]) + provider = users.find do |user| + # have a match if the full instance name matches the full resource name, OR + # the base resource name matches the base instance name, and the + # resource domain matches the instance domain + username, user_domain = name_and_domain(user.name, user.domain) + (user.name == resname) || + ((username == name) && (user_domain == resdomain)) end + resource.provider = provider if provider end end - def self.set_project(newproject, name) - # some backends do not store the project/tenant in the user object, so we have to - # to modify the project/tenant instead - # First, see if the project actually needs to change - roles = request('user role', 'list', [name, '--project', newproject]) - unless roles.empty? - return # if already set, just skip - end - # Currently the only way to assign a user to a tenant not using user-create - # is to use user-role-add - this means we also need a role - there is usual - # a default role called _member_ which can be used for this purpose. What - # usually happens in a puppet module is that immediately after calling - # keystone_user, the module will then assign a role to that user. It is - # ok for a user to have the _member_ role and another role. - default_role = "_member_" - begin - request('role', 'show', [default_role]) - rescue - debug("Keystone role #{default_role} does not exist - creating") - request('role', 'create', [default_role]) - end - request('role', 'add', [default_role, '--project', newproject, '--user', name]) - end end diff --git a/keystone/lib/puppet/provider/keystone_user_role/openstack.rb b/keystone/lib/puppet/provider/keystone_user_role/openstack.rb index da2b87044..e670a6750 100644 --- a/keystone/lib/puppet/provider/keystone_user_role/openstack.rb +++ b/keystone/lib/puppet/provider/keystone_user_role/openstack.rb @@ -1,4 +1,5 @@ require 'puppet/provider/keystone' +require 'puppet/provider/keystone/util' Puppet::Type.type(:keystone_user_role).provide( :openstack, @@ -7,7 +8,7 @@ desc "Provider to manage keystone role assignments to users." - @credentials = Puppet::Provider::Openstack::CredentialsV2_0.new + @credentials = Puppet::Provider::Openstack::CredentialsV3.new def initialize(value={}) super(value) @@ -15,9 +16,6 @@ def initialize(value={}) end def create - properties = [] - properties << '--project' << get_project - properties << '--user' << get_user if resource[:roles] resource[:roles].each do |role| self.class.request('role', 'add', [role] + properties) @@ -26,9 +24,6 @@ def create end def destroy - properties = [] - properties << '--project' << get_project - properties << '--user' << get_user if @property_hash[:roles] @property_hash[:roles].each do |role| self.class.request('role', 'remove', [role] + properties) @@ -38,10 +33,8 @@ def destroy end def exists? - if @user_role_hash - return ! @property_hash[:name].empty? - else - roles = self.class.request('user role', 'list', [get_user, '--project', get_project]) + if self.class.user_role_hash.nil? || self.class.user_role_hash.empty? + roles = self.class.request('role', 'list', properties) # Since requesting every combination of users, roles, and # projects is so expensive, construct the property hash here # instead of in self.instances so it can be used in the role @@ -55,8 +48,8 @@ def exists? role[:name] end end - return @property_hash[:ensure] == :present end + return @property_hash[:ensure] == :present end def roles @@ -68,13 +61,11 @@ def roles=(value) # determine the roles to be added and removed remove = current_roles - Array(value) add = Array(value) - current_roles - user = get_user - project = get_project add.each do |role_name| - self.class.request('role', 'add', [role_name, '--project', project, '--user', user]) + self.class.request('role', 'add', [role_name] + properties) end remove.each do |role_name| - self.class.request('role', 'remove', [role_name, '--project', project, '--user', user]) + self.class.request('role', 'remove', [role_name] + properties) end end @@ -91,6 +82,19 @@ def self.instances private + def properties + properties = [] + if get_project_id + properties << '--project' << get_project_id + elsif get_domain + properties << '--domain' << get_domain + else + error("No project or domain specified for role") + end + properties << '--user' << get_user_id + properties + end + def get_user resource[:name].rpartition('@').first end @@ -99,12 +103,67 @@ def get_project resource[:name].rpartition('@').last end + # if the role is for a domain, it will be specified as + # user@::domain - the "project" part will be empty + def get_domain + # use defined because @domain may be nil + return @domain if defined?(@domain) + projname, domname = Util.split_domain(get_project) + if projname.nil? + @domain = domname # no project specified, so must be a domain + else + @domain = nil # not a domain specific role + end + @domain + end + + def get_user_id + @user_id ||= Puppet::Resource.indirection.find("Keystone_user/#{get_user}")[:id] + end + + def get_project_id + # use defined because @project_id may be nil + return @project_id if defined?(@project_id) + projname, domname = Util.split_domain(get_project) + if projname.nil? + @project_id = nil + else + @project_id ||= Puppet::Resource.indirection.find("Keystone_tenant/#{get_project}")[:id] + end + @project_id + end + def self.get_projects - request('project', 'list').collect { |project| project[:name] } + request('project', 'list', '--long').collect do |project| + { + :id => project[:id], + :name => project[:name], + :domain_id => project[:domain_id], + :domain => domain_name_from_id(project[:domain_id]) + } + end end - def self.get_users(project) - request('user', 'list', ['--project', project]).collect { |user| user[:name] } + def self.get_users(project_id=nil, domain_id=nil) + properties = ['--long'] + if project_id + properties << '--project' << project_id + elsif domain_id + properties << '--domain' << domain_id + end + request('user', 'list', properties).collect do |user| + { + :id => user[:id], + :name => user[:name], + # note - column is "Domain" but it is really the domain id + :domain_id => user[:domain], + :domain => domain_name_from_id(user[:domain]) + } + end + end + + def self.user_role_hash + @user_role_hash end def self.set_user_role_hash(user_role_hash) @@ -112,16 +171,32 @@ def self.set_user_role_hash(user_role_hash) end def self.build_user_role_hash - hash = @user_role_hash || {} + # The new hash will have the property that if the + # given key does not exist, create it with an empty + # array as the value for the hash key + hash = @user_role_hash || Hash.new{|h,k| h[k] = []} return hash unless hash.empty? - projects = get_projects - projects.each do |project| - users = get_users(project) - users.each do |user| - user_roles = request('user role', 'list', [user, '--project', project]) - hash["#{user}@#{project}"] = [] - user_roles.each do |role| - hash["#{user}@#{project}"] << role[:name] + # Need a mapping of project id to names. + project_hash = {} + Puppet::Type.type(:keystone_tenant).provider(:openstack).instances.each do |project| + project_hash[project.id] = project.name + end + # Need a mapping of user id to names. + user_hash = {} + Puppet::Type.type(:keystone_user).provider(:openstack).instances.each do |user| + user_hash[user.id] = user.name + end + # need a mapping of role id to name + role_hash = {} + request('role', 'list').each {|role| role_hash[role[:id]] = role[:name]} + # now, get all role assignments + request('role assignment', 'list').each do |assignment| + if assignment[:user] + if assignment[:project] + hash["#{user_hash[assignment[:user]]}@#{project_hash[assignment[:project]]}"] << role_hash[assignment[:role]] + else + domainname = domain_id_to_name(assignment[:domain]) + hash["#{user_hash[assignment[:user]]}@::#{domainname}"] << role_hash[assignment[:role]] end end end diff --git a/keystone/lib/puppet/type/keystone_domain.rb b/keystone/lib/puppet/type/keystone_domain.rb index 4a2d77736..687da2826 100644 --- a/keystone/lib/puppet/type/keystone_domain.rb +++ b/keystone/lib/puppet/type/keystone_domain.rb @@ -46,8 +46,8 @@ end # we should not do anything until the keystone service is started - autorequire(:service) do - 'keystone' + autorequire(:anchor) do + ['keystone_started'] end diff --git a/keystone/lib/puppet/type/keystone_endpoint.rb b/keystone/lib/puppet/type/keystone_endpoint.rb index 43c5eb2ea..55d69f427 100644 --- a/keystone/lib/puppet/type/keystone_endpoint.rb +++ b/keystone/lib/puppet/type/keystone_endpoint.rb @@ -31,8 +31,8 @@ end # we should not do anything until the keystone service is started - autorequire(:service) do - ['keystone'] + autorequire(:anchor) do + ['keystone_started'] end autorequire(:keystone_service) do diff --git a/keystone/lib/puppet/type/keystone_role.rb b/keystone/lib/puppet/type/keystone_role.rb index 3636afb27..15ec26a5c 100644 --- a/keystone/lib/puppet/type/keystone_role.rb +++ b/keystone/lib/puppet/type/keystone_role.rb @@ -22,7 +22,7 @@ end # we should not do anything until the keystone service is started - autorequire(:service) do - ['keystone'] + autorequire(:anchor) do + ['keystone_started'] end end diff --git a/keystone/lib/puppet/type/keystone_service.rb b/keystone/lib/puppet/type/keystone_service.rb index a4be4edae..5fb2933c3 100644 --- a/keystone/lib/puppet/type/keystone_service.rb +++ b/keystone/lib/puppet/type/keystone_service.rb @@ -35,7 +35,7 @@ # config is configured IF we need them for authentication. # If there is no keystone config, authentication credentials # need to come from another source. - autorequire(:service) do - ['keystone'] + autorequire(:anchor) do + ['keystone_started'] end end diff --git a/keystone/lib/puppet/type/keystone_tenant.rb b/keystone/lib/puppet/type/keystone_tenant.rb index 449ccd04e..4bddd8185 100644 --- a/keystone/lib/puppet/type/keystone_tenant.rb +++ b/keystone/lib/puppet/type/keystone_tenant.rb @@ -53,7 +53,7 @@ def insync?(is) # config is configured IF we need them for authentication. # If there is no keystone config, authentication credentials # need to come from another source. - autorequire(:service) do - ['keystone'] + autorequire(:anchor) do + ['keystone_started','default_domain_created'] end end diff --git a/keystone/lib/puppet/type/keystone_user.rb b/keystone/lib/puppet/type/keystone_user.rb index b484e7c5f..5c13d762c 100644 --- a/keystone/lib/puppet/type/keystone_user.rb +++ b/keystone/lib/puppet/type/keystone_user.rb @@ -2,6 +2,8 @@ File.expand_path('../..', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) } File.expand_path('../../../../openstacklib/lib', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) } +require 'puppet/provider/keystone/util' + Puppet::Type.newtype(:keystone_user) do desc 'Type for managing keystone users.' @@ -13,6 +15,11 @@ end newparam(:ignore_default_tenant) do + # DEPRECATED - To be removed in next release (Liberty) + # https://bugs.launchpad.net/puppet-keystone/+bug/1472437 + validate do |v| + Puppet.warning('The ignore_default_tenant parameter is deprecated and will be removed in the future.') + end newvalues(/(t|T)rue/, /(f|F)alse/, true, false) defaultto(false) munge do |value| @@ -48,6 +55,11 @@ def should_to_s( newvalue ) end newproperty(:tenant) do + # DEPRECATED - To be removed in next release (Liberty) + # https://bugs.launchpad.net/puppet-keystone/+bug/1472437 + validate do |v| + Puppet.warning('The tenant parameter is deprecated and will be removed in the future. Please use keystone_user_role to assign a user to a project.') + end newvalues(/\S+/) end @@ -69,12 +81,27 @@ def should_to_s( newvalue ) end end + newproperty(:domain) do + newvalues(nil, /\S+/) + def insync?(is) + raise(Puppet::Error, "The domain cannot be changed from #{self.should} to #{is}") unless self.should == is + true + end + end + autorequire(:keystone_tenant) do + # DEPRECATED - To be removed in next release (Liberty) + # https://bugs.launchpad.net/puppet-keystone/+bug/1472437 self[:tenant] end + autorequire(:keystone_domain) do + # use the domain parameter if given, or the one from name if any + self[:domain] or Util.split_domain(self[:name])[1] + end + # we should not do anything until the keystone service is started - autorequire(:service) do - ['keystone'] + autorequire(:anchor) do + ['keystone_started','default_domain_created'] end end diff --git a/keystone/lib/puppet/type/keystone_user_role.rb b/keystone/lib/puppet/type/keystone_user_role.rb index 502dc3976..28be7fdf2 100644 --- a/keystone/lib/puppet/type/keystone_user_role.rb +++ b/keystone/lib/puppet/type/keystone_user_role.rb @@ -2,6 +2,8 @@ File.expand_path('../..', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) } File.expand_path('../../../../openstacklib/lib', File.dirname(__FILE__)).tap { |dir| $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir) } +require 'puppet/provider/keystone/util' + Puppet::Type.newtype(:keystone_user_role) do desc <<-EOT @@ -31,15 +33,33 @@ def insync?(is) end autorequire(:keystone_tenant) do - self[:name].rpartition('@').last + proj, dom = Util.split_domain(self[:name].rpartition('@').last) + rv = nil + if proj # i.e. not ::domain + rv = self[:name].rpartition('@').last + end + rv end autorequire(:keystone_role) do self[:roles] end + autorequire(:keystone_domain) do + rv = [] + userdom = Util.split_domain(self[:name].rpartition('@').first)[1] + if userdom + rv << userdom + end + projectdom = Util.split_domain(self[:name].rpartition('@').last)[1] + if projectdom + rv << projectdom + end + rv + end + # we should not do anything until the keystone service is started - autorequire(:service) do - ['keystone'] + autorequire(:anchor) do + ['keystone_started'] end end diff --git a/keystone/manifests/endpoint.pp b/keystone/manifests/endpoint.pp index 6c821f475..ddf5c1368 100644 --- a/keystone/manifests/endpoint.pp +++ b/keystone/manifests/endpoint.pp @@ -22,6 +22,20 @@ # [*version*] # (optional) API version for endpoint. Appended to all endpoint urls. (Defaults to 'v2.0') # +# [*user_domain*] +# (Optional) Domain for $auth_name +# Defaults to undef (use the keystone server default domain) +# +# [*project_domain*] +# (Optional) Domain for $tenant (project) +# Defaults to undef (use the keystone server default domain) +# +# [*default_domain*] +# (Optional) Domain for $auth_name and $tenant (project) +# If keystone_user_domain is not specified, use $keystone_default_domain +# If keystone_project_domain is not specified, use $keystone_default_domain +# Defaults to undef +# # === Examples # # class { 'keystone::endpoint': @@ -36,6 +50,9 @@ $admin_url = 'http://127.0.0.1:35357', $version = 'v2.0', $region = 'RegionOne', + $user_domain = undef, + $project_domain = undef, + $default_domain = undef, ) { $public_url_real = "${public_url}/${version}" @@ -56,6 +73,9 @@ admin_url => $admin_url_real, internal_url => $internal_url_real, region => $region, + user_domain => $user_domain, + project_domain => $project_domain, + default_domain => $default_domain, } } diff --git a/keystone/manifests/init.pp b/keystone/manifests/init.pp index 20c2011e3..9dfd5e7e8 100644 --- a/keystone/manifests/init.pp +++ b/keystone/manifests/init.pp @@ -363,6 +363,14 @@ # (Optional) Number of maximum active Fernet keys. Integer > 0. # Defaults to undef # +# [*default_domain*] +# (optional) When Keystone v3 support is enabled, v2 clients will need +# to have a domain assigned for certain operations. For example, +# doing a user create operation must have a domain associated with it. +# This is the domain which will be used if a domain is needed and not +# explicitly set in the request. +# Defaults to undef (will use built-in Keystone default) +# # == Dependencies # None # @@ -467,6 +475,7 @@ $enable_fernet_setup = false, $fernet_key_repository = '/etc/keystone/fernet-keys', $fernet_max_active_keys = undef, + $default_domain = undef, # DEPRECATED PARAMETERS $mysql_module = undef, $compute_port = undef, @@ -804,6 +813,7 @@ } if $service_name == $::keystone::params::service_name { + $service_name_real = $::keystone::params::service_name if $validate_service { if $validate_auth_url { $v_auth_url = $validate_auth_url @@ -836,6 +846,7 @@ } } } elsif $service_name == 'httpd' { + include ::apache::params class { '::keystone::service': ensure => 'stopped', service_name => $::keystone::params::service_name, @@ -843,6 +854,7 @@ provider => $service_provider, validate => false, } + $service_name_real = $::apache::params::service_name } else { fail('Invalid service_name. Either keystone/openstack-keystone for running as a standalone service, or httpd for being run by a httpd server') } @@ -927,4 +939,33 @@ } } + if $default_domain { + keystone_domain { $default_domain: + ensure => present, + enabled => true, + is_default => true, + require => File['/etc/keystone/keystone.conf'], + notify => Exec['restart_keystone'], + } + anchor { 'default_domain_created': + require => Keystone_domain[$default_domain], + } + # Update this code when https://bugs.launchpad.net/keystone/+bug/1472285 is addressed. + # 1/ Keystone needs to be started before creating the default domain + # 2/ Once the default domain is created, we can query Keystone to get the default domain ID + # 3/ The Keystone_domain provider has in charge of doing the query and configure keystone.conf + # 4/ After such a change, we need to restart Keystone service. + # restart_keystone exec is doing 4/, it restart Keystone if we have a new default domain setted + # and if we manage the service to be enabled. + if $manage_service and $enabled { + exec { 'restart_keystone': + path => ['/usr/sbin', '/usr/bin', '/sbin', '/bin/'], + command => "service ${service_name_real} restart", + refreshonly => true, + } + } + } + anchor { 'keystone_started': + require => Service[$service_name] + } } diff --git a/keystone/manifests/resource/authtoken.pp b/keystone/manifests/resource/authtoken.pp new file mode 100644 index 000000000..5165abb3a --- /dev/null +++ b/keystone/manifests/resource/authtoken.pp @@ -0,0 +1,253 @@ +# == Definition: keystone::resource::authtoken +# +# This resource configures Keystone authentication resources for an OpenStack +# service. It will manage the [keystone_authtoken] section in the given +# config resource. It supports all of the authentication parameters specified +# at http://www.jamielennox.net/blog/2015/02/17/loading-authentication-plugins/ +# with the addition of the default domain for user and project. +# +# The username and project_name parameters may be given in the form +# "name::domainname". The authtoken resource will use the domains in +# the following order: +# 1) The given domain parameter (user_domain_name or project_domain_name) +# 2) The domain given as the "::domainname" part of username or project_name +# 3) The default_domain_name +# +# For example, instead of doing this:: +# +# glance_api_config { +# 'keystone_authtoken/admin_tenant_name': value => $keystone_tenant; +# 'keystone_authtoken/admin_user' : value => $keystone_user; +# 'keystone_authtoken/admin_password' : value => $keystone_password; +# secret => true; +# ... +# } +# +# manifests should do this instead:: +# +# keystone::resource::authtoken { 'glance_api_config': +# username => $keystone_user, +# password => $keystone_password, +# auth_url => $real_identity_uri, +# project_name => $keystone_tenant, +# user_domain_name => $keystone_user_domain, +# project_domain_name => $keystone_project_domain, +# default_domain_name => $keystone_default_domain, +# cacert => $ca_file, +# ... +# } +# +# The use of `keystone::resource::authtoken` makes it easy to avoid mistakes, +# and makes it easier to support some of the newer authentication types coming +# with Keystone Kilo and later, such as Kerberos, Federation, etc. +# +# == Parameters: +# +# [*name*] +# The name of the resource corresponding to the config file. For example, +# keystone::resource::authtoken { 'glance_api_config': ... } +# Where 'glance_api_config' is the name of the resource used to manage +# the glance api configuration. +# string; required +# +# [*username*] +# The name of the service user; +# string; required +# +# [*password*] +# Password to create for the service user; +# string; required +# +# [*auth_url*] +# The URL to use for authentication. +# string; required +# +# [*auth_plugin*] +# The plugin to use for authentication. +# string; optional: default to 'password' +# +# [*user_id*] +# The ID of the service user; +# string; optional: default to undef +# +# [*user_domain_name*] +# (Optional) Name of domain for $username +# Defaults to undef +# +# [*user_domain_id*] +# (Optional) ID of domain for $username +# Defaults to undef +# +# [*project_name*] +# Service project name; +# string; optional: default to undef +# +# [*project_id*] +# Service project ID; +# string; optional: default to undef +# +# [*project_domain_name*] +# (Optional) Name of domain for $project_name +# Defaults to undef +# +# [*project_domain_id*] +# (Optional) ID of domain for $project_name +# Defaults to undef +# +# [*domain_name*] +# (Optional) Use this for auth to obtain a domain-scoped token. +# If using this option, do not specify $project_name or $project_id. +# Defaults to undef +# +# [*domain_id*] +# (Optional) Use this for auth to obtain a domain-scoped token. +# If using this option, do not specify $project_name or $project_id. +# Defaults to undef +# +# [*default_domain_name*] +# (Optional) Name of domain for $username and $project_name +# If user_domain_name is not specified, use $default_domain_name +# If project_domain_name is not specified, use $default_domain_name +# Defaults to undef +# +# [*default_domain_id*] +# (Optional) ID of domain for $user_id and $project_id +# If user_domain_id is not specified, use $default_domain_id +# If project_domain_id is not specified, use $default_domain_id +# Defaults to undef +# +# [*trust_id*] +# (Optional) Trust ID +# Defaults to undef +# +# [*cacert*] +# (Optional) CA certificate file for TLS (https) +# Defaults to undef +# +# [*cert*] +# (Optional) Certificate file for TLS (https) +# Defaults to undef +# +# [*key*] +# (Optional) Key file for TLS (https) +# Defaults to undef +# +# [*insecure*] +# If true, explicitly allow TLS without checking server cert against any +# certificate authorities. WARNING: not recommended. Use with caution. +# boolean; Defaults to false (which means be secure) +# +define keystone::resource::authtoken( + $username, + $password, + $auth_url, + $auth_plugin = 'password', + $user_id = undef, + $user_domain_name = undef, + $user_domain_id = undef, + $project_name = undef, + $project_id = undef, + $project_domain_name = undef, + $project_domain_id = undef, + $domain_name = undef, + $domain_id = undef, + $default_domain_name = undef, + $default_domain_id = undef, + $trust_id = undef, + $cacert = undef, + $cert = undef, + $key = undef, + $insecure = false, +) { + + if !$project_name and !$project_id and !$domain_name and !$domain_id { + fail('Must specify either a project (project_name or project_id, for a project scoped token) or a domain (domain_name or domain_id, for a domain scoped token)') + } + + if ($project_name or $project_id) and ($domain_name or $domain_id) { + fail('Cannot specify both a project (project_name or project_id) and a domain (domain_name or domain_id)') + } + + $user_and_domain_array = split($username, '::') + $real_username = $user_and_domain_array[0] + $real_user_domain_name = pick($user_domain_name, $user_and_domain_array[1], $default_domain_name, '__nodomain__') + + $project_and_domain_array = split($project_name, '::') + $real_project_name = $project_and_domain_array[0] + $real_project_domain_name = pick($project_domain_name, $project_and_domain_array[1], $default_domain_name, '__nodomain__') + + create_resources($name, {'keystone_authtoken/auth_plugin' => {'value' => $auth_plugin}}) + create_resources($name, {'keystone_authtoken/auth_url' => {'value' => $auth_url}}) + create_resources($name, {'keystone_authtoken/username' => {'value' => $real_username}}) + create_resources($name, {'keystone_authtoken/password' => {'value' => $password, 'secret' => true}}) + if $user_id { + create_resources($name, {'keystone_authtoken/user_id' => {'value' => $user_id}}) + } else { + create_resources($name, {'keystone_authtoken/user_id' => {'ensure' => 'absent'}}) + } + if $real_user_domain_name == '__nodomain__' { + create_resources($name, {'keystone_authtoken/user_domain_name' => {'ensure' => 'absent'}}) + } else { + create_resources($name, {'keystone_authtoken/user_domain_name' => {'value' => $real_user_domain_name}}) + } + if $user_domain_id { + create_resources($name, {'keystone_authtoken/user_domain_id' => {'value' => $user_domain_id}}) + } elsif $default_domain_id { + create_resources($name, {'keystone_authtoken/user_domain_id' => {'value' => $default_domain_id}}) + } else { + create_resources($name, {'keystone_authtoken/user_domain_id' => {'ensure' => 'absent'}}) + } + if $project_name { + create_resources($name, {'keystone_authtoken/project_name' => {'value' => $real_project_name}}) + } else { + create_resources($name, {'keystone_authtoken/project_name' => {'ensure' => 'absent'}}) + } + if $project_id { + create_resources($name, {'keystone_authtoken/project_id' => {'value' => $project_id}}) + } else { + create_resources($name, {'keystone_authtoken/project_id' => {'ensure' => 'absent'}}) + } + if $real_project_domain_name == '__nodomain__' { + create_resources($name, {'keystone_authtoken/project_domain_name' => {'ensure' => 'absent'}}) + } else { + create_resources($name, {'keystone_authtoken/project_domain_name' => {'value' => $real_project_domain_name}}) + } + if $project_domain_id { + create_resources($name, {'keystone_authtoken/project_domain_id' => {'value' => $project_domain_id}}) + } elsif $default_domain_id { + create_resources($name, {'keystone_authtoken/project_domain_id' => {'value' => $default_domain_id}}) + } else { + create_resources($name, {'keystone_authtoken/project_domain_id' => {'ensure' => 'absent'}}) + } + if $domain_name { + create_resources($name, {'keystone_authtoken/domain_name' => {'value' => $domain_name}}) + } else { + create_resources($name, {'keystone_authtoken/domain_name' => {'ensure' => 'absent'}}) + } + if $domain_id { + create_resources($name, {'keystone_authtoken/domain_id' => {'value' => $domain_id}}) + } else { + create_resources($name, {'keystone_authtoken/domain_id' => {'ensure' => 'absent'}}) + } + if $trust_id { + create_resources($name, {'keystone_authtoken/trust_id' => {'value' => $trust_id}}) + } else { + create_resources($name, {'keystone_authtoken/trust_id' => {'ensure' => 'absent'}}) + } + if $cacert { + create_resources($name, {'keystone_authtoken/cacert' => {'value' => $cacert}}) + } else { + create_resources($name, {'keystone_authtoken/cacert' => {'ensure' => 'absent'}}) + } + if $cert { + create_resources($name, {'keystone_authtoken/cert' => {'value' => $cert}}) + } else { + create_resources($name, {'keystone_authtoken/cert' => {'ensure' => 'absent'}}) + } + if $key { + create_resources($name, {'keystone_authtoken/key' => {'value' => $key}}) + } else { + create_resources($name, {'keystone_authtoken/key' => {'ensure' => 'absent'}}) + } + create_resources($name, {'keystone_authtoken/insecure' => {'value' => $insecure}}) +} diff --git a/keystone/manifests/resource/service_identity.pp b/keystone/manifests/resource/service_identity.pp index 9bbd1b13a..4ac132205 100644 --- a/keystone/manifests/resource/service_identity.pp +++ b/keystone/manifests/resource/service_identity.pp @@ -69,10 +69,6 @@ # List of roles; # string; optional: default to ['admin'] # -# [*domain*] -# User domain (keystone v3), not implemented yet. -# string; optional: default to undef -# # [*email*] # Service email; # string; optional: default to '$auth_name@localhost' @@ -93,6 +89,20 @@ # Whether to create the service. # string; optional: default to True # +# [*user_domain*] +# (Optional) Domain for $auth_name +# Defaults to undef (use the keystone server default domain) +# +# [*project_domain*] +# (Optional) Domain for $tenant (project) +# Defaults to undef (use the keystone server default domain) +# +# [*default_domain*] +# (Optional) Domain for $auth_name and $tenant (project) +# If keystone_user_domain is not specified, use $keystone_default_domain +# If keystone_project_domain is not specified, use $keystone_default_domain +# Defaults to undef +# define keystone::resource::service_identity( $admin_url = false, $internal_url = false, @@ -104,7 +114,6 @@ $configure_user = true, $configure_user_role = true, $configure_service = true, - $domain = undef, $email = "${name}@localhost", $region = 'RegionOne', $service_name = undef, @@ -112,19 +121,32 @@ $tenant = 'services', $ignore_default_tenant = false, $roles = ['admin'], + $user_domain = undef, + $project_domain = undef, + $default_domain = undef, ) { - - if $domain { - warning('Keystone domains are not yet managed by puppet-keystone.') - } - if $service_name == undef { $service_name_real = $auth_name } else { $service_name_real = $service_name } + if $user_domain == undef { + $user_domain_real = $default_domain + } else { + $user_domain_real = $user_domain + } + if $configure_user { + if $user_domain_real { + # We have to use ensure_resource here and hope for the best, because we have + # no way to know if the $user_domain is the same domain passed as the + # $default_domain parameter to class keystone. + ensure_resource('keystone_domain', $user_domain_real, { + 'ensure' => 'present', + 'enabled' => true, + }) + } ensure_resource('keystone_user', $auth_name, { 'ensure' => 'present', 'enabled' => true, @@ -132,6 +154,7 @@ 'email' => $email, 'tenant' => $tenant, 'ignore_default_tenant' => $ignore_default_tenant, + 'domain' => $user_domain_real, }) } @@ -140,9 +163,6 @@ 'ensure' => 'present', 'roles' => $roles, }) - if $configure_user { - Keystone_user[$auth_name] -> Keystone_user_role["${auth_name}@${tenant}"] - } } if $configure_service { diff --git a/keystone/manifests/roles/admin.pp b/keystone/manifests/roles/admin.pp index aa5abd72f..37758c812 100644 --- a/keystone/manifests/roles/admin.pp +++ b/keystone/manifests/roles/admin.pp @@ -51,7 +51,19 @@ # # [*configure_user_role*] # Optional. Should the admin role be configured for the admin user? -# Defaulst to 'true'. +# Defaults to 'true'. +# +# [*admin_user_domain*] +# Optional. Domain of the admin user +# Defaults to undef (undef will resolve to class keystone $default_domain) +# +# [*admin_project_domain*] +# Optional. Domain of the admin tenant +# Defaults to undef (undef will resolve to class keystone $default_domain) +# +# [*service_project_domain*] +# Optional. Domain for $service_tenant +# Defaults to undef (undef will resolve to class keystone $default_domain) # # == Dependencies # == Examples @@ -75,17 +87,28 @@ $service_tenant_desc = 'Tenant for the openstack services', $configure_user = true, $configure_user_role = true, + $admin_user_domain = undef, + $admin_project_domain = undef, + $service_project_domain = undef, ) { + $domains = unique(delete_undef_values([ $admin_user_domain, $admin_project_domain, $service_project_domain])) + keystone_domain { $domains: + ensure => present, + enabled => true, + } + keystone_tenant { $service_tenant: ensure => present, enabled => true, description => $service_tenant_desc, + domain => $service_project_domain, } keystone_tenant { $admin_tenant: ensure => present, enabled => true, description => $admin_tenant_desc, + domain => $admin_project_domain, } keystone_role { 'admin': ensure => present, @@ -98,6 +121,7 @@ tenant => $admin_tenant, email => $email, password => $password, + domain => $admin_user_domain, ignore_default_tenant => $ignore_default_tenant, } } diff --git a/keystone/metadata.json b/keystone/metadata.json index 77e23afd4..5a2e3ff61 100644 --- a/keystone/metadata.json +++ b/keystone/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-keystone", - "version": "5.1.0", + "name": "openstack-keystone", + "version": "6.0.0", "author": "Puppet Labs and OpenStack Contributors", "summary": "Puppet module for OpenStack Keystone", "license": "Apache-2.0", @@ -34,6 +34,6 @@ { "name": "puppetlabs/apache", "version_requirement": ">=1.0.0 <2.0.0" }, { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/keystone/spec/acceptance/basic_keystone_spec.rb b/keystone/spec/acceptance/basic_keystone_spec.rb index b0fd8d398..f8aa5023f 100644 --- a/keystone/spec/acceptance/basic_keystone_spec.rb +++ b/keystone/spec/acceptance/basic_keystone_spec.rb @@ -42,14 +42,17 @@ class { '::keystone': database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone', admin_token => 'admin_token', enabled => true, + default_domain => 'default_domain', } + # "v2" admin and service class { '::keystone::roles::admin': - email => 'test@example.tld', - password => 'a_big_secret', + email => 'test@example.tld', + password => 'a_big_secret', } class { '::keystone::endpoint': - public_url => "http://127.0.0.1:5000/", - admin_url => "http://127.0.0.1:35357/", + public_url => "http://127.0.0.1:5000/", + admin_url => "http://127.0.0.1:35357/", + default_domain => 'admin', } ::keystone::resource::service_identity { 'beaker-ci': service_type => 'beaker', @@ -60,6 +63,56 @@ class { '::keystone::endpoint': admin_url => 'http://127.0.0.1:1234', internal_url => 'http://127.0.0.1:1234', } + # v3 admin + # we don't use ::keystone::roles::admin but still create resources manually: + keystone_domain { 'admin_domain': + ensure => present, + enabled => true, + description => 'Domain for admin v3 users', + } + keystone_domain { 'service_domain': + ensure => present, + enabled => true, + description => 'Domain for admin v3 users', + } + keystone_tenant { 'servicesv3': + ensure => present, + enabled => true, + description => 'Tenant for the openstack services', + domain => 'service_domain', + } + keystone_tenant { 'openstackv3': + ensure => present, + enabled => true, + description => 'admin tenant', + domain => 'admin_domain', + } + keystone_user { 'adminv3': + ensure => present, + enabled => true, + tenant => 'openstackv3', # note: don't have to use 'openstackv3::admin_domain' here since the tenant name 'openstackv3' is unique among all domains + email => 'test@example.tld', + password => 'a_big_secret', + domain => 'admin_domain', + } + keystone_user_role { 'adminv3@openstackv3': + ensure => present, + roles => ['admin'], + } + # service user exists only in the service_domain - must + # use v3 api + ::keystone::resource::service_identity { 'beaker-civ3': + service_type => 'beakerv3', + service_description => 'beakerv3 service', + service_name => 'beakerv3', + password => 'secret', + tenant => 'servicesv3', + public_url => 'http://127.0.0.1:1234/v3', + admin_url => 'http://127.0.0.1:1234/v3', + internal_url => 'http://127.0.0.1:1234/v3', + user_domain => 'service_domain', + project_domain => 'service_domain', + } EOS @@ -77,40 +130,97 @@ class { '::keystone::endpoint': end describe cron do - it { should have_entry('1 0 * * * keystone-manage token_flush >>/var/log/keystone/keystone-tokenflush.log 2>&1').with_user('keystone') } + it { is_expected.to have_entry('1 0 * * * keystone-manage token_flush >>/var/log/keystone/keystone-tokenflush.log 2>&1').with_user('keystone') } end - describe 'test keystone user/tenant/service/role/endpoint resources' do + shared_examples_for 'keystone user/tenant/service/role/endpoint resources using v2 API' do |auth_creds| + it 'should find users in the default domain' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v2.0 --os-identity-api-version 2 user list") do |r| + expect(r.stdout).to match(/admin/) + expect(r.stderr).to be_empty + end + end + it 'should find tenants in the default domain' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v2.0 --os-identity-api-version 2 project list") do |r| + expect(r.stdout).to match(/openstack/) + expect(r.stderr).to be_empty + end + end + it 'should find beaker service' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v2.0 --os-identity-api-version 2 service list") do |r| + expect(r.stdout).to match(/beaker/) + expect(r.stderr).to be_empty + end + end + it 'should find admin role' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v2.0 --os-identity-api-version 2 role list") do |r| + expect(r.stdout).to match(/admin/) + expect(r.stderr).to be_empty + end + end + it 'should find beaker endpoints' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v2.0 --os-identity-api-version 2 endpoint list --long") do |r| + expect(r.stdout).to match(/1234/) + expect(r.stderr).to be_empty + end + end + end + shared_examples_for 'keystone user/tenant/service/role/endpoint resources using v3 API' do |auth_creds| it 'should find beaker user' do - shell('openstack --os-username admin --os-password a_big_secret --os-tenant-name openstack --os-auth-url http://127.0.0.1:5000/v2.0 user list') do |r| + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v3 --os-identity-api-version 3 user list") do |r| expect(r.stdout).to match(/beaker/) expect(r.stderr).to be_empty end end it 'should find services tenant' do - shell('openstack --os-username admin --os-password a_big_secret --os-tenant-name openstack --os-auth-url http://127.0.0.1:5000/v2.0 project list') do |r| + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v3 --os-identity-api-version 3 project list") do |r| expect(r.stdout).to match(/services/) expect(r.stderr).to be_empty end end it 'should find beaker service' do - shell('openstack --os-username admin --os-password a_big_secret --os-tenant-name openstack --os-auth-url http://127.0.0.1:5000/v2.0 service list') do |r| + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v3 --os-identity-api-version 3 service list") do |r| expect(r.stdout).to match(/beaker/) expect(r.stderr).to be_empty end end it 'should find admin role' do - shell('openstack --os-username admin --os-password a_big_secret --os-tenant-name openstack --os-auth-url http://127.0.0.1:5000/v2.0 role list') do |r| + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v3 --os-identity-api-version 3 role list") do |r| expect(r.stdout).to match(/admin/) expect(r.stderr).to be_empty end end it 'should find beaker endpoints' do - shell('openstack --os-username admin --os-password a_big_secret --os-tenant-name openstack --os-auth-url http://127.0.0.1:5000/v2.0 endpoint list --long') do |r| + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v3 --os-identity-api-version 3 endpoint list") do |r| expect(r.stdout).to match(/1234/) expect(r.stderr).to be_empty end end end + describe 'with v2 admin with v2 credentials' do + include_examples 'keystone user/tenant/service/role/endpoint resources using v2 API', + '--os-username admin --os-password a_big_secret --os-project-name openstack' + end + describe 'with v2 service with v2 credentials' do + include_examples 'keystone user/tenant/service/role/endpoint resources using v2 API', + '--os-username beaker-ci --os-password secret --os-project-name services' + end + describe 'with v2 admin with v3 credentials' do + include_examples 'keystone user/tenant/service/role/endpoint resources using v3 API', + '--os-username admin --os-password a_big_secret --os-project-name openstack --os-user-domain-name default_domain --os-project-domain-name default_domain' + end + describe "with v2 service with v3 credentials" do + include_examples 'keystone user/tenant/service/role/endpoint resources using v3 API', + '--os-username beaker-ci --os-password secret --os-project-name services --os-user-domain-name default_domain --os-project-domain-name default_domain' + end + describe 'with v3 admin with v3 credentials' do + include_examples 'keystone user/tenant/service/role/endpoint resources using v3 API', + '--os-username adminv3 --os-password a_big_secret --os-project-name openstackv3 --os-user-domain-name admin_domain --os-project-domain-name admin_domain' + end + describe "with v3 service with v3 credentials" do + include_examples 'keystone user/tenant/service/role/endpoint resources using v3 API', + '--os-username beaker-civ3 --os-password secret --os-project-name servicesv3 --os-user-domain-name service_domain --os-project-domain-name service_domain' + end + end end diff --git a/keystone/spec/acceptance/keystone_wsgi_apache_spec.rb b/keystone/spec/acceptance/keystone_wsgi_apache_spec.rb new file mode 100644 index 000000000..b7c8d9dc2 --- /dev/null +++ b/keystone/spec/acceptance/keystone_wsgi_apache_spec.rb @@ -0,0 +1,232 @@ +require 'spec_helper_acceptance' + +describe 'keystone server running with Apache/WSGI with resources' do + + context 'default parameters' do + + it 'should work with no errors' do + pp= <<-EOS + Exec { logoutput => 'on_failure' } + + # Common resources + case $::osfamily { + 'Debian': { + include ::apt + class { '::openstack_extras::repo::debian::ubuntu': + release => 'kilo', + package_require => true, + } + } + 'RedHat': { + class { '::openstack_extras::repo::redhat::redhat': + release => 'kilo', + } + package { 'openstack-selinux': ensure => 'latest' } + } + default: { + fail("Unsupported osfamily (${::osfamily})") + } + } + + class { '::mysql::server': } + + # Keystone resources + class { '::keystone::client': } + class { '::keystone::cron::token_flush': } + class { '::keystone::db::mysql': + password => 'keystone', + } + class { '::keystone': + verbose => true, + debug => true, + database_connection => 'mysql://keystone:keystone@127.0.0.1/keystone', + admin_token => 'admin_token', + enabled => true, + service_name => 'httpd', + default_domain => 'default_domain', + } + include ::apache + class { '::keystone::wsgi::apache': + ssl => false, + } + + # "v2" admin and service + class { '::keystone::roles::admin': + email => 'test@example.tld', + password => 'a_big_secret', + } + class { '::keystone::endpoint': + public_url => "http://127.0.0.1:5000/", + admin_url => "http://127.0.0.1:35357/", + default_domain => 'admin', + } + ::keystone::resource::service_identity { 'beaker-ci': + service_type => 'beaker', + service_description => 'beaker service', + service_name => 'beaker', + password => 'secret', + public_url => 'http://127.0.0.1:1234', + admin_url => 'http://127.0.0.1:1234', + internal_url => 'http://127.0.0.1:1234', + } + # v3 admin + # we don't use ::keystone::roles::admin but still create resources manually: + keystone_domain { 'admin_domain': + ensure => present, + enabled => true, + description => 'Domain for admin v3 users', + } + keystone_domain { 'service_domain': + ensure => present, + enabled => true, + description => 'Domain for admin v3 users', + } + keystone_tenant { 'servicesv3': + ensure => present, + enabled => true, + description => 'Tenant for the openstack services', + domain => 'service_domain', + } + keystone_tenant { 'openstackv3': + ensure => present, + enabled => true, + description => 'admin tenant', + domain => 'admin_domain', + } + keystone_user { 'adminv3': + ensure => present, + enabled => true, + tenant => 'openstackv3', # note: don't have to use 'openstackv3::admin_domain' here since the tenant name 'openstackv3' is unique among all domains + email => 'test@example.tld', + password => 'a_big_secret', + domain => 'admin_domain', + } + keystone_user_role { 'adminv3@openstackv3': + ensure => present, + roles => ['admin'], + } + # service user exists only in the service_domain - must + # use v3 api + ::keystone::resource::service_identity { 'beaker-civ3': + service_type => 'beakerv3', + service_description => 'beakerv3 service', + service_name => 'beakerv3', + password => 'secret', + tenant => 'servicesv3', + public_url => 'http://127.0.0.1:1234/v3', + admin_url => 'http://127.0.0.1:1234/v3', + internal_url => 'http://127.0.0.1:1234/v3', + user_domain => 'service_domain', + project_domain => 'service_domain', + } + EOS + + + # Run it twice and test for idempotency + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + + describe port(5000) do + it { is_expected.to be_listening } + end + + describe port(35357) do + it { is_expected.to be_listening } + end + + describe cron do + it { is_expected.to have_entry('1 0 * * * keystone-manage token_flush >>/var/log/keystone/keystone-tokenflush.log 2>&1').with_user('keystone') } + end + + shared_examples_for 'keystone user/tenant/service/role/endpoint resources using v2 API' do |auth_creds| + it 'should find users in the default domain' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v2.0 --os-identity-api-version 2 user list") do |r| + expect(r.stdout).to match(/admin/) + expect(r.stderr).to be_empty + end + end + it 'should find tenants in the default domain' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v2.0 --os-identity-api-version 2 project list") do |r| + expect(r.stdout).to match(/openstack/) + expect(r.stderr).to be_empty + end + end + it 'should find beaker service' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v2.0 --os-identity-api-version 2 service list") do |r| + expect(r.stdout).to match(/beaker/) + expect(r.stderr).to be_empty + end + end + it 'should find admin role' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v2.0 --os-identity-api-version 2 role list") do |r| + expect(r.stdout).to match(/admin/) + expect(r.stderr).to be_empty + end + end + it 'should find beaker endpoints' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v2.0 --os-identity-api-version 2 endpoint list --long") do |r| + expect(r.stdout).to match(/1234/) + expect(r.stderr).to be_empty + end + end + end + shared_examples_for 'keystone user/tenant/service/role/endpoint resources using v3 API' do |auth_creds| + it 'should find beaker user' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v3 --os-identity-api-version 3 user list") do |r| + expect(r.stdout).to match(/beaker/) + expect(r.stderr).to be_empty + end + end + it 'should find services tenant' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v3 --os-identity-api-version 3 project list") do |r| + expect(r.stdout).to match(/services/) + expect(r.stderr).to be_empty + end + end + it 'should find beaker service' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v3 --os-identity-api-version 3 service list") do |r| + expect(r.stdout).to match(/beaker/) + expect(r.stderr).to be_empty + end + end + it 'should find admin role' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v3 --os-identity-api-version 3 role list") do |r| + expect(r.stdout).to match(/admin/) + expect(r.stderr).to be_empty + end + end + it 'should find beaker endpoints' do + shell("openstack #{auth_creds} --os-auth-url http://127.0.0.1:5000/v3 --os-identity-api-version 3 endpoint list") do |r| + expect(r.stdout).to match(/1234/) + expect(r.stderr).to be_empty + end + end + end + describe 'with v2 admin with v2 credentials' do + include_examples 'keystone user/tenant/service/role/endpoint resources using v2 API', + '--os-username admin --os-password a_big_secret --os-project-name openstack' + end + describe 'with v2 service with v2 credentials' do + include_examples 'keystone user/tenant/service/role/endpoint resources using v2 API', + '--os-username beaker-ci --os-password secret --os-project-name services' + end + describe 'with v2 admin with v3 credentials' do + include_examples 'keystone user/tenant/service/role/endpoint resources using v3 API', + '--os-username admin --os-password a_big_secret --os-project-name openstack --os-user-domain-name default_domain --os-project-domain-name default_domain' + end + describe "with v2 service with v3 credentials" do + include_examples 'keystone user/tenant/service/role/endpoint resources using v3 API', + '--os-username beaker-ci --os-password secret --os-project-name services --os-user-domain-name default_domain --os-project-domain-name default_domain' + end + describe 'with v3 admin with v3 credentials' do + include_examples 'keystone user/tenant/service/role/endpoint resources using v3 API', + '--os-username adminv3 --os-password a_big_secret --os-project-name openstackv3 --os-user-domain-name admin_domain --os-project-domain-name admin_domain' + end + describe "with v3 service with v3 credentials" do + include_examples 'keystone user/tenant/service/role/endpoint resources using v3 API', + '--os-username beaker-civ3 --os-password secret --os-project-name servicesv3 --os-user-domain-name service_domain --os-project-domain-name service_domain' + end + + end +end diff --git a/keystone/spec/classes/keystone_endpoint_spec.rb b/keystone/spec/classes/keystone_endpoint_spec.rb index 217d791f9..59390ec98 100644 --- a/keystone/spec/classes/keystone_endpoint_spec.rb +++ b/keystone/spec/classes/keystone_endpoint_spec.rb @@ -48,4 +48,19 @@ ) end end + + describe 'with domain parameters' do + + let :params do + { :user_domain => 'userdomain', + :project_domain => 'projectdomain', + :default_domain => 'defaultdomain' } + end + + it { is_expected.to contain_keystone__resource__service_identity('keystone').with( + :user_domain => 'userdomain', + :project_domain => 'projectdomain', + :default_domain => 'defaultdomain' + )} + end end diff --git a/keystone/spec/classes/keystone_roles_admin_spec.rb b/keystone/spec/classes/keystone_roles_admin_spec.rb index bbd6d953b..10f2a3850 100644 --- a/keystone/spec/classes/keystone_roles_admin_spec.rb +++ b/keystone/spec/classes/keystone_roles_admin_spec.rb @@ -54,8 +54,8 @@ end it { is_expected.to contain_keystone_tenant('foobar').with( - :ensure => 'present', - :enabled => true, + :ensure => 'present', + :enabled => true, :description => 'foobar description' )} it { is_expected.to contain_keystone_tenant('admin').with( @@ -95,8 +95,8 @@ before do let :params do { - :configure_user => false, - :configure_user_role => false + :configure_user => false, + :configure_user_role => false } end @@ -105,4 +105,83 @@ end end + describe 'when specifying admin_user_domain and admin_project_domain' do + let :params do + { + :email => 'foo@bar', + :password => 'ChangeMe', + :admin_tenant => 'admin_tenant', + :admin_user_domain => 'admin_user_domain', + :admin_project_domain => 'admin_project_domain', + } + end + it { is_expected.to contain_keystone_user('admin').with( + :domain => 'admin_user_domain', + :tenant => 'admin_tenant' + )} + it { is_expected.to contain_keystone_tenant('admin_tenant').with(:domain => 'admin_project_domain') } + it { is_expected.to contain_keystone_domain('admin_user_domain') } + it { is_expected.to contain_keystone_domain('admin_project_domain') } + + end + + describe 'when specifying admin_user_domain and admin_project_domain' do + let :params do + { + :email => 'foo@bar', + :password => 'ChangeMe', + :admin_tenant => 'admin_tenant::admin_project_domain', + :admin_user_domain => 'admin_user_domain', + :admin_project_domain => 'admin_project_domain', + } + end + it { is_expected.to contain_keystone_user('admin').with( + :domain => 'admin_user_domain', + :tenant => 'admin_tenant::admin_project_domain' + )} + it { is_expected.to contain_keystone_tenant('admin_tenant::admin_project_domain').with(:domain => 'admin_project_domain') } + it { is_expected.to contain_keystone_domain('admin_user_domain') } + it { is_expected.to contain_keystone_domain('admin_project_domain') } + + end + + describe 'when specifying a service domain' do + let :params do + { + :email => 'foo@bar', + :password => 'ChangeMe', + :service_tenant => 'service_project', + :service_project_domain => 'service_domain' + } + end + it { is_expected.to contain_keystone_tenant('service_project').with(:domain => 'service_domain') } + it { is_expected.to contain_keystone_domain('service_domain') } + + end + + describe 'when specifying a service domain and service tenant domain' do + let :params do + { + :email => 'foo@bar', + :password => 'ChangeMe', + :service_tenant => 'service_project::service_domain', + :service_project_domain => 'service_domain' + } + end + it { is_expected.to contain_keystone_tenant('service_project::service_domain').with(:domain => 'service_domain') } + it { is_expected.to contain_keystone_domain('service_domain') } + + end + + describe 'when admin_user_domain and admin_project_domain are equal' do + let :params do + { + :email => 'foo@bar', + :password => 'ChangeMe', + :admin_user_domain => 'admin_domain', + :admin_project_domain => 'admin_domain', + } + end + it { is_expected.to contain_keystone_domain('admin_domain') } + end end diff --git a/keystone/spec/classes/keystone_spec.rb b/keystone/spec/classes/keystone_spec.rb index 89c4fc55e..497598210 100644 --- a/keystone/spec/classes/keystone_spec.rb +++ b/keystone/spec/classes/keystone_spec.rb @@ -93,6 +93,7 @@ 'rabbit_host' => '127.0.0.1', 'rabbit_password' => 'openstack', 'rabbit_userid' => 'admin', + 'default_domain' => 'other_domain', } httpd_params = {'service_name' => 'httpd'}.merge(default_params) @@ -175,7 +176,7 @@ end it 'should contain correct revoke driver' do - should contain_keystone_config('revoke/driver').with_value(param_hash['revoke_driver']) + is_expected.to contain_keystone_config('revoke/driver').with_value(param_hash['revoke_driver']) end it 'should ensure proper setting of admin_endpoint and public_endpoint' do @@ -211,6 +212,11 @@ is_expected.to contain_keystone_config('DEFAULT/public_workers').with_value('2') end end + + if param_hash['default_domain'] + it { is_expected.to contain_keystone_domain(param_hash['default_domain']).with(:is_default => true) } + it { is_expected.to contain_anchor('default_domain_created') } + end end [default_params, override_params].each do |param_hash| @@ -229,6 +235,8 @@ 'hasrestart' => true ) } + it { is_expected.to contain_anchor('keystone_started') } + end end @@ -245,11 +253,11 @@ it do expect { - should contain_service(platform_parameters[:service_name]).with('ensure' => 'running') + is_expected.to contain_service(platform_parameters[:service_name]).with('ensure' => 'running') }.to raise_error(RSpec::Expectations::ExpectationNotMetError, /expected that the catalogue would contain Service\[#{platform_parameters[:service_name]}\]/) end - it { should contain_class('keystone::service').with( + it { is_expected.to contain_class('keystone::service').with( 'ensure' => 'stopped', 'service_name' => platform_parameters[:service_name], 'enable' => false, @@ -276,6 +284,7 @@ 'hasstatus' => true, 'hasrestart' => true ) } + it { is_expected.to contain_anchor('keystone_started') } end describe 'when configuring signing token provider' do @@ -845,6 +854,51 @@ end end + shared_examples_for "when configuring default domain" do + describe 'with default config' do + let :params do + default_params + end + it { is_expected.to_not contain_exec('restart_keystone') } + end + describe 'with default domain and eventlet service is managed and enabled' do + let :params do + default_params.merge({ + 'default_domain'=> 'test', + }) + end + it { is_expected.to contain_exec('restart_keystone').with( + 'command' => "service #{platform_parameters[:service_name]} restart", + ) } + it { is_expected.to contain_anchor('default_domain_created') } + end + describe 'with default domain and wsgi service is managed and enabled' do + let :pre_condition do + 'include ::apache' + end + let :params do + default_params.merge({ + 'default_domain'=> 'test', + 'service_name' => 'httpd', + }) + end + it { is_expected.to contain_exec('restart_keystone').with( + 'command' => "service #{platform_parameters[:httpd_service_name]} restart", + ) } + it { is_expected.to contain_anchor('default_domain_created') } + end + describe 'with default domain and service is not managed' do + let :params do + default_params.merge({ + 'default_domain' => 'test', + 'manage_service' => false, + }) + end + it { is_expected.to_not contain_exec('restart_keystone') } + it { is_expected.to contain_anchor('default_domain_created') } + end + end + context 'on RedHat platforms' do let :facts do global_facts.merge({ @@ -855,11 +909,13 @@ let :platform_parameters do { - :service_name => 'openstack-keystone' + :service_name => 'openstack-keystone', + :httpd_service_name => 'httpd', } end it_configures 'when using default class parameters for httpd' + it_configures 'when configuring default domain' end context 'on Debian platforms' do @@ -873,10 +929,12 @@ let :platform_parameters do { - :service_name => 'keystone' + :service_name => 'keystone', + :httpd_service_name => 'apache2', } end it_configures 'when using default class parameters for httpd' + it_configures 'when configuring default domain' end end diff --git a/keystone/spec/defines/keystone_resource_authtoken_spec.rb b/keystone/spec/defines/keystone_resource_authtoken_spec.rb new file mode 100644 index 000000000..06894070b --- /dev/null +++ b/keystone/spec/defines/keystone_resource_authtoken_spec.rb @@ -0,0 +1,198 @@ +require 'spec_helper' + +describe 'keystone::resource::authtoken' do + + let (:title) { 'keystone_config' } + + let :required_params do + { :username => 'keystone', + :password => 'secret', + :auth_url => 'http://127.0.0.1:35357/', + :project_name => 'services' } + end + + shared_examples 'shared examples' do + + context 'with only required parameters' do + let :params do + required_params + end + + it { is_expected.to contain_keystone_config('keystone_authtoken/username').with( + :value => 'keystone', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/user_id').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/password').with( + :value => 'secret', + :secret => true, + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/auth_plugin').with( + :value => 'password', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/auth_url').with( + :value => 'http://127.0.0.1:35357/', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/project_name').with( + :value => 'services', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/project_id').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/user_domain_name').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/project_domain_name').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/user_domain_id').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/project_domain_id').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/domain_name').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/domain_id').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/trust_id').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/cacert').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/cert').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/key').with( + :ensure => 'absent', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/insecure').with( + :value => 'false', + )} + + end + + context 'when omitting a required parameter password' do + let :params do + required_params.delete(:password) + end + it { expect { is_expected.to raise_error(Puppet::Error) } } + end + + context 'when specifying auth_url' do + let :params do + required_params.merge({:auth_url => 'https://host:11111/v3/'}) + end + it { is_expected.to contain_keystone_config('keystone_authtoken/auth_url').with( + :value => 'https://host:11111/v3/', + )} + + end + + context 'when specifying project and scope_domain' do + let :params do + required_params.merge({:domain_name => 'domain'}) + end + it { expect { is_expected.to raise_error(Puppet::Error, 'Cannot specify both a project (project_name or project_id) and a domain (domain_name or domain_id)') } } + end + + context 'when specifying neither project nor domain' do + let :params do + required_params.delete(:project_name) + end + it { expect { is_expected.to raise_error(Puppet::Error, 'Must specify either a project (project_name or project_id, for a project scoped token) or a domain (domain_name or domain_id, for a domain scoped token)') } } + end + + context 'when specifying domain in name' do + let :params do + required_params.merge({ + :username => 'keystone::userdomain', + :project_name => 'services::projdomain', + :default_domain_name => 'shouldnotuse' + }) + end + it { is_expected.to contain_keystone_config('keystone_authtoken/user_domain_name').with( + :value => 'userdomain', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/project_domain_name').with( + :value => 'projdomain', + )} + + end + + context 'when specifying domain in parameters' do + let :params do + required_params.merge({ + :username => 'keystone::userdomain', + :user_domain_name => 'realuserdomain', + :project_name => 'services::projdomain', + :project_domain_name => 'realprojectdomain', + :default_domain_name => 'shouldnotuse' + }) + end + it { is_expected.to contain_keystone_config('keystone_authtoken/user_domain_name').with( + :value => 'realuserdomain', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/project_domain_name').with( + :value => 'realprojectdomain', + )} + + end + + context 'when specifying only default domain' do + let :params do + required_params.merge({ + :default_domain_name => 'defaultdomain' + }) + end + it { is_expected.to contain_keystone_config('keystone_authtoken/user_domain_name').with( + :value => 'defaultdomain', + )} + + it { is_expected.to contain_keystone_config('keystone_authtoken/project_domain_name').with( + :value => 'defaultdomain', + )} + + end + + end + + context 'on a Debian osfamily' do + let :facts do + { :osfamily => "Debian" } + end + + include_examples 'shared examples' + end + + context 'on a RedHat osfamily' do + let :facts do + { :osfamily => 'RedHat' } + end + + include_examples 'shared examples' + end +end diff --git a/keystone/spec/defines/keystone_resource_service_identity_spec.rb b/keystone/spec/defines/keystone_resource_service_identity_spec.rb index 18979635e..63ef98ad9 100644 --- a/keystone/spec/defines/keystone_resource_service_identity_spec.rb +++ b/keystone/spec/defines/keystone_resource_service_identity_spec.rb @@ -69,6 +69,69 @@ it { expect { is_expected.to raise_error(Puppet::Error) } } end + context 'with user domain' do + let :params do + required_params.merge({:user_domain => 'userdomain'}) + end + it { is_expected.to contain_keystone_domain('userdomain').with( + :ensure => 'present', + )} + it { is_expected.to contain_keystone_user(title).with( + :ensure => 'present', + :password => 'secrete', + :email => 'neutron@localhost', + :tenant => 'services', + :domain => 'userdomain', + )} + it { is_expected.to contain_keystone_user_role("#{title}@services").with( + :ensure => 'present', + :roles => ['admin'], + )} + end + context 'with user and project domain' do + let :params do + required_params.merge({ + :user_domain => 'userdomain', + :project_domain => 'projdomain', + }) + end + it { is_expected.to contain_keystone_user(title).with( + :ensure => 'present', + :password => 'secrete', + :email => 'neutron@localhost', + :tenant => 'services', + :domain => 'userdomain', + )} + it { is_expected.to contain_keystone_domain('userdomain').with( + :ensure => 'present', + )} + it { is_expected.to contain_keystone_user_role("#{title}@services").with( + :ensure => 'present', + :roles => ['admin'], + )} + end + context 'with default domain only' do + let :params do + required_params.merge({ + :default_domain => 'defaultdomain', + }) + end + it { is_expected.to contain_keystone_user(title).with( + :ensure => 'present', + :password => 'secrete', + :email => 'neutron@localhost', + :tenant => 'services', + :domain => 'defaultdomain', + )} + it { is_expected.to contain_keystone_domain('defaultdomain').with( + :ensure => 'present', + )} + it { is_expected.to contain_keystone_user_role("#{title}@services").with( + :ensure => 'present', + :roles => ['admin'], + )} + end + end context 'on a Debian osfamily' do diff --git a/keystone/spec/spec_helper_acceptance.rb b/keystone/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/keystone/spec/spec_helper_acceptance.rb +++ b/keystone/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/keystone/spec/unit/provider/keystone_paste_ini/ini_setting_spec.rb b/keystone/spec/unit/provider/keystone_paste_ini/ini_setting_spec.rb index 2eff5d63f..56379487f 100644 --- a/keystone/spec/unit/provider/keystone_paste_ini/ini_setting_spec.rb +++ b/keystone/spec/unit/provider/keystone_paste_ini/ini_setting_spec.rb @@ -23,7 +23,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/keystone/spec/unit/provider/keystone_user/openstack_spec.rb b/keystone/spec/unit/provider/keystone_user/openstack_spec.rb index 3f545d0cf..d7de008c7 100644 --- a/keystone/spec/unit/provider/keystone_user/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_user/openstack_spec.rb @@ -1,9 +1,14 @@ require 'puppet' require 'spec_helper' require 'puppet/provider/keystone_user/openstack' +require 'puppet/provider/openstack' provider_class = Puppet::Type.type(:keystone_user).provider(:openstack) +def project_class + Puppet::Type.type(:keystone_tenant).provider(:openstack) +end + describe provider_class do shared_examples 'authenticated with environment variables' do @@ -21,6 +26,7 @@ :password => 'foo', :tenant => 'foo', :email => 'foo@example.com', + :domain => 'foo_domain', } end @@ -32,22 +38,95 @@ provider_class.new(resource) end + def before_hook(delete, missing, noproject, user_cached) + provider.class.expects(:openstack).once + .with('domain', 'list', '--quiet', '--format', 'csv', []) + .returns('"ID","Name","Enabled","Description" +"foo_domain_id","foo_domain",True,"foo domain" +"bar_domain_id","bar_domain",True,"bar domain" +"another_domain_id","another_domain",True,"another domain" +"disabled_domain_id","disabled_domain",False,"disabled domain" +') + if user_cached + return # using cached user, so no user list + end + if noproject + project = '' + else + project = 'foo' + end + # delete will call the search again and should not return the deleted user + foo_returns = ['"ID","Name","Project Id","Domain","Description","Email","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo",' + project + ',"foo_domain_id","foo description","foo@example.com",True +"2cb05cfed7c24279be884ba4f6520262","foo",' + project + ',"bar_domain_id","foo description","foo@example.com",True +"3cb05cfed7c24279be884ba4f6520262","foo",' + project + ',"another_domain_id","foo description","foo@example.com",True +'] + nn = 1 + if delete + nn = 2 + foo_returns << '' + end + if missing + foo_returns = [''] + end + provider.class.expects(:openstack).times(nn) + .with('user', 'list', '--quiet', '--format', 'csv', ['--long']) + .returns(*foo_returns) + end + + before :each, :default => true do + before_hook(false, false, false, false) + end + before :each, :delete => true do + before_hook(true, false, false, false) + end + before :each, :missing => true do + before_hook(false, true, false, false) + end + before :each, :noproject => true do + before_hook(false, false, true, false) + end + before :each, :default_https => true do + before_hook(false, false, false, false) + end + before :each, :user_cached => true do + before_hook(false, false, false, true) + end + before :each, :nohooks => true do + # do nothing + end + describe 'when managing a user' do it_behaves_like 'authenticated with environment variables' do describe '#create' do it 'creates a user' do - provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', '--long') - .returns('"ID","Name","Project","Email","Enabled" -"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True + project_class.expects(:openstack).once + .with('domain', 'list', '--quiet', '--format', 'csv', []) + .returns('"ID","Name","Enabled","Description" +"foo_domain_id","foo_domain",True,"foo domain" +"bar_domain_id","bar_domain",True,"bar domain" +"another_domain_id","another_domain",True,"another domain" +"disabled_domain_id","disabled_domain",False,"disabled domain" +') + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","foo","bar_domain_id","foo",True +') + provider.class.expects(:openstack) + .with('role', 'show', '--format', 'shell', '_member_') + .returns(' +name="_member_" ') - provider.class.stubs(:openstack) - .with('user', 'create', '--format', 'shell', ['foo', '--enable', '--password', 'foo', '--project', 'foo', '--email', 'foo@example.com']) + provider.class.expects(:openstack) + .with('role', 'add', ['_member_', '--project', '2cb05cfed7c24279be884ba4f6520262', '--user', '12b23f07d4a3448d8189521ab09610b0']) + provider.class.expects(:openstack) + .with('user', 'create', '--format', 'shell', ['foo', '--enable', '--password', 'foo', '--email', 'foo@example.com', '--domain', 'foo_domain']) .returns('email="foo@example.com" enabled="True" id="12b23f07d4a3448d8189521ab09610b0" name="foo" -project_id="5e2001b2248540f191ff22627dc0c2d7" username="foo" ') provider.create @@ -57,11 +136,9 @@ describe '#destroy' do it 'destroys a user' do - provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', '--long') - .returns('"ID","Name","Project","Email","Enabled"') - provider.class.stubs(:openstack) - .with('user', 'delete', []) + provider.instance_variable_get('@property_hash')[:id] = 'my-user-id' + provider.class.expects(:openstack) + .with('user', 'delete', 'my-user-id') provider.destroy expect(provider.exists?).to be_falsey end @@ -71,9 +148,6 @@ describe '#exists' do context 'when user does not exist' do subject(:response) do - provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', '--long') - .returns('"ID","Name","Project","Email","Enabled"') response = provider.exists? end @@ -81,134 +155,133 @@ end end - describe '#instances' do + describe '#instances', :default => true do it 'finds every user' do - provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', '--long') - .returns('"ID","Name","Project","Email","Enabled" -"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True -') - instances = Puppet::Type::Keystone_user::ProviderOpenstack.instances - expect(instances.count).to eq(1) + instances = provider.class.instances + expect(instances.count).to eq(3) + expect(instances[0].name).to eq('foo') + expect(instances[0].domain).to eq('another_domain') + expect(instances[1].name).to eq('foo::foo_domain') + expect(instances[2].name).to eq('foo::bar_domain') end end describe '#tenant' do - it 'gets the tenant with default backend' do - provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', '--long') - .returns('"ID","Name","Project","Email","Enabled" -"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo@example.com",True + it 'gets the tenant with default backend', :nohooks => true do + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True ') - provider.class.stubs(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', ['foo', '--project', 'foo']) - .returns('"ID","Name","Project","User" -"9fe2ff9ee4384b1894a90878d3e92bab","_member_","foo","foo" + provider.class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', ['--user', '1cb05cfed7c24279be884ba4f6520262', '--long']) + .returns('"ID","Name","Domain ID","Description","Enabled" +"foo_project_id1","foo","foo_domain_id","",True ') + provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' tenant = provider.tenant expect(tenant).to eq('foo') end - it 'gets the tenant with LDAP backend' do - provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', '--long') - .returns('"ID","Name","Project","Email","Enabled" -"1cb05cfed7c24279be884ba4f6520262","foo","","foo@example.com",True + it 'gets the tenant with LDAP backend', :nohooks => true do + provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True ') provider.class.expects(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', ['foo', '--project', 'foo']) - .returns('"ID","Name","Project","User" -"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo" + .with('project', 'list', '--quiet', '--format', 'csv', ['--user', '1cb05cfed7c24279be884ba4f6520262', '--long']) + .returns('"ID","Name","Domain ID","Description","Enabled" +"foo_project_id1","foo","foo_domain_id","",True +"bar_project_id2","bar","bar_domain_id","",True +"foo_project_id2","foo","another_domain_id","",True ') tenant = provider.tenant expect(tenant).to eq('foo') end end - describe '#tenant=' do - context 'when using default backend' do + context 'when using default backend', :nohooks => true do it 'sets the tenant' do + provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' + provider.instance_variable_get('@property_hash')[:domain] = 'foo_domain' + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True +') provider.class.expects(:openstack) - .with('user', 'set', ['foo', '--project', 'bar']) + .with('role', 'show', '--format', 'shell', '_member_') + .returns('name="_member_"') provider.class.expects(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', ['foo', '--project', 'bar']) - .returns('"ID","Name","Project","User" -"9fe2ff9ee4384b1894a90878d3e92bab","_member_","bar","foo" -') + .with('role', 'add', ['_member_', '--project', '2cb05cfed7c24279be884ba4f6520262', '--user', '1cb05cfed7c24279be884ba4f6520262']) provider.tenant=('bar') end end - - context 'when using LDAP read-write backend' do + context 'when using LDAP read-write backend', :nohooks => true do it 'sets the tenant when _member_ role exists' do - provider.class.expects(:openstack) - .with('user', 'set', ['foo', '--project', 'bar']) - provider.class.expects(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', ['foo', '--project', 'bar']) - .returns('') - provider.class.expects(:openstack) - .with('role', 'show', '--format', 'shell', ['_member_']) - .returns('id="9fe2ff9ee4384b1894a90878d3e92bab" -name="_member_" + provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' + provider.instance_variable_get('@property_hash')[:domain] = 'foo_domain' + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True ') provider.class.expects(:openstack) - .with('role', 'add', ['_member_', '--project', 'bar', '--user', 'foo']) + .with('role', 'show', '--format', 'shell', '_member_') + .returns('name="_member_"') + provider.class.expects(:openstack) + .with('role', 'add', ['_member_', '--project', '2cb05cfed7c24279be884ba4f6520262', '--user', '1cb05cfed7c24279be884ba4f6520262']) provider.tenant=('bar') end it 'sets the tenant when _member_ role does not exist' do + provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' + provider.instance_variable_get('@property_hash')[:domain] = 'foo_domain' + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True +') provider.class.expects(:openstack) - .with('user', 'set', ['foo', '--project', 'bar']) - provider.class.expects(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', ['foo', '--project', 'bar']) - .returns('') - provider.class.expects(:openstack) - .with('role', 'show', '--format', 'shell', ['_member_']) + .with('role', 'show', '--format', 'shell', '_member_') .raises(Puppet::ExecutionFailure, 'no such role _member_') provider.class.expects(:openstack) - .with('role', 'create', '--format', 'shell', ['_member_']) + .with('role', 'create', '--format', 'shell', '_member_') .returns('name="_member_"') provider.class.expects(:openstack) - .with('role', 'add', ['_member_', '--project', 'bar', '--user', 'foo']) - .returns('id="8wr2ff9ee4384b1894a90878d3e92bab" -name="_member_" -') + .with('role', 'add', ['_member_', '--project', '2cb05cfed7c24279be884ba4f6520262', '--user', '1cb05cfed7c24279be884ba4f6520262']) provider.tenant=('bar') end end - -# This doesn't make sense, need to clarify what's happening with LDAP mock -=begin - context 'when using LDAP read-only backend' do + context 'when using LDAP read-only backend', :nohooks => true do it 'sets the tenant when _member_ role exists' do - provider.class.expects(:openstack) - .with('user', 'set', [['foo', '--project', 'bar']]) - .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']]) - .returns('') - provider.class.expects(:openstack) - .with('role', 'show', '--format', 'shell', [['_member_']]) - .returns('id="9fe2ff9ee4384b1894a90878d3e92bab" -name="_member_" + provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' + provider.instance_variable_get('@property_hash')[:domain] = 'foo_domain' + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True ') provider.class.expects(:openstack) - .with('role', 'add', [['_member_', '--project', 'bar', '--user', 'foo']]) - provider.tenant=('bar') - end - - it 'sets the tenant and gets an unexpected exception message' do + .with('role', 'show', '--format', 'shell', '_member_') + .returns('name="_member_"') provider.class.expects(:openstack) - .with('user', 'set', [['foo', '--project', 'bar']]) - .raises(Puppet::ExecutionFailure, 'unknown error message') - expect{ provider.tenant=('bar') }.to raise_error(Puppet::ExecutionFailure, /unknown error message/) + .with('role', 'add', ['_member_', '--project', '2cb05cfed7c24279be884ba4f6520262', '--user', '1cb05cfed7c24279be884ba4f6520262']) + provider.tenant=('bar') end end -=end end end end - describe "#password" do + describe "#password", :nohooks => true do let(:user_attrs) do { :name => 'foo', @@ -217,6 +290,7 @@ :password => 'foo', :tenant => 'foo', :email => 'foo@example.com', + :domain => 'foo_domain', } end @@ -229,12 +303,26 @@ end shared_examples 'with auth-url environment variable' do - ENV['OS_AUTH_URL'] = 'http://localhost:5000' + ENV['OS_AUTH_URL'] = 'http://127.0.0.1:5000' end it_behaves_like 'with auth-url environment variable' do it 'checks the password' do - Puppet::Provider::Openstack.stubs(:openstack) + provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' + mockcreds = {} + Puppet::Provider::Openstack::CredentialsV3.expects(:new).returns(mockcreds) + mockcreds.expects(:auth_url=).with('http://127.0.0.1:5000') + mockcreds.expects(:password=).with('foo') + mockcreds.expects(:username=).with('foo') + mockcreds.expects(:user_id=).with('1cb05cfed7c24279be884ba4f6520262') + mockcreds.expects(:project_id=).with('project-id-1') + mockcreds.expects(:to_env).returns(mockcreds) + Puppet::Provider::Openstack.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', ['--user', '1cb05cfed7c24279be884ba4f6520262', '--long']) + .returns('"ID","Name","Domain ID","Description","Enabled" +"project-id-1","foo","foo_domain_id","foo",True +') + Puppet::Provider::Openstack.expects(:openstack) .with('token', 'issue', ['--format', 'value']) .returns('2015-05-14T04:06:05Z e664a386befa4a30878dcef20e79f167 @@ -246,13 +334,48 @@ end it 'fails the password check' do - Puppet::Provider::Openstack.stubs(:openstack) + provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' + Puppet::Provider::Openstack.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', ['--user', '1cb05cfed7c24279be884ba4f6520262', '--long']) + .returns('"ID","Name","Domain ID","Description","Enabled" +"project-id-1","foo","foo_domain_id","foo",True +') + Puppet::Provider::Openstack.expects(:openstack) .with('token', 'issue', ['--format', 'value']) .raises(Puppet::ExecutionFailure, 'HTTP 401 invalid authentication') password = provider.password expect(password).to eq(nil) end + + it 'checks the password with domain scoped token' do + provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' + provider.instance_variable_get('@property_hash')[:domain] = 'foo_domain' + mockcreds = {} + Puppet::Provider::Openstack::CredentialsV3.expects(:new).returns(mockcreds) + mockcreds.expects(:auth_url=).with('http://127.0.0.1:5000') + mockcreds.expects(:password=).with('foo') + mockcreds.expects(:username=).with('foo') + mockcreds.expects(:user_id=).with('1cb05cfed7c24279be884ba4f6520262') + mockcreds.expects(:domain_name=).with('foo_domain') + mockcreds.expects(:to_env).returns(mockcreds) + Puppet::Provider::Openstack.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', ['--user', '1cb05cfed7c24279be884ba4f6520262', '--long']) + .returns('"ID","Name","Domain ID","Description","Enabled" +') + Puppet::Provider::Openstack.expects(:openstack) + .with('token', 'issue', ['--format', 'value']) + .returns('2015-05-14T04:06:05Z +e664a386befa4a30878dcef20e79f167 +8dce2ae9ecd34c199d2877bf319a3d06 +ac43ec53d5a74a0b9f51523ae41a29f0 +') + password = provider.password + expect(password).to eq('foo') + end end + end + + describe 'when updating a user with unmanaged password', :nohooks => true do describe 'when updating a user with unmanaged password' do @@ -265,13 +388,239 @@ :replace_password => 'False', :tenant => 'foo', :email => 'foo@example.com', + :domain => 'foo_domain', } 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 + it_behaves_like 'authenticated with environment variables' do + describe 'v3 domains with no domain in resource', :nohooks => true do + let(:user_attrs) do + { + :name => 'foo', + :ensure => 'present', + :enabled => 'True', + :password => 'foo', + :tenant => 'foo', + :email => 'foo@example.com', + } + end + + it 'adds default domain to commands' do + provider_class.class_exec { + @default_domain_id = nil + } + mock = { + 'identity' => {'default_domain_id' => 'foo_domain_id'} + } + Puppet::Util::IniConfig::File.expects(:new).returns(mock) + File.expects(:exists?).with('/etc/keystone/keystone.conf').returns(true) + mock.expects(:read).with('/etc/keystone/keystone.conf') + provider.class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', ['--user', '1cb05cfed7c24279be884ba4f6520262', '--long']) + .returns('"ID","Name" +') + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True +') + provider.class.expects(:openstack) + .with('role', 'show', '--format', 'shell', '_member_') + .returns(' +name="_member_" +') + provider.class.expects(:openstack) + .with('role', 'add', ['_member_', '--project', '1cb05cfed7c24279be884ba4f6520262', '--user', '1cb05cfed7c24279be884ba4f6520262']) + provider.class.expects(:openstack) + .with('user', 'create', '--format', 'shell', ['foo', '--enable', '--password', 'foo', '--email', 'foo@example.com', '--domain', 'foo_domain']) + .returns('email="foo@example.com" +enabled="True" +id="1cb05cfed7c24279be884ba4f6520262" +name="foo" +username="foo" +') + provider.create + expect(provider.exists?).to be_truthy + expect(provider.id).to eq("1cb05cfed7c24279be884ba4f6520262") + end + end + + describe 'v3 domains with domain in resource' do + let(:user_attrs) do + { + :name => 'foo', + :ensure => 'present', + :enabled => 'True', + :password => 'foo', + :tenant => 'foo', + :email => 'foo@example.com', + :domain => 'bar_domain', + } + end + + it 'uses given domain in commands' do + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True +') + provider.class.expects(:openstack) + .with('role', 'show', '--format', 'shell', '_member_') + .returns(' +name="_member_" +') + provider.class.expects(:openstack) + .with('role', 'add', ['_member_', '--project', '1cb05cfed7c24279be884ba4f6520262', '--user', '2cb05cfed7c24279be884ba4f6520262']) + provider.class.expects(:openstack) + .with('user', 'create', '--format', 'shell', ['foo', '--enable', '--password', 'foo', '--email', 'foo@example.com', '--domain', 'bar_domain']) + .returns('email="foo@example.com" +enabled="True" +id="2cb05cfed7c24279be884ba4f6520262" +name="foo" +username="foo" +') + provider.create + expect(provider.exists?).to be_truthy + expect(provider.id).to eq("2cb05cfed7c24279be884ba4f6520262") + end + end + + describe 'v3 domains with domain in name/title' do + let(:user_attrs) do + { + :name => 'foo::bar_domain', + :ensure => 'present', + :enabled => 'True', + :password => 'foo', + :tenant => 'foo', + :email => 'foo@example.com', + } + end + + it 'uses given domain in commands' do + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True +') + provider.class.expects(:openstack) + .with('role', 'show', '--format', 'shell', '_member_') + .returns(' +name="_member_" +') + provider.class.expects(:openstack) + .with('role', 'add', ['_member_', '--project', '1cb05cfed7c24279be884ba4f6520262', '--user', '2cb05cfed7c24279be884ba4f6520262']) + provider.class.expects(:openstack) + .with('user', 'create', '--format', 'shell', ['foo', '--enable', '--password', 'foo', '--email', 'foo@example.com', '--domain', 'bar_domain']) + .returns('email="foo@example.com" +enabled="True" +id="2cb05cfed7c24279be884ba4f6520262" +name="foo" +username="foo" +') + provider.create + expect(provider.exists?).to be_truthy + expect(provider.id).to eq("2cb05cfed7c24279be884ba4f6520262") + end + end + + describe 'v3 domains with domain in name/title and in resource' do + let(:user_attrs) do + { + :name => 'foo::bar_domain', + :ensure => 'present', + :enabled => 'True', + :password => 'foo', + :tenant => 'foo', + :email => 'foo@example.com', + :domain => 'foo_domain', + } + end + + it 'uses the resource domain in commands' do + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True +') + provider.class.expects(:openstack) + .with('role', 'show', '--format', 'shell', '_member_') + .returns(' +name="_member_" +') + provider.class.expects(:openstack) + .with('role', 'add', ['_member_', '--project', '1cb05cfed7c24279be884ba4f6520262', '--user', '2cb05cfed7c24279be884ba4f6520262']) + provider.class.expects(:openstack) + .with('user', 'create', '--format', 'shell', ['foo', '--enable', '--password', 'foo', '--email', 'foo@example.com', '--domain', 'foo_domain']) + .returns('email="foo@example.com" +enabled="True" +id="2cb05cfed7c24279be884ba4f6520262" +name="foo" +username="foo" +') + provider.create + expect(provider.exists?).to be_truthy + expect(provider.id).to eq("2cb05cfed7c24279be884ba4f6520262") + end + end + + describe 'v3 domains with domain in name/title and in resource and in tenant' do + let(:user_attrs) do + { + :name => 'foo::bar_domain', + :ensure => 'present', + :enabled => 'True', + :password => 'foo', + :tenant => 'foo::foo_domain', + :email => 'foo@example.com', + :domain => 'foo_domain', + } + end + + it 'uses the resource domain in commands' do + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" +"1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True +"2cb05cfed7c24279be884ba4f6520262","foo","bar_domain_id","foo",True +') + provider.class.expects(:openstack) + .with('role', 'show', '--format', 'shell', '_member_') + .returns(' +name="_member_" +') + provider.class.expects(:openstack) + .with('role', 'add', ['_member_', '--project', '1cb05cfed7c24279be884ba4f6520262', '--user', '2cb05cfed7c24279be884ba4f6520262']) + provider.class.expects(:openstack) + .with('user', 'create', '--format', 'shell', ['foo', '--enable', '--password', 'foo', '--email', 'foo@example.com', '--domain', 'foo_domain']) + .returns('email="foo@example.com" +enabled="True" +id="2cb05cfed7c24279be884ba4f6520262" +name="foo" +username="foo" +') + provider.create + expect(provider.exists?).to be_truthy + expect(provider.id).to eq("2cb05cfed7c24279be884ba4f6520262") + 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 2490adc52..7a88d85c3 100644 --- a/keystone/spec/unit/provider/keystone_user_role/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_user_role/openstack_spec.rb @@ -3,9 +3,183 @@ require 'puppet/provider/keystone_user_role/openstack' provider_class = Puppet::Type.type(:keystone_user_role).provider(:openstack) +def user_class + Puppet::Type.type(:keystone_user).provider(:openstack) +end +def project_class + Puppet::Type.type(:keystone_tenant).provider(:openstack) +end describe provider_class do + # assumes Enabled is the last column - no quotes + def list_to_csv(thelist) + if thelist.is_a?(String) + return '' + end + str="" + thelist.each do |rec| + if rec.is_a?(String) + return '' + end + rec.each do |xx| + if xx.equal?(rec.last) + # True/False have no quotes + if xx == 'True' or xx == 'False' + str = str + xx + "\n" + else + str = str + '"' + xx + '"' + "\n" + end + else + str = str + '"' + xx + '",' + end + end + end + str + end + + def before_need_instances + provider.class.expects(:openstack).once + .with('domain', 'list', '--quiet', '--format', 'csv') + .returns('"ID","Name","Enabled","Description" +"foo_domain_id","foo_domain",True,"foo domain" +"bar_domain_id","bar_domain",True,"bar domain" +"another_domain_id","another_domain",True,"another domain" +"disabled_domain_id","disabled_domain",False,"disabled domain" +') + project_list = [['project-id-1','foo','foo_domain_id','foo project in foo domain','True'], + ['project-id-2','foo','bar_domain_id','foo project in bar domain','True'], + ['project-id-3','bar','foo_domain_id','bar project in foo domain','True'], + ['project-id-4','etc','another_domain_id','another project','True']] + + user_list_for_project = { + 'project-id-1' => [['user-id-1','foo@example.com','foo','foo_domain','foo user','foo@foo_domain','True'], + ['user-id-2','bar@example.com','foo','foo_domain','bar user','bar@foo_domain','True']], + 'project-id-2' => [['user-id-3','foo@bar.com','foo','bar_domain','foo user','foo@bar_domain','True'], + ['user-id-4','bar@bar.com','foo','bar_domain','bar user','bar@bar_domain','True']] + } + user_list_for_project.default = '' + + user_list_for_domain = { + 'foo_domain_id' => [['user-id-1','foo@example.com','foo','foo_domain','foo user','foo@foo_domain','True'], + ['user-id-2','bar@example.com','foo','foo_domain','bar user','bar@foo_domain','True']], + 'bar_domain_id' => [['user-id-3','foo@bar.com','foo','bar_domain','foo user','foo@bar_domain','True'], + ['user-id-4','bar@bar.com','foo','bar_domain','bar user','bar@bar_domain','True']] + } + user_list_for_domain.default = '' + + role_list_for_project_user = { + 'project-id-1' => { + 'user-id-1' => [['role-id-1','foo','foo','foo'], + ['role-id-2','bar','foo','foo']] + }, + 'project-id-2' => { + 'user-id-3' => [['role-id-1','foo','foo','foo'], + ['role-id-2','bar','foo','foo']] + } + } + role_list_for_project_user.default = '' + + role_list_for_domain_user = { + 'foo_domain_id' => { + 'user-id-2' => [['role-id-1','foo','foo_domain','foo'], + ['role-id-2','bar','foo_domain','foo']] + }, + 'bar_domain_id' => { + 'user-id-4' => [['role-id-1','foo','bar_domain','foo'], + ['role-id-2','bar','bar_domain','foo']] + } + } + role_list_for_project_user.default = '' + + provider.class.expects(:openstack).once + .with('project', 'list', '--quiet', '--format', 'csv', ['--long']) + .returns('"ID","Name","Domain ID","Description","Enabled"' + "\n" + list_to_csv(project_list)) + project_list.each do |rec| + csvlist = list_to_csv(user_list_for_project[rec[0]]) + provider.class.expects(:openstack) + .with('user', 'list', '--quiet', '--format', 'csv', ['--long', '--project', rec[0]]) + .returns('"ID","Name","Project","Domain","Description","Email","Enabled"' + "\n" + csvlist) + next if csvlist == '' + user_list_for_project[rec[0]].each do |urec| + csvlist = '' + if role_list_for_project_user.has_key?(rec[0]) and + role_list_for_project_user[rec[0]].has_key?(urec[0]) + csvlist = list_to_csv(role_list_for_project_user[rec[0]][urec[0]]) + end + provider.class.expects(:openstack) + .with('role', 'list', '--quiet', '--format', 'csv', ['--project', rec[0], '--user', urec[0]]) + .returns('"ID","Name","Project","User"' + "\n" + csvlist) + end + end + ['foo_domain_id', 'bar_domain_id'].each do |domid| + csvlist = list_to_csv(user_list_for_domain[domid]) + provider.class.expects(:openstack) + .with('user', 'list', '--quiet', '--format', 'csv', ['--long', '--domain', domid]) + .returns('"ID","Name","Project","Domain","Description","Email","Enabled"' + "\n" + csvlist) + next if csvlist == '' + user_list_for_domain[domid].each do |urec| + csvlist = '' + if role_list_for_domain_user.has_key?(domid) and + role_list_for_domain_user[domid].has_key?(urec[0]) + csvlist = list_to_csv(role_list_for_domain_user[domid][urec[0]]) + end + provider.class.expects(:openstack) + .with('role', 'list', '--quiet', '--format', 'csv', ['--domain', domid, '--user', urec[0]]) + .returns('"ID","Name","Domain","User"' + "\n" + csvlist) + end + end + end + + def before_common(destroy, nolist=false, instances=false) + rolelistprojectuser = [['role-id-1','foo','foo','foo'], + ['role-id-2','bar','foo','foo']] + csvlist = list_to_csv(rolelistprojectuser) + rolelistreturns = ['"ID","Name","Project","User"' + "\n" + csvlist] + nn = 1 + if destroy + rolelistreturns = [''] + nn = 1 + end + unless nolist + provider.class.expects(:openstack).times(nn) + .with('role', 'list', '--quiet', '--format', 'csv', ['--project', 'project-id-1', '--user', 'user-id-1']) + .returns(*rolelistreturns) + end + + userhash = {:id => 'user-id-1', :name => 'foo@example.com'} + usermock = user_class.new(userhash) + unless instances + usermock.expects(:exists?).with(any_parameters).returns(true) + user_class.expects(:new).twice.with(any_parameters).returns(usermock) + end + user_class.expects(:instances).with(any_parameters).returns([usermock]) + + projecthash = {:id => 'project-id-1', :name => 'foo'} + projectmock = project_class.new(projecthash) + unless instances + projectmock.expects(:exists?).with(any_parameters).returns(true) + project_class.expects(:new).with(any_parameters).returns(projectmock) + end + project_class.expects(:instances).with(any_parameters).returns([projectmock]) + end + + before :each, :default => true do + before_common(false) + end + + before :each, :destroy => true do + before_common(true) + end + + before :each, :nolist => true do + before_common(true, true) + end + + before :each, :instances => true do + before_common(true, true, true) + end + shared_examples 'authenticated with environment variables' do ENV['OS_USERNAME'] = 'test' ENV['OS_PASSWORD'] = 'abc123' @@ -31,59 +205,83 @@ provider_class.new(resource) end - before(:each) do - provider.class.stubs(:openstack) - .with('user', 'list', '--quiet', '--format', 'csv', ['foo', '--project', 'foo']) - .returns('"ID","Name","Project","User" -"1cb05cfed7c24279be884ba4f6520262","foo","foo","foo" -') - end - - describe '#create' do + describe '#create', :default => true do it 'adds all the roles to the user' do - provider.class.stubs(:openstack) - .with('role', 'add', ['foo', '--project', 'foo', '--user', 'foo']) - provider.class.stubs(:openstack) - .with('role', 'add', ['bar', '--project', 'foo', '--user', 'foo']) - provider.class.stubs(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', ['foo', '--project', 'foo']) - .returns('"ID","Name","Project","User" -"1cb05ed7c24279be884ba4f6520262","foo","foo","foo" -"2cb05ed7c24279be884ba4f6520262","bar","foo","foo" -') + provider.class.expects(:openstack) + .with('role', 'add', ['foo', '--project', 'project-id-1', '--user', 'user-id-1']) + provider.class.expects(:openstack) + .with('role', 'add', ['bar', '--project', 'project-id-1', '--user', 'user-id-1']) provider.create expect(provider.exists?).to be_truthy end end - describe '#destroy' do + describe '#destroy', :destroy => true do it 'removes all the roles from a user' do - provider.class.stubs(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', ['foo', '--project', 'foo']) - .returns('"ID","Name","Project","User"') - provider.class.stubs(:openstack) - .with('role', 'remove', ['foo', '--project', 'foo', '--user', 'foo']) - provider.class.stubs(:openstack) - .with('role', 'remove', ['bar', '--project', 'foo', '--user', 'foo']) + provider.instance_variable_get('@property_hash')[:roles] = ['foo', 'bar'] + provider.class.expects(:openstack) + .with('role', 'remove', ['foo', '--project', 'project-id-1', '--user', 'user-id-1']) + provider.class.expects(:openstack) + .with('role', 'remove', ['bar', '--project', 'project-id-1', '--user', 'user-id-1']) provider.destroy expect(provider.exists?).to be_falsey end end - describe '#exists' do + describe '#exists', :default => true do subject(:response) do - provider.class.stubs(:openstack) - .with('user role', 'list', '--quiet', '--format', 'csv', ['foo', '--project', 'foo']) - .returns('"ID","Name","Project","User" -"1cb05ed7c24279be884ba4f6520262","foo","foo","foo" -') response = provider.exists? end it { is_expected.to be_truthy } end + + describe '#instances', :instances => true do + it 'finds every user role' do + provider.class.expects(:openstack) + .with('role', 'list', '--quiet', '--format', 'csv', []) + .returns('"ID","Name" +"foo-role-id","foo" +"bar-role-id","bar" +') + provider.class.expects(:openstack) + .with('role assignment', 'list', '--quiet', '--format', 'csv', []) + .returns(' +"Role","User","Group","Project","Domain" +"foo-role-id","user-id-1","","project-id-1","" +"bar-role-id","user-id-1","","project-id-1","" +') + instances = provider.class.instances + expect(instances.count).to eq(1) + expect(instances[0].name).to eq('foo@example.com@foo') + expect(instances[0].roles).to eq(['foo', 'bar']) + end + end + + describe '#roles=', :nolist => true do + let(:user_role_attrs) do + { + :name => 'foo@foo', + :ensure => 'present', + :roles => ['one', 'two'], + } + end + + it 'applies the new roles' do + provider.instance_variable_get('@property_hash')[:roles] = ['foo', 'bar'] + provider.class.expects(:openstack) + .with('role', 'remove', ['foo', '--project', 'project-id-1', '--user', 'user-id-1']) + provider.class.expects(:openstack) + .with('role', 'remove', ['bar', '--project', 'project-id-1', '--user', 'user-id-1']) + provider.class.expects(:openstack) + .with('role', 'add', ['one', '--project', 'project-id-1', '--user', 'user-id-1']) + provider.class.expects(:openstack) + .with('role', 'add', ['two', '--project', 'project-id-1', '--user', 'user-id-1']) + provider.roles=(['one', 'two']) + end + end end end end diff --git a/keystone/spec/unit/type/keystone_paste_ini_spec.rb b/keystone/spec/unit/type/keystone_paste_ini_spec.rb index 98f7157b6..2eae98a04 100644 --- a/keystone/spec/unit/type/keystone_paste_ini_spec.rb +++ b/keystone/spec/unit/type/keystone_paste_ini_spec.rb @@ -18,6 +18,6 @@ end it 'should accept a valid value' do @keystone_paste_ini[:value] = 'bar' - @keystone_paste_ini[:value].should == 'bar' + expect(@keystone_paste_ini[:value]).to eq('bar') end end diff --git a/keystone/spec/unit/type/keystone_user_spec.rb b/keystone/spec/unit/type/keystone_user_spec.rb new file mode 100644 index 000000000..789af435f --- /dev/null +++ b/keystone/spec/unit/type/keystone_user_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' +require 'puppet' +require 'puppet/type/keystone_user' + +describe Puppet::Type.type(:keystone_user) do + + before :each do + @project = Puppet::Type.type(:keystone_user).new( + :name => 'foo', + :domain => 'foo-domain', + ) + + @domain = @project.parameter('domain') + end + + it 'should not be in sync for domain changes' do + expect { @domain.insync?('not-the-domain') }.to raise_error(Puppet::Error, /The domain cannot be changed from/) + expect { @domain.insync?(nil) }.to raise_error(Puppet::Error, /The domain cannot be changed from/) + end + + it 'should be in sync if domain is the same' do + expect(@domain.insync?('foo-domain')).to be true + end + +end diff --git a/manila/CHANGELOG.md b/manila/CHANGELOG.md new file mode 100644 index 000000000..5cc2dcc87 --- /dev/null +++ b/manila/CHANGELOG.md @@ -0,0 +1,4 @@ +##2015-07-08 - 6.0.0 +###Summary + +- Initial release of the puppet-manila module diff --git a/manila/README.md b/manila/README.md index b352daf4e..56df97022 100644 --- a/manila/README.md +++ b/manila/README.md @@ -1,7 +1,7 @@ manila ======= -1.0.0 - 2014.2.0 - Juno +6.0.0 - 2015.1.0 - Kilo #### Table of Contents diff --git a/manila/manifests/init.pp b/manila/manifests/init.pp index 9725ca59b..3ab7172c4 100644 --- a/manila/manifests/init.pp +++ b/manila/manifests/init.pp @@ -279,8 +279,8 @@ '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/control_exchange': value => $control_exchange; - 'DEFAULT/amqp_durable_queues': value => $amqp_durable_queues; + 'DEFAULT/control_exchange': value => $control_exchange; + 'oslo_messaging_rabbit/amqp_durable_queues': value => $amqp_durable_queues; } if $rabbit_hosts { diff --git a/manila/metadata.json b/manila/metadata.json index 8e3fbb96a..b930a28b4 100644 --- a/manila/metadata.json +++ b/manila/metadata.json @@ -1,10 +1,10 @@ { - "name": "stackforge-manila", - "version": "5.0.0", - "author": "NetApp and StackForge Contributors", + "name": "openstack-manila", + "version": "6.0.0", + "author": "NetApp and OpenStack Contributors", "summary": "Puppet module for OpenStack Manila", "license": "Apache-2.0", - "source": "git://github.com/stackforge/puppet-manila.git", + "source": "git://github.com/openstack/puppet-manila.git", "project_page": "https://launchpad.net/puppet-manila", "issues_url": "https://bugs.launchpad.net/puppet-manila", "requirements": [ @@ -33,10 +33,10 @@ "dependencies": [ { "name": "dprince/qpid", "version_requirement": ">=1.0.0 <2.0.0" }, { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, - { "name": "stackforge/glance", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, + { "name": "openstack/glance", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/rabbitmq", "version_requirement": ">=2.0.2 <6.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/manila/spec/classes/manila_spec.rb b/manila/spec/classes/manila_spec.rb index 4fe4ca38f..6d2fef593 100644 --- a/manila/spec/classes/manila_spec.rb +++ b/manila/spec/classes/manila_spec.rb @@ -287,7 +287,7 @@ req_params end - it { is_expected.to contain_manila_config('DEFAULT/amqp_durable_queues').with_value(false) } + it { is_expected.to contain_manila_config('oslo_messaging_rabbit/amqp_durable_queues').with_value(false) } end describe 'with amqp_durable_queues enabled' do @@ -297,7 +297,7 @@ }) end - it { is_expected.to contain_manila_config('DEFAULT/amqp_durable_queues').with_value(true) } + it { is_expected.to contain_manila_config('oslo_messaging_rabbit/amqp_durable_queues').with_value(true) } end describe 'with sqlite' do diff --git a/manila/spec/spec_helper_acceptance.rb b/manila/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/manila/spec/spec_helper_acceptance.rb +++ b/manila/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/neutron/CHANGELOG.md b/neutron/CHANGELOG.md index bebeeaafe..95589050f 100644 --- a/neutron/CHANGELOG.md +++ b/neutron/CHANGELOG.md @@ -1,3 +1,51 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a backwards-incompatible major release for OpenStack Kilo. + +####Backwards-incompatible changes +- Remove deprecated parameters +- Drop OVS & LB monolitic plugins +- Use libreswan on fedora +- Move rabbit/kombu settings to oslo_messaging_rabbit section +- FWaaS: update packaging for Debian & Ubuntu +- Don't specify a nova region by default +- Do not create tun and int bridges manually + +####Features +- Puppet 4.x support +- Refactorise Keystone resources management +- Add 'state_path' and 'lock_path' to neutron class +- Add service_name parameter to neutron::server class +- DB: Added postgresql backend using openstacklib helper +- Subscribe neutron db sync to db connection setting +- Ensure DB is provisioned before db-sync +- Add support for identity_uri +- Notify the ovs-agent service if the config changes +- Add portdb and fastpath_flood to n1kv.conf +- Add fwaas package for Kilo in Red Hat platforms +- Add memcache_servers parameter to base neutron class +- Add MidoNet plugin support +- Add PLUMgrid plugin support +- Add OpenContrail plugin support +- Tag all neutron packages +- Allow to configure Nova metadata protocol +- Configure OVS mechanism agent configs in its config file +- Don't manage chmod for /etc/neutron and neutron.conf +- Introduce public_url, internal_url and admin_url +- Allow customization of dhcp_domain setting +- Add manage_service parameter to all agents +- Add ability to specify auth_region + +####Bugfixes +- Fix l3 agent network_device_mtu deprecation +- Set allow_automatic_l3agent_failover in neutron.conf instead of l3_agent.ini +- Fix parsing of network gateway id for router + +####Maintenance +- Acceptance tests with Beaker +- Fix spec tests for RSpec 3.x and Puppet 4.x + ##2015-06-17 - 5.1.0 ###Summary diff --git a/neutron/README.md b/neutron/README.md index 518a59f8c..82c03b422 100644 --- a/neutron/README.md +++ b/neutron/README.md @@ -1,7 +1,7 @@ neutron =================================== -5.1.0 - 2014.2 - Juno +6.0.0 - 2015.1 - Kilo #### Table of Contents diff --git a/neutron/manifests/agents/ml2/ovs.pp b/neutron/manifests/agents/ml2/ovs.pp index 4dc0b6d59..697d55bc8 100644 --- a/neutron/manifests/agents/ml2/ovs.pp +++ b/neutron/manifests/agents/ml2/ovs.pp @@ -118,8 +118,8 @@ fail('Local ip for ovs agent must be set when tunneling is enabled') } - if $enable_distributed_routing and ! $l2_population { - fail('L2 population must be enabled when DVR is enabled') + if $enable_tunneling and $enable_distributed_routing and ! $l2_population { + fail('L2 population must be enabled when DVR and tunneling are enabled') } Package['neutron-ovs-agent'] -> Neutron_agent_ovs<||> diff --git a/neutron/manifests/agents/n1kv_vem.pp b/neutron/manifests/agents/n1kv_vem.pp index 35113a917..1159a0505 100644 --- a/neutron/manifests/agents/n1kv_vem.pp +++ b/neutron/manifests/agents/n1kv_vem.pp @@ -9,6 +9,10 @@ # (required) N1KV VSM(Virtual Supervisor Module) VM's IP. # Defaults to 127.0.0.1 # +# [*n1kv_vsm_ipv6*] +# (required) N1KV VSM(Virtual Supervisor Module) VM's IP. +# Defaults to ::1 +# # [*n1kv_vsm_domainid*] # (required) N1KV VSM DomainID. # Defaults to 1000 @@ -101,6 +105,7 @@ # class neutron::agents::n1kv_vem ( $n1kv_vsm_ip = '127.0.0.1', + $n1kv_vsm_ipv6 = '::1', $n1kv_vsm_domain_id = 1000, $host_mgmt_intf = 'eth1', $uplink_profile = {}, diff --git a/neutron/manifests/plugins/ml2/cisco/nexus1000v.pp b/neutron/manifests/plugins/ml2/cisco/nexus1000v.pp new file mode 100644 index 000000000..0d05fc29b --- /dev/null +++ b/neutron/manifests/plugins/ml2/cisco/nexus1000v.pp @@ -0,0 +1,119 @@ +# +# Configure the Mech Driver for cisco nexus 1000v neutron plugin +# +# === Parameters +# +#[*n1kv_vsm_ip*] +#IP(s) of N1KV VSM(Virtual Supervisor Module) +#$n1kv_vsm_ip = 1.2.3.4, 5.6.7.8 +#Defaults to empty +# +#[*n1kv_vsm_username*] +#Username of N1KV VSM(Virtual Supervisor Module) +#Defaults to empty +# +#[*n1kv_vsm_password*] +#Password of N1KV VSM(Virtual Supervisor Module) +#Defaults to empty +# +#[*default_policy_profile*] +# (Optional) Name of the policy profile to be associated with a port when no +# policy profile is specified during port creates. +# Default value:default-pp +# default_policy_profile = default-pp +# +#[*default_vlan_network_profile*] +# (Optional) Name of the VLAN network profile to be associated with a network. +# Default value:default-vlan-np +# default_vlan_network_profile = default-vlan-np +# +#[*default_vxlan_network_profile*] +# (Optional) Name of the VXLAN network profile to be associated with a network. +# Default value:default-vxlan-np +# default_vxlan_network_profile = default-vxlan-np +# +#[*poll_duration*] +# (Optional) Time in seconds for which the plugin polls the VSM for updates in +# policy profiles. +# Default value: 60 +# poll_duration = 60 +# +#[*http_pool_size*] +# (Optional) Number of threads to use to make HTTP requests to the VSM. +# Default value: 4 +# http_pool_size = 4 +# +#[*http_timeout*] +# (Optional) Timeout duration in seconds for the http request +# Default value: 15 +# http_timeout = 15 +# +#[*sync_interval*] +# (Optional) Time duration in seconds between consecutive neutron-VSM syncs +# Default value: 300, the time between two consecutive syncs is 300 seconds. +# sync_interval = 300 +# +#[*max_vsm_retries*] +# (Optional) Maximum number of retry attempts for VSM REST API. +# Default value: 2, each HTTP request to VSM will be retried twice on +# failures. +# max_vsm_retries = 2 +# +#[*restrict_policy_profiles*] +# (Optional) Specify whether tenants are restricted from accessing all the +# policy profiles. +# Default value: False, indicating all tenants can access all policy profiles. +# restrict_policy_profiles = False +# +#[*enable_vif_type_n1kv*] +# (Optional) If set to True, the VIF type for portbindings is set to N1KV. +# Otherwise the VIF type is set to OVS. +# Default value: False, indicating that the VIF type will be set to OVS. +# enable_vif_type_n1kv = False +# +class neutron::plugins::ml2::cisco::nexus1000v ( + $n1kv_vsm_ip = undef, + $n1kv_vsm_username = undef, + $n1kv_vsm_password = undef, + $default_policy_profile = 'default-pp', + $default_vlan_network_profile = 'default-vlan-np', + $default_vxlan_network_profile = 'default-vxlan-np', + $poll_duration = '60', + $http_pool_size = '4', + $http_timeout = '15', + $sync_interval = '300', + $max_vsm_retries = '2', + $restrict_policy_profiles = 'False', + $enable_vif_type_n1kv = 'False', +) +{ + if($::osfamily != 'Redhat') { + # Current support exists for Redhat family. + # Support for Debian will be added in the future. + fail("Unsupported osfamily ${::osfamily}") + } + + package { 'python-networking-cisco': + require => Package['openstack-neutron'], + tag => 'openstack', + } + + $extension_drivers = 'cisco_n1kv_ext' + neutron_plugin_ml2 { + 'ml2/extension_drivers' : value => $extension_drivers; + 'ml2_cisco_n1kv/n1kv_vsm_ips' : value => $n1kv_vsm_ip; + 'ml2_cisco_n1kv/username' : value => $n1kv_vsm_username; + 'ml2_cisco_n1kv/password' : value => $n1kv_vsm_password; + 'ml2_cisco_n1kv/default_policy_profile' : value => $default_policy_profile; + 'ml2_cisco_n1kv/default_vlan_network_profile' : value => $default_vlan_network_profile; + 'ml2_cisco_n1kv/default_vxlan_network_profile' : value => $default_vxlan_network_profile; + 'ml2_cisco_n1kv/poll_duration' : value => $poll_duration; + 'ml2_cisco_n1kv/http_pool_size' : value => $http_pool_size; + 'ml2_cisco_n1kv/http_timeout' : value => $http_timeout; + 'ml2_cisco_n1kv/sync_interval' : value => $sync_interval; + 'ml2_cisco_n1kv/max_vsm_retries' : value => $max_vsm_retries; + 'ml2_cisco_n1kv/restrict_policy_profiles' : value => $restrict_policy_profiles; + 'ml2_cisco_n1kv/enable_vif_type_n1kv' : value => $enable_vif_type_n1kv; + } +} + diff --git a/neutron/manifests/plugins/ml2/mech_driver.pp b/neutron/manifests/plugins/ml2/mech_driver.pp index f2963cf7e..d452cbf4c 100644 --- a/neutron/manifests/plugins/ml2/mech_driver.pp +++ b/neutron/manifests/plugins/ml2/mech_driver.pp @@ -24,8 +24,8 @@ ){ if ($name == 'sriovnicswitch') { neutron_plugin_ml2 { - 'ml2_sriov/supported_pci_vendor_dev': value => join($supported_pci_vendor_devs, ','); - 'ml2_sriov/agent_required': value => $sriov_agent_required; + 'ml2_sriov/supported_pci_vendor_devs': value => join($supported_pci_vendor_devs, ','); + 'ml2_sriov/agent_required': value => $sriov_agent_required; } } } diff --git a/neutron/metadata.json b/neutron/metadata.json index 4b06568b8..37973491d 100644 --- a/neutron/metadata.json +++ b/neutron/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-neutron", - "version": "5.1.0", + "name": "openstack-neutron", + "version": "6.0.0", "author": "OpenStack Contributors", "summary": "Puppet module for OpenStack Neutron", "license": "Apache-2.0", @@ -32,11 +32,11 @@ "description": "Installs and configures OpenStack Neutron (Networking).", "dependencies": [ { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, - { "name": "stackforge/nova", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, + { "name": "openstack/nova", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, - { "name": "stackforge/vswitch", "version_requirement": ">=1.0.0 <2.0.0" }, + { "name": "openstack/vswitch", "version_requirement": ">=2.0.0 <3.0.0" }, { "name": "duritong/sysctl", "version_requirement": ">=0.0.1 <1.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/neutron/spec/classes/neutron_agents_ml2_ovs_spec.rb b/neutron/spec/classes/neutron_agents_ml2_ovs_spec.rb index 48c34b567..d1dbbcf1c 100644 --- a/neutron/spec/classes/neutron_agents_ml2_ovs_spec.rb +++ b/neutron/spec/classes/neutron_agents_ml2_ovs_spec.rb @@ -164,13 +164,28 @@ end end - context 'when l2 population is disabled and DVR enabled' do + context 'when l2 population is disabled and DVR and tunneling enabled' do before :each do params.merge!(:enable_distributed_routing => true, - :l2_population => false ) + :l2_population => false, + :enable_tunneling => true, + :local_ip => '127.0.0.1' ) end - it_raises 'a Puppet::Error', /L2 population must be enabled when DVR is enabled/ + it_raises 'a Puppet::Error', /L2 population must be enabled when DVR and tunneling are enabled/ + end + + context 'when DVR is enabled and l2 population and tunneling are disabled' do + before :each do + params.merge!(:enable_distributed_routing => true, + :l2_population => false, + :enable_tunneling => false ) + end + + it 'should enable DVR without L2 population' do + is_expected.to contain_neutron_agent_ovs('agent/enable_distributed_routing').with_value(true) + is_expected.to contain_neutron_agent_ovs('agent/l2_population').with_value(false) + end end end end diff --git a/neutron/spec/classes/neutron_agents_n1kv_vem_spec.rb b/neutron/spec/classes/neutron_agents_n1kv_vem_spec.rb index 484b63638..1e68817ae 100644 --- a/neutron/spec/classes/neutron_agents_n1kv_vem_spec.rb +++ b/neutron/spec/classes/neutron_agents_n1kv_vem_spec.rb @@ -67,6 +67,7 @@ let :params do { :n1kv_vsm_ip => '9.0.0.1', + :n1kv_vsm_ipv6 => '::3', :n1kv_vsm_domain_id => 900, :host_mgmt_intf => 'eth9', :portdb => 'ovs', @@ -76,6 +77,8 @@ it do is_expected.to contain_file('/etc/n1kv/n1kv.conf') \ .with_content(/^l3control-ipaddr 9.0.0.1/) + is_expected.to contain_file('/etc/n1kv/n1kv.conf') \ + .with_content(/^l3control-ipv6addr ::3/) is_expected.to contain_file('/etc/n1kv/n1kv.conf') \ .with_content(/^switch-domain 900/) is_expected.to contain_file('/etc/n1kv/n1kv.conf') \ @@ -93,6 +96,30 @@ end end + context 'verify n1kv.conf svs-mode with default IPv6 address' do + let :params do + { + :n1kv_vsm_ipv6 => '::1' + } + end + it do + is_expected.to contain_file('/etc/n1kv/n1kv.conf') \ + .without_content(/^svs-mode V6/) + end + end + + context 'verify n1kv.conf svs-mode with non-default IPv6 address' do + let :params do + { + :n1kv_vsm_ipv6 => '::3' + } + end + it do + is_expected.to contain_file('/etc/n1kv/n1kv.conf') \ + .with_content(/^svs-mode V6/) + end + end + context 'verify node_type' do let :params do { diff --git a/neutron/spec/classes/neutron_plugins_cisco_ml2_spec.rb b/neutron/spec/classes/neutron_plugins_cisco_ml2_spec.rb index 73ddcf2e2..5fdbd10d5 100644 --- a/neutron/spec/classes/neutron_plugins_cisco_ml2_spec.rb +++ b/neutron/spec/classes/neutron_plugins_cisco_ml2_spec.rb @@ -62,3 +62,56 @@ class { 'neutron': end end + + +describe 'neutron::plugins::ml2::cisco::nexus1000v' do + + context 'verify default n1kv params in plugin.ini' do + + let :facts do + { :operatingsystem => 'RedHat', + :operatingsystemrelease => '7', + :osfamily => 'RedHat' + } + end + + let :params do + { + :n1kv_vsm_ip => '9.0.0.1', + :n1kv_vsm_username => 'user1', + :n1kv_vsm_password => 'pasSw0rd', + :default_policy_profile => 'test-pp', + :default_vlan_network_profile => 'test-vlan-np', + :default_vxlan_network_profile => 'test-vxlan-np', + :poll_duration => '120', + :http_pool_size => '6', + :http_timeout => '60', + :sync_interval => '30', + :max_vsm_retries => '3', + :restrict_policy_profiles => 'False', + :enable_vif_type_n1kv => 'True', + } + end + let :ml2_params do + { + :extension_drivers => 'cisco_n1kv_ext', + } + end + it do + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/n1kv_vsm_ips').with_value(params[:n1kv_vsm_ip]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/username').with_value(params[:n1kv_vsm_username]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/password').with_value(params[:n1kv_vsm_password]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/default_policy_profile').with_value(params[:default_policy_profile]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/default_vlan_network_profile').with_value(params[:default_vlan_network_profile]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/default_vxlan_network_profile').with_value(params[:default_vxlan_network_profile]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/poll_duration').with_value(params[:poll_duration]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/http_pool_size').with_value(params[:http_pool_size]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/http_timeout').with_value(params[:http_timeout]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/sync_interval').with_value(params[:sync_interval]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/max_vsm_retries').with_value(params[:max_vsm_retries]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/restrict_policy_profiles').with_value(params[:restrict_policy_profiles]) + is_expected.to contain_neutron_plugin_ml2('ml2_cisco_n1kv/enable_vif_type_n1kv').with_value(params[:enable_vif_type_n1kv]) + is_expected.to contain_neutron_plugin_ml2('ml2/extension_drivers').with_value(ml2_params[:extension_drivers]) + end + end +end diff --git a/neutron/spec/classes/neutron_plugins_ml2_spec.rb b/neutron/spec/classes/neutron_plugins_ml2_spec.rb index f1b507355..2022fb2d1 100644 --- a/neutron/spec/classes/neutron_plugins_ml2_spec.rb +++ b/neutron/spec/classes/neutron_plugins_ml2_spec.rb @@ -193,7 +193,7 @@ ) end it 'configures sriov mechanism driver with agent_enabled' do - is_expected.to contain_neutron_plugin_ml2('ml2_sriov/supported_pci_vendor_dev').with_value(['15b3:1004,8086:10ca']) + is_expected.to contain_neutron_plugin_ml2('ml2_sriov/supported_pci_vendor_devs').with_value(['15b3:1004,8086:10ca']) is_expected.to contain_neutron_plugin_ml2('ml2_sriov/agent_required').with_value('true') end end diff --git a/neutron/spec/spec_helper_acceptance.rb b/neutron/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/neutron/spec/spec_helper_acceptance.rb +++ b/neutron/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/neutron/templates/n1kv.conf.erb b/neutron/templates/n1kv.conf.erb index dd9409432..c2fccc340 100644 --- a/neutron/templates/n1kv.conf.erb +++ b/neutron/templates/n1kv.conf.erb @@ -29,6 +29,21 @@ switch-domain <%= @n1kv_vsm_domain_id %> # restart_on_modify: No l3control-ipaddr <%= @n1kv_vsm_ip %> +# TAG: l3control-ipv6addr +# Description: IPv6 Address of VSM Mgmt I/F +# Optional: No +# Default: ::1 +# restart_on_modify: No +l3control-ipv6addr <%= @n1kv_vsm_ipv6 %> + +# Set svs-mode to V6 if IPv6 address for VSM +# is set to something other than default ::1. +# This tells VEM to communicate with VSM on +# IPv6 instead of the default IPv4 option +<% if @n1kv_vsm_ipv6 != '::1' -%> +svs-mode V6 +<% end -%> + # TAG: host-mgmt-intf # Description: Management interface of the Host # Optional: No (on N1KV, we need this diff --git a/nova/CHANGELOG.md b/nova/CHANGELOG.md index 70688bc4b..68dcbe8ac 100644 --- a/nova/CHANGELOG.md +++ b/nova/CHANGELOG.md @@ -1,3 +1,52 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a backwards-incompatible major release for OpenStack Kilo. + +####Backwards-incompatible changes +- Remove deprecated parameters +- Disable file injection when using RBD as compute ephemeral storage +- Remove Python Package Declaration +- move setting of novncproxy_base_url +- Move rabbit/kombu settings to oslo_messaging_rabbit section +- MySQL: change default MySQL collate to utf8_general_ci +- Moved spice configuration options from DEFAULT to spice section + +####Features +- Puppet 4.x support +- Refactorise Keystone resources management +- Configure database parameters on the right nodes +- Add parameters for availability zones configuration +- Migrate postgresql backend to use openstacklib::db::postgresql +- Allow auth_name and auth_name_v3 to be the same +- Add an option to not configure RabbitMQ service +- Database: add slave_connection support +- Support for heal_instance_info_cache_interval +- Only tag packages with openstack tag +- Add PCI Passthrough/SR-IOV support +- Add support for identity_uri +- IPv6 support for migration check +- Allow libvirt secret key setting from param +- Adds OracleLinux support +- Ensure /etc/nova exists before creating secret.xml +- Run db-sync if nova packages are upgraded +- Make package 'bridge-utils' install optional +- Introduce public_url, internal_url and admin_url (and v3/ec2) +- Better handling of package dependencies in nova generic_service +- Add scheduler_driver parameter to nova::scheduler class +- Add parameter to control use of rbd for the ephemeral storage +- Install only required libvirt packages +- keystone/auth: make service description configurable + +####Bugfixes +- Fix catalog compilation when not configuring endpoint +- Fix behaviour of 'set-secret-value virsh' exec +- Fix variable access in RBD secret template + +####Maintenance +- Acceptance tests with Beaker +- Fix spec tests for RSpec 3.x and Puppet 4.x + ##2015-06-17 - 5.1.0 ###Summary diff --git a/nova/README.md b/nova/README.md index 9abc48838..02b0034b3 100644 --- a/nova/README.md +++ b/nova/README.md @@ -1,7 +1,7 @@ nova ==== -5.1.0 - 2014.2 - Juno +6.0.0 - 2015.1 - Kilo #### Table of Contents diff --git a/nova/lib/puppet/provider/nova_network/nova_manage.rb b/nova/lib/puppet/provider/nova_network/nova_manage.rb index 6da03a39d..c4cb3bd10 100644 --- a/nova/lib/puppet/provider/nova_network/nova_manage.rb +++ b/nova/lib/puppet/provider/nova_network/nova_manage.rb @@ -2,7 +2,7 @@ desc "Manage nova network" - optional_commands :nova_manage => 'nova-manage' + optional_commands :nova_manage => 'nova-manage', :nova => 'nova' # I need to setup caching and what-not to make this lookup performance not suck def self.instances @@ -30,18 +30,19 @@ def create :dns2 => '--dns2', :gateway => '--gateway', :bridge => '--bridge', - :vlan_start => '--vlan_start' + :vlan_start => '--vlan-start', + :allowed_start => '--allowed-start', + :allowed_end => '--allowed-end', }.each do |param, opt| if resource[param] optional_opts.push(opt).push(resource[param]) end end - nova_manage('network', 'create', + nova('network-create', resource[:label], + '--fixed-range-v4', resource[:name], - resource[:num_networks], - resource[:network_size], optional_opts ) end diff --git a/nova/lib/puppet/type/nova_network.rb b/nova/lib/puppet/type/nova_network.rb index 3a750e02e..c9e654d93 100644 --- a/nova/lib/puppet/type/nova_network.rb +++ b/nova/lib/puppet/type/nova_network.rb @@ -37,6 +37,16 @@ newparam(:dns2) do end + newparam(:allowed_start) do + desc 'Start of allowed addresses for instances' + newvalues(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/) + end + + newparam(:allowed_end) do + desc 'End of allowed addresses for instances' + newvalues(/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/) + end + newparam(:vlan_start) do end diff --git a/nova/manifests/compute/ironic.pp b/nova/manifests/compute/ironic.pp index 52bb37596..ae5c8800f 100644 --- a/nova/manifests/compute/ironic.pp +++ b/nova/manifests/compute/ironic.pp @@ -24,13 +24,16 @@ # The url for Ironic api endpoint. # Defaults to 'http://127.0.0.1:6385/v1' # +# [*compute_driver*] +# (optional) Compute driver. +# Defaults to 'ironic.IronicDriver' +# # [*admin_user*] # (optional) DEPRECATED: Use admin_username instead. # # [*admin_passwd*] # (optional) DEPRECATED: Use admin_password instead. # - class nova::compute::ironic ( $admin_username = 'admin', $admin_password = 'ironic', @@ -40,6 +43,7 @@ # DEPRECATED PARAMETERS $admin_user = undef, $admin_passwd = undef, + $compute_driver = 'ironic.IronicDriver' ) { if $admin_user { @@ -59,6 +63,6 @@ 'ironic/admin_url': value => $admin_url; 'ironic/admin_tenant_name': value => $admin_tenant_name; 'ironic/api_endpoint': value => $api_endpoint; - 'DEFAULT/compute_driver': value => 'nova.virt.ironic.IronicDriver'; + 'DEFAULT/compute_driver': value => $compute_driver; } } diff --git a/nova/manifests/compute/libvirt.pp b/nova/manifests/compute/libvirt.pp index 7f7e5df65..f6834ca54 100644 --- a/nova/manifests/compute/libvirt.pp +++ b/nova/manifests/compute/libvirt.pp @@ -78,6 +78,10 @@ # (optional) libvirt service name. # Defaults to $::nova::params::libvirt_service_name # +# [*compute_driver*] +# (optional) Compute driver. +# Defaults to 'libvirt.LibvirtDriver' +# class nova::compute::libvirt ( $libvirt_virt_type = 'kvm', $vncserver_listen = '127.0.0.1', @@ -92,6 +96,7 @@ $remove_unused_resized_minimum_age_seconds = undef, $remove_unused_original_minimum_age_seconds = undef, $libvirt_service_name = $::nova::params::libvirt_service_name, + $compute_driver = 'libvirt.LibvirtDriver' ) inherits nova::params { include ::nova::params @@ -171,7 +176,7 @@ } nova_config { - 'DEFAULT/compute_driver': value => 'libvirt.LibvirtDriver'; + 'DEFAULT/compute_driver': value => $compute_driver; 'DEFAULT/vncserver_listen': value => $vncserver_listen; 'libvirt/virt_type': value => $libvirt_virt_type; 'libvirt/cpu_mode': value => $libvirt_cpu_mode_real; diff --git a/nova/manifests/compute/vmware.pp b/nova/manifests/compute/vmware.pp index 5432e5bcf..40b2d460d 100644 --- a/nova/manifests/compute/vmware.pp +++ b/nova/manifests/compute/vmware.pp @@ -43,21 +43,25 @@ # default location for bug work-arounds. # Defaults to None. # - +# [*compute_driver*] +# (optional) Compute driver. +# Defaults to 'vmwareapi.VMwareVCDriver' +# class nova::compute::vmware( $host_ip, $host_username, $host_password, $cluster_name, - $api_retry_count=5, - $maximum_objects=100, - $task_poll_interval=5.0, - $use_linked_clone=true, - $wsdl_location=undef + $api_retry_count = 5, + $maximum_objects = 100, + $task_poll_interval = 5.0, + $use_linked_clone = true, + $wsdl_location = undef, + $compute_driver = 'vmwareapi.VMwareVCDriver' ) { nova_config { - 'DEFAULT/compute_driver': value => 'vmwareapi.VMwareVCDriver'; + 'DEFAULT/compute_driver': value => $compute_driver; 'VMWARE/host_ip': value => $host_ip; 'VMWARE/host_username': value => $host_username; 'VMWARE/host_password': value => $host_password; diff --git a/nova/manifests/compute/xenserver.pp b/nova/manifests/compute/xenserver.pp index f28c0b486..cebd6d23e 100644 --- a/nova/manifests/compute/xenserver.pp +++ b/nova/manifests/compute/xenserver.pp @@ -13,24 +13,31 @@ # [*xenapi_connection_password*] # (required) Password for connection to XenServer/Xen Cloud Platform # +# [*compute_driver*] +# (optional) Compute driver. +# Defaults to 'xenapi.XenAPIDriver' +# # [*xenapi_inject_image*] -# (optional) This parameter was removed in Diablo and does nothing. -# Defaults to false +# (optional) DEPRECATED: This parameter does nothing. # class nova::compute::xenserver( $xenapi_connection_url, $xenapi_connection_username, $xenapi_connection_password, - $xenapi_inject_image=false + $compute_driver = 'xenapi.XenAPIDriver', + # DEPRECATED PARAMETERS + $xenapi_inject_image = undef, ) { + if $xenapi_inject_image != undef { + warning('The xenapi_inject_image parameter is deprecated and has no effect.') + } + nova_config { - 'DEFAULT/compute_driver': value => 'xenapi.XenAPIDriver'; - 'DEFAULT/connection_type': value => 'xenapi'; + 'DEFAULT/compute_driver': value => $compute_driver; 'DEFAULT/xenapi_connection_url': value => $xenapi_connection_url; 'DEFAULT/xenapi_connection_username': value => $xenapi_connection_username; 'DEFAULT/xenapi_connection_password': value => $xenapi_connection_password; - 'DEFAULT/xenapi_inject_image': value => $xenapi_inject_image; } ensure_packages(['python-pip']) diff --git a/nova/manifests/manage/network.pp b/nova/manifests/manage/network.pp index 922b3ae47..536d7e3bd 100644 --- a/nova/manifests/manage/network.pp +++ b/nova/manifests/manage/network.pp @@ -19,30 +19,42 @@ # (optional) The vlan number to use if in vlan mode # Defaults to undef # +# [*allowed_start*] +# (optional) Start of allowed addresses for instances +# Defaults to undef +# +# [*allowed_end*] +# (optional) End of allowed addresses for instances +# Defaults to undef +# # [*project*] # (optional) Project that network should be associated with # Defaults to undef # define nova::manage::network ( $network, - $label = 'novanetwork', - $num_networks = 1, - $network_size = 255, - $vlan_start = undef, - $project = undef + $label = 'novanetwork', + $num_networks = 1, + $network_size = 255, + $vlan_start = undef, + $project = undef, + $allowed_start = undef, + $allowed_end = undef, ) { File['/etc/nova/nova.conf'] -> Nova_network[$name] Exec<| title == 'nova-db-sync' |> -> Nova_network[$name] nova_network { $name: - ensure => present, - network => $network, - label => $label, - num_networks => $num_networks, - network_size => $network_size, - project => $project, - vlan_start => $vlan_start, + ensure => present, + network => $network, + label => $label, + num_networks => $num_networks, + network_size => $network_size, + project => $project, + vlan_start => $vlan_start, + allowed_start => $allowed_start, + allowed_end => $allowed_end, } } diff --git a/nova/manifests/network.pp b/nova/manifests/network.pp index 94c01c139..6a2f4a421 100644 --- a/nova/manifests/network.pp +++ b/nova/manifests/network.pp @@ -59,6 +59,15 @@ # (optional) Whether to install and enable the service # Defaults to true # +# [*allowed_start*] +# (optional) Start of allowed addresses for instances +# Defaults to undef +# +# [*allowed_end*] +# (optional) End of allowed addresses for instances +# Defaults to undef +# + class nova::network( $private_interface = undef, $fixed_range = '10.0.0.0/8', @@ -71,7 +80,9 @@ $config_overrides = {}, $create_networks = true, $ensure_package = 'present', - $install_service = true + $install_service = true, + $allowed_start = undef, + $allowed_end = undef, ) { include ::nova::params @@ -107,10 +118,12 @@ if $create_networks { nova::manage::network { 'nova-vm-net': - network => $fixed_range, - num_networks => $num_networks, - network_size => $network_size, - vlan_start => $vlan_start, + network => $fixed_range, + num_networks => $num_networks, + network_size => $network_size, + vlan_start => $vlan_start, + allowed_start => $allowed_start, + allowed_end => $allowed_end, } if $floating_range { nova::manage::floating { 'nova-vm-floating': diff --git a/nova/manifests/scheduler.pp b/nova/manifests/scheduler.pp index 97955c36f..ee787142e 100644 --- a/nova/manifests/scheduler.pp +++ b/nova/manifests/scheduler.pp @@ -18,13 +18,13 @@ # # [*scheduler_driver*] # (optional) Default driver to use for the scheduler -# Defaults to 'nova.scheduler.host_manager.HostManager' +# Defaults to 'nova.scheduler.filter_scheduler.FilterScheduler' # class nova::scheduler( $enabled = false, $manage_service = true, $ensure_package = 'present', - $scheduler_driver = 'nova.scheduler.host_manager.HostManager', + $scheduler_driver = 'nova.scheduler.filter_scheduler.FilterScheduler', ) { include ::nova::db diff --git a/nova/metadata.json b/nova/metadata.json index a42c33a59..4b4f43dca 100644 --- a/nova/metadata.json +++ b/nova/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-nova", - "version": "5.1.0", + "name": "openstack-nova", + "version": "6.0.0", "author": "Puppet Labs and OpenStack Contributors", "summary": "Puppet module for OpenStack Nova", "license": "Apache-2.0", @@ -33,12 +33,12 @@ "dependencies": [ { "name": "dprince/qpid", "version_requirement": ">=1.0.0 <2.0.0" }, { "name": "duritong/sysctl", "version_requirement": ">=0.0.1 <1.0.0" }, - { "name": "stackforge/cinder", "version_requirement": ">=5.0.0 <6.0.0" }, - { "name": "stackforge/glance", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/cinder", "version_requirement": ">=6.0.0 <7.0.0" }, + { "name": "openstack/glance", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/rabbitmq", "version_requirement": ">=2.0.2 <6.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/nova/spec/classes/nova_compute_ironic_spec.rb b/nova/spec/classes/nova_compute_ironic_spec.rb index d5433f753..401839526 100644 --- a/nova/spec/classes/nova_compute_ironic_spec.rb +++ b/nova/spec/classes/nova_compute_ironic_spec.rb @@ -2,13 +2,37 @@ describe 'nova::compute::ironic' do - it 'configures ironic in nova.conf' do - is_expected.to contain_nova_config('ironic/admin_username').with_value('admin') - is_expected.to contain_nova_config('ironic/admin_password').with_value('ironic') - is_expected.to contain_nova_config('ironic/admin_url').with_value('http://127.0.0.1:35357/v2.0') - is_expected.to contain_nova_config('ironic/admin_tenant_name').with_value('services') - is_expected.to contain_nova_config('ironic/api_endpoint').with_value('http://127.0.0.1:6385/v1') - is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('nova.virt.ironic.IronicDriver') + context 'with default parameters' do + it 'configures ironic in nova.conf' do + is_expected.to contain_nova_config('ironic/admin_username').with_value('admin') + is_expected.to contain_nova_config('ironic/admin_password').with_value('ironic') + is_expected.to contain_nova_config('ironic/admin_url').with_value('http://127.0.0.1:35357/v2.0') + is_expected.to contain_nova_config('ironic/admin_tenant_name').with_value('services') + is_expected.to contain_nova_config('ironic/api_endpoint').with_value('http://127.0.0.1:6385/v1') + is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('ironic.IronicDriver') + end + end + + context 'with overridden parameters' do + let :params do + { + :admin_username => 'ironic', + :admin_password => 's3cr3t', + :admin_url => 'http://10.0.0.10:35357/v2.0', + :admin_tenant_name => 'services2', + :api_endpoint => 'http://10.0.0.10:6385/v1', + :compute_driver => 'ironic.FoobarDriver' + } + end + + it 'configures ironic in nova.conf' do + is_expected.to contain_nova_config('ironic/admin_username').with_value('ironic') + is_expected.to contain_nova_config('ironic/admin_password').with_value('s3cr3t') + is_expected.to contain_nova_config('ironic/admin_url').with_value('http://10.0.0.10:35357/v2.0') + is_expected.to contain_nova_config('ironic/admin_tenant_name').with_value('services2') + is_expected.to contain_nova_config('ironic/api_endpoint').with_value('http://10.0.0.10:6385/v1') + is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('ironic.FoobarDriver') + end end context 'with deprecated parameters' do diff --git a/nova/spec/classes/nova_compute_libvirt_spec.rb b/nova/spec/classes/nova_compute_libvirt_spec.rb index 87b144054..0082578ac 100644 --- a/nova/spec/classes/nova_compute_libvirt_spec.rb +++ b/nova/spec/classes/nova_compute_libvirt_spec.rb @@ -58,10 +58,12 @@ :remove_unused_kernels => true, :remove_unused_resized_minimum_age_seconds => 3600, :remove_unused_original_minimum_age_seconds => 3600, - :libvirt_service_name => 'custom_service' + :libvirt_service_name => 'custom_service', + :compute_driver => 'libvirt.FoobarDriver', } end + it { is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('libvirt.FoobarDriver')} it { is_expected.to contain_nova_config('libvirt/virt_type').with_value('qemu')} it { is_expected.to contain_nova_config('libvirt/cpu_mode').with_value('host-passthrough')} it { is_expected.to contain_nova_config('libvirt/disk_cachemodes').with_value('file=directsync,block=none')} diff --git a/nova/spec/classes/nova_compute_vmware_spec.rb b/nova/spec/classes/nova_compute_vmware_spec.rb index 90ef18b53..9bd295045 100644 --- a/nova/spec/classes/nova_compute_vmware_spec.rb +++ b/nova/spec/classes/nova_compute_vmware_spec.rb @@ -14,7 +14,8 @@ :maximum_objects => 100, :task_poll_interval => 10.5, :use_linked_clone => false, - :wsdl_location => 'http://127.0.0.1:8080/vmware/SDK/wsdl/vim25/vimService.wsdl'} + :wsdl_location => 'http://127.0.0.1:8080/vmware/SDK/wsdl/vim25/vimService.wsdl', + :compute_driver => 'vmwareapi.FoobarDriver' } end it 'configures vmwareapi in nova.conf' do @@ -42,6 +43,7 @@ end it 'configures vmwareapi in nova.conf' do + is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value(params[:compute_driver]) is_expected.to contain_nova_config('VMWARE/api_retry_count').with_value(params[:api_retry_count]) is_expected.to contain_nova_config('VMWARE/maximum_objects').with_value(params[:maximum_objects]) is_expected.to contain_nova_config('VMWARE/task_poll_interval').with_value(params[:task_poll_interval]) diff --git a/nova/spec/classes/nova_compute_xenserver_spec.rb b/nova/spec/classes/nova_compute_xenserver_spec.rb index ccb8cfb87..5aaf2d899 100644 --- a/nova/spec/classes/nova_compute_xenserver_spec.rb +++ b/nova/spec/classes/nova_compute_xenserver_spec.rb @@ -12,11 +12,9 @@ it 'configures xenapi in nova.conf' do is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('xenapi.XenAPIDriver') - is_expected.to contain_nova_config('DEFAULT/connection_type').with_value('xenapi') is_expected.to contain_nova_config('DEFAULT/xenapi_connection_url').with_value(params[:xenapi_connection_url]) is_expected.to contain_nova_config('DEFAULT/xenapi_connection_username').with_value(params[:xenapi_connection_username]) is_expected.to contain_nova_config('DEFAULT/xenapi_connection_password').with_value(params[:xenapi_connection_password]) - is_expected.to contain_nova_config('DEFAULT/xenapi_inject_image').with_value(false) end it 'installs xenapi with pip' do @@ -26,4 +24,14 @@ ) end end + + context 'with overridden parameters' do + before do + params.merge!({:compute_driver => 'xenapi.FoobarDriver'}) + end + + it 'configures xenapi in nova.conf' do + is_expected.to contain_nova_config('DEFAULT/compute_driver').with_value('xenapi.FoobarDriver') + end + end end diff --git a/nova/spec/classes/nova_scheduler_spec.rb b/nova/spec/classes/nova_scheduler_spec.rb index 9b589eb14..b2235bc50 100644 --- a/nova/spec/classes/nova_scheduler_spec.rb +++ b/nova/spec/classes/nova_scheduler_spec.rb @@ -24,7 +24,7 @@ :ensure => 'running' )} - it { is_expected.to contain_nova_config('DEFAULT/scheduler_driver').with_value('nova.scheduler.host_manager.HostManager') } + it { is_expected.to contain_nova_config('DEFAULT/scheduler_driver').with_value('nova.scheduler.filter_scheduler.FilterScheduler') } context 'with manage_service as false' do let :params do diff --git a/nova/spec/defines/nova_manage_networks_spec.rb b/nova/spec/defines/nova_manage_networks_spec.rb index e177c054e..b8ec36876 100644 --- a/nova/spec/defines/nova_manage_networks_spec.rb +++ b/nova/spec/defines/nova_manage_networks_spec.rb @@ -21,11 +21,13 @@ } end it { is_expected.to contain_nova_network('foo').with( - :ensure => 'present', - :network => '10.0.0.0/24', - :label => 'novanetwork', - :num_networks => 1, - :project => nil + :ensure => 'present', + :network => '10.0.0.0/24', + :label => 'novanetwork', + :num_networks => 1, + :project => nil, + :allowed_start => nil, + :allowed_end => nil, ) } end describe 'when overriding num networks' do @@ -53,4 +55,20 @@ :project => 'foo' ) } end + + describe 'when overriding allowed range' do + let :params do + { + :network => '10.0.0.0/20', + :allowed_start => '10.0.0.1', + :allowed_end => '10.0.0.5' + } + end + it { is_expected.to contain_nova_network('foo').with( + :network => '10.0.0.0/20', + :allowed_start => '10.0.0.1', + :allowed_end => '10.0.0.5' + ) } + end + end diff --git a/nova/spec/spec_helper_acceptance.rb b/nova/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/nova/spec/spec_helper_acceptance.rb +++ b/nova/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/openstack_extras/CHANGELOG.md b/openstack_extras/CHANGELOG.md index 0337785df..e9bb37bb0 100644 --- a/openstack_extras/CHANGELOG.md +++ b/openstack_extras/CHANGELOG.md @@ -1,3 +1,29 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a backwards-incompatible major release for OpenStack Kilo. + +####Backwards-incompatible changes +- repo: bump to Kilo by default + +####Features +- Puppet 4.x support +- Add hash based repository management +- Add pacemaker provider for HA services +- Add auth file from openstack repo +- Support native OS primitive classes in Pacemaker +- Support cloned resources in Pacemaker +- auth_file: allow to change the path +- repo/redhat: manage EPEL with metalink instead of baseurl + +####Bugfixes +- Ensure python-mysqldb is installed before MySQL db_sync +- Fix dependency on nova-common package + +####Maintenance +- repo/apt: update to support apt 2.1.0 module +- Increase major bound on puppetlabs-apt + ##2014-11-21 - 5.0.0 ###Summary diff --git a/openstack_extras/README.md b/openstack_extras/README.md index e0488f76d..fbbea5145 100644 --- a/openstack_extras/README.md +++ b/openstack_extras/README.md @@ -1,7 +1,7 @@ openstack_extras ============ -5.0.0 - 2014.2.0 - Juno +6.0.0 - 2015.1.0 - Kilo #### Table of Contents diff --git a/openstack_extras/metadata.json b/openstack_extras/metadata.json index 384010a36..979433203 100644 --- a/openstack_extras/metadata.json +++ b/openstack_extras/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-openstack_extras", - "version": "5.0.0", + "name": "openstack-openstack_extras", + "version": "6.0.0", "author": "OpenStack Contributors", "summary": "Puppet OpenStack Extras Module", "license": "Apache-2.0", diff --git a/openstacklib/CHANGELOG.md b/openstacklib/CHANGELOG.md index 944eb5df7..9c36e17e9 100644 --- a/openstacklib/CHANGELOG.md +++ b/openstacklib/CHANGELOG.md @@ -1,3 +1,26 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a backwards-incompatible major release for OpenStack Kilo. + +####Backwards-incompatible changes +- MySQL: change default MySQL collate to utf8_general_ci + +####Features +- Puppet 4.x support +- Add db::postgresql to openstacklib +- Implement openstacklib::wsgi::apache +- Move openstackclient parent provider to openstacklib +- Keystone V3 API support +- Restructures authentication for resource providers + +####Bugfixes +- Properly handle policy values containing spaces + +####Maintenance +- Bump mysql version to 3.x +- Acceptance tests with Beaker + ##2015-06-17 - 5.1.0 ###Summary diff --git a/openstacklib/README.md b/openstacklib/README.md index 90fb090d0..e97677d15 100644 --- a/openstacklib/README.md +++ b/openstacklib/README.md @@ -1,7 +1,8 @@ openstacklib ============ -5.1.0 - 2014.2 - Juno +6.0.0 - 2015.1 - Kilo + #### Table of Contents 1. [Overview - What is the openstacklib module?](#overview) diff --git a/openstacklib/metadata.json b/openstacklib/metadata.json index bc79e797f..6520213a1 100644 --- a/openstacklib/metadata.json +++ b/openstacklib/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-openstacklib", - "version": "5.1.0", + "name": "openstack-openstacklib", + "version": "6.0.0", "author": "Puppet Labs and OpenStack Contributors", "summary": "Puppet OpenStack Libraries", "license": "Apache-2.0", diff --git a/openstacklib/spec/spec_helper_acceptance.rb b/openstacklib/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/openstacklib/spec/spec_helper_acceptance.rb +++ b/openstacklib/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/sahara/CHANGELOG.md b/sahara/CHANGELOG.md new file mode 100644 index 000000000..9f217799c --- /dev/null +++ b/sahara/CHANGELOG.md @@ -0,0 +1,4 @@ +##2015-07-08 - 6.0.0 +###Summary + +- Initial release of the puppet-sahara module diff --git a/sahara/README.md b/sahara/README.md index a8d5a5a5a..1c617bd07 100644 --- a/sahara/README.md +++ b/sahara/README.md @@ -1,6 +1,8 @@ sahara ====== +6.0.0 - 2015.1 - Kilo + #### Table of Contents 1. [Overview - What is the sahara module?](#overview) diff --git a/sahara/examples/basic.pp b/sahara/examples/basic.pp index a217ca364..ee66f1ccd 100644 --- a/sahara/examples/basic.pp +++ b/sahara/examples/basic.pp @@ -31,13 +31,13 @@ database_connection => 'mysql://sahara:a_big_secret@127.0.0.1:3306/sahara', verbose => true, debug => true, - keystone_username => 'admin', - keystone_password => 'secrets_everywhere', - keystone_tenant => 'admin', - keystone_url => 'http://127.0.0.1:5000/v2.0/', - identity_url => 'http://127.0.0.1:35357/', - service_host => '0.0.0.0', - service_port => 8386, + admin_user => 'admin', + admin_password => 'secrets_everywhere', + admin_tenant_name => 'admin', + auth_uri => 'http://127.0.0.1:5000/v2.0/', + identity_uri => 'http://127.0.0.1:35357/', + host => '0.0.0.0', + port => 8386, use_floating_ips => true, } diff --git a/sahara/manifests/init.pp b/sahara/manifests/init.pp index dfe4e73e6..2237bc9df 100644 --- a/sahara/manifests/init.pp +++ b/sahara/manifests/init.pp @@ -37,11 +37,11 @@ # If set to boolean false, it will not log to any directory. # Defaults to '/var/log/sahara' # -# [*service_host*] +# [*host*] # (Optional) Hostname for sahara to listen on # Defaults to '0.0.0.0'. # -# [*service_port*] +# [*port*] # (Optional) Port for sahara to listen on # Defaults to 8386. # @@ -59,26 +59,64 @@ # # == keystone authentication options # -# [*keystone_username*] -# (Optional) Username for sahara credentials +# [*admin_user*] +# (Optional) Service user name # Defaults to 'admin'. # -# [*keystone_password*] -# (Optional) Password for sahara credentials +# [*admin_password*] +# (Optional) Service user password. # Defaults to false. # -# [*keystone_tenant*] -# (Optional) Tenant for keystone_username +# [*admin_tenant_name*] +# (Optional) Service tenant name. # Defaults to 'admin'. # -# [*keystone_url*] -# (Optional) Public identity endpoint +# [*auth_uri*] +# (Optional) Complete public Identity API endpoint. # Defaults to 'http://127.0.0.1:5000/v2.0/'. # -# [*identity_url*] -# (Optional) Admin identity endpoint +# [*identity_uri*] +# (Optional) Complete admin Identity API endpoint. +# This should specify the unversioned root endpoint. # Defaults to 'http://127.0.0.1:35357/'. # +# == DEPRECATED PARAMETERS +# +# [*service_host*] +# (Optional) DEPRECATED: Use host instead. +# Hostname for sahara to listen on +# Defaults to undef. +# +# [*service_port*] +# (Optional) DEPRECATED: Use port instead. +# Port for sahara to listen on +# Defaults to undef. +# +# [*keystone_username*] +# (Optional) DEPRECATED: Use admin_user instead. +# Username for sahara credentials +# Defaults to undef. +# +# [*keystone_password*] +# (Optional) DEPRECATED: Use admin_password instead. +# Password for sahara credentials +# Defaults to undef. +# +# [*keystone_tenant*] +# (Optional) DEPRECATED: Use admin_tenant_name instead. +# Tenant for keystone_username +# Defaults to undef. +# +# [*keystone_url*] +# (Optional) DEPRECATED: Use auth_uri instead. +# Public identity endpoint +# Defaults to undef. +# +# [*identity_url*] +# (Optional) DEPRECATED: Use identity_uri instead. +# Admin identity endpoint +# Defaults to undef. +# class sahara( $manage_service = true, $enabled = true, @@ -88,20 +126,77 @@ $use_syslog = false, $log_facility = 'LOG_USER', $log_dir = '/var/log/sahara', - $service_host = '0.0.0.0', - $service_port = 8386, + $host = '0.0.0.0', + $port = '8386', $use_neutron = false, $use_floating_ips = true, $database_connection = 'mysql://sahara:secrete@localhost:3306/sahara', - $keystone_username = 'admin', - $keystone_password = false, - $keystone_tenant = 'admin', - $keystone_url = 'http://127.0.0.1:5000/v2.0/', - $identity_url = 'http://127.0.0.1:35357/', + $admin_user = 'admin', + $admin_password = false, + $admin_tenant_name = 'admin', + $auth_uri = 'http://127.0.0.1:5000/v2.0/', + $identity_uri = 'http://127.0.0.1:35357/', + # DEPRECATED PARAMETERS + $service_host = undef, + $service_port = undef, + $keystone_username = undef, + $keystone_password = undef, + $keystone_tenant = undef, + $keystone_url = undef, + $identity_url = undef, ) { include ::sahara::params include ::sahara::policy + if $service_host { + warning('The service_host parameter is deprecated. Use host parameter instead') + $host_real = $service_host + } else { + $host_real = $host + } + + if $service_port { + warning('The service_port parameter is deprecated. Use port parameter instead') + $port_real = $service_port + } else { + $port_real = $port + } + + if $keystone_username { + warning('The keystone_username parameter is deprecated. Use admin_user parameter instead') + $admin_user_real = $keystone_username + } else { + $admin_user_real = $admin_user + } + + if $keystone_password { + warning('The keystone_password parameter is deprecated. Use admin_password parameter instead') + $admin_password_real = $keystone_password + } else { + $admin_password_real = $admin_password + } + + if $keystone_tenant { + warning('The keystone_tenant parameter is deprecated. Use admin_tenant_name parameter instead') + $admin_tenant_name_real = $keystone_tenant + } else { + $admin_tenant_name_real = $admin_tenant_name + } + + if $keystone_url { + warning('The keystone_url parameter is deprecated. Use auth_uri parameter instead') + $auth_uri_real = $keystone_url + } else { + $auth_uri_real = $auth_uri + } + + if $identity_url { + warning('The identity_url parameter is deprecated. Use identity_uri parameter instead') + $identity_uri_real = $identity_url + } else { + $identity_uri_real = $identity_uri + } + if $::osfamily == 'RedHat' { $group_require = Package['sahara'] $dir_require = Package['sahara'] @@ -186,24 +281,23 @@ sahara_config { 'DEFAULT/use_neutron': value => $use_neutron; 'DEFAULT/use_floating_ips': value => $use_floating_ips; - 'DEFAULT/host': value => $service_host; - 'DEFAULT/port': value => $service_port; - 'DEFAULT/debug': value => $debug; - 'DEFAULT/verbose': value => $verbose; - + 'DEFAULT/host': value => $host_real; + 'DEFAULT/port': value => $port_real; + 'DEFAULT/debug': value => $debug; + 'DEFAULT/verbose': value => $verbose; 'database/connection': value => $database_connection, secret => true; } - if $keystone_password { + if $admin_password_real { sahara_config { - 'keystone_authtoken/auth_uri': value => $keystone_url; - 'keystone_authtoken/identity_uri': value => $identity_url; - 'keystone_authtoken/admin_user': value => $keystone_username; - 'keystone_authtoken/admin_tenant_name': value => $keystone_tenant; + 'keystone_authtoken/auth_uri': value => $auth_uri_real; + 'keystone_authtoken/identity_uri': value => $identity_uri_real; + 'keystone_authtoken/admin_user': value => $admin_user_real; + 'keystone_authtoken/admin_tenant_name': value => $admin_tenant_name_real; 'keystone_authtoken/admin_password': - value => $keystone_password, + value => $admin_password_real, secret => true; } } @@ -220,12 +314,12 @@ if $use_syslog { sahara_config { - 'DEFAULT/use_syslog': value => true; - 'DEFAULT/syslog_log_facility': value => $log_facility; + 'DEFAULT/use_syslog': value => true; + 'DEFAULT/syslog_log_facility': value => $log_facility; } } else { sahara_config { - 'DEFAULT/use_syslog': value => false; + 'DEFAULT/use_syslog': value => false; } } diff --git a/sahara/manifests/notify/qpid.pp b/sahara/manifests/notify/qpid.pp index 82289e52c..8577d5edf 100644 --- a/sahara/manifests/notify/qpid.pp +++ b/sahara/manifests/notify/qpid.pp @@ -56,11 +56,13 @@ # (Optional) The default exchange to scope topics. # Defaults to 'openstack'. # +# == DEPRECATED PARAMETERS +# # [*kombu_ssl_version*] # (optional) SSL version to use (valid only if SSL enabled). # Valid values are TLSv1, SSLv23 and SSLv3. SSLv2 may be # available on some distributions. -# Defaults to 'TLSv1' +# Defaults to undef # # [*kombu_ssl_keyfile*] # (Optional) SSL key file (valid only if SSL enabled). @@ -76,7 +78,7 @@ # # [*kombu_reconnect_delay*] # (Optional) Backoff on cancel notification (valid only if SSL enabled). -# Defaults to '1.0'; floating-point value. +# Defaults to undef # class sahara::notify::qpid( $durable_queues = false, @@ -92,59 +94,52 @@ $qpid_topology_version = 2, $notification_topics = 'notifications', $control_exchange = 'openstack', - $kombu_ssl_version = 'TLSv1', + # DEPRECATED PARAMETERS + $kombu_ssl_version = undef, $kombu_ssl_keyfile = undef, $kombu_ssl_certfile = undef, $kombu_ssl_ca_certs = undef, - $kombu_reconnect_delay = '1.0', + $kombu_reconnect_delay = undef, ) { - if $qpid_protocol == 'ssl' { - if !$kombu_ssl_keyfile { - fail('kombu_ssl_keyfile must be set when using SSL in qpid') - } - if !$kombu_ssl_certfile { - fail('kombu_ssl_certfile must be set when using SSL in qpid') - } - if !$kombu_ssl_ca_certs { - fail('kombu_ca_certs must be set when using SSL in qpid') - } - 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; - } - } elsif $qpid_protocol == 'tcp' { - 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; - } - } else { - fail("valid qpid_protocol settings are 'tcp' and 'ssl' only") + + if $kombu_ssl_version { + warning('The kombu_ssl_version parameter is deprecated and has no effect.') + } + + if $kombu_ssl_keyfile { + warning('The kombu_ssl_keyfile parameter is deprecated and has no effect.') + } + + if $kombu_ssl_certfile { + warning('The kombu_ssl_certfile is deprecated and has no effect.') + } + + if $kombu_ssl_ca_certs { + warning('The kombu_ssl_ca_certs is deprecated and has no effect.') + } + + if $kombu_reconnect_delay { + warning('The kombu_reconnect_delay is deprecated and has no effect.') } sahara_config { - 'DEFAULT/rpc_backend': value => 'qpid'; - 'DEFAULT/qpid_hosts': value => '$qpid_hostname:$qpid_port'; + 'DEFAULT/rpc_backend': value => 'qpid'; + 'oslo_messaging_qpid/qpid_hosts': value => '$qpid_hostname:$qpid_port'; - 'DEFAULT/amqp_durable_queues': value => $durable_queues; - 'DEFAULT/qpid_hostname': value => $qpid_hostname; - 'DEFAULT/qpid_port': value => $qpid_port; - 'DEFAULT/qpid_username': value => $qpid_username; - 'DEFAULT/qpid_password': + 'oslo_messaging_qpid/amqp_durable_queues': value => $durable_queues; + 'oslo_messaging_qpid/qpid_hostname': value => $qpid_hostname; + 'oslo_messaging_qpid/qpid_port': value => $qpid_port; + 'oslo_messaging_qpid/qpid_username': value => $qpid_username; + 'oslo_messaging_qpid/qpid_password': value => $qpid_password, secret => true; - 'DEFAULT/qpid_sasl_mechanisms': value => $qpid_sasl_mechanisms; - 'DEFAULT/qpid_heartbeat': value => $qpid_heartbeat; - 'DEFAULT/qpid_protocol': value => $qpid_protocol; - 'DEFAULT/qpid_tcp_nodelay': value => $qpid_tcp_nodelay; - 'DEFAULT/qpid_receiver_capacity': value => $qpid_receiver_capacity; - 'DEFAULT/qpid_topology_version': value => $qpid_topology_version; - 'DEFAULT/notification_topics': value => $notification_topics; - 'DEFAULT/control_exchange': value => $control_exchange; + 'oslo_messaging_qpid/qpid_sasl_mechanisms': value => $qpid_sasl_mechanisms; + 'oslo_messaging_qpid/qpid_heartbeat': value => $qpid_heartbeat; + 'oslo_messaging_qpid/qpid_protocol': value => $qpid_protocol; + 'oslo_messaging_qpid/qpid_tcp_nodelay': value => $qpid_tcp_nodelay; + 'oslo_messaging_qpid/qpid_receiver_capacity': value => $qpid_receiver_capacity; + 'oslo_messaging_qpid/qpid_topology_version': value => $qpid_topology_version; + 'DEFAULT/notification_topics': value => $notification_topics; + 'DEFAULT/control_exchange': value => $control_exchange; } } diff --git a/sahara/manifests/notify/rabbitmq.pp b/sahara/manifests/notify/rabbitmq.pp index 387637474..2b5610647 100644 --- a/sahara/manifests/notify/rabbitmq.pp +++ b/sahara/manifests/notify/rabbitmq.pp @@ -104,6 +104,7 @@ $kombu_ssl_ca_certs = undef, $kombu_reconnect_delay = '1.0', ) { + if $rabbit_use_ssl { if $kombu_ssl_ca_certs { @@ -125,9 +126,9 @@ } if $kombu_ssl_version { - sahara_config { 'oslo_messaging_rabbit/kombu_ssl_version': value => $kombu_ssl_version; } + sahara_config { 'oslo_messaging_rabbit/kombu_ssl_version': value => $kombu_ssl_version; } } else { - sahara_config { 'oslo_messaging_rabbit/kombu_ssl_version': ensure => absent; } + sahara_config { 'oslo_messaging_rabbit/kombu_ssl_version': ensure => absent; } } } else { @@ -154,20 +155,20 @@ } sahara_config { - 'oslo_messaging_rabbit/rpc_backend': value => 'rabbit'; - 'DEFAULT/amqp_durable_queues': value => $durable_queues; - 'oslo_messaging_rabbit/rabbit_use_ssl': value => $rabbit_use_ssl; - 'oslo_messaging_rabbit/rabbit_userid': value => $rabbit_userid; + 'DEFAULT/rpc_backend': value => 'rabbit'; + 'oslo_messaging_rabbit/amqp_durable_queues': value => $durable_queues; + 'oslo_messaging_rabbit/rabbit_use_ssl': value => $rabbit_use_ssl; + 'oslo_messaging_rabbit/rabbit_userid': value => $rabbit_userid; 'oslo_messaging_rabbit/rabbit_password': value => $rabbit_password, secret => true; - 'oslo_messaging_rabbit/rabbit_login_method': value => $rabbit_login_method; - 'oslo_messaging_rabbit/rabbit_virtual_host': value => $rabbit_virtual_host; + 'oslo_messaging_rabbit/rabbit_login_method': value => $rabbit_login_method; + 'oslo_messaging_rabbit/rabbit_virtual_host': value => $rabbit_virtual_host; 'oslo_messaging_rabbit/rabbit_retry_interval': value => $rabbit_retry_interval; - 'oslo_messaging_rabbit/rabbit_retry_backoff': value => $rabbit_retry_backoff; - 'oslo_messaging_rabbit/rabbit_max_retries': value => $rabbit_max_retries; - 'DEFAULT/notification_topics': value => $notification_topics; - 'DEFAULT/control_exchange': value => $control_exchange; + 'oslo_messaging_rabbit/rabbit_retry_backoff': value => $rabbit_retry_backoff; + 'oslo_messaging_rabbit/rabbit_max_retries': value => $rabbit_max_retries; + 'DEFAULT/notification_topics': value => $notification_topics; + 'DEFAULT/control_exchange': value => $control_exchange; 'oslo_messaging_rabbit/kombu_reconnect_delay': value => $kombu_reconnect_delay; } } diff --git a/sahara/manifests/notify/zeromq.pp b/sahara/manifests/notify/zeromq.pp index d65441bcf..638ceaf47 100644 --- a/sahara/manifests/notify/zeromq.pp +++ b/sahara/manifests/notify/zeromq.pp @@ -32,11 +32,13 @@ # (Optional) TTL for zeromq messages. # Defaults to 30. # +# == DEPRECATED PARAMETERS +# # [*kombu_ssl_version*] # (optional) SSL version to use (valid only if SSL enabled). # Valid values are TLSv1, SSLv23 and SSLv3. SSLv2 may be # available on some distributions. -# Defaults to 'TLSv1' +# Defaults to undef # # [*kombu_ssl_keyfile*] # (Optional) SSL key file (valid only if SSL enabled). @@ -52,7 +54,7 @@ # # [*kombu_reconnect_delay*] # (Optional) Backoff on cancel notification (valid only if SSL enabled). -# Defaults to '1.0'; floating-point value. +# Defaults to undef # class sahara::notify::zeromq( $zeromq_bind_address = '*', @@ -62,47 +64,42 @@ $zeromq_ipc_dir = '/var/run/openstack', $zeromq_host = 'sahara', $cast_timeout = 30, - $kombu_ssl_version = 'TLSv1', + # DEPRECATED PARAMETERS + $kombu_ssl_version = undef, $kombu_ssl_keyfile = undef, $kombu_ssl_certfile = undef, $kombu_ssl_ca_certs = undef, - $kombu_reconnect_delay = '1.0', + $kombu_reconnect_delay = undef, ) { - if $kombu_ssl_keyfile or $kombu_ssl_certfile or $kombu_ssl_ca_certs { - if !$kombu_ssl_keyfile { - fail('kombu_ssl_keyfile must be set when using SSL in zeromq') - } - if !$kombu_ssl_certfile { - fail('kombu_ssl_certfile must be set when using SSL in zeromq') - } - if !$kombu_ssl_ca_certs { - fail('kombu_ca_certs must be set when using SSL in zeromq') - } - 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; - } - } 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; - } + + if $kombu_ssl_version { + warning('The kombu_ssl_version parameter is deprecated and has no effect.') + } + + if $kombu_ssl_keyfile { + warning('The kombu_ssl_keyfile parameter is deprecated and has no effect.') + } + + if $kombu_ssl_certfile { + warning('The kombu_ssl_certfile is deprecated and has no effect.') + } + + if $kombu_ssl_ca_certs { + warning('The kombu_ssl_ca_certs is deprecated and has no effect.') + } + + if $kombu_reconnect_delay { + warning('The kombu_reconnect_delay is deprecated and has no effect.') } sahara_config { - 'DEFAULT/rpc_backend': value => 'zmq'; - 'DEFAULT/rpc_zmq_bind_address': value => $zeromq_bind_address; - 'DEFAULT/rpc_zmq_port': value => $zeromq_port; - 'DEFAULT/rpc_zmq_contexts': value => $zeromq_contexts; + 'DEFAULT/rpc_backend': value => 'zmq'; + 'DEFAULT/rpc_zmq_bind_address': value => $zeromq_bind_address; + 'DEFAULT/rpc_zmq_port': value => $zeromq_port; + 'DEFAULT/rpc_zmq_contexts': value => $zeromq_contexts; 'DEFAULT/rpc_zmq_topic_backlog': value => $zeromq_topic_backlog; - 'DEFAULT/rpc_zmq_ipc_dir': value => $zeromq_ipc_dir; - 'DEFAULT/rpc_zmq_host': value => $zeromq_host; - 'DEFAULT/rpc_cast_timeout': value => $cast_timeout; + 'DEFAULT/rpc_zmq_ipc_dir': value => $zeromq_ipc_dir; + 'DEFAULT/rpc_zmq_host': value => $zeromq_host; + 'DEFAULT/rpc_cast_timeout': value => $cast_timeout; } } diff --git a/sahara/metadata.json b/sahara/metadata.json index bc78a7631..ae1144d90 100644 --- a/sahara/metadata.json +++ b/sahara/metadata.json @@ -1,10 +1,10 @@ { - "name": "stackforge-sahara", - "version": "5.0.0", - "author": "Red Hat and StackForge Contributors", + "name": "openstack-sahara", + "version": "6.0.0", + "author": "Red Hat and OpenStack Contributors", "summary": "Puppet module for OpenStack Sahara", "license": "Apache-2.0", - "source": "git://github.com/stackforge/puppet-sahara.git", + "source": "git://github.com/openstack/puppet-sahara.git", "project_page": "https://launchpad.net/puppet-sahara", "issues_url": "https://bugs.launchpad.net/puppet-sahara", "requirements": [ @@ -28,10 +28,10 @@ "description": "Installs and configures OpenStack Sahara (Data Processing).", "dependencies": [ { "name": "duritong/sysctl", "version_requirement": ">=0.0.1 <1.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, { "name": "puppetlabs/postgresql", "version_requirement": ">=3.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/sahara/spec/acceptance/basic_sahara_spec.rb b/sahara/spec/acceptance/basic_sahara_spec.rb index 180f34954..d5a8d5e76 100644 --- a/sahara/spec/acceptance/basic_sahara_spec.rb +++ b/sahara/spec/acceptance/basic_sahara_spec.rb @@ -80,7 +80,7 @@ class { '::keystone::endpoint': # Sahara resources class { '::sahara': database_connection => 'mysql://sahara:a_big_secret@127.0.0.1/sahara?charset=utf8', - keystone_password => 'a_big_secret', + admin_password => 'a_big_secret', } class { '::sahara::db::mysql': password => 'a_big_secret', diff --git a/sahara/spec/classes/sahara_init_spec.rb b/sahara/spec/classes/sahara_init_spec.rb index 7cb52c1c0..87c870f71 100644 --- a/sahara/spec/classes/sahara_init_spec.rb +++ b/sahara/spec/classes/sahara_init_spec.rb @@ -7,7 +7,7 @@ let :params do { - :keystone_password => 'secrete' + :admin_password => 'secrete' } end @@ -18,6 +18,64 @@ it { is_expected.to contain_exec('sahara-dbmanage') } end + shared_examples_for 'sahara config' do + context 'with default params' do + it { is_expected.to contain_sahara_config('DEFAULT/use_neutron').with_value('false') } + it { is_expected.to contain_sahara_config('DEFAULT/use_floating_ips').with_value('true') } + it { is_expected.to contain_sahara_config('DEFAULT/host').with_value('0.0.0.0') } + it { is_expected.to contain_sahara_config('DEFAULT/port').with_value('8386') } + it { is_expected.to contain_sahara_config('keystone_authtoken/auth_uri').with_value('http://127.0.0.1:5000/v2.0/') } + it { is_expected.to contain_sahara_config('keystone_authtoken/identity_uri').with_value('http://127.0.0.1:35357/') } + it { is_expected.to contain_sahara_config('keystone_authtoken/admin_user').with_value('admin') } + it { is_expected.to contain_sahara_config('keystone_authtoken/admin_tenant_name').with_value('admin') } + it { is_expected.to contain_sahara_config('keystone_authtoken/admin_password').with_value('secrete').with_secret(true) } + end + + context 'with passing params' do + let :params do { + :use_neutron => 'true', + :host => 'localhost', + :port => '8387', + :auth_uri => 'http://8.8.8.8:5000/v2.0/', + :identity_uri => 'http://8.8.8.8:35357/', + :admin_user => 'sahara', + :admin_tenant_name => 'sahara-tenant', + :admin_password => 'new_password', + } + end + + it { is_expected.to contain_sahara_config('DEFAULT/use_neutron').with_value('true') } + it { is_expected.to contain_sahara_config('DEFAULT/host').with_value('localhost') } + it { is_expected.to contain_sahara_config('DEFAULT/port').with_value('8387') } + it { is_expected.to contain_sahara_config('keystone_authtoken/auth_uri').with_value('http://8.8.8.8:5000/v2.0/') } + it { is_expected.to contain_sahara_config('keystone_authtoken/identity_uri').with_value('http://8.8.8.8:35357/') } + it { is_expected.to contain_sahara_config('keystone_authtoken/admin_user').with_value('sahara') } + it { is_expected.to contain_sahara_config('keystone_authtoken/admin_tenant_name').with_value('sahara-tenant') } + it { is_expected.to contain_sahara_config('keystone_authtoken/admin_password').with_value('new_password').with_secret(true) } + end + + context 'with deprecated params' do + let :params do { + :service_host => 'localhost', + :service_port => '8387', + :keystone_url => 'http://8.8.8.8:5000/v2.0/', + :identity_url => 'http://8.8.8.8:35357/', + :keystone_username => 'sahara', + :keystone_tenant => 'sahara-tenant', + :keystone_password => 'new_password', + } + end + + it { is_expected.to contain_sahara_config('DEFAULT/host').with_value('localhost') } + it { is_expected.to contain_sahara_config('DEFAULT/port').with_value('8387') } + it { is_expected.to contain_sahara_config('keystone_authtoken/auth_uri').with_value('http://8.8.8.8:5000/v2.0/') } + it { is_expected.to contain_sahara_config('keystone_authtoken/identity_uri').with_value('http://8.8.8.8:35357/') } + it { is_expected.to contain_sahara_config('keystone_authtoken/admin_user').with_value('sahara') } + it { is_expected.to contain_sahara_config('keystone_authtoken/admin_tenant_name').with_value('sahara-tenant') } + it { is_expected.to contain_sahara_config('keystone_authtoken/admin_password').with_value('new_password').with_secret(true) } + end + end + shared_examples_for 'sahara logging' do context 'with syslog disabled' do it { is_expected.to contain_sahara_config('DEFAULT/use_syslog').with_value(false) } @@ -62,6 +120,7 @@ end it_configures 'sahara' + it_configures 'sahara config' it_configures 'sahara logging' it_behaves_like 'generic sahara service', { @@ -76,6 +135,7 @@ end it_configures 'sahara' + it_configures 'sahara config' it_configures 'sahara logging' it_behaves_like 'generic sahara service', { diff --git a/sahara/spec/classes/sahara_notify_qpid_spec.rb b/sahara/spec/classes/sahara_notify_qpid_spec.rb index fa645beef..3cb51fcb0 100644 --- a/sahara/spec/classes/sahara_notify_qpid_spec.rb +++ b/sahara/spec/classes/sahara_notify_qpid_spec.rb @@ -11,12 +11,12 @@ {:qpid_password => 'pass'} end - it { is_expected.to contain_sahara_config('DEFAULT/qpid_username').with_value('guest') } - it { is_expected.to contain_sahara_config('DEFAULT/qpid_password').with_value('pass') } - it { is_expected.to contain_sahara_config('DEFAULT/qpid_password').with_value(params[:qpid_password]).with_secret(true) } - it { is_expected.to contain_sahara_config('DEFAULT/qpid_hostname').with_value('localhost') } - it { is_expected.to contain_sahara_config('DEFAULT/qpid_port').with_value('5672') } - it { is_expected.to contain_sahara_config('DEFAULT/qpid_protocol').with_value('tcp') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_username').with_value('guest') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_password').with_value('pass') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_password').with_value(params[:qpid_password]).with_secret(true) } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_hostname').with_value('localhost') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_port').with_value('5672') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_protocol').with_value('tcp') } end describe 'when passing params' do @@ -28,10 +28,10 @@ :qpid_port => '5673' } end - it { is_expected.to contain_sahara_config('DEFAULT/qpid_username').with_value('guest2') } - it { is_expected.to contain_sahara_config('DEFAULT/qpid_hostname').with_value('localhost2') } - it { is_expected.to contain_sahara_config('DEFAULT/qpid_port').with_value('5673') } - it { is_expected.to contain_sahara_config('DEFAULT/qpid_protocol').with_value('tcp') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_username').with_value('guest2') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_hostname').with_value('localhost2') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_port').with_value('5673') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_protocol').with_value('tcp') } end describe 'when configuring with ssl' do @@ -42,17 +42,11 @@ :qpid_hostname => 'localhost3', :qpid_port => '5671', :qpid_protocol => 'ssl', - :kombu_ssl_keyfile => '/srv/sahara_ssl.key', - :kombu_ssl_certfile => '/srv/sahara_ssl.crt', - :kombu_ssl_ca_certs => '/srv/cacert', } end - it { is_expected.to contain_sahara_config('DEFAULT/qpid_username').with_value('guest3') } - it { is_expected.to contain_sahara_config('DEFAULT/qpid_hostname').with_value('localhost3') } - it { is_expected.to contain_sahara_config('DEFAULT/qpid_port').with_value('5671') } - it { is_expected.to contain_sahara_config('DEFAULT/qpid_protocol').with_value('ssl') } - it { is_expected.to contain_sahara_config('DEFAULT/kombu_ssl_keyfile').with_value('/srv/sahara_ssl.key') } - it { is_expected.to contain_sahara_config('DEFAULT/kombu_ssl_certfile').with_value('/srv/sahara_ssl.crt') } - it { is_expected.to contain_sahara_config('DEFAULT/kombu_ssl_ca_certs').with_value('/srv/cacert') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_username').with_value('guest3') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_hostname').with_value('localhost3') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_port').with_value('5671') } + it { is_expected.to contain_sahara_config('oslo_messaging_qpid/qpid_protocol').with_value('ssl') } end end diff --git a/sahara/spec/classes/sahara_notify_rabbitmq_spec.rb b/sahara/spec/classes/sahara_notify_rabbitmq_spec.rb index 66f6abd66..acf1c31ee 100644 --- a/sahara/spec/classes/sahara_notify_rabbitmq_spec.rb +++ b/sahara/spec/classes/sahara_notify_rabbitmq_spec.rb @@ -17,7 +17,7 @@ it { is_expected.to contain_sahara_config('oslo_messaging_rabbit/rabbit_port').with_value('5672') } it { is_expected.to contain_sahara_config('oslo_messaging_rabbit/rabbit_hosts').with_value('localhost:5672') } it { is_expected.to contain_sahara_config('oslo_messaging_rabbit/rabbit_ha_queues').with_value('false') } - it { is_expected.to contain_sahara_config('DEFAULT/amqp_durable_queues').with_value('false') } + it { is_expected.to contain_sahara_config('oslo_messaging_rabbit/amqp_durable_queues').with_value('false') } it { is_expected.to contain_sahara_config('oslo_messaging_rabbit/rabbit_virtual_host').with_value('/') } it { is_expected.to contain_sahara_config('DEFAULT/control_exchange').with_value('openstack') } it { is_expected.to contain_sahara_config('DEFAULT/notification_topics').with_value('notifications') } @@ -101,7 +101,7 @@ it { is_expected.to contain_sahara_config('oslo_messaging_rabbit/rabbit_host').with_value('localhost2') } it { is_expected.to contain_sahara_config('oslo_messaging_rabbit/rabbit_port').with_value('5673') } it { is_expected.to contain_sahara_config('oslo_messaging_rabbit/rabbit_hosts').with_value('localhost2:5673') } - it { is_expected.to contain_sahara_config('DEFAULT/amqp_durable_queues').with_value('true') } + it { is_expected.to contain_sahara_config('oslo_messaging_rabbit/amqp_durable_queues').with_value('true') } end describe 'when passing params for multiple rabbit hosts' do @@ -120,13 +120,4 @@ it { is_expected.to_not contain_sahara_config('oslo_messaging_rabbit/rabbit_host') } end - describe 'when using deprecated params' do - let :params do - { - :durable_queues => true, - :rabbit_password => 'pass' - } - end - it { is_expected.to contain_sahara_config('DEFAULT/amqp_durable_queues').with_value('true') } - end end diff --git a/sahara/spec/spec_helper_acceptance.rb b/sahara/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/sahara/spec/spec_helper_acceptance.rb +++ b/sahara/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/swift/CHANGELOG.md b/swift/CHANGELOG.md index 96f997976..5feeae935 100644 --- a/swift/CHANGELOG.md +++ b/swift/CHANGELOG.md @@ -1,3 +1,37 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a backwards-incompatible major release for OpenStack Kilo. + +####Backwards-incompatible changes +- Remove deprecated class (swift::proxy::proxy-logging) +- Use keystonemiddleware instead of client +- Removal of SSH Components + +####Features +- Puppet 4.x support +- Allow setting reseller_prefix for keystone filter +- Add manage_service feature +- Refactorise Keystone resources management +- Add seed parameter to ringbuilder::rebalance +- Add support for identity_uri +- Provide a mean to change the default rsync chmod +- Add ability to override service name for service catalog +- Add node_timeout parameter for proxy-server.conf +- Full ipv6 support +- Tag all Swift packages +- Notify services if swift.conf is modified +- Add rsyslog logging support to object-server +- Handle both string and array for memcache param +- Introduce public_url(_s3), internal_url(_s3) and admin_url(_s3) +- Add max_header_size field for PKI tokens + +####Bugfixes +- Fix swift::proxy::ceilometer + +####Maintenance +- Acceptance tests with Beaker + ##2015-06-17 - 5.1.0 ###Summary diff --git a/swift/README.md b/swift/README.md index 54993526e..2d62614bb 100644 --- a/swift/README.md +++ b/swift/README.md @@ -1,7 +1,7 @@ swift ======= -5.1.0 - 2014.2 - Juno +6.0.0 - 2015.1 - Kilo #### Table of Contents diff --git a/swift/metadata.json b/swift/metadata.json index 037d324d5..931aa1fc0 100644 --- a/swift/metadata.json +++ b/swift/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-swift", - "version": "5.1.0", + "name": "openstack-swift", + "version": "6.0.0", "author": "Puppet Labs and OpenStack Contributors", "summary": "Puppet module for OpenStack Swift", "license": "Apache-2.0", @@ -32,7 +32,7 @@ "description": "Installs and configures OpenStack Swift (Object Storage).", "dependencies": [ { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/rsync", "version_requirement": ">=0.2.0 <1.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, { "name": "puppetlabs/xinetd", "version_requirement": ">=1.0.1 <2.0.0" }, diff --git a/swift/spec/spec_helper_acceptance.rb b/swift/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/swift/spec/spec_helper_acceptance.rb +++ b/swift/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/tempest/CHANGELOG.md b/tempest/CHANGELOG.md index 9cfa27941..42b7891f2 100644 --- a/tempest/CHANGELOG.md +++ b/tempest/CHANGELOG.md @@ -1,3 +1,17 @@ +##2015-07-08 - 6.0.0 +###Summary + +This is a major release for OpenStack Kilo. + +####Features +- Puppet 4.x support +- Allow to activate Ceilometer tests +- Allow to not manage Tempest code in Puppet +- Implement more Tempest options + +####Maintenance +- Acceptance tests with Beaker + ##2015-06-17 - 5.1.0 ###Summary diff --git a/tempest/README.markdown b/tempest/README.markdown index 63b4c7795..5a082493f 100644 --- a/tempest/README.markdown +++ b/tempest/README.markdown @@ -1,7 +1,7 @@ Tempest ======= -5.1.0 - 2014.2 - Juno +6.0.0 - 2015.1 - Kilo Module for installing and configuring tempest. diff --git a/tempest/manifests/config.pp b/tempest/manifests/config.pp new file mode 100644 index 000000000..ab137b750 --- /dev/null +++ b/tempest/manifests/config.pp @@ -0,0 +1,30 @@ +# == Class: tempest::config +# +# This class is used to manage arbitrary Tempest configurations. +# +# === Parameters +# +# [*tempest_config*] +# (optional) Allow configuration of arbitrary Tempest configurations. +# The value is an hash of tempest_config resources. Example: +# { 'DEFAULT/foo' => { value => 'fooValue'}, +# 'DEFAULT/bar' => { value => 'barValue'} +# } +# In yaml format, Example: +# tempest_config: +# DEFAULT/foo: +# value: fooValue +# DEFAULT/bar: +# value: barValue +# +# NOTE: The configuration MUST NOT be already handled by this module +# or Puppet catalog compilation will fail with duplicate resources. +# +class tempest::config ( + $tempest_config = {}, +) { + + validate_hash($tempest_config) + + create_resources('tempest_config', $tempest_config) +} diff --git a/tempest/manifests/init.pp b/tempest/manifests/init.pp index e60520a9f..82917102d 100644 --- a/tempest/manifests/init.pp +++ b/tempest/manifests/init.pp @@ -32,6 +32,7 @@ # tempest.conf parameters # $identity_uri = undef, + $identity_uri_v3 = undef, $cli_dir = undef, $lock_path = '/var/lib/tempest', $debug = false, @@ -52,6 +53,7 @@ $admin_password = undef, $admin_tenant_name = undef, $admin_role = undef, + $admin_domain_name = undef, # image information $image_ref = undef, $image_ref_alt = undef, @@ -80,6 +82,7 @@ $swift_available = false, $keystone_v2 = true, $keystone_v3 = true, + $auth_version = 'v2', ) { include '::tempest::params' @@ -160,13 +163,16 @@ 'identity/admin_tenant_name': value => $admin_tenant_name; 'identity/admin_username': value => $admin_username; 'identity/admin_role': value => $admin_role; + 'identity/admin_domain_name': value => $admin_domain_name; 'identity/alt_password': value => $alt_password, secret => true; 'identity/alt_tenant_name': value => $alt_tenant_name; 'identity/alt_username': value => $alt_username; 'identity/password': value => $password, secret => true; 'identity/tenant_name': value => $tenant_name; 'identity/uri': value => $identity_uri; + 'identity/uri_v3': value => $identity_uri_v3; 'identity/username': value => $username; + 'identity/auth_version': value => $auth_version; 'identity-feature-enabled/api_v2': value => $keystone_v2; 'identity-feature-enabled/api_v3': value => $keystone_v3; 'network/public_network_id': value => $public_network_id; diff --git a/tempest/metadata.json b/tempest/metadata.json index a07e05e7a..08973e2a6 100644 --- a/tempest/metadata.json +++ b/tempest/metadata.json @@ -1,6 +1,6 @@ { - "name": "stackforge-tempest", - "version": "5.1.0", + "name": "openstack-tempest", + "version": "6.0.0", "author": "OpenStack Contributors", "summary": "Puppet module for OpenStack Tempest", "license": "Apache-2.0", diff --git a/tempest/spec/classes/tempest_config_spec.rb b/tempest/spec/classes/tempest_config_spec.rb new file mode 100644 index 000000000..3deeee021 --- /dev/null +++ b/tempest/spec/classes/tempest_config_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe 'tempest::config' do + + let :params do + { :tempest_config => { + 'DEFAULT/foo' => { 'value' => 'fooValue' }, + 'DEFAULT/bar' => { 'value' => 'barValue' }, + 'DEFAULT/baz' => { 'ensure' => 'absent' } + } + } + end + + it 'configures arbitrary tempest configurations' do + is_expected.to contain_tempest_config('DEFAULT/foo').with_value('fooValue') + is_expected.to contain_tempest_config('DEFAULT/bar').with_value('barValue') + is_expected.to contain_tempest_config('DEFAULT/baz').with_ensure('absent') + end + +end diff --git a/tempest/spec/classes/tempest_spec.rb b/tempest/spec/classes/tempest_spec.rb index 38cec0baa..eaafbd026 100644 --- a/tempest/spec/classes/tempest_spec.rb +++ b/tempest/spec/classes/tempest_spec.rb @@ -162,10 +162,12 @@ is_expected.to contain_tempest_config('compute/resize_available').with(:value => nil) is_expected.to contain_tempest_config('compute/allow_tenant_isolation').with(:value => nil) is_expected.to contain_tempest_config('identity/admin_password').with(:value => nil) + is_expected.to contain_tempest_config('identity/admin_domain_name').with(:value => nil) is_expected.to contain_tempest_config('identity/admin_password').with_secret( true ) is_expected.to contain_tempest_config('identity/admin_tenant_name').with(:value => nil) is_expected.to contain_tempest_config('identity/admin_username').with(:value => nil) is_expected.to contain_tempest_config('identity/admin_role').with(:value => nil) + is_expected.to contain_tempest_config('identity/auth_version').with(:value => 'v2') is_expected.to contain_tempest_config('identity/alt_password').with(:value => nil) is_expected.to contain_tempest_config('identity/alt_password').with_secret( true ) is_expected.to contain_tempest_config('identity/alt_tenant_name').with(:value => nil) @@ -174,6 +176,7 @@ is_expected.to contain_tempest_config('identity/password').with_secret( true ) is_expected.to contain_tempest_config('identity/tenant_name').with(:value => nil) is_expected.to contain_tempest_config('identity/uri').with(:value => nil) + is_expected.to contain_tempest_config('identity/uri_v3').with(:value => nil) is_expected.to contain_tempest_config('identity/username').with(:value => nil) is_expected.to contain_tempest_config('identity-feature-enabled/api_v2').with(:value => true) is_expected.to contain_tempest_config('identity-feature-enabled/api_v3').with(:value => true) diff --git a/tempest/spec/spec_helper_acceptance.rb b/tempest/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/tempest/spec/spec_helper_acceptance.rb +++ b/tempest/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/trove/CHANGELOG.md b/trove/CHANGELOG.md new file mode 100644 index 000000000..f8faa92a0 --- /dev/null +++ b/trove/CHANGELOG.md @@ -0,0 +1,4 @@ +##2015-07-08 - 6.0.0 +###Summary + +- Initial release of the puppet-trove module diff --git a/trove/README.md b/trove/README.md index 06271ae03..98b235006 100644 --- a/trove/README.md +++ b/trove/README.md @@ -1,6 +1,8 @@ puppet-trove ============= +6.0.0 - 2015.1 - Kilo + #### Table of Contents 1. [Overview - What is the trove module?](#overview) diff --git a/trove/manifests/config.pp b/trove/manifests/config.pp new file mode 100644 index 000000000..93d63136d --- /dev/null +++ b/trove/manifests/config.pp @@ -0,0 +1,84 @@ +# +# Copyright (C) 2015 UnitedStack +# +# Author: Xingchao Yu +# +# 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: trove::config +# +# This class is used to manage arbitrary trove configurations. +# +# === Parameters +# +# [*trove_config*] +# (optional) Allow configuration of arbitrary trove configurations. +# The value is an hash of trove_config resources. +# Defaults to {} +# +# [*trove_taskmanager_config*] +# (optional) Allow configuration of arbitrary trove taskmanager configurations. +# The value is an hash of trove_taskmanager_config resources. +# Defaults to {} +# +# [*trove_conductor_config*] +# (optional) Allow configuration of arbitrary trove conductor configurations. +# The value is an hash of trove_conductor_config resources. +# Defaults to {} +# +# [*trove_guestagent_config*] +# (optional) Allow configuration of arbitrary trove guestagent configurations. +# The value is an hash of trove_guestagent_config resources. +# Defaults to {} +# +# [*trove_api_paste_ini*] +# (optional) Allow configuration of arbitrary trove paste api configurations. +# The value is an hash of trove_paste_api_ini resources. +# Defaults to {} +# +# Example: +# { 'DEFAULT/foo' => { value => 'fooValue'}, +# 'DEFAULT/bar' => { value => 'barValue'} +# } +# +# In yaml format, Example: +# trove_config: +# DEFAULT/foo: +# value: fooValue +# DEFAULT/bar: +# value: barValue +# +# NOTE: The configuration MUST NOT be already handled by this module +# or Puppet catalog compilation will fail with duplicate resources. +# +class trove::config ( + $trove_config = {}, + $trove_taskmanager_config = {}, + $trove_conductor_config = {}, + $trove_guestagent_config = {}, + $trove_api_paste_ini = {}, +) { + + validate_hash($trove_config) + validate_hash($trove_taskmanager_config) + validate_hash($trove_conductor_config) + validate_hash($trove_guestagent_config) + validate_hash($trove_api_paste_ini) + + create_resources('trove_config', $trove_config) + create_resources('trove_taskmanager_config', $trove_taskmanager_config) + create_resources('trove_conductor_config', $trove_conductor_config) + create_resources('trove_guestagent_config', $trove_guestagent_config) + create_resources('trove_api_paste_ini', $trove_api_paste_ini) + +} diff --git a/trove/manifests/keystone/auth.pp b/trove/manifests/keystone/auth.pp index b39761ca7..b76309ac5 100644 --- a/trove/manifests/keystone/auth.pp +++ b/trove/manifests/keystone/auth.pp @@ -195,8 +195,10 @@ $real_service_name = pick($service_name, $auth_name) - Keystone_user_role["${auth_name}@${tenant}"] ~> Service <| name == 'trove-server' |> - Keystone_endpoint["${region}/${real_service_name}"] ~> Service <| name == 'trove-server' |> + Keystone_user_role["${auth_name}@${tenant}"] ~> Service <| name == 'trove-server' |> + + Keystone_endpoint<| title == "${region}/${real_service_name}" |> + ~> Service <| name == 'trove-server' |> keystone::resource::service_identity { 'trove': configure_user => true, diff --git a/trove/metadata.json b/trove/metadata.json index e5d06d86d..b635a4585 100644 --- a/trove/metadata.json +++ b/trove/metadata.json @@ -1,10 +1,10 @@ { - "name": "stackforge-trove", - "version": "5.0.0", - "author": "eNovance and StackForge Contributors", + "name": "openstack-trove", + "version": "6.0.0", + "author": "eNovance and OpenStack Contributors", "summary": "Puppet module for OpenStack Trove", "license": "Apache-2.0", - "source": "git://github.com/stackforge/puppet-trove.git", + "source": "git://github.com/openstack/puppet-trove.git", "project_page": "https://launchpad.net/puppet-trove", "issues_url": "https://bugs.launchpad.net/puppet-trove", "requirements": [ @@ -32,8 +32,8 @@ "description": "Installs and configures OpenStack Trove (Database service).", "dependencies": [ { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/trove/spec/classes/trove_config_spec.rb b/trove/spec/classes/trove_config_spec.rb new file mode 100644 index 000000000..233945b9b --- /dev/null +++ b/trove/spec/classes/trove_config_spec.rb @@ -0,0 +1,63 @@ +require 'spec_helper' + +describe 'trove::config' do + + let :params do + { :trove_config => { + 'DEFAULT/foo' => { 'value' => 'fooValue' }, + 'DEFAULT/bar' => { 'value' => 'barValue' }, + 'DEFAULT/baz' => { 'ensure' => 'absent' } + }, + :trove_taskmanager_config => { + 'DEFAULT/foo2' => { 'value' => 'fooValue' }, + 'DEFAULT/bar2' => { 'value' => 'barValue' }, + 'DEFAULT/baz2' => { 'ensure' => 'absent' } + }, + :trove_conductor_config => { + 'DEFAULT/foo2' => { 'value' => 'fooValue' }, + 'DEFAULT/bar2' => { 'value' => 'barValue' }, + 'DEFAULT/baz2' => { 'ensure' => 'absent' } + }, + :trove_guestagent_config => { + 'DEFAULT/foo2' => { 'value' => 'fooValue' }, + 'DEFAULT/bar2' => { 'value' => 'barValue' }, + 'DEFAULT/baz2' => { 'ensure' => 'absent' } + }, + :trove_api_paste_ini => { + 'DEFAULT/foo2' => { 'value' => 'fooValue' }, + 'DEFAULT/bar2' => { 'value' => 'barValue' }, + 'DEFAULT/baz2' => { 'ensure' => 'absent' } + } + } + end + + it 'configures arbitrary trove configurations' do + is_expected.to contain_trove_config('DEFAULT/foo').with_value('fooValue') + is_expected.to contain_trove_config('DEFAULT/bar').with_value('barValue') + is_expected.to contain_trove_config('DEFAULT/baz').with_ensure('absent') + end + + it 'configures arbitrary trove taskmanager configurations' do + is_expected.to contain_trove_taskmanager_config('DEFAULT/foo2').with_value('fooValue') + is_expected.to contain_trove_taskmanager_config('DEFAULT/bar2').with_value('barValue') + is_expected.to contain_trove_taskmanager_config('DEFAULT/baz2').with_ensure('absent') + end + + it 'configures arbitrary trove conductor configurations' do + is_expected.to contain_trove_conductor_config('DEFAULT/foo2').with_value('fooValue') + is_expected.to contain_trove_conductor_config('DEFAULT/bar2').with_value('barValue') + is_expected.to contain_trove_conductor_config('DEFAULT/baz2').with_ensure('absent') + end + + it 'configures arbitrary trove guestagent configurations' do + is_expected.to contain_trove_guestagent_config('DEFAULT/foo2').with_value('fooValue') + is_expected.to contain_trove_guestagent_config('DEFAULT/bar2').with_value('barValue') + is_expected.to contain_trove_guestagent_config('DEFAULT/baz2').with_ensure('absent') + end + + it 'configures arbitrary trove api-paste configurations' do + is_expected.to contain_trove_api_paste_ini('DEFAULT/foo2').with_value('fooValue') + is_expected.to contain_trove_api_paste_ini('DEFAULT/bar2').with_value('barValue') + is_expected.to contain_trove_api_paste_ini('DEFAULT/baz2').with_ensure('absent') + end +end diff --git a/trove/spec/classes/trove_keystone_auth_spec.rb b/trove/spec/classes/trove_keystone_auth_spec.rb index 63204e9d5..dde648f47 100644 --- a/trove/spec/classes/trove_keystone_auth_spec.rb +++ b/trove/spec/classes/trove_keystone_auth_spec.rb @@ -130,4 +130,12 @@ it { is_expected.to contain_keystone_endpoint('RegionOne/trove_service') } end + describe 'when disabling endpoint configuration' do + let :params do + { :configure_endpoint => false, + :password => 'trove_password' } + end + + it { is_expected.to_not contain_keystone_endpoint('RegionOne/neutron') } + end end diff --git a/trove/spec/spec_helper_acceptance.rb b/trove/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/trove/spec/spec_helper_acceptance.rb +++ b/trove/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" diff --git a/tuskar/CHANGELOG.md b/tuskar/CHANGELOG.md new file mode 100644 index 000000000..2c923da3c --- /dev/null +++ b/tuskar/CHANGELOG.md @@ -0,0 +1,4 @@ +##2015-07-08 - 6.0.0 +###Summary + +- Initial release of the puppet-tuskar module diff --git a/tuskar/README.md b/tuskar/README.md index cc951f880..ce38bab2d 100644 --- a/tuskar/README.md +++ b/tuskar/README.md @@ -1,6 +1,8 @@ puppet-tuskar ============= +6.0.0 - 2015.1 - Kilo + #### Table of Contents 1. [Overview - What is the tuskar module?](#overview) diff --git a/tuskar/metadata.json b/tuskar/metadata.json index 74adfe2fe..b6af43303 100644 --- a/tuskar/metadata.json +++ b/tuskar/metadata.json @@ -1,10 +1,10 @@ { - "name": "stackforge-tuskar", - "version": "5.0.0", - "author": "eNovance and StackForge Contributors", + "name": "openstack-tuskar", + "version": "6.0.0", + "author": "eNovance and OpenStack Contributors", "summary": "Puppet module for OpenStack Tuskar", "license": "Apache-2.0", - "source": "git://github.com/stackforge/puppet-tuskar.git", + "source": "git://github.com/openstack/puppet-tuskar.git", "project_page": "https://launchpad.net/puppet-tuskar", "issues_url": "https://bugs.launchpad.net/puppet-tuskar", "requirements": [ @@ -32,8 +32,8 @@ "description": "Installs and configures OpenStack Tuskar (Management service).", "dependencies": [ { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, - { "name": "stackforge/keystone", "version_requirement": ">=5.0.0 <6.0.0" }, + { "name": "openstack/keystone", "version_requirement": ">=6.0.0 <7.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" }, - { "name": "stackforge/openstacklib", "version_requirement": ">=5.0.0 <6.0.0" } + { "name": "openstack/openstacklib", "version_requirement": ">=6.0.0 <7.0.0" } ] } diff --git a/vswitch/CHANGELOG.md b/vswitch/CHANGELOG.md new file mode 100644 index 000000000..a9635a2a4 --- /dev/null +++ b/vswitch/CHANGELOG.md @@ -0,0 +1,14 @@ +##2015-07-08 - 2.0.0 +###Summary + +This is a major release for OpenStack Kilo but contains no API-breaking +changes. + + +####Features +- Puppet 4.x support +- make dkms on Debian/Ubuntu optional + +####Maintenance +- Acceptance tests with Beaker +- Fix spec tests for RSpec 3.x and Puppet 4.x diff --git a/vswitch/README.md b/vswitch/README.md index 449bebe4b..94a5c3c7d 100644 --- a/vswitch/README.md +++ b/vswitch/README.md @@ -1,7 +1,7 @@ VSwitch ======= -1.1.0 - 2014.2 - Juno +2.0.0 - 2015.1 - Kilo A Puppet module providing things for vSwitches. At the moment OVS is the only one I've added but please feel free to contribute new providers through diff --git a/vswitch/metadata.json b/vswitch/metadata.json index 9dc0d6132..4d963a466 100644 --- a/vswitch/metadata.json +++ b/vswitch/metadata.json @@ -1,7 +1,7 @@ { - "name": "stackforge-vswitch", - "version": "1.1.0", - "author": "Endre Karlson, Dan Bode and StackForge Contributors", + "name": "openstack-vswitch", + "version": "2.0.0", + "author": "Endre Karlson, Dan Bode and OpenStack Contributors", "license": "Apache-2.0", "source": "git://github.com/openstack/puppet-vswitch.git", "project_page": "https://launchpad.net/puppet-vswitch", diff --git a/vswitch/spec/spec_helper_acceptance.rb b/vswitch/spec/spec_helper_acceptance.rb index 429e807c4..144b31e3f 100644 --- a/vswitch/spec/spec_helper_acceptance.rb +++ b/vswitch/spec/spec_helper_acceptance.rb @@ -38,7 +38,7 @@ zuul_clone_cmd += "git://git.openstack.org #{repo}" on host, zuul_clone_cmd else - on host, "git clone https://git.openstack.org/#{repo} #{repo}" + on host, "git clone -b stable/kilo https://git.openstack.org/#{repo} #{repo}" end on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" From ede2198f5ed34fd67ebd4554a75892877ccd636d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=A1gr?= Date: Tue, 22 Sep 2015 15:30:23 +0200 Subject: [PATCH 03/54] v3 update this commit is setting modules to following state: heat - old commit: 108e9b092698e423840cef6ac24233313b9470b1 - new commit: 3ced80f2eb6fc8a0694e8586c212d1a3ec5a3bdc keystone - old commit: 5f9080f3adf14921f025038533bfcb9ebdee564c - new commit: 1fb920c38df80a75779ea34b5181534ff9207738 Change-Id: Id1f323d4b7b5cd67590ae91dd5affa9e00c76f92 --- Puppetfile | 4 +- .../provider/heat_domain_id_setter/ruby.rb | 189 --------------- heat/lib/puppet/type/heat_domain_id_setter.rb | 31 --- heat/manifests/keystone/domain.pp | 100 ++++---- heat/spec/acceptance/basic_heat_spec.rb | 8 +- .../spec/classes/heat_keystone_domain_spec.rb | 51 ++-- .../heat_domain_id_setter/heat_spec.rb | 177 -------------- keystone/lib/puppet/provider/keystone.rb | 139 ++++++----- .../provider/keystone_domain/openstack.rb | 1 + .../provider/keystone_tenant/openstack.rb | 1 + .../provider/keystone_user/openstack.rb | 27 ++- keystone/spec/classes/keystone_spec.rb | 1 - keystone/spec/spec_helper.rb | 13 + .../keystone_domain/openstack_spec.rb | 42 ++-- keystone/spec/unit/provider/keystone_spec.rb | 228 +++++++++++++++--- .../keystone_tenant/openstack_spec.rb | 16 +- .../provider/keystone_user/openstack_spec.rb | 132 +++++----- .../keystone_user_role/openstack_spec.rb | 6 + 18 files changed, 491 insertions(+), 675 deletions(-) delete mode 100644 heat/lib/puppet/provider/heat_domain_id_setter/ruby.rb delete mode 100644 heat/lib/puppet/type/heat_domain_id_setter.rb delete mode 100644 heat/spec/unit/provider/heat_domain_id_setter/heat_spec.rb diff --git a/Puppetfile b/Puppetfile index d436cb192..8c1235bb2 100644 --- a/Puppetfile +++ b/Puppetfile @@ -59,7 +59,7 @@ mod 'haproxy', :git => 'https://github.com/puppetlabs/puppetlabs-haproxy.git' mod 'heat', - :commit => '108e9b092698e423840cef6ac24233313b9470b1', + :commit => '3ced80f2eb6fc8a0694e8586c212d1a3ec5a3bdc', :git => 'https://github.com/openstack/puppet-heat.git' mod 'horizon', @@ -83,7 +83,7 @@ mod 'keepalived', :git => 'https://github.com/Unyonsys/puppet-module-keepalived.git' mod 'keystone', - :commit => '5f9080f3adf14921f025038533bfcb9ebdee564c', + :commit => '1fb920c38df80a75779ea34b5181534ff9207738', :git => 'https://github.com/openstack/puppet-keystone.git' mod 'manila', diff --git a/heat/lib/puppet/provider/heat_domain_id_setter/ruby.rb b/heat/lib/puppet/provider/heat_domain_id_setter/ruby.rb deleted file mode 100644 index 12ce71acf..000000000 --- a/heat/lib/puppet/provider/heat_domain_id_setter/ruby.rb +++ /dev/null @@ -1,189 +0,0 @@ -## NB: This must work with Ruby 1.8! - -# This provider permits the stack_user_domain parameter in heat.conf -# to be set by providing a domain_name to the Puppet module and -# using the Keystone REST API to translate the name into the corresponding -# UUID. -# -# This requires that tenant names be unique. If there are multiple matches -# for a given tenant name, this provider will raise an exception. - -require 'rubygems' -require 'net/http' -require 'json' - -class KeystoneError < Puppet::Error -end - -class KeystoneConnectionError < KeystoneError -end - -class KeystoneAPIError < KeystoneError -end - -# Provides common request handling semantics to the other methods in -# this module. -# -# +req+:: -# An HTTPRequest object -# +url+:: -# A parsed URL (returned from URI.parse) -def handle_request(req, url) - begin - # There is issue with ipv6 where address has to be in brackets, this causes the - # underlying ruby TCPSocket to fail. Net::HTTP.new will fail without brackets on - # joining the ipv6 address with :port or passing brackets to TCPSocket. It was - # found that if we use Net::HTTP.start with url.hostname the incriminated code - # won't be hit. - use_ssl = url.scheme == "https" ? true : false - res = Net::HTTP.start(url.hostname, url.port, {:use_ssl => use_ssl}) {|http| - http.request(req) - } - - if res.code != '200' - raise KeystoneAPIError, "Received error response from Keystone server at #{url}: #{res.message}" - end - rescue Errno::ECONNREFUSED => detail - raise KeystoneConnectionError, "Failed to connect to Keystone server at #{url}: #{detail}" - rescue SocketError => detail - raise KeystoneConnectionError, "Failed to connect to Keystone server at #{url}: #{detail}" - end - - res -end - -# Authenticates to a Keystone server and obtains an authentication token. -# It returns a 2-element +[token, authinfo]+, where +token+ is a token -# suitable for passing to openstack apis in the +X-Auth-Token+ header, and -# +authinfo+ is the complete response from Keystone, including the service -# catalog (if available). -# -# +auth_url+:: -# Keystone endpoint URL. This function assumes API version -# 2.0 and an administrative endpoint, so this will typically look like -# +http://somehost:35357/v2.0+. -# -# +username+:: -# Username for authentication. -# -# +password+:: -# Password for authentication -# -# +tenantID+:: -# Tenant UUID -# -# +tenantName+:: -# Tenant name -# -def heat_handle_requests(auth_url, - username, - password, - tenantId=nil, - tenantName=nil) - - post_args = { - 'auth' => { - 'passwordCredentials' => { - 'username' => username, - 'password' => password - }, - }} - - if tenantId - post_args['auth']['tenantId'] = tenantId - end - - if tenantName - post_args['auth']['tenantName'] = tenantName - end - - url = URI.parse("#{auth_url}/tokens") - req = Net::HTTP::Post.new url.path - req['content-type'] = 'application/json' - req.body = post_args.to_json - - res = handle_request(req, url) - data = JSON.parse res.body - return data['access']['token']['id'], data -end - -# Queries a Keystone server to a list of all tenants. -# -# +auth_url+:: -# Keystone endpoint. See the notes for +auth_url+ in -# +heat_handle_requests+. -# -# +token+:: -# A Keystone token that will be passed in requests as the value of the -# +X-Auth-Token+ header. -# -def keystone_v3_domains(auth_url, - token) - - auth_url.sub!('v2.0', 'v3') - url = URI.parse("#{auth_url}/domains") - req = Net::HTTP::Get.new url.path - req['content-type'] = 'application/json' - req['x-auth-token'] = token - - res = handle_request(req, url) - data = JSON.parse res.body - data['domains'] -end - -Puppet::Type.type(:heat_domain_id_setter).provide(:ruby) do - def authenticate - token, authinfo = heat_handle_requests( - @resource[:auth_url], - @resource[:auth_username], - @resource[:auth_password], - nil, - @resource[:auth_tenant_name]) - - return token - end - - def find_domain_by_name(token) - domains = keystone_v3_domains( - @resource[:auth_url], - token) - domains.select{|domain| domain['name'] == @resource[:domain_name]} - end - - def exists? - false - end - - def create - config - end - - # This looks for the domain specified by the 'domain_name' parameter to - # the resource and returns the corresponding UUID if there is a single - # match. - # - # Raises a KeystoneAPIError if: - # - # - There are multiple matches, or - # - There are zero matches - def get_domain_id - token = authenticate - domains = find_domain_by_name(token) - - if domains.length == 1 - return domains[0]['id'] - elsif domains.length > 1 - name = domains[0]['name'] - raise KeystoneAPIError, 'Found multiple matches for domain name "#{name}"' - else - raise KeystoneAPIError, 'Unable to find matching domain' - end - end - - def config - Puppet::Type.type(:heat_config).new( - {:name => 'DEFAULT/stack_user_domain', :value => "#{get_domain_id}"} - ).create - end - -end diff --git a/heat/lib/puppet/type/heat_domain_id_setter.rb b/heat/lib/puppet/type/heat_domain_id_setter.rb deleted file mode 100644 index d6e1eeef0..000000000 --- a/heat/lib/puppet/type/heat_domain_id_setter.rb +++ /dev/null @@ -1,31 +0,0 @@ -Puppet::Type.newtype(:heat_domain_id_setter) do - - ensurable - - newparam(:name, :namevar => true) do - desc 'The name of the setting to update' - end - - newparam(:domain_name) do - desc 'The heat domain name' - end - - newparam(:auth_url) do - desc 'The Keystone endpoint URL' - defaultto 'http://localhost:35357/v2.0' - end - - newparam(:auth_username) do - desc 'Username with which to authenticate' - defaultto 'admin' - end - - newparam(:auth_password) do - desc 'Password with which to authenticate' - end - - newparam(:auth_tenant_name) do - desc 'Tenant name with which to authenticate' - defaultto 'admin' - end -end diff --git a/heat/manifests/keystone/domain.pp b/heat/manifests/keystone/domain.pp index 35f675ff8..19b26703c 100644 --- a/heat/manifests/keystone/domain.pp +++ b/heat/manifests/keystone/domain.pp @@ -1,12 +1,23 @@ # == Class: heat::keystone::domain # -# Configures heat domain in Keystone. -# -# Note: Implementation is done by heat-keystone-setup-domain script temporarily -# because currently puppet-keystone does not support v3 API +# Configures Heat domain in Keystone. # # === Parameters # +# [*domain_name*] +# Heat domain name. Defaults to 'heat'. +# +# [*domain_admin*] +# Keystone domain admin user which will be created. Defaults to 'heat_admin'. +# +# [*domain_admin_email*] +# Keystone domain admin user email address. Defaults to 'heat_admin@localhost'. + +# [*domain_password*] +# Keystone domain admin user password. Defaults to 'changeme'. +# +# === Deprecated Parameters +# # [*auth_url*] # Keystone auth url # @@ -19,57 +30,54 @@ # [*keystone_tenant*] # Keystone admin tenant name # -# [*domain_name*] -# Heat domain name. Defaults to 'heat'. -# -# [*domain_admin*] -# Keystone domain admin user which will be created. Defaults to 'heat_admin'. -# -# [*domain_password*] -# Keystone domain admin user password. Defaults to 'changeme'. -# class heat::keystone::domain ( - $auth_url = undef, - $keystone_admin = undef, - $keystone_password = undef, - $keystone_tenant = undef, - $domain_name = 'heat', - $domain_admin = 'heat_admin', - $domain_password = 'changeme', + $domain_name = 'heat', + $domain_admin = 'heat_admin', + $domain_admin_email = 'heat_admin@localhost', + $domain_password = 'changeme', + + # DEPRECATED PARAMETERS + $auth_url = undef, + $keystone_admin = undef, + $keystone_password = undef, + $keystone_tenant = undef, ) { include ::heat::params - $cmd_evn = [ - "OS_TENANT_NAME=${keystone_tenant}", - "OS_USERNAME=${keystone_admin}", - "OS_PASSWORD=${keystone_password}", - "OS_AUTH_URL=${auth_url}", - "HEAT_DOMAIN=${domain_name}", - "HEAT_DOMAIN_ADMIN=${domain_admin}", - "HEAT_DOMAIN_PASSWORD=${domain_password}" - ] - exec { 'heat_domain_create': - path => '/usr/bin', - command => 'heat-keystone-setup-domain', - environment => $cmd_evn, - require => Package['heat-common'], - logoutput => 'on_failure' + if $auth_url { + warning('The auth_url parameter is deprecated and will be removed in future releases') } - - heat_domain_id_setter { 'heat_domain_id': - ensure => present, - domain_name => $domain_name, - auth_url => $auth_url, - auth_username => $keystone_admin, - auth_password => $keystone_password, - auth_tenant_name => $keystone_tenant, - require => Exec['heat_domain_create'], + if $keystone_admin { + warning('The keystone_admin parameter is deprecated and will be removed in future releases') + } + if $keystone_password { + warning('The keystone_password parameter is deprecated and will be removed in future releases') } + if $keystone_tenant { + warning('The keystone_tenant parameter is deprecated and will be removed in future releases') + } + + ensure_resource('keystone_domain', 'heat_domain', { + 'ensure' => 'present', + 'enabled' => true, + 'name' => $domain_name + }) + ensure_resource('keystone_user', 'heat_domain_admin', { + 'ensure' => 'present', + 'enabled' => true, + 'name' => $domain_admin, + 'email' => $domain_admin_email, + 'password' => $domain_password, + 'domain' => $domain_name, + }) + ensure_resource('keystone_user_role', "${domain_admin}@::${domain_name}", { + 'roles' => ['admin'], + }) heat_config { - 'DEFAULT/stack_domain_admin': value => $domain_admin; + 'DEFAULT/stack_domain_admin': value => $domain_admin; 'DEFAULT/stack_domain_admin_password': value => $domain_password, secret => true; + 'DEFAULT/stack_user_domain_name': value => $domain_name; } - } diff --git a/heat/spec/acceptance/basic_heat_spec.rb b/heat/spec/acceptance/basic_heat_spec.rb index 1f78e4833..785af33fe 100644 --- a/heat/spec/acceptance/basic_heat_spec.rb +++ b/heat/spec/acceptance/basic_heat_spec.rb @@ -70,8 +70,9 @@ class { '::keystone': enabled => true, } class { '::keystone::roles::admin': - email => 'test@example.tld', - password => 'a_big_secret', + email => 'test@example.tld', + password => 'a_big_secret', + admin_roles => ['admin', '_member_', 'heat_stack_owner'] } class { '::keystone::endpoint': public_url => "https://${::fqdn}:5000/", @@ -93,6 +94,9 @@ class { '::heat::db::mysql': class { '::heat::keystone::auth': password => 'a_big_secret', } + class { '::heat::keystone::domain': + domain_password => 'oh_my_no_secret', + } class { '::heat::client': } class { '::heat::api': } class { '::heat::engine': diff --git a/heat/spec/classes/heat_keystone_domain_spec.rb b/heat/spec/classes/heat_keystone_domain_spec.rb index 0eba85d82..c8d77911d 100644 --- a/heat/spec/classes/heat_keystone_domain_spec.rb +++ b/heat/spec/classes/heat_keystone_domain_spec.rb @@ -3,13 +3,10 @@ describe 'heat::keystone::domain' do let :params do { - :auth_url => 'http://127.0.0.1:35357/v2.0', - :keystone_admin => 'admin', - :keystone_password => 'admin_passwd', - :keystone_tenant => 'admin', - :domain_name => 'heat', - :domain_admin => 'heat_admin', - :domain_password => 'domain_passwd' + :domain_name => 'heat', + :domain_admin => 'heat_admin', + :domain_admin_email => 'heat_admin@localhost', + :domain_password => 'domain_passwd' } end @@ -18,34 +15,26 @@ is_expected.to contain_heat_config('DEFAULT/stack_domain_admin').with_value(params[:domain_admin]) is_expected.to contain_heat_config('DEFAULT/stack_domain_admin_password').with_value(params[:domain_password]) is_expected.to contain_heat_config('DEFAULT/stack_domain_admin_password').with_secret(true) + is_expected.to contain_heat_config('DEFAULT/stack_user_domain_name').with_value(params[:domain_name]) end - it 'should configure heat domain id' do - is_expected.to contain_heat_domain_id_setter('heat_domain_id').with( - :ensure => 'present', - :domain_name => params[:domain_name], - :auth_url => params[:auth_url], - :auth_username => params[:keystone_admin], - :auth_password => params[:keystone_password], - :auth_tenant_name => params[:keystone_tenant] + it 'should create keystone domain' do + is_expected.to contain_keystone_domain('heat_domain').with( + :ensure => 'present', + :enabled => 'true', + :name => params[:domain_name] ) - end - it 'should exec helper script' do - is_expected.to contain_exec('heat_domain_create').with( - :command => 'heat-keystone-setup-domain', - :path => '/usr/bin', - :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]}", - "HEAT_DOMAIN=#{params[:domain_name]}", - "HEAT_DOMAIN_ADMIN=#{params[:domain_admin]}", - "HEAT_DOMAIN_PASSWORD=#{params[:domain_password]}" - ] + is_expected.to contain_keystone_user('heat_domain_admin').with( + :ensure => 'present', + :enabled => 'true', + :name => params[:domain_admin], + :email => params[:domain_admin_email], + :password => params[:domain_password], + :domain => params[:domain_name], + ) + is_expected.to contain_keystone_user_role('heat_admin@::heat').with( + :roles => ['admin'], ) end end diff --git a/heat/spec/unit/provider/heat_domain_id_setter/heat_spec.rb b/heat/spec/unit/provider/heat_domain_id_setter/heat_spec.rb deleted file mode 100644 index a6bc4d9c0..000000000 --- a/heat/spec/unit/provider/heat_domain_id_setter/heat_spec.rb +++ /dev/null @@ -1,177 +0,0 @@ -require 'spec_helper' -require 'puppet' -require 'puppet/type/heat_domain_id_setter' - -provider_class = Puppet::Type.type(:heat_domain_id_setter).provider(:ruby) - -# used to simulate an authentication response from Keystone -# (POST v2.0/tokens) -auth_response = { - 'access' => { - 'token' => { - 'id' => 'TOKEN', - } - } -} - -# used to simulate a response to GET v3/domains -domains_response = { - 'domains' => [ - { - 'name' => 'heat', - 'id' => 'UUID_HEAT' - }, - { - 'name' => 'multiple_matches_domain', - 'id' => 'UUID1' - }, - { - 'name' => 'multiple_matches_domain', - 'id' => 'UUID2' - }, - ] -} - -# Stub for ini_setting resource -Puppet::Type.newtype(:ini_setting) do -end - -# Stub for ini_setting provider -Puppet::Type.newtype(:ini_setting).provide(:ruby) do - def create - end -end - -describe 'Puppet::Type.type(:heat_keystone_domain_id_setter)' do - let :params do - { - :name => 'heat_domain_id', - :ensure => 'present', - :domain_name => 'heat', - :auth_url => 'http://127.0.0.1:35357/v2.0', - :auth_username => 'admin', - :auth_password => 'admin_passwd', - :auth_tenant_name => 'admin', - } - end - - it 'should have a non-nil provider' do - expect(provider_class).not_to be_nil - end - - context 'when url is correct' do - before :each do - stub_request(:post, "http://127.0.0.1:35357/v2.0/tokens"). - to_return(:status => 200, - :body => auth_response.to_json, - :headers => {}) - stub_request(:get, "http://127.0.0.1:35357/v3/domains"). - with(:headers => {'X-Auth-Token'=>'TOKEN'}). - to_return(:status => 200, - :body => domains_response.to_json, - :headers => {}) - end - - it 'should create a resource' do - resource = Puppet::Type::Heat_domain_id_setter.new(params) - provider = provider_class.new(resource) - expect(provider.exists?).to be_falsey - expect(provider.create).to be_nil - end - end - - # What happens if we ask for a domain that does not exist? - context 'when domain cannot be found' do - before :each do - stub_request(:post, "http://127.0.0.1:35357/v2.0/tokens"). - to_return(:status => 200, - :body => auth_response.to_json, - :headers => {}) - stub_request(:get, "http://127.0.0.1:35357/v3/domains"). - with(:headers => {'X-Auth-Token'=>'TOKEN'}). - to_return(:status => 200, - :body => domains_response.to_json, - :headers => {}) - - params.merge!(:domain_name => 'bad_domain_name') - end - - it 'should receive an api error' do - resource = Puppet::Type::Heat_domain_id_setter.new(params) - provider = provider_class.new(resource) - expect(provider.exists?).to be_falsey - expect { provider.create }.to raise_error KeystoneAPIError, /Unable to find matching domain/ - end - end - - # What happens if we ask for a domain name that results in multiple - # matches? - context 'when there are multiple matching domains' do - before :each do - stub_request(:post, "http://127.0.0.1:35357/v2.0/tokens"). - to_return(:status => 200, - :body => auth_response.to_json, - :headers => {}) - stub_request(:get, "http://127.0.0.1:35357/v3/domains"). - with(:headers => {'X-Auth-Token'=>'TOKEN'}). - to_return(:status => 200, - :body => domains_response.to_json, - :headers => {}) - - params.merge!(:domain_name => 'multiple_matches_domain') - end - - it 'should receive an api error' do - resource = Puppet::Type::Heat_domain_id_setter.new(params) - provider = provider_class.new(resource) - expect(provider.exists?).to be_falsey - expect { provider.create }.to raise_error KeystoneAPIError, /Found multiple matches for domain name/ - end - end - - # What happens if we pass a bad password? - context 'when password is incorrect' do - before :each do - stub_request(:post, "http://127.0.0.1:35357/v2.0/tokens"). - to_return(:status => 401, - :body => auth_response.to_json, - :headers => {}) - end - - it 'should receive an authentication error' do - resource = Puppet::Type::Heat_domain_id_setter.new(params) - provider = provider_class.new(resource) - expect(provider.exists?).to be_falsey - expect { provider.create }.to raise_error KeystoneAPIError - end - end - - # What happens if the server is not listening? - context 'when keystone server is unavailable' do - before :each do - stub_request(:post, "http://127.0.0.1:35357/v2.0/tokens").to_raise Errno::ECONNREFUSED - end - - it 'should receive a connection error' do - resource = Puppet::Type::Heat_domain_id_setter.new(params) - provider = provider_class.new(resource) - expect(provider.exists?).to be_falsey - expect { provider.create }.to raise_error KeystoneConnectionError - end - end - - # What happens if we mistype the hostname? - context 'when keystone server is unknown' do - before :each do - stub_request(:post, "http://127.0.0.1:35357/v2.0/tokens").to_raise SocketError, 'getaddrinfo: Name or service not known' - end - - it 'should receive a connection error' do - resource = Puppet::Type::Heat_domain_id_setter.new(params) - provider = provider_class.new(resource) - expect(provider.exists?).to be_falsey - expect { provider.create }.to raise_error KeystoneConnectionError - end - end - -end diff --git a/keystone/lib/puppet/provider/keystone.rb b/keystone/lib/puppet/provider/keystone.rb index 03700a81c..64f46de50 100644 --- a/keystone/lib/puppet/provider/keystone.rb +++ b/keystone/lib/puppet/provider/keystone.rb @@ -10,6 +10,8 @@ class Puppet::Provider::Keystone < Puppet::Provider::Openstack INI_FILENAME = '/etc/keystone/keystone.conf' + @@default_domain_id = nil + def self.admin_endpoint @admin_endpoint ||= get_admin_endpoint end @@ -18,91 +20,97 @@ def self.admin_token @admin_token ||= get_admin_token end + def self.clean_host(host) + host ||= '127.0.0.1' + case host + when '0.0.0.0' + return '127.0.0.1' + when '::0' + return '[::1]' + else + return host + end + end + def self.default_domain - domain_hash[default_domain_id] + domain_name_from_id(default_domain_id) end def self.default_domain_id - return @default_domain_id if @default_domain_id - if keystone_file and keystone_file['identity'] and keystone_file['identity']['default_domain_id'] - @default_domain_id = "#{keystone_file['identity']['default_domain_id'].strip}" + if @@default_domain_id + @@default_domain_id + elsif keystone_file and keystone_file['identity'] and keystone_file['identity']['default_domain_id'] + keystone_file['identity']['default_domain_id'].strip else - @default_domain_id = 'default' + 'default' end - @default_domain_id end - def self.domain_hash - return @domain_hash if @domain_hash - list = request('domain', 'list') - @domain_hash = Hash[list.collect{|domain| [domain[:id], domain[:name]]}] - @domain_hash + def self.default_domain_id=(id) + @@default_domain_id = id end def self.domain_name_from_id(id) - domain_hash[id] + unless @domain_hash + list = request('domain', 'list') + @domain_hash = Hash[list.collect{|domain| [domain[:id], domain[:name]]}] + end + unless @domain_hash.include?(id) + name = request('domain', 'show', id)[:name] + @domain_hash[id] = name if name + end + unless @domain_hash.include?(id) + err("Could not find domain with id [#{id}]") + end + @domain_hash[id] end def self.get_admin_endpoint + endpoint = nil if keystone_file - if keystone_file['DEFAULT'] - if keystone_file['DEFAULT']['admin_endpoint'] - auth_url = keystone_file['DEFAULT']['admin_endpoint'].strip.chomp('/') - return "#{auth_url}/v#{@credentials.version}/" - end - - if keystone_file['DEFAULT']['admin_port'] - admin_port = keystone_file['DEFAULT']['admin_port'].strip - else - admin_port = '35357' - end - - if keystone_file['DEFAULT']['admin_bind_host'] - host = keystone_file['DEFAULT']['admin_bind_host'].strip - if host == "0.0.0.0" - host = "127.0.0.1" - elsif host == '::0' - host = '[::1]' - end - else - host = "127.0.0.1" - end - end - - if keystone_file['ssl'] && keystone_file['ssl']['enable'] && keystone_file['ssl']['enable'].strip.downcase == 'true' - protocol = 'https' + if url = get_section('DEFAULT', 'admin_endpoint') + endpoint = url.chomp('/') else - protocol = 'http' + admin_port = get_section('DEFAULT', 'admin_port') || '35357' + host = clean_host(get_section('DEFAULT', 'admin_bind_host')) + protocol = ssl? ? 'https' : 'http' + endpoint = "#{protocol}://#{host}:#{admin_port}" end end - - "#{protocol}://#{host}:#{admin_port}/v#{@credentials.version}/" + return endpoint end - def self.get_admin_token - if keystone_file and keystone_file['DEFAULT'] and keystone_file['DEFAULT']['admin_token'] - return "#{keystone_file['DEFAULT']['admin_token'].strip}" - else - return nil - end + get_section('DEFAULT', 'admin_token') end - def self.get_endpoint - endpoint = nil + def self.get_auth_url + auth_url = nil if ENV['OS_AUTH_URL'] - endpoint = ENV['OS_AUTH_URL'] + auth_url = ENV['OS_AUTH_URL'].dup + elsif auth_url = get_os_vars_from_rcfile(rc_filename)['OS_AUTH_URL'] else - endpoint = get_os_vars_from_rcfile(rc_filename)['OS_AUTH_URL'] - unless endpoint - # This is from legacy but seems wrong, we want auth_url not url! - endpoint = get_admin_endpoint - end + auth_url = admin_endpoint end - unless endpoint - raise(Puppet::Error::OpenstackAuthInputError, 'Could not find auth url to check user password.') + return auth_url + end + + def self.get_section(group, name) + if keystone_file && keystone_file[group] && keystone_file[group][name] + return keystone_file[group][name].strip end - endpoint + return nil + end + + def self.get_service_url + service_url = nil + if ENV['OS_URL'] + service_url = ENV['OS_URL'].dup + elsif admin_endpoint + service_url = admin_endpoint + service_url << "/v#{@credentials.version}" + end + return service_url end def self.ini_filename @@ -151,12 +159,23 @@ def self.request(service, action, properties=nil) def self.request_by_service_token(service, action, error, properties=nil) properties ||= [] - @credentials.token = get_admin_token - @credentials.url = get_admin_endpoint + @credentials.token = admin_token + @credentials.url = service_url raise error unless @credentials.service_token_set? Puppet::Provider::Openstack.request(service, action, properties, @credentials) end + def self.service_url + @service_url ||= get_service_url + end + + def self.ssl? + if keystone_file && keystone_file['ssl'] && keystone_file['ssl']['enable'] && keystone_file['ssl']['enable'].strip.downcase == 'true' + return true + end + return false + end + # Helper functions to use on the pre-validated enabled field def bool_to_sym(bool) bool == true ? :true : :false diff --git a/keystone/lib/puppet/provider/keystone_domain/openstack.rb b/keystone/lib/puppet/provider/keystone_domain/openstack.rb index 14a8f6982..134b46d08 100644 --- a/keystone/lib/puppet/provider/keystone_domain/openstack.rb +++ b/keystone/lib/puppet/provider/keystone_domain/openstack.rb @@ -99,6 +99,7 @@ def ensure_default_domain(create, destroy=false, value=nil) end if changed self.class.keystone_file.store + self.class.default_domain_id = newid debug("The default_domain_id was changed from #{curid} to #{newid}") end end diff --git a/keystone/lib/puppet/provider/keystone_tenant/openstack.rb b/keystone/lib/puppet/provider/keystone_tenant/openstack.rb index 57a299fd6..ac1dfb107 100644 --- a/keystone/lib/puppet/provider/keystone_tenant/openstack.rb +++ b/keystone/lib/puppet/provider/keystone_tenant/openstack.rb @@ -32,6 +32,7 @@ def create properties << project_domain end @property_hash = self.class.request('project', 'create', properties) + @property_hash[:name] = resource[:name] @property_hash[:ensure] = :present end diff --git a/keystone/lib/puppet/provider/keystone_user/openstack.rb b/keystone/lib/puppet/provider/keystone_user/openstack.rb index eb1e303fd..e6f2486dc 100644 --- a/keystone/lib/puppet/provider/keystone_user/openstack.rb +++ b/keystone/lib/puppet/provider/keystone_user/openstack.rb @@ -34,12 +34,14 @@ def create properties << user_domain end @property_hash = self.class.request('user', 'create', properties) + @property_hash[:name] = resource[:name] @property_hash[:domain] = user_domain if resource[:tenant] # DEPRECATED - To be removed in next release (Liberty) # https://bugs.launchpad.net/puppet-keystone/+bug/1472437 project_id = Puppet::Resource.indirection.find("Keystone_tenant/#{resource[:tenant]}")[:id] set_project(resource[:tenant], project_id) + @property_hash[:tenant] = resource[:tenant] end @property_hash[:ensure] = :present end @@ -92,17 +94,22 @@ def id end def password - res = nil - return res if resource[:password] == nil + passwd = nil + return passwd if resource[:password] == nil if resource[:enabled] == :false || resource[:replace_password] == :false # Unchanged password - res = resource[:password] + passwd = resource[:password] else # Password validation - credentials = Puppet::Provider::Openstack::CredentialsV3.new - credentials.auth_url = self.class.get_endpoint - credentials.password = resource[:password] - credentials.user_id = id + credentials = Puppet::Provider::Openstack::CredentialsV3.new + unless auth_url = self.class.get_auth_url + raise(Puppet::Error::OpenstackAuthInputError, "Could not find authentication url to validate user's password.") + end + auth_url << "/v#{credentials.version}" unless auth_url =~ /\/v\d(\.\d)?$/ + credentials.auth_url = auth_url + credentials.password = resource[:password] + credentials.user_id = id + # NOTE: The only reason we use username is so that the openstack provider # will know we are doing v3password auth - otherwise, it is not used. The # user_id uniquely identifies the user including domain. @@ -121,10 +128,10 @@ def password rescue Puppet::Error::OpenstackUnauthorizedError # password is invalid else - res = resource[:password] unless token.empty? + passwd = resource[:password] unless token.empty? end end - return res + return passwd end def password=(value) @@ -147,7 +154,7 @@ def find_project_for_user(projname, project_id = nil) self.class.request('project', 'list', ['--user', id, '--long']).each do |project| if (project_id == project[:id]) || ((projname == project_name) && (project_domain == self.class.domain_name_from_id(project[:domain_id]))) - return project[:name] + return projname end end return nil diff --git a/keystone/spec/classes/keystone_spec.rb b/keystone/spec/classes/keystone_spec.rb index 497598210..7f85c9c47 100644 --- a/keystone/spec/classes/keystone_spec.rb +++ b/keystone/spec/classes/keystone_spec.rb @@ -27,7 +27,6 @@ 'admin_bind_host' => '0.0.0.0', 'public_port' => '5000', 'admin_port' => '35357', - 'admin_token' => 'service_token', 'verbose' => false, 'debug' => false, 'catalog_type' => 'sql', diff --git a/keystone/spec/spec_helper.rb b/keystone/spec/spec_helper.rb index 78594f8ae..fb2fcd0c0 100644 --- a/keystone/spec/spec_helper.rb +++ b/keystone/spec/spec_helper.rb @@ -7,3 +7,16 @@ c.alias_it_should_behave_like_to :it_configures, 'configures' c.alias_it_should_behave_like_to :it_raises, 'raises' end + +def setup_provider_tests + Puppet::Provider::Keystone.class_exec do + def self.reset + @admin_endpoint = nil + @tenant_hash = nil + @admin_token = nil + @keystone_file = nil + Puppet::Provider::Keystone.default_domain_id = nil + @domain_hash = nil + end + end +end diff --git a/keystone/spec/unit/provider/keystone_domain/openstack_spec.rb b/keystone/spec/unit/provider/keystone_domain/openstack_spec.rb index 497f09bae..c57373202 100644 --- a/keystone/spec/unit/provider/keystone_domain/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_domain/openstack_spec.rb @@ -2,26 +2,12 @@ require 'spec_helper' require 'puppet/provider/keystone_domain/openstack' -provider_class = Puppet::Type.type(:keystone_domain).provider(:openstack) +setup_provider_tests -class Puppet::Provider::Keystone - def self.reset - @admin_endpoint = nil - @tenant_hash = nil - @admin_token = nil - @keystone_file = nil - @domain_id_to_name = nil - @default_domain_id = nil - @domain_hash = nil - end -end +provider_class = Puppet::Type.type(:keystone_domain).provider(:openstack) describe provider_class do - after :each do - provider_class.reset - end - shared_examples 'authenticated with environment variables' do ENV['OS_USERNAME'] = 'test' ENV['OS_PASSWORD'] = 'abc123' @@ -48,6 +34,18 @@ def self.reset provider_class.new(resource) end + let(:another_class) do + class AnotherKlass < Puppet::Provider::Keystone + @credentials = Puppet::Provider::Openstack::CredentialsV3.new + end + AnotherKlass + end + + after :each do + provider_class.reset + another_class.reset + end + it_behaves_like 'authenticated with environment variables' do describe '#create' do it 'creates a domain' do @@ -115,12 +113,12 @@ def self.reset end it 'creates a default domain' do - File.expects(:exists?).returns(true) + File.expects(:exists?).twice.returns(true) mock = { 'identity' => {'default_domain_id' => ' default'} } - Puppet::Util::IniConfig::File.expects(:new).returns(mock) - mock.expects(:read).with('/etc/keystone/keystone.conf') + Puppet::Util::IniConfig::File.expects(:new).twice.returns(mock) + mock.expects(:read).twice.with('/etc/keystone/keystone.conf') mock.expects(:store) provider.class.expects(:openstack) .with('domain', 'create', '--format', 'shell', ['foo', '--enable', '--description', 'foo']) @@ -129,9 +127,13 @@ def self.reset description="foo" enabled=True ') + expect(provider.class.default_domain_id).to eq('default') + expect(another_class.default_domain_id).to eq('default') provider.create expect(provider.exists?).to be_truthy expect(mock['identity']['default_domain_id']).to eq('1cb05cfed7c24279be884ba4f6520262') + expect(provider.class.default_domain_id).to eq('1cb05cfed7c24279be884ba4f6520262') + expect(another_class.default_domain_id).to eq('1cb05cfed7c24279be884ba4f6520262') end end @@ -154,6 +156,8 @@ def self.reset provider.destroy expect(provider.exists?).to be_falsey expect(kcmock['identity']['default_domain_id']).to eq('default') + expect(provider.class.default_domain_id).to eq('default') + expect(another_class.default_domain_id).to eq('default') end end diff --git a/keystone/spec/unit/provider/keystone_spec.rb b/keystone/spec/unit/provider/keystone_spec.rb index 44d265f52..e1035540f 100644 --- a/keystone/spec/unit/provider/keystone_spec.rb +++ b/keystone/spec/unit/provider/keystone_spec.rb @@ -3,122 +3,200 @@ require 'puppet/provider/keystone' require 'tempfile' +setup_provider_tests + klass = Puppet::Provider::Keystone class Puppet::Provider::Keystone @credentials = Puppet::Provider::Openstack::CredentialsV3.new - - def self.reset - @admin_endpoint = nil - @tenant_hash = nil - @admin_token = nil - @keystone_file = nil - @domain_id_to_name = nil - @default_domain_id = nil - @domain_hash = nil - end end describe Puppet::Provider::Keystone do + let(:another_class) do + class AnotherKlass < Puppet::Provider::Keystone + @credentials = Puppet::Provider::Openstack::CredentialsV3.new + end + AnotherKlass + end + after :each do klass.reset + another_class.reset end - describe 'when retrieving the security token' do - it 'should return nothing if there is no keystone config file' do + describe '#ssl?' do + it 'should be false if there is no keystone file' do File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(false) - expect(klass.get_admin_token).to be_nil + expect(klass.ssl?).to be_falsey end - it 'should return nothing if the keystone config file does not have a DEFAULT section' do + it 'should be false if ssl is not configured in keystone file' do mock = {} File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) Puppet::Util::IniConfig::File.expects(:new).returns(mock) mock.expects(:read).with('/etc/keystone/keystone.conf') - expect(klass.get_admin_token).to be_nil + expect(klass.ssl?).to be_falsey end - it 'should fail if the keystone config file does not contain an admin token' do - mock = {'DEFAULT' => {'not_a_token' => 'foo'}} + it 'should be false if ssl is configured and disable in keystone file' do + mock = {'ssl' => {'enable' => 'False'}} File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) Puppet::Util::IniConfig::File.expects(:new).returns(mock) mock.expects(:read).with('/etc/keystone/keystone.conf') - expect(klass.get_admin_token).to be_nil + expect(klass.ssl?).to be_falsey end - it 'should parse the admin token if it is in the config file' do - mock = {'DEFAULT' => {'admin_token' => 'foo'}} + it 'should be true if ssl is configured and enabled in keystone file' do + mock = {'ssl' => {'enable' => 'True'}} File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) Puppet::Util::IniConfig::File.expects(:new).returns(mock) mock.expects(:read).with('/etc/keystone/keystone.conf') - expect(klass.get_admin_token).to eq('foo') + expect(klass.ssl?).to be_truthy + end + end + + describe '#get_admin_endpoint' do + it 'should return nothing if there is no keystone config file' do + expect(klass.get_admin_endpoint).to be_nil + end + + it 'should use the admin_endpoint from keystone config file with no trailing slash' do + mock = {'DEFAULT' => {'admin_endpoint' => 'https://keystone.example.com/'}} + File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) + Puppet::Util::IniConfig::File.expects(:new).returns(mock) + mock.expects(:read).with('/etc/keystone/keystone.conf') + expect(klass.get_admin_endpoint).to eq('https://keystone.example.com') end it 'should use the specified bind_host in the admin endpoint' do - mock = {'DEFAULT' => {'admin_bind_host' => '192.168.56.210', 'admin_port' => '35357' }} + mock = {'DEFAULT' => {'admin_bind_host' => '192.168.56.210', 'admin_port' => '5001' }} File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) Puppet::Util::IniConfig::File.expects(:new).returns(mock) mock.expects(:read).with('/etc/keystone/keystone.conf') - expect(klass.get_admin_endpoint).to eq('http://192.168.56.210:35357/v3/') + expect(klass.get_admin_endpoint).to eq('http://192.168.56.210:5001') end it 'should use localhost in the admin endpoint if bind_host is 0.0.0.0' do - mock = {'DEFAULT' => { 'admin_bind_host' => '0.0.0.0', 'admin_port' => '35357' }} + mock = {'DEFAULT' => { 'admin_bind_host' => '0.0.0.0', 'admin_port' => '5001' }} File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) Puppet::Util::IniConfig::File.expects(:new).returns(mock) mock.expects(:read).with('/etc/keystone/keystone.conf') - expect(klass.get_admin_endpoint).to eq('http://127.0.0.1:35357/v3/') + expect(klass.get_admin_endpoint).to eq('http://127.0.0.1:5001') end it 'should use [::1] in the admin endpoint if bind_host is ::0' do - mock = {'DEFAULT' => { 'admin_bind_host' => '::0', 'admin_port' => '35357' }} + mock = {'DEFAULT' => { 'admin_bind_host' => '::0', 'admin_port' => '5001' }} File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) Puppet::Util::IniConfig::File.expects(:new).returns(mock) mock.expects(:read).with('/etc/keystone/keystone.conf') - expect(klass.get_admin_endpoint).to eq('http://[::1]:35357/v3/') + expect(klass.get_admin_endpoint).to eq('http://[::1]:5001') end it 'should use localhost in the admin endpoint if bind_host is unspecified' do - mock = {'DEFAULT' => { 'admin_port' => '35357' }} + mock = {'DEFAULT' => { 'admin_port' => '5001' }} File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) Puppet::Util::IniConfig::File.expects(:new).returns(mock) mock.expects(:read).with('/etc/keystone/keystone.conf') - expect(klass.get_admin_endpoint).to eq('http://127.0.0.1:35357/v3/') + expect(klass.get_admin_endpoint).to eq('http://127.0.0.1:5001') end it 'should use https if ssl is enabled' do - mock = {'DEFAULT' => {'admin_bind_host' => '192.168.56.210', 'admin_port' => '35357' }, 'ssl' => {'enable' => 'True'}} + mock = {'DEFAULT' => {'admin_bind_host' => '192.168.56.210', 'admin_port' => '5001' }, 'ssl' => {'enable' => 'True'}} File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) Puppet::Util::IniConfig::File.expects(:new).returns(mock) mock.expects(:read).with('/etc/keystone/keystone.conf') - expect(klass.get_admin_endpoint).to eq('https://192.168.56.210:35357/v3/') + expect(klass.get_admin_endpoint).to eq('https://192.168.56.210:5001') end it 'should use http if ssl is disabled' do - mock = {'DEFAULT' => {'admin_bind_host' => '192.168.56.210', 'admin_port' => '35357' }, 'ssl' => {'enable' => 'False'}} + mock = {'DEFAULT' => {'admin_bind_host' => '192.168.56.210', 'admin_port' => '5001' }, 'ssl' => {'enable' => 'False'}} File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) Puppet::Util::IniConfig::File.expects(:new).returns(mock) mock.expects(:read).with('/etc/keystone/keystone.conf') - expect(klass.get_admin_endpoint).to eq('http://192.168.56.210:35357/v3/') + expect(klass.get_admin_endpoint).to eq('http://192.168.56.210:5001') end + end - it 'should use the defined admin_endpoint if available' do - mock = {'DEFAULT' => {'admin_endpoint' => 'https://keystone.example.com' }, 'ssl' => {'enable' => 'False'}} + describe '#get_auth_url' do + it 'should return nothing when OS_AUTH_URL is no defined in either the environment or the openrc file and there is no keystone configuration file' do + home = ENV['HOME'] + ENV.clear + File.expects(:exists?).with("#{home}/openrc").returns(false) + File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(false) + expect(klass.get_auth_url).to be_nil + end + + it 'should return the OS_AUTH_URL from the environment' do + ENV.clear + ENV['OS_AUTH_URL'] = 'http://127.0.0.1:5001' + expect(klass.get_auth_url).to eq('http://127.0.0.1:5001') + end + + it 'should return the OS_AUTH_URL from the openrc file when there is no OS_AUTH_URL in the environment' do + home = ENV['HOME'] + ENV.clear + mock = {'OS_AUTH_URL' => 'http://127.0.0.1:5001'} + klass.expects(:get_os_vars_from_rcfile).with("#{home}/openrc").returns(mock) + expect(klass.get_auth_url).to eq('http://127.0.0.1:5001') + end + + it 'should use admin_endpoint when nothing else is available' do + ENV.clear + mock = 'http://127.0.0.1:5001' + klass.expects(:admin_endpoint).returns(mock) + expect(klass.get_auth_url).to eq('http://127.0.0.1:5001') + end + end + + describe '#get_service_url when retrieving the security token' do + it 'should return nothing when OS_URL is not defined in environment' do + ENV.clear + expect(klass.get_service_url).to be_nil + end + + it 'should return the OS_URL from the environment' do + ENV['OS_URL'] = 'http://127.0.0.1:5001/v3' + expect(klass.get_service_url).to eq('http://127.0.0.1:5001/v3') + end + + it 'should use admin_endpoint with the API version number' do + ENV.clear + mock = 'http://127.0.0.1:5001' + klass.expects(:admin_endpoint).twice.returns(mock) + expect(klass.get_service_url).to eq('http://127.0.0.1:5001/v3') + end + end + + describe 'when retrieving the security token' do + it 'should return nothing if there is no keystone config file' do + File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(false) + expect(klass.get_admin_token).to be_nil + end + + it 'should return nothing if the keystone config file does not have a DEFAULT section' do + mock = {} File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) Puppet::Util::IniConfig::File.expects(:new).returns(mock) mock.expects(:read).with('/etc/keystone/keystone.conf') - expect(klass.get_admin_endpoint).to eq('https://keystone.example.com/v3/') + expect(klass.get_admin_token).to be_nil end - it 'should handle an admin_endpoint with a trailing slash' do - mock = {'DEFAULT' => {'admin_endpoint' => 'https://keystone.example.com/' }, 'ssl' => {'enable' => 'False'}} + it 'should fail if the keystone config file does not contain an admin token' do + mock = {'DEFAULT' => {'not_a_token' => 'foo'}} File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) Puppet::Util::IniConfig::File.expects(:new).returns(mock) mock.expects(:read).with('/etc/keystone/keystone.conf') - expect(klass.get_admin_endpoint).to eq('https://keystone.example.com/v3/') + expect(klass.get_admin_token).to be_nil end + it 'should parse the admin token if it is in the config file' do + mock = {'DEFAULT' => {'admin_token' => 'foo'}} + File.expects(:exists?).with("/etc/keystone/keystone.conf").returns(true) + Puppet::Util::IniConfig::File.expects(:new).returns(mock) + mock.expects(:read).with('/etc/keystone/keystone.conf') + expect(klass.get_admin_token).to eq('foo') + end end describe 'when using domains' do @@ -153,6 +231,29 @@ def self.reset ') expect(klass.name_and_domain('foo')).to eq(['foo', 'SomeName']) end + it 'should return the default_domain_id from one class set in another class' 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' + klass.expects(:openstack) + .with('domain', 'list', '--quiet', '--format', 'csv', []) + .returns('"ID","Name","Enabled","Description" +"default","Default",True,"default domain" +"somename","SomeName",True,"some domain" +') + another_class.expects(:openstack) + .with('domain', 'list', '--quiet', '--format', 'csv', []) + .returns('"ID","Name","Enabled","Description" +"default","Default",True,"default domain" +"somename","SomeName",True,"some domain" +') + expect(klass.default_domain).to eq('Default') + expect(another_class.default_domain).to eq('Default') + klass.default_domain_id = 'somename' + expect(klass.default_domain).to eq('SomeName') + expect(another_class.default_domain).to eq('SomeName') + end it 'should return Default if default_domain_id is not configured' do ENV['OS_USERNAME'] = 'test' ENV['OS_PASSWORD'] = 'abc123' @@ -169,5 +270,54 @@ def self.reset ') expect(klass.name_and_domain('foo')).to eq(['foo', 'Default']) end + it 'should list all domains when requesting a domain name from an ID' 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' + klass.expects(:openstack) + .with('domain', 'list', '--quiet', '--format', 'csv', []) + .returns('"ID","Name","Enabled","Description" +"somename","SomeName",True,"default domain" +') + expect(klass.domain_name_from_id('somename')).to eq('SomeName') + end + it 'should lookup a domain when not found in the hash' 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' + klass.expects(:openstack) + .with('domain', 'list', '--quiet', '--format', 'csv', []) + .returns('"ID","Name","Enabled","Description" +"somename","SomeName",True,"default domain" +') + klass.expects(:openstack) + .with('domain', 'show', '--format', 'shell', 'another') + .returns(' +name="AnOther" +id="another" +') + expect(klass.domain_name_from_id('somename')).to eq('SomeName') + expect(klass.domain_name_from_id('another')).to eq('AnOther') + end + it 'should print an error when there is no such domain' 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' + klass.expects(:openstack) + .with('domain', 'list', '--quiet', '--format', 'csv', []) + .returns('"ID","Name","Enabled","Description" +"somename","SomeName",True,"default domain" +') + klass.expects(:openstack) + .with('domain', 'show', '--format', 'shell', 'doesnotexist') + .returns(' +') + klass.expects(:err) + .with('Could not find domain with id [doesnotexist]') + expect(klass.domain_name_from_id('doesnotexist')).to eq(nil) + end end end diff --git a/keystone/spec/unit/provider/keystone_tenant/openstack_spec.rb b/keystone/spec/unit/provider/keystone_tenant/openstack_spec.rb index fd17e4250..8cfcf1b24 100644 --- a/keystone/spec/unit/provider/keystone_tenant/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_tenant/openstack_spec.rb @@ -2,19 +2,9 @@ require 'spec_helper' require 'puppet/provider/keystone_tenant/openstack' -provider_class = Puppet::Type.type(:keystone_tenant).provider(:openstack) +setup_provider_tests -class Puppet::Provider::Keystone - def self.reset - @admin_endpoint = nil - @tenant_hash = nil - @admin_token = nil - @keystone_file = nil - @domain_id_to_name = nil - @default_domain_id = nil - @domain_hash = nil - end -end +provider_class = Puppet::Type.type(:keystone_tenant).provider(:openstack) describe provider_class do @@ -203,6 +193,7 @@ def before_hook(domainlist) provider.create expect(provider.exists?).to be_truthy expect(provider.id).to eq("project-id") + expect(provider.name).to eq('foo::foo_domain') end end @@ -230,6 +221,7 @@ def before_hook(domainlist) provider.create expect(provider.exists?).to be_truthy expect(provider.id).to eq("project-id") + expect(provider.name).to eq('foo::bar_domain') end end end diff --git a/keystone/spec/unit/provider/keystone_user/openstack_spec.rb b/keystone/spec/unit/provider/keystone_user/openstack_spec.rb index d7de008c7..f3836ef1d 100644 --- a/keystone/spec/unit/provider/keystone_user/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_user/openstack_spec.rb @@ -3,6 +3,8 @@ require 'puppet/provider/keystone_user/openstack' require 'puppet/provider/openstack' +setup_provider_tests + provider_class = Puppet::Type.type(:keystone_user).provider(:openstack) def project_class @@ -18,6 +20,11 @@ def project_class ENV['OS_AUTH_URL'] = 'http://127.0.0.1:5000' end + after :each do + provider_class.reset + project_class.reset + end + let(:user_attrs) do { :name => 'foo', @@ -38,10 +45,27 @@ def project_class provider_class.new(resource) end - def before_hook(delete, missing, noproject, user_cached) + def before_hook(delete, missing, noproject, user_cached, project_only) + unless noproject + project_class.expects(:openstack).once + .with('domain', 'list', '--quiet', '--format', 'csv', []) + .returns('"ID","Name","Enabled","Description" +"default","Default",True,"default" +"foo_domain_id","foo_domain",True,"foo domain" +"bar_domain_id","bar_domain",True,"bar domain" +"another_domain_id","another_domain",True,"another domain" +"disabled_domain_id","disabled_domain",False,"disabled domain" +') + end + + if project_only + return + end + provider.class.expects(:openstack).once .with('domain', 'list', '--quiet', '--format', 'csv', []) .returns('"ID","Name","Enabled","Description" +"default","Default",True,"default" "foo_domain_id","foo_domain",True,"foo domain" "bar_domain_id","bar_domain",True,"bar domain" "another_domain_id","another_domain",True,"another domain" @@ -75,39 +99,37 @@ def before_hook(delete, missing, noproject, user_cached) end before :each, :default => true do - before_hook(false, false, false, false) + before_hook(false, false, false, false, false) end before :each, :delete => true do - before_hook(true, false, false, false) + before_hook(true, false, false, false, false) end before :each, :missing => true do - before_hook(false, true, false, false) + before_hook(false, true, false, false, false) end before :each, :noproject => true do - before_hook(false, false, true, false) + before_hook(false, false, true, false, false) end before :each, :default_https => true do - before_hook(false, false, false, false) + before_hook(false, false, false, false, false) end before :each, :user_cached => true do - before_hook(false, false, false, true) + before_hook(false, false, false, true, false) end before :each, :nohooks => true do # do nothing end + before :each, :project_only => true do + before_hook(false, false, false, false, true) + end + before :each, :noproject_user_cached => true do + before_hook(false, false, true, true, false) + end describe 'when managing a user' do it_behaves_like 'authenticated with environment variables' do - describe '#create' do + describe '#create', :project_only => true do it 'creates a user' do - project_class.expects(:openstack).once - .with('domain', 'list', '--quiet', '--format', 'csv', []) - .returns('"ID","Name","Enabled","Description" -"foo_domain_id","foo_domain",True,"foo domain" -"bar_domain_id","bar_domain",True,"bar domain" -"another_domain_id","another_domain",True,"another domain" -"disabled_domain_id","disabled_domain",False,"disabled domain" -') project_class.expects(:openstack) .with('project', 'list', '--quiet', '--format', 'csv', '--long') .returns('"ID","Name","Domain ID","Description","Enabled" @@ -155,7 +177,7 @@ def before_hook(delete, missing, noproject, user_cached) end end - describe '#instances', :default => true do + describe '#instances', :noproject => true do it 'finds every user' do instances = provider.class.instances expect(instances.count).to eq(3) @@ -167,10 +189,10 @@ def before_hook(delete, missing, noproject, user_cached) end describe '#tenant' do - it 'gets the tenant with default backend', :nohooks => true do - project_class.expects(:openstack) - .with('project', 'list', '--quiet', '--format', 'csv', '--long') - .returns('"ID","Name","Domain ID","Description","Enabled" + it 'gets the tenant with default backend', :user_cached => true do + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" "1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True "2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True ') @@ -184,11 +206,11 @@ def before_hook(delete, missing, noproject, user_cached) expect(tenant).to eq('foo') end - it 'gets the tenant with LDAP backend', :nohooks => true do + it 'gets the tenant with LDAP backend', :user_cached => true do provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' - project_class.expects(:openstack) - .with('project', 'list', '--quiet', '--format', 'csv', '--long') - .returns('"ID","Name","Domain ID","Description","Enabled" + project_class.expects(:openstack) + .with('project', 'list', '--quiet', '--format', 'csv', '--long') + .returns('"ID","Name","Domain ID","Description","Enabled" "1cb05cfed7c24279be884ba4f6520262","foo","foo_domain_id","foo",True "2cb05cfed7c24279be884ba4f6520262","bar","bar_domain_id","bar",True ') @@ -203,8 +225,8 @@ def before_hook(delete, missing, noproject, user_cached) expect(tenant).to eq('foo') end end - describe '#tenant=' do - context 'when using default backend', :nohooks => true do + describe '#tenant=', :project_only => true do + context 'when using default backend' do it 'sets the tenant' do provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' provider.instance_variable_get('@property_hash')[:domain] = 'foo_domain' @@ -222,7 +244,7 @@ def before_hook(delete, missing, noproject, user_cached) provider.tenant=('bar') end end - context 'when using LDAP read-write backend', :nohooks => true do + context 'when using LDAP read-write backend' do it 'sets the tenant when _member_ role exists' do provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' provider.instance_variable_get('@property_hash')[:domain] = 'foo_domain' @@ -281,7 +303,7 @@ def before_hook(delete, missing, noproject, user_cached) end end - describe "#password", :nohooks => true do + describe "#password" do let(:user_attrs) do { :name => 'foo', @@ -307,16 +329,15 @@ def before_hook(delete, missing, noproject, user_cached) end it_behaves_like 'with auth-url environment variable' do - it 'checks the password' do + it 'checks the password', :noproject_user_cached => true do provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' - mockcreds = {} - Puppet::Provider::Openstack::CredentialsV3.expects(:new).returns(mockcreds) - mockcreds.expects(:auth_url=).with('http://127.0.0.1:5000') - mockcreds.expects(:password=).with('foo') - mockcreds.expects(:username=).with('foo') - mockcreds.expects(:user_id=).with('1cb05cfed7c24279be884ba4f6520262') - mockcreds.expects(:project_id=).with('project-id-1') - mockcreds.expects(:to_env).returns(mockcreds) + mock_creds = Puppet::Provider::Openstack::CredentialsV3.new + mock_creds.auth_url='http://127.0.0.1:5000' + mock_creds.password='foo' + mock_creds.username='foo' + mock_creds.user_id='1cb05cfed7c24279be884ba4f6520262' + mock_creds.project_id='project-id-1' + Puppet::Provider::Openstack::CredentialsV3.expects(:new).returns(mock_creds) Puppet::Provider::Openstack.expects(:openstack) .with('project', 'list', '--quiet', '--format', 'csv', ['--user', '1cb05cfed7c24279be884ba4f6520262', '--long']) .returns('"ID","Name","Domain ID","Description","Enabled" @@ -333,7 +354,7 @@ def before_hook(delete, missing, noproject, user_cached) expect(password).to eq('foo') end - it 'fails the password check' do + it 'fails the password check', :noproject_user_cached => true do provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' Puppet::Provider::Openstack.expects(:openstack) .with('project', 'list', '--quiet', '--format', 'csv', ['--user', '1cb05cfed7c24279be884ba4f6520262', '--long']) @@ -347,17 +368,16 @@ def before_hook(delete, missing, noproject, user_cached) expect(password).to eq(nil) end - it 'checks the password with domain scoped token' do + it 'checks the password with domain scoped token', :nohooks => true do provider.instance_variable_get('@property_hash')[:id] = '1cb05cfed7c24279be884ba4f6520262' provider.instance_variable_get('@property_hash')[:domain] = 'foo_domain' - mockcreds = {} - Puppet::Provider::Openstack::CredentialsV3.expects(:new).returns(mockcreds) - mockcreds.expects(:auth_url=).with('http://127.0.0.1:5000') - mockcreds.expects(:password=).with('foo') - mockcreds.expects(:username=).with('foo') - mockcreds.expects(:user_id=).with('1cb05cfed7c24279be884ba4f6520262') - mockcreds.expects(:domain_name=).with('foo_domain') - mockcreds.expects(:to_env).returns(mockcreds) + mock_creds = Puppet::Provider::Openstack::CredentialsV3.new + mock_creds.auth_url='http://127.0.0.1:5000' + mock_creds.password='foo' + mock_creds.username='foo' + mock_creds.user_id='1cb05cfed7c24279be884ba4f6520262' + mock_creds.domain_name='foo_domain' + Puppet::Provider::Openstack::CredentialsV3.expects(:new).returns(mock_creds) Puppet::Provider::Openstack.expects(:openstack) .with('project', 'list', '--quiet', '--format', 'csv', ['--user', '1cb05cfed7c24279be884ba4f6520262', '--long']) .returns('"ID","Name","Domain ID","Description","Enabled" @@ -407,7 +427,7 @@ def before_hook(delete, missing, noproject, user_cached) end it_behaves_like 'authenticated with environment variables' do - describe 'v3 domains with no domain in resource', :nohooks => true do + describe 'v3 domains with no domain in resource', :user_cached => true do let(:user_attrs) do { :name => 'foo', @@ -420,9 +440,6 @@ def before_hook(delete, missing, noproject, user_cached) end it 'adds default domain to commands' do - provider_class.class_exec { - @default_domain_id = nil - } mock = { 'identity' => {'default_domain_id' => 'foo_domain_id'} } @@ -460,7 +477,7 @@ def before_hook(delete, missing, noproject, user_cached) end end - describe 'v3 domains with domain in resource' do + describe 'v3 domains with domain in resource', :project_only => true do let(:user_attrs) do { :name => 'foo', @@ -501,7 +518,7 @@ def before_hook(delete, missing, noproject, user_cached) end end - describe 'v3 domains with domain in name/title' do + describe 'v3 domains with domain in name/title', :project_only => true do let(:user_attrs) do { :name => 'foo::bar_domain', @@ -538,10 +555,11 @@ def before_hook(delete, missing, noproject, user_cached) provider.create expect(provider.exists?).to be_truthy expect(provider.id).to eq("2cb05cfed7c24279be884ba4f6520262") + expect(provider.name).to eq('foo::bar_domain') end end - describe 'v3 domains with domain in name/title and in resource' do + describe 'v3 domains with domain in name/title and in resource', :project_only => true do let(:user_attrs) do { :name => 'foo::bar_domain', @@ -579,10 +597,11 @@ def before_hook(delete, missing, noproject, user_cached) provider.create expect(provider.exists?).to be_truthy expect(provider.id).to eq("2cb05cfed7c24279be884ba4f6520262") + expect(provider.name).to eq('foo::bar_domain') end end - describe 'v3 domains with domain in name/title and in resource and in tenant' do + describe 'v3 domains with domain in name/title and in resource and in tenant', :project_only => true do let(:user_attrs) do { :name => 'foo::bar_domain', @@ -620,6 +639,7 @@ def before_hook(delete, missing, noproject, user_cached) provider.create expect(provider.exists?).to be_truthy expect(provider.id).to eq("2cb05cfed7c24279be884ba4f6520262") + expect(provider.name).to eq('foo::bar_domain') 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 7a88d85c3..51c147535 100644 --- a/keystone/spec/unit/provider/keystone_user_role/openstack_spec.rb +++ b/keystone/spec/unit/provider/keystone_user_role/openstack_spec.rb @@ -2,6 +2,8 @@ require 'spec_helper' require 'puppet/provider/keystone_user_role/openstack' +setup_provider_tests + provider_class = Puppet::Type.type(:keystone_user_role).provider(:openstack) def user_class Puppet::Type.type(:keystone_user).provider(:openstack) @@ -12,6 +14,10 @@ def project_class describe provider_class do + after :each do + provider_class.reset + end + # assumes Enabled is the last column - no quotes def list_to_csv(thelist) if thelist.is_a?(String) From 041b91e0da0586ba5253b07dbc2d0df36e243a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=A1gr?= Date: Tue, 29 Sep 2015 13:52:03 +0200 Subject: [PATCH 04/54] Properly update rabbitmq This commit is setting modules to following state: rabbitmq - old commit: 1cdf6568473a0a45fb0b06b21b0c9a82c398bf08 - new commit: aa3ec5e061f619f4340a9c6ef1465f2f6a673cb4 This commit is for properly update rabbitmq module, so we can remove patch [1] from patches branches. [1] https://github.com/redhat-openstack/openstack-puppet-modules/commit/3f5a7e94e1b9dfb686d3e18a9ccf6e344ace766d Change-Id: Ic22da93c413ab13a68d5a7d60d0a309141d752be --- Puppetfile | 2 +- rabbitmq/README.md | 9 + .../provider/rabbitmq_erlang_cookie/ruby.rb | 2 +- rabbitmq/lib/puppet/type/rabbitmq_policy.rb | 18 ++ rabbitmq/manifests/config.pp | 43 ++- rabbitmq/manifests/init.pp | 5 +- rabbitmq/manifests/install/rabbitmqadmin.pp | 5 +- rabbitmq/manifests/params.pp | 3 +- rabbitmq/spec/classes/rabbitmq_spec.rb | 266 ++++++++++++------ .../unit/puppet/type/rabbitmq_policy_spec.rb | 28 ++ rabbitmq/templates/rabbitmq.config.erb | 6 +- rabbitmq/templates/rabbitmqadmin.conf.erb | 2 +- 12 files changed, 271 insertions(+), 118 deletions(-) diff --git a/Puppetfile b/Puppetfile index 8c1235bb2..6a9976719 100644 --- a/Puppetfile +++ b/Puppetfile @@ -155,7 +155,7 @@ mod 'qpid', :git => 'https://github.com/dprince/puppet-qpid' mod 'rabbitmq', - :commit => '1cdf6568473a0a45fb0b06b21b0c9a82c398bf08', + :commit => 'aa3ec5e061f619f4340a9c6ef1465f2f6a673cb4', :git => 'https://github.com/puppetlabs/puppetlabs-rabbitmq.git' mod 'redis', diff --git a/rabbitmq/README.md b/rabbitmq/README.md index a29252695..3a0e4ab22 100644 --- a/rabbitmq/README.md +++ b/rabbitmq/README.md @@ -221,6 +221,8 @@ RabbitMQ Environment Variables in rabbitmq_env.config The erlang cookie to use for clustering - must be the same between all nodes. This value has no default and must be set explicitly if using clustering. +If you run Pacemaker and you don't want to use RabbitMQ buildin cluster, you can +set config_cluster to 'False' and set 'erlang_cookie'. ####`file_limit` @@ -272,6 +274,13 @@ Boolean, whether or not to manage package repositories. The port for the RabbitMQ management interface. +####`management_ssl` + +Enable/Disable SSL for the maangement port. +Has an effect only if ssl => true. +Default is true. +Valid values are true or false. + ####`node_ip_address` The value of NODE_IP_ADDRESS in rabbitmq_env.config diff --git a/rabbitmq/lib/puppet/provider/rabbitmq_erlang_cookie/ruby.rb b/rabbitmq/lib/puppet/provider/rabbitmq_erlang_cookie/ruby.rb index 58c8b3c96..74a96168f 100644 --- a/rabbitmq/lib/puppet/provider/rabbitmq_erlang_cookie/ruby.rb +++ b/rabbitmq/lib/puppet/provider/rabbitmq_erlang_cookie/ruby.rb @@ -16,7 +16,7 @@ def exists? def content=(value) if resource[:force] == :true # Danger! puppet('resource', 'service', resource[:service_name], 'ensure=stopped') - FileUtils.rm_rf(resource[:rabbitmq_home] + File::PATH_SEPARATOR + 'mnesia') + FileUtils.rm_rf(resource[:rabbitmq_home] + File::SEPARATOR + 'mnesia') File.open(resource[:path], 'w') do |cookie| cookie.chmod(0400) cookie.write(value) diff --git a/rabbitmq/lib/puppet/type/rabbitmq_policy.rb b/rabbitmq/lib/puppet/type/rabbitmq_policy.rb index 259a1d66c..8b796d21c 100644 --- a/rabbitmq/lib/puppet/type/rabbitmq_policy.rb +++ b/rabbitmq/lib/puppet/type/rabbitmq_policy.rb @@ -87,6 +87,18 @@ def validate_definition(definition) raise ArgumentError, "Invalid expires value '#{expires_val}'" end end + if definition.key? 'message-ttl' + message_ttl_val = definition['message-ttl'] + unless message_ttl_val.to_i.to_s == message_ttl_val + raise ArgumentError, "Invalid message-ttl value '#{message_ttl_val}'" + end + end + if definition.key? 'max-length' + max_length_val = definition['max-length'] + unless max_length_val.to_i.to_s == max_length_val + raise ArgumentError, "Invalid max-length value '#{max_length_val}'" + end + end end def munge_definition(definition) @@ -96,6 +108,12 @@ def munge_definition(definition) if definition.key? 'expires' definition['expires'] = definition['expires'].to_i end + if definition.key? 'message-ttl' + definition['message-ttl'] = definition['message-ttl'].to_i + end + if definition.key? 'max-length' + definition['max-length'] = definition['max-length'].to_i + end definition end end diff --git a/rabbitmq/manifests/config.pp b/rabbitmq/manifests/config.pp index 159ae68db..7f7ffd693 100644 --- a/rabbitmq/manifests/config.pp +++ b/rabbitmq/manifests/config.pp @@ -17,6 +17,7 @@ $erlang_cookie = $rabbitmq::erlang_cookie $interface = $rabbitmq::interface $management_port = $rabbitmq::management_port + $management_ssl = $rabbitmq::management_ssl $node_ip_address = $rabbitmq::node_ip_address $plugin_dir = $rabbitmq::plugin_dir $rabbitmq_user = $rabbitmq::rabbitmq_user @@ -138,35 +139,31 @@ notify => Class['Rabbitmq::Service'], refreshonly => true, } - } else { - file { '/etc/security/limits.d/rabbitmq-server.conf': - content => template('rabbitmq/limits.conf'), - owner => '0', - group => '0', - mode => '0644', - notify => Class['Rabbitmq::Service'], - } + } + file { '/etc/security/limits.d/rabbitmq-server.conf': + content => template('rabbitmq/limits.conf'), + owner => '0', + group => '0', + mode => '0644', + notify => Class['Rabbitmq::Service'], } } default: { } } - if $config_cluster { - - if $erlang_cookie == undef { - fail('You must set the $erlang_cookie value in order to configure clustering.') - } else { - rabbitmq_erlang_cookie { "${rabbitmq_home}/.erlang.cookie": - content => $erlang_cookie, - force => $wipe_db_on_cookie_change, - rabbitmq_user => $rabbitmq_user, - rabbitmq_group => $rabbitmq_group, - rabbitmq_home => $rabbitmq_home, - service_name => $service_name, - before => File['rabbitmq.config'], - notify => Class['rabbitmq::service'], - } + if $erlang_cookie == undef and $config_cluster { + fail('You must set the $erlang_cookie value in order to configure clustering.') + } elsif $erlang_cookie != undef { + rabbitmq_erlang_cookie { "${rabbitmq_home}/.erlang.cookie": + content => $erlang_cookie, + force => $wipe_db_on_cookie_change, + rabbitmq_user => $rabbitmq_user, + rabbitmq_group => $rabbitmq_group, + rabbitmq_home => $rabbitmq_home, + service_name => $service_name, + before => File['rabbitmq.config'], + notify => Class['rabbitmq::service'], } } } diff --git a/rabbitmq/manifests/init.pp b/rabbitmq/manifests/init.pp index 4e115f9b2..36e0ca0c2 100644 --- a/rabbitmq/manifests/init.pp +++ b/rabbitmq/manifests/init.pp @@ -15,6 +15,7 @@ $erlang_cookie = $rabbitmq::params::erlang_cookie, $interface = $rabbitmq::params::interface, $management_port = $rabbitmq::params::management_port, + $management_ssl = $rabbitmq::params::management_ssl, $node_ip_address = $rabbitmq::params::node_ip_address, $package_apt_pin = $rabbitmq::params::package_apt_pin, $package_ensure = $rabbitmq::params::package_ensure, @@ -101,9 +102,7 @@ } validate_bool($wipe_db_on_cookie_change) validate_bool($tcp_keepalive) - if ! is_integer($file_limit) { - validate_re($file_limit, '^(unlimited|infinity)$', '$file_limit must be an integer, \'unlimited\', or \'infinity\'.') - } + validate_re($file_limit, '^(\d+|-1|unlimited|infinity)$', '$file_limit must be a positive integer, \'-1\', \'unlimited\', or \'infinity\'.') # Validate service parameters. validate_re($service_ensure, '^(running|stopped)$') validate_bool($service_manage) diff --git a/rabbitmq/manifests/install/rabbitmqadmin.pp b/rabbitmq/manifests/install/rabbitmqadmin.pp index bf545eea4..cbb10e106 100644 --- a/rabbitmq/manifests/install/rabbitmqadmin.pp +++ b/rabbitmq/manifests/install/rabbitmqadmin.pp @@ -1,16 +1,17 @@ # class rabbitmq::install::rabbitmqadmin { - if($rabbitmq::ssl) { + if($rabbitmq::ssl and $rabbitmq::management_ssl) { $management_port = $rabbitmq::ssl_management_port + $protocol = 'https' } else { $management_port = $rabbitmq::management_port + $protocol = 'http' } $default_user = $rabbitmq::default_user $default_pass = $rabbitmq::default_pass - $protocol = $rabbitmq::ssl ? { false => 'http', default => 'https' } staging::file { 'rabbitmqadmin': target => "${rabbitmq::rabbitmq_home}/rabbitmqadmin", diff --git a/rabbitmq/manifests/params.pp b/rabbitmq/manifests/params.pp index 7366d9579..15e737881 100644 --- a/rabbitmq/manifests/params.pp +++ b/rabbitmq/manifests/params.pp @@ -66,6 +66,7 @@ #install $admin_enable = true $management_port = '15672' + $management_ssl = true $package_apt_pin = '' $package_gpg_key = 'http://www.rabbitmq.com/rabbitmq-signing-key-public.asc' $repos_ensure = true @@ -117,5 +118,5 @@ $environment_variables = {} $config_variables = {} $config_kernel_variables = {} - $file_limit = 16384 + $file_limit = '16384' } diff --git a/rabbitmq/spec/classes/rabbitmq_spec.rb b/rabbitmq/spec/classes/rabbitmq_spec.rb index 534ba4f1f..45b4b7cd2 100644 --- a/rabbitmq/spec/classes/rabbitmq_spec.rb +++ b/rabbitmq/spec/classes/rabbitmq_spec.rb @@ -150,8 +150,8 @@ it { should contain_file('/etc/default/rabbitmq-server').with_content(/ulimit -n infinity/) } end - context 'with file_limit => -1' do - let(:params) {{ :file_limit => -1 }} + context 'with file_limit => \'-1\'' do + let(:params) {{ :file_limit => '-1' }} it { should contain_file('/etc/default/rabbitmq-server').with_content(/ulimit -n -1/) } end @@ -160,10 +160,17 @@ it { should contain_file('/etc/default/rabbitmq-server').with_content(/ulimit -n 1234/) } end - context 'with file_limit => foo' do + context 'with file_limit => \'-42\'' do + let(:params) {{ :file_limit => '-42' }} + it 'does not compile' do + expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be a positive integer, '-1', 'unlimited', or 'infinity'/) + end + end + + context 'with file_limit => \'foo\'' do let(:params) {{ :file_limit => 'foo' }} it 'does not compile' do - expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be an integer, 'unlimited', or 'infinity'/) + expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be a positive integer, '-1', 'unlimited', or 'infinity'/) end end end @@ -174,6 +181,72 @@ should contain_class('rabbitmq::repo::rhel') should contain_exec('rpm --import http://www.rabbitmq.com/rabbitmq-signing-key-public.asc') end + + context 'with file_limit => \'unlimited\'' do + let(:params) {{ :file_limit => 'unlimited' }} + it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( + 'owner' => '0', + 'group' => '0', + 'mode' => '0644', + 'notify' => 'Class[Rabbitmq::Service]', + 'content' => 'rabbitmq soft nofile unlimited +rabbitmq hard nofile unlimited +' + ) } + end + + context 'with file_limit => \'infinity\'' do + let(:params) {{ :file_limit => 'infinity' }} + it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( + 'owner' => '0', + 'group' => '0', + 'mode' => '0644', + 'notify' => 'Class[Rabbitmq::Service]', + 'content' => 'rabbitmq soft nofile infinity +rabbitmq hard nofile infinity +' + ) } + end + + context 'with file_limit => \'-1\'' do + let(:params) {{ :file_limit => '-1' }} + it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( + 'owner' => '0', + 'group' => '0', + 'mode' => '0644', + 'notify' => 'Class[Rabbitmq::Service]', + 'content' => 'rabbitmq soft nofile -1 +rabbitmq hard nofile -1 +' + ) } + end + + context 'with file_limit => \'1234\'' do + let(:params) {{ :file_limit => '1234' }} + it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( + 'owner' => '0', + 'group' => '0', + 'mode' => '0644', + 'notify' => 'Class[Rabbitmq::Service]', + 'content' => 'rabbitmq soft nofile 1234 +rabbitmq hard nofile 1234 +' + ) } + end + + context 'with file_limit => \'-42\'' do + let(:params) {{ :file_limit => '-42' }} + it 'does not compile' do + expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be a positive integer, '-1', 'unlimited', or 'infinity'/) + end + end + + context 'with file_limit => \'foo\'' do + let(:params) {{ :file_limit => 'foo' }} + it 'does not compile' do + expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be a positive integer, '-1', 'unlimited', or 'infinity'/) + end + end end context 'on Redhat' do @@ -264,7 +337,7 @@ 'notify' => 'Class[Rabbitmq::Service]', 'refreshonly' => true ) } - context 'with file_limit => unlimited' do + context 'with file_limit => \'unlimited\'' do let(:params) {{ :file_limit => 'unlimited' }} it { should contain_file('/etc/systemd/system/rabbitmq-server.service.d/limits.conf').with( 'owner' => '0', @@ -277,7 +350,7 @@ ) } end - context 'with file_limit => infinity' do + context 'with file_limit => \'infinity\'' do let(:params) {{ :file_limit => 'infinity' }} it { should contain_file('/etc/systemd/system/rabbitmq-server.service.d/limits.conf').with( 'owner' => '0', @@ -290,8 +363,8 @@ ) } end - context 'with file_limit => -1' do - let(:params) {{ :file_limit => -1 }} + context 'with file_limit => \'-1\'' do + let(:params) {{ :file_limit => '-1' }} it { should contain_file('/etc/systemd/system/rabbitmq-server.service.d/limits.conf').with( 'owner' => '0', 'group' => '0', @@ -315,76 +388,6 @@ ' ) } end - - context 'with file_limit => foo' do - let(:params) {{ :file_limit => 'foo' }} - it 'does not compile' do - expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be an integer, 'unlimited', or 'infinity'/) - end - end - end - - context 'on RedHat before 7.0' do - let(:facts) {{ :osfamily => 'RedHat', :operatingsystemmajrelease => '6' }} - - context 'with file_limit => unlimited' do - let(:params) {{ :file_limit => 'unlimited' }} - it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( - 'owner' => '0', - 'group' => '0', - 'mode' => '0644', - 'notify' => 'Class[Rabbitmq::Service]', - 'content' => 'rabbitmq soft nofile unlimited -rabbitmq hard nofile unlimited -' - ) } - end - - context 'with file_limit => infinity' do - let(:params) {{ :file_limit => 'infinity' }} - it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( - 'owner' => '0', - 'group' => '0', - 'mode' => '0644', - 'notify' => 'Class[Rabbitmq::Service]', - 'content' => 'rabbitmq soft nofile infinity -rabbitmq hard nofile infinity -' - ) } - end - - context 'with file_limit => -1' do - let(:params) {{ :file_limit => -1 }} - it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( - 'owner' => '0', - 'group' => '0', - 'mode' => '0644', - 'notify' => 'Class[Rabbitmq::Service]', - 'content' => 'rabbitmq soft nofile -1 -rabbitmq hard nofile -1 -' - ) } - end - - context 'with file_limit => \'1234\'' do - let(:params) {{ :file_limit => '1234' }} - it { should contain_file('/etc/security/limits.d/rabbitmq-server.conf').with( - 'owner' => '0', - 'group' => '0', - 'mode' => '0644', - 'notify' => 'Class[Rabbitmq::Service]', - 'content' => 'rabbitmq soft nofile 1234 -rabbitmq hard nofile 1234 -' - ) } - end - - context 'with file_limit => foo' do - let(:params) {{ :file_limit => 'foo' }} - it 'does not compile' do - expect { catalogue }.to raise_error(Puppet::Error, /\$file_limit must be an integer, 'unlimited', or 'infinity'/) - end - end end ['Debian', 'RedHat', 'SUSE', 'Archlinux'].each do |distro| @@ -471,6 +474,25 @@ end end + describe 'with erlang_cookie set but without config_cluster' do + let(:params) {{ + :config_cluster => false, + :erlang_cookie => 'TESTCOOKIE', + }} + it 'contains the rabbitmq_erlang_cookie' do + should contain_rabbitmq_erlang_cookie('/var/lib/rabbitmq/.erlang.cookie') + end + end + + describe 'without erlang_cookie and without config_cluster' do + let(:params) {{ + :config_cluster => false, + }} + it 'contains the rabbitmq_erlang_cookie' do + should_not contain_rabbitmq_erlang_cookie('/var/lib/rabbitmq/.erlang.cookie') + end + end + describe 'and sets appropriate configuration' do let(:params) {{ :config_cluster => true, @@ -640,6 +662,79 @@ end end + describe 'ssl options and mangament_ssl false' do + let(:params) { + { :ssl => true, + :ssl_port => 3141, + :ssl_cacert => '/path/to/cacert', + :ssl_cert => '/path/to/cert', + :ssl_key => '/path/to/key', + :management_ssl => false, + :management_port => 13142 + } } + + it 'should set ssl options to specified values' do + should contain_file('rabbitmq.config').with_content( + %r{ssl_listeners, \[3141\]} + ) + should contain_file('rabbitmq.config').with_content( + %r{ssl_options, \[} + ) + should contain_file('rabbitmq.config').with_content( + %r{cacertfile,"/path/to/cacert"} + ) + should contain_file('rabbitmq.config').with_content( + %r{certfile,"/path/to/cert"} + ) + should contain_file('rabbitmq.config').with_content( + %r{keyfile,"/path/to/key"} + ) + end + it 'should set non ssl port for management port' do + should contain_file('rabbitmq.config').with_content( + %r{port, 13142} + ) + end + end + + describe 'ssl options and mangament_ssl true' do + let(:params) { + { :ssl => true, + :ssl_port => 3141, + :ssl_cacert => '/path/to/cacert', + :ssl_cert => '/path/to/cert', + :ssl_key => '/path/to/key', + :management_ssl => true, + :ssl_management_port => 13141 + } } + + it 'should set ssl options to specified values' do + should contain_file('rabbitmq.config').with_content( + %r{ssl_listeners, \[3141\]} + ) + should contain_file('rabbitmq.config').with_content( + %r{ssl_opts, } + ) + should contain_file('rabbitmq.config').with_content( + %r{ssl_options, \[} + ) + should contain_file('rabbitmq.config').with_content( + %r{cacertfile,"/path/to/cacert"} + ) + should contain_file('rabbitmq.config').with_content( + %r{certfile,"/path/to/cert"} + ) + should contain_file('rabbitmq.config').with_content( + %r{keyfile,"/path/to/key"} + ) + end + it 'should set ssl managment port to specified values' do + should contain_file('rabbitmq.config').with_content( + %r{port, 13141} + ) + end + end + describe 'ssl options' do let(:params) { { :ssl => true, @@ -811,10 +906,11 @@ should contain_file('rabbitmq.config').with_content(%r{listener, \[}) should contain_file('rabbitmq.config').with_content(%r{port, 5926\}}) should contain_file('rabbitmq.config').with_content(%r{ssl, true\}}) - should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[\{cacertfile, "/path/to/cacert"\},}) + should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[}) + should contain_file('rabbitmq.config').with_content(%r{cacertfile, "/path/to/cacert"\},}) should contain_file('rabbitmq.config').with_content(%r{certfile, "/path/to/cert"\},}) should contain_file('rabbitmq.config').with_content(%r{keyfile, "/path/to/key"\}}) - should contain_file('rabbitmq.config').with_content(%r{,\{versions, \['tlsv1.1', 'tlsv1.2'\]\}[\r\n ]*\]\}}) + should contain_file('rabbitmq.config').with_content(%r{,\{versions, \['tlsv1.1', 'tlsv1.2'\]\}}) end end @@ -833,9 +929,10 @@ should contain_file('rabbitmq.config').with_content(%r{listener, \[}) should contain_file('rabbitmq.config').with_content(%r{port, 3141\}}) should contain_file('rabbitmq.config').with_content(%r{ssl, true\}}) - should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[\{cacertfile, "/path/to/cacert"\},}) + should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[}) + should contain_file('rabbitmq.config').with_content(%r{cacertfile, "/path/to/cacert"\},}) should contain_file('rabbitmq.config').with_content(%r{certfile, "/path/to/cert"\},}) - should contain_file('rabbitmq.config').with_content(%r{keyfile, "/path/to/key"\}[\r\n ]*\]\}}) + should contain_file('rabbitmq.config').with_content(%r{keyfile, "/path/to/key"\}}) end end @@ -868,9 +965,10 @@ should contain_file('rabbitmq.config').with_content(%r{listener, \[}) should contain_file('rabbitmq.config').with_content(%r{port, 3141\},}) should contain_file('rabbitmq.config').with_content(%r{ssl, true\},}) - should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[\{cacertfile, "/path/to/cacert"\},}) + should contain_file('rabbitmq.config').with_content(%r{ssl_opts, \[}) + should contain_file('rabbitmq.config').with_content(%r{cacertfile, "/path/to/cacert"\},}) should contain_file('rabbitmq.config').with_content(%r{certfile, "/path/to/cert"\},}) - should contain_file('rabbitmq.config').with_content(%r{keyfile, "/path/to/key"\}[\r\n ]*\]\}}) + should contain_file('rabbitmq.config').with_content(%r{keyfile, "/path/to/key"\}}) end end diff --git a/rabbitmq/spec/unit/puppet/type/rabbitmq_policy_spec.rb b/rabbitmq/spec/unit/puppet/type/rabbitmq_policy_spec.rb index 36bf2a73f..ff96b1d8f 100644 --- a/rabbitmq/spec/unit/puppet/type/rabbitmq_policy_spec.rb +++ b/rabbitmq/spec/unit/puppet/type/rabbitmq_policy_spec.rb @@ -116,4 +116,32 @@ @policy[:definition] = definition }.to raise_error(Puppet::Error, /Invalid expires value.*future/) end + + it 'should accept and convert the message-ttl value' do + definition = {'message-ttl' => '1800000'} + @policy[:definition] = definition + @policy[:definition]['message-ttl'].should be_a(Fixnum) + @policy[:definition]['message-ttl'].should == 1800000 + end + + it 'should not accept non-numeric message-ttl value' do + definition = {'message-ttl' => 'future'} + expect { + @policy[:definition] = definition + }.to raise_error(Puppet::Error, /Invalid message-ttl value.*future/) + end + + it 'should accept and convert the max-length value' do + definition = {'max-length' => '1800000'} + @policy[:definition] = definition + @policy[:definition]['max-length'].should be_a(Fixnum) + @policy[:definition]['max-length'].should == 1800000 + end + + it 'should not accept non-numeric max-length value' do + definition = {'max-length' => 'future'} + expect { + @policy[:definition] = definition + }.to raise_error(Puppet::Error, /Invalid max-length value.*future/) + end end diff --git a/rabbitmq/templates/rabbitmq.config.erb b/rabbitmq/templates/rabbitmq.config.erb index 71b777621..3426ebd7e 100644 --- a/rabbitmq/templates/rabbitmq.config.erb +++ b/rabbitmq/templates/rabbitmq.config.erb @@ -67,10 +67,12 @@ <%- if @admin_enable -%>, {rabbitmq_management, [ {listener, [ -<%- if @ssl -%> +<%- if @ssl && @management_ssl -%> {port, <%= @ssl_management_port %>}, {ssl, true}, - {ssl_opts, [<%- if @ssl_cacert != 'UNSET' -%>{cacertfile, "<%= @ssl_cacert %>"},<%- end -%> + {ssl_opts, [<%- if @ssl_cacert != 'UNSET' %> + {cacertfile, "<%= @ssl_cacert %>"}, + <%- end -%> {certfile, "<%= @ssl_cert %>"}, {keyfile, "<%= @ssl_key %>"} diff --git a/rabbitmq/templates/rabbitmqadmin.conf.erb b/rabbitmq/templates/rabbitmqadmin.conf.erb index d76c81147..5ea629c22 100644 --- a/rabbitmq/templates/rabbitmqadmin.conf.erb +++ b/rabbitmq/templates/rabbitmqadmin.conf.erb @@ -1,5 +1,5 @@ [default] -<% if @ssl -%> +<% if @ssl && @management_ssl -%> ssl = True port = <%= @ssl_management_port %> <% else -%> From 639fcba6f61069f236f5d288dd6a11b5a4364e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=A1gr?= Date: Thu, 15 Oct 2015 13:24:34 +0200 Subject: [PATCH 05/54] stable/kilo update This commit is setting modules to following state: ceph - old commit: b6ab15b47c81d7694fdcfd75d8f2e0a0481ca40c - new commit: 71fccdf944a2b0721a972a8a86f97703cabd586e cinder - old commit: b2163382956032f6df37d8a02f18a4abf89b7008 - new commit: 330dda3c4106ffef318d330f4de303b631196581 gnocchi - old commit: 388ace2495661ff909b45c00471a121b5f2d18e3 - new commit: 02692807d218210a27a4043e27b3aa0ac38e8b28 keystone - old commit: 1fb920c38df80a75779ea34b5181534ff9207738 - new commit: 6dbef6298478b5a8799c9dadd8d0b4b7edbcdd74 n1k_vsm - old commit: 7b57af350fdb25830e0136658324f9c51e49657f - new commit: 8266fb6dd504bc6ab310644728b076a6de996cbd nova - old commit: 52e7f810a50f15e2c32cd1270374899ef7df675f - new commit: ea1eddfaa04a3c44d9b6863bb4a87c89b91f3305 pacemaker - old commit: 1fa8e5591ab606a7be3bae32df088f6cec26d3c0 - new commit: 733c1088ccfa24739929af7a8612ff0ade46bc6f tripleo - old commit: 717eb39ca7295e128ab99694ea3a7ae658b9528f - new commit: a003b3d97ebe8bd470717c419434851d60669bf7 Change-Id: Ic75fb9b8daeb06991daed9c6540988b97da34326 --- Puppetfile | 16 +- ceph/.fixtures.yml | 4 +- ceph/Gemfile | 4 +- ceph/Gemfile-rspec-system | 2 +- ceph/Puppetfile | 4 +- ceph/README.md | 10 +- ceph/manifests/repo.pp | 37 ++- ceph/manifests/rgw.pp | 2 +- ceph/metadata.json | 4 +- ceph/spec/acceptance/ceph_usecases_spec.rb | 20 +- .../spec/acceptance/nodesets/centos70-x64.yml | 15 + .../{nodepool.yml => nodepool-centos7.yml} | 3 +- .../acceptance/nodesets/nodepool-trusty.yml | 13 + ceph/spec/classes/ceph_mons_spec.rb | 17 +- ceph/spec/classes/ceph_profile_base_spec.rb | 13 +- ceph/spec/classes/ceph_profile_client_spec.rb | 18 +- ceph/spec/classes/ceph_profile_mon_spec.rb | 19 +- ceph/spec/classes/ceph_profile_osd_spec.rb | 18 +- ceph/spec/classes/ceph_repo_spec.rb | 299 ++++++++++++++++-- ceph/spec/defines/ceph_key_spec.rb | 6 +- ceph/spec/defines/ceph_mon_spec.rb | 60 ++-- ceph/spec/defines/ceph_osd_spec.rb | 10 +- ceph/spec/defines/ceph_pool_spec.rb | 14 +- ceph/spec/defines/ceph_rgw_apache_spec.rb | 64 ++-- ceph/spec/defines/ceph_rgw_spec.rb | 48 +-- ceph/spec/spec_helper_acceptance.rb | 14 +- ceph/spec/spec_helper_system.rb | 10 +- ceph/spec/system/ceph_key_spec.rb | 50 +-- ceph/spec/system/ceph_mon_spec.rb | 102 +++--- ceph/spec/system/ceph_mons_spec.rb | 118 +++---- ceph/spec/system/ceph_osd_spec.rb | 118 +++---- ceph/spec/system/ceph_osds_spec.rb | 24 +- ceph/spec/system/ceph_pool_spec.rb | 40 +-- ceph/spec/system/ceph_profile_base_spec.rb | 18 +- ceph/spec/system/ceph_profile_client_spec.rb | 50 +-- ceph/spec/system/ceph_profile_mon_spec.rb | 108 +++---- ceph/spec/system/ceph_profile_osd_spec.rb | 108 +++---- ceph/spec/system/ceph_repo_spec.rb | 124 ++++---- ceph/spec/system/ceph_rgw_apache_spec.rb | 26 +- ceph/spec/system/ceph_usecases_spec.rb | 116 +++---- .../provider/ceph_config/ini_setting_spec.rb | 8 +- ceph/spec/unit/type/ceph_config_spec.rb | 6 +- cinder/manifests/api.pp | 16 + cinder/manifests/cron/db_purge.pp | 76 +++++ cinder/spec/acceptance/basic_cinder_spec.rb | 6 + cinder/spec/classes/cinder_api_spec.rb | 17 + .../spec/classes/cinder_cron_db_purge_spec.rb | 33 ++ gnocchi/.fixtures.yml | 13 - gnocchi/.gitignore | 14 +- gnocchi/Gemfile | 42 +-- gnocchi/README.md | 30 ++ gnocchi/Rakefile | 86 ++++- .../provider/gnocchi_config/ini_setting.rb | 19 +- gnocchi/lib/puppet/type/gnocchi_config.rb | 11 + gnocchi/manifests/api.pp | 70 ++-- gnocchi/manifests/config.pp | 30 ++ gnocchi/manifests/generic_service.pp | 2 + gnocchi/manifests/keystone/auth.pp | 6 +- gnocchi/manifests/logging.pp | 265 ++++++++++++++++ .../acceptance/nodesets/centos-70-x64.yml | 11 + gnocchi/spec/acceptance/nodesets/default.yml | 11 +- .../acceptance/nodesets/nodepool-centos7.yml | 2 +- .../acceptance/nodesets/nodepool-trusty.yml | 2 +- .../nodesets/ubuntu-server-1404-x64.yml | 12 +- gnocchi/spec/classes/gnocchi_api_spec.rb | 6 +- gnocchi/spec/classes/gnocchi_config_spec.rb | 20 ++ gnocchi/spec/classes/gnocchi_logging_spec.rb | 146 +++++++++ gnocchi/spec/shared_examples.rb | 12 +- gnocchi/spec/spec_helper.rb | 3 + .../gnocchi_config/ini_setting_spec.rb | 29 ++ gnocchi/spec/unit/type/gnocchi_config_spec.rb | 11 + keystone/manifests/cron/token_flush.pp | 21 +- .../classes/keystone_cron_token_flush_spec.rb | 67 ++-- n1k_vsm/.fixtures.yml | 5 + n1k_vsm/Gemfile | 30 +- n1k_vsm/manifests/deploy.pp | 67 +++- n1k_vsm/manifests/init.pp | 35 +- n1k_vsm/manifests/pkgprep_ovscfg.pp | 90 +++--- n1k_vsm/manifests/vsmprep.pp | 27 +- .../acceptance/nodesets/centos-70-x64.yml | 11 + n1k_vsm/spec/acceptance/nodesets/default.yml | 11 + .../acceptance/nodesets/nodepool-centos7.yml | 10 + .../acceptance/nodesets/nodepool-trusty.yml | 10 + .../nodesets/ubuntu-server-1404-x64.yml | 11 + n1k_vsm/spec/classes/n1kv_vsm_spec.rb | 21 ++ n1k_vsm/spec/classes/n1kv_vsm_vsmprep_spec.rb | 78 +++++ n1k_vsm/spec/shared_examples.rb | 5 + n1k_vsm/spec/spec_helper.rb | 19 ++ n1k_vsm/spec/spec_helper_acceptance.rb | 56 ++++ n1k_vsm/templates/vsm_vm.xml.erb | 9 + n1k_vsm/templates/vsm_vm_secondary.xml.erb | 92 ++++++ .../puppet/provider/nova_admin/nova_manage.rb | 20 -- .../provider/nova_project/nova_manage.rb | 19 -- nova/lib/puppet/type/nova_admin.rb | 11 - nova/lib/puppet/type/nova_project.rb | 21 -- nova/manifests/cron/archive_deleted_rows.pp | 21 +- .../nova_cron_archive_deleted_rows_spec.rb | 23 +- pacemaker/README.md | 8 + .../provider/pcmk_resource_default/pcs.rb | 54 ++++ .../lib/puppet/type/pcmk_resource_default.rb | 16 + pacemaker/manifests/corosync.pp | 32 +- pacemaker/manifests/resource_defaults.pp | 12 + tripleo/.fixtures.yml | 6 + tripleo/.gitignore | 13 +- tripleo/.sync.yml | 3 + tripleo/Gemfile | 42 +-- tripleo/Rakefile | 22 +- .../provider/package_manifest/flat_file.rb | 39 +++ tripleo/lib/puppet/type/package_manifest.rb | 8 + tripleo/manifests/firewall.pp | 91 ++++++ tripleo/manifests/firewall/post.pp | 51 +++ tripleo/manifests/firewall/pre.pp | 57 ++++ tripleo/manifests/firewall/rule.pp | 80 +++++ tripleo/manifests/loadbalancer.pp | 121 ++++--- tripleo/manifests/noop.pp | 68 ++++ tripleo/manifests/packages.pp | 5 +- .../acceptance/nodesets/centos-70-x64.yml | 11 + tripleo/spec/acceptance/nodesets/default.yml | 11 + .../acceptance/nodesets/nodepool-centos7.yml | 10 + .../acceptance/nodesets/nodepool-trusty.yml | 10 + .../nodesets/ubuntu-server-1404-x64.yml | 11 + tripleo/spec/classes/tripleo_firewall_spec.rb | 114 +++++++ tripleo/spec/classes/tripleo_init_spec.rb | 23 ++ tripleo/spec/spec_helper.rb | 3 + tripleo/spec/spec_helper_acceptance.rb | 56 ++++ .../spec/unit/type/package_manifest_spec.rb | 37 +++ 126 files changed, 3460 insertions(+), 1105 deletions(-) create mode 100644 ceph/spec/acceptance/nodesets/centos70-x64.yml rename ceph/spec/acceptance/nodesets/{nodepool.yml => nodepool-centos7.yml} (76%) create mode 100644 ceph/spec/acceptance/nodesets/nodepool-trusty.yml create mode 100644 cinder/manifests/cron/db_purge.pp create mode 100644 cinder/spec/classes/cinder_cron_db_purge_spec.rb delete mode 100644 gnocchi/.fixtures.yml create mode 100644 gnocchi/manifests/config.pp create mode 100644 gnocchi/manifests/logging.pp create mode 100644 gnocchi/spec/acceptance/nodesets/centos-70-x64.yml create mode 100644 gnocchi/spec/classes/gnocchi_config_spec.rb create mode 100644 gnocchi/spec/classes/gnocchi_logging_spec.rb create mode 100644 n1k_vsm/.fixtures.yml create mode 100644 n1k_vsm/spec/acceptance/nodesets/centos-70-x64.yml create mode 100644 n1k_vsm/spec/acceptance/nodesets/default.yml create mode 100644 n1k_vsm/spec/acceptance/nodesets/nodepool-centos7.yml create mode 100644 n1k_vsm/spec/acceptance/nodesets/nodepool-trusty.yml create mode 100644 n1k_vsm/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml create mode 100644 n1k_vsm/spec/classes/n1kv_vsm_spec.rb create mode 100644 n1k_vsm/spec/classes/n1kv_vsm_vsmprep_spec.rb create mode 100644 n1k_vsm/spec/shared_examples.rb create mode 100644 n1k_vsm/spec/spec_helper.rb create mode 100644 n1k_vsm/spec/spec_helper_acceptance.rb create mode 100644 n1k_vsm/templates/vsm_vm_secondary.xml.erb delete mode 100644 nova/lib/puppet/provider/nova_admin/nova_manage.rb delete mode 100644 nova/lib/puppet/provider/nova_project/nova_manage.rb delete mode 100644 nova/lib/puppet/type/nova_admin.rb delete mode 100644 nova/lib/puppet/type/nova_project.rb create mode 100644 pacemaker/lib/puppet/provider/pcmk_resource_default/pcs.rb create mode 100644 pacemaker/lib/puppet/type/pcmk_resource_default.rb create mode 100644 pacemaker/manifests/resource_defaults.pp create mode 100644 tripleo/.fixtures.yml create mode 100644 tripleo/.sync.yml create mode 100644 tripleo/lib/puppet/provider/package_manifest/flat_file.rb create mode 100644 tripleo/lib/puppet/type/package_manifest.rb create mode 100644 tripleo/manifests/firewall.pp create mode 100644 tripleo/manifests/firewall/post.pp create mode 100644 tripleo/manifests/firewall/pre.pp create mode 100644 tripleo/manifests/firewall/rule.pp create mode 100644 tripleo/manifests/noop.pp create mode 100644 tripleo/spec/acceptance/nodesets/centos-70-x64.yml create mode 100644 tripleo/spec/acceptance/nodesets/default.yml create mode 100644 tripleo/spec/acceptance/nodesets/nodepool-centos7.yml create mode 100644 tripleo/spec/acceptance/nodesets/nodepool-trusty.yml create mode 100644 tripleo/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml create mode 100644 tripleo/spec/classes/tripleo_firewall_spec.rb create mode 100644 tripleo/spec/classes/tripleo_init_spec.rb create mode 100644 tripleo/spec/spec_helper_acceptance.rb create mode 100644 tripleo/spec/unit/type/package_manifest_spec.rb diff --git a/Puppetfile b/Puppetfile index 6a9976719..06975df0b 100644 --- a/Puppetfile +++ b/Puppetfile @@ -11,7 +11,7 @@ mod 'ceilometer', :git => 'https://github.com/openstack/puppet-ceilometer.git' mod 'ceph', - :commit => 'b6ab15b47c81d7694fdcfd75d8f2e0a0481ca40c', + :commit => '71fccdf944a2b0721a972a8a86f97703cabd586e', :git => 'https://github.com/stackforge/puppet-ceph.git' mod 'certmonger', @@ -19,7 +19,7 @@ mod 'certmonger', :git => 'https://github.com/rcritten/puppet-certmonger.git' mod 'cinder', - :commit => 'b2163382956032f6df37d8a02f18a4abf89b7008', + :commit => '330dda3c4106ffef318d330f4de303b631196581', :git => 'https://github.com/openstack/puppet-cinder.git' mod 'common', @@ -51,7 +51,7 @@ mod 'gluster', :git => 'https://github.com/purpleidea/puppet-gluster.git' mod 'gnocchi', - :commit => '388ace2495661ff909b45c00471a121b5f2d18e3', + :commit => '02692807d218210a27a4043e27b3aa0ac38e8b28', :git => 'https://github.com/openstack/puppet-gnocchi.git' mod 'haproxy', @@ -83,7 +83,7 @@ mod 'keepalived', :git => 'https://github.com/Unyonsys/puppet-module-keepalived.git' mod 'keystone', - :commit => '1fb920c38df80a75779ea34b5181534ff9207738', + :commit => '6dbef6298478b5a8799c9dadd8d0b4b7edbcdd74', :git => 'https://github.com/openstack/puppet-keystone.git' mod 'manila', @@ -111,7 +111,7 @@ mod 'mysql', :git => 'https://github.com/puppetlabs/puppetlabs-mysql.git' mod 'n1k_vsm', - :commit => '7b57af350fdb25830e0136658324f9c51e49657f', + :commit => '8266fb6dd504bc6ab310644728b076a6de996cbd', :git => 'https://github.com/stackforge/puppet-n1k-vsm.git' mod 'nagios', @@ -123,7 +123,7 @@ mod 'neutron', :git => 'https://github.com/openstack/puppet-neutron.git' mod 'nova', - :commit => '52e7f810a50f15e2c32cd1270374899ef7df675f', + :commit => 'ea1eddfaa04a3c44d9b6863bb4a87c89b91f3305', :git => 'https://github.com/openstack/puppet-nova.git' mod 'nssdb', @@ -143,7 +143,7 @@ mod 'openstacklib', :git => 'https://github.com/openstack/puppet-openstacklib.git' mod 'pacemaker', - :commit => '1fa8e5591ab606a7be3bae32df088f6cec26d3c0', + :commit => '733c1088ccfa24739929af7a8612ff0ade46bc6f', :git => 'https://github.com/redhat-openstack/puppet-pacemaker.git' mod 'puppet', @@ -207,7 +207,7 @@ mod 'timezone', :git => 'https://github.com/saz/puppet-timezone.git' mod 'tripleo', - :commit => '717eb39ca7295e128ab99694ea3a7ae658b9528f', + :commit => 'a003b3d97ebe8bd470717c419434851d60669bf7', :git => 'https://github.com/openstack/puppet-tripleo.git' mod 'trove', diff --git a/ceph/.fixtures.yml b/ceph/.fixtures.yml index 9428e1cf0..0448cc0ae 100644 --- a/ceph/.fixtures.yml +++ b/ceph/.fixtures.yml @@ -7,10 +7,10 @@ fixtures: 'inifile': 'git://github.com/puppetlabs/puppetlabs-inifile' 'apache': repo: 'git://github.com/puppetlabs/puppetlabs-apache' - ref: '1.0.1' + ref: '1.4.1' 'concat': repo: 'git://github.com/puppetlabs/puppetlabs-concat' - ref: '1.1.0' + ref: '1.2.1' symlinks: 'ceph': "#{source_dir}" diff --git a/ceph/Gemfile b/ceph/Gemfile index 0511f9d06..e3e4a8158 100644 --- a/ceph/Gemfile +++ b/ceph/Gemfile @@ -2,8 +2,8 @@ source 'https://rubygems.org' group :development, :test do gem 'puppetlabs_spec_helper', :require => false - gem 'rspec-puppet', '~> 2.0.0', :require => false - gem 'beaker-rspec', '~> 2.2.4', :require => false + gem 'rspec-puppet', '~> 2.1.0', :require => false + gem 'beaker-rspec', :require => false gem 'puppet-lint-param-docs' gem 'metadata-json-lint' gem 'puppet-lint-absolute_classname-check' diff --git a/ceph/Gemfile-rspec-system b/ceph/Gemfile-rspec-system index cce2000a1..1927be5de 100644 --- a/ceph/Gemfile-rspec-system +++ b/ceph/Gemfile-rspec-system @@ -3,7 +3,7 @@ source 'https://rubygems.org' group :development, :test do gem 'puppetlabs_spec_helper', :require => false - gem 'rspec-puppet', '~> 2.0.0', :require => false + gem 'rspec-puppet', '~> 2.1.0', :require => false gem 'metadata-json-lint' gem 'puppet-lint-param-docs' gem 'puppet-lint-absolute_classname-check' diff --git a/ceph/Puppetfile b/ceph/Puppetfile index 65400b5f6..f84861ad4 100644 --- a/ceph/Puppetfile +++ b/ceph/Puppetfile @@ -17,8 +17,8 @@ mod 'bodepd/scenario_node_terminus', mod 'puppetlabs/apache', :git => 'git://github.com/puppetlabs/puppetlabs-apache', - :ref => '1.0.1' + :ref => '1.4.1' mod 'puppetlabs/concat', :git => 'git://github.com/puppetlabs/puppetlabs-concat', - :ref => '1.1.x' + :ref => '1.2.1' diff --git a/ceph/README.md b/ceph/README.md index f3ae2179c..bdd0b03b2 100644 --- a/ceph/README.md +++ b/ceph/README.md @@ -128,10 +128,12 @@ The RS_SET environment variable contains the resource set of linux distribution configurations for which integration tests are going to be run. Available values are -* two-ubuntu-server-1204-x64 -* ubuntu-server-1204-x64 -* two-centos-66-x64 -* centos-66-x64 +* two-ubuntu-server-12042-x64 +* one-ubuntu-server-12042-x64 +* two-centos-65-x64 +* one-centos-65-x64 +* two-centos-70-x64 +* one-centos-70-x64 The default is diff --git a/ceph/manifests/repo.pp b/ceph/manifests/repo.pp index 45662b0d7..c01c2ebb7 100644 --- a/ceph/manifests/repo.pp +++ b/ceph/manifests/repo.pp @@ -2,6 +2,7 @@ # Copyright (C) 2013 Cloudwatt # Copyright (C) 2014 Nine Internet Solutions AG # Copyright (C) 2014 Catalyst IT Limited +# Copyright (C) 2015 Red Hat # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -21,6 +22,7 @@ # Author: Andrew Woodward # Author: David Gurtner # Author: Ricardo Rocha +# Author: Emilien Macchi # # == Class: ceph::repo # @@ -53,7 +55,7 @@ apt::key { 'ceph': ensure => $ensure, key => '17ED316D', - key_source => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', + key_source => 'http://git.ceph.com/?p=ceph.git;a=blob_plain;f=keys/release.asc', } apt::source { 'ceph': @@ -98,17 +100,34 @@ 'RedHat': { $enabled = $ensure ? { 'present' => '1', 'absent' => '0', default => absent, } - yumrepo { 'ext-epel-6.8': + + if ((($::operatingsystem == 'RedHat' or $::operatingsystem == 'CentOS') and (versioncmp($::operatingsystemmajrelease, '7') < 0)) or ($::operatingsystem == 'Fedora' and (versioncmp($::operatingsystemmajrelease, '19') < 0))) { + $el = '6' + } else { + $el = '7' + } + + if ($::operatingsystem == 'CentOS') { + file_line { 'exclude base': + ensure => $ensure, + path => '/etc/yum.repos.d/CentOS-Base.repo', + after => '^\[base\]$', + line => 'exclude=python-ceph-compat python-rbd python-rados python-cephfs', + } -> Package<| tag == 'ceph' |> + } + + yumrepo { "ext-epel-${el}": # puppet versions prior to 3.5 do not support ensure, use enabled instead enabled => $enabled, - descr => 'External EPEL 6.8', - name => 'ext-epel-6.8', + descr => "External EPEL ${el}", + name => "ext-epel-${el}", baseurl => absent, gpgcheck => '0', gpgkey => absent, - mirrorlist => 'http://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch', + mirrorlist => "http://mirrors.fedoraproject.org/metalink?repo=epel-${el}&arch=\$basearch", priority => '20', # prefer ceph repos over EPEL tag => 'ceph', + exclude => 'python-ceph-compat python-rbd python-rados python-cephfs', } yumrepo { 'ext-ceph': @@ -116,7 +135,7 @@ enabled => $enabled, descr => "External Ceph ${release}", name => "ext-ceph-${release}", - baseurl => "http://ceph.com/rpm-${release}/el6/\$basearch", + baseurl => "http://ceph.com/rpm-${release}/el${el}/\$basearch", gpgcheck => '1', gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', mirrorlist => absent, @@ -129,7 +148,7 @@ enabled => $enabled, descr => 'External Ceph noarch', name => "ext-ceph-${release}-noarch", - baseurl => "http://ceph.com/rpm-${release}/el6/noarch", + baseurl => "http://ceph.com/rpm-${release}/el${el}/noarch", gpgcheck => '1', gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', mirrorlist => absent, @@ -137,7 +156,7 @@ tag => 'ceph', } - if $extras { + if $extras and $el == '6' { yumrepo { 'ext-ceph-extras': enabled => $enabled, @@ -159,7 +178,7 @@ enabled => $enabled, descr => 'FastCGI basearch packages for Ceph', name => 'ext-ceph-fastcgi', - baseurl => 'http://gitbuilder.ceph.com/mod_fastcgi-rpm-rhel6-x86_64-basic/ref/master', + baseurl => "http://gitbuilder.ceph.com/mod_fastcgi-rpm-rhel${el}-x86_64-basic/ref/master", gpgcheck => '1', gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/autobuild.asc', mirrorlist => absent, diff --git a/ceph/manifests/rgw.pp b/ceph/manifests/rgw.pp index 727b93972..7fad377ab 100644 --- a/ceph/manifests/rgw.pp +++ b/ceph/manifests/rgw.pp @@ -24,7 +24,7 @@ # # === Parameters: # -# [*pgk_cephrgw*] Package name for the ceph radosgw. +# [*pkg_radosgw*] Package name for the ceph radosgw. # Optional. Default is osfamily dependent (check ceph::params). # # [*rgw_data*] The path where the radosgw data should be stored. diff --git a/ceph/metadata.json b/ceph/metadata.json index 989784120..8fee7ef4b 100644 --- a/ceph/metadata.json +++ b/ceph/metadata.json @@ -32,8 +32,8 @@ "description": "Installs and configures Ceph.", "dependencies": [ { "name": "puppetlabs/apt", "version_requirement": ">=1.4.0 <2.0.0" }, - { "name": "puppetlabs/apache", "version_requirement": ">=1.0.1 <2.0.0" }, - { "name": "puppetlabs/concat", "version_requirement": ">=1.1.0 <2.0.0" }, + { "name": "puppetlabs/apache", "version_requirement": ">=1.4.1 <2.0.0" }, + { "name": "puppetlabs/concat", "version_requirement": ">=1.2.1 <2.0.0" }, { "name": "puppetlabs/inifile", "version_requirement": ">=1.0.0 <2.0.0" }, { "name": "puppetlabs/stdlib", "version_requirement": ">=4.0.0 <5.0.0" } ] diff --git a/ceph/spec/acceptance/ceph_usecases_spec.rb b/ceph/spec/acceptance/ceph_usecases_spec.rb index 12ca10683..523ce2905 100644 --- a/ceph/spec/acceptance/ceph_usecases_spec.rb +++ b/ceph/spec/acceptance/ceph_usecases_spec.rb @@ -51,13 +51,13 @@ class { 'ceph': shell 'sleep 10' # we need to wait a bit until the OSD is up shell 'ceph -s', { :acceptable_exit_codes => [0] } do |r| - r.stdout.should =~ /1 mons at/ - r.stderr.should be_empty + expect(r.stdout).to match(/1 mons at/) + expect(r.stderr).to be_empty end shell 'ceph osd tree', { :acceptable_exit_codes => [0] } do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty end end @@ -93,14 +93,14 @@ class { 'ceph': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=a', { :acceptable_exit_codes => [1] } do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.a/ + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.a/) end end if osfamily == 'RedHat' shell 'service ceph status mon.a', { :acceptable_exit_codes => [1] } do |r| - r.stdout.should =~ /mon.a not found/ - r.stderr.should be_empty + expect(r.stdout).to match(/mon.a not found/) + expect(r.stderr).to be_empty end end end @@ -116,7 +116,9 @@ class { 'ceph::repo': EOS apply_manifest(pp, :catch_failures => true) - apply_manifest(pp, :catch_changes => true) + # can't check for idempotency because of https://tickets.puppetlabs.com/browse/PUP-1198 + #apply_manifest(pp, :catch_changes => true) + apply_manifest(pp, :catch_failures => true) end end end diff --git a/ceph/spec/acceptance/nodesets/centos70-x64.yml b/ceph/spec/acceptance/nodesets/centos70-x64.yml new file mode 100644 index 000000000..b75c1f17d --- /dev/null +++ b/ceph/spec/acceptance/nodesets/centos70-x64.yml @@ -0,0 +1,15 @@ +HOSTS: + first: + roles: + - master + - mon + - osd + - client + platform: el-7-x86_64 + box: puppetlabs/centos-7.0-64-nocm + box_url: https://atlas.hashicorp.com/puppetlabs/boxes/centos-7.0-64-nocm + hypervisor: vagrant + ip: 10.11.12.2 +CONFIG: + type: foss + set_env: false diff --git a/ceph/spec/acceptance/nodesets/nodepool.yml b/ceph/spec/acceptance/nodesets/nodepool-centos7.yml similarity index 76% rename from ceph/spec/acceptance/nodesets/nodepool.yml rename to ceph/spec/acceptance/nodesets/nodepool-centos7.yml index 0765232d5..d52883df5 100644 --- a/ceph/spec/acceptance/nodesets/nodepool.yml +++ b/ceph/spec/acceptance/nodesets/nodepool-centos7.yml @@ -5,8 +5,9 @@ HOSTS: - mon - osd - client - platform: ubuntu-1404-amd64 + platform: el-7-x86_64 hypervisor: none ip: 127.0.0.1 CONFIG: type: foss + set_env: false diff --git a/ceph/spec/acceptance/nodesets/nodepool-trusty.yml b/ceph/spec/acceptance/nodesets/nodepool-trusty.yml new file mode 100644 index 000000000..dc22d561a --- /dev/null +++ b/ceph/spec/acceptance/nodesets/nodepool-trusty.yml @@ -0,0 +1,13 @@ +HOSTS: + first: + roles: + - master + - mon + - osd + - client + platform: ubuntu-14.04-amd64 + hypervisor: none + ip: 127.0.0.1 +CONFIG: + type: foss + set_env: false diff --git a/ceph/spec/classes/ceph_mons_spec.rb b/ceph/spec/classes/ceph_mons_spec.rb index a46b6dbad..a21e5b46b 100644 --- a/ceph/spec/classes/ceph_mons_spec.rb +++ b/ceph/spec/classes/ceph_mons_spec.rb @@ -68,11 +68,22 @@ it_configures 'ceph mons' end - describe 'RedHat' do + describe 'RHEL6' do let :facts do { - :osfamily => 'RedHat', - :operatingsystem => 'RedHat', + :osfamily => 'RedHat', + :operatingsystemmajrelease => '6', + } + end + + it_configures 'ceph mons' + end + + describe 'RHEL7' do + let :facts do + { + :osfamily => 'RedHat', + :operatingsystemmajrelease => '7', } end diff --git a/ceph/spec/classes/ceph_profile_base_spec.rb b/ceph/spec/classes/ceph_profile_base_spec.rb index f1c1d9b9e..cdf4bf414 100644 --- a/ceph/spec/classes/ceph_profile_base_spec.rb +++ b/ceph/spec/classes/ceph_profile_base_spec.rb @@ -63,7 +63,18 @@ context 'on RHEL6' do let :facts do - { :osfamily => 'RedHat', } + { :osfamily => 'RedHat', + :operatingsystemmajrelease => '6' } + end + + it_configures 'ceph profile base' + end + + context 'on RHEL7' do + + let :facts do + { :osfamily => 'RedHat', + :operatingsystemmajrelease => '7' } end it_configures 'ceph profile base' diff --git a/ceph/spec/classes/ceph_profile_client_spec.rb b/ceph/spec/classes/ceph_profile_client_spec.rb index f5483ec3a..c830b4868 100644 --- a/ceph/spec/classes/ceph_profile_client_spec.rb +++ b/ceph/spec/classes/ceph_profile_client_spec.rb @@ -118,12 +118,22 @@ context 'on RHEL6' do let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'RHEL6', - } + { :osfamily => 'RedHat', + :operatingsystemmajrelease => '6' } end + + it_configures 'ceph profile client' + end + + context 'on RHEL7' do + + let :facts do + { :osfamily => 'RedHat', + :operatingsystemmajrelease => '7' } + end + + it_configures 'ceph profile client' end end diff --git a/ceph/spec/classes/ceph_profile_mon_spec.rb b/ceph/spec/classes/ceph_profile_mon_spec.rb index b7de0bbd3..33bea69d3 100644 --- a/ceph/spec/classes/ceph_profile_mon_spec.rb +++ b/ceph/spec/classes/ceph_profile_mon_spec.rb @@ -92,11 +92,20 @@ context 'on RHEL6' do let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'RHEL6', - :hostname => 'first', - } + { :osfamily => 'RedHat', + :hostname => 'first', + :operatingsystemmajrelease => '6' } + end + + it_configures 'ceph profile mon' + end + + context 'on RHEL7' do + + let :facts do + { :osfamily => 'RedHat', + :hostname => 'first', + :operatingsystemmajrelease => '7' } end it_configures 'ceph profile mon' diff --git a/ceph/spec/classes/ceph_profile_osd_spec.rb b/ceph/spec/classes/ceph_profile_osd_spec.rb index c4979d4b6..0b309bdd3 100644 --- a/ceph/spec/classes/ceph_profile_osd_spec.rb +++ b/ceph/spec/classes/ceph_profile_osd_spec.rb @@ -68,13 +68,21 @@ it_configures 'ceph profile osd' end - describe 'on RedHat' do + describe 'on RHEL6' do let :facts do - { - :osfamily => 'RedHat', - :operatingsystem => 'RHEL6', - } + { :osfamily => 'RedHat', + :operatingsystemmajrelease => '6' } + end + + it_configures 'ceph profile osd' + end + + describe 'on RHEL7' do + + let :facts do + { :osfamily => 'RedHat', + :operatingsystemmajrelease => '7' } end it_configures 'ceph profile osd' diff --git a/ceph/spec/classes/ceph_repo_spec.rb b/ceph/spec/classes/ceph_repo_spec.rb index 5181e8e67..c10e4442c 100644 --- a/ceph/spec/classes/ceph_repo_spec.rb +++ b/ceph/spec/classes/ceph_repo_spec.rb @@ -34,7 +34,7 @@ it { is_expected.to contain_apt__key('ceph').with( :key => '17ED316D', - :key_source => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc' + :key_source => 'http://git.ceph.com/?p=ceph.git;a=blob_plain;f=keys/release.asc' ) } it { is_expected.to contain_apt__source('ceph').with( @@ -75,7 +75,7 @@ it { is_expected.to contain_apt__key('ceph').with( :key => '17ED316D', - :key_source => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc' + :key_source => 'http://git.ceph.com/?p=ceph.git;a=blob_plain;f=keys/release.asc' ) } it { is_expected.to contain_apt__source('ceph').with( @@ -187,21 +187,24 @@ let :facts do { - :osfamily => 'RedHat', + :osfamily => 'RedHat', + :operatingsystem => 'RedHat', + :operatingsystemmajrelease => '6', } end describe "with default params" do - it { is_expected.to contain_yumrepo('ext-epel-6.8').with( + it { is_expected.to contain_yumrepo('ext-epel-6').with( :enabled => '1', - :descr => 'External EPEL 6.8', - :name => 'ext-epel-6.8', + :descr => 'External EPEL 6', + :name => 'ext-epel-6', :baseurl => 'absent', :gpgcheck => '0', :gpgkey => 'absent', :mirrorlist => 'http://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch', - :priority => '20' + :priority => '20', + :exclude => 'python-ceph-compat python-rbd python-rados python-cephfs', ) } it { is_expected.to contain_yumrepo('ext-ceph').with( @@ -234,15 +237,16 @@ } end - it { is_expected.to contain_yumrepo('ext-epel-6.8').with( + it { is_expected.to contain_yumrepo('ext-epel-6').with( :enabled => '1', - :descr => 'External EPEL 6.8', - :name => 'ext-epel-6.8', + :descr => 'External EPEL 6', + :name => 'ext-epel-6', :baseurl => 'absent', :gpgcheck => '0', :gpgkey => 'absent', :mirrorlist => 'http://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch', - :priority => '20' + :priority => '20', + :exclude => 'python-ceph-compat python-rbd python-rados python-cephfs', ) } it { is_expected.to contain_yumrepo('ext-ceph').with( @@ -277,15 +281,16 @@ } end - it { is_expected.to contain_yumrepo('ext-epel-6.8').with( + it { is_expected.to contain_yumrepo('ext-epel-6').with( :enabled => '0', - :descr => 'External EPEL 6.8', - :name => 'ext-epel-6.8', + :descr => 'External EPEL 6', + :name => 'ext-epel-6', :baseurl => 'absent', :gpgcheck => '0', :gpgkey => 'absent', :mirrorlist => 'http://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch', - :priority => '20' + :priority => '20', + :exclude => 'python-ceph-compat python-rbd python-rados python-cephfs', ) } it { is_expected.to contain_yumrepo('ext-ceph').with( @@ -341,15 +346,16 @@ } end - it { is_expected.to contain_yumrepo('ext-epel-6.8').with( + it { is_expected.to contain_yumrepo('ext-epel-6').with( :enabled => '1', - :descr => 'External EPEL 6.8', - :name => 'ext-epel-6.8', + :descr => 'External EPEL 6', + :name => 'ext-epel-6', :baseurl => 'absent', :gpgcheck => '0', :gpgkey => 'absent', :mirrorlist => 'http://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch', - :priority => '20' + :priority => '20', + :exclude => 'python-ceph-compat python-rbd python-rados python-cephfs', ) } it { is_expected.to contain_yumrepo('ext-ceph').with( @@ -394,15 +400,16 @@ } end - it { is_expected.to contain_yumrepo('ext-epel-6.8').with( + it { is_expected.to contain_yumrepo('ext-epel-6').with( :enabled => '1', - :descr => 'External EPEL 6.8', - :name => 'ext-epel-6.8', + :descr => 'External EPEL 6', + :name => 'ext-epel-6', :baseurl => 'absent', :gpgcheck => '0', :gpgkey => 'absent', :mirrorlist => 'http://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch', - :priority => '20' + :priority => '20', + :exclude => 'python-ceph-compat python-rbd python-rados python-cephfs', ) } it { is_expected.to contain_yumrepo('ext-ceph').with( @@ -441,4 +448,250 @@ end end + describe 'RHEL7' do + + let :facts do + { + :osfamily => 'RedHat', + :operatingsystem => 'RedHat', + :operatingsystemmajrelease => '7', + } + end + + describe "with default params" do + + it { should contain_yumrepo('ext-epel-7').with( + :enabled => '1', + :descr => 'External EPEL 7', + :name => 'ext-epel-7', + :baseurl => 'absent', + :gpgcheck => '0', + :gpgkey => 'absent', + :mirrorlist => 'http://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch', + :priority => '20', + :exclude => 'python-ceph-compat python-rbd python-rados python-cephfs', + ) } + + it { should contain_yumrepo('ext-ceph').with( + :enabled => '1', + :descr => 'External Ceph giant', + :name => 'ext-ceph-giant', + :baseurl => 'http://ceph.com/rpm-giant/el7/$basearch', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', + :mirrorlist => 'absent', + :priority => '10' + ) } + + it { should contain_yumrepo('ext-ceph-noarch').with( + :enabled => '1', + :descr => 'External Ceph noarch', + :name => 'ext-ceph-giant-noarch', + :baseurl => 'http://ceph.com/rpm-giant/el7/noarch', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', + :mirrorlist => 'absent', + :priority => '10' + ) } + end + + describe "when overriding ceph release" do + let :params do + { + :release => 'firefly' + } + end + + it { should contain_yumrepo('ext-epel-7').with( + :enabled => '1', + :descr => 'External EPEL 7', + :name => 'ext-epel-7', + :baseurl => 'absent', + :gpgcheck => '0', + :gpgkey => 'absent', + :mirrorlist => 'http://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch', + :priority => '20', + :exclude => 'python-ceph-compat python-rbd python-rados python-cephfs', + ) } + + it { should contain_yumrepo('ext-ceph').with( + :enabled => '1', + :descr => 'External Ceph firefly', + :name => 'ext-ceph-firefly', + :baseurl => 'http://ceph.com/rpm-firefly/el7/$basearch', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', + :mirrorlist => 'absent', + :priority => '10' + ) } + + it { should contain_yumrepo('ext-ceph-noarch').with( + :enabled => '1', + :descr => 'External Ceph noarch', + :name => 'ext-ceph-firefly-noarch', + :baseurl => 'http://ceph.com/rpm-firefly/el7/noarch', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', + :mirrorlist => 'absent', + :priority => '10' + ) } + end + + describe "with ensure => absent to disable" do + let :params do + { + :ensure => 'absent', + :extras => true, + :fastcgi => true + } + end + + it { should contain_yumrepo('ext-epel-7').with( + :enabled => '0', + :descr => 'External EPEL 7', + :name => 'ext-epel-7', + :baseurl => 'absent', + :gpgcheck => '0', + :gpgkey => 'absent', + :mirrorlist => 'http://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch', + :priority => '20', + :exclude => 'python-ceph-compat python-rbd python-rados python-cephfs', + ) } + + it { should contain_yumrepo('ext-ceph').with( + :enabled => '0', + :descr => 'External Ceph giant', + :name => 'ext-ceph-giant', + :baseurl => 'http://ceph.com/rpm-giant/el7/$basearch', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', + :mirrorlist => 'absent', + :priority => '10' + ) } + + it { should contain_yumrepo('ext-ceph-noarch').with( + :enabled => '0', + :descr => 'External Ceph noarch', + :name => 'ext-ceph-giant-noarch', + :baseurl => 'http://ceph.com/rpm-giant/el7/noarch', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', + :mirrorlist => 'absent', + :priority => '10' + ) } + + it { should_not contain_yumrepo('ext-ceph-extras') } + + it { should contain_yumrepo('ext-ceph-fastcgi').with( + :enabled => '0', + :descr => 'FastCGI basearch packages for Ceph', + :name => 'ext-ceph-fastcgi', + :baseurl => 'http://gitbuilder.ceph.com/mod_fastcgi-rpm-rhel7-x86_64-basic/ref/master', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/autobuild.asc', + :mirrorlist => 'absent', + :priority => '20' + ) } + + end + + describe "with ceph extras" do + let :params do + { + :extras => true + } + end + + it { should contain_yumrepo('ext-epel-7').with( + :enabled => '1', + :descr => 'External EPEL 7', + :name => 'ext-epel-7', + :baseurl => 'absent', + :gpgcheck => '0', + :gpgkey => 'absent', + :mirrorlist => 'http://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch', + :priority => '20', + :exclude => 'python-ceph-compat python-rbd python-rados python-cephfs', + ) } + + it { should contain_yumrepo('ext-ceph').with( + :enabled => '1', + :descr => 'External Ceph giant', + :name => 'ext-ceph-giant', + :baseurl => 'http://ceph.com/rpm-giant/el7/$basearch', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', + :mirrorlist => 'absent', + :priority => '10' + ) } + + it { should contain_yumrepo('ext-ceph-noarch').with( + :enabled => '1', + :descr => 'External Ceph noarch', + :name => 'ext-ceph-giant-noarch', + :baseurl => 'http://ceph.com/rpm-giant/el7/noarch', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', + :mirrorlist => 'absent', + :priority => '10' + ) } + + it { should_not contain_yumrepo('ext-ceph-extras') } + end + + describe "with ceph fast-cgi" do + let :params do + { + :fastcgi => true + } + end + + it { should contain_yumrepo('ext-epel-7').with( + :enabled => '1', + :descr => 'External EPEL 7', + :name => 'ext-epel-7', + :baseurl => 'absent', + :gpgcheck => '0', + :gpgkey => 'absent', + :mirrorlist => 'http://mirrors.fedoraproject.org/metalink?repo=epel-7&arch=$basearch', + :priority => '20', + :exclude => 'python-ceph-compat python-rbd python-rados python-cephfs', + ) } + + it { should contain_yumrepo('ext-ceph').with( + :enabled => '1', + :descr => 'External Ceph giant', + :name => 'ext-ceph-giant', + :baseurl => 'http://ceph.com/rpm-giant/el7/$basearch', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', + :mirrorlist => 'absent', + :priority => '10' + ) } + + it { should contain_yumrepo('ext-ceph-noarch').with( + :enabled => '1', + :descr => 'External Ceph noarch', + :name => 'ext-ceph-giant-noarch', + :baseurl => 'http://ceph.com/rpm-giant/el7/noarch', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc', + :mirrorlist => 'absent', + :priority => '10' + ) } + + it { should contain_yumrepo('ext-ceph-fastcgi').with( + :enabled => '1', + :descr => 'FastCGI basearch packages for Ceph', + :name => 'ext-ceph-fastcgi', + :baseurl => 'http://gitbuilder.ceph.com/mod_fastcgi-rpm-rhel7-x86_64-basic/ref/master', + :gpgcheck => '1', + :gpgkey => 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/autobuild.asc', + :mirrorlist => 'absent', + :priority => '20' + ) } + + end + end + end diff --git a/ceph/spec/defines/ceph_key_spec.rb b/ceph/spec/defines/ceph_key_spec.rb index e614ecd49..38be3d543 100644 --- a/ceph/spec/defines/ceph_key_spec.rb +++ b/ceph/spec/defines/ceph_key_spec.rb @@ -40,15 +40,15 @@ end it { - should contain_exec('ceph-key-client.admin').with( + is_expected.to contain_exec('ceph-key-client.admin').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements\nset -ex\nceph-authtool /etc/ceph/ceph.client.admin.keyring --name 'client.admin' --add-key 'supersecret' --cap mon 'allow *' --cap osd 'allow rw' " ) - should contain_file('/etc/ceph/ceph.client.admin.keyring').with( + is_expected.to contain_file('/etc/ceph/ceph.client.admin.keyring').with( 'owner' => 'nobody', 'group' => 'nogroup', 'mode' => '0600' ) - should contain_exec('ceph-injectkey-client.admin').with( + is_expected.to contain_exec('ceph-injectkey-client.admin').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements\nset -ex\nceph auth add client.admin --in-file=/etc/ceph/ceph.client.admin.keyring" ) } diff --git a/ceph/spec/defines/ceph_mon_spec.rb b/ceph/spec/defines/ceph_mon_spec.rb index c74ef50fc..5c4656f32 100644 --- a/ceph/spec/defines/ceph_mon_spec.rb +++ b/ceph/spec/defines/ceph_mon_spec.rb @@ -39,7 +39,7 @@ it { expect { - should contain_service('ceph-mon-A').with('ensure' => 'running') + is_expected.to contain_service('ceph-mon-A').with('ensure' => 'running') }.to raise_error(Puppet::Error, /authentication_type cephx requires either key or keyring to be set but both are undef/) } end @@ -56,13 +56,13 @@ } end - it { should contain_service('ceph-mon-A').with('ensure' => 'running') } - it { should contain_exec('ceph-mon-ceph.client.admin.keyring-A').with( + it { is_expected.to contain_service('ceph-mon-A').with('ensure' => 'running') } + it { is_expected.to contain_exec('ceph-mon-ceph.client.admin.keyring-A').with( 'command' => '/bin/true # comment to satisfy puppet syntax requirements set -ex touch /etc/ceph/ceph.client.admin.keyring' ) } - it { should contain_exec('ceph-mon-mkfs-A').with( + it { is_expected.to contain_exec('ceph-mon-mkfs-A').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex mon_data=\$(ceph-mon --id A --show-config-value mon_data) @@ -80,10 +80,10 @@ fi ", 'logoutput' => true) } - it { should contain_file('/tmp/ceph-mon-keyring-A').with( + it { is_expected.to contain_file('/tmp/ceph-mon-keyring-A').with( 'mode' => '0444', 'content' => "[mon.]\n\tkey = AQATGHJTUCBqIBAA7M2yafV1xctn1pgr3GcKPg==\n\tcaps mon = \"allow *\"\n") } - it { should contain_exec('rm-keyring-A').with('command' => '/bin/rm /tmp/ceph-mon-keyring-A') } + it { is_expected.to contain_exec('rm-keyring-A').with('command' => '/bin/rm /tmp/ceph-mon-keyring-A') } end describe 'with keyring' do @@ -98,13 +98,13 @@ } end - it { should contain_service('ceph-mon-A').with('ensure' => 'running') } - it { should contain_exec('ceph-mon-ceph.client.admin.keyring-A').with( + it { is_expected.to contain_service('ceph-mon-A').with('ensure' => 'running') } + it { is_expected.to contain_exec('ceph-mon-ceph.client.admin.keyring-A').with( 'command' => '/bin/true # comment to satisfy puppet syntax requirements set -ex touch /etc/ceph/ceph.client.admin.keyring' ) } - it { should contain_exec('ceph-mon-mkfs-A').with( + it { is_expected.to contain_exec('ceph-mon-mkfs-A').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex mon_data=\$(ceph-mon --id A --show-config-value mon_data) @@ -138,13 +138,13 @@ } end - it { should contain_service('ceph-mon-A').with('ensure' => 'running') } - it { should contain_exec('ceph-mon-testcluster.client.admin.keyring-A').with( + it { is_expected.to contain_service('ceph-mon-A').with('ensure' => 'running') } + it { is_expected.to contain_exec('ceph-mon-testcluster.client.admin.keyring-A').with( 'command' => '/bin/true # comment to satisfy puppet syntax requirements set -ex touch /etc/ceph/testcluster.client.admin.keyring' ) } - it { should contain_exec('ceph-mon-mkfs-A').with( + it { is_expected.to contain_exec('ceph-mon-mkfs-A').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex mon_data=\$(ceph-mon --cluster testcluster --id A --show-config-value mon_data) @@ -179,8 +179,8 @@ } end - it { should contain_service('ceph-mon-A').with('ensure' => 'stopped') } - it { should contain_exec('remove-mon-A').with( + it { is_expected.to contain_service('ceph-mon-A').with('ensure' => 'stopped') } + it { is_expected.to contain_exec('remove-mon-A').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex mon_data=\$(ceph-mon --cluster testcluster --id A --show-config-value mon_data) @@ -196,12 +196,12 @@ end end - context 'RHEL6' do + context 'RHEL7' do let :facts do { :osfamily => 'RedHat', - :operatingsystem => 'RHEL6', + :operatingsystem => 'RHEL7', } end @@ -213,7 +213,7 @@ it { expect { - should contain_service('ceph-mon-A').with('ensure' => 'running') + is_expected.to contain_service('ceph-mon-A').with('ensure' => 'running') }.to raise_error(Puppet::Error, /authentication_type cephx requires either key or keyring to be set but both are undef/) } end @@ -230,13 +230,13 @@ } end - it { should contain_service('ceph-mon-A').with('ensure' => 'running') } - it { should contain_exec('ceph-mon-ceph.client.admin.keyring-A').with( + it { is_expected.to contain_service('ceph-mon-A').with('ensure' => 'running') } + it { is_expected.to contain_exec('ceph-mon-ceph.client.admin.keyring-A').with( 'command' => '/bin/true # comment to satisfy puppet syntax requirements set -ex touch /etc/ceph/ceph.client.admin.keyring' ) } - it { should contain_exec('ceph-mon-mkfs-A').with( + it { is_expected.to contain_exec('ceph-mon-mkfs-A').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex mon_data=\$(ceph-mon --id A --show-config-value mon_data) @@ -254,10 +254,10 @@ fi ", 'logoutput' => true) } - it { should contain_file('/tmp/ceph-mon-keyring-A').with( + it { is_expected.to contain_file('/tmp/ceph-mon-keyring-A').with( 'mode' => '0444', 'content' => "[mon.]\n\tkey = AQATGHJTUCBqIBAA7M2yafV1xctn1pgr3GcKPg==\n\tcaps mon = \"allow *\"\n") } - it { should contain_exec('rm-keyring-A').with('command' => '/bin/rm /tmp/ceph-mon-keyring-A') } + it { is_expected.to contain_exec('rm-keyring-A').with('command' => '/bin/rm /tmp/ceph-mon-keyring-A') } end describe 'with keyring' do @@ -272,13 +272,13 @@ } end - it { should contain_service('ceph-mon-A').with('ensure' => 'running') } - it { should contain_exec('ceph-mon-ceph.client.admin.keyring-A').with( + it { is_expected.to contain_service('ceph-mon-A').with('ensure' => 'running') } + it { is_expected.to contain_exec('ceph-mon-ceph.client.admin.keyring-A').with( 'command' => '/bin/true # comment to satisfy puppet syntax requirements set -ex touch /etc/ceph/ceph.client.admin.keyring' ) } - it { should contain_exec('ceph-mon-mkfs-A').with( + it { is_expected.to contain_exec('ceph-mon-mkfs-A').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex mon_data=\$(ceph-mon --id A --show-config-value mon_data) @@ -312,13 +312,13 @@ } end - it { should contain_service('ceph-mon-A').with('ensure' => 'running') } - it { should contain_exec('ceph-mon-testcluster.client.admin.keyring-A').with( + it { is_expected.to contain_service('ceph-mon-A').with('ensure' => 'running') } + it { is_expected.to contain_exec('ceph-mon-testcluster.client.admin.keyring-A').with( 'command' => '/bin/true # comment to satisfy puppet syntax requirements set -ex touch /etc/ceph/testcluster.client.admin.keyring' ) } - it { should contain_exec('ceph-mon-mkfs-A').with( + it { is_expected.to contain_exec('ceph-mon-mkfs-A').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex mon_data=\$(ceph-mon --cluster testcluster --id A --show-config-value mon_data) @@ -353,8 +353,8 @@ } end - it { should contain_service('ceph-mon-A').with('ensure' => 'stopped') } - it { should contain_exec('remove-mon-A').with( + it { is_expected.to contain_service('ceph-mon-A').with('ensure' => 'stopped') } + it { is_expected.to contain_exec('remove-mon-A').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex mon_data=\$(ceph-mon --cluster testcluster --id A --show-config-value mon_data) diff --git a/ceph/spec/defines/ceph_osd_spec.rb b/ceph/spec/defines/ceph_osd_spec.rb index 2a4895e36..c66fcfbb8 100644 --- a/ceph/spec/defines/ceph_osd_spec.rb +++ b/ceph/spec/defines/ceph_osd_spec.rb @@ -29,7 +29,7 @@ '/tmp' end - it { should contain_exec('ceph-osd-prepare-/tmp').with( + it { is_expected.to contain_exec('ceph-osd-prepare-/tmp').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex if ! test -b /tmp ; then @@ -45,7 +45,7 @@ ", 'logoutput' => true ) } - it { should contain_exec('ceph-osd-activate-/tmp').with( + it { is_expected.to contain_exec('ceph-osd-activate-/tmp').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex if ! test -b /tmp ; then @@ -78,7 +78,7 @@ } end - it { should contain_exec('ceph-osd-prepare-/tmp/data').with( + it { is_expected.to contain_exec('ceph-osd-prepare-/tmp/data').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex if ! test -b /tmp/data ; then @@ -94,7 +94,7 @@ ", 'logoutput' => true ) } - it { should contain_exec('ceph-osd-activate-/tmp/data').with( + it { is_expected.to contain_exec('ceph-osd-activate-/tmp/data').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex if ! test -b /tmp/data ; then @@ -126,7 +126,7 @@ } end - it { should contain_exec('remove-osd-/tmp').with( + it { is_expected.to contain_exec('remove-osd-/tmp').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements set -ex if [ -z \"\$id\" ] ; then diff --git a/ceph/spec/defines/ceph_pool_spec.rb b/ceph/spec/defines/ceph_pool_spec.rb index ff85173b4..97e171588 100644 --- a/ceph/spec/defines/ceph_pool_spec.rb +++ b/ceph/spec/defines/ceph_pool_spec.rb @@ -37,19 +37,19 @@ end it { - should contain_exec('create-volumes').with( + is_expected.to contain_exec('create-volumes').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements\nset -ex\nceph osd pool create volumes 3" ) - should contain_exec('set-volumes-pg_num').with( + is_expected.to contain_exec('set-volumes-pg_num').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements\nset -ex\nceph osd pool set volumes pg_num 3" ) - should contain_exec('set-volumes-pgp_num').with( + is_expected.to contain_exec('set-volumes-pgp_num').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements\nset -ex\nceph osd pool set volumes pgp_num 4" ) - should contain_exec('set-volumes-size').with( + is_expected.to contain_exec('set-volumes-size').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements\nset -ex\nceph osd pool set volumes size 2" ) - should_not contain_exec('delete-volumes') + is_expected.not_to contain_exec('delete-volumes') } end @@ -67,8 +67,8 @@ end it { - should_not contain_exec('create-volumes') - should contain_exec('delete-volumes').with( + is_expected.not_to contain_exec('create-volumes') + is_expected.to contain_exec('delete-volumes').with( 'command' => "/bin/true # comment to satisfy puppet syntax requirements\nset -ex\nceph osd pool delete volumes volumes --yes-i-really-really-mean-it" ) } diff --git a/ceph/spec/defines/ceph_rgw_apache_spec.rb b/ceph/spec/defines/ceph_rgw_apache_spec.rb index e1450074c..1d65e9332 100644 --- a/ceph/spec/defines/ceph_rgw_apache_spec.rb +++ b/ceph/spec/defines/ceph_rgw_apache_spec.rb @@ -49,7 +49,7 @@ class { 'ceph::repo': 'radosgw.gateway' end - it { should contain_apache__vhost('myhost.domain-radosgw').with( { + it { is_expected.to contain_apache__vhost('myhost.domain-radosgw').with( { 'servername' => 'myhost.domain', 'serveradmin' => 'root@localhost', 'port' => 80, @@ -63,14 +63,14 @@ class { 'ceph::repo': ServerSignature Off", })} - it { should contain_class('apache') } - it { should contain_class('apache::mod::alias') } - it { should contain_class('apache::mod::auth_basic') } - it { should contain_apache__mod('fastcgi').with ( { 'package' => 'libapache2-mod-fastcgi' } ) } - it { should contain_class('apache::mod::mime') } - it { should contain_class('apache::mod::rewrite') } + it { is_expected.to contain_class('apache') } + it { is_expected.to contain_class('apache::mod::alias') } + it { is_expected.to contain_class('apache::mod::auth_basic') } + it { is_expected.to contain_apache__mod('fastcgi').with ( { 'package' => 'libapache2-mod-fastcgi' } ) } + it { is_expected.to contain_class('apache::mod::mime') } + it { is_expected.to contain_class('apache::mod::rewrite') } - it { should contain_file('/var/www/s3gw.fcgi').with({ + it { is_expected.to contain_file('/var/www/s3gw.fcgi').with({ 'ensure' => 'file', 'owner' => 'root', 'group' => 'root', @@ -98,7 +98,7 @@ class { 'ceph::repo': } end - it { should contain_apache__vhost('mydns.hostname-radosgw').with( { + it { is_expected.to contain_apache__vhost('mydns.hostname-radosgw').with( { 'servername' => 'mydns.hostname', 'serveradmin' => 'admin@hostname', 'port' => 1111, @@ -112,14 +112,14 @@ class { 'ceph::repo': ServerSignature Off", } ) } - it { should contain_class('apache') } - it { should contain_class('apache::mod::alias') } - it { should contain_class('apache::mod::auth_basic') } - it { should contain_apache__mod('fastcgi').with ( { 'package' => 'libapache2-mod-fastcgi' } ) } - it { should contain_class('apache::mod::mime') } - it { should contain_class('apache::mod::rewrite') } + it { is_expected.to contain_class('apache') } + it { is_expected.to contain_class('apache::mod::alias') } + it { is_expected.to contain_class('apache::mod::auth_basic') } + it { is_expected.to contain_apache__mod('fastcgi').with ( { 'package' => 'libapache2-mod-fastcgi' } ) } + it { is_expected.to contain_class('apache::mod::mime') } + it { is_expected.to contain_class('apache::mod::rewrite') } - it { should contain_file('/some/fcgi/filepath') } + it { is_expected.to contain_file('/some/fcgi/filepath') } end end @@ -144,7 +144,7 @@ class { 'ceph::repo': 'radosgw.gateway' end - it { should contain_apache__vhost('myhost.domain-radosgw').with( { + it { is_expected.to contain_apache__vhost('myhost.domain-radosgw').with( { 'servername' => 'myhost.domain', 'serveradmin' => 'root@localhost', 'port' => 80, @@ -158,14 +158,14 @@ class { 'ceph::repo': ServerSignature Off", })} - it { should contain_class('apache') } - it { should contain_class('apache::mod::alias') } - it { should contain_class('apache::mod::auth_basic') } - it { should contain_apache__mod('fastcgi').with ( { 'package' => 'mod_fastcgi' } ) } - it { should contain_class('apache::mod::mime') } - it { should contain_class('apache::mod::rewrite') } + it { is_expected.to contain_class('apache') } + it { is_expected.to contain_class('apache::mod::alias') } + it { is_expected.to contain_class('apache::mod::auth_basic') } + it { is_expected.to contain_apache__mod('fastcgi').with ( { 'package' => 'mod_fastcgi' } ) } + it { is_expected.to contain_class('apache::mod::mime') } + it { is_expected.to contain_class('apache::mod::rewrite') } - it { should contain_file('/var/www/s3gw.fcgi').with({ + it { is_expected.to contain_file('/var/www/s3gw.fcgi').with({ 'ensure' => 'file', 'owner' => 'root', 'group' => 'root', @@ -193,7 +193,7 @@ class { 'ceph::repo': } end - it { should contain_apache__vhost('mydns.hostname-radosgw').with( { + it { is_expected.to contain_apache__vhost('mydns.hostname-radosgw').with( { 'servername' => 'mydns.hostname', 'serveradmin' => 'admin@hostname', 'port' => 1111, @@ -207,14 +207,14 @@ class { 'ceph::repo': ServerSignature Off", } ) } - it { should contain_class('apache') } - it { should contain_class('apache::mod::alias') } - it { should contain_class('apache::mod::auth_basic') } - it { should contain_apache__mod('fastcgi').with ( { 'package' => 'mod_fastcgi' } ) } - it { should contain_class('apache::mod::mime') } - it { should contain_class('apache::mod::rewrite') } + it { is_expected.to contain_class('apache') } + it { is_expected.to contain_class('apache::mod::alias') } + it { is_expected.to contain_class('apache::mod::auth_basic') } + it { is_expected.to contain_apache__mod('fastcgi').with ( { 'package' => 'mod_fastcgi' } ) } + it { is_expected.to contain_class('apache::mod::mime') } + it { is_expected.to contain_class('apache::mod::rewrite') } - it { should contain_file('/some/fcgi/filepath') } + it { is_expected.to contain_file('/some/fcgi/filepath') } end end diff --git a/ceph/spec/defines/ceph_rgw_spec.rb b/ceph/spec/defines/ceph_rgw_spec.rb index a3e3617ff..0fc1c8622 100644 --- a/ceph/spec/defines/ceph_rgw_spec.rb +++ b/ceph/spec/defines/ceph_rgw_spec.rb @@ -31,29 +31,29 @@ 'radosgw.gateway' end - it { should contain_package("#{default_params[:pkg_radosgw]}").with('ensure' => 'installed') } - it { should contain_ceph_config('client.radosgw.gateway/user').with_value("#{default_params[:user]}") } - it { should contain_ceph_config('client.radosgw.gateway/host').with_value('myhost') } - it { should contain_ceph_config('client.radosgw.gateway/keyring').with_value('/etc/ceph/ceph.client.radosgw.gateway.keyring') } - it { should contain_ceph_config('client.radosgw.gateway/log_file').with_value('/var/log/ceph/radosgw.log') } - it { should contain_ceph_config('client.radosgw.gateway/rgw_dns_name').with_value('myhost.domain') } - it { should contain_ceph_config('client.radosgw.gateway/rgw_print_continue').with_value(true) } - it { should contain_ceph_config('client.radosgw.gateway/rgw_socket_path').with_value('/tmp/radosgw.sock') } - it { should contain_ceph_config('client.radosgw.gateway/rgw_port').with_value(80) } - - it { should contain_file('/var/lib/ceph/radosgw').with({ + it { is_expected.to contain_package("#{default_params[:pkg_radosgw]}").with('ensure' => 'installed') } + it { is_expected.to contain_ceph_config('client.radosgw.gateway/user').with_value("#{default_params[:user]}") } + it { is_expected.to contain_ceph_config('client.radosgw.gateway/host').with_value('myhost') } + it { is_expected.to contain_ceph_config('client.radosgw.gateway/keyring').with_value('/etc/ceph/ceph.client.radosgw.gateway.keyring') } + it { is_expected.to contain_ceph_config('client.radosgw.gateway/log_file').with_value('/var/log/ceph/radosgw.log') } + it { is_expected.to contain_ceph_config('client.radosgw.gateway/rgw_dns_name').with_value('myhost.domain') } + it { is_expected.to contain_ceph_config('client.radosgw.gateway/rgw_print_continue').with_value(true) } + it { is_expected.to contain_ceph_config('client.radosgw.gateway/rgw_socket_path').with_value('/tmp/radosgw.sock') } + it { is_expected.to contain_ceph_config('client.radosgw.gateway/rgw_port').with_value(80) } + + it { is_expected.to contain_file('/var/lib/ceph/radosgw').with({ 'ensure' => 'directory', 'mode' => '0755', })} - it { should contain_file('/var/lib/ceph/radosgw/ceph-radosgw.gateway').with({ + it { is_expected.to contain_file('/var/lib/ceph/radosgw/ceph-radosgw.gateway').with({ 'ensure' => 'directory', 'owner' => 'root', 'group' => 'root', 'mode' => '0750', })} - it { should contain_service('radosgw-radosgw.gateway') } + it { is_expected.to contain_service('radosgw-radosgw.gateway') } end @@ -78,25 +78,25 @@ } end - it { should contain_package('pkgradosgw').with('ensure' => 'installed') } + it { is_expected.to contain_package('pkgradosgw').with('ensure' => 'installed') } - it { should contain_ceph_config('client.myid/host').with_value('myhost') } - it { should contain_ceph_config('client.myid/keyring').with_value('/etc/ceph/ceph.myid.keyring') } - it { should contain_ceph_config('client.myid/log_file').with_value('/var/log/ceph/mylogfile.log') } - it { should contain_ceph_config('client.myid/rgw_dns_name').with_value('mydns.hostname') } - it { should contain_ceph_config('client.myid/rgw_print_continue').with_value(false) } - it { should contain_ceph_config('client.myid/rgw_socket_path').with_value('/some/location/radosgw.sock') } - it { should contain_ceph_config('client.myid/rgw_port').with_value(1111) } - it { should contain_ceph_config('client.myid/user').with_value('wwwuser') } + it { is_expected.to contain_ceph_config('client.myid/host').with_value('myhost') } + it { is_expected.to contain_ceph_config('client.myid/keyring').with_value('/etc/ceph/ceph.myid.keyring') } + it { is_expected.to contain_ceph_config('client.myid/log_file').with_value('/var/log/ceph/mylogfile.log') } + it { is_expected.to contain_ceph_config('client.myid/rgw_dns_name').with_value('mydns.hostname') } + it { is_expected.to contain_ceph_config('client.myid/rgw_print_continue').with_value(false) } + it { is_expected.to contain_ceph_config('client.myid/rgw_socket_path').with_value('/some/location/radosgw.sock') } + it { is_expected.to contain_ceph_config('client.myid/rgw_port').with_value(1111) } + it { is_expected.to contain_ceph_config('client.myid/user').with_value('wwwuser') } - it { should contain_file('/var/lib/ceph/radosgw/ceph-myid').with( { + it { is_expected.to contain_file('/var/lib/ceph/radosgw/ceph-myid').with( { 'ensure' => 'directory', 'owner' => 'root', 'group' => 'root', 'mode' => '0750', } ) } - it { should contain_service('radosgw-myid') } + it { is_expected.to contain_service('radosgw-myid') } end diff --git a/ceph/spec/spec_helper_acceptance.rb b/ceph/spec/spec_helper_acceptance.rb index f301c819e..e6803f79e 100644 --- a/ceph/spec/spec_helper_acceptance.rb +++ b/ceph/spec/spec_helper_acceptance.rb @@ -24,13 +24,18 @@ hosts.each do |host| install_puppet + # clean out any module cruft + shell('rm -fr /etc/puppet/modules/*') on host, "mkdir -p #{host['distmoduledir']}" + # we will provide our own epel with some excludes later + shell('test -f /etc/debian_version || yum-config-manager --disable epel') end + c.formatter = :documentation + c.before :suite do - puppet_module_install(:source => proj_root, :module_name => 'ceph') - scp_to hosts, File.join(proj_root, 'spec/fixtures/hieradata/hiera.yaml'), '/etc/puppet/hiera.yaml' hosts.each do |host| + scp_to hosts, File.join(proj_root, 'spec/fixtures/hieradata/hiera.yaml'), '/etc/puppet/hiera.yaml' # https://tickets.puppetlabs.com/browse/PUP-2566 on host, 'sed -i "/templatedir/d" /etc/puppet/puppet.conf' install_package host, 'git' @@ -38,8 +43,9 @@ on host, puppet('module install puppetlabs/stdlib --version ">=4.0.0 <5.0.0"'), { :acceptable_exit_codes => [0,1] } on host, puppet('module install puppetlabs/inifile --version ">=1.0.0 <2.0.0"'), { :acceptable_exit_codes => [0,1] } on host, puppet('module install puppetlabs/apt --version ">=1.4.0 <2.0.0"'), { :acceptable_exit_codes => [0,1] } - on host, puppet('module install puppetlabs/concat --version ">=1.1.0 <2.0.0"'), { :acceptable_exit_codes => [0,1] } - on host, puppet('module install puppetlabs/apache --version ">=1.0.1 <2.0.0"'), { :acceptable_exit_codes => [0,1] } + on host, puppet('module install puppetlabs/concat --version ">=1.2.1 <2.0.0"'), { :acceptable_exit_codes => [0,1] } + on host, puppet('module install puppetlabs/apache --version ">=1.4.1 <2.0.0"'), { :acceptable_exit_codes => [0,1] } + puppet_module_install(:source => proj_root, :module_name => 'ceph') # Flush the firewall flushfw = <<-EOS iptables -F diff --git a/ceph/spec/spec_helper_system.rb b/ceph/spec/spec_helper_system.rb index ab82e0cb7..3f725cbf9 100644 --- a/ceph/spec/spec_helper_system.rb +++ b/ceph/spec/spec_helper_system.rb @@ -44,15 +44,15 @@ puppet_module_install(:source => File.join(proj_root, '../scenario_node_terminus'), :module_name => 'scenario_node_terminus', :node => vm) - shell(:command => 'puppet module install --version 4.x puppetlabs/stdlib', + shell(:command => 'puppet module install --version ">=4.0.0 <5.0.0" puppetlabs/stdlib', :node => vm) - shell(:command => 'puppet module install --version 1.0.0 puppetlabs/inifile', + shell(:command => 'puppet module install --version ">=1.0.0 <2.0.0" puppetlabs/inifile', :node => vm) - shell(:command => 'puppet module install --version 1.4.0 puppetlabs/apt', + shell(:command => 'puppet module install --version ">=1.4.0 <2.0.0" puppetlabs/apt', :node => vm) - shell(:command => 'puppet module install --version 1.1.x puppetlabs/concat', + shell(:command => 'puppet module install --version ">=1.2.1 <2.0.0" puppetlabs/concat', :node => vm) - shell(:command => 'puppet module install --version 1.0.1 puppetlabs/apache', + shell(:command => 'puppet module install --version ">=1.4.1 <2.0.0" puppetlabs/apache', :node => vm) rcp(:sp => File.join(proj_root, 'spec/fixtures/hieradata/hiera.yaml'), :dp => '/etc/puppet/hiera.yaml', diff --git a/ceph/spec/system/ceph_key_spec.rb b/ceph/spec/system/ceph_key_spec.rb index 8e3fa645a..c18389c8d 100644 --- a/ceph/spec/system/ceph_key_spec.rb +++ b/ceph/spec/system/ceph_key_spec.rb @@ -67,7 +67,7 @@ class { 'ceph::repo': machines.each do |mon| puppet_apply(:node => mon, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -85,7 +85,7 @@ class { 'ceph::repo': machines.each do |mon| puppet_apply(:node => mon, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -117,33 +117,33 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph auth list' do |r| - r.stdout.should_not =~ /client.admin/ - r.exit_code.should be_zero + expect(r.stdout).not_to match(/client.admin/) + expect(r.exit_code).to be_zero end shell 'ls -l /etc/ceph/ceph.client.admin.keyring' do |r| - r.stdout.should =~ /.*-rw-------.*root\sroot.*/m - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/.*-rw-------.*root\sroot.*/m) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'cat /etc/ceph/ceph.client.admin.keyring' do |r| - r.stdout.should =~ /.*\[client.admin\].*key = #{admin_key}.*caps mds = "allow \*".*caps mon = "allow \*".*caps osd = "allow \*".*/m - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/.*\[client.admin\].*key = #{admin_key}.*caps mds = "allow \*".*caps mon = "allow \*".*caps osd = "allow \*".*/m) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one monitor and all packages' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end @@ -192,34 +192,34 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 - r.stdout.should_not =~ /Exec\[ceph-key-client\.admin\]/ # client.admin key needs to contain a / character! + expect(r.exit_code).not_to eq(1) + expect(r.stdout).not_to match(/Exec\[ceph-key-client\.admin\]/) # client.admin key needs to contain a / character! end shell 'ceph auth list' do |r| - r.stdout.should =~ /.*client\.volumes.*key:\s#{volume_key}.*/m + expect(r.stdout).to match(/.*client\.volumes.*key:\s#{volume_key}.*/m) # r.stderr.should be_empty # ceph auth writes to stderr! - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell 'ls -l /etc/ceph/ceph.client.volumes.keyring' do |r| - r.stdout.should =~ /.*-rw-------.*nobody\s#{nogroup}.*/m - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/.*-rw-------.*nobody\s#{nogroup}.*/m) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'cat /etc/ceph/ceph.client.volumes.keyring' do |r| - r.stdout.should =~ /.*\[client.volumes\].*key = #{volume_key}.*caps mon = "allow \*".*caps osd = "allow rw".*/m - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/.*\[client.volumes\].*key = #{volume_key}.*caps mon = "allow \*".*caps osd = "allow rw".*/m) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one monitor and all packages' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end diff --git a/ceph/spec/system/ceph_mon_spec.rb b/ceph/spec/system/ceph_mon_spec.rb index 8d9939ba5..d0a4c93fd 100644 --- a/ceph/spec/system/ceph_mon_spec.rb +++ b/ceph/spec/system/ceph_mon_spec.rb @@ -40,7 +40,7 @@ class { 'ceph::repo': machines.each do |mon| puppet_apply(:node => mon, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -58,7 +58,7 @@ class { 'ceph::repo': machines.each do |mon| puppet_apply(:node => mon, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -78,15 +78,15 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons at/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons at/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end @@ -98,9 +98,9 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end osfamily = facter.facts['osfamily'] @@ -108,16 +108,16 @@ class { 'ceph': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=a' do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.a/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.a/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.a' do |r| - r.stdout.should =~ /mon.a not found/ - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to match(/mon.a not found/) + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end end @@ -137,13 +137,13 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'test -z "$(cat /etc/ceph/ceph.client.admin.keyring)"' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end end @@ -155,9 +155,9 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end osfamily = facter.facts['osfamily'] @@ -165,16 +165,16 @@ class { 'ceph': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=a' do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.a/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.a/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.a' do |r| - r.stdout.should =~ /mon.a not found/ - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to match(/mon.a not found/) + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end end @@ -198,13 +198,13 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'test -f /etc/ceph/ceph.client.admin.keyring' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end end @@ -216,9 +216,9 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end osfamily = facter.facts['osfamily'] @@ -226,16 +226,16 @@ class { 'ceph': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=a' do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.a/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.a/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.a' do |r| - r.stdout.should =~ /mon.a not found/ - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to match(/mon.a not found/) + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end end @@ -243,7 +243,7 @@ class { 'ceph': describe 'on two hosts' do it 'should be two hosts' do - machines.size.should == 2 + expect(machines.size).to eq(2) end it 'should install two monitors' do @@ -262,16 +262,16 @@ class { 'ceph': EOS puppet_apply(:node => mon, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end shell 'ceph -s' do |r| - r.stdout.should =~ /2 mons .* quorum 0,1/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/2 mons .* quorum 0,1/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end @@ -284,9 +284,9 @@ class { 'ceph': EOS puppet_apply(:node => mon, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end osfamily = facter.facts['osfamily'] @@ -294,16 +294,16 @@ class { 'ceph': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell "status ceph-mon id=#{mon}" do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.#{mon}/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.#{mon}/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell "service ceph status mon.#{mon}" do |r| - r.stdout.should =~ /mon.#{mon} not found/ - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to match(/mon.#{mon} not found/) + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end end diff --git a/ceph/spec/system/ceph_mons_spec.rb b/ceph/spec/system/ceph_mons_spec.rb index 745e05815..6894edf99 100644 --- a/ceph/spec/system/ceph_mons_spec.rb +++ b/ceph/spec/system/ceph_mons_spec.rb @@ -117,15 +117,15 @@ end puppet_apply(data_site_pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons at/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons at/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end @@ -146,7 +146,7 @@ end puppet_apply(data_site_pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end osfamily = facter.facts['osfamily'] @@ -154,16 +154,16 @@ if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /status: Unknown job: ceph-mon/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/status: Unknown job: ceph-mon/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /ceph: unrecognized service/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/ceph: unrecognized service/) + expect(r.exit_code).not_to be_zero end end end @@ -201,26 +201,26 @@ end puppet_apply(data_site_pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'cat /etc/ceph/ceph.client.admin.keyring' do |r| - r.stdout.should =~ /#{admin_key}/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/#{admin_key}/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons at/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons at/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph auth list' do |r| - r.stdout.should =~ /#{admin_key}/ - r.exit_code.should be_zero + expect(r.stdout).to match(/#{admin_key}/) + expect(r.exit_code).to be_zero end end @@ -242,7 +242,7 @@ end puppet_apply(data_site_pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end osfamily = facter.facts['osfamily'] @@ -250,16 +250,16 @@ if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /status: Unknown job: ceph-mon/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/status: Unknown job: ceph-mon/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /ceph: unrecognized service/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/ceph: unrecognized service/) + expect(r.exit_code).not_to be_zero end end end @@ -282,7 +282,7 @@ machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end rcp(:sp => snt_data, :dp => data_path, :d => node(:name => vm)) @@ -334,15 +334,15 @@ end puppet_apply('') do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons at/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons at/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end @@ -359,7 +359,7 @@ end puppet_apply('') do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end osfamily = facter.facts['osfamily'] @@ -367,16 +367,16 @@ if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /status: Unknown job: ceph-mon/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/status: Unknown job: ceph-mon/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /ceph: unrecognized service/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/ceph: unrecognized service/) + expect(r.exit_code).not_to be_zero end end end @@ -416,26 +416,26 @@ end puppet_apply('') do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'cat /etc/ceph/ceph.client.admin.keyring' do |r| - r.stdout.should =~ /#{admin_key}/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/#{admin_key}/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons at/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons at/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph auth list' do |r| - r.stdout.should =~ /#{admin_key}/ - r.exit_code.should be_zero + expect(r.stdout).to match(/#{admin_key}/) + expect(r.exit_code).to be_zero end end @@ -452,7 +452,7 @@ end puppet_apply('') do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end osfamily = facter.facts['osfamily'] @@ -460,16 +460,16 @@ if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /status: Unknown job: ceph-mon/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/status: Unknown job: ceph-mon/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /ceph: unrecognized service/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/ceph: unrecognized service/) + expect(r.exit_code).not_to be_zero end end end diff --git a/ceph/spec/system/ceph_osd_spec.rb b/ceph/spec/system/ceph_osd_spec.rb index d5e3ebf38..5f67f1eea 100644 --- a/ceph/spec/system/ceph_osd_spec.rb +++ b/ceph/spec/system/ceph_osd_spec.rb @@ -56,7 +56,7 @@ class { 'ceph::repo': machines.each do |mon| puppet_apply(:node => mon, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -74,7 +74,7 @@ class { 'ceph::repo': machines.each do |mon| puppet_apply(:node => mon, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -98,22 +98,22 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -123,20 +123,20 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell "test -b #{data} && ceph-disk zap #{data}" end it 'should uninstall one monitor and all packages' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end @@ -172,21 +172,21 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -194,13 +194,13 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell "test -b #{data} && ceph-disk zap #{data}" @@ -208,7 +208,7 @@ class { 'ceph': it 'should uninstall one monitor and all packages' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end @@ -233,21 +233,21 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd and external journal' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -255,26 +255,26 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell "test -b #{data} && ceph-disk zap #{data}" end it 'should uninstall one monitor and all packages' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end it 'should install one OSD no cephx on a partition' do shell 'sgdisk --largest-new=1 --change-name="1:ceph data" --partition-guid=1:7aebb13f-d4a5-4b94-8622-355d2b5401f1 --typecode=1:4fbd7e29-9d25-41b8-afd0-062c0ceff05d -- /dev/sdb' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end pp = <<-EOS @@ -294,21 +294,21 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -318,20 +318,20 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell 'ceph-disk zap /dev/sdb' end it 'should install one OSD no cephx on partition and activate after umount' do shell 'sgdisk --delete=1 /dev/sdb || true; sgdisk --largest-new=1 --change-name="1:ceph data" --partition-guid=1:7aebb13f-d4a5-4b94-8622-355d2b5401f1 --typecode=1:4fbd7e29-9d25-41b8-afd0-062c0ceff05d -- /dev/sdb' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end pp = <<-EOS @@ -351,41 +351,41 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end # stop and umount (but leave it prepared) shell 'stop ceph-osd id=0 || /etc/init.d/ceph stop osd.0; umount /dev/sdb1' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end # rerun puppet (should activate but not prepare) puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end # check osd up and same osd.id shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0\s*up/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0\s*up/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -395,20 +395,20 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell 'ceph-disk zap /dev/sdb' end it 'should uninstall one monitor and all packages' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end diff --git a/ceph/spec/system/ceph_osds_spec.rb b/ceph/spec/system/ceph_osds_spec.rb index 9df41a206..d398d4553 100644 --- a/ceph/spec/system/ceph_osds_spec.rb +++ b/ceph/spec/system/ceph_osds_spec.rb @@ -52,7 +52,7 @@ machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end rcp(:sp => data, :dp => data_path, :d => node(:name => vm)) @@ -114,7 +114,7 @@ machines.each do |vm| puppet_apply('') do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell(:node => vm, :command => 'test -b /dev/sdb && sgdisk --zap-all --clear --mbrtogpt -- /dev/sdb') @@ -148,15 +148,15 @@ end puppet_apply('') do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end end @@ -199,15 +199,15 @@ end puppet_apply('') do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end end diff --git a/ceph/spec/system/ceph_pool_spec.rb b/ceph/spec/system/ceph_pool_spec.rb index a1ca42778..93c8eabbf 100644 --- a/ceph/spec/system/ceph_pool_spec.rb +++ b/ceph/spec/system/ceph_pool_spec.rb @@ -46,7 +46,7 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end @@ -66,7 +66,7 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end @@ -80,27 +80,27 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end shell 'ceph osd pool get volumes pg_num' do |r| - r.stdout.should =~ /pg_num: 64/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/pg_num: 64/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph osd pool get volumes pgp_num' do |r| - r.stdout.should =~ /pgp_num: 64/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/pgp_num: 64/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph osd pool get volumes size' do |r| - r.stdout.should =~ /size: 3/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/size: 3/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end @@ -115,9 +115,9 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end pp2 = <<-EOS @@ -127,15 +127,15 @@ class { 'ceph::repo': EOS puppet_apply(pp2) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should == 0 + expect(r.exit_code).to eq(0) end shell 'ceph osd lspools | grep volumes' do |r| - r.stdout.should be_empty - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end diff --git a/ceph/spec/system/ceph_profile_base_spec.rb b/ceph/spec/system/ceph_profile_base_spec.rb index 13a7d9608..4f27becd3 100644 --- a/ceph/spec/system/ceph_profile_base_spec.rb +++ b/ceph/spec/system/ceph_profile_base_spec.rb @@ -54,7 +54,7 @@ class { 'ceph::repo': machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -93,21 +93,21 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'cat /etc/ceph/ceph.conf' do |r| - r.stdout.should =~ /#{fsid}/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/#{fsid}/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell querycommand do |r| - r.stdout.should =~ /#{queryresult}/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/#{queryresult}/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end end diff --git a/ceph/spec/system/ceph_profile_client_spec.rb b/ceph/spec/system/ceph_profile_client_spec.rb index 435484c31..ce7d47d71 100644 --- a/ceph/spec/system/ceph_profile_client_spec.rb +++ b/ceph/spec/system/ceph_profile_client_spec.rb @@ -62,7 +62,7 @@ class { 'ceph::repo': machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -104,37 +104,37 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons .* quorum 0 first/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons .* quorum 0 first/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph -n client.volumes -s' do |r| - r.stdout.should =~ /1 mons .* quorum 0 first/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons .* quorum 0 first/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph auth list' do |r| - r.stdout.should =~ /#{admin_key}/ - r.exit_code.should be_zero + expect(r.stdout).to match(/#{admin_key}/) + expect(r.exit_code).to be_zero end shell 'ceph auth list' do |r| - r.stdout.should =~ /#{volumes_key}/ - r.exit_code.should be_zero + expect(r.stdout).to match(/#{volumes_key}/) + expect(r.exit_code).to be_zero end end it 'should uninstall one monitor' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -201,31 +201,31 @@ class { 'ceph::repo': end puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end ['first', 'second'].each do |vm| if vm == "first" shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons .* quorum 0 first/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons .* quorum 0 first/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph auth list' do |r| - r.stdout.should =~ /#{admin_key}/ - r.exit_code.should be_zero + expect(r.stdout).to match(/#{admin_key}/) + expect(r.exit_code).to be_zero end end if vm == "second" shell 'ceph -n client.volumes -s' do |r| - r.stdout.should =~ /1 mons .* quorum 0 first/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons .* quorum 0 first/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end end @@ -234,7 +234,7 @@ class { 'ceph::repo': it 'should uninstall one monitor' do [ 'second', 'first' ].each do |vm| puppet_apply(:node => vm, :code => purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end diff --git a/ceph/spec/system/ceph_profile_mon_spec.rb b/ceph/spec/system/ceph_profile_mon_spec.rb index 69fc2658a..68541fb3b 100644 --- a/ceph/spec/system/ceph_profile_mon_spec.rb +++ b/ceph/spec/system/ceph_profile_mon_spec.rb @@ -48,7 +48,7 @@ class { 'ceph::repo': machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -76,15 +76,15 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons .* quorum 0 first/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons .* quorum 0 first/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end @@ -96,7 +96,7 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end osfamily = facter.facts['osfamily'] @@ -104,16 +104,16 @@ class { 'ceph::repo': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.first/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.first/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.first' do |r| - r.stdout.should =~ /mon.first not found/ - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to match(/mon.first not found/) + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end end @@ -150,20 +150,20 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons .* quorum 0 first/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons .* quorum 0 first/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph auth list' do |r| - r.stdout.should =~ /#{admin_key}/ - r.exit_code.should be_zero + expect(r.stdout).to match(/#{admin_key}/) + expect(r.exit_code).to be_zero end end @@ -175,7 +175,7 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end osfamily = facter.facts['osfamily'] @@ -183,16 +183,16 @@ class { 'ceph::repo': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.first/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.first/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.first' do |r| - r.stdout.should =~ /mon.first not found/ - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to match(/mon.first not found/) + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end end @@ -232,20 +232,20 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons .* quorum 0 first/ + expect(r.stdout).to match(/1 mons .* quorum 0 first/) - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph auth list' do |r| - r.stdout.should =~ /#{admin_key}/ - r.exit_code.should be_zero + expect(r.stdout).to match(/#{admin_key}/) + expect(r.exit_code).to be_zero end end @@ -257,7 +257,7 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end osfamily = facter.facts['osfamily'] @@ -265,16 +265,16 @@ class { 'ceph::repo': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.first/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.first/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.first' do |r| - r.stdout.should =~ /mon.first not found/ - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to match(/mon.first not found/) + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end end @@ -282,7 +282,7 @@ class { 'ceph::repo': describe 'on two hosts' do it 'should be two hosts' do - machines.size.should == 2 + expect(machines.size).to eq(2) end it 'should install two monitors' do @@ -309,16 +309,16 @@ class { 'ceph::repo': EOS puppet_apply(:node => mon, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end shell 'ceph -s' do |r| - r.stdout.should =~ /2 mons .* quorum 0,1 first,second/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/2 mons .* quorum 0,1 first,second/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end @@ -331,7 +331,7 @@ class { 'ceph::repo': EOS puppet_apply(:node => mon, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end osfamily = facter.facts['osfamily'] @@ -339,16 +339,16 @@ class { 'ceph::repo': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell "status ceph-mon id=#{mon}" do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.#{mon}/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.#{mon}/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell "service ceph status mon.#{mon}" do |r| - r.stdout.should =~ /mon.#{mon} not found/ - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to match(/mon.#{mon} not found/) + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end end diff --git a/ceph/spec/system/ceph_profile_osd_spec.rb b/ceph/spec/system/ceph_profile_osd_spec.rb index a2de9c54f..dd1da3715 100644 --- a/ceph/spec/system/ceph_profile_osd_spec.rb +++ b/ceph/spec/system/ceph_profile_osd_spec.rb @@ -61,7 +61,7 @@ class { 'ceph::repo': machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -90,21 +90,21 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -114,18 +114,18 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell 'ceph-disk zap /dev/sdb' end it 'should uninstall one monitor' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end @@ -153,21 +153,21 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -175,18 +175,18 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell 'ceph-disk zap /dev/sdb' end it 'should uninstall one monitor' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end @@ -225,21 +225,21 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -247,11 +247,11 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell 'ceph-disk zap /dev/sdb' @@ -259,7 +259,7 @@ class { 'ceph::repo': it 'should uninstall one monitor and all packages' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -296,28 +296,28 @@ class { 'ceph::repo': end puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons .* quorum 0 first/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons .* quorum 0 first/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd on second host' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -325,23 +325,23 @@ class { 'ceph::repo': EOS puppet_apply(:node => 'second', :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell(:node => 'second', :command => 'ceph-disk zap /dev/sdb') puppet_apply(:node => 'second', :code => purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end it 'should uninstall one monitor on first host' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end @@ -388,28 +388,28 @@ class { 'ceph::repo': end puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons .* quorum 0 first/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons .* quorum 0 first/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd on second host' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -420,23 +420,23 @@ class { '::ceph::profile::client': } -> EOS puppet_apply(:node => 'second', :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell(:node => 'second', :command => 'ceph-disk zap /dev/sdb') puppet_apply(:node => 'second', :code => purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end it 'should uninstall one monitor' do puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end diff --git a/ceph/spec/system/ceph_repo_spec.rb b/ceph/spec/system/ceph_repo_spec.rb index c20dfcb03..2d43f08f9 100644 --- a/ceph/spec/system/ceph_repo_spec.rb +++ b/ceph/spec/system/ceph_repo_spec.rb @@ -46,7 +46,7 @@ class { 'ceph::repo': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end @@ -54,33 +54,33 @@ class { 'ceph::repo': if osfamily == 'Debian' shell 'apt-cache policy ceph' do |r| - r.stdout.should_not =~ /ceph.com/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).not_to match(/ceph.com/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'apt-cache policy curl' do |r| - r.stdout.should_not =~ /ceph.com/ - r.exit_code.should be_zero + expect(r.stdout).not_to match(/ceph.com/) + expect(r.exit_code).to be_zero end shell 'apt-cache policy libapache2-mod-fastcgi' do |r| - r.stdout.should_not =~ /ceph.com/ - r.exit_code.should be_zero + expect(r.stdout).not_to match(/ceph.com/) + expect(r.exit_code).to be_zero end end if osfamily == 'RedHat' shell 'yum info ceph' do |r| - r.stdout.should_not =~ /ceph.com/ - r.stderr.should =~ /Error: No matching Packages to list/ - r.exit_code.should_not be_zero + expect(r.stdout).not_to match(/ceph.com/) + expect(r.stderr).to match(/Error: No matching Packages to list/) + expect(r.exit_code).not_to be_zero end shell 'yum info qemu-kvm' do |r| - r.stdout.should_not =~ /Repo.*ext-ceph-extras/ - r.exit_code.should be_zero + expect(r.stdout).not_to match(/Repo.*ext-ceph-extras/) + expect(r.exit_code).to be_zero end shell 'yum info mod_fastcgi' do |r| - r.stdout.should_not =~ /Repo.*ext-ceph-fastcgi/ - r.stderr.should =~ /Error: No matching Packages to list/ - r.exit_code.should_not be_zero + expect(r.stdout).not_to match(/Repo.*ext-ceph-fastcgi/) + expect(r.stderr).to match(/Error: No matching Packages to list/) + expect(r.exit_code).not_to be_zero end end end @@ -116,28 +116,28 @@ class { 'ceph::repo': # Run it twice and test for idempotency puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell querycommand do |r| - r.stdout.should =~ /#{queryresult}/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/#{queryresult}/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end # Test extras is not enabled if osfamily == 'Debian' shell 'apt-cache policy curl' do |r| - r.stdout.should_not =~ /ceph\.com.*ceph-extras/ - r.exit_code.should be_zero + expect(r.stdout).not_to match(/ceph\.com.*ceph-extras/) + expect(r.exit_code).to be_zero end end if osfamily == 'RedHat' shell 'yum info qemu-kvm' do |r| - r.stdout.should_not =~ /Repo.*ext-ceph-extras/ - r.exit_code.should be_zero + expect(r.stdout).not_to match(/Repo.*ext-ceph-extras/) + expect(r.exit_code).to be_zero end end @@ -151,23 +151,23 @@ class { 'ceph::repo': # Run it twice and test for idempotency puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end if osfamily == 'Debian' shell querycommand do |r| - r.stdout.should_not =~ /ceph.com/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).not_to match(/ceph.com/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end if osfamily == 'RedHat' shell querycommand do |r| - r.stdout.should_not =~ /ceph.com/ - r.stderr.should =~ /Error: No matching Packages to list/ - r.exit_code.should_not be_zero + expect(r.stdout).not_to match(/ceph.com/) + expect(r.stderr).to match(/Error: No matching Packages to list/) + expect(r.exit_code).not_to be_zero end end end @@ -184,24 +184,24 @@ class { 'ceph::repo': # Run it twice and test for idempotency puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end # Test for a package in ceph-extras (curl/qemu-kvm) if osfamily == 'Debian' shell 'apt-cache policy curl' do |r| - r.stdout.should =~ /ceph\.com.*ceph-extras/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/ceph\.com.*ceph-extras/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end if osfamily == 'RedHat' shell 'yum info qemu-kvm' do |r| - r.stdout.should =~ /Repo.*ext-ceph-extras/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/Repo.*ext-ceph-extras/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end @@ -216,21 +216,21 @@ class { 'ceph::repo': # Run it twice and test for idempotency puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end if osfamily == 'Debian' shell 'apt-cache policy curl' do |r| - r.stdout.should_not =~ /ceph.com/ - r.exit_code.should be_zero + expect(r.stdout).not_to match(/ceph.com/) + expect(r.exit_code).to be_zero end end if osfamily == 'RedHat' shell 'yum info qemu-kvm' do |r| - r.stdout.should_not =~ /Repo.*ext-ceph-extras/ - r.exit_code.should be_zero + expect(r.stdout).not_to match(/Repo.*ext-ceph-extras/) + expect(r.exit_code).to be_zero end end end @@ -247,24 +247,24 @@ class { 'ceph::repo': # Run it twice and test for idempotency puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end # Test fastcgi in ceph-fastcgi if osfamily == 'Debian' shell 'apt-cache policy libapache2-mod-fastcgi' do |r| - r.stdout.should =~ /ceph.com/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/ceph.com/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end if osfamily == 'RedHat' shell 'yum info mod_fastcgi' do |r| - r.stdout.should =~ /Repo.*ext-ceph-fastcgi/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/Repo.*ext-ceph-fastcgi/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end @@ -279,22 +279,22 @@ class { 'ceph::repo': # Run it twice and test for idempotency puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end if osfamily == 'Debian' shell 'apt-cache policy libapache2-mod-fastcgi' do |r| - r.stdout.should_not =~ /ceph.com/ - r.exit_code.should be_zero + expect(r.stdout).not_to match(/ceph.com/) + expect(r.exit_code).to be_zero end end if osfamily == 'RedHat' shell 'yum info mod_fastcgi' do |r| - r.stdout.should_not =~ /Repo.*ext-ceph-fastcgi/ - r.stderr.should =~ /Error: No matching Packages to list/ - r.exit_code.should_not be_zero + expect(r.stdout).not_to match(/Repo.*ext-ceph-fastcgi/) + expect(r.stderr).to match(/Error: No matching Packages to list/) + expect(r.exit_code).not_to be_zero end end end diff --git a/ceph/spec/system/ceph_rgw_apache_spec.rb b/ceph/spec/system/ceph_rgw_apache_spec.rb index dcdbad0fe..fde061786 100644 --- a/ceph/spec/system/ceph_rgw_apache_spec.rb +++ b/ceph/spec/system/ceph_rgw_apache_spec.rb @@ -20,7 +20,7 @@ describe 'ceph::rgw::apache' do - releases = ENV['RELEASES'] ? ENV['RELEASES'].split : [ 'dumpling', 'firefly', 'giant' ] + releases = ENV['RELEASES'] ? ENV['RELEASES'].split : [ 'dumpling', 'giant' ] fsid = 'a4807c9a-e76f-4666-a297-6d6cbc922e3a' mon_key ='AQCztJdSyNb0NBAASA2yPZPuwXeIQnDJ9O8gVw==' admin_key = 'AQA0TVRTsP/aHxAAFBvntu1dSEJHxtJeFFrRsg==' @@ -109,36 +109,36 @@ class { 'ceph': } puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell servicequery[osfamily] do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell 'radosgw-admin user create --uid=puppet --display-name=puppet-user' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell 'radosgw-admin subuser create --uid=puppet --subuser=puppet:swift --access=full' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end # need to create subuser key twice, due to http://tracker.ceph.com/issues/9155 shell "radosgw-admin key create --subuser=puppet:swift --key-type=swift --secret='123456'" do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell "radosgw-admin key create --subuser=puppet:swift --key-type=swift --secret='123456'" do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end shell 'curl -i -H "X-Auth-User: puppet:swift" -H "X-Auth-Key: 123456" http://first/auth/v1.0/' do |r| - r.exit_code.should be_zero - r.stdout.should =~ /HTTP\/1\.1 204 No Content/ - r.stdout.should_not =~ /401 Unauthorized/ + expect(r.exit_code).to be_zero + expect(r.stdout).to match(/HTTP\/1\.1 204 No Content/) + expect(r.stdout).not_to match(/401 Unauthorized/) end end @@ -151,7 +151,7 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph-disk zap /dev/sdb' @@ -196,7 +196,7 @@ class { 'apache': EOS puppet_apply(purge) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end diff --git a/ceph/spec/system/ceph_usecases_spec.rb b/ceph/spec/system/ceph_usecases_spec.rb index 511e28825..0eef0ec52 100644 --- a/ceph/spec/system/ceph_usecases_spec.rb +++ b/ceph/spec/system/ceph_usecases_spec.rb @@ -49,27 +49,27 @@ class { 'ceph': puppet_apply(pp) do |r| # due to the generate() the above is not idempotent # so we don't run twice as usual - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'sleep 30' # we need to wait a bit until the OSD is up shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons at/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons at/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -79,12 +79,12 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell 'ceph osd tree | grep DNE' do |r| - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end @@ -96,7 +96,7 @@ class { 'ceph': EOS puppet_apply(pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end osfamily = facter.facts['osfamily'] @@ -104,16 +104,16 @@ class { 'ceph': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=a' do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.a/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.a/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.a' do |r| - r.stdout.should =~ /mon.a not found/ - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to match(/mon.a not found/) + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end end @@ -130,7 +130,7 @@ class { 'ceph::repo': machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -193,28 +193,28 @@ class { 'ceph': machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons at/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons at/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall one osd' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -224,13 +224,13 @@ class { 'ceph': EOS puppet_apply(:node => 'second', :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell(:node => 'second', :command => "test -b /dev/sdb && ceph-disk zap /dev/sdb") shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end end @@ -242,7 +242,7 @@ class { 'ceph': EOS puppet_apply(:node => 'first', :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end osfamily = facter.facts['osfamily'] @@ -250,16 +250,16 @@ class { 'ceph': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.first/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.first/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.first' do |r| - r.stdout.should =~ /mon.first not found/ - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to match(/mon.first not found/) + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end end @@ -276,7 +276,7 @@ class { 'ceph::repo': machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end @@ -316,29 +316,29 @@ class { 'ceph': machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) r.refresh - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end shell 'ceph -s' do |r| - r.stdout.should =~ /1 mons at/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/1 mons at/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end shell 'ceph osd tree' do |r| - r.stdout.should =~ /osd.0/ - r.stdout.should =~ /osd.1/ - r.stderr.should be_empty - r.exit_code.should be_zero + expect(r.stdout).to match(/osd.0/) + expect(r.stdout).to match(/osd.1/) + expect(r.stderr).to be_empty + expect(r.exit_code).to be_zero end end it 'should uninstall two OSDs' do shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should_not be_zero + expect(r.exit_code).not_to be_zero end pp = <<-EOS @@ -349,14 +349,14 @@ class { 'ceph': machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end shell(:node => vm, :command => "test -b /dev/sdb && ceph-disk zap /dev/sdb") end shell 'ceph osd tree | grep DNE' do |r| - r.exit_code.should be_zero + expect(r.exit_code).to be_zero end end @@ -368,7 +368,7 @@ class { 'ceph': EOS puppet_apply(:node => 'first', :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end osfamily = facter.facts['osfamily'] @@ -376,16 +376,16 @@ class { 'ceph': if osfamily == 'Debian' && operatingsystem == 'Ubuntu' shell 'status ceph-mon id=first' do |r| - r.stdout.should be_empty - r.stderr.should =~ /Unknown instance: ceph.first/ - r.exit_code.should_not be_zero + expect(r.stdout).to be_empty + expect(r.stderr).to match(/Unknown instance: ceph.first/) + expect(r.exit_code).not_to be_zero end end if osfamily == 'RedHat' shell 'service ceph status mon.first' do |r| - r.stdout.should =~ /mon.first not found/ - r.stderr.should be_empty - r.exit_code.should_not be_zero + expect(r.stdout).to match(/mon.first not found/) + expect(r.stderr).to be_empty + expect(r.exit_code).not_to be_zero end end end @@ -402,7 +402,7 @@ class { 'ceph::repo': machines.each do |vm| puppet_apply(:node => vm, :code => pp) do |r| - r.exit_code.should_not == 1 + expect(r.exit_code).not_to eq(1) end end end diff --git a/ceph/spec/unit/provider/ceph_config/ini_setting_spec.rb b/ceph/spec/unit/provider/ceph_config/ini_setting_spec.rb index f034d8857..8a944c691 100644 --- a/ceph/spec/unit/provider/ceph_config/ini_setting_spec.rb +++ b/ceph/spec/unit/provider/ceph_config/ini_setting_spec.rb @@ -43,16 +43,16 @@ } } def validate(expected, tmpfile = tmpfile) - File.read(tmpfile).should == expected + expect(File.read(tmpfile)).to eq(expected) end it 'should create keys = value and ensure space around equals' do resource = Puppet::Type::Ceph_config.new(params.merge( :name => 'global/ceph_is_foo', :value => 'bar')) provider = provider_class.new(resource) - provider.exists?.should be_falsey + expect(provider.exists?).to be_falsey provider.create - provider.exists?.should be_truthy + expect(provider.exists?).to be_truthy validate(<<-EOS [global] @@ -65,7 +65,7 @@ def validate(expected, tmpfile = tmpfile) resource = Puppet::Type::Ceph_config.new( :name => 'global/ceph_is_foo', :value => 'bar') provider = provider_class.new(resource) - provider.file_path.should == '/etc/ceph/ceph.conf' + expect(provider.file_path).to eq('/etc/ceph/ceph.conf') end end diff --git a/ceph/spec/unit/type/ceph_config_spec.rb b/ceph/spec/unit/type/ceph_config_spec.rb index 01e4af85b..c78dfb684 100644 --- a/ceph/spec/unit/type/ceph_config_spec.rb +++ b/ceph/spec/unit/type/ceph_config_spec.rb @@ -26,16 +26,16 @@ it 'should work bascily' do @ceph_config[:value] = 'max' - @ceph_config[:value].should == 'max' + expect(@ceph_config[:value]).to eq('max') end it 'should convert true to True' do @ceph_config[:value] = 'tRuE' - @ceph_config[:value].should == 'True' + expect(@ceph_config[:value]).to eq('True') end it 'should convert false to False' do @ceph_config[:value] = 'fAlSe' - @ceph_config[:value].should == 'False' + expect(@ceph_config[:value]).to eq('False') end end \ No newline at end of file diff --git a/cinder/manifests/api.pp b/cinder/manifests/api.pp index 828902ed2..ec861c9ea 100644 --- a/cinder/manifests/api.pp +++ b/cinder/manifests/api.pp @@ -40,6 +40,15 @@ # requests. For example, boot-from-volume. # Defaults to undef. # +# [*nova_catalog_info*] +# (optional) Match this value when searching for nova in the service +# catalog. +# Defaults to 'compute:Compute Service:publicURL' +# +# [*nova_catalog_admin_info*] +# (optional) Same as nova_catalog_info, but for admin endpoint. +# Defaults to 'compute:Compute Service:adminURL' +# # [*keystone_auth_admin_prefix*] # (optional) DEPRECATED The admin_prefix used to admin endpoint of the auth # host. This allow admin auth URIs like http://auth_host:35357/keystone. @@ -131,6 +140,8 @@ $auth_uri = false, $identity_uri = false, $os_region_name = undef, + $nova_catalog_info = 'compute:Compute Service:publicURL', + $nova_catalog_admin_info = 'compute:Compute Service:adminURL', $service_workers = $::processorcount, $package_ensure = 'present', $bind_host = '0.0.0.0', @@ -215,6 +226,11 @@ } } + cinder_config { + 'DEFAULT/nova_catalog_info': value => $nova_catalog_info; + 'DEFAULT/nova_catalog_admin_info': value => $nova_catalog_admin_info; + } + if $keystone_auth_uri and $auth_uri { fail('both keystone_auth_uri and auth_uri are set and they have the same meaning') } diff --git a/cinder/manifests/cron/db_purge.pp b/cinder/manifests/cron/db_purge.pp new file mode 100644 index 000000000..559f7848e --- /dev/null +++ b/cinder/manifests/cron/db_purge.pp @@ -0,0 +1,76 @@ +# +# Copyright (C) 2015 Red Hat Inc. +# +# Author: Martin Magr +# +# 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: cinder::cron::db_purge +# +# Move deleted instances to another table that you don't have to backup +# unless you have data retention policies. +# +# === Parameters +# +# [*minute*] +# (optional) Defaults to '1'. +# +# [*hour*] +# (optional) Defaults to '0'. +# +# [*monthday*] +# (optional) Defaults to '*'. +# +# [*month*] +# (optional) Defaults to '*'. +# +# [*weekday*] +# (optional) Defaults to '*'. +# +# [*user*] +# (optional) User with access to cinder files. +# Defaults to 'cinder'. +# +# [*age*] +# (optional) Number of days prior to today for deletion, +# e.g. value 60 means to purge deleted rows that have the "deleted_at" +# column greater than 60 days ago. +# Defaults to 30 +# +# [*destination*] +# (optional) Path to file to which rows should be archived +# Defaults to '/var/log/cinder/cinder-rowsflush.log'. +# +class cinder::cron::db_purge ( + $minute = 1, + $hour = 0, + $monthday = '*', + $month = '*', + $weekday = '*', + $user = 'cinder', + $age = 30, + $destination = '/var/log/cinder/cinder-rowsflush.log' +) { + + cron { 'cinder-manage db purge': + command => "cinder-manage db purge ${age} >>${destination} 2>&1", + environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh', + user => $user, + minute => $minute, + hour => $hour, + monthday => $monthday, + month => $month, + weekday => $weekday, + require => Package['cinder'], + } +} diff --git a/cinder/spec/acceptance/basic_cinder_spec.rb b/cinder/spec/acceptance/basic_cinder_spec.rb index f12c9e03d..9b5595b79 100644 --- a/cinder/spec/acceptance/basic_cinder_spec.rb +++ b/cinder/spec/acceptance/basic_cinder_spec.rb @@ -102,6 +102,7 @@ class { '::cinder::quota': } class { '::cinder::scheduler': } class { '::cinder::scheduler::filter': } class { '::cinder::volume': } + class { '::cinder::cron::db_purge': } # TODO: create a backend and spawn a volume EOS @@ -115,5 +116,10 @@ class { '::cinder::volume': } it { is_expected.to be_listening.with('tcp') } end + describe cron do + it { is_expected.to have_entry('1 0 * * * cinder-manage db purge 30 >>/var/log/cinder/cinder-rowsflush.log 2>&1').with_user('cinder') } + end + + end end diff --git a/cinder/spec/classes/cinder_api_spec.rb b/cinder/spec/classes/cinder_api_spec.rb index e901ec9a0..7be1b6552 100644 --- a/cinder/spec/classes/cinder_api_spec.rb +++ b/cinder/spec/classes/cinder_api_spec.rb @@ -30,6 +30,12 @@ is_expected.to contain_cinder_config('DEFAULT/osapi_volume_workers').with( :value => '8' ) + is_expected.to contain_cinder_config('DEFAULT/nova_catalog_info').with( + :value => 'compute:Compute Service:publicURL' + ) + is_expected.to contain_cinder_config('DEFAULT/nova_catalog_admin_info').with( + :value => 'compute:Compute Service:adminURL' + ) is_expected.to contain_cinder_config('DEFAULT/default_volume_type').with( :ensure => 'absent' ) @@ -73,6 +79,17 @@ end end + describe 'with a custom nova_catalog params' do + let :params do + req_params.merge({ + 'nova_catalog_admin_info' => 'compute:nova:adminURL', + 'nova_catalog_info' => 'compute:nova:publicURL', + }) + end + it { is_expected.to contain_cinder_config('DEFAULT/nova_catalog_admin_info').with_value('compute:nova:adminURL') } + it { is_expected.to contain_cinder_config('DEFAULT/nova_catalog_info').with_value('compute:nova:publicURL') } + end + describe 'with a custom region for nova' do let :params do req_params.merge({'os_region_name' => 'MyRegion'}) diff --git a/cinder/spec/classes/cinder_cron_db_purge_spec.rb b/cinder/spec/classes/cinder_cron_db_purge_spec.rb new file mode 100644 index 000000000..f78e9a7bc --- /dev/null +++ b/cinder/spec/classes/cinder_cron_db_purge_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe 'cinder::cron::db_purge' do + + let :facts do + { :osfamily => 'RedHat' } + end + + let :params do + { :minute => 1, + :hour => 0, + :monthday => '*', + :month => '*', + :weekday => '*', + :user => 'cinder', + :age => '30', + :destination => '/var/log/cinder/cinder-rowsflush.log' } + end + + it 'configures a cron' do + is_expected.to contain_cron('cinder-manage db purge').with( + :command => "cinder-manage db purge #{params[:age]} >>#{params[:destination]} 2>&1", + :environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh', + :user => params[:user], + :minute => params[:minute], + :hour => params[:hour], + :monthday => params[:monthday], + :month => params[:month], + :weekday => params[:weekday], + :require => 'Package[cinder]', + ) + end +end diff --git a/gnocchi/.fixtures.yml b/gnocchi/.fixtures.yml deleted file mode 100644 index 2561c2fce..000000000 --- a/gnocchi/.fixtures.yml +++ /dev/null @@ -1,13 +0,0 @@ -fixtures: - repositories: - 'inifile': 'git://github.com/puppetlabs/puppetlabs-inifile' - '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' - 'openstacklib': 'git://github.com/stackforge/puppet-openstacklib.git' - 'postgresql': 'git://github.com/puppetlabs/puppet-postgresql.git' - 'stdlib': 'git://github.com/puppetlabs/puppetlabs-stdlib.git' - symlinks: - 'gnocchi': "#{source_dir}" diff --git a/gnocchi/.gitignore b/gnocchi/.gitignore index da4238187..15c55efd0 100644 --- a/gnocchi/.gitignore +++ b/gnocchi/.gitignore @@ -1,7 +1,11 @@ -*.swp -spec/fixtures/modules/* -spec/fixtures/manifests/site.pp +pkg/ Gemfile.lock -.vendor -.bundle/ vendor/ +spec/fixtures/ +.vagrant/ +.bundle/ +coverage/ +.idea/ +*.swp +*.iml +openstack/ diff --git a/gnocchi/Gemfile b/gnocchi/Gemfile index 9ea211333..fc2214398 100644 --- a/gnocchi/Gemfile +++ b/gnocchi/Gemfile @@ -1,25 +1,31 @@ -source 'https://rubygems.org' +source ENV['GEM_SOURCE'] || "https://rubygems.org" group :development, :test do - gem 'puppetlabs_spec_helper', :require => false - gem 'rspec-puppet', '~> 2.1.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' + gem 'puppetlabs_spec_helper', :require => 'false' + gem 'rspec-puppet', '~> 2.2.0', :require => 'false' + gem 'metadata-json-lint', :require => 'false' + gem 'puppet-lint-param-docs', :require => 'false' + gem 'puppet-lint-absolute_classname-check', :require => 'false' + gem 'puppet-lint-absolute_template_path', :require => 'false' + gem 'puppet-lint-trailing_newline-check', :require => 'false' + gem 'puppet-lint-unquoted_string-check', :require => 'false' + gem 'puppet-lint-leading_zero-check', :require => 'false' + gem 'puppet-lint-variable_contains_upcase', :require => 'false' + gem 'puppet-lint-numericvariable', :require => 'false' + gem 'json', :require => 'false' + gem 'webmock', :require => 'false' +end - # 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' +group :system_tests do + gem 'beaker-rspec', :require => 'false' + gem 'beaker-puppet_install_helper', :require => 'false' + gem 'r10k', :require => 'false' +end - gem 'beaker-rspec', :require => false - gem 'beaker-puppet_install_helper', :require => false - gem 'json' - gem 'webmock' +if facterversion = ENV['FACTER_GEM_VERSION'] + gem 'facter', facterversion, :require => false +else + gem 'facter', :require => false end if puppetversion = ENV['PUPPET_GEM_VERSION'] diff --git a/gnocchi/README.md b/gnocchi/README.md index 5a00b70be..00ac0ed86 100644 --- a/gnocchi/README.md +++ b/gnocchi/README.md @@ -34,6 +34,36 @@ Implementation gnocchi is a combination of Puppet manifest and ruby code to delivery configuration and extra functionality through types and providers. +### Types + +#### gnocchi_config + +The `gnocchi_config` provider is a children of the ini_setting provider. It allows one to write an entry in the `/etc/gnocchi/gnocchi.conf` file. + +```puppet +gnocchi_config { 'DEFAULT/verbose' : + value => true, +} +``` + +This will write `verbose=true` in the `[DEFAULT]` section. + +##### name + +Section/setting name to manage from `gnocchi.conf` + +##### value + +The value of the setting to be defined. + +##### secret + +Whether to hide the value from Puppet logs. Defaults to `false`. + +##### ensure_absent_val + +If value is equal to ensure_absent_val then the resource will behave as if `ensure => absent` was specified. Defaults to `` + Limitations ----------- diff --git a/gnocchi/Rakefile b/gnocchi/Rakefile index 84c9a7046..3c3603e3c 100644 --- a/gnocchi/Rakefile +++ b/gnocchi/Rakefile @@ -1,9 +1,85 @@ require 'puppetlabs_spec_helper/rake_tasks' require 'puppet-lint/tasks/puppet-lint' +require 'puppet-syntax/tasks/puppet-syntax' +require 'json' -PuppetLint.configuration.fail_on_warnings = true -PuppetLint.configuration.send('disable_80chars') -PuppetLint.configuration.send('disable_class_parameter_defaults') +modname = JSON.parse(open('metadata.json').read)['name'].split('-')[1] -task(:default).clear -task :default => [:spec, :lint] +PuppetSyntax.exclude_paths ||= [] +PuppetSyntax.exclude_paths << "spec/fixtures/**/*" +PuppetSyntax.exclude_paths << "pkg/**/*" +PuppetSyntax.exclude_paths << "vendor/**/*" + +Rake::Task[:lint].clear +PuppetLint::RakeTask.new :lint do |config| + config.ignore_paths = ["spec/**/*.pp", "vendor/**/*.pp"] + config.fail_on_warnings = true + config.log_format = '%{path}:%{linenumber}:%{KIND}: %{message}' + config.disable_checks = ["80chars", "class_inherits_from_params_class", "class_parameter_defaults", "only_variable_string"] +end + +desc "Run acceptance tests" +RSpec::Core::RakeTask.new(:acceptance) do |t| + t.pattern = 'spec/acceptance' +end + +Rake::Task[:spec_prep].clear +desc 'Create the fixtures directory' +task :spec_prep do + # Allow to test the module with custom dependencies + # like you could do with .fixtures file + if ENV['PUPPETFILE'] + puppetfile = ENV['PUPPETFILE'] + if ENV['GEM_HOME'] + gem_home = ENV['GEM_HOME'] + gem_bin_dir = "#{gem_home}" + '/bin/' + else + gem_bin_dir = '' + end + r10k = ['env'] + r10k += ["PUPPETFILE=#{puppetfile}"] + r10k += ["PUPPETFILE_DIR=#{Dir.pwd}/spec/fixtures/modules"] + r10k += ["#{gem_bin_dir}r10k"] + r10k += ['puppetfile', 'install', '-v'] + sh(*r10k) + else + # otherwise, use official OpenStack Puppetfile + zuul_ref = ENV['ZUUL_REF'] + zuul_branch = ENV['ZUUL_BRANCH'] + zuul_url = ENV['ZUUL_URL'] + repo = 'openstack/puppet-openstack-integration' + rm_rf(repo) + if File.exists?('/usr/zuul-env/bin/zuul-cloner') + zuul_clone_cmd = ['/usr/zuul-env/bin/zuul-cloner'] + zuul_clone_cmd += ['--cache-dir', '/opt/git'] + zuul_clone_cmd += ['--zuul-ref', "#{zuul_ref}"] + zuul_clone_cmd += ['--zuul-branch', "#{zuul_branch}"] + zuul_clone_cmd += ['--zuul-url', "#{zuul_url}"] + zuul_clone_cmd += ['git://git.openstack.org', "#{repo}"] + sh(*zuul_clone_cmd) + else + sh("git clone https://git.openstack.org/#{repo} #{repo}") + end + script = ['env'] + script += ["PUPPETFILE_DIR=#{Dir.pwd}/spec/fixtures/modules"] + script += ["ZUUL_REF=#{zuul_ref}"] + script += ["ZUUL_BRANCH=#{zuul_branch}"] + script += ["ZUUL_URL=#{zuul_url}"] + script += ['bash', "#{repo}/install_modules_unit.sh"] + sh(*script) + end + rm_rf("spec/fixtures/modules/#{modname}") + ln_s(Dir.pwd, "spec/fixtures/modules/#{modname}") + mkdir_p('spec/fixtures/manifests') + touch('spec/fixtures/manifests/site.pp') +end + +Rake::Task[:spec_clean].clear +desc 'Clean up the fixtures directory' +task :spec_clean do + rm_rf('spec/fixtures/modules') + rm_rf('openstack') + if File.zero?('spec/fixtures/manifests/site.pp') + rm_f('spec/fixtures/manifests/site.pp') + end +end diff --git a/gnocchi/lib/puppet/provider/gnocchi_config/ini_setting.rb b/gnocchi/lib/puppet/provider/gnocchi_config/ini_setting.rb index 0fee4b125..e4f5888aa 100644 --- a/gnocchi/lib/puppet/provider/gnocchi_config/ini_setting.rb +++ b/gnocchi/lib/puppet/provider/gnocchi_config/ini_setting.rb @@ -1,27 +1,10 @@ Puppet::Type.type(:gnocchi_config).provide( :ini_setting, - :parent => Puppet::Type.type(:ini_setting).provider(:ruby) + :parent => Puppet::Type.type(:openstack_config).provider(:ini_setting) ) do - def section - resource[:name].split('/', 2).first - end - - def setting - resource[:name].split('/', 2).last - end - - def separator - '=' - end - def self.file_path '/etc/gnocchi/gnocchi.conf' end - # added for backwards compatibility with older versions of inifile - def file_path - self.class.file_path - end - end diff --git a/gnocchi/lib/puppet/type/gnocchi_config.rb b/gnocchi/lib/puppet/type/gnocchi_config.rb index 9fbf10c0f..7c32cf25c 100644 --- a/gnocchi/lib/puppet/type/gnocchi_config.rb +++ b/gnocchi/lib/puppet/type/gnocchi_config.rb @@ -14,6 +14,7 @@ value.capitalize! if value =~ /^(true|false)$/i value end + newvalues(/^[\S ]*$/) def is_to_s( currentvalue ) if resource.secret? @@ -39,4 +40,14 @@ def should_to_s( newvalue ) defaultto false end + + newparam(:ensure_absent_val) do + desc 'A value that is specified as the value property will behave as if ensure => absent was specified' + defaultto('') + end + + autorequire(:package) do + 'gnocchi-api' + end + end diff --git a/gnocchi/manifests/api.pp b/gnocchi/manifests/api.pp index 86be53de3..bbb12a3f9 100644 --- a/gnocchi/manifests/api.pp +++ b/gnocchi/manifests/api.pp @@ -34,21 +34,33 @@ # # [*verbose*] # (optional) Rather to log the gnocchi api service at verbose level. -# Default: false +# Defaults to undef # # [*debug*] # (optional) Rather to log the gnocchi api service at debug level. -# Default: false +# Defaults to undef # # [*log_file*] # (optional) The path of file used for logging # If set to boolean false, it will not log to any file. -# Default: /var/log/gnocchi/gnocchi-api.log +# Defaults to undef # -# [*log_dir*] +# [*use_syslog*] +# (Optional) Use syslog for logging. +# Defaults to undef +# +# [*use_stderr*] +# (optional) Use stderr for logging +# Defaults to undef +# +# [*log_facility*] +# (Optional) Syslog facility to receive log lines. +# Defaults to undef +# +# [*log_dir*] # (optional) directory to which gnocchi logs are sent. # If set to boolean false, it will not log to any directory. -# Defaults to '/var/log/gnocchi' +# Defaults to undef # # [*keystone_tenant*] # (optional) Tenant to authenticate to. @@ -81,10 +93,13 @@ # class gnocchi::api( $keystone_password, - $verbose = false, - $debug = false, - $log_file = '/var/log/gnocchi/gnocchi-api.log', - $log_dir = '/var/log/gnocchi', + $verbose = undef, + $debug = undef, + $use_syslog = undef, + $use_stderr = undef, + $log_facility = undef, + $log_dir = undef, + $log_file = undef, $keystone_tenant = 'services', $keystone_user = 'gnocchi', $identity_uri = 'http://127.0.0.1:35357', @@ -97,11 +112,11 @@ ) inherits gnocchi { require ::keystone::python + include ::gnocchi::logging include ::gnocchi::params Gnocchi_config<||> ~> Exec['post-gnocchi_config'] Gnocchi_config<||> ~> Service['gnocchi-api'] - Package['gnocchi-api'] -> Gnocchi_config<||> if $::gnocchi::database_connection { if($::gnocchi::database_connection =~ /mysql:\/\/\S+:\S+@\S+\/\S+/) { @@ -122,47 +137,12 @@ # basic service config gnocchi_config { - 'DEFAULT/verbose': value => $verbose; - 'DEFAULT/debug': value => $debug; 'keystone_authtoken/identity_uri': value => $identity_uri; 'keystone_authtoken/admin_user': value => $keystone_user; 'keystone_authtoken/admin_password': value => $keystone_password, secret => true; 'keystone_authtoken/admin_tenant_name': value => $keystone_tenant; } - # Logging - if $log_file { - gnocchi_config { - 'DEFAULT/log_file': value => $log_file; - } - } else { - gnocchi_config { - 'DEFAULT/log_file': ensure => absent; - } - } - - if $log_dir { - gnocchi_config { - 'DEFAULT/log_dir': value => $log_dir; - } - } else { - gnocchi_config { - 'DEFAULT/log_dir': ensure => absent; - } - } - - # Syslog - if $use_syslog { - gnocchi_config { - 'DEFAULT/use_syslog' : value => true; - 'DEFAULT/syslog_log_facility' : value => $log_facility; - } - } else { - gnocchi_config { - 'DEFAULT/use_syslog': value => false; - } - } - resources { 'gnocchi_config': purge => $purge_config, } diff --git a/gnocchi/manifests/config.pp b/gnocchi/manifests/config.pp new file mode 100644 index 000000000..7e473ec9b --- /dev/null +++ b/gnocchi/manifests/config.pp @@ -0,0 +1,30 @@ +# == Class: gnocchi::config +# +# This class is used to manage arbitrary Gnocchi configurations. +# +# === Parameters +# +# [*gnocchi_config*] +# (optional) Allow configuration of arbitrary Gnocchi configurations. +# The value is an hash of gnocchi_config resources. Example: +# { 'DEFAULT/foo' => { value => 'fooValue'}, +# 'DEFAULT/bar' => { value => 'barValue'} +# } +# In yaml format, Example: +# gnocchi_config: +# DEFAULT/foo: +# value: fooValue +# DEFAULT/bar: +# value: barValue +# +# NOTE: The configuration MUST NOT be already handled by this module +# or Puppet catalog compilation will fail with duplicate resources. +# +class gnocchi::config ( + $gnocchi_config = {}, +) { + + validate_hash($gnocchi_config) + + create_resources('gnocchi_config', $gnocchi_config) +} diff --git a/gnocchi/manifests/generic_service.pp b/gnocchi/manifests/generic_service.pp index 9530cc151..9e0e898a0 100644 --- a/gnocchi/manifests/generic_service.pp +++ b/gnocchi/manifests/generic_service.pp @@ -68,6 +68,7 @@ ensure => $ensure_package, name => $package_name, notify => Service[$gnocchi_title], + tag => ['openstack', 'gnocchi-package'], } } } @@ -86,6 +87,7 @@ name => $service_name, enable => $enabled, hasstatus => true, + tag => 'gnocchi-service', } } } diff --git a/gnocchi/manifests/keystone/auth.pp b/gnocchi/manifests/keystone/auth.pp index cb010d9d6..129b0e253 100644 --- a/gnocchi/manifests/keystone/auth.pp +++ b/gnocchi/manifests/keystone/auth.pp @@ -45,6 +45,9 @@ # [*service_type*] # Type of service. Defaults to 'gnocchi'. # +# [*service_description*] +# Description for keystone service. Optional. Defaults to 'OpenStack Datapoint Service'. +# # [*public_protocol*] # Protocol for public endpoint. Defaults to 'http'. # @@ -88,6 +91,7 @@ $configure_user = true, $configure_user_role = true, $service_type = 'gnocchi', + $service_description = 'OpenStack Datapoint Service', $public_protocol = 'http', $public_address = '127.0.0.1', $public_port = '8041', @@ -108,7 +112,7 @@ configure_user_role => true, configure_endpoint => $configure_endpoint, service_type => $service_type, - service_description => 'OpenStack Datapoint Service', + service_description => $service_description, region => $region, password => $password, email => $email, diff --git a/gnocchi/manifests/logging.pp b/gnocchi/manifests/logging.pp new file mode 100644 index 000000000..38586ab2e --- /dev/null +++ b/gnocchi/manifests/logging.pp @@ -0,0 +1,265 @@ +# Class gnocchi::logging +# +# gnocchi logging configuration +# +# == parameters +# +# [*verbose*] +# (Optional) Should the daemons log verbose messages +# Defaults to 'false' +# +# [*debug*] +# (Optional) Should the daemons log debug messages +# Defaults to 'false' +# +# [*use_syslog*] +# (Optional) Use syslog for logging. +# Defaults to 'false' +# +# [*use_stderr*] +# (optional) Use stderr for logging +# Defaults to 'true' +# +# [*log_facility*] +# (Optional) Syslog facility to receive log lines. +# Defaults to 'LOG_USER' +# +# [*log_dir*] +# (optional) Directory where logs should be stored. +# If set to boolean false, it will not log to any directory. +# Defaults to '/var/log/gnocchi' +# +# [*log_file*] +# (optional) The path of file used for logging +# If set to boolean false, it will not log to any file. +# Default to '/var/log/gnocchi-api.log' +# +# [*logging_context_format_string*] +# (optional) Format string to use for log messages with context. +# Defaults to undef. +# Example: '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s\ +# [%(request_id)s %(user_identity)s] %(instance)s%(message)s' +# +# [*logging_default_format_string*] +# (optional) Format string to use for log messages without context. +# Defaults to undef. +# Example: '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s\ +# [-] %(instance)s%(message)s' +# +# [*logging_debug_format_suffix*] +# (optional) Formatted data to append to log format when level is DEBUG. +# Defaults to undef. +# Example: '%(funcName)s %(pathname)s:%(lineno)d' +# +# [*logging_exception_prefix*] +# (optional) Prefix each line of exception output with this format. +# Defaults to undef. +# Example: '%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s' +# +# [*log_config_append*] +# The name of an additional logging configuration file. +# Defaults to undef. +# See https://docs.python.org/2/howto/logging.html +# +# [*default_log_levels*] +# (optional) Hash of logger (keys) and level (values) pairs. +# Defaults to undef. +# Example: +# { 'amqp' => 'WARN', 'amqplib' => 'WARN', 'boto' => 'WARN', +# 'qpid' => 'WARN', 'sqlalchemy' => 'WARN', 'suds' => 'INFO', +# 'iso8601' => 'WARN', +# 'requests.packages.urllib3.connectionpool' => 'WARN' } +# +# [*publish_errors*] +# (optional) Publish error events (boolean value). +# Defaults to undef (false if unconfigured). +# +# [*fatal_deprecations*] +# (optional) Make deprecations fatal (boolean value) +# Defaults to undef (false if unconfigured). +# +# [*instance_format*] +# (optional) If an instance is passed with the log message, format it +# like this (string value). +# Defaults to undef. +# Example: '[instance: %(uuid)s] ' +# +# [*instance_uuid_format*] +# (optional) If an instance UUID is passed with the log message, format +# it like this (string value). +# Defaults to undef. +# Example: instance_uuid_format='[instance: %(uuid)s] ' + +# [*log_date_format*] +# (optional) Format string for %%(asctime)s in log records. +# Defaults to undef. +# Example: 'Y-%m-%d %H:%M:%S' + +class gnocchi::logging( + $use_syslog = false, + $use_stderr = true, + $log_facility = 'LOG_USER', + $log_dir = '/var/log/gnocchi', + $log_file = '/var/log/gnocchi/gnocchi-api.log', + $verbose = false, + $debug = false, + $logging_context_format_string = undef, + $logging_default_format_string = undef, + $logging_debug_format_suffix = undef, + $logging_exception_prefix = undef, + $log_config_append = undef, + $default_log_levels = undef, + $publish_errors = undef, + $fatal_deprecations = undef, + $instance_format = undef, + $instance_uuid_format = undef, + $log_date_format = undef, +) { + + # NOTE(spredzy): In order to keep backward compatibility we rely on the pick function + # to use gnocchi:: first then gnocchi::logging::. + $use_syslog_real = pick($::gnocchi::api::use_syslog,$use_syslog) + $use_stderr_real = pick($::gnocchi::api::use_stderr,$use_stderr) + $log_facility_real = pick($::gnocchi::api::log_facility,$log_facility) + $log_dir_real = pick($::gnocchi::api::log_dir,$log_dir) + $log_file_real = pick($::gnocchi::api::log_file,$log_file) + $verbose_real = pick($::gnocchi::api::verbose,$verbose) + $debug_real = pick($::gnocchi::api::debug,$debug) + + gnocchi_config { + 'DEFAULT/debug' : value => $debug_real; + 'DEFAULT/verbose' : value => $verbose_real; + 'DEFAULT/use_stderr' : value => $use_stderr_real; + 'DEFAULT/use_syslog' : value => $use_syslog_real; + 'DEFAULT/log_dir' : value => $log_dir_real; + 'DEFAULT/log_file' : value => $log_file_real; + 'DEFAULT/syslog_log_facility': value => $log_facility_real; + } + + if $logging_context_format_string { + gnocchi_config { + 'DEFAULT/logging_context_format_string' : + value => $logging_context_format_string; + } + } + else { + gnocchi_config { + 'DEFAULT/logging_context_format_string' : ensure => absent; + } + } + + if $logging_default_format_string { + gnocchi_config { + 'DEFAULT/logging_default_format_string' : + value => $logging_default_format_string; + } + } + else { + gnocchi_config { + 'DEFAULT/logging_default_format_string' : ensure => absent; + } + } + + if $logging_debug_format_suffix { + gnocchi_config { + 'DEFAULT/logging_debug_format_suffix' : + value => $logging_debug_format_suffix; + } + } + else { + gnocchi_config { + 'DEFAULT/logging_debug_format_suffix' : ensure => absent; + } + } + + if $logging_exception_prefix { + gnocchi_config { + 'DEFAULT/logging_exception_prefix' : value => $logging_exception_prefix; + } + } + else { + gnocchi_config { + 'DEFAULT/logging_exception_prefix' : ensure => absent; + } + } + + if $log_config_append { + gnocchi_config { + 'DEFAULT/log_config_append' : value => $log_config_append; + } + } + else { + gnocchi_config { + 'DEFAULT/log_config_append' : ensure => absent; + } + } + + if $default_log_levels { + gnocchi_config { + 'DEFAULT/default_log_levels' : + value => join(sort(join_keys_to_values($default_log_levels, '=')), ','); + } + } + else { + gnocchi_config { + 'DEFAULT/default_log_levels' : ensure => absent; + } + } + + if $publish_errors { + gnocchi_config { + 'DEFAULT/publish_errors' : value => $publish_errors; + } + } + else { + gnocchi_config { + 'DEFAULT/publish_errors' : ensure => absent; + } + } + + if $fatal_deprecations { + gnocchi_config { + 'DEFAULT/fatal_deprecations' : value => $fatal_deprecations; + } + } + else { + gnocchi_config { + 'DEFAULT/fatal_deprecations' : ensure => absent; + } + } + + if $instance_format { + gnocchi_config { + 'DEFAULT/instance_format' : value => $instance_format; + } + } + else { + gnocchi_config { + 'DEFAULT/instance_format' : ensure => absent; + } + } + + if $instance_uuid_format { + gnocchi_config { + 'DEFAULT/instance_uuid_format' : value => $instance_uuid_format; + } + } + else { + gnocchi_config { + 'DEFAULT/instance_uuid_format' : ensure => absent; + } + } + + if $log_date_format { + gnocchi_config { + 'DEFAULT/log_date_format' : value => $log_date_format; + } + } + else { + gnocchi_config { + 'DEFAULT/log_date_format' : ensure => absent; + } + } + + +} diff --git a/gnocchi/spec/acceptance/nodesets/centos-70-x64.yml b/gnocchi/spec/acceptance/nodesets/centos-70-x64.yml new file mode 100644 index 000000000..5f097e9fe --- /dev/null +++ b/gnocchi/spec/acceptance/nodesets/centos-70-x64.yml @@ -0,0 +1,11 @@ +HOSTS: + centos-server-70-x64: + roles: + - master + platform: el-7-x86_64 + box: puppetlabs/centos-7.0-64-nocm + box_url: https://vagrantcloud.com/puppetlabs/centos-7.0-64-nocm + hypervisor: vagrant +CONFIG: + log_level: debug + type: foss diff --git a/gnocchi/spec/acceptance/nodesets/default.yml b/gnocchi/spec/acceptance/nodesets/default.yml index cba1cd04c..486b6a34e 100644 --- a/gnocchi/spec/acceptance/nodesets/default.yml +++ b/gnocchi/spec/acceptance/nodesets/default.yml @@ -1,11 +1,10 @@ HOSTS: - ubuntu-server-1404-x64: + ubuntu-server-14.04-amd64: roles: - master platform: ubuntu-14.04-amd64 - box : puppetlabs/ubuntu-14.04-64-nocm - box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm - hypervisor : vagrant + box: puppetlabs/ubuntu-14.04-64-nocm + box_url: https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm + hypervisor: vagrant CONFIG: - log_level : debug - type: git + type: foss diff --git a/gnocchi/spec/acceptance/nodesets/nodepool-centos7.yml b/gnocchi/spec/acceptance/nodesets/nodepool-centos7.yml index 575ae6732..c55287420 100644 --- a/gnocchi/spec/acceptance/nodesets/nodepool-centos7.yml +++ b/gnocchi/spec/acceptance/nodesets/nodepool-centos7.yml @@ -3,7 +3,7 @@ HOSTS: roles: - master platform: el-7-x86_64 - hypervisor : none + hypervisor: none ip: 127.0.0.1 CONFIG: type: foss diff --git a/gnocchi/spec/acceptance/nodesets/nodepool-trusty.yml b/gnocchi/spec/acceptance/nodesets/nodepool-trusty.yml index a95d9f38d..9fc624e24 100644 --- a/gnocchi/spec/acceptance/nodesets/nodepool-trusty.yml +++ b/gnocchi/spec/acceptance/nodesets/nodepool-trusty.yml @@ -3,7 +3,7 @@ HOSTS: roles: - master platform: ubuntu-14.04-amd64 - hypervisor : none + hypervisor: none ip: 127.0.0.1 CONFIG: type: foss diff --git a/gnocchi/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/gnocchi/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml index cba1cd04c..8001929b2 100644 --- a/gnocchi/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml +++ b/gnocchi/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml @@ -1,11 +1,11 @@ HOSTS: - ubuntu-server-1404-x64: + ubuntu-server-14.04-amd64: roles: - master platform: ubuntu-14.04-amd64 - box : puppetlabs/ubuntu-14.04-64-nocm - box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm - hypervisor : vagrant + box: puppetlabs/ubuntu-14.04-64-nocm + box_url: https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm + hypervisor: vagrant CONFIG: - log_level : debug - type: git + log_level: debug + type: foss diff --git a/gnocchi/spec/classes/gnocchi_api_spec.rb b/gnocchi/spec/classes/gnocchi_api_spec.rb index 244c875e3..fd1e04022 100644 --- a/gnocchi/spec/classes/gnocchi_api_spec.rb +++ b/gnocchi/spec/classes/gnocchi_api_spec.rb @@ -17,6 +17,10 @@ context 'with default parameters' do + it 'contains the logging class' do + is_expected.to contain_class('gnocchi::logging') + end + it 'installs gnocchi-api package and service' do is_expected.to contain_service('gnocchi-api').with( :name => platform_params[:api_service_name], @@ -32,8 +36,6 @@ end it 'configures gnocchi-api with default parameters' do - is_expected.to contain_gnocchi_config('DEFAULT/verbose').with_value(false) - is_expected.to contain_gnocchi_config('DEFAULT/debug').with_value(false) is_expected.to contain_gnocchi_config('keystone_authtoken/identity_uri').with_value(params[:identity_uri]) is_expected.to contain_gnocchi_config('keystone_authtoken/admin_tenant_name').with_value(params[:keystone_tenant]) is_expected.to contain_gnocchi_config('keystone_authtoken/admin_user').with_value(params[:keystone_user]) diff --git a/gnocchi/spec/classes/gnocchi_config_spec.rb b/gnocchi/spec/classes/gnocchi_config_spec.rb new file mode 100644 index 000000000..edf53aeb8 --- /dev/null +++ b/gnocchi/spec/classes/gnocchi_config_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe 'gnocchi::config' do + + let :params do + { :gnocchi_config => { + 'DEFAULT/foo' => { 'value' => 'fooValue' }, + 'DEFAULT/bar' => { 'value' => 'barValue' }, + 'DEFAULT/baz' => { 'ensure' => 'absent' } + } + } + end + + it 'configures arbitrary gnocchi configurations' do + is_expected.to contain_gnocchi_config('DEFAULT/foo').with_value('fooValue') + is_expected.to contain_gnocchi_config('DEFAULT/bar').with_value('barValue') + is_expected.to contain_gnocchi_config('DEFAULT/baz').with_ensure('absent') + end + +end diff --git a/gnocchi/spec/classes/gnocchi_logging_spec.rb b/gnocchi/spec/classes/gnocchi_logging_spec.rb new file mode 100644 index 000000000..6a4c3e4a5 --- /dev/null +++ b/gnocchi/spec/classes/gnocchi_logging_spec.rb @@ -0,0 +1,146 @@ +require 'spec_helper' + +describe 'gnocchi::logging' do + + let :params do + { + } + end + + let :log_params do + { + :logging_context_format_string => '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s', + :logging_default_format_string => '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s', + :logging_debug_format_suffix => '%(funcName)s %(pathname)s:%(lineno)d', + :logging_exception_prefix => '%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s', + :log_config_append => '/etc/gnocchi/logging.conf', + :publish_errors => true, + :default_log_levels => { + 'amqp' => 'WARN', 'amqplib' => 'WARN', 'boto' => 'WARN', + 'qpid' => 'WARN', 'sqlalchemy' => 'WARN', 'suds' => 'INFO', + 'iso8601' => 'WARN', + 'requests.packages.urllib3.connectionpool' => 'WARN' }, + :fatal_deprecations => true, + :instance_format => '[instance: %(uuid)s] ', + :instance_uuid_format => '[instance: %(uuid)s] ', + :log_date_format => '%Y-%m-%d %H:%M:%S', + :use_syslog => true, + :use_stderr => false, + :log_facility => 'LOG_FOO', + :log_dir => '/var/log', + :log_file => '/var/log/foo.log', + :verbose => true, + :debug => true, + } + end + + shared_examples_for 'gnocchi-logging' do + + context 'with basic logging options and default settings' do + it_configures 'basic default logging settings' + end + + context 'with basic logging options and non-default settings' do + before { params.merge!( log_params ) } + it_configures 'basic non-default logging settings' + end + + context 'with extended logging options' do + before { params.merge!( log_params ) } + it_configures 'logging params set' + end + + context 'without extended logging options' do + it_configures 'logging params unset' + end + + end + + shared_examples 'basic default logging settings' do + it 'configures gnocchi logging settins with default values' do + is_expected.to contain_gnocchi_config('DEFAULT/use_syslog').with(:value => 'false') + is_expected.to contain_gnocchi_config('DEFAULT/use_stderr').with(:value => 'true') + is_expected.to contain_gnocchi_config('DEFAULT/log_dir').with(:value => '/var/log/gnocchi') + is_expected.to contain_gnocchi_config('DEFAULT/log_file').with(:value => '/var/log/gnocchi/gnocchi-api.log') + is_expected.to contain_gnocchi_config('DEFAULT/verbose').with(:value => 'false') + is_expected.to contain_gnocchi_config('DEFAULT/debug').with(:value => 'false') + end + end + + shared_examples 'basic non-default logging settings' do + it 'configures gnocchi logging settins with non-default values' do + is_expected.to contain_gnocchi_config('DEFAULT/use_syslog').with(:value => 'true') + is_expected.to contain_gnocchi_config('DEFAULT/use_stderr').with(:value => 'false') + is_expected.to contain_gnocchi_config('DEFAULT/syslog_log_facility').with(:value => 'LOG_FOO') + is_expected.to contain_gnocchi_config('DEFAULT/log_dir').with(:value => '/var/log') + is_expected.to contain_gnocchi_config('DEFAULT/log_file').with(:value => '/var/log/foo.log') + is_expected.to contain_gnocchi_config('DEFAULT/verbose').with(:value => 'true') + is_expected.to contain_gnocchi_config('DEFAULT/debug').with(:value => 'true') + end + end + + shared_examples_for 'logging params set' do + it 'enables logging params' do + is_expected.to contain_gnocchi_config('DEFAULT/logging_context_format_string').with_value( + '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s') + + is_expected.to contain_gnocchi_config('DEFAULT/logging_default_format_string').with_value( + '%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s') + + is_expected.to contain_gnocchi_config('DEFAULT/logging_debug_format_suffix').with_value( + '%(funcName)s %(pathname)s:%(lineno)d') + + is_expected.to contain_gnocchi_config('DEFAULT/logging_exception_prefix').with_value( + '%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s') + + is_expected.to contain_gnocchi_config('DEFAULT/log_config_append').with_value( + '/etc/gnocchi/logging.conf') + is_expected.to contain_gnocchi_config('DEFAULT/publish_errors').with_value( + true) + + is_expected.to contain_gnocchi_config('DEFAULT/default_log_levels').with_value( + 'amqp=WARN,amqplib=WARN,boto=WARN,iso8601=WARN,qpid=WARN,requests.packages.urllib3.connectionpool=WARN,sqlalchemy=WARN,suds=INFO') + + is_expected.to contain_gnocchi_config('DEFAULT/fatal_deprecations').with_value( + true) + + is_expected.to contain_gnocchi_config('DEFAULT/instance_format').with_value( + '[instance: %(uuid)s] ') + + is_expected.to contain_gnocchi_config('DEFAULT/instance_uuid_format').with_value( + '[instance: %(uuid)s] ') + + is_expected.to contain_gnocchi_config('DEFAULT/log_date_format').with_value( + '%Y-%m-%d %H:%M:%S') + end + end + + + shared_examples_for 'logging params unset' do + [ :logging_context_format_string, :logging_default_format_string, + :logging_debug_format_suffix, :logging_exception_prefix, + :log_config_append, :publish_errors, + :default_log_levels, :fatal_deprecations, + :instance_format, :instance_uuid_format, + :log_date_format, ].each { |param| + it { is_expected.to contain_gnocchi_config("DEFAULT/#{param}").with_ensure('absent') } + } + end + + context 'on Debian platforms' do + let :facts do + { :osfamily => 'Debian' } + end + + it_configures 'gnocchi-logging' + end + + context 'on RedHat platforms' do + let :facts do + { :osfamily => 'RedHat' } + end + + it_configures 'gnocchi-logging' + end + +end diff --git a/gnocchi/spec/shared_examples.rb b/gnocchi/spec/shared_examples.rb index 4bc52a928..a888e4622 100644 --- a/gnocchi/spec/shared_examples.rb +++ b/gnocchi/spec/shared_examples.rb @@ -11,13 +11,15 @@ is_expected.to contain_package(service[:name]).with({ :name => service[:package_name], :ensure => 'present', - :notify => "Service[#{service[:name]}]" + :notify => "Service[#{service[:name]}]", + :tag => ['openstack', 'gnocchi-package'], }) is_expected.to contain_service(service[:name]).with({ :name => service[:service_name], :ensure => 'stopped', :hasstatus => true, - :enable => false + :enable => false, + :tag => 'gnocchi-service', }) end end @@ -32,13 +34,15 @@ is_expected.to contain_package(service[:name]).with({ :name => service[:package_name], :ensure => '2014.1-1', - :notify => "Service[#{service[:name]}]" + :notify => "Service[#{service[:name]}]", + :tag => ['openstack', 'gnocchi-package'], }) is_expected.to contain_service(service[:name]).with({ :name => service[:service_name], :ensure => 'running', :hasstatus => true, - :enable => true + :enable => true, + :tag => 'gnocchi-service', }) end end diff --git a/gnocchi/spec/spec_helper.rb b/gnocchi/spec/spec_helper.rb index 53d4dd02d..3df4cede1 100644 --- a/gnocchi/spec/spec_helper.rb +++ b/gnocchi/spec/spec_helper.rb @@ -1,7 +1,10 @@ require 'puppetlabs_spec_helper/module_spec_helper' require 'shared_examples' +require 'webmock/rspec' RSpec.configure do |c| 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/gnocchi/spec/unit/provider/gnocchi_config/ini_setting_spec.rb b/gnocchi/spec/unit/provider/gnocchi_config/ini_setting_spec.rb index 059a5a2f5..a3fbe1cbb 100644 --- a/gnocchi/spec/unit/provider/gnocchi_config/ini_setting_spec.rb +++ b/gnocchi/spec/unit/provider/gnocchi_config/ini_setting_spec.rb @@ -13,6 +13,17 @@ 'inifile', 'lib') ) +$LOAD_PATH.push( + File.join( + File.dirname(__FILE__), + '..', + '..', + '..', + 'fixtures', + 'modules', + 'openstacklib', + 'lib') +) require 'spec_helper' provider_class = Puppet::Type.type(:gnocchi_config).provider(:ini_setting) describe provider_class do @@ -34,4 +45,22 @@ expect(provider.section).to eq('dude') expect(provider.setting).to eq('foo') end + + it 'should ensure absent when is specified as a value' do + resource = Puppet::Type::Gnocchi_config.new( + {:name => 'dude/foo', :value => ''} + ) + provider = provider_class.new(resource) + provider.exists? + expect(resource[:ensure]).to eq :absent + end + + it 'should ensure absent when value matches ensure_absent_val' do + resource = Puppet::Type::Gnocchi_config.new( + {:name => 'dude/foo', :value => 'foo', :ensure_absent_val => 'foo' } + ) + provider = provider_class.new(resource) + provider.exists? + expect(resource[:ensure]).to eq :absent + end end diff --git a/gnocchi/spec/unit/type/gnocchi_config_spec.rb b/gnocchi/spec/unit/type/gnocchi_config_spec.rb index d711b0345..64580fe4c 100644 --- a/gnocchi/spec/unit/type/gnocchi_config_spec.rb +++ b/gnocchi/spec/unit/type/gnocchi_config_spec.rb @@ -49,4 +49,15 @@ @gnocchi_config[:ensure] = :latest }.to raise_error(Puppet::Error, /Invalid value/) end + + it 'should autorequire the package that install the file' do + catalog = Puppet::Resource::Catalog.new + package = Puppet::Type.type(:package).new(:name => 'gnocchi-api') + catalog.add_resource package, @gnocchi_config + dependency = @gnocchi_config.autorequire + expect(dependency.size).to eq(1) + expect(dependency[0].target).to eq(@gnocchi_config) + expect(dependency[0].source).to eq(package) + end + end diff --git a/keystone/manifests/cron/token_flush.pp b/keystone/manifests/cron/token_flush.pp index 331eeba56..6dba32b47 100644 --- a/keystone/manifests/cron/token_flush.pp +++ b/keystone/manifests/cron/token_flush.pp @@ -45,14 +45,19 @@ # Induces a random delay before running the cronjob to avoid running all # cron jobs at the same time on all hosts this job is configured. # +# [*destination*] +# (optional) Path to file to which rows should be archived +# Defaults to '/var/log/keystone/keystone-tokenflush.log'. +# class keystone::cron::token_flush ( - $ensure = present, - $minute = 1, - $hour = 0, - $monthday = '*', - $month = '*', - $weekday = '*', - $maxdelay = 0, + $ensure = present, + $minute = 1, + $hour = 0, + $monthday = '*', + $month = '*', + $weekday = '*', + $maxdelay = 0, + $destination = '/var/log/keystone/keystone-tokenflush.log' ) { if $maxdelay == 0 { @@ -63,7 +68,7 @@ cron { 'keystone-manage token_flush': ensure => $ensure, - command => "${sleep}keystone-manage token_flush >>/var/log/keystone/keystone-tokenflush.log 2>&1", + command => "${sleep}keystone-manage token_flush >>${destination} 2>&1", environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh', user => 'keystone', minute => $minute, diff --git a/keystone/spec/classes/keystone_cron_token_flush_spec.rb b/keystone/spec/classes/keystone_cron_token_flush_spec.rb index 88e1fd519..24ebcd8aa 100644 --- a/keystone/spec/classes/keystone_cron_token_flush_spec.rb +++ b/keystone/spec/classes/keystone_cron_token_flush_spec.rb @@ -6,62 +6,73 @@ { :osfamily => 'Debian' } end + let :params do + { :ensure => 'present', + :minute => 1, + :hour => 0, + :monthday => '*', + :month => '*', + :weekday => '*', + :maxdelay => 0, + :destination => '/var/log/keystone/keystone-tokenflush.log' } + end + describe 'with default parameters' do it 'configures a cron' do is_expected.to contain_cron('keystone-manage token_flush').with( - :ensure => 'present', - :command => 'keystone-manage token_flush >>/var/log/keystone/keystone-tokenflush.log 2>&1', + :ensure => params[:ensure], + :command => "keystone-manage token_flush >>#{params[:destination]} 2>&1", :environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh', :user => 'keystone', - :minute => 1, - :hour => 0, - :monthday => '*', - :month => '*', - :weekday => '*' + :minute => params[:minute], + :hour => params[:hour], + :monthday => params[:monthday], + :month => params[:month], + :weekday => params[:weekday] ) end end describe 'when specifying a maxdelay param' do - let :params do - { + before :each do + params.merge!( :maxdelay => 600 - } + ) end it 'configures a cron with delay' do is_expected.to contain_cron('keystone-manage token_flush').with( - :ensure => 'present', - :command => 'sleep `expr ${RANDOM} \\% 600`; keystone-manage token_flush >>/var/log/keystone/keystone-tokenflush.log 2>&1', + :ensure => params[:ensure], + :command => "sleep `expr ${RANDOM} \\% #{params[:maxdelay]}`; keystone-manage token_flush >>#{params[:destination]} 2>&1", :environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh', :user => 'keystone', - :minute => 1, - :hour => 0, - :monthday => '*', - :month => '*', - :weekday => '*' + :minute => params[:minute], + :hour => params[:hour], + :monthday => params[:monthday], + :month => params[:month], + :weekday => params[:weekday] ) end end - describe 'when specifying a maxdelay param' do - let :params do - { + describe 'when disabling cron job' do + before :each do + params.merge!( :ensure => 'absent' - } + ) end it 'configures a cron with delay' do is_expected.to contain_cron('keystone-manage token_flush').with( - :ensure => 'absent', - :command => 'keystone-manage token_flush >>/var/log/keystone/keystone-tokenflush.log 2>&1', + :ensure => params[:ensure], + :command => "keystone-manage token_flush >>#{params[:destination]} 2>&1", :environment => 'PATH=/bin:/usr/bin:/usr/sbin SHELL=/bin/sh', :user => 'keystone', - :minute => 1, - :hour => 0, - :monthday => '*', - :month => '*', - :weekday => '*' + :minute => params[:minute], + :hour => params[:hour], + :monthday => params[:monthday], + :month => params[:month], + :weekday => params[:weekday] ) end end diff --git a/n1k_vsm/.fixtures.yml b/n1k_vsm/.fixtures.yml new file mode 100644 index 000000000..d54b7e67d --- /dev/null +++ b/n1k_vsm/.fixtures.yml @@ -0,0 +1,5 @@ +fixtures: + repositories: + 'stdlib': 'git://github.com/puppetlabs/puppetlabs-stdlib.git' + symlinks: + "n1k_vsm": "#{source_dir}" diff --git a/n1k_vsm/Gemfile b/n1k_vsm/Gemfile index 8de97162d..6d4ce9a07 100644 --- a/n1k_vsm/Gemfile +++ b/n1k_vsm/Gemfile @@ -1,8 +1,30 @@ -source 'https://rubygems.org' +source ENV['GEM_SOURCE'] || "https://rubygems.org" group :development, :test do - gem 'puppetlabs_spec_helper', :require => false - gem 'puppet-lint', '~> 0.3.2' + gem 'puppetlabs_spec_helper', :require => 'false' + gem 'rspec-puppet', '~> 2.2.0', :require => 'false' + gem 'metadata-json-lint', :require => 'false' + gem 'puppet-lint-param-docs', :require => 'false' + gem 'puppet-lint-absolute_classname-check', :require => 'false' + gem 'puppet-lint-absolute_template_path', :require => 'false' + gem 'puppet-lint-trailing_newline-check', :require => 'false' + gem 'puppet-lint-unquoted_string-check', :require => 'false' + gem 'puppet-lint-leading_zero-check', :require => 'false' + gem 'puppet-lint-variable_contains_upcase', :require => 'false' + gem 'puppet-lint-numericvariable', :require => 'false' + gem 'json', :require => 'false' + gem 'webmock', :require => 'false' +end + +group :system_tests do + gem 'beaker-rspec', :require => 'false' + gem 'beaker-puppet_install_helper', :require => 'false' +end + +if facterversion = ENV['FACTER_GEM_VERSION'] + gem 'facter', facterversion, :require => false +else + gem 'facter', :require => false end if puppetversion = ENV['PUPPET_GEM_VERSION'] @@ -10,3 +32,5 @@ if puppetversion = ENV['PUPPET_GEM_VERSION'] else gem 'puppet', :require => false end + +# vim:ft=ruby diff --git a/n1k_vsm/manifests/deploy.pp b/n1k_vsm/manifests/deploy.pp index b39afe6cb..4427b264c 100644 --- a/n1k_vsm/manifests/deploy.pp +++ b/n1k_vsm/manifests/deploy.pp @@ -5,14 +5,31 @@ # class n1k_vsm::deploy { + require ::n1k_vsm + include ::n1k_vsm + #ensure tap interfaces and deploy the vsm $ctrltap = 'vsm-ctrl0' $mgmttap = 'vsm-mgmt0' $pkttap = 'vsm-pkt0' + # Validate and get the array of digits for the vsm_mac_base (or use default) + # Using _vmb as the name for the final string to increase readability + $tmp_mac_base = regsubst($n1k_vsm::vsm_mac_base, '[^0-9a-fA-F]+', '') + if size($tmp_mac_base) < 7 { + $vmb = split('005dc79', '') + } else { + $vmb = split($tmp_mac_base, '') + } + + # Generate MACs for VSM + $ctrlmac = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}1" + $mgmtmac = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}2" + $pktmac = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}3" + exec { 'Exec_create_disk': command => "/usr/bin/qemu-img create -f raw ${n1k_vsm::diskfile} ${n1k_vsm::disksize}G", - unless => "/usr/bin/virsh list --all | grep -c ${n1k_vsm::vsmname}", + creates => $n1k_vsm::diskfile, } $targetxmlfile = "/var/spool/cisco/vsm/vsm_${n1k_vsm::vsm_role}_deploy.xml" @@ -21,19 +38,49 @@ owner => 'root', group => 'root', mode => '0666', + seltype => 'virt_content_t', content => template('n1k_vsm/vsm_vm.xml.erb'), require => Exec['Exec_create_disk'], } - exec { 'Exec_Define_VSM': - command => "/usr/bin/virsh define ${targetxmlfile}", - unless => "/usr/bin/virsh list --all | grep -c ${n1k_vsm::vsmname}", - } + # Don't start VSM if this is pacemaker controlled deployment + if !($n1k_vsm::pacemaker_control) { + exec { 'Exec_Define_VSM': + command => "/usr/bin/virsh define ${targetxmlfile}", + unless => "/usr/bin/virsh list --all | grep -c ${n1k_vsm::vsmname}", + require => File['File_Target_XML_File'], + } - exec { 'Exec_Launch_VSM': - command => "/usr/bin/virsh start ${n1k_vsm::vsmname}", - unless => "/usr/bin/virsh list --all | grep ${n1k_vsm::vsmname} | grep -c running", - } + exec { 'Exec_Launch_VSM': + command => "/usr/bin/virsh start ${n1k_vsm::vsmname}", + unless => ("/usr/bin/virsh list --all | grep ${n1k_vsm::vsmname} | grep -c running"), + require => Exec['Exec_Define_VSM'], + } + } else { + # For pacemker controlled deployment, set up the secondary VSM as well + # ensure tap interfaces and deploy the vsm + $ctrltap_s = 'vsm-ctrl1' + $mgmttap_s = 'vsm-mgmt1' + $pkttap_s = 'vsm-pkt1' + # Generate MACs + $ctrlmac_s = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}4" + $mgmtmac_s = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}5" + $pktmac_s = "52:54:${vmb[0]}${vmb[1]}:${vmb[2]}${vmb[3]}:${vmb[4]}${vmb[5]}:${vmb[6]}6" - Exec['Exec_create_disk'] -> File['File_Target_XML_File'] -> Exec['Exec_Define_VSM'] -> Exec['Exec_Launch_VSM'] + exec { 'Exec_create_disk_Secondary': + command => "/usr/bin/qemu-img create -f raw ${n1k_vsm::diskfile_s} ${n1k_vsm::disksize}G", + creates => $n1k_vsm::diskfile_s, + } + + $targetxmlfile_s = "/var/spool/cisco/vsm/vsm_${n1k_vsm::vsm_role_s}_deploy.xml" + file { 'File_Target_XML_File_Secondary': + path => $targetxmlfile_s, + owner => 'root', + group => 'root', + mode => '0666', + seltype => 'virt_content_t', + content => template('n1k_vsm/vsm_vm_secondary.xml.erb'), + require => Exec['Exec_create_disk_Secondary'], + } + } } diff --git a/n1k_vsm/manifests/init.pp b/n1k_vsm/manifests/init.pp index 13307a44e..c6fb9b74c 100644 --- a/n1k_vsm/manifests/init.pp +++ b/n1k_vsm/manifests/init.pp @@ -36,6 +36,19 @@ # [*n1kv_version*] # (required) Version of the Nexus1000v VSM # +# [*pacemaker_control*] +# (optional) Set to determine if pacemaker will control the VSM. If true will deploy both +# primary and secondary VSMs on all nodes and will not start VSM. Defaults to false and +# thus is optional unless this functionality is being used. +# +# [*existing_bridge*] +# (required) If VSM should be installed behind an existing bridge, this should be set to +# true and the bridge name should be provided in phy_if_bridge. +# +# [*vsm_mac_base*] +# (optional) If set, provides randomization for the MAC addresses for the VSM VM(s). +# Should be a (random) hexadecimal number of at least 7 digits (more is fine). +# class n1k_vsm( $n1kv_source = '', $n1kv_version = 'latest', @@ -47,6 +60,9 @@ $vsm_mgmt_ip, $vsm_mgmt_netmask, $vsm_mgmt_gateway, + $pacemaker_control = false, + $existing_bridge = false, + $vsm_mac_base = '' ) { if($::osfamily != 'Redhat') { @@ -55,6 +71,15 @@ fail("Unsupported osfamily ${::osfamily}") } + # Ensure role is set to primary for pacemaker controlled deployment + # Additionally setup the extra variables for the secondary VSM + if ($n1k_vsm::pacemaker_control) { + $vsm_role_s = 'secondary' + $vsmname_s = 'vsm-s' + $imgfile_s = "/var/spool/cisco/vsm/${vsm_role_s}_repacked.iso" + $diskfile_s = "/var/spool/cisco/vsm/${vsm_role_s}_disk" + } + if ($n1k_vsm::vsm_role == 'primary') or ($n1k_vsm::vsm_role == 'standalone') { $vsmname = 'vsm-p' $mgmtip = $vsm_mgmt_ip @@ -73,7 +98,9 @@ $disksize = 4 $imgfile = "/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_repacked.iso" $diskfile = "/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_disk" - $ovsbridge = 'vsm-br' + + #Set bridge name properly + $ovsbridge = 'vsm-br' #VSM installation will be done only once. Will not respond to puppet sync $_phy_if_bridge = regsubst($n1k_vsm::phy_if_bridge, '[.:-]+', '_', 'G') @@ -82,7 +109,7 @@ $phy_ip_addr = inline_template("<%= scope.lookupvar('::ipaddress_${_phy_if_bridge}') %>") $phy_ip_mask = inline_template("<%= scope.lookupvar('::netmask_${_phy_if_bridge}') %>") $gw_intf = $n1k_vsm::phy_gateway - include n1k_vsm::pkgprep_ovscfg + include ::n1k_vsm::pkgprep_ovscfg } notify {"Arg: intf ${phy_if_bridge} vsm_role ${vsm_role} domainid ${vsm_domain_id}" : withpath => true} @@ -90,7 +117,7 @@ notify {"gw_dv ${gw_intf} ovs ${ovsbridge} vsmname ${n1k_vsm::vsmname}" : withpath => true} notify {"mgmtip ${n1k_vsm::mgmtip} vsm_mask ${n1k_vsm::mgmtnetmask} vsm_gw ${n1k_vsm::mgmtgateway}": withpath => false} - include n1k_vsm::vsmprep - include n1k_vsm::deploy + include ::n1k_vsm::vsmprep + include ::n1k_vsm::deploy Class['n1k_vsm::vsmprep'] -> Class['n1k_vsm::deploy'] } diff --git a/n1k_vsm/manifests/pkgprep_ovscfg.pp b/n1k_vsm/manifests/pkgprep_ovscfg.pp index 073fd985f..ec0a44474 100644 --- a/n1k_vsm/manifests/pkgprep_ovscfg.pp +++ b/n1k_vsm/manifests/pkgprep_ovscfg.pp @@ -4,8 +4,8 @@ # class n1k_vsm::pkgprep_ovscfg { - require n1k_vsm - include n1k_vsm + require ::n1k_vsm + include ::n1k_vsm case $::osfamily { 'RedHat': { @@ -19,7 +19,7 @@ # VSM dependent packages installation section package { 'Package_qemu-kvm': ensure => installed, - name => 'qemu-kvm', + name => 'qemu-kvm-rhev', } package {'Package_libvirt': @@ -64,8 +64,11 @@ notify { "Debug br ${n1k_vsm::ovsbridge} intf ${n1k_vsm::phy_if_bridge} ." : withpath => true } notify { "Debug ${n1k_vsm::vsmname} ip ${n1k_vsm::phy_ip_addr} mask ${n1k_vsm::phy_ip_mask} gw_intf ${n1k_vsm::gw_intf}" : withpath => true } - # Check if we've already configured the ovs - if $n1k_vsm::gw_intf != $n1k_vsm::ovsbridge { + $_ovsbridge = regsubst($n1k_vsm::ovsbridge, '[.:-]+', '_', 'G') + $_ovsbridge_mac = inline_template("<%= scope.lookupvar('::macaddress_${_ovsbridge}') %>") + + # Check if we've already configured the vsm bridge, skip configuration if so + if ($_ovsbridge_mac == '') { # Modify Ovs bridge inteface configuation file augeas { 'Augeas_modify_ifcfg-ovsbridge': name => $n1k_vsm::ovsbridge, @@ -87,47 +90,50 @@ 'set USERCTL no', ], } - - # Modify Physical Interface config file - augeas { 'Augeas_modify_ifcfg-phy_if_bridge': - name => $n1k_vsm::phy_if_bridge, - context => "/files/etc/sysconfig/network-scripts/ifcfg-${n1k_vsm::phy_if_bridge}", - changes => [ - 'set TYPE OVSPort', - "set DEVICE ${n1k_vsm::phy_if_bridge}", - 'set DEVICETYPE ovs', - "set OVS_BRIDGE ${n1k_vsm::ovsbridge}", - 'set NM_CONTROLLED no', - 'set BOOTPROTO none', - 'set ONBOOT yes', - "set NAME ${n1k_vsm::phy_if_bridge}", - 'set DEFROUTE no', - 'set IPADDR ""', - 'rm NETMASK', - 'rm GATEWAY', - 'set USERCTL no', - ], - } - exec { 'Flap_n1kv_phy_if': - command => "/sbin/ifdown ${n1k_vsm::phy_if_bridge} && /sbin/ifup ${n1k_vsm::phy_if_bridge}", - require => augeas['Augeas_modify_ifcfg-phy_if_bridge'], - } exec { 'Flap_n1kv_bridge': command => "/sbin/ifdown ${n1k_vsm::ovsbridge} && /sbin/ifup ${n1k_vsm::ovsbridge}", - require => augeas['Augeas_modify_ifcfg-ovsbridge'], + require => Augeas['Augeas_modify_ifcfg-ovsbridge'], } - # Make sure that networking comes fine after reboot- add init file and restart networking - file { 'Create_Init_File': - replace => 'yes', - path => '/etc/init.d/n1kv', - owner => 'root', - group => 'root', - mode => '0775', - source => 'puppet:///modules/n1k_vsm/n1kv', - require => exec['Flap_n1kv_phy_if', 'Flap_n1kv_bridge'], - notify => Service['Service_network'], + + if !($n1k_vsm::existing_bridge) { + # If there isn't an existing bridge, the interface is a port, and we + # need to add it to vsm-br + # Modify Physical Interface config file + augeas { 'Augeas_modify_ifcfg-phy_if_bridge': + name => $n1k_vsm::phy_if_bridge, + context => "/files/etc/sysconfig/network-scripts/ifcfg-${n1k_vsm::phy_if_bridge}", + changes => [ + 'set TYPE OVSPort', + "set DEVICE ${n1k_vsm::phy_if_bridge}", + 'set DEVICETYPE ovs', + "set OVS_BRIDGE ${n1k_vsm::ovsbridge}", + 'set NM_CONTROLLED no', + 'set BOOTPROTO none', + 'set ONBOOT yes', + "set NAME ${n1k_vsm::phy_if_bridge}", + 'set DEFROUTE no', + 'set IPADDR ""', + 'rm NETMASK', + 'rm GATEWAY', + 'set USERCTL no', + ], + } + exec { 'Flap_n1kv_phy_if': + command => "/sbin/ifdown ${n1k_vsm::phy_if_bridge} && /sbin/ifup ${n1k_vsm::phy_if_bridge}", + require => Augeas['Augeas_modify_ifcfg-phy_if_bridge'], + } + } else { + # If there is an existing bridge- create patch ports to connect vsm-br to it + exec { 'Create_patch_port_on_existing_bridge': + command => "/bin/ovs-vsctl --may-exist add-port ${n1k_vsm::phy_if_bridge} ${n1k_vsm::phy_if_bridge}-${n1k_vsm::ovsbridge} -- set Interface ${n1k_vsm::phy_if_bridge}-${n1k_vsm::ovsbridge} type=patch options:peer=${n1k_vsm::ovsbridge}-${n1k_vsm::phy_if_bridge}", + require => Exec['Flap_n1kv_bridge'], + } + exec { 'Create_patch_port_on_vsm_bridge': + command => "/bin/ovs-vsctl --may-exist add-port ${n1k_vsm::ovsbridge} ${n1k_vsm::ovsbridge}-${n1k_vsm::phy_if_bridge} -- set Interface ${n1k_vsm::ovsbridge}-${n1k_vsm::phy_if_bridge} type=patch options:peer=${n1k_vsm::phy_if_bridge}-${n1k_vsm::ovsbridge}", + require => Exec['Flap_n1kv_bridge'], + } } - } # endif of if "${n1k_vsm::gw_intf}" != "${n1k_vsm::ovsbridge}" + } # endif of if "${n1k_vsm::gw_intf}" != "${n1k_vsm::ovsbridge}" or ($n1k_vsm::existing_bridge == 'true') } 'Ubuntu': { } diff --git a/n1k_vsm/manifests/vsmprep.pp b/n1k_vsm/manifests/vsmprep.pp index f7046662a..c5e79fcfc 100644 --- a/n1k_vsm/manifests/vsmprep.pp +++ b/n1k_vsm/manifests/vsmprep.pp @@ -5,9 +5,9 @@ # class n1k_vsm::vsmprep { - include 'stdlib' - require n1k_vsm - include n1k_vsm + include ::stdlib + require ::n1k_vsm + include ::n1k_vsm # prepare vsm folders ensure_resource('file', '/var/spool/cisco/', { @@ -35,12 +35,9 @@ } } else { $vsmimage_uri = 'unspec' + $vsm_path = '/opt/cisco/vsm' } -# exec { 'Prev_VSM': -# command => "/bin/rm -f /var/spool/cisco/vsm/* || /bin/true", -# } - if $vsmimage_uri == 'file' { #specify location on target-host where image file will be downloaded to. file { $vsmtgtimg: @@ -63,8 +60,9 @@ } } package {'nexus-1000v-iso': - ensure => $n1k_vsm::n1kv_version, - name => 'nexus-1000v-iso' + ensure => 'present', + name => 'nexus-1000v-iso', + provider => 'yum', } } @@ -80,8 +78,15 @@ # Now generate ovf xml file and repackage the iso exec { 'Exec_VSM_Repackage_Script': - command => "/tmp/repackiso.py -i${vsm_path}/n1000v-dk9.${n1k_vsm::n1kv_version}.iso -d${n1k_vsm::vsm_domain_id} -n${n1k_vsm::vsmname} -m${n1k_vsm::mgmtip} -s${n1k_vsm::mgmtnetmask} -g${n1k_vsm::mgmtgateway} -p${n1k_vsm::vsm_admin_passwd} -r${n1k_vsm::vsm_role} -f/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_repacked.iso ", - unless => "/usr/bin/virsh list --all | grep -c ${n1k_vsm::vsmname}", + command => "/tmp/repackiso.py -i${vsm_path}/n1000v-dk9.${n1k_vsm::n1kv_version}.iso -d${n1k_vsm::vsm_domain_id} -n${n1k_vsm::vsmname} -m${n1k_vsm::mgmtip} -s${n1k_vsm::mgmtnetmask} -g${n1k_vsm::mgmtgateway} -p${n1k_vsm::vsm_admin_passwd} -r${n1k_vsm::vsm_role} -f/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_repacked.iso", + creates => "/var/spool/cisco/vsm/${n1k_vsm::vsm_role}_repacked.iso", } + # If we're under pacemaker_control, create a secondary VSM iso as well + if ($n1k_vsm::pacemaker_control) { + exec { 'Exec_VSM_Repackage_Script_secondary': + command => "/tmp/repackiso.py -i${vsm_path}/n1000v-dk9.${n1k_vsm::n1kv_version}.iso -d${n1k_vsm::vsm_domain_id} -n${n1k_vsm::vsmname_s} -m${n1k_vsm::mgmtip} -s${n1k_vsm::mgmtnetmask} -g${n1k_vsm::mgmtgateway} -p${n1k_vsm::vsm_admin_passwd} -r${n1k_vsm::vsm_role_s} -f/var/spool/cisco/vsm/${n1k_vsm::vsm_role_s}_repacked.iso", + creates => "/var/spool/cisco/vsm/${n1k_vsm::vsm_role_s}_repacked.iso", + } + } } diff --git a/n1k_vsm/spec/acceptance/nodesets/centos-70-x64.yml b/n1k_vsm/spec/acceptance/nodesets/centos-70-x64.yml new file mode 100644 index 000000000..5f097e9fe --- /dev/null +++ b/n1k_vsm/spec/acceptance/nodesets/centos-70-x64.yml @@ -0,0 +1,11 @@ +HOSTS: + centos-server-70-x64: + roles: + - master + platform: el-7-x86_64 + box: puppetlabs/centos-7.0-64-nocm + box_url: https://vagrantcloud.com/puppetlabs/centos-7.0-64-nocm + hypervisor: vagrant +CONFIG: + log_level: debug + type: foss diff --git a/n1k_vsm/spec/acceptance/nodesets/default.yml b/n1k_vsm/spec/acceptance/nodesets/default.yml new file mode 100644 index 000000000..3bb3e6264 --- /dev/null +++ b/n1k_vsm/spec/acceptance/nodesets/default.yml @@ -0,0 +1,11 @@ +HOSTS: + ubuntu-server-1404-x64: + roles: + - master + platform: ubuntu-14.04-amd64 + box: puppetlabs/ubuntu-14.04-64-nocm + box_url: https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm + hypervisor: vagrant +CONFIG: + log_level: debug + type: git diff --git a/n1k_vsm/spec/acceptance/nodesets/nodepool-centos7.yml b/n1k_vsm/spec/acceptance/nodesets/nodepool-centos7.yml new file mode 100644 index 000000000..c55287420 --- /dev/null +++ b/n1k_vsm/spec/acceptance/nodesets/nodepool-centos7.yml @@ -0,0 +1,10 @@ +HOSTS: + centos-70-x64: + roles: + - master + platform: el-7-x86_64 + hypervisor: none + ip: 127.0.0.1 +CONFIG: + type: foss + set_env: false diff --git a/n1k_vsm/spec/acceptance/nodesets/nodepool-trusty.yml b/n1k_vsm/spec/acceptance/nodesets/nodepool-trusty.yml new file mode 100644 index 000000000..7f503cadd --- /dev/null +++ b/n1k_vsm/spec/acceptance/nodesets/nodepool-trusty.yml @@ -0,0 +1,10 @@ +HOSTS: + ubuntu-1404-x64: + roles: + - master + platform: ubuntu-14.04-amd64 + hypervisor: none + ip: 127.0.0.1 +CONFIG: + type: foss + set_env: false diff --git a/n1k_vsm/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/n1k_vsm/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml new file mode 100644 index 000000000..3bb3e6264 --- /dev/null +++ b/n1k_vsm/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml @@ -0,0 +1,11 @@ +HOSTS: + ubuntu-server-1404-x64: + roles: + - master + platform: ubuntu-14.04-amd64 + box: puppetlabs/ubuntu-14.04-64-nocm + box_url: https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm + hypervisor: vagrant +CONFIG: + log_level: debug + type: git diff --git a/n1k_vsm/spec/classes/n1kv_vsm_spec.rb b/n1k_vsm/spec/classes/n1kv_vsm_spec.rb new file mode 100644 index 000000000..564802b6d --- /dev/null +++ b/n1k_vsm/spec/classes/n1kv_vsm_spec.rb @@ -0,0 +1,21 @@ +# +# Copyright (C) 2015 eNovance SAS +# +# 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. +# + +require 'spec_helper' + +describe 'n1k_vsm' do + +end diff --git a/n1k_vsm/spec/classes/n1kv_vsm_vsmprep_spec.rb b/n1k_vsm/spec/classes/n1kv_vsm_vsmprep_spec.rb new file mode 100644 index 000000000..09f79c244 --- /dev/null +++ b/n1k_vsm/spec/classes/n1kv_vsm_vsmprep_spec.rb @@ -0,0 +1,78 @@ +# +# Copyright (C) 2015 eNovance SAS +# +# 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. +# + +require 'spec_helper' + +describe 'n1k_vsm::vsmprep' do + + let :params do + { } + end + + shared_examples_for 'n1k vsm prep' do + + context 'with default values' do + let :pre_condition do + "class { 'n1k_vsm': + phy_gateway => '1.1.1.3', + vsm_domain_id => '1', + vsm_admin_passwd => 'secrete', + vsm_mgmt_ip => '1.1.1.1', + vsm_mgmt_netmask => '255.255.255.0', + vsm_mgmt_gateway => '1.1.1.2', + }" + end + + # Currently we always just check if VSM is present + it 'installs latest n1kv sofware' do + is_expected.to contain_package('nexus-1000v-iso').with( + :ensure => 'present', + ) + end + end + + context 'with custom values' do + let :pre_condition do + "class { 'n1k_vsm': + phy_gateway => '1.1.1.3', + vsm_domain_id => '1', + vsm_admin_passwd => 'secrete', + vsm_mgmt_ip => '1.1.1.1', + vsm_mgmt_netmask => '255.255.255.0', + vsm_mgmt_gateway => '1.1.1.2', + n1kv_version => '5.2.1.SK3.2.2a-1', + }" + end + + # Currently we always just check if VSM is present + it 'installs latest n1kv sofware' do + is_expected.to contain_package('nexus-1000v-iso').with( + :ensure => 'present', + ) + end + end + + end + + context 'on RedHat platforms' do + let :facts do + { :osfamily => 'RedHat' } + end + + it_configures 'n1k vsm prep' + end + +end diff --git a/n1k_vsm/spec/shared_examples.rb b/n1k_vsm/spec/shared_examples.rb new file mode 100644 index 000000000..fec0eacc9 --- /dev/null +++ b/n1k_vsm/spec/shared_examples.rb @@ -0,0 +1,5 @@ +shared_examples_for "a Puppet::Error" do |description| + it "with message matching #{description.inspect}" do + expect { is_expected.to have_class_count(1) }.to raise_error(Puppet::Error, description) + end +end diff --git a/n1k_vsm/spec/spec_helper.rb b/n1k_vsm/spec/spec_helper.rb new file mode 100644 index 000000000..700be6a27 --- /dev/null +++ b/n1k_vsm/spec/spec_helper.rb @@ -0,0 +1,19 @@ +require 'puppetlabs_spec_helper/module_spec_helper' +require 'shared_examples' +require 'webmock/rspec' + +RSpec.configure do |c| + c.alias_it_should_behave_like_to :it_configures, 'configures' + c.alias_it_should_behave_like_to :it_raises, 'raises' + + c.default_facts = { + :kernel => 'Linux', + :concat_basedir => '/var/lib/puppet/concat', + :memorysize => '1000 MB', + :processorcount => '1', + :puppetversion => '3.7.3', + :uniqueid => '123' + } +end + +at_exit { RSpec::Puppet::Coverage.report! } diff --git a/n1k_vsm/spec/spec_helper_acceptance.rb b/n1k_vsm/spec/spec_helper_acceptance.rb new file mode 100644 index 000000000..429e807c4 --- /dev/null +++ b/n1k_vsm/spec/spec_helper_acceptance.rb @@ -0,0 +1,56 @@ +require 'beaker-rspec' +require 'beaker/puppet_install_helper' + +run_puppet_install_helper + +RSpec.configure do |c| + # Project root + proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) + modname = JSON.parse(open('metadata.json').read)['name'].split('-')[1] + + # Readable test descriptions + c.formatter = :documentation + + # Configure all nodes in nodeset + c.before :suite do + # Install module and dependencies + hosts.each do |host| + + # install git + install_package host, 'git' + + zuul_ref = ENV['ZUUL_REF'] + zuul_branch = ENV['ZUUL_BRANCH'] + zuul_url = ENV['ZUUL_URL'] + + repo = 'openstack/puppet-openstack-integration' + + # Start out with clean moduledir, don't trust r10k to purge it + on host, "rm -rf /etc/puppet/modules/*" + # Install dependent modules via git or zuul + r = on host, "test -e /usr/zuul-env/bin/zuul-cloner", { :acceptable_exit_codes => [0,1] } + if r.exit_code == 0 + zuul_clone_cmd = '/usr/zuul-env/bin/zuul-cloner ' + zuul_clone_cmd += '--cache-dir /opt/git ' + zuul_clone_cmd += "--zuul-ref #{zuul_ref} " + zuul_clone_cmd += "--zuul-branch #{zuul_branch} " + zuul_clone_cmd += "--zuul-url #{zuul_url} " + zuul_clone_cmd += "git://git.openstack.org #{repo}" + on host, zuul_clone_cmd + else + on host, "git clone https://git.openstack.org/#{repo} #{repo}" + end + + on host, "ZUUL_REF=#{zuul_ref} ZUUL_BRANCH=#{zuul_branch} ZUUL_URL=#{zuul_url} bash #{repo}/install_modules.sh" + + # Install the module being tested + on host, "rm -fr /etc/puppet/modules/#{modname}" + puppet_module_install(:source => proj_root, :module_name => modname) + + on host, "rm -fr #{repo}" + + # List modules installed to help with debugging + on host, puppet('module','list'), { :acceptable_exit_codes => 0 } + end + end +end diff --git a/n1k_vsm/templates/vsm_vm.xml.erb b/n1k_vsm/templates/vsm_vm.xml.erb index 82a2a013e..7096724b6 100644 --- a/n1k_vsm/templates/vsm_vm.xml.erb +++ b/n1k_vsm/templates/vsm_vm.xml.erb @@ -41,6 +41,9 @@ + <% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %> + + <% end %>
@@ -49,6 +52,9 @@ + <% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %> + + <% end %>
@@ -57,6 +63,9 @@ + <% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %> + + <% end %>
diff --git a/n1k_vsm/templates/vsm_vm_secondary.xml.erb b/n1k_vsm/templates/vsm_vm_secondary.xml.erb new file mode 100644 index 000000000..cbd237bfa --- /dev/null +++ b/n1k_vsm/templates/vsm_vm_secondary.xml.erb @@ -0,0 +1,92 @@ + + <%= scope.lookupvar('n1k_vsm::vsmname_s') %> + <%= scope.lookupvar('n1k_vsm::memory') %> + <%= scope.lookupvar('n1k_vsm::vcpu') %> + + + hvm + + + + + + + + destroy + restart + restart + + + /usr/libexec/qemu-kvm + + + '/> + + + + + + '/> + + + + + + +
+ + + + '/> + + + + <% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %> + + <% end %> +
+ + + + '/> + + + + <% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %> + + <% end %> +
+ + + + '/> + + + + <% if scope.lookupvar('n1k_vsm::pacemaker_control') == true %> + + <% end %> +
+ + + + + + + + +